From dbb6d13f34739204cea3408c9cc37c947470cf10 Mon Sep 17 00:00:00 2001 From: shweet Date: Fri, 19 Sep 2025 17:57:48 -0400 Subject: [PATCH 01/15] refactor pt 1; getting each thing right and then will push to main --- CMakeLists.txt | 4 +- Icon.ico | Bin 0 -> 16958 bytes Icon.rc | 1 + compile_commands.json | 1 + src/COMMON.h | 528 ++-- src/PACKED.h | 347 --- src/RESOURCE.h | 197 ++ src/anm2.cpp | 2553 +++++++++-------- src/anm2.h | 411 ++- src/canvas.cpp | 360 ++- src/canvas.h | 86 +- src/clipboard.cpp | 191 +- src/clipboard.h | 18 +- src/dialog.cpp | 111 +- src/dialog.h | 57 +- src/editor.cpp | 87 +- src/editor.h | 37 +- src/ffmpeg.cpp | 93 +- src/ffmpeg.h | 44 +- src/generate_preview.cpp | 81 +- src/generate_preview.h | 17 +- src/imgui.cpp | 5699 ++++++++++++++++++-------------------- src/imgui.h | 3293 ++++++++-------------- src/main.cpp | 88 +- src/preview.cpp | 471 ++-- src/preview.h | 35 +- src/resources.cpp | 20 +- src/resources.h | 11 +- src/settings.cpp | 543 ++-- src/settings.h | 429 +-- src/shader.cpp | 68 +- src/snapshots.cpp | 102 +- src/snapshots.h | 36 +- src/state.h | 45 +- src/texture.cpp | 167 +- src/texture.h | 12 +- src/window.cpp | 20 +- 37 files changed, 7313 insertions(+), 8950 deletions(-) create mode 100644 Icon.ico create mode 100644 Icon.rc create mode 120000 compile_commands.json delete mode 100644 src/PACKED.h create mode 100644 src/RESOURCE.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 09e09cd..2c0d633 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ add_executable(${PROJECT_NAME} if(WIN32) enable_language(RC) - target_sources(${PROJECT_NAME} PRIVATE assets/Icon.rc) + target_sources(${PROJECT_NAME} PRIVATE Icon.rc) set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE TRUE) endif() @@ -72,4 +72,4 @@ target_link_libraries(${PROJECT_NAME} PRIVATE OpenGL::GL SDL3::SDL3) message("System: ${CMAKE_SYSTEM_NAME}") message("Project: ${PROJECT_NAME}") -message("Build: ${CMAKE_BUILD_TYPE}") \ No newline at end of file +message("Build: ${CMAKE_BUILD_TYPE}") diff --git a/Icon.ico b/Icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c9105c049fbb234969c0180bdaec80b6f1a4ef0b GIT binary patch literal 16958 zcmeI2QEtLO3`Dml=wHA4$uUq*!cltU-XPsTE5YFS#mcT$E1W7sW^B)l*Fqq*l(+hK zK9~CXSx#T2e3Vj7^{#J~?|QHAU$2Vgl@rJbK`j_#XL zPb==?M!#;}tB|MfTI+j}+tBO!Bhcs<(i73X<{srU>dB&u8~xIMa3>=>aCF{Ay?ed{ z8vXM8^ZdK*z|nm(>S@JYT>H%yyXJO)v-wrMJ1n{>+HbblHMawt&9Ca+VbM)7`gQy4 zt3nRxCVuiqxbkUC{F<+E?|Sk_xa!row|?c*nE1&b;mW5m@oT=uz3a&z z;i^~T-ujhKW8x=&ge#xM#IN}p_pT>@gsWbSd+S#|jftQ95l;P85A~Z3PyhY|^86qF zKVY`~CcXaYFHhgkqxr-?8jt#k=8yJA{82yAeBvLCNBu_g=zo?&R zervt0`$hdk^IPj}-7o4Vn%`RQ=zdZE`hAn?NBbjw(yx9srh4KZjgx-$t1;D&_DB4r zU;S!K^~66Lp8g+yZ|3>?6PRtkN$;!gKg}ocoIp-s{{;L`&mHKEYFYm&q+T!he7_B; hY(3YZ)ayDNa8eBMy=^%t8cqn-c& literal 0 HcmV?d00001 diff --git a/Icon.rc b/Icon.rc new file mode 100644 index 0000000..0599d31 --- /dev/null +++ b/Icon.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "Icon.ico" diff --git a/compile_commands.json b/compile_commands.json new file mode 120000 index 0000000..25eb4b2 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1 @@ +build/compile_commands.json \ No newline at end of file diff --git a/src/COMMON.h b/src/COMMON.h index 9c8948c..2c7999a 100644 --- a/src/COMMON.h +++ b/src/COMMON.h @@ -1,55 +1,39 @@ #pragma once +#define GLAD_GL_IMPLEMENTATION #include #include -#include #include -#include #include +#include #include -#include -#include +#include +#include #include -#include +#include #include -#include -#include +#include +#include #include -#include +#include #include -#include -#include -#include -#include +#include +#include +#include #include -#include -#include -#include +#include +#include +#include +#include -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; - -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; - -typedef float f32; -typedef double f64; - -#define PI (GLM_PI) -#define TAU (PI * 2) - -using namespace glm; +using namespace glm; #define PREFERENCES_DIRECTORY "anm2ed" #define ROUND_NEAREST_MULTIPLE(value, multiple) (roundf((value) / (multiple)) * (multiple)) -#define FLOAT_TO_U8(x) (static_cast((x) * 255.0f)) -#define U8_TO_FLOAT(x) ((x) / 255.0f) +#define FLOAT_TO_UINT8(x) (static_cast((x) * 255.0f)) +#define UINT8_TO_FLOAT(x) ((x) / 255.0f) #define PERCENT_TO_UNIT(x) (x / 100.0f) #define UNIT_TO_PERCENT(x) (x * 100.0f) #define SECOND 1000.0f @@ -62,15 +46,15 @@ using namespace glm; #define GL_ID_NONE 0 #ifdef _WIN32 - #define POPEN _popen - #define PCLOSE _pclose - #define PWRITE_MODE "wb" - #define PREAD_MODE "r" +#define POPEN _popen +#define PCLOSE _pclose +#define PWRITE_MODE "wb" +#define PREAD_MODE "r" #else - #define POPEN popen - #define PCLOSE pclose - #define PWRITE_MODE "w" - #define PREAD_MODE "r" +#define POPEN popen +#define PCLOSE pclose +#define PWRITE_MODE "w" +#define PREAD_MODE "r" #endif static const GLuint GL_TEXTURE_INDICES[] = {0, 1, 2, 2, 3, 0}; @@ -82,299 +66,254 @@ static const vec4 COLOR_OPAQUE = {1.0f, 1.0f, 1.0f, 1.0f}; static const vec4 COLOR_TRANSPARENT = {0.0f, 0.0f, 0.0f, 0.0f}; static const vec3 COLOR_OFFSET_NONE = {0.0f, 0.0f, 0.0f}; -static inline std::string preferences_path_get(void) -{ - char* preferencesPath = SDL_GetPrefPath("", PREFERENCES_DIRECTORY); - std::string preferencesPathString = preferencesPath; - SDL_free(preferencesPath); - return preferencesPathString; +static inline std::string preferences_path_get(void) { + char* preferencesPath = SDL_GetPrefPath("", PREFERENCES_DIRECTORY); + std::string preferencesPathString = preferencesPath; + SDL_free(preferencesPath); + return preferencesPathString; } -static inline bool string_to_bool(const std::string& string) -{ - if (string == "1") return true; +static inline bool string_to_bool(const std::string& string) { + if (string == "1") + return true; - std::string lower = string; - std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); - - return lower == "true"; + std::string lower = string; + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + + return lower == "true"; } -static inline std::string string_quote(const std::string& string) -{ - return "\"" + string + "\""; -} +static inline std::string string_quote(const std::string& string) { return "\"" + string + "\""; } static inline std::string string_to_lowercase(std::string string) { - std::transform - ( - string.begin(), string.end(), string.begin(), - [](u8 character){ return std::tolower(character); } - ); - return string; + std::transform(string.begin(), string.end(), string.begin(), [](char character) { return std::tolower(character); }); + return string; } -static inline std::string string_backslash_replace(std::string string) -{ - for (char& character : string) - if (character == '\\') - character = '/'; - return string; +static inline std::string string_backslash_replace(std::string string) { + for (char& character : string) + if (character == '\\') + character = '/'; + return string; } #define FLOAT_FORMAT_MAX_DECIMALS 5 #define FLOAT_FORMAT_EPSILON 1e-5f -static constexpr f32 FLOAT_FORMAT_POW10[] = { - 1.f, - 10.f, - 100.f, - 1000.f, - 10000.f, - 100000.f +static constexpr float FLOAT_FORMAT_POW10[] = {1.f, 10.f, 100.f, 1000.f, 10000.f, 100000.f}; + +static inline int float_decimals_needed(float value) { + for (int decimalCount = 0; decimalCount <= FLOAT_FORMAT_MAX_DECIMALS; ++decimalCount) { + float scale = FLOAT_FORMAT_POW10[decimalCount]; + float rounded = roundf(value * scale) / scale; + if (fabsf(value - rounded) < FLOAT_FORMAT_EPSILON) + return decimalCount; + } + return FLOAT_FORMAT_MAX_DECIMALS; +} + +static inline const char* float_format_get(float value) { + static std::string formatString; + const int decimalCount = float_decimals_needed(value); + formatString = (decimalCount == 0) ? "%.0f" : ("%." + std::to_string(decimalCount) + "f"); + return formatString.c_str(); +} + +static inline const char* vec2_format_get(const vec2& value) { + static std::string formatString; + const int decimalCountX = float_decimals_needed(value.x); + const int decimalCountY = float_decimals_needed(value.y); + const int decimalCount = (decimalCountX > decimalCountY) ? decimalCountX : decimalCountY; + formatString = (decimalCount == 0) ? "%.0f" : ("%." + std::to_string(decimalCount) + "f"); + return formatString.c_str(); +} + +static inline std::string working_directory_from_file_set(const std::string& path) { + std::filesystem::path filePath = path; + std::filesystem::path parentPath = filePath.parent_path(); + std::filesystem::current_path(parentPath); + return parentPath.string(); }; -static inline s32 f32_decimals_needed(f32 value) -{ - for (s32 decimalCount = 0; decimalCount <= FLOAT_FORMAT_MAX_DECIMALS; ++decimalCount) - { - f32 scale = FLOAT_FORMAT_POW10[decimalCount]; - f32 rounded = roundf(value * scale) / scale; - if (fabsf(value - rounded) < FLOAT_FORMAT_EPSILON) - return decimalCount; - } - return FLOAT_FORMAT_MAX_DECIMALS; +static inline std::string path_extension_change(const std::string& path, const std::string& extension) { + std::filesystem::path filePath(path); + filePath.replace_extension(extension); + return filePath.string(); } -static inline const char* f32_format_get(f32 value) -{ - static std::string formatString; - const s32 decimalCount = f32_decimals_needed(value); - formatString = (decimalCount == 0) - ? "%.0f" - : ("%." + std::to_string(decimalCount) + "f"); - return formatString.c_str(); +static inline bool path_is_extension(const std::string& path, const std::string& extension) { + auto e = std::filesystem::path(path).extension().string(); + std::transform(e.begin(), e.end(), e.begin(), ::tolower); + return e == ("." + extension); } -static inline const char* vec2_format_get(const vec2& value) -{ - static std::string formatString; - const s32 decimalCountX = f32_decimals_needed(value.x); - const s32 decimalCountY = f32_decimals_needed(value.y); - const s32 decimalCount = (decimalCountX > decimalCountY) ? decimalCountX : decimalCountY; - formatString = (decimalCount == 0) - ? "%.0f" - : ("%." + std::to_string(decimalCount) + "f"); - return formatString.c_str(); +static inline bool path_exists(const std::filesystem::path& pathCheck) { + std::error_code errorCode; + return std::filesystem::exists(pathCheck, errorCode) && ((void)std::filesystem::status(pathCheck, errorCode), !errorCode); } -static inline std::string working_directory_from_file_set(const std::string& path) -{ - std::filesystem::path filePath = path; - std::filesystem::path parentPath = filePath.parent_path(); - std::filesystem::current_path(parentPath); - return parentPath.string(); +static inline bool path_is_valid(const std::filesystem::path& pathCheck) { + namespace fs = std::filesystem; + std::error_code ec; + + if (fs::is_directory(pathCheck, ec)) + return false; + + fs::path parentDir = pathCheck.has_parent_path() ? pathCheck.parent_path() : fs::path("."); + if (!fs::is_directory(parentDir, ec)) + return false; + + bool existedBefore = fs::exists(pathCheck, ec); + std::ofstream testStream(pathCheck, std::ios::app | std::ios::binary); + bool isValid = testStream.is_open(); + testStream.close(); + + if (!existedBefore && isValid) + fs::remove(pathCheck, ec); + + return isValid; +} + +static inline int string_to_enum(const std::string& string, const char* const* array, int n) { + for (int i = 0; i < n; i++) + if (string == array[i]) + return i; + return -1; }; -static inline std::string path_extension_change(const std::string& path, const std::string& extension) -{ - std::filesystem::path filePath(path); - filePath.replace_extension(extension); - return filePath.string(); +template T& dummy_value() { + static T value{}; + return value; } -static inline bool path_is_extension(const std::string& path, const std::string& extension) -{ - auto e = std::filesystem::path(path).extension().string(); - std::transform(e.begin(), e.end(), e.begin(), ::tolower); - return e == ("." + extension); +template static inline int map_next_id_get(const std::map& map) { + int id = 0; + + for (const auto& [key, value] : map) { + if (key != id) + break; + ++id; + } + + return id; } -static inline bool path_exists(const std::filesystem::path& pathCheck) -{ - std::error_code errorCode; - return std::filesystem::exists(pathCheck, errorCode) && ((void)std::filesystem::status(pathCheck, errorCode), !errorCode); +template static inline auto map_find(Map& map, typename Map::key_type id) -> typename Map::mapped_type* { + if (auto it = map.find(id); it != map.end()) + return &it->second; + return nullptr; } -static inline bool path_is_valid(const std::filesystem::path& pathCheck) -{ - namespace fs = std::filesystem; - std::error_code ec; +template static inline void map_swap(Map& map, const Key& key1, const Key& key2) { + if (key1 == key2) + return; - if (fs::is_directory(pathCheck, ec)) return false; + auto it1 = map.find(key1); + auto it2 = map.find(key2); - fs::path parentDir = pathCheck.has_parent_path() ? pathCheck.parent_path() : fs::path("."); - if (!fs::is_directory(parentDir, ec)) return false; - - bool existedBefore = fs::exists(pathCheck, ec); - std::ofstream testStream(pathCheck, std::ios::app | std::ios::binary); - bool isValid = testStream.is_open(); - testStream.close(); - - if (!existedBefore && isValid) - fs::remove(pathCheck, ec); - - return isValid; -} - -static inline s32 string_to_enum(const std::string& string, const char* const* array, s32 n) -{ - for (s32 i = 0; i < n; i++) - if (string == array[i]) - return i; - return -1; + if (it1 != map.end() && it2 != map.end()) { + using std::swap; + swap(it1->second, it2->second); + } else if (it1 != map.end()) { + map[key2] = std::move(it1->second); + map.erase(it1); + } else if (it2 != map.end()) { + map[key1] = std::move(it2->second); + map.erase(it2); + } }; -template -T& dummy_value() -{ - static T value{}; - return value; +template static inline void map_insert_shift(std::map& map, int index, const T& value) { + const int insertIndex = index + 1; + + std::vector> toShift; + for (auto it = map.rbegin(); it != map.rend(); ++it) { + if (it->first < insertIndex) + break; + toShift.emplace_back(it->first + 1, std::move(it->second)); + } + + for (const auto& [newKey, _] : toShift) + map.erase(newKey - 1); + + for (auto& [newKey, val] : toShift) + map[newKey] = std::move(val); + + map[insertIndex] = value; } -template -static inline s32 map_next_id_get(const std::map& map) -{ - s32 id = 0; - - for (const auto& [key, value] : map) - { - if (key != id) - break; - ++id; - } - - return id; +template static inline T* vector_find(std::vector& v, const T& value) { + auto it = std::find(v.begin(), v.end(), value); + return (it != v.end()) ? &(*it) : nullptr; } -template -static inline auto map_find(Map& map, typename Map::key_type id) - -> typename Map::mapped_type* -{ - if (auto it = map.find(id); it != map.end()) - return &it->second; - return nullptr; +template static inline void vector_value_erase(std::vector& v, const T& value) { v.erase(std::remove(v.begin(), v.end(), value), v.end()); } + +template static inline void vector_value_swap(std::vector& v, const T& a, const T& b) { + for (auto& element : v) { + if (element == a) + element = b; + else if (element == b) + element = a; + } } -template -static inline void map_swap(Map& map, const Key& key1, const Key& key2) -{ - if (key1 == key2) - return; - - auto it1 = map.find(key1); - auto it2 = map.find(key2); - - if (it1 != map.end() && it2 != map.end()) - { - using std::swap; - swap(it1->second, it2->second); - } - else if (it1 != map.end()) - { - map[key2] = std::move(it1->second); - map.erase(it1); - } - else if (it2 != map.end()) - { - map[key1] = std::move(it2->second); - map.erase(it2); - } -}; - -template -static inline void map_insert_shift(std::map& map, s32 index, const T& value) -{ - const s32 insertIndex = index + 1; - - std::vector> toShift; - for (auto it = map.rbegin(); it != map.rend(); ++it) - { - if (it->first < insertIndex) - break; - toShift.emplace_back(it->first + 1, std::move(it->second)); - } - - for (const auto& [newKey, _] : toShift) - map.erase(newKey - 1); - - for (auto& [newKey, val] : toShift) - map[newKey] = std::move(val); - - map[insertIndex] = value; +static inline void unordered_set_id_toggle(std::unordered_set& set, int id) { + if (auto it = set.find(id); it != set.end()) + set.erase(it); + else + set.insert(id); } -template -void vector_value_erase(std::vector& v, const T& value) -{ - v.erase(std::remove(v.begin(), v.end(), value), v.end()); +static inline mat4 quad_model_get(vec2 size = {}, vec2 position = {}, vec2 pivot = {}, vec2 scale = vec2(1.0f), float rotation = {}) { + vec2 scaleAbsolute = glm::abs(scale); + vec2 scaleSign = glm::sign(scale); + vec2 pivotScaled = pivot * scaleAbsolute; + vec2 sizeScaled = size * scaleAbsolute; + + mat4 model(1.0f); + model = glm::translate(model, vec3(position - pivotScaled, 0.0f)); + model = glm::translate(model, vec3(pivotScaled, 0.0f)); + model = glm::scale(model, vec3(scaleSign, 1.0f)); + model = glm::rotate(model, glm::radians(rotation), vec3(0, 0, 1)); + model = glm::translate(model, vec3(-pivotScaled, 0.0f)); + model = glm::scale(model, vec3(sizeScaled, 1.0f)); + return model; } -template -void vector_value_swap(std::vector& v, const T& a, const T& b) -{ - for (auto& element : v) - { - if (element == a) element = b; - else if (element == b) element = a; - } +static inline mat4 quad_model_parent_get(vec2 position = {}, vec2 pivot = {}, vec2 scale = vec2(1.0f), float rotation = {}) { + vec2 scaleSign = glm::sign(scale); + vec2 scaleAbsolute = glm::abs(scale); + float handedness = (scaleSign.x * scaleSign.y) < 0.0f ? -1.0f : 1.0f; + + mat4 local(1.0f); + local = glm::translate(local, vec3(pivot, 0.0f)); + local = glm::scale(local, vec3(scaleSign, 1.0f)); + local = glm::rotate(local, glm::radians(rotation) * handedness, vec3(0, 0, 1)); + local = glm::translate(local, vec3(-pivot, 0.0f)); + local = glm::scale(local, vec3(scaleAbsolute, 1.0f)); + + return glm::translate(mat4(1.0f), vec3(position, 0.0f)) * local; } -static inline mat4 quad_model_get(vec2 size = {}, vec2 position = {}, vec2 pivot = {}, vec2 scale = vec2(1.0f), f32 rotation = {}) -{ - vec2 scaleAbsolute = glm::abs(scale); - vec2 scaleSign = glm::sign(scale); - vec2 pivotScaled = pivot * scaleAbsolute; - vec2 sizeScaled = size * scaleAbsolute; +#define DEFINE_STRING_TO_ENUM_FUNCTION(function, enumType, stringArray, count) \ + static inline enumType function(const std::string& string) { return static_cast(string_to_enum(string, stringArray, count)); }; - mat4 model(1.0f); - model = glm::translate(model, vec3(position - pivotScaled, 0.0f)); - model = glm::translate(model, vec3(pivotScaled, 0.0f)); - model = glm::scale(model, vec3(scaleSign, 1.0f)); - model = glm::rotate(model, glm::radians(rotation), vec3(0, 0, 1)); - model = glm::translate(model, vec3(-pivotScaled, 0.0f)); - model = glm::scale(model, vec3(sizeScaled, 1.0f)); - return model; -} +#define DATATYPE_LIST \ + X(TYPE_INT, int) \ + X(TYPE_BOOL, bool) \ + X(TYPE_FLOAT, float) \ + X(TYPE_STRING, std::string) \ + X(TYPE_IVEC2, ivec2) \ + X(TYPE_IVEC2_WH, ivec2) \ + X(TYPE_VEC2, vec2) \ + X(TYPE_VEC2_WH, vec2) \ + X(TYPE_VEC3, vec3) \ + X(TYPE_VEC4, vec4) -static inline mat4 quad_model_parent_get(vec2 position = {}, vec2 pivot = {}, vec2 scale = vec2(1.0f), f32 rotation = {}) -{ - vec2 scaleSign = glm::sign(scale); - vec2 scaleAbsolute = glm::abs(scale); - f32 handedness = (scaleSign.x * scaleSign.y) < 0.0f ? -1.0f : 1.0f; - - mat4 local(1.0f); - local = glm::translate(local, vec3(pivot, 0.0f)); - local = glm::scale(local, vec3(scaleSign, 1.0f)); - local = glm::rotate(local, glm::radians(rotation) * handedness, vec3(0, 0, 1)); - local = glm::translate(local, vec3(-pivot, 0.0f)); - local = glm::scale(local, vec3(scaleAbsolute, 1.0f)); - - return glm::translate(mat4(1.0f), vec3(position, 0.0f)) * local; -} - -#define DEFINE_STRING_TO_ENUM_FUNCTION(function, enumType, stringArray, count) \ - static inline enumType function(const std::string& string) \ - { \ - return static_cast(string_to_enum(string, stringArray, count)); \ - }; - -#define DATATYPE_LIST \ - X(TYPE_INT, s32) \ - X(TYPE_BOOL, bool) \ - X(TYPE_FLOAT, f32) \ - X(TYPE_STRING, std::string) \ - X(TYPE_IVEC2, ivec2) \ - X(TYPE_IVEC2_WH, ivec2) \ - X(TYPE_VEC2, vec2) \ - X(TYPE_VEC2_WH, vec2) \ - X(TYPE_VEC3, vec3) \ - X(TYPE_VEC4, vec4) - -enum DataType -{ - #define X(symbol, ctype) symbol, - DATATYPE_LIST - #undef X +enum DataType { +#define X(symbol, ctype) symbol, + DATATYPE_LIST +#undef X }; #define DATATYPE_TO_CTYPE(dt) DATATYPE_CTYPE_##dt @@ -382,8 +321,13 @@ enum DataType DATATYPE_LIST #undef X -enum OriginType -{ - ORIGIN_TOP_LEFT, - ORIGIN_CENTER +enum OriginType { ORIGIN_TOP_LEFT, ORIGIN_CENTER }; + +struct WorkingDirectory { + std::filesystem::path previous; + WorkingDirectory(const std::string& file) { + previous = std::filesystem::current_path(); + working_directory_from_file_set(file); + } + ~WorkingDirectory() { std::filesystem::current_path(previous); } }; \ No newline at end of file diff --git a/src/PACKED.h b/src/PACKED.h deleted file mode 100644 index d161fb2..0000000 --- a/src/PACKED.h +++ /dev/null @@ -1,347 +0,0 @@ -#pragma once - -#include "COMMON.h" - -const u8 TEXTURE_ATLAS[] = -{ - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, - 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xa0, - 0x04, 0x03, 0x00, 0x00, 0x00, 0x01, 0x5e, 0x74, 0xbf, 0x00, 0x00, 0x00, - 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, - 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x0f, 0x50, 0x4c, - 0x54, 0x45, 0x00, 0x00, 0x00, 0x76, 0x76, 0x76, 0xff, 0xff, 0xff, 0x60, - 0x60, 0x60, 0xff, 0xff, 0xff, 0x3e, 0xd5, 0x47, 0x6d, 0x00, 0x00, 0x00, - 0x03, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x00, 0x00, 0xfa, 0x76, 0xc4, 0xde, - 0x00, 0x00, 0x04, 0x62, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0x59, - 0x5b, 0x6e, 0x24, 0x37, 0x0c, 0x2c, 0x80, 0xbc, 0x40, 0xee, 0x90, 0x03, - 0x10, 0x20, 0x0f, 0xc0, 0x80, 0x75, 0xff, 0x33, 0xe5, 0x83, 0xa2, 0x5a, - 0x63, 0xcf, 0xae, 0xa7, 0x37, 0xb1, 0x03, 0x6c, 0xac, 0x0f, 0x77, 0x6b, - 0x5a, 0xd5, 0x7c, 0x15, 0x49, 0xb5, 0x0c, 0xfc, 0xc2, 0x20, 0x9f, 0xff, - 0xae, 0xd9, 0xd7, 0x28, 0x00, 0xe0, 0xb1, 0x9e, 0x04, 0x40, 0x9a, 0x92, - 0x76, 0xac, 0x27, 0xf3, 0x78, 0x21, 0xbd, 0x00, 0x01, 0xa0, 0x04, 0x98, - 0xd0, 0x46, 0x26, 0x00, 0x04, 0x49, 0xe8, 0x9e, 0x36, 0xc0, 0x95, 0x80, - 0x2e, 0x51, 0x64, 0xdf, 0xee, 0x15, 0xa4, 0x92, 0x83, 0x58, 0x2a, 0x29, - 0x4b, 0xd8, 0x00, 0x9d, 0x17, 0xf6, 0x02, 0xc9, 0x56, 0x68, 0xe6, 0x6d, - 0x4b, 0xbf, 0xa2, 0x67, 0x4c, 0x4d, 0x35, 0xec, 0xb5, 0x89, 0x41, 0x24, - 0x9e, 0x01, 0x94, 0xd0, 0xd4, 0xb6, 0x34, 0x35, 0x7b, 0x81, 0x78, 0x90, - 0xe5, 0xf6, 0x08, 0x28, 0x40, 0x13, 0xcc, 0x13, 0x50, 0x08, 0x03, 0x20, - 0xee, 0x51, 0xee, 0x06, 0x48, 0xfb, 0x8e, 0x61, 0x64, 0x02, 0x9a, 0x4a, - 0x1c, 0x00, 0xe1, 0xf2, 0xb8, 0xb8, 0xbb, 0x1b, 0x80, 0x48, 0xad, 0xb6, - 0x75, 0x59, 0xcf, 0x04, 0xda, 0x4b, 0x00, 0x12, 0x03, 0x30, 0x77, 0x37, - 0x33, 0x21, 0x01, 0xd2, 0xae, 0xc0, 0x75, 0xd4, 0x2e, 0x40, 0xb0, 0x00, - 0x40, 0x44, 0xc4, 0x45, 0xa0, 0x4c, 0x40, 0x99, 0x17, 0x60, 0x02, 0x37, - 0x5e, 0xd2, 0x15, 0x5f, 0x98, 0x99, 0xd9, 0x13, 0xc0, 0xa2, 0x86, 0xb4, - 0xdf, 0xed, 0x22, 0x8d, 0x88, 0x00, 0x10, 0x5a, 0xff, 0xe1, 0xc7, 0xe4, - 0x83, 0xe1, 0x8b, 0xc6, 0xd0, 0x5c, 0xde, 0x48, 0x94, 0x07, 0x72, 0x5f, - 0xf3, 0xa1, 0xf9, 0xdb, 0xe7, 0x93, 0x17, 0xc1, 0xa6, 0x80, 0x93, 0xa4, - 0x5f, 0x9c, 0x92, 0xe5, 0x13, 0xbc, 0x71, 0x2f, 0x0a, 0x00, 0x02, 0x08, - 0x02, 0xac, 0xcd, 0x5a, 0x09, 0xba, 0xb3, 0xec, 0x12, 0x45, 0x77, 0x27, - 0x81, 0x26, 0x28, 0x40, 0xeb, 0x3c, 0x19, 0x40, 0x3f, 0xb7, 0x2d, 0x4a, - 0xe8, 0x1e, 0xa4, 0x0d, 0x40, 0x3a, 0x4f, 0x6c, 0xab, 0xd4, 0xcf, 0x01, - 0x68, 0xb9, 0x47, 0x42, 0xcb, 0x9d, 0x15, 0x39, 0x80, 0xc9, 0x93, 0xa1, - 0xf9, 0x7e, 0x2e, 0x15, 0x51, 0x15, 0xa6, 0xe5, 0x41, 0x8f, 0x44, 0x42, - 0xb3, 0x01, 0x4a, 0x68, 0x0e, 0xcd, 0xf7, 0x73, 0x9a, 0x6a, 0xa6, 0x30, - 0xd2, 0x59, 0xae, 0xd5, 0x00, 0xd9, 0x79, 0x32, 0x34, 0xd7, 0x72, 0x96, - 0x47, 0x42, 0x52, 0x4d, 0x52, 0x4d, 0x4b, 0x09, 0x8c, 0x4a, 0x57, 0x9e, - 0xc0, 0xdc, 0x1d, 0x80, 0x66, 0xd0, 0xa1, 0x09, 0x28, 0x48, 0x24, 0x84, - 0x2c, 0xf7, 0x65, 0x34, 0x09, 0x21, 0x13, 0x4e, 0x53, 0x29, 0xb1, 0x9e, - 0x97, 0x39, 0x01, 0x48, 0x01, 0x61, 0x00, 0xe9, 0xee, 0xed, 0x56, 0x8d, - 0x4a, 0x90, 0x10, 0xa7, 0x81, 0x66, 0x6b, 0x6e, 0xe2, 0xb4, 0x0e, 0x6d, - 0x01, 0x50, 0xba, 0xaf, 0xc0, 0x95, 0x66, 0x20, 0x08, 0x67, 0x39, 0x28, - 0xc7, 0x3c, 0xfd, 0x19, 0x35, 0x4c, 0x4d, 0xb2, 0xa9, 0x01, 0x53, 0x24, - 0xd4, 0x24, 0x05, 0x24, 0xf9, 0xc0, 0xbf, 0x83, 0x5c, 0x64, 0xcf, 0xdd, - 0xcf, 0x8c, 0xb9, 0xe6, 0xbf, 0xca, 0xf7, 0xb9, 0xbe, 0xdc, 0x1f, 0xd6, - 0x75, 0xa9, 0xa6, 0x49, 0x4d, 0x5e, 0x57, 0x00, 0x40, 0x57, 0xc2, 0x29, - 0xa1, 0x47, 0xed, 0xc6, 0x94, 0x9d, 0x7d, 0x5d, 0xc5, 0xcd, 0xde, 0xab, - 0xb6, 0xd8, 0xa9, 0xfd, 0x86, 0x5d, 0x11, 0x01, 0x40, 0xcd, 0xed, 0xf4, - 0xce, 0x2a, 0xba, 0xec, 0x6a, 0xd7, 0x45, 0x71, 0xcc, 0x4a, 0x00, 0x28, - 0x0a, 0x80, 0x0c, 0x93, 0x52, 0x6c, 0x96, 0xae, 0xc2, 0xa5, 0x00, 0xa2, - 0x25, 0x6d, 0x0d, 0x82, 0x06, 0x68, 0x16, 0x10, 0x9a, 0x9a, 0x88, 0x82, - 0xa6, 0x76, 0xfa, 0xa5, 0x2e, 0x09, 0x87, 0x4a, 0xc5, 0x4a, 0x80, 0x99, - 0x9a, 0xba, 0x12, 0x91, 0xa4, 0x76, 0x8c, 0xba, 0x09, 0xc5, 0xa9, 0x92, - 0x06, 0x03, 0xcf, 0x01, 0xd9, 0x12, 0x98, 0x38, 0x55, 0x6a, 0x01, 0x4f, - 0x55, 0xa2, 0x32, 0xb5, 0x99, 0xd5, 0x2a, 0x69, 0x26, 0xd0, 0x02, 0xde, - 0x19, 0x2d, 0x4c, 0xb0, 0x7b, 0x76, 0x8e, 0x77, 0x3a, 0x6f, 0xb4, 0xf2, - 0x0d, 0xe9, 0xc6, 0xad, 0xb9, 0xda, 0xf4, 0x14, 0x9c, 0xbe, 0x67, 0xc6, - 0x73, 0x4e, 0x29, 0x93, 0xcc, 0x01, 0xe4, 0x05, 0xe0, 0xdb, 0x2d, 0xc2, - 0xa6, 0xc6, 0x29, 0x61, 0xab, 0x24, 0x91, 0x3f, 0x22, 0x5f, 0xef, 0x08, - 0x94, 0x4c, 0x6a, 0x02, 0xd4, 0xa4, 0xe6, 0x43, 0xe9, 0xbe, 0x4d, 0xef, - 0x7f, 0x3a, 0x0e, 0x39, 0xba, 0xb3, 0xf7, 0xb1, 0x8b, 0x2d, 0xfd, 0xd4, - 0xa2, 0x1e, 0x15, 0x5b, 0xf7, 0xf4, 0x01, 0x58, 0xff, 0xb0, 0xe6, 0x52, - 0x5c, 0x3d, 0xe2, 0xec, 0x19, 0xd0, 0xea, 0x38, 0x09, 0x6b, 0x3d, 0x94, - 0x58, 0x8b, 0x62, 0xf7, 0x83, 0x69, 0x03, 0x4c, 0xb0, 0x37, 0x0c, 0x10, - 0xa6, 0x5a, 0x2f, 0xf4, 0xae, 0x64, 0x50, 0xb0, 0xb0, 0x38, 0x88, 0x7d, - 0x33, 0xb5, 0x27, 0x3c, 0xb5, 0x2b, 0x9f, 0x04, 0xe9, 0x6d, 0xad, 0xda, - 0x74, 0x9c, 0x01, 0x24, 0x9c, 0x4e, 0x27, 0x84, 0x4e, 0x76, 0x4a, 0x1b, - 0xbb, 0x75, 0x69, 0xd7, 0xd9, 0xde, 0xb5, 0xf5, 0x0e, 0x46, 0x89, 0x01, - 0x28, 0x49, 0x46, 0x02, 0x10, 0xea, 0x08, 0xb0, 0x8c, 0xe5, 0x19, 0x4d, - 0x9d, 0xbd, 0x59, 0x1b, 0x0c, 0x05, 0xd9, 0xfc, 0x0e, 0xe6, 0x08, 0xd0, - 0x1d, 0x87, 0x01, 0x00, 0x70, 0x77, 0x77, 0x87, 0x82, 0xac, 0x55, 0x41, - 0x29, 0x23, 0xe0, 0x08, 0xc0, 0x0e, 0x87, 0x01, 0x02, 0x81, 0x92, 0x5e, - 0xab, 0xc4, 0xb6, 0x1f, 0x1e, 0x0a, 0xc4, 0xb2, 0xe1, 0x04, 0xa4, 0x7a, - 0x0d, 0xab, 0x97, 0x26, 0x79, 0xf1, 0x9d, 0xd7, 0x26, 0x76, 0x01, 0xba, - 0x26, 0x74, 0xe0, 0xcb, 0x05, 0x86, 0x38, 0x13, 0xe4, 0x00, 0x2c, 0x1b, - 0x00, 0x19, 0x80, 0xb8, 0xd9, 0x63, 0xc9, 0x9c, 0x48, 0x7f, 0x15, 0xdd, - 0xf1, 0x3e, 0xbd, 0x24, 0x5f, 0x04, 0x0c, 0x68, 0x95, 0xd3, 0xb1, 0xc0, - 0xba, 0xbe, 0x82, 0xf5, 0x03, 0xc0, 0x2a, 0xa7, 0xcc, 0x8f, 0x00, 0x57, - 0x5d, 0x99, 0x52, 0xf1, 0x1a, 0x40, 0xb9, 0xdb, 0x74, 0xfe, 0x04, 0x70, - 0xd4, 0xc6, 0xb2, 0x01, 0x74, 0x33, 0x69, 0x00, 0xd7, 0xde, 0x6f, 0xae, - 0xdb, 0x06, 0xd9, 0x1f, 0x4d, 0x9d, 0x9b, 0x3f, 0x03, 0x6c, 0x22, 0xd4, - 0x00, 0xea, 0xc7, 0x80, 0x63, 0x38, 0x73, 0x01, 0xca, 0x2e, 0x95, 0xdc, - 0x59, 0xee, 0x57, 0x3e, 0x1c, 0x05, 0x79, 0xdc, 0xba, 0x32, 0xf5, 0xb9, - 0xd1, 0xba, 0xea, 0xed, 0xe9, 0xd6, 0x36, 0xfe, 0x63, 0xc0, 0xaa, 0x83, - 0x6b, 0xfd, 0x0b, 0x80, 0xfe, 0xd4, 0xc0, 0xec, 0x0a, 0xc4, 0x6d, 0xed, - 0x10, 0x1e, 0x36, 0x3b, 0xa7, 0x4a, 0xaf, 0x91, 0xf5, 0xb1, 0x0b, 0xdd, - 0x18, 0xfe, 0x66, 0xd8, 0xfb, 0x57, 0x3f, 0x07, 0x8c, 0x05, 0x1f, 0x02, - 0x82, 0x13, 0xe2, 0xaf, 0x02, 0xe0, 0x1b, 0xf0, 0x7b, 0x00, 0xd6, 0xde, - 0xef, 0x65, 0x80, 0xae, 0xae, 0xfd, 0x32, 0x80, 0xa9, 0x7c, 0xd8, 0x7e, - 0x7c, 0x08, 0xe8, 0xcf, 0xbf, 0x97, 0x01, 0xfd, 0xbd, 0x78, 0x9e, 0x07, - 0xfc, 0x7b, 0x00, 0x3e, 0x19, 0xff, 0x31, 0xe0, 0xf3, 0x8d, 0xfe, 0xc5, - 0x38, 0xdc, 0x8f, 0xf4, 0x6d, 0x2e, 0xdd, 0x66, 0xeb, 0xef, 0x99, 0xd3, - 0x73, 0x36, 0xf6, 0x32, 0x60, 0xce, 0x93, 0x5e, 0x07, 0xac, 0xd3, 0x9f, - 0x97, 0xfb, 0xc3, 0x9c, 0x6b, 0xdc, 0x00, 0xf4, 0x97, 0xe2, 0x0d, 0x40, - 0x9f, 0x59, 0xde, 0x01, 0x88, 0xe1, 0x5d, 0x37, 0xfd, 0x29, 0xe0, 0x7b, - 0x7c, 0x8f, 0xaf, 0x19, 0x77, 0x3f, 0xb6, 0xf6, 0x3f, 0x15, 0x5e, 0x1c, - 0xca, 0x9b, 0x04, 0x27, 0x70, 0xeb, 0xc0, 0x63, 0x8e, 0x1d, 0x3e, 0x0f, - 0xb0, 0x56, 0xfe, 0x99, 0x77, 0x00, 0x7f, 0xdc, 0x05, 0xfc, 0xf5, 0xe9, - 0x12, 0x6e, 0x01, 0x3e, 0xdf, 0xad, 0xb7, 0x23, 0x7d, 0x9f, 0x4b, 0xb7, - 0xd9, 0x7a, 0x3f, 0x1f, 0xbe, 0xc7, 0xff, 0x75, 0xfc, 0x0d, 0x3b, 0xd4, - 0xd5, 0x4b, 0x3b, 0xfe, 0xb6, 0x75, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, - 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -const u32 TEXTURE_ATLAS_LENGTH = (u32)std::size(TEXTURE_ATLAS); -const vec2 TEXTURE_ATLAS_SIZE = {96, 160}; - -enum AtlasType -{ - ATLAS_NONE, - ATLAS_FOLDER, - ATLAS_ROOT, - ATLAS_LAYER, - ATLAS_NULL, - ATLAS_TRIGGERS, - ATLAS_VISIBLE, - ATLAS_INVISIBLE, - ATLAS_SHOW_RECT, - ATLAS_HIDE_RECT, - ATLAS_SHOW_UNUSED, - ATLAS_HIDE_UNUSED, - ATLAS_PAN, - ATLAS_MOVE, - ATLAS_ROTATE, - ATLAS_SCALE, - ATLAS_CROP, - ATLAS_DRAW, - ATLAS_ERASE, - ATLAS_COLOR_PICKER, - ATLAS_UNDO, - ATLAS_REDO, - ATLAS_ANIMATION, - ATLAS_SPRITESHEET, - ATLAS_EVENT, - ATLAS_PLAY, - ATLAS_PAUSE, - ATLAS_ADD, - ATLAS_REMOVE, - ATLAS_TRIGGER, - ATLAS_PIVOT, - ATLAS_SQUARE, - ATLAS_CIRCLE, - ATLAS_PICKER, - ATLAS_FRAME, - ATLAS_FRAME_ALT, - ATLAS_TARGET, - ATLAS_TARGET_ALT, - ATLAS_COUNT -}; - -struct AtlasEntry -{ - vec2 position; - vec2 size; -}; - -const vec2 ATLAS_SIZE_SMALL = {8, 8}; -const vec2 ATLAS_SIZE_NORMAL = {16, 16}; -const vec2 ATLAS_SIZE_OBLONG = {16, 40}; -const vec2 ATLAS_SIZE_BIG = {40, 40}; - -const inline AtlasEntry ATLAS_ENTRIES[ATLAS_COUNT] = -{ - {{ 0, 0}, ATLAS_SIZE_NORMAL}, - {{ 16, 0}, ATLAS_SIZE_NORMAL}, - {{ 32, 0}, ATLAS_SIZE_NORMAL}, - {{ 48, 0}, ATLAS_SIZE_NORMAL}, - {{ 64, 0}, ATLAS_SIZE_NORMAL}, - {{ 80, 0}, ATLAS_SIZE_NORMAL}, - {{ 0, 16}, ATLAS_SIZE_NORMAL}, - {{ 16, 16}, ATLAS_SIZE_NORMAL}, - {{ 32, 16}, ATLAS_SIZE_NORMAL}, - {{ 48, 16}, ATLAS_SIZE_NORMAL}, - {{ 64, 16}, ATLAS_SIZE_NORMAL}, - {{ 80, 16}, ATLAS_SIZE_NORMAL}, - {{ 0, 32}, ATLAS_SIZE_NORMAL}, - {{ 16, 32}, ATLAS_SIZE_NORMAL}, - {{ 32, 32}, ATLAS_SIZE_NORMAL}, - {{ 48, 32}, ATLAS_SIZE_NORMAL}, - {{ 64, 32}, ATLAS_SIZE_NORMAL}, - {{ 80, 32}, ATLAS_SIZE_NORMAL}, - {{ 0, 48}, ATLAS_SIZE_NORMAL}, - {{ 16, 48}, ATLAS_SIZE_NORMAL}, - {{ 32, 48}, ATLAS_SIZE_NORMAL}, - {{ 48, 48}, ATLAS_SIZE_NORMAL}, - {{ 64, 48}, ATLAS_SIZE_NORMAL}, - {{ 80, 48}, ATLAS_SIZE_NORMAL}, - {{ 0, 64}, ATLAS_SIZE_NORMAL}, - {{ 16, 64}, ATLAS_SIZE_NORMAL}, - {{ 32, 64}, ATLAS_SIZE_NORMAL}, - {{ 48, 64}, ATLAS_SIZE_NORMAL}, - {{ 64, 64}, ATLAS_SIZE_NORMAL}, - {{ 80, 64}, ATLAS_SIZE_SMALL }, - {{ 88, 64}, ATLAS_SIZE_SMALL }, - {{ 80, 72}, ATLAS_SIZE_SMALL }, - {{ 88, 72}, ATLAS_SIZE_SMALL }, - {{ 0, 80}, ATLAS_SIZE_OBLONG}, - {{16, 80}, ATLAS_SIZE_OBLONG}, - {{32, 80}, ATLAS_SIZE_OBLONG}, - {{48, 80}, ATLAS_SIZE_BIG}, - {{48, 120}, ATLAS_SIZE_BIG} -}; - -#define ATLAS_POSITION(type) ATLAS_ENTRIES[type].position -#define ATLAS_SIZE(type) ATLAS_ENTRIES[type].size -#define ATLAS_UV_MIN(type) (ATLAS_POSITION(type) / TEXTURE_ATLAS_SIZE) -#define ATLAS_UV_MAX(type) ((ATLAS_POSITION(type) + ATLAS_SIZE(type)) / TEXTURE_ATLAS_SIZE) -#define ATLAS_UV_ARGS(type) ATLAS_UV_MIN(type), ATLAS_UV_MAX(type) -#define ATLAS_UV_VERTICES(type) UV_VERTICES(ATLAS_UV_MIN(type), ATLAS_UV_MAX(type)) - -struct ShaderData -{ - std::string vertex; - std::string fragment; -}; - -enum ShaderType -{ - SHADER_LINE, - SHADER_TEXTURE, - SHADER_AXIS, - SHADER_GRID, - SHADER_COUNT -}; - -const std::string SHADER_VERTEX = R"( -#version 330 core -layout (location = 0) in vec2 i_position; -layout (location = 1) in vec2 i_uv; -out vec2 i_uv_out; -uniform mat4 u_transform; -void main() -{ - i_uv_out = i_uv; - gl_Position = u_transform * vec4(i_position, 0.0, 1.0); -} -)"; - -const std::string SHADER_AXIS_VERTEX = R"( -#version 330 core -layout (location = 0) in vec2 i_position; // full screen line segment: -1..1 -uniform vec2 u_origin_ndc; // world origin in NDC -uniform int u_axis; // 0 = X axis, 1 = Y axis - -void main() -{ - vec2 pos = (u_axis == 0) - ? vec2(i_position.x, u_origin_ndc.y) // horizontal line across screen - : vec2(u_origin_ndc.x, i_position.x); // vertical line across screen; - - gl_Position = vec4(pos, 0.0, 1.0); -} -)"; - -const std::string SHADER_GRID_VERTEX = R"( -#version 330 core -layout ( location = 0 ) in vec2 i_position; -out vec2 clip; - -void main() { - clip = i_position; - gl_Position = vec4(i_position, 0.0, 1.0); -} -)"; - -const std::string SHADER_FRAGMENT = R"( -#version 330 core -out vec4 o_fragColor; -uniform vec4 u_color; -void main() -{ - o_fragColor = u_color; -} -)"; - -const std::string SHADER_TEXTURE_FRAGMENT = R"( -#version 330 core -in vec2 i_uv_out; -uniform sampler2D u_texture; -uniform vec4 u_tint; -uniform vec3 u_color_offset; -out vec4 o_fragColor; -void main() -{ - vec4 texColor = texture(u_texture, i_uv_out); - texColor *= u_tint; - texColor.rgb += u_color_offset; - o_fragColor = texColor; -} -)"; - -const std::string SHADER_GRID_FRAGMENT = R"( -#version 330 core -in vec2 clip; - -uniform mat4 u_model; -uniform vec2 u_size; -uniform vec2 u_offset; -uniform vec4 u_color; - -out vec4 o_fragColor; - -void main() -{ - vec4 w = u_model * vec4(clip, 0.0, 1.0); - w /= w.w; - vec2 world = w.xy; - - vec2 g = (world - u_offset) / u_size; - - vec2 d = abs(fract(g) - 0.5); - float distance = min(d.x, d.y); - - float fw = min(fwidth(g.x), fwidth(g.y)); - float alpha = 1.0 - smoothstep(0.0, fw, distance); - - if (alpha <= 0.0) discard; - o_fragColor = vec4(u_color.rgb, u_color.a * alpha); -} -)"; - -#define SHADER_UNIFORM_AXIS "u_axis" -#define SHADER_UNIFORM_COLOR "u_color" -#define SHADER_UNIFORM_TRANSFORM "u_transform" -#define SHADER_UNIFORM_TINT "u_tint" -#define SHADER_UNIFORM_COLOR_OFFSET "u_color_offset" -#define SHADER_UNIFORM_OFFSET "u_offset" -#define SHADER_UNIFORM_ORIGIN_NDC "u_origin_ndc" -#define SHADER_UNIFORM_SIZE "u_size" -#define SHADER_UNIFORM_MODEL "u_model" -#define SHADER_UNIFORM_TEXTURE "u_texture" - -const ShaderData SHADER_DATA[SHADER_COUNT] = -{ - {SHADER_VERTEX, SHADER_FRAGMENT}, - {SHADER_VERTEX, SHADER_TEXTURE_FRAGMENT}, - {SHADER_AXIS_VERTEX, SHADER_FRAGMENT}, - {SHADER_GRID_VERTEX, SHADER_GRID_FRAGMENT} -}; diff --git a/src/RESOURCE.h b/src/RESOURCE.h new file mode 100644 index 0000000..25b0346 --- /dev/null +++ b/src/RESOURCE.h @@ -0,0 +1,197 @@ +#pragma once + +#include "COMMON.h" + +#define ATLAS_PATH "resources/atlas.png" +#define FONT_PATH "resources/font.ttf" +#define FONT_SIZE 16 + +const vec2 TEXTURE_ATLAS_SIZE = {96, 160}; + +enum AtlasType { + ATLAS_NONE, + ATLAS_FOLDER, + ATLAS_ROOT, + ATLAS_LAYER, + ATLAS_NULL, + ATLAS_TRIGGERS, + ATLAS_VISIBLE, + ATLAS_INVISIBLE, + ATLAS_SHOW_RECT, + ATLAS_HIDE_RECT, + ATLAS_SHOW_UNUSED, + ATLAS_HIDE_UNUSED, + ATLAS_PAN, + ATLAS_MOVE, + ATLAS_ROTATE, + ATLAS_SCALE, + ATLAS_CROP, + ATLAS_DRAW, + ATLAS_ERASE, + ATLAS_COLOR_PICKER, + ATLAS_UNDO, + ATLAS_REDO, + ATLAS_ANIMATION, + ATLAS_SPRITESHEET, + ATLAS_EVENT, + ATLAS_PLAY, + ATLAS_PAUSE, + ATLAS_ADD, + ATLAS_REMOVE, + ATLAS_TRIGGER, + ATLAS_PIVOT, + ATLAS_SQUARE, + ATLAS_CIRCLE, + ATLAS_PICKER, + ATLAS_FRAME, + ATLAS_FRAME_ALT, + ATLAS_TARGET, + ATLAS_TARGET_ALT, + ATLAS_COUNT +}; + +struct AtlasEntry { + vec2 position; + vec2 size; +}; + +const vec2 ATLAS_SIZE_SMALL = {8, 8}; +const vec2 ATLAS_SIZE_NORMAL = {16, 16}; +const vec2 ATLAS_SIZE_OBLONG = {16, 40}; +const vec2 ATLAS_SIZE_BIG = {40, 40}; + +const inline AtlasEntry ATLAS_ENTRIES[ATLAS_COUNT] = { + {{0, 0}, ATLAS_SIZE_NORMAL}, {{16, 0}, ATLAS_SIZE_NORMAL}, {{32, 0}, ATLAS_SIZE_NORMAL}, {{48, 0}, ATLAS_SIZE_NORMAL}, {{64, 0}, ATLAS_SIZE_NORMAL}, + {{80, 0}, ATLAS_SIZE_NORMAL}, {{0, 16}, ATLAS_SIZE_NORMAL}, {{16, 16}, ATLAS_SIZE_NORMAL}, {{32, 16}, ATLAS_SIZE_NORMAL}, {{48, 16}, ATLAS_SIZE_NORMAL}, + {{64, 16}, ATLAS_SIZE_NORMAL}, {{80, 16}, ATLAS_SIZE_NORMAL}, {{0, 32}, ATLAS_SIZE_NORMAL}, {{16, 32}, ATLAS_SIZE_NORMAL}, {{32, 32}, ATLAS_SIZE_NORMAL}, + {{48, 32}, ATLAS_SIZE_NORMAL}, {{64, 32}, ATLAS_SIZE_NORMAL}, {{80, 32}, ATLAS_SIZE_NORMAL}, {{0, 48}, ATLAS_SIZE_NORMAL}, {{16, 48}, ATLAS_SIZE_NORMAL}, + {{32, 48}, ATLAS_SIZE_NORMAL}, {{48, 48}, ATLAS_SIZE_NORMAL}, {{64, 48}, ATLAS_SIZE_NORMAL}, {{80, 48}, ATLAS_SIZE_NORMAL}, {{0, 64}, ATLAS_SIZE_NORMAL}, + {{16, 64}, ATLAS_SIZE_NORMAL}, {{32, 64}, ATLAS_SIZE_NORMAL}, {{48, 64}, ATLAS_SIZE_NORMAL}, {{64, 64}, ATLAS_SIZE_NORMAL}, {{80, 64}, ATLAS_SIZE_SMALL}, + {{88, 64}, ATLAS_SIZE_SMALL}, {{80, 72}, ATLAS_SIZE_SMALL}, {{88, 72}, ATLAS_SIZE_SMALL}, {{0, 80}, ATLAS_SIZE_OBLONG}, {{16, 80}, ATLAS_SIZE_OBLONG}, + {{32, 80}, ATLAS_SIZE_OBLONG}, {{48, 80}, ATLAS_SIZE_BIG}, {{48, 120}, ATLAS_SIZE_BIG}}; + +#define ATLAS_POSITION(type) ATLAS_ENTRIES[type].position +#define ATLAS_SIZE(type) ATLAS_ENTRIES[type].size +#define ATLAS_UV_MIN(type) (ATLAS_POSITION(type) / TEXTURE_ATLAS_SIZE) +#define ATLAS_UV_MAX(type) ((ATLAS_POSITION(type) + ATLAS_SIZE(type)) / TEXTURE_ATLAS_SIZE) +#define ATLAS_UV_ARGS(type) ATLAS_UV_MIN(type), ATLAS_UV_MAX(type) +#define ATLAS_UV_VERTICES(type) UV_VERTICES(ATLAS_UV_MIN(type), ATLAS_UV_MAX(type)) + +struct ShaderData { + std::string vertex; + std::string fragment; +}; + +enum ShaderType { SHADER_LINE, SHADER_TEXTURE, SHADER_AXIS, SHADER_GRID, SHADER_COUNT }; + +const std::string SHADER_VERTEX = R"( +#version 330 core +layout (location = 0) in vec2 i_position; +layout (location = 1) in vec2 i_uv; +out vec2 i_uv_out; +uniform mat4 u_transform; +void main() +{ + i_uv_out = i_uv; + gl_Position = u_transform * vec4(i_position, 0.0, 1.0); +} +)"; + +const std::string SHADER_AXIS_VERTEX = R"( +#version 330 core +layout (location = 0) in vec2 i_position; // full screen line segment: -1..1 +uniform vec2 u_origin_ndc; // world origin in NDC +uniform int u_axis; // 0 = X axis, 1 = Y axis + +void main() +{ + vec2 pos = (u_axis == 0) + ? vec2(i_position.x, u_origin_ndc.y) // horizontal line across screen + : vec2(u_origin_ndc.x, i_position.x); // vertical line across screen; + + gl_Position = vec4(pos, 0.0, 1.0); +} +)"; + +const std::string SHADER_GRID_VERTEX = R"( +#version 330 core +layout ( location = 0 ) in vec2 i_position; +out vec2 clip; + +void main() { + clip = i_position; + gl_Position = vec4(i_position, 0.0, 1.0); +} +)"; + +const std::string SHADER_FRAGMENT = R"( +#version 330 core +out vec4 o_fragColor; +uniform vec4 u_color; +void main() +{ + o_fragColor = u_color; +} +)"; + +const std::string SHADER_TEXTURE_FRAGMENT = R"( +#version 330 core +in vec2 i_uv_out; +uniform sampler2D u_texture; +uniform vec4 u_tint; +uniform vec3 u_color_offset; +out vec4 o_fragColor; +void main() +{ + vec4 texColor = texture(u_texture, i_uv_out); + texColor *= u_tint; + texColor.rgb += u_color_offset; + o_fragColor = texColor; +} +)"; + +const std::string SHADER_GRID_FRAGMENT = R"( +#version 330 core +in vec2 clip; + +uniform mat4 u_model; +uniform vec2 u_size; +uniform vec2 u_offset; +uniform vec4 u_color; + +out vec4 o_fragColor; + +void main() +{ + vec4 w = u_model * vec4(clip, 0.0, 1.0); + w /= w.w; + vec2 world = w.xy; + + vec2 g = (world - u_offset) / u_size; + + vec2 d = abs(fract(g) - 0.5); + float distance = min(d.x, d.y); + + float fw = min(fwidth(g.x), fwidth(g.y)); + float alpha = 1.0 - smoothstep(0.0, fw, distance); + + if (alpha <= 0.0) discard; + o_fragColor = vec4(u_color.rgb, u_color.a * alpha); +} +)"; + +#define SHADER_UNIFORM_AXIS "u_axis" +#define SHADER_UNIFORM_COLOR "u_color" +#define SHADER_UNIFORM_TRANSFORM "u_transform" +#define SHADER_UNIFORM_TINT "u_tint" +#define SHADER_UNIFORM_COLOR_OFFSET "u_color_offset" +#define SHADER_UNIFORM_OFFSET "u_offset" +#define SHADER_UNIFORM_ORIGIN_NDC "u_origin_ndc" +#define SHADER_UNIFORM_SIZE "u_size" +#define SHADER_UNIFORM_MODEL "u_model" +#define SHADER_UNIFORM_TEXTURE "u_texture" + +const ShaderData SHADER_DATA[SHADER_COUNT] = {{SHADER_VERTEX, SHADER_FRAGMENT}, + {SHADER_VERTEX, SHADER_TEXTURE_FRAGMENT}, + {SHADER_AXIS_VERTEX, SHADER_FRAGMENT}, + {SHADER_GRID_VERTEX, SHADER_GRID_FRAGMENT}}; diff --git a/src/anm2.cpp b/src/anm2.cpp index c65d2ec..5ef807e 100644 --- a/src/anm2.cpp +++ b/src/anm2.cpp @@ -2,1345 +2,1304 @@ using namespace tinyxml2; -static void _anm2_created_on_set(Anm2* self) -{ - auto now = std::chrono::system_clock::now(); - std::time_t time = std::chrono::system_clock::to_time_t(now); - std::tm localTime = *std::localtime(&time); +static void _anm2_created_on_set(Anm2* self) { + auto now = std::chrono::system_clock::now(); + std::time_t time = std::chrono::system_clock::to_time_t(now); + std::tm localTime = *std::localtime(&time); - std::ostringstream timeString; - timeString << std::put_time(&localTime, ANM2_CREATED_ON_FORMAT); - self->createdOn = timeString.str(); + std::ostringstream timeString; + timeString << std::put_time(&localTime, ANM2_CREATED_ON_FORMAT); + self->createdOn = timeString.str(); } -static void _anm2_frame_serialize(Anm2Frame* frame, Anm2Type type, XMLDocument* document = nullptr, XMLElement* addElement = nullptr, std::string* string = nullptr) -{ - XMLDocument localDocument; - XMLDocument* useDocument = document ? document : &localDocument; - - XMLElement* element = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]); - - if (type == ANM2_TRIGGERS) - { - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_EVENT_ID], frame->eventID); // EventID - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_AT_FRAME], frame->atFrame); // AtFrame - } - else - { - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_POSITION], frame->position.x); // XPosition - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_POSITION], frame->position.y); // YPosition - - if (type == ANM2_LAYER) - { - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_PIVOT], frame->pivot.x); // XPivot - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_PIVOT], frame->pivot.y); // YPivot - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_CROP], frame->crop.x); // XCrop - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_CROP], frame->crop.y); // YCrop - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_WIDTH], frame->size.x); // Width - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_HEIGHT], frame->size.y); // Height - } - - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_SCALE], frame->scale.x); // XScale - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_SCALE], frame->scale.y); // YScale - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DELAY], frame->delay); /* Delay */ - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], frame->isVisible); // Visible - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_TINT], FLOAT_TO_U8(frame->tintRGBA.r)); // RedTint - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], FLOAT_TO_U8(frame->tintRGBA.g)); // GreenTint - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], FLOAT_TO_U8(frame->tintRGBA.b)); // BlueTint - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], FLOAT_TO_U8(frame->tintRGBA.a)); // AlphaTint - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], FLOAT_TO_U8(frame->offsetRGB.r)); // RedOffset - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], FLOAT_TO_U8(frame->offsetRGB.g)); // GreenOffset - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], FLOAT_TO_U8(frame->offsetRGB.b)); // BlueOffset - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ROTATION], frame->rotation); // Rotation - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_INTERPOLATED], frame->isInterpolated); // Interpolated - } - - if (addElement) addElement->InsertEndChild(element); - - if (string && !document) - { - useDocument->InsertEndChild(element); - XMLPrinter printer; - useDocument->Print(&printer); - *string = std::string(printer.CStr()); - } -} - -static void _anm2_animation_serialize(Anm2Animation* animation, XMLDocument* document = nullptr, XMLElement* addElement = nullptr, std::string* string = nullptr) -{ - XMLDocument localDocument; - XMLDocument* useDocument = document ? document : &localDocument; - - // Animation - XMLElement* element = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION]); - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], animation->name.c_str()); // Name - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_FRAME_NUM], animation->frameNum); // FrameNum - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_LOOP], animation->isLoop); // Loop - - // RootAnimation - XMLElement* rootElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ROOT_ANIMATION]); - - for (auto& frame : animation->rootAnimation.frames) - _anm2_frame_serialize(&frame, ANM2_ROOT, useDocument, rootElement); - - element->InsertEndChild(rootElement); - - // LayerAnimations - XMLElement* layersElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATIONS]); - - for (auto& id : animation->layerOrder) - { - // LayerAnimation - Anm2Item& layerAnimation = animation->layerAnimations[id]; - XMLElement* layerElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION]); - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_LAYER_ID], id); // LayerId - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], layerAnimation.isVisible); // Visible - - for (auto& frame : layerAnimation.frames) - _anm2_frame_serialize(&frame, ANM2_LAYER, useDocument, layerElement); - - layersElement->InsertEndChild(layerElement); - } - - element->InsertEndChild(layersElement); - - // Nulls - XMLElement* nullsElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATIONS]); - - for (auto& [id, null] : animation->nullAnimations) - { - // NullAnimation - XMLElement* nullElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION]); - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NULL_ID], id); // NullId - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], null.isVisible); // Visible - - for (auto& frame : null.frames) - _anm2_frame_serialize(&frame, ANM2_NULL, useDocument, nullElement); - - nullsElement->InsertEndChild(nullElement); - } - - element->InsertEndChild(nullsElement); - - // Triggers - XMLElement* triggersElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS]); - - for (auto& frame : animation->triggers.frames) - _anm2_frame_serialize(&frame, ANM2_TRIGGERS, useDocument, triggersElement); - - element->InsertEndChild(triggersElement); - - if (addElement) addElement->InsertEndChild(element); - - if (string && !document) - { - useDocument->InsertEndChild(element); - XMLPrinter printer; - useDocument->Print(&printer); - *string = std::string(printer.CStr()); - } -} - -bool anm2_serialize(Anm2* self, const std::string& path) -{ - XMLDocument document; - - if (!self || path.empty()) return false; - - if (self->version == 0) _anm2_created_on_set(self); - - self->path = path; - self->version++; - - // AnimatedActor - XMLElement* animatedActorElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATED_ACTOR]); - document.InsertFirstChild(animatedActorElement); - - // Info - XMLElement* infoElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_INFO]); - infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_CREATED_BY], self->createdBy.c_str()); // CreatedBy - infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_CREATED_ON], self->createdOn.c_str()); // CreatedOn - infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VERSION], self->version); // Version - infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_FPS], self->fps); // FPS - animatedActorElement->InsertEndChild(infoElement); - - // Content - XMLElement* contentElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_CONTENT]); - - // Spritesheets - XMLElement* spritesheetsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEETS]); - - for (auto& [id, spritesheet] : self->spritesheets) - { - // Spritesheet - XMLElement* spritesheetElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET]); - spritesheetElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_PATH], spritesheet.path.c_str()); // Path - spritesheetElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID - spritesheetsElement->InsertEndChild(spritesheetElement); - } - - contentElement->InsertEndChild(spritesheetsElement); - - // Layers - XMLElement* layersElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYERS]); - - for (auto& [id, layer] : self->layers) - { - // Layer - XMLElement* layerElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER]); - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], layer.name.c_str()); // Path - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SPRITESHEET_ID], layer.spritesheetID); // SpritesheetId - layersElement->InsertEndChild(layerElement); - } - - contentElement->InsertEndChild(layersElement); - - // Nulls - XMLElement* nullsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULLS]); - - for (auto& [id, null] : self->nulls) - { - // Null - XMLElement* nullElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL]); - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], null.name.c_str()); // Name - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID - if (null.isShowRect) nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SHOW_RECT], null.isShowRect); // ShowRect - nullsElement->InsertEndChild(nullElement); - } - - contentElement->InsertEndChild(nullsElement); - - // Events - XMLElement* eventsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENTS]); - - for (auto& [id, event] : self->events) - { - // Event - XMLElement* eventElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT]); - eventElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], event.name.c_str()); // Name - eventElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID - eventsElement->InsertEndChild(eventElement); - } - - contentElement->InsertEndChild(eventsElement); - - animatedActorElement->InsertEndChild(contentElement); - - // Animations - XMLElement* animationsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATIONS]); - if (self->defaultAnimationID != ID_NONE) - animationsElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DEFAULT_ANIMATION], self->animations[self->defaultAnimationID].name.c_str()); // DefaultAnimation - - for (auto& [id, animation] : self->animations) - _anm2_animation_serialize(&animation, &document, animationsElement); - - animatedActorElement->InsertEndChild(animationsElement); - - XMLError error = document.SaveFile(path.c_str()); - - if (error != XML_SUCCESS) - { - log_error(std::format(ANM2_WRITE_ERROR, path)); - return false; - } - - log_info(std::format(ANM2_WRITE_INFO, path)); - - return true; -} - -static void _anm2_frame_deserialize(Anm2Frame* frame, const XMLElement* element) -{ - for (const XMLAttribute* attribute = element->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_X_POSITION: frame->position.x = std::atof(attribute->Value()); break; // XPosition - case ANM2_ATTRIBUTE_Y_POSITION: frame->position.y = std::atof(attribute->Value()); break; // YPosition - case ANM2_ATTRIBUTE_X_PIVOT: frame->pivot.x = std::atof(attribute->Value()); break; // XPivot - case ANM2_ATTRIBUTE_Y_PIVOT: frame->pivot.y = std::atof(attribute->Value()); break; // YPivot - case ANM2_ATTRIBUTE_X_CROP: frame->crop.x = std::atof(attribute->Value()); break; // XCrop - case ANM2_ATTRIBUTE_Y_CROP: frame->crop.y = std::atof(attribute->Value()); break; // YCrop - case ANM2_ATTRIBUTE_WIDTH: frame->size.x = std::atof(attribute->Value()); break; // Width - case ANM2_ATTRIBUTE_HEIGHT: frame->size.y = std::atof(attribute->Value()); break; // Height - case ANM2_ATTRIBUTE_X_SCALE: frame->scale.x = std::atof(attribute->Value()); break; // XScale - case ANM2_ATTRIBUTE_Y_SCALE: frame->scale.y = std::atof(attribute->Value()); break; // YScale - case ANM2_ATTRIBUTE_RED_TINT: frame->tintRGBA.r = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // RedTint - case ANM2_ATTRIBUTE_GREEN_TINT: frame->tintRGBA.g = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // GreenTint - case ANM2_ATTRIBUTE_BLUE_TINT: frame->tintRGBA.b = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // BlueTint - case ANM2_ATTRIBUTE_ALPHA_TINT: frame->tintRGBA.a = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // AlphaTint - case ANM2_ATTRIBUTE_RED_OFFSET: frame->offsetRGB.r = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // RedOffset - case ANM2_ATTRIBUTE_GREEN_OFFSET: frame->offsetRGB.g = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // GreenOffset - case ANM2_ATTRIBUTE_BLUE_OFFSET: frame->offsetRGB.b = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // BlueOffset - case ANM2_ATTRIBUTE_ROTATION: frame->rotation = std::atof(attribute->Value()); break; // Rotation - case ANM2_ATTRIBUTE_VISIBLE: frame->isVisible = string_to_bool(attribute->Value()); break; // Visible - case ANM2_ATTRIBUTE_INTERPOLATED: frame->isInterpolated = string_to_bool(attribute->Value()); break; // Interpolated - case ANM2_ATTRIBUTE_AT_FRAME: frame->atFrame = std::atoi(attribute->Value()); break; // AtFrame - case ANM2_ATTRIBUTE_DELAY: frame->delay = std::atoi(attribute->Value()); break; // Delay - case ANM2_ATTRIBUTE_EVENT_ID: frame->eventID = std::atoi(attribute->Value()); break; // EventID - default: break; - } - } -} - -static void _anm2_animation_deserialize(Anm2Animation* animation, const XMLElement* element) -{ - auto frames_deserialize = [&](const XMLElement* itemElement, Anm2Item* item) - { - // Frame - for - ( - const XMLElement* frame = itemElement->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]); - frame; frame = frame->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]) - ) - _anm2_frame_deserialize(&item->frames.emplace_back(Anm2Frame()), frame); - }; - - s32 id{}; - - for (const XMLAttribute* attribute = element->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_NAME: animation->name = std::string(attribute->Value()); break; // Name - case ANM2_ATTRIBUTE_FRAME_NUM: animation->frameNum = std::atoi(attribute->Value()); break; // FrameNum - case ANM2_ATTRIBUTE_LOOP: animation->isLoop = string_to_bool(attribute->Value()); break; // Loop - default: break; - } - } - - // RootAnimation - if (const XMLElement* rootAnimation = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ROOT_ANIMATION])) - frames_deserialize(rootAnimation, &animation->rootAnimation); - - // LayerAnimations - if (const XMLElement* layerAnimations = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATIONS])) - { - // LayerAnimation - for - ( - const XMLElement* layerAnimation = layerAnimations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION]); - layerAnimation; layerAnimation = layerAnimation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION]) - ) - { - Anm2Item layerAnimationItem; - - for (const XMLAttribute* attribute = layerAnimation->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_LAYER_ID: id = std::atoi(attribute->Value()); break; // LayerID - case ANM2_ATTRIBUTE_VISIBLE: layerAnimationItem.isVisible = string_to_bool(attribute->Value()); break; // Visible - default: break; - } - } - - frames_deserialize(layerAnimation, &layerAnimationItem); - animation->layerAnimations[id] = layerAnimationItem; - animation->layerOrder.push_back(id); - } - } - - // NullAnimations - if (const XMLElement* nullAnimations = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATIONS])) - { - // NullAnimation - for - ( - const XMLElement* nullAnimation = nullAnimations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION]); - nullAnimation; nullAnimation = nullAnimation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION]) - ) - { - Anm2Item nullAnimationItem; - - for (const XMLAttribute* attribute = nullAnimation->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_NULL_ID: id = std::atoi(attribute->Value()); break; - case ANM2_ATTRIBUTE_VISIBLE: nullAnimationItem.isVisible = string_to_bool(attribute->Value()); break; - default: break; - } - } - - frames_deserialize(nullAnimation, &nullAnimationItem); - animation->nullAnimations[id] = nullAnimationItem; - } - } - - // Triggers - if (const XMLElement* triggers = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS])) - { - // Trigger - for - ( - const XMLElement* trigger = triggers->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]); - trigger; trigger = trigger->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]) - ) - _anm2_frame_deserialize(&animation->triggers.frames.emplace_back(Anm2Frame()), trigger); - } -} - -bool anm2_deserialize(Anm2* self, const std::string& path, bool isTextures) -{ - if (!self) return false; - - if (path.empty()) - { - log_error(ANM2_EMPTY_ERROR); - return false; - } - - XMLDocument document; - if (document.LoadFile(path.c_str()) != XML_SUCCESS) - { - log_error(std::format(ANM2_PARSE_ERROR, path, document.ErrorStr())); - return false; - } - - anm2_new(self); - self->path = path; - std::string defaultAnimation{}; - s32 id{}; - - // Save old working directory and then use anm2's path as directory - // (used for loading textures from anm2 correctly which are relative) - std::filesystem::path workingPath = std::filesystem::current_path(); - working_directory_from_file_set(path); - - const XMLElement* root = document.RootElement(); - - // Info - if (const XMLElement* info = root->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_INFO])) - { - for (const XMLAttribute* attribute = info->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_CREATED_BY: self->createdBy = std::string(attribute->Value()); break; // CreatedBy - case ANM2_ATTRIBUTE_CREATED_ON: self->createdOn = std::string(attribute->Value()); break; // CreatedOn - case ANM2_ATTRIBUTE_VERSION: self->version = std::atoi(attribute->Value()); break; // Version - case ANM2_ATTRIBUTE_FPS: self->fps = std::atoi(attribute->Value()); break; // FPS - default: break; - } - } - } - - // Content - if (const XMLElement* content = root->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_CONTENT])) - { - // Spritesheets - if (const XMLElement* spritesheets = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEETS])) - { - for - ( - const XMLElement* spritesheet = spritesheets->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET]); - spritesheet; spritesheet = spritesheet->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET]) - ) - { - Anm2Spritesheet addSpritesheet; - - for (const XMLAttribute* attribute = spritesheet->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_PATH: - // Spritesheet paths from Isaac Rebirth are made with the assumption that - // the paths are case-insensitive (as the game was developed on Windows) - // However when using the resource dumper, the spritesheet paths are all lowercase (on Linux anyways) - // If the check doesn't work, set the spritesheet path to lowercase - // If the check doesn't work, replace backslashes with slashes - // At the minimum this should make all textures be able to be loaded on Linux - // If it doesn't work beyond that then that's on the user :^) - addSpritesheet.path = attribute->Value(); - if (!path_exists(addSpritesheet.path)) addSpritesheet.path = string_to_lowercase(addSpritesheet.path); - if (!path_exists(addSpritesheet.path)) addSpritesheet.path = string_backslash_replace(addSpritesheet.path); - if (isTextures) texture_from_path_init(&addSpritesheet.texture, addSpritesheet.path); - break; - case ANM2_ATTRIBUTE_ID: id = std::atoi(attribute->Value()); break; - default: break; - } - } - - self->spritesheets[id] = addSpritesheet; - } - } - - // Layers - if (const XMLElement* layers = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYERS])) - { - for - ( - const XMLElement* layer = layers->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER]); - layer; layer = layer->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER]) - ) - { - Anm2Layer addLayer; - - for (const XMLAttribute* attribute = layer->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_NAME: addLayer.name = std::string(attribute->Value()); break; // Name - case ANM2_ATTRIBUTE_ID: id = std::atoi(attribute->Value()); break; // ID - case ANM2_ATTRIBUTE_SPRITESHEET_ID: addLayer.spritesheetID = std::atoi(attribute->Value()); break; // ID - default: break; - } - } - - self->layers[id] = addLayer; - } - } - - // Nulls - if (const XMLElement* nulls = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULLS])) - { - for - ( - const XMLElement* null = nulls->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL]); - null; null = null->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL]) - ) - { - Anm2Null addNull; - - for (const XMLAttribute* attribute = null->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_NAME: addNull.name = std::string(attribute->Value()); break; // Name - case ANM2_ATTRIBUTE_ID: id = std::atoi(attribute->Value()); break; // IDs - default: break; - } - } - - self->nulls[id] = addNull; - } - } - - // Events - if (const XMLElement* events = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENTS])) - { - // Event - for - ( - const XMLElement* event = events->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT]); - event; event = event->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT]) - ) - { - Anm2Event addEvent; - - for (const XMLAttribute* attribute = event->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_NAME: addEvent.name = std::string(attribute->Value()); break; // Name - case ANM2_ATTRIBUTE_ID: id = std::atoi(attribute->Value()); break; // ID - default: break; - } - } - - self->events[id] = addEvent; - } - } - } - - // Animations - if (const XMLElement* animations = root->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATIONS])) - { - for (const XMLAttribute* attribute = animations->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_DEFAULT_ANIMATION: defaultAnimation = std::string(attribute->Value()); break; // DefaultAnimation - default: break; - } - } - - // Animation - for - ( - const XMLElement* animation = animations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION]); - animation; animation = animation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION]) - ) - _anm2_animation_deserialize(&self->animations[map_next_id_get(self->animations)], animation); - } - - for (auto& [id, animation] : self->animations) - if (animation.name == defaultAnimation) - self->defaultAnimationID = id; - - if (isTextures) anm2_spritesheet_texture_pixels_download(self); - - std::filesystem::current_path(workingPath); - - log_info(std::format(ANM2_READ_INFO, path)); - - return true; -} - -void anm2_animation_layer_animation_add(Anm2Animation* animation, s32 id) -{ - animation->layerAnimations[id] = Anm2Item{}; - animation->layerOrder.push_back(id); -} - -void anm2_animation_layer_animation_remove(Anm2Animation* animation, s32 id) -{ - animation->layerAnimations.erase(id); - vector_value_erase(animation->layerOrder, id); -} - -void anm2_animation_null_animation_add(Anm2Animation* animation, s32 id) -{ - animation->nullAnimations[id] = Anm2Item{}; -} - -void anm2_animation_null_animation_remove(Anm2Animation* animation, s32 id) -{ - animation->nullAnimations.erase(id); -} - -s32 anm2_layer_add(Anm2* self) -{ - s32 id = map_next_id_get(self->layers); - self->layers[id] = Anm2Layer{}; - return id; -} - -void anm2_layer_remove(Anm2* self, s32 id) -{ - self->layers.erase(id); - - for (auto& [_, animation] : self->animations) - anm2_animation_layer_animation_remove(&animation, id); -} - -s32 anm2_null_add(Anm2* self) -{ - s32 id = map_next_id_get(self->nulls); - self->nulls[id] = Anm2Null{}; - return id; -} - -void anm2_null_remove(Anm2* self, s32 id) -{ - if (!self->nulls.contains(id)) return; - - self->nulls.erase(id); - - for (auto& [_, animation] : self->animations) - anm2_animation_null_animation_remove(&animation, id); -} - -s32 anm2_animation_add(Anm2* self, Anm2Animation* animation, s32 id) -{ - s32 addID = map_next_id_get(self->animations); - - Anm2Animation localAnimation; - Anm2Animation* addAnimation = animation ? animation : &localAnimation; - - if (!animation) addAnimation->rootAnimation.frames.push_back(Anm2Frame{}); - - if (id != ID_NONE) - { - map_insert_shift(self->animations, id, *addAnimation); - return id + 1; - } - else - self->animations[addID] = *addAnimation; - - return addID; -} - -void anm2_animation_remove(Anm2* self, s32 id) -{ - self->animations.erase(id); -} - -void anm2_new(Anm2* self) -{ - *self = Anm2{}; - _anm2_created_on_set(self); -} - -Anm2Animation* anm2_animation_from_reference(Anm2* self, Anm2Reference* reference) -{ - return map_find(self->animations, reference->animationID); -} - -Anm2Item* anm2_item_from_reference(Anm2* self, Anm2Reference* reference) -{ - if (reference->itemType == ANM2_NONE) return nullptr; - - Anm2Animation* animation = anm2_animation_from_reference(self, reference); - - if (!animation) return nullptr; - - switch (reference->itemType) - { - case ANM2_ROOT: return &animation->rootAnimation; - case ANM2_LAYER: return map_find(animation->layerAnimations, reference->itemID); - case ANM2_NULL: return map_find(animation->nullAnimations, reference->itemID); - case ANM2_TRIGGERS: return &animation->triggers; - default: return nullptr; - } -} - -s32 anm2_frame_index_from_time(Anm2* self, Anm2Reference reference, f32 time) -{ - Anm2Animation* animation = anm2_animation_from_reference(self, &reference); - - if (!animation) return INDEX_NONE; - if (time < 0 || time > animation->frameNum) return INDEX_NONE; - - Anm2Item* item = anm2_item_from_reference(self, &reference); - - if (!item) return INDEX_NONE; - - if (reference.itemType == ANM2_TRIGGERS) - for (auto [i, frame] : std::views::enumerate(item->frames)) - if (frame.atFrame == (s32)time) return i; - - s32 delayCurrent = 0; - s32 delayNext = 0; - - for (auto [i, frame] : std::views::enumerate(item->frames)) - { - delayNext += frame.delay; - - if (time >= delayCurrent && time < delayNext) - return i; - - delayCurrent += frame.delay; - } - - return INDEX_NONE; -} - -Anm2Frame* anm2_frame_from_reference(Anm2* self, Anm2Reference* reference) -{ - Anm2Item* item = anm2_item_from_reference(self, reference); - - if (!item) return nullptr; - - if (reference->frameIndex <= INDEX_NONE || reference->frameIndex >= (s32)item->frames.size()) - return nullptr; - - return &item->frames[reference->frameIndex]; -} - -void anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, f32 time) -{ - Anm2Animation* animation = anm2_animation_from_reference(self, &reference); - if (!animation) return; - - time = std::clamp(ROUND_NEAREST_MULTIPLE(time, 1.0f), 0.0f, animation->frameNum - 1.0f); - - Anm2Item* item = anm2_item_from_reference(self, &reference); - - if (!item) return; - - Anm2Frame* frameNext = nullptr; - s32 delayCurrent = 0; - s32 delayNext = 0; - - for (auto [i, iFrame] : std::views::enumerate(item->frames)) - { - if (reference.itemType == ANM2_TRIGGERS) - { - if ((s32)time == iFrame.atFrame) - { - *frame = iFrame; - break; - } - } - else - { - *frame = iFrame; - - delayNext += frame->delay; - - if (time >= delayCurrent && time < delayNext) - { - if (i + 1 < (s32)item->frames.size()) - frameNext = &item->frames[i + 1]; - else - frameNext = nullptr; - break; - } - - delayCurrent += frame->delay; - } - } - - if (reference.itemType == ANM2_TRIGGERS) - return; - - if (frame->isInterpolated && frameNext && frame->delay > 1) - { - f32 interpolation = (time - delayCurrent) / (delayNext - delayCurrent); - - frame->rotation = glm::mix(frame->rotation, frameNext->rotation, interpolation); - frame->position = glm::mix(frame->position, frameNext->position, interpolation); - frame->scale = glm::mix(frame->scale, frameNext->scale, interpolation); - frame->offsetRGB = glm::mix(frame->offsetRGB, frameNext->offsetRGB, interpolation); - frame->tintRGBA = glm::mix(frame->tintRGBA, frameNext->tintRGBA, interpolation); - } -} - -s32 anm2_animation_length_get(Anm2Animation* self) -{ - s32 length = 0; - - auto accumulate_max_delay = [&](const std::vector& frames) - { - s32 delaySum = 0; - for (const auto& frame : frames) - { - delaySum += frame.delay; - length = std::max(length, delaySum); - } - }; - - accumulate_max_delay(self->rootAnimation.frames); - - for (const auto& [_, item] : self->layerAnimations) - accumulate_max_delay(item.frames); - - for (const auto& [_, item] : self->nullAnimations) - accumulate_max_delay(item.frames); - - for (const auto& frame : self->triggers.frames) - length = std::max(length, frame.atFrame + 1); - - return length; -} - -void anm2_animation_length_set(Anm2Animation* self) -{ - self->frameNum = anm2_animation_length_get(self); -} - -Anm2Frame* anm2_frame_add(Anm2* self, Anm2Frame* frame, Anm2Reference* reference) -{ - Anm2Animation* animation = anm2_animation_from_reference(self, reference); - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!animation || !item) return nullptr; - - Anm2Frame frameAdd = frame ? *frame : Anm2Frame{}; - - if (reference->itemType == ANM2_TRIGGERS) - { - s32 atFrame = reference->time != VALUE_NONE ? (s32)reference->time : 0; - - for (auto& frameCheck : item->frames) - { - if (frameCheck.atFrame == atFrame) - { - atFrame++; - break; - } - } - - frameAdd.delay = 1; - frameAdd.atFrame = atFrame; - return &item->frames.emplace_back(frameAdd); - } - else - { - s32 index = reference->frameIndex; - - if (index < 0 || index >= (s32)item->frames.size()) - { - item->frames.push_back(frameAdd); - return &item->frames.back(); - } - else - { - item->frames.insert(item->frames.begin() + index, frameAdd); - return &item->frames[(size_t)(index)]; - } - } -} - -void anm2_frame_remove(Anm2* self, Anm2Reference* reference) -{ - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) return; - item->frames.erase(item->frames.begin() + reference->frameIndex); -} - -void anm2_reference_clear(Anm2Reference* self) -{ - *self = Anm2Reference{}; -} - -void anm2_reference_item_clear(Anm2Reference* self) -{ - *self = {self->animationID}; -} - -void anm2_reference_frame_clear(Anm2Reference* self) -{ - self->frameIndex = INDEX_NONE; -} - -void anm2_item_frame_set(Anm2* self, Anm2Reference* reference, const Anm2FrameChange& change, Anm2ChangeType type, s32 start, s32 count) -{ - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) return; - - if (start < 0 || count <= 0) return; - const s32 size = (s32)item->frames.size(); - if (size == 0 || start >= size) return; - - const s32 end = std::min(start + count, size); - - for (s32 i = start; i < end; ++i) - { - Anm2Frame& dest = item->frames[i]; - - // Booleans always just set if provided - if (change.isVisible) dest.isVisible = *change.isVisible; - if (change.isInterpolated) dest.isInterpolated = *change.isInterpolated; - - switch (type) - { - case ANM2_CHANGE_SET: - if (change.rotation) dest.rotation = *change.rotation; - if (change.delay) dest.delay = std::max(ANM2_FRAME_DELAY_MIN, *change.delay); - if (change.crop) dest.crop = *change.crop; - if (change.pivot) dest.pivot = *change.pivot; - if (change.position) dest.position = *change.position; - if (change.size) dest.size = *change.size; - if (change.scale) dest.scale = *change.scale; - if (change.offsetRGB) dest.offsetRGB = glm::clamp(*change.offsetRGB, 0.0f, 1.0f); - if (change.tintRGBA) dest.tintRGBA = glm::clamp(*change.tintRGBA, 0.0f, 1.0f); - break; - - case ANM2_CHANGE_ADD: - if (change.rotation) dest.rotation += *change.rotation; - if (change.delay) dest.delay = std::max(ANM2_FRAME_DELAY_MIN, dest.delay + *change.delay); - if (change.crop) dest.crop += *change.crop; - if (change.pivot) dest.pivot += *change.pivot; - if (change.position) dest.position += *change.position; - if (change.size) dest.size += *change.size; - if (change.scale) dest.scale += *change.scale; - if (change.offsetRGB) dest.offsetRGB = glm::clamp(dest.offsetRGB + *change.offsetRGB, 0.0f, 1.0f); - if (change.tintRGBA) dest.tintRGBA = glm::clamp(dest.tintRGBA + *change.tintRGBA, 0.0f, 1.0f); - break; - - case ANM2_CHANGE_SUBTRACT: - if (change.rotation) dest.rotation -= *change.rotation; - if (change.delay) dest.delay = std::max(ANM2_FRAME_DELAY_MIN, dest.delay - *change.delay); - if (change.crop) dest.crop -= *change.crop; - if (change.pivot) dest.pivot -= *change.pivot; - if (change.position) dest.position -= *change.position; - if (change.size) dest.size -= *change.size; - if (change.scale) dest.scale -= *change.scale; - if (change.offsetRGB) dest.offsetRGB = glm::clamp(dest.offsetRGB - *change.offsetRGB, 0.0f, 1.0f); - if (change.tintRGBA) dest.tintRGBA = glm::clamp(dest.tintRGBA - *change.tintRGBA, 0.0f, 1.0f); - break; - } - } -} - -void anm2_animation_merge(Anm2* self, s32 animationID, const std::vector& mergeIDs, Anm2MergeType type) -{ - Anm2Animation newAnimation = self->animations[animationID]; - - auto merge_item = [&](Anm2Item& destinationItem, const Anm2Item& sourceItem) - { - switch (type) - { - case ANM2_MERGE_APPEND: - destinationItem.frames.insert(destinationItem.frames.end(), sourceItem.frames.begin(), sourceItem.frames.end()); - break; - case ANM2_MERGE_PREPEND: - destinationItem.frames.insert(destinationItem.frames.begin(), sourceItem.frames.begin(), sourceItem.frames.end()); - break; - case ANM2_MERGE_REPLACE: - if (destinationItem.frames.size() < sourceItem.frames.size()) - destinationItem.frames.resize(sourceItem.frames.size()); - for (s32 i = 0; i < (s32)sourceItem.frames.size(); i++) - destinationItem.frames[i] = sourceItem.frames[i]; - break; - case ANM2_MERGE_IGNORE: - break; - } - }; - - for (auto mergeID : mergeIDs) - { - if (animationID == mergeID) continue; - - const Anm2Animation& mergeAnimation = self->animations[mergeID]; - - merge_item(newAnimation.rootAnimation, mergeAnimation.rootAnimation); - - for (const auto& [id, layerAnimation] : mergeAnimation.layerAnimations) - merge_item(newAnimation.layerAnimations[id], layerAnimation); - - for (const auto& [id, nullAnimation] : mergeAnimation.nullAnimations) - merge_item(newAnimation.nullAnimations[id], nullAnimation); - - merge_item(newAnimation.triggers, mergeAnimation.triggers); - } - - self->animations[animationID] = newAnimation; - - anm2_animation_length_set(&self->animations[animationID]); -} - -void anm2_frame_bake(Anm2* self, Anm2Reference* reference, s32 interval, bool isRoundScale, bool isRoundRotation) -{ - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) return; - - Anm2Frame* frame = anm2_frame_from_reference(self, reference); - if (!frame) return; - - Anm2Reference referenceNext = *reference; - referenceNext.frameIndex = reference->frameIndex + 1; - - Anm2Frame* frameNext = anm2_frame_from_reference(self, &referenceNext); - if (!frameNext) frameNext = frame; - - const Anm2Frame baseFrame = *frame; - const Anm2Frame baseFrameNext = *frameNext; - - s32 delay = 0; - s32 insertIndex = reference->frameIndex; - - while (delay < baseFrame.delay) - { - f32 interpolation = (f32)delay / baseFrame.delay; - - Anm2Frame baked = *frame; - baked.delay = std::min(interval, baseFrame.delay - delay); - baked.isInterpolated = (insertIndex == reference->frameIndex) ? baseFrame.isInterpolated : false; - - baked.rotation = glm::mix(baseFrame.rotation, baseFrameNext.rotation, interpolation); - baked.position = glm::mix(baseFrame.position, baseFrameNext.position, interpolation); - baked.scale = glm::mix(baseFrame.scale, baseFrameNext.scale, interpolation); - baked.offsetRGB = glm::mix(baseFrame.offsetRGB, baseFrameNext.offsetRGB, interpolation); - baked.tintRGBA = glm::mix(baseFrame.tintRGBA, baseFrameNext.tintRGBA, interpolation); - - if (isRoundScale) baked.scale = vec2((s32)baked.scale.x, (s32)baked.scale.y); - if (isRoundRotation) baked.rotation = (s32)baked.rotation; - - if (insertIndex == reference->frameIndex) - item->frames[insertIndex] = baked; - else - item->frames.insert(item->frames.begin() + insertIndex, baked); - insertIndex++; - - delay += baked.delay; - } -} - -void anm2_scale(Anm2* self, f32 scale) -{ - auto frame_scale = [&](Anm2Frame& frame) - { - frame.position = vec2((s32)(frame.position.x * scale), (s32)(frame.position.y * scale)); - frame.size = vec2((s32)(frame.size.x * scale), (s32)(frame.size.y * scale)); - frame.crop = vec2((s32)(frame.crop.x * scale), (s32)(frame.crop.y * scale)); - frame.pivot = vec2((s32)(frame.pivot.x * scale), (s32)(frame.pivot.y * scale)); - }; - - for (auto& [_, animation] : self->animations) - { - for (auto& frame : animation.rootAnimation.frames) - frame_scale(frame); - - for (auto& [_, layerAnimation] : animation.layerAnimations) - for (auto& frame : layerAnimation.frames) - frame_scale(frame); - - for (auto& [_, nullAnimation] : animation.nullAnimations) - for (auto& frame : nullAnimation.frames) - frame_scale(frame); - } -} - -void anm2_generate_from_grid(Anm2* self, Anm2Reference* reference, vec2 startPosition, vec2 size, vec2 pivot, s32 columns, s32 count, s32 delay) -{ - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) return; - - Anm2Reference frameReference = *reference; - - for (s32 i = 0; i < count; i++) - { - const s32 row = i / columns; - const s32 column = i % columns; - - Anm2Frame frame{}; - - frame.delay = delay; - frame.pivot = pivot; - frame.size = size; - frame.crop = startPosition + vec2(size.x * column, size.y * row); - - anm2_frame_add(self, &frame, &frameReference); - frameReference.frameIndex++; - } -} - -void anm2_free(Anm2* self) -{ - for (auto& [id, spritesheet] : self->spritesheets) - texture_free(&spritesheet.texture); -} - -void anm2_spritesheet_texture_pixels_upload(Anm2* self) -{ - for (auto& [_, spritesheet] : self->spritesheets) - { - Texture& texture = spritesheet.texture; - - if (texture.id != GL_ID_NONE && !texture.isInvalid) - { - assert(!spritesheet.pixels.empty()); - glBindTexture(GL_TEXTURE_2D, texture.id); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture.size.x, texture.size.y, GL_RGBA, GL_UNSIGNED_BYTE, spritesheet.pixels.data()); - } - } -} - -void anm2_spritesheet_texture_pixels_download(Anm2* self) -{ - for (auto& [_, spritesheet] : self->spritesheets) - { - Texture& texture = spritesheet.texture; - - if (texture.id != GL_ID_NONE && !texture.isInvalid) - { - size_t bufferSize = (size_t)texture.size.x * (size_t)texture.size.y * TEXTURE_CHANNELS; - spritesheet.pixels.resize(bufferSize); - glBindTexture(GL_TEXTURE_2D, texture.id); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, spritesheet.pixels.data()); - } - } -} - -vec4 anm2_animation_rect_get(Anm2* self, Anm2Reference* reference, bool isRootTransform) -{ - f32 minX = std::numeric_limits::infinity(); - f32 minY = std::numeric_limits::infinity(); - f32 maxX = -std::numeric_limits::infinity(); - f32 maxY = -std::numeric_limits::infinity(); - - bool any = false; - - Anm2Frame frame; - Anm2Frame root; - - Anm2Animation* animation = anm2_animation_from_reference(self, reference); - if (!animation) return vec4(-1.0f); - - for (f32 t = 0.0f; t <= animation->frameNum; t += 1.0f) - { - for (const auto& [id, _] : animation->layerAnimations) - { - anm2_frame_from_time(self, &frame, {reference->animationID, ANM2_LAYER, id}, t); - if (!frame.isVisible) continue; - if (frame.size.x <= 0 || frame.size.y <= 0) continue; - - mat4 rootModel(1.0f); - if (isRootTransform) - { - anm2_frame_from_time(self, &root, {reference->animationID, ANM2_ROOT}, t); - rootModel = quad_model_parent_get(root.position, root.pivot, PERCENT_TO_UNIT(root.scale), root.rotation); - } - - mat4 model = quad_model_get(frame.size, frame.position, frame.pivot, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 fullModel = rootModel * model; - - vec2 corners[4] = { {0,0}, {1,0}, {1,1}, {0,1} }; - - for (auto& corner : corners) - { - vec4 world = fullModel * vec4(corner, 0.0f, 1.0f); - minX = std::min(minX, world.x); - minY = std::min(minY, world.y); - maxX = std::max(maxX, world.x); - maxY = std::max(maxY, world.y); - any = true; - } - } +static void _anm2_frame_serialize(Anm2Frame* frame, Anm2Type type, XMLDocument* document = nullptr, XMLElement* addElement = nullptr, + std::string* string = nullptr) { + XMLDocument localDocument; + XMLDocument* useDocument = document ? document : &localDocument; + + XMLElement* element = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]); + + if (type == ANM2_TRIGGER) { + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_EVENT_ID], frame->eventID); // EventID + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_AT_FRAME], frame->atFrame); // AtFrame + } else { + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_POSITION], frame->position.x); // XPosition + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_POSITION], frame->position.y); // YPosition + + if (type == ANM2_LAYER) { + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_PIVOT], frame->pivot.x); // XPivot + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_PIVOT], frame->pivot.y); // YPivot + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_CROP], frame->crop.x); // XCrop + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_CROP], frame->crop.y); // YCrop + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_WIDTH], frame->size.x); // Width + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_HEIGHT], frame->size.y); // Height } - if (!any) return vec4(-1.0f); - return {minX, minY, maxX - minX, maxY - minY}; + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_SCALE], frame->scale.x); // XScale + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_SCALE], frame->scale.y); // YScale + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DELAY], frame->delay); /* Delay */ + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], frame->isVisible); // Visible + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_TINT], FLOAT_TO_UINT8(frame->tintRGBA.r)); // RedTint + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], FLOAT_TO_UINT8(frame->tintRGBA.g)); // GreenTint + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], FLOAT_TO_UINT8(frame->tintRGBA.b)); // BlueTint + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], FLOAT_TO_UINT8(frame->tintRGBA.a)); // AlphaTint + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], FLOAT_TO_UINT8(frame->offsetRGB.r)); // RedOffset + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], FLOAT_TO_UINT8(frame->offsetRGB.g)); // GreenOffset + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], FLOAT_TO_UINT8(frame->offsetRGB.b)); // BlueOffset + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ROTATION], frame->rotation); // Rotation + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_INTERPOLATED], frame->isInterpolated); // Interpolated + } + + if (addElement) + addElement->InsertEndChild(element); + + if (string && !document) { + useDocument->InsertEndChild(element); + XMLPrinter printer; + useDocument->Print(&printer); + *string = std::string(printer.CStr()); + } } -void anm2_animation_serialize_to_string(Anm2Animation* animation, std::string* string) -{ - _anm2_animation_serialize(animation, nullptr, nullptr, string); +static void _anm2_animation_serialize(Anm2Animation* animation, XMLDocument* document = nullptr, XMLElement* addElement = nullptr, + std::string* string = nullptr) { + XMLDocument localDocument; + XMLDocument* useDocument = document ? document : &localDocument; + + // Animation + XMLElement* element = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION]); + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], animation->name.c_str()); // Name + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_FRAME_NUM], animation->frameNum); // FrameNum + element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_LOOP], animation->isLoop); // Loop + + // RootAnimation + XMLElement* rootElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ROOT_ANIMATION]); + + for (auto& frame : animation->rootAnimation.frames) + _anm2_frame_serialize(&frame, ANM2_ROOT, useDocument, rootElement); + + element->InsertEndChild(rootElement); + + // LayerAnimations + XMLElement* layersElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATIONS]); + + for (auto& id : animation->layerOrder) { + // LayerAnimation + Anm2Item& layerAnimation = animation->layerAnimations[id]; + XMLElement* layerElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION]); + layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_LAYER_ID], id); // LayerId + layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], layerAnimation.isVisible); // Visible + + for (auto& frame : layerAnimation.frames) + _anm2_frame_serialize(&frame, ANM2_LAYER, useDocument, layerElement); + + layersElement->InsertEndChild(layerElement); + } + + element->InsertEndChild(layersElement); + + // Nulls + XMLElement* nullsElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATIONS]); + + for (auto& [id, null] : animation->nullAnimations) { + // NullAnimation + XMLElement* nullElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION]); + nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NULL_ID], id); // NullId + nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], null.isVisible); // Visible + + for (auto& frame : null.frames) + _anm2_frame_serialize(&frame, ANM2_NULL, useDocument, nullElement); + + nullsElement->InsertEndChild(nullElement); + } + + element->InsertEndChild(nullsElement); + + // Triggers + XMLElement* triggersElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS]); + + for (auto& frame : animation->triggers.frames) + _anm2_frame_serialize(&frame, ANM2_TRIGGER, useDocument, triggersElement); + + element->InsertEndChild(triggersElement); + + if (addElement) + addElement->InsertEndChild(element); + + if (string && !document) { + useDocument->InsertEndChild(element); + XMLPrinter printer; + useDocument->Print(&printer); + *string = std::string(printer.CStr()); + } } -void anm2_frame_serialize_to_string(Anm2Frame* frame, Anm2Type type, std::string* string) -{ - _anm2_frame_serialize(frame, type, nullptr, nullptr, string); +bool anm2_serialize(Anm2* self, const std::string& path) { + XMLDocument document; + + if (!self || path.empty()) + return false; + + if (self->version == 0) + _anm2_created_on_set(self); + + self->path = path; + self->version++; + + // AnimatedActor + XMLElement* animatedActorElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATED_ACTOR]); + document.InsertFirstChild(animatedActorElement); + + // Info + XMLElement* infoElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_INFO]); + infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_CREATED_BY], self->createdBy.c_str()); // CreatedBy + infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_CREATED_ON], self->createdOn.c_str()); // CreatedOn + infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VERSION], self->version); // Version + infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_FPS], self->fps); // FPS + animatedActorElement->InsertEndChild(infoElement); + + // Content + XMLElement* contentElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_CONTENT]); + + // Spritesheets + XMLElement* spritesheetsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEETS]); + + for (auto& [id, spritesheet] : self->spritesheets) { + // Spritesheet + XMLElement* spritesheetElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET]); + spritesheetElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_PATH], spritesheet.path.c_str()); // Path + spritesheetElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID + spritesheetsElement->InsertEndChild(spritesheetElement); + } + + contentElement->InsertEndChild(spritesheetsElement); + + // Layers + XMLElement* layersElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYERS]); + + for (auto& [id, layer] : self->layers) { + // Layer + XMLElement* layerElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER]); + layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], layer.name.c_str()); // Path + layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID + layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SPRITESHEET_ID], layer.spritesheetID); // SpritesheetId + layersElement->InsertEndChild(layerElement); + } + + contentElement->InsertEndChild(layersElement); + + // Nulls + XMLElement* nullsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULLS]); + + for (auto& [id, null] : self->nulls) { + // Null + XMLElement* nullElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL]); + nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], null.name.c_str()); // Name + nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID + if (null.isShowRect) + nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SHOW_RECT], null.isShowRect); // ShowRect + nullsElement->InsertEndChild(nullElement); + } + + contentElement->InsertEndChild(nullsElement); + + // Events + XMLElement* eventsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENTS]); + + for (auto& [id, event] : self->events) { + // Event + XMLElement* eventElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT]); + eventElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], event.name.c_str()); // Name + eventElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID + eventsElement->InsertEndChild(eventElement); + } + + contentElement->InsertEndChild(eventsElement); + + animatedActorElement->InsertEndChild(contentElement); + + // Animations + XMLElement* animationsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATIONS]); + if (self->defaultAnimationID != ID_NONE) + animationsElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DEFAULT_ANIMATION], + self->animations[self->defaultAnimationID].name.c_str()); // DefaultAnimation + + for (auto& [id, animation] : self->animations) + _anm2_animation_serialize(&animation, &document, animationsElement); + + animatedActorElement->InsertEndChild(animationsElement); + + XMLError error = document.SaveFile(path.c_str()); + + if (error != XML_SUCCESS) { + log_error(std::format(ANM2_WRITE_ERROR, path)); + return false; + } + + log_info(std::format(ANM2_WRITE_INFO, path)); + + return true; } -bool anm2_animation_deserialize_from_xml(Anm2Animation* animation, const std::string& xml) -{ - XMLDocument document; - - auto animation_deserialize_error = [&]() - { - log_error(std::format(ANM2_ANIMATION_PARSE_ERROR, xml, document.ErrorStr())); - return false; - }; - - if (document.Parse(xml.c_str()) != XML_SUCCESS) return animation_deserialize_error(); - - const XMLElement* element = document.RootElement(); - if (!element) return animation_deserialize_error(); - if (std::string(element->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION])) - return animation_deserialize_error(); - - _anm2_animation_deserialize(animation, element); - return true; +static void _anm2_frame_deserialize(Anm2Frame* frame, const XMLElement* element) { + for (const XMLAttribute* attribute = element->FirstAttribute(); attribute; attribute = attribute->Next()) { + switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { + case ANM2_ATTRIBUTE_X_POSITION: + frame->position.x = std::atof(attribute->Value()); + break; // XPosition + case ANM2_ATTRIBUTE_Y_POSITION: + frame->position.y = std::atof(attribute->Value()); + break; // YPosition + case ANM2_ATTRIBUTE_X_PIVOT: + frame->pivot.x = std::atof(attribute->Value()); + break; // XPivot + case ANM2_ATTRIBUTE_Y_PIVOT: + frame->pivot.y = std::atof(attribute->Value()); + break; // YPivot + case ANM2_ATTRIBUTE_X_CROP: + frame->crop.x = std::atof(attribute->Value()); + break; // XCrop + case ANM2_ATTRIBUTE_Y_CROP: + frame->crop.y = std::atof(attribute->Value()); + break; // YCrop + case ANM2_ATTRIBUTE_WIDTH: + frame->size.x = std::atof(attribute->Value()); + break; // Width + case ANM2_ATTRIBUTE_HEIGHT: + frame->size.y = std::atof(attribute->Value()); + break; // Height + case ANM2_ATTRIBUTE_X_SCALE: + frame->scale.x = std::atof(attribute->Value()); + break; // XScale + case ANM2_ATTRIBUTE_Y_SCALE: + frame->scale.y = std::atof(attribute->Value()); + break; // YScale + case ANM2_ATTRIBUTE_RED_TINT: + frame->tintRGBA.r = UINT8_TO_FLOAT(std::atoi(attribute->Value())); + break; // RedTint + case ANM2_ATTRIBUTE_GREEN_TINT: + frame->tintRGBA.g = UINT8_TO_FLOAT(std::atoi(attribute->Value())); + break; // GreenTint + case ANM2_ATTRIBUTE_BLUE_TINT: + frame->tintRGBA.b = UINT8_TO_FLOAT(std::atoi(attribute->Value())); + break; // BlueTint + case ANM2_ATTRIBUTE_ALPHA_TINT: + frame->tintRGBA.a = UINT8_TO_FLOAT(std::atoi(attribute->Value())); + break; // AlphaTint + case ANM2_ATTRIBUTE_RED_OFFSET: + frame->offsetRGB.r = UINT8_TO_FLOAT(std::atoi(attribute->Value())); + break; // RedOffset + case ANM2_ATTRIBUTE_GREEN_OFFSET: + frame->offsetRGB.g = UINT8_TO_FLOAT(std::atoi(attribute->Value())); + break; // GreenOffset + case ANM2_ATTRIBUTE_BLUE_OFFSET: + frame->offsetRGB.b = UINT8_TO_FLOAT(std::atoi(attribute->Value())); + break; // BlueOffset + case ANM2_ATTRIBUTE_ROTATION: + frame->rotation = std::atof(attribute->Value()); + break; // Rotation + case ANM2_ATTRIBUTE_VISIBLE: + frame->isVisible = string_to_bool(attribute->Value()); + break; // Visible + case ANM2_ATTRIBUTE_INTERPOLATED: + frame->isInterpolated = string_to_bool(attribute->Value()); + break; // Interpolated + case ANM2_ATTRIBUTE_AT_FRAME: + frame->atFrame = std::atoi(attribute->Value()); + break; // AtFrame + case ANM2_ATTRIBUTE_DELAY: + frame->delay = std::atoi(attribute->Value()); + break; // Delay + case ANM2_ATTRIBUTE_EVENT_ID: + frame->eventID = std::atoi(attribute->Value()); + break; // EventID + default: + break; + } + } } -bool anm2_frame_deserialize_from_xml(Anm2Frame* frame, const std::string& xml) -{ - XMLDocument document; - - auto frame_deserialize_error = [&]() - { - log_error(std::format(ANM2_FRAME_PARSE_ERROR, xml, document.ErrorStr())); - return false; - }; +static void _anm2_animation_deserialize(Anm2Animation* animation, const XMLElement* element) { + auto frames_deserialize = [&](const XMLElement* itemElement, Anm2Item* item) { + // Frame + for (const XMLElement* frame = itemElement->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]); frame; + frame = frame->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME])) + _anm2_frame_deserialize(&item->frames.emplace_back(Anm2Frame()), frame); + }; - if (document.Parse(xml.c_str()) != XML_SUCCESS) return frame_deserialize_error(); + int id{}; - const XMLElement* element = document.RootElement(); - if (!element) return frame_deserialize_error(); + for (const XMLAttribute* attribute = element->FirstAttribute(); attribute; attribute = attribute->Next()) { + switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { + case ANM2_ATTRIBUTE_NAME: + animation->name = std::string(attribute->Value()); + break; // Name + case ANM2_ATTRIBUTE_FRAME_NUM: + animation->frameNum = std::atoi(attribute->Value()); + break; // FrameNum + case ANM2_ATTRIBUTE_LOOP: + animation->isLoop = string_to_bool(attribute->Value()); + break; // Loop + default: + break; + } + } - if - ( - std::string(element->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]) && - std::string(element->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]) - ) - return frame_deserialize_error(); + // RootAnimation + if (const XMLElement* rootAnimation = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ROOT_ANIMATION])) + frames_deserialize(rootAnimation, &animation->rootAnimation); - _anm2_frame_deserialize(frame, element); - - return true; + // LayerAnimations + if (const XMLElement* layerAnimations = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATIONS])) { + // LayerAnimation + for (const XMLElement* layerAnimation = layerAnimations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION]); layerAnimation; + layerAnimation = layerAnimation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION])) { + Anm2Item layerAnimationItem; + + for (const XMLAttribute* attribute = layerAnimation->FirstAttribute(); attribute; attribute = attribute->Next()) { + switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { + case ANM2_ATTRIBUTE_LAYER_ID: + id = std::atoi(attribute->Value()); + break; // LayerID + case ANM2_ATTRIBUTE_VISIBLE: + layerAnimationItem.isVisible = string_to_bool(attribute->Value()); + break; // Visible + default: + break; + } + } + + frames_deserialize(layerAnimation, &layerAnimationItem); + animation->layerAnimations[id] = layerAnimationItem; + animation->layerOrder.push_back(id); + } + } + + // NullAnimations + if (const XMLElement* nullAnimations = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATIONS])) { + // NullAnimation + for (const XMLElement* nullAnimation = nullAnimations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION]); nullAnimation; + nullAnimation = nullAnimation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION])) { + Anm2Item nullAnimationItem; + + for (const XMLAttribute* attribute = nullAnimation->FirstAttribute(); attribute; attribute = attribute->Next()) { + switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { + case ANM2_ATTRIBUTE_NULL_ID: + id = std::atoi(attribute->Value()); + break; + case ANM2_ATTRIBUTE_VISIBLE: + nullAnimationItem.isVisible = string_to_bool(attribute->Value()); + break; + default: + break; + } + } + + frames_deserialize(nullAnimation, &nullAnimationItem); + animation->nullAnimations[id] = nullAnimationItem; + } + } + + // Triggers + if (const XMLElement* triggers = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS])) { + // Trigger + for (const XMLElement* trigger = triggers->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]); trigger; + trigger = trigger->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER])) + _anm2_frame_deserialize(&animation->triggers.frames.emplace_back(Anm2Frame()), trigger); + } +} + +bool anm2_deserialize(Anm2* self, const std::string& path, bool isTextures) { + if (!self) + return false; + + if (path.empty()) { + log_error(ANM2_EMPTY_ERROR); + return false; + } + + XMLDocument document; + if (document.LoadFile(path.c_str()) != XML_SUCCESS) { + log_error(std::format(ANM2_PARSE_ERROR, path, document.ErrorStr())); + return false; + } + + anm2_new(self); + self->path = path; + std::string defaultAnimation{}; + int id{}; + + // Save old working directory and then use anm2's path as directory + // (used for loading textures from anm2 correctly which are relative) + std::filesystem::path workingPath = std::filesystem::current_path(); + working_directory_from_file_set(path); + + const XMLElement* root = document.RootElement(); + + // Info + if (const XMLElement* info = root->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_INFO])) { + for (const XMLAttribute* attribute = info->FirstAttribute(); attribute; attribute = attribute->Next()) { + switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { + case ANM2_ATTRIBUTE_CREATED_BY: + self->createdBy = std::string(attribute->Value()); + break; // CreatedBy + case ANM2_ATTRIBUTE_CREATED_ON: + self->createdOn = std::string(attribute->Value()); + break; // CreatedOn + case ANM2_ATTRIBUTE_VERSION: + self->version = std::atoi(attribute->Value()); + break; // Version + case ANM2_ATTRIBUTE_FPS: + self->fps = std::atoi(attribute->Value()); + break; // FPS + default: + break; + } + } + } + + // Content + if (const XMLElement* content = root->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_CONTENT])) { + // Spritesheets + if (const XMLElement* spritesheets = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEETS])) { + for (const XMLElement* spritesheet = spritesheets->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET]); spritesheet; + spritesheet = spritesheet->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET])) { + Anm2Spritesheet addSpritesheet; + + for (const XMLAttribute* attribute = spritesheet->FirstAttribute(); attribute; attribute = attribute->Next()) { + switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { + case ANM2_ATTRIBUTE_PATH: + // Spritesheet paths from Isaac Rebirth are made with the assumption that + // the paths are case-insensitive (as the game was developed on Windows) + // However when using the resource dumper, the spritesheet paths are all lowercase (on Linux anyways) + // If the check doesn't work, set the spritesheet path to lowercase + // If the check doesn't work, replace backslashes with slashes + // At the minimum this should make all textures be able to be loaded on Linux + // If it doesn't work beyond that then that's on the user :^) + addSpritesheet.path = attribute->Value(); + if (!path_exists(addSpritesheet.path)) + addSpritesheet.path = string_to_lowercase(addSpritesheet.path); + if (!path_exists(addSpritesheet.path)) + addSpritesheet.path = string_backslash_replace(addSpritesheet.path); + if (isTextures) + texture_from_path_init(&addSpritesheet.texture, addSpritesheet.path); + break; + case ANM2_ATTRIBUTE_ID: + id = std::atoi(attribute->Value()); + break; + default: + break; + } + } + + self->spritesheets[id] = addSpritesheet; + } + } + + // Layers + if (const XMLElement* layers = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYERS])) { + for (const XMLElement* layer = layers->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER]); layer; + layer = layer->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER])) { + Anm2Layer addLayer; + + for (const XMLAttribute* attribute = layer->FirstAttribute(); attribute; attribute = attribute->Next()) { + switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { + case ANM2_ATTRIBUTE_NAME: + addLayer.name = std::string(attribute->Value()); + break; // Name + case ANM2_ATTRIBUTE_ID: + id = std::atoi(attribute->Value()); + break; // ID + case ANM2_ATTRIBUTE_SPRITESHEET_ID: + addLayer.spritesheetID = std::atoi(attribute->Value()); + break; // ID + default: + break; + } + } + + self->layers[id] = addLayer; + } + } + + // Nulls + if (const XMLElement* nulls = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULLS])) { + for (const XMLElement* null = nulls->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL]); null; + null = null->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL])) { + Anm2Null addNull; + + for (const XMLAttribute* attribute = null->FirstAttribute(); attribute; attribute = attribute->Next()) { + switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { + case ANM2_ATTRIBUTE_NAME: + addNull.name = std::string(attribute->Value()); + break; // Name + case ANM2_ATTRIBUTE_ID: + id = std::atoi(attribute->Value()); + break; // IDs + default: + break; + } + } + + self->nulls[id] = addNull; + } + } + + // Events + if (const XMLElement* events = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENTS])) { + // Event + for (const XMLElement* event = events->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT]); event; + event = event->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT])) { + Anm2Event addEvent; + + for (const XMLAttribute* attribute = event->FirstAttribute(); attribute; attribute = attribute->Next()) { + switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { + case ANM2_ATTRIBUTE_NAME: + addEvent.name = std::string(attribute->Value()); + break; // Name + case ANM2_ATTRIBUTE_ID: + id = std::atoi(attribute->Value()); + break; // ID + default: + break; + } + } + + self->events[id] = addEvent; + } + } + } + + // Animations + if (const XMLElement* animations = root->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATIONS])) { + for (const XMLAttribute* attribute = animations->FirstAttribute(); attribute; attribute = attribute->Next()) { + switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { + case ANM2_ATTRIBUTE_DEFAULT_ANIMATION: + defaultAnimation = std::string(attribute->Value()); + break; // DefaultAnimation + default: + break; + } + } + + // Animation + for (const XMLElement* animation = animations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION]); animation; + animation = animation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION])) + _anm2_animation_deserialize(&self->animations[map_next_id_get(self->animations)], animation); + } + + for (auto& [id, animation] : self->animations) + if (animation.name == defaultAnimation) + self->defaultAnimationID = id; + + if (isTextures) + anm2_spritesheet_texture_pixels_download(self); + + std::filesystem::current_path(workingPath); + + log_info(std::format(ANM2_READ_INFO, path)); + + return true; +} + +void anm2_animation_layer_animation_add(Anm2Animation* animation, int id) { + animation->layerAnimations[id] = Anm2Item{}; + animation->layerOrder.push_back(id); +} + +void anm2_animation_layer_animation_remove(Anm2Animation* animation, int id) { + animation->layerAnimations.erase(id); + vector_value_erase(animation->layerOrder, id); +} + +void anm2_animation_null_animation_add(Anm2Animation* animation, int id) { animation->nullAnimations[id] = Anm2Item{}; } + +void anm2_animation_null_animation_remove(Anm2Animation* animation, int id) { animation->nullAnimations.erase(id); } + +int anm2_layer_add(Anm2* self) { + int id = map_next_id_get(self->layers); + self->layers[id] = Anm2Layer{}; + return id; +} + +void anm2_layer_remove(Anm2* self, int id) { + self->layers.erase(id); + + for (auto& [_, animation] : self->animations) + anm2_animation_layer_animation_remove(&animation, id); +} + +int anm2_null_add(Anm2* self) { + int id = map_next_id_get(self->nulls); + self->nulls[id] = Anm2Null{}; + return id; +} + +void anm2_null_remove(Anm2* self, int id) { + if (!self->nulls.contains(id)) + return; + + self->nulls.erase(id); + + for (auto& [_, animation] : self->animations) + anm2_animation_null_animation_remove(&animation, id); +} + +int anm2_animation_add(Anm2* self, Anm2Animation* animation, int id) { + int addID = map_next_id_get(self->animations); + + Anm2Animation localAnimation; + Anm2Animation* addAnimation = animation ? animation : &localAnimation; + + if (!animation) + addAnimation->rootAnimation.frames.push_back(Anm2Frame{}); + + if (id != ID_NONE) { + map_insert_shift(self->animations, id, *addAnimation); + return id + 1; + } else + self->animations[addID] = *addAnimation; + + return addID; +} + +void anm2_animation_remove(Anm2* self, int id) { self->animations.erase(id); } + +void anm2_new(Anm2* self) { + *self = Anm2{}; + _anm2_created_on_set(self); +} + +Anm2Animation* anm2_animation_from_reference(Anm2* self, Anm2Reference reference) { return map_find(self->animations, reference.animationID); } + +Anm2Item* anm2_item_from_reference(Anm2* self, Anm2Reference reference) { + if (reference.itemType == ANM2_NONE) + return nullptr; + + Anm2Animation* animation = anm2_animation_from_reference(self, reference); + + if (!animation) + return nullptr; + + switch (reference.itemType) { + case ANM2_ROOT: + return &animation->rootAnimation; + case ANM2_LAYER: + return map_find(animation->layerAnimations, reference.itemID); + case ANM2_NULL: + return map_find(animation->nullAnimations, reference.itemID); + case ANM2_TRIGGER: + return &animation->triggers; + default: + return nullptr; + } +} + +int anm2_frame_index_from_time(Anm2* self, Anm2Reference reference, float time) { + Anm2Animation* animation = anm2_animation_from_reference(self, reference); + if (!animation) + return INDEX_NONE; + if (time < 0 || time > animation->frameNum) + return INDEX_NONE; + + Anm2Item* item = anm2_item_from_reference(self, reference); + + if (!item) + return INDEX_NONE; + + if (reference.itemType == ANM2_TRIGGER) + for (auto [i, frame] : std::views::enumerate(item->frames)) + if (frame.atFrame == (int)time) + return i; + + int delayCurrent = 0; + int delayNext = 0; + + for (auto [i, frame] : std::views::enumerate(item->frames)) { + delayNext += frame.delay; + + if (time >= delayCurrent && time < delayNext) + return i; + + delayCurrent += frame.delay; + } + + return INDEX_NONE; +} + +float anm2_time_from_reference(Anm2* self, Anm2Reference reference) { + Anm2Animation* animation = anm2_animation_from_reference(self, reference); + if (!animation) + return INDEX_NONE; + + Anm2Item* item = anm2_item_from_reference(self, reference); + if (!item) + return INDEX_NONE; + + float time = 0.0f; + + if (reference.frameIndex <= 0) + return 0.0f; + + if (reference.frameIndex >= (int)item->frames.size()) { + for (auto& frame : item->frames) + time += (float)frame.delay; + return time; + } + + if (reference.itemType == ANM2_TRIGGER) + return (float)item->frames[reference.frameIndex].atFrame; + + for (int i = 0; i < reference.frameIndex; i++) + time += (float)item->frames[i].delay; + + return time; +} + +Anm2Frame* anm2_frame_from_reference(Anm2* self, Anm2Reference reference) { + Anm2Item* item = anm2_item_from_reference(self, reference); + + if (!item) + return nullptr; + + if (reference.frameIndex <= INDEX_NONE || reference.frameIndex >= (int)item->frames.size()) + return nullptr; + + return &item->frames[reference.frameIndex]; +} + +void anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, float time) { + Anm2Animation* animation = anm2_animation_from_reference(self, reference); + if (!animation) + return; + + time = std::clamp(ROUND_NEAREST_MULTIPLE(time, 1.0f), 0.0f, animation->frameNum - 1.0f); + + Anm2Item* item = anm2_item_from_reference(self, reference); + + if (!item) + return; + + Anm2Frame* frameNext = nullptr; + int delayCurrent = 0; + int delayNext = 0; + + for (auto [i, iFrame] : std::views::enumerate(item->frames)) { + if (reference.itemType == ANM2_TRIGGER) { + if ((int)time == iFrame.atFrame) { + *frame = iFrame; + break; + } + } else { + *frame = iFrame; + + delayNext += frame->delay; + + if (time >= delayCurrent && time < delayNext) { + if (i + 1 < (int)item->frames.size()) + frameNext = &item->frames[i + 1]; + else + frameNext = nullptr; + break; + } + + delayCurrent += frame->delay; + } + } + + if (reference.itemType == ANM2_TRIGGER) + return; + + if (frame->isInterpolated && frameNext && frame->delay > 1) { + float interpolation = (time - delayCurrent) / (delayNext - delayCurrent); + + frame->rotation = glm::mix(frame->rotation, frameNext->rotation, interpolation); + frame->position = glm::mix(frame->position, frameNext->position, interpolation); + frame->scale = glm::mix(frame->scale, frameNext->scale, interpolation); + frame->offsetRGB = glm::mix(frame->offsetRGB, frameNext->offsetRGB, interpolation); + frame->tintRGBA = glm::mix(frame->tintRGBA, frameNext->tintRGBA, interpolation); + } +} + +int anm2_animation_length_get(Anm2Animation* self) { + int length = 0; + + auto accumulate_max_delay = [&](const std::vector& frames) { + int delaySum = 0; + for (const auto& frame : frames) { + delaySum += frame.delay; + length = std::max(length, delaySum); + } + }; + + accumulate_max_delay(self->rootAnimation.frames); + + for (const auto& [_, item] : self->layerAnimations) + accumulate_max_delay(item.frames); + + for (const auto& [_, item] : self->nullAnimations) + accumulate_max_delay(item.frames); + + for (const auto& frame : self->triggers.frames) + length = std::max(length, frame.atFrame + 1); + + return length; +} + +void anm2_animation_length_set(Anm2Animation* self) { self->frameNum = anm2_animation_length_get(self); } + +Anm2Frame* anm2_frame_add(Anm2* self, Anm2Frame* frame, Anm2Reference reference) { + Anm2Animation* animation = anm2_animation_from_reference(self, reference); + Anm2Item* item = anm2_item_from_reference(self, reference); + if (!animation || !item) + return nullptr; + + Anm2Frame frameAdd = frame ? *frame : Anm2Frame{}; + + if (reference.itemType == ANM2_TRIGGER) { + int atFrame = frame ? frame->atFrame : 0; + + for (auto& frameCheck : item->frames) { + if (frameCheck.atFrame == atFrame) { + atFrame++; + break; + } + } + + frameAdd.atFrame = atFrame; + + return &item->frames.emplace_back(frameAdd); + } else { + int index = reference.frameIndex; + + if (index < 0 || index >= (int)item->frames.size()) { + item->frames.push_back(frameAdd); + return &item->frames.back(); + } else { + item->frames.insert(item->frames.begin() + index, frameAdd); + return &item->frames[(size_t)(index)]; + } + } +} + +void anm2_frame_remove(Anm2* self, Anm2Reference reference) { + Anm2Item* item = anm2_item_from_reference(self, reference); + if (!item) + return; + item->frames.erase(item->frames.begin() + reference.frameIndex); +} + +void anm2_item_frame_set(Anm2* self, Anm2Reference reference, const Anm2FrameChange& change, Anm2ChangeType changeType, int start, int count) { + Anm2Item* item = anm2_item_from_reference(self, reference); + if (!item) + return; + + int size = (int)item->frames.size(); + if (size == 0 || start >= size) + return; + if (start < 0 || count <= 0) + return; + + int end = std::min(start + count, size); + + for (int i = start; i < end; i++) { + Anm2Frame& dest = item->frames[i]; + +#define X(name, ctype, ...) \ + if (change.name) { \ + if constexpr (std::is_same_v) { \ + dest.name = *change.name; \ + } else { \ + switch (changeType) { \ + case ANM2_CHANGE_SET: \ + dest.name = *change.name; \ + break; \ + case ANM2_CHANGE_ADD: \ + dest.name += *change.name; \ + break; \ + case ANM2_CHANGE_SUBTRACT: \ + dest.name -= *change.name; \ + break; \ + } \ + } \ + } + ANM2_FRAME_MEMBERS +#undef X + } +} + +void anm2_animation_merge(Anm2* self, int animationID, const std::vector& mergeIDs, Anm2MergeType type) { + Anm2Animation newAnimation = self->animations[animationID]; + + auto merge_item = [&](Anm2Item& destinationItem, const Anm2Item& sourceItem) { + switch (type) { + case ANM2_MERGE_APPEND: + destinationItem.frames.insert(destinationItem.frames.end(), sourceItem.frames.begin(), sourceItem.frames.end()); + break; + case ANM2_MERGE_PREPEND: + destinationItem.frames.insert(destinationItem.frames.begin(), sourceItem.frames.begin(), sourceItem.frames.end()); + break; + case ANM2_MERGE_REPLACE: + if (destinationItem.frames.size() < sourceItem.frames.size()) + destinationItem.frames.resize(sourceItem.frames.size()); + for (int i = 0; i < (int)sourceItem.frames.size(); i++) + destinationItem.frames[i] = sourceItem.frames[i]; + break; + case ANM2_MERGE_IGNORE: + break; + } + }; + + for (auto mergeID : mergeIDs) { + if (animationID == mergeID) + continue; + + const Anm2Animation& mergeAnimation = self->animations[mergeID]; + + merge_item(newAnimation.rootAnimation, mergeAnimation.rootAnimation); + + for (const auto& [id, layerAnimation] : mergeAnimation.layerAnimations) + merge_item(newAnimation.layerAnimations[id], layerAnimation); + + for (const auto& [id, nullAnimation] : mergeAnimation.nullAnimations) + merge_item(newAnimation.nullAnimations[id], nullAnimation); + + merge_item(newAnimation.triggers, mergeAnimation.triggers); + } + + self->animations[animationID] = newAnimation; + + anm2_animation_length_set(&self->animations[animationID]); +} + +void anm2_frame_bake(Anm2* self, Anm2Reference reference, int interval, bool isRoundScale, bool isRoundRotation) { + Anm2Item* item = anm2_item_from_reference(self, reference); + if (!item) + return; + + Anm2Frame* frame = anm2_frame_from_reference(self, reference); + if (!frame) + return; + + Anm2Reference referenceNext = {reference.animationID, reference.itemType, reference.itemID, reference.frameIndex + 1}; + Anm2Frame* frameNext = anm2_frame_from_reference(self, referenceNext); + if (!frameNext) + frameNext = frame; + + const Anm2Frame baseFrame = *frame; + const Anm2Frame baseFrameNext = *frameNext; + + int delay = 0; + int insertIndex = reference.frameIndex; + + while (delay < baseFrame.delay) { + float interpolation = (float)delay / baseFrame.delay; + + Anm2Frame baked = *frame; + baked.delay = std::min(interval, baseFrame.delay - delay); + baked.isInterpolated = (insertIndex == reference.frameIndex) ? baseFrame.isInterpolated : false; + + baked.rotation = glm::mix(baseFrame.rotation, baseFrameNext.rotation, interpolation); + baked.position = glm::mix(baseFrame.position, baseFrameNext.position, interpolation); + baked.scale = glm::mix(baseFrame.scale, baseFrameNext.scale, interpolation); + baked.offsetRGB = glm::mix(baseFrame.offsetRGB, baseFrameNext.offsetRGB, interpolation); + baked.tintRGBA = glm::mix(baseFrame.tintRGBA, baseFrameNext.tintRGBA, interpolation); + + if (isRoundScale) + baked.scale = vec2((int)baked.scale.x, (int)baked.scale.y); + if (isRoundRotation) + baked.rotation = (int)baked.rotation; + + if (insertIndex == reference.frameIndex) + item->frames[insertIndex] = baked; + else + item->frames.insert(item->frames.begin() + insertIndex, baked); + insertIndex++; + + delay += baked.delay; + } +} + +void anm2_scale(Anm2* self, float scale) { + auto frame_scale = [&](Anm2Frame& frame) { + frame.position = vec2((int)(frame.position.x * scale), (int)(frame.position.y * scale)); + frame.size = vec2((int)(frame.size.x * scale), (int)(frame.size.y * scale)); + frame.crop = vec2((int)(frame.crop.x * scale), (int)(frame.crop.y * scale)); + frame.pivot = vec2((int)(frame.pivot.x * scale), (int)(frame.pivot.y * scale)); + }; + + for (auto& [_, animation] : self->animations) { + for (auto& frame : animation.rootAnimation.frames) + frame_scale(frame); + + for (auto& [_, layerAnimation] : animation.layerAnimations) + for (auto& frame : layerAnimation.frames) + frame_scale(frame); + + for (auto& [_, nullAnimation] : animation.nullAnimations) + for (auto& frame : nullAnimation.frames) + frame_scale(frame); + } +} + +void anm2_generate_from_grid(Anm2* self, Anm2Reference reference, vec2 startPosition, vec2 size, vec2 pivot, int columns, int count, int delay) { + Anm2Item* item = anm2_item_from_reference(self, reference); + if (!item) + return; + + Anm2Reference frameReference = reference; + + for (int i = 0; i < count; i++) { + const int row = i / columns; + const int column = i % columns; + + Anm2Frame frame{}; + + frame.delay = delay; + frame.pivot = pivot; + frame.size = size; + frame.crop = startPosition + vec2(size.x * column, size.y * row); + + anm2_frame_add(self, &frame, frameReference); + frameReference.frameIndex++; + } +} + +void anm2_free(Anm2* self) { + for (auto& [id, spritesheet] : self->spritesheets) + texture_free(&spritesheet.texture); +} + +void anm2_spritesheet_texture_pixels_upload(Anm2* self) { + for (auto& [_, spritesheet] : self->spritesheets) { + Texture& texture = spritesheet.texture; + + if (texture.id != GL_ID_NONE && !texture.isInvalid) { + assert(!spritesheet.pixels.empty()); + glBindTexture(GL_TEXTURE_2D, texture.id); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture.size.x, texture.size.y, GL_RGBA, GL_UNSIGNED_BYTE, spritesheet.pixels.data()); + } + } +} + +void anm2_spritesheet_texture_pixels_download(Anm2* self) { + for (auto& [_, spritesheet] : self->spritesheets) { + Texture& texture = spritesheet.texture; + + if (texture.id != GL_ID_NONE && !texture.isInvalid) { + size_t bufferSize = (size_t)texture.size.x * (size_t)texture.size.y * TEXTURE_CHANNELS; + spritesheet.pixels.resize(bufferSize); + glBindTexture(GL_TEXTURE_2D, texture.id); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, spritesheet.pixels.data()); + } + } +} + +vec4 anm2_animation_rect_get(Anm2* self, Anm2Reference reference, bool isRootTransform) { + float minX = std::numeric_limits::infinity(); + float minY = std::numeric_limits::infinity(); + float maxX = -std::numeric_limits::infinity(); + float maxY = -std::numeric_limits::infinity(); + + bool any = false; + + Anm2Frame frame; + Anm2Frame root; + + Anm2Animation* animation = anm2_animation_from_reference(self, reference); + if (!animation) + return vec4(-1.0f); + + for (float t = 0.0f; t <= animation->frameNum; t += 1.0f) { + for (const auto& [id, _] : animation->layerAnimations) { + anm2_frame_from_time(self, &frame, {reference.animationID, ANM2_LAYER, id}, t); + if (!frame.isVisible) + continue; + if (frame.size.x <= 0 || frame.size.y <= 0) + continue; + + mat4 rootModel(1.0f); + if (isRootTransform) { + anm2_frame_from_time(self, &root, {reference.animationID, ANM2_ROOT}, t); + rootModel = quad_model_parent_get(root.position, root.pivot, PERCENT_TO_UNIT(root.scale), root.rotation); + } + + mat4 model = quad_model_get(frame.size, frame.position, frame.pivot, PERCENT_TO_UNIT(frame.scale), frame.rotation); + mat4 fullModel = rootModel * model; + + vec2 corners[4] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; + + for (auto& corner : corners) { + vec4 world = fullModel * vec4(corner, 0.0f, 1.0f); + minX = std::min(minX, world.x); + minY = std::min(minY, world.y); + maxX = std::max(maxX, world.x); + maxY = std::max(maxY, world.y); + any = true; + } + } + } + + if (!any) + return vec4(-1.0f); + return {minX, minY, maxX - minX, maxY - minY}; +} + +void anm2_animation_serialize_to_string(Anm2Animation* animation, std::string* string) { _anm2_animation_serialize(animation, nullptr, nullptr, string); } + +void anm2_frame_serialize_to_string(Anm2Frame* frame, Anm2Type type, std::string* string) { _anm2_frame_serialize(frame, type, nullptr, nullptr, string); } + +bool anm2_animation_deserialize_from_xml(Anm2Animation* animation, const std::string& xml) { + XMLDocument document; + + auto animation_deserialize_error = [&]() { + log_error(std::format(ANM2_ANIMATION_PARSE_ERROR, xml, document.ErrorStr())); + return false; + }; + + if (document.Parse(xml.c_str()) != XML_SUCCESS) + return animation_deserialize_error(); + + const XMLElement* element = document.RootElement(); + if (!element) + return animation_deserialize_error(); + if (std::string(element->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION])) + return animation_deserialize_error(); + + _anm2_animation_deserialize(animation, element); + return true; +} + +bool anm2_frame_deserialize_from_xml(Anm2Frame* frame, const std::string& xml) { + XMLDocument document; + + auto frame_deserialize_error = [&]() { + log_error(std::format(ANM2_FRAME_PARSE_ERROR, xml, document.ErrorStr())); + return false; + }; + + if (document.Parse(xml.c_str()) != XML_SUCCESS) + return frame_deserialize_error(); + + const XMLElement* element = document.RootElement(); + if (!element) + return frame_deserialize_error(); + + if (std::string(element->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]) && + std::string(element->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER])) + return frame_deserialize_error(); + + _anm2_frame_deserialize(frame, element); + + return true; } /* void anm2_merge(Anm2* self, const std::string& path, Anm2MergeType type) { - Anm2 anm2; + Anm2 anm2; - if (anm2_deserialize(&anm2, path, false)) - { - std::unordered_map spritesheetMap; - for (auto& [id, spritesheet] : anm2.spritesheets) - { - bool isExists = false; - - for (auto& [selfID, selfSpritesheet] : self->spritesheets) - { - if (spritesheet.path == selfSpritesheet.path) isExists = true; - spritesheetMap[id] = selfID; - } + if (anm2_deserialize(&anm2, path, false)) + { + std::unordered_map spritesheetMap; + for (auto& [id, spritesheet] : anm2.spritesheets) + { + bool isExists = false; - if (isExists) continue; + for (auto& [selfID, selfSpritesheet] : self->spritesheets) + { + if (spritesheet.path == selfSpritesheet.path) isExists = true; + spritesheetMap[id] = selfID; + } - s32 nextID = map_next_id_get(self->spritesheets); - self->spritesheet[nextID] = spritesheet; - spritesheetMap[id] = nextID; - } + if (isExists) continue; - std::unordered_map layerMap; - for (auto& [id, layer] : anm2.layers) - { - bool isExists = false; + int nextID = map_next_id_get(self->spritesheets); + self->spritesheet[nextID] = spritesheet; + spritesheetMap[id] = nextID; + } - layer.spritesheetID = spritesheetMap[layer.spritesheetID]; + std::unordered_map layerMap; + for (auto& [id, layer] : anm2.layers) + { + bool isExists = false; - for (auto& [selfID, selfLayer] : self->layers) - { - if (layer.name == selfLayer.name) isExists = true; - layerMap[id] = selfID; - } + layer.spritesheetID = spritesheetMap[layer.spritesheetID]; - if (isExists) continue; + for (auto& [selfID, selfLayer] : self->layers) + { + if (layer.name == selfLayer.name) isExists = true; + layerMap[id] = selfID; + } - s32 nextID = map_next_id_get(self->layers); - self->layer[nextID] = layer; - layerMap[id] = nextID; - } + if (isExists) continue; - std::unordered_map nullMap; - for (auto& [id, null] : anm2.nulls) - { - bool isExists = false; - - for (auto& [selfID, selfNull] : self->nulls) - { - if (null.name == selfNull.name) isExists = true; - nullMap[id] = selfID; - } + int nextID = map_next_id_get(self->layers); + self->layer[nextID] = layer; + layerMap[id] = nextID; + } - if (isExists) continue; + std::unordered_map nullMap; + for (auto& [id, null] : anm2.nulls) + { + bool isExists = false; - s32 nextID = map_next_id_get(self->nulls); - self->null[nextID] = null; - nullMap[id] = nextID; - } + for (auto& [selfID, selfNull] : self->nulls) + { + if (null.name == selfNull.name) isExists = true; + nullMap[id] = selfID; + } - std::unordered_map eventMap; - for (auto& [id, event] : anm2.events) - { - bool isExists = false; - - for (auto& [selfID, selfEvent] : self->events) - { - if (event.name == selfEvent.name) isExists = true; - eventMap[id] = selfID; - } + if (isExists) continue; - if (isExists) continue; + int nextID = map_next_id_get(self->nulls); + self->null[nextID] = null; + nullMap[id] = nextID; + } - s32 nextID = map_next_id_get(self->events); - self->event[nextID] = event; - eventMap[id] = nextID; - } + std::unordered_map eventMap; + for (auto& [id, event] : anm2.events) + { + bool isExists = false; - for (auto& [id, animation] : anm2.animations) - { - bool isExists = false; - - for (auto& [selfID, selfAnimation] : self->animations) - { - if (event.name == selfAnimation.name) isExists = true; - eventMap[id] = selfID; - } + for (auto& [selfID, selfEvent] : self->events) + { + if (event.name == selfEvent.name) isExists = true; + eventMap[id] = selfID; + } - if (isExists) continue; + if (isExists) continue; - for (auto& frame : animation.rootAnimation.frames) - { + int nextID = map_next_id_get(self->events); + self->event[nextID] = event; + eventMap[id] = nextID; + } - - } + for (auto& [id, animation] : anm2.animations) + { + bool isExists = false; - for (auto& [layerID, layerAnimation] : animation.layerAnimations) - { - s32 newLayerID = layerMap[layerID]; + for (auto& [selfID, selfAnimation] : self->animations) + { + if (event.name == selfAnimation.name) isExists = true; + eventMap[id] = selfID; + } + + if (isExists) continue; + + for (auto& frame : animation.rootAnimation.frames) + { - } - } - } + } + + for (auto& [layerID, layerAnimation] : animation.layerAnimations) + { + int newLayerID = layerMap[layerID]; + + + } + } + } } */ \ No newline at end of file diff --git a/src/anm2.h b/src/anm2.h index 02c8614..b0affcb 100644 --- a/src/anm2.h +++ b/src/anm2.h @@ -2,8 +2,8 @@ #include "resources.h" -#define ANM2_SCALE_CONVERT(x) ((f32)x / 100.0f) -#define ANM2_TINT_CONVERT(x) ((f32)x / 255.0f) +#define ANM2_SCALE_CONVERT(x) ((float)x / 100.0f) +#define ANM2_TINT_CONVERT(x) ((float)x / 255.0f) #define ANM2_FPS_MIN 0 #define ANM2_FPS_DEFAULT 30 @@ -26,283 +26,240 @@ #define ANM2_EXTENSION "anm2" #define ANM2_SPRITESHEET_EXTENSION "png" -#define ANM2_ELEMENT_LIST \ - X(ANIMATED_ACTOR, "AnimatedActor") \ - X(INFO, "Info") \ - X(CONTENT, "Content") \ - X(SPRITESHEETS, "Spritesheets") \ - X(SPRITESHEET, "Spritesheet") \ - X(LAYERS, "Layers") \ - X(LAYER, "Layer") \ - X(NULLS, "Nulls") \ - X(NULL, "Null") \ - X(EVENTS, "Events") \ - X(EVENT, "Event") \ - X(ANIMATIONS, "Animations") \ - X(ANIMATION, "Animation") \ - X(ROOT_ANIMATION, "RootAnimation") \ - X(FRAME, "Frame") \ - X(LAYER_ANIMATIONS, "LayerAnimations") \ - X(LAYER_ANIMATION, "LayerAnimation") \ - X(NULL_ANIMATIONS, "NullAnimations") \ - X(NULL_ANIMATION, "NullAnimation") \ - X(TRIGGERS, "Triggers") \ - X(TRIGGER, "Trigger") +#define ANM2_ELEMENT_LIST \ + X(ANIMATED_ACTOR, "AnimatedActor") \ + X(INFO, "Info") \ + X(CONTENT, "Content") \ + X(SPRITESHEETS, "Spritesheets") \ + X(SPRITESHEET, "Spritesheet") \ + X(LAYERS, "Layers") \ + X(LAYER, "Layer") \ + X(NULLS, "Nulls") \ + X(NULL, "Null") \ + X(EVENTS, "Events") \ + X(EVENT, "Event") \ + X(ANIMATIONS, "Animations") \ + X(ANIMATION, "Animation") \ + X(ROOT_ANIMATION, "RootAnimation") \ + X(FRAME, "Frame") \ + X(LAYER_ANIMATIONS, "LayerAnimations") \ + X(LAYER_ANIMATION, "LayerAnimation") \ + X(NULL_ANIMATIONS, "NullAnimations") \ + X(NULL_ANIMATION, "NullAnimation") \ + X(TRIGGERS, "Triggers") \ + X(TRIGGER, "Trigger") -typedef enum -{ - #define X(name, str) ANM2_ELEMENT_##name, - ANM2_ELEMENT_LIST - #undef X - ANM2_ELEMENT_COUNT +typedef enum { +#define X(name, str) ANM2_ELEMENT_##name, + ANM2_ELEMENT_LIST +#undef X + ANM2_ELEMENT_COUNT } Anm2Element; -const inline char* ANM2_ELEMENT_STRINGS[] = -{ - #define X(name, str) str, +const inline char* ANM2_ELEMENT_STRINGS[] = { +#define X(name, str) str, ANM2_ELEMENT_LIST - #undef X +#undef X }; DEFINE_STRING_TO_ENUM_FUNCTION(ANM2_ELEMENT_STRING_TO_ENUM, Anm2Element, ANM2_ELEMENT_STRINGS, ANM2_ELEMENT_COUNT) -#define ANM2_ATTRIBUTE_LIST \ - X(CREATED_BY, "CreatedBy") \ - X(CREATED_ON, "CreatedOn") \ - X(VERSION, "Version") \ - X(FPS, "Fps") \ - X(ID, "Id") \ - X(PATH, "Path") \ - X(NAME, "Name") \ - X(SPRITESHEET_ID, "SpritesheetId") \ - X(SHOW_RECT, "ShowRect") \ - X(DEFAULT_ANIMATION, "DefaultAnimation") \ - X(FRAME_NUM, "FrameNum") \ - X(LOOP, "Loop") \ - X(X_POSITION, "XPosition") \ - X(Y_POSITION, "YPosition") \ - X(X_PIVOT, "XPivot") \ - X(Y_PIVOT, "YPivot") \ - X(X_CROP, "XCrop") \ - X(Y_CROP, "YCrop") \ - X(WIDTH, "Width") \ - X(HEIGHT, "Height") \ - X(X_SCALE, "XScale") \ - X(Y_SCALE, "YScale") \ - X(DELAY, "Delay") \ - X(VISIBLE, "Visible") \ - X(RED_TINT, "RedTint") \ - X(GREEN_TINT, "GreenTint") \ - X(BLUE_TINT, "BlueTint") \ - X(ALPHA_TINT, "AlphaTint") \ - X(RED_OFFSET, "RedOffset") \ - X(GREEN_OFFSET, "GreenOffset") \ - X(BLUE_OFFSET, "BlueOffset") \ - X(ROTATION, "Rotation") \ - X(INTERPOLATED, "Interpolated") \ - X(LAYER_ID, "LayerId") \ - X(NULL_ID, "NullId") \ - X(EVENT_ID, "EventId") \ - X(AT_FRAME, "AtFrame") +#define ANM2_ATTRIBUTE_LIST \ + X(CREATED_BY, "CreatedBy") \ + X(CREATED_ON, "CreatedOn") \ + X(VERSION, "Version") \ + X(FPS, "Fps") \ + X(ID, "Id") \ + X(PATH, "Path") \ + X(NAME, "Name") \ + X(SPRITESHEET_ID, "SpritesheetId") \ + X(SHOW_RECT, "ShowRect") \ + X(DEFAULT_ANIMATION, "DefaultAnimation") \ + X(FRAME_NUM, "FrameNum") \ + X(LOOP, "Loop") \ + X(X_POSITION, "XPosition") \ + X(Y_POSITION, "YPosition") \ + X(X_PIVOT, "XPivot") \ + X(Y_PIVOT, "YPivot") \ + X(X_CROP, "XCrop") \ + X(Y_CROP, "YCrop") \ + X(WIDTH, "Width") \ + X(HEIGHT, "Height") \ + X(X_SCALE, "XScale") \ + X(Y_SCALE, "YScale") \ + X(DELAY, "Delay") \ + X(VISIBLE, "Visible") \ + X(RED_TINT, "RedTint") \ + X(GREEN_TINT, "GreenTint") \ + X(BLUE_TINT, "BlueTint") \ + X(ALPHA_TINT, "AlphaTint") \ + X(RED_OFFSET, "RedOffset") \ + X(GREEN_OFFSET, "GreenOffset") \ + X(BLUE_OFFSET, "BlueOffset") \ + X(ROTATION, "Rotation") \ + X(INTERPOLATED, "Interpolated") \ + X(LAYER_ID, "LayerId") \ + X(NULL_ID, "NullId") \ + X(EVENT_ID, "EventId") \ + X(AT_FRAME, "AtFrame") -typedef enum -{ - #define X(name, str) ANM2_ATTRIBUTE_##name, - ANM2_ATTRIBUTE_LIST - #undef X - ANM2_ATTRIBUTE_COUNT +typedef enum { +#define X(name, str) ANM2_ATTRIBUTE_##name, + ANM2_ATTRIBUTE_LIST +#undef X + ANM2_ATTRIBUTE_COUNT } Anm2Attribute; -static const char* ANM2_ATTRIBUTE_STRINGS[] = -{ - #define X(name, str) str, +static const char* ANM2_ATTRIBUTE_STRINGS[] = { +#define X(name, str) str, ANM2_ATTRIBUTE_LIST - #undef X +#undef X }; DEFINE_STRING_TO_ENUM_FUNCTION(ANM2_ATTRIBUTE_STRING_TO_ENUM, Anm2Attribute, ANM2_ATTRIBUTE_STRINGS, ANM2_ATTRIBUTE_COUNT) -enum Anm2Type -{ - ANM2_NONE, - ANM2_ROOT, - ANM2_LAYER, - ANM2_NULL, - ANM2_TRIGGERS, - ANM2_COUNT +enum Anm2Type { ANM2_NONE, ANM2_ROOT, ANM2_LAYER, ANM2_NULL, ANM2_TRIGGER, ANM2_COUNT }; + +struct Anm2Spritesheet { + std::string path{}; + Texture texture; + std::vector pixels; + + auto operator<=>(const Anm2Spritesheet&) const = default; }; -struct Anm2Spritesheet -{ - std::string path{}; - Texture texture; - std::vector pixels; +struct Anm2Layer { + std::string name = "New Layer"; + int spritesheetID{}; - auto operator<=>(const Anm2Spritesheet&) const = default; + auto operator<=>(const Anm2Layer&) const = default; }; -struct Anm2Layer -{ - std::string name = "New Layer"; - s32 spritesheetID{}; +struct Anm2Null { + std::string name = "New Null"; + bool isShowRect = false; - auto operator<=>(const Anm2Layer&) const = default; + auto operator<=>(const Anm2Null&) const = default; }; -struct Anm2Null -{ - std::string name = "New Null"; - bool isShowRect = false; +struct Anm2Event { + std::string name = "New Event"; - auto operator<=>(const Anm2Null&) const = default; + auto operator<=>(const Anm2Event&) const = default; }; -struct Anm2Event -{ - std::string name = "New Event"; +#define ANM2_FRAME_MEMBERS \ + X(isVisible, bool, true) \ + X(isInterpolated, bool, false) \ + X(rotation, float, 0.0f) \ + X(delay, int, ANM2_FRAME_DELAY_MIN) \ + X(atFrame, int, INDEX_NONE) \ + X(eventID, int, ID_NONE) \ + X(crop, vec2, {}) \ + X(pivot, vec2, {}) \ + X(position, vec2, {}) \ + X(size, vec2, {}) \ + X(scale, vec2, {100, 100}) \ + X(offsetRGB, vec3, COLOR_OFFSET_NONE) \ + X(tintRGBA, vec4, COLOR_OPAQUE) - auto operator<=>(const Anm2Event&) const = default; +struct Anm2Frame { +#define X(name, type, ...) type name = __VA_ARGS__; + ANM2_FRAME_MEMBERS +#undef X + auto operator<=>(const Anm2Frame&) const = default; }; -struct Anm2Frame -{ - bool isVisible = true; - bool isInterpolated = false; - f32 rotation{}; - s32 delay = ANM2_FRAME_DELAY_MIN; - s32 atFrame = INDEX_NONE; - s32 eventID = ID_NONE; - vec2 crop{}; - vec2 pivot{}; - vec2 position{}; - vec2 size{}; - vec2 scale = {100, 100}; - vec3 offsetRGB = COLOR_OFFSET_NONE; - vec4 tintRGBA = COLOR_OPAQUE; - - auto operator<=>(const Anm2Frame&) const = default; +struct Anm2FrameChange { +#define X(name, type, ...) std::optional name{}; + ANM2_FRAME_MEMBERS +#undef X }; -struct Anm2Item -{ - bool isVisible = true; - std::vector frames; +struct Anm2Item { + bool isVisible = true; + std::vector frames; - auto operator<=>(const Anm2Item&) const = default; + auto operator<=>(const Anm2Item&) const = default; }; -struct Anm2Animation -{ - s32 frameNum = ANM2_FRAME_NUM_MIN; - std::string name = "New Animation"; - bool isLoop = true; - Anm2Item rootAnimation; - std::unordered_map layerAnimations; - std::vector layerOrder; - std::map nullAnimations; - Anm2Item triggers; - - auto operator<=>(const Anm2Animation&) const = default; +struct Anm2Animation { + int frameNum = ANM2_FRAME_NUM_MIN; + std::string name = "New Animation"; + bool isLoop = true; + Anm2Item rootAnimation; + std::unordered_map layerAnimations; + std::vector layerOrder; + std::map nullAnimations; + Anm2Item triggers; + + auto operator<=>(const Anm2Animation&) const = default; }; -struct Anm2 -{ - std::string path{}; - std::string createdBy = "robot"; - std::string createdOn{}; - std::map spritesheets; - std::map layers; - std::map nulls; - std::map events; - std::map animations; - s32 defaultAnimationID = ID_NONE; - s32 fps = ANM2_FPS_DEFAULT; - s32 version{}; +struct Anm2 { + std::string path{}; + std::string createdBy = "robot"; + std::string createdOn{}; + std::map spritesheets; + std::map layers; + std::map nulls; + std::map events; + std::map animations; + int defaultAnimationID = ID_NONE; + int fps = ANM2_FPS_DEFAULT; + int version{}; - auto operator<=>(const Anm2&) const = default; + auto operator<=>(const Anm2&) const = default; }; -struct Anm2Reference -{ - s32 animationID = ID_NONE; - Anm2Type itemType = ANM2_NONE; - s32 itemID = ID_NONE; - s32 frameIndex = INDEX_NONE; - f32 time = VALUE_NONE; - auto operator<=>(const Anm2Reference&) const = default; +struct Anm2Reference { + int animationID = ID_NONE; + Anm2Type itemType = ANM2_NONE; + int itemID = ID_NONE; + int frameIndex = INDEX_NONE; + float time = VALUE_NONE; + auto operator<=>(const Anm2Reference&) const = default; }; -struct Anm2FrameChange -{ - std::optional isVisible; - std::optional isInterpolated; - std::optional rotation; - std::optional delay; - std::optional crop; - std::optional pivot; - std::optional position; - std::optional size; - std::optional scale; - std::optional offsetRGB; - std::optional tintRGBA; -}; +enum Anm2MergeType { ANM2_MERGE_APPEND, ANM2_MERGE_REPLACE, ANM2_MERGE_PREPEND, ANM2_MERGE_IGNORE }; -enum Anm2MergeType -{ - ANM2_MERGE_APPEND, - ANM2_MERGE_REPLACE, - ANM2_MERGE_PREPEND, - ANM2_MERGE_IGNORE -}; +enum Anm2ChangeType { ANM2_CHANGE_ADD, ANM2_CHANGE_SUBTRACT, ANM2_CHANGE_SET }; -enum Anm2ChangeType -{ - ANM2_CHANGE_ADD, - ANM2_CHANGE_SUBTRACT, - ANM2_CHANGE_SET -}; +enum OnionskinDrawOrder { ONIONSKIN_BELOW, ONIONSKIN_ABOVE }; -enum OnionskinDrawOrder -{ - ONIONSKIN_BELOW, - ONIONSKIN_ABOVE -}; - -Anm2Animation* anm2_animation_from_reference(Anm2* self, Anm2Reference* reference); -Anm2Frame* anm2_frame_add(Anm2* self, Anm2Frame* frame, Anm2Reference* reference); -Anm2Frame* anm2_frame_from_reference(Anm2* self, Anm2Reference* reference); -Anm2Item* anm2_item_from_reference(Anm2* self, Anm2Reference* reference); +Anm2Animation* anm2_animation_from_reference(Anm2* self, Anm2Reference reference); +Anm2Frame* anm2_frame_add(Anm2* self, Anm2Frame* frame, Anm2Reference reference); +Anm2Frame* anm2_frame_from_reference(Anm2* self, Anm2Reference reference); +Anm2Item* anm2_item_from_reference(Anm2* self, Anm2Reference reference); bool anm2_animation_deserialize_from_xml(Anm2Animation* animation, const std::string& xml); bool anm2_deserialize(Anm2* self, const std::string& path, bool isTextures = true); bool anm2_frame_deserialize_from_xml(Anm2Frame* frame, const std::string& xml); bool anm2_serialize(Anm2* self, const std::string& path); -s32 anm2_animation_add(Anm2* self, Anm2Animation* animation = nullptr, s32 id = ID_NONE); -s32 anm2_animation_length_get(Anm2Animation* self); -s32 anm2_frame_index_from_time(Anm2* self, Anm2Reference reference, f32 time); -s32 anm2_layer_add(Anm2* self); -s32 anm2_null_add(Anm2* self); -vec4 anm2_animation_rect_get(Anm2* anm2, Anm2Reference* reference, bool isRootTransform); -void anm2_animation_layer_animation_add(Anm2Animation* animation, s32 id); -void anm2_animation_layer_animation_remove(Anm2Animation* animation, s32 id); +int anm2_animation_add(Anm2* self, Anm2Animation* animation = nullptr, int id = ID_NONE); +int anm2_animation_length_get(Anm2Animation* self); +int anm2_frame_index_from_time(Anm2* self, Anm2Reference reference, float time); +int anm2_layer_add(Anm2* self); +int anm2_null_add(Anm2* self); +vec4 anm2_animation_rect_get(Anm2* anm2, Anm2Reference reference, bool isRootTransform); +void anm2_animation_layer_animation_add(Anm2Animation* animation, int id); +void anm2_animation_layer_animation_remove(Anm2Animation* animation, int id); void anm2_animation_length_set(Anm2Animation* self); -void anm2_animation_merge(Anm2* self, s32 animationID, const std::vector& mergeIDs, Anm2MergeType type); -void anm2_animation_null_animation_add(Anm2Animation* animation, s32 id); -void anm2_animation_null_animation_remove(Anm2Animation* animation, s32 id); -void anm2_animation_remove(Anm2* self, s32 id); +void anm2_animation_merge(Anm2* self, int animationID, const std::vector& mergeIDs, Anm2MergeType type); +void anm2_animation_null_animation_add(Anm2Animation* animation, int id); +void anm2_animation_null_animation_remove(Anm2Animation* animation, int id); +void anm2_animation_remove(Anm2* self, int id); void anm2_animation_serialize_to_string(Anm2Animation* animation, std::string* string); -void anm2_frame_bake(Anm2* self, Anm2Reference* reference, s32 interval, bool isRoundScale, bool isRoundRotation); -void anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, f32 time); -void anm2_frame_remove(Anm2* self, Anm2Reference* reference); +void anm2_frame_bake(Anm2* self, Anm2Reference reference, int interval, bool isRoundScale, bool isRoundRotation); +void anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, float time); +void anm2_frame_remove(Anm2* self, Anm2Reference reference); void anm2_frame_serialize_to_string(Anm2Frame* frame, Anm2Type type, std::string* string); void anm2_free(Anm2* self); -void anm2_generate_from_grid(Anm2* self, Anm2Reference* reference, vec2 startPosition, vec2 size, vec2 pivot, s32 columns, s32 count, s32 delay); -void anm2_item_frame_set(Anm2* self, Anm2Reference* reference, const Anm2FrameChange& change, Anm2ChangeType type, s32 start, s32 count); -void anm2_layer_remove(Anm2* self, s32 id); +void anm2_generate_from_grid(Anm2* self, Anm2Reference reference, vec2 startPosition, vec2 size, vec2 pivot, int columns, int count, int delay); +void anm2_item_frame_set(Anm2* self, Anm2Reference reference, const Anm2FrameChange& change, Anm2ChangeType changeType, int start, int count); +void anm2_layer_remove(Anm2* self, int id); void anm2_new(Anm2* self); -void anm2_null_remove(Anm2* self, s32 id); -void anm2_reference_clear(Anm2Reference* self); -void anm2_reference_frame_clear(Anm2Reference* self); -void anm2_reference_item_clear(Anm2Reference* self); -void anm2_scale(Anm2* self, f32 scale); +void anm2_null_remove(Anm2* self, int id); +void anm2_scale(Anm2* self, float scale); void anm2_spritesheet_texture_pixels_download(Anm2* self); -void anm2_spritesheet_texture_pixels_upload(Anm2* self); \ No newline at end of file +void anm2_spritesheet_texture_pixels_upload(Anm2* self); +float anm2_time_from_reference(Anm2* self, Anm2Reference reference); \ No newline at end of file diff --git a/src/canvas.cpp b/src/canvas.cpp index 806ec9a..5e55649 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1,244 +1,224 @@ #include "canvas.h" -static void _canvas_framebuffer_set(Canvas* self, const ivec2& size) -{ - self->size = size; - self->previousSize = size; - - glBindFramebuffer(GL_FRAMEBUFFER, self->fbo); +static void _canvas_framebuffer_set(Canvas* self, const ivec2& size) { + self->size = size; + self->previousSize = size; - glBindTexture(GL_TEXTURE_2D, self->framebuffer); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self->size.x, self->size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindFramebuffer(GL_FRAMEBUFFER, self->fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->framebuffer, 0); + glBindTexture(GL_TEXTURE_2D, self->framebuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self->size.x, self->size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glBindRenderbuffer(GL_RENDERBUFFER, self->rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, self->size.x, self->size.y); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, self->rbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->framebuffer, 0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindRenderbuffer(GL_RENDERBUFFER, self->rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, self->size.x, self->size.y); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, self->rbo); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); } -void canvas_init(Canvas* self, const ivec2& size) -{ - // Axis - glGenVertexArrays(1, &self->axisVAO); - glGenBuffers(1, &self->axisVBO); +void canvas_init(Canvas* self, const ivec2& size) { + // Axis + glGenVertexArrays(1, &self->axisVAO); + glGenBuffers(1, &self->axisVBO); - glBindVertexArray(self->axisVAO); + glBindVertexArray(self->axisVAO); - glBindBuffer(GL_ARRAY_BUFFER, self->axisVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_AXIS_VERTICES), CANVAS_AXIS_VERTICES, GL_STATIC_DRAW); - - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, sizeof(f32), (void*)0); - - // Grid - glGenVertexArrays(1, &self->gridVAO); - glGenBuffers(1, &self->gridVBO); - - glBindVertexArray(self->gridVAO); - glBindBuffer(GL_ARRAY_BUFFER, self->gridVBO); + glBindBuffer(GL_ARRAY_BUFFER, self->axisVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_AXIS_VERTICES), CANVAS_AXIS_VERTICES, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(f32), (void*)0); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, sizeof(float), (void*)0); - // Rect - glGenVertexArrays(1, &self->rectVAO); - glGenBuffers(1, &self->rectVBO); + // Grid + glGenVertexArrays(1, &self->gridVAO); + glGenBuffers(1, &self->gridVBO); - glBindVertexArray(self->rectVAO); + glBindVertexArray(self->gridVAO); + glBindBuffer(GL_ARRAY_BUFFER, self->gridVBO); - glBindBuffer(GL_ARRAY_BUFFER, self->rectVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_RECT_VERTICES), CANVAS_RECT_VERTICES, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(f32), (void*)0); + // Rect + glGenVertexArrays(1, &self->rectVAO); + glGenBuffers(1, &self->rectVBO); - // Grid - glGenVertexArrays(1, &self->gridVAO); - glBindVertexArray(self->gridVAO); + glBindVertexArray(self->rectVAO); - glGenBuffers(1, &self->gridVBO); - glBindBuffer(GL_ARRAY_BUFFER, self->gridVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_GRID_VERTICES), CANVAS_GRID_VERTICES, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, self->rectVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_RECT_VERTICES), CANVAS_RECT_VERTICES, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*)0); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); - glBindVertexArray(0); + // Grid + glGenVertexArrays(1, &self->gridVAO); + glBindVertexArray(self->gridVAO); - // Texture - glGenVertexArrays(1, &self->textureVAO); - glGenBuffers(1, &self->textureVBO); - glGenBuffers(1, &self->textureEBO); + glGenBuffers(1, &self->gridVBO); + glBindBuffer(GL_ARRAY_BUFFER, self->gridVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_GRID_VERTICES), CANVAS_GRID_VERTICES, GL_STATIC_DRAW); - glBindVertexArray(self->textureVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*)0); - glBindBuffer(GL_ARRAY_BUFFER, self->textureVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(f32) * 4 * 4, nullptr, GL_DYNAMIC_DRAW); + glBindVertexArray(0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->textureEBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GL_TEXTURE_INDICES), GL_TEXTURE_INDICES, GL_DYNAMIC_DRAW); + // Texture + glGenVertexArrays(1, &self->textureVAO); + glGenBuffers(1, &self->textureVBO); + glGenBuffers(1, &self->textureEBO); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(f32), (void*)0); + glBindVertexArray(self->textureVAO); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(f32), (void*)(2 * sizeof(f32))); - - glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, self->textureVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 4, nullptr, GL_DYNAMIC_DRAW); - // Framebuffer - glGenTextures(1, &self->framebuffer); - glGenFramebuffers(1, &self->fbo); - glGenRenderbuffers(1, &self->rbo); - _canvas_framebuffer_set(self, size); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->textureEBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GL_TEXTURE_INDICES), GL_TEXTURE_INDICES, GL_DYNAMIC_DRAW); - self->isInit = true; + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); + + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); + + glBindVertexArray(0); + + // Framebuffer + glGenTextures(1, &self->framebuffer); + glGenFramebuffers(1, &self->fbo); + glGenRenderbuffers(1, &self->rbo); + _canvas_framebuffer_set(self, size); + + self->isInit = true; } -mat4 canvas_transform_get(Canvas* self, vec2 pan, f32 zoom, OriginType origin) -{ - f32 zoomFactor = PERCENT_TO_UNIT(zoom); - mat4 projection = glm::ortho(0.0f, (f32)self->size.x, 0.0f, (f32)self->size.y, -1.0f, 1.0f); - mat4 view = mat4{1.0f}; - vec2 size = vec2(self->size.x, self->size.y); - - switch (origin) - { - case ORIGIN_TOP_LEFT: - view = glm::translate(view, vec3(pan, 0.0f)); - break; - default: - view = glm::translate(view, vec3((size * 0.5f) + pan, 0.0f)); - break; - } +mat4 canvas_transform_get(Canvas* self, vec2 pan, float zoom, OriginType origin) { + float zoomFactor = PERCENT_TO_UNIT(zoom); + mat4 projection = glm::ortho(0.0f, (float)self->size.x, 0.0f, (float)self->size.y, -1.0f, 1.0f); + mat4 view = mat4{1.0f}; + vec2 size = vec2(self->size.x, self->size.y); - view = glm::scale(view, vec3(zoomFactor, zoomFactor, 1.0f)); - - return projection * view; + switch (origin) { + case ORIGIN_TOP_LEFT: + view = glm::translate(view, vec3(pan, 0.0f)); + break; + default: + view = glm::translate(view, vec3((size * 0.5f) + pan, 0.0f)); + break; + } + + view = glm::scale(view, vec3(zoomFactor, zoomFactor, 1.0f)); + + return projection * view; } -void canvas_clear(vec4& color) -{ - glClearColor(color.r, color.g, color.b, color.a); - glClear(GL_COLOR_BUFFER_BIT); +void canvas_clear(vec4& color) { + glClearColor(color.r, color.g, color.b, color.a); + glClear(GL_COLOR_BUFFER_BIT); } -void canvas_viewport_set(Canvas* self) -{ - glViewport(0, 0, (s32)self->size.x, (s32)self->size.y); +void canvas_viewport_set(Canvas* self) { glViewport(0, 0, (int)self->size.x, (int)self->size.y); } + +void canvas_framebuffer_resize_check(Canvas* self) { + if (self->previousSize != self->size) + _canvas_framebuffer_set(self, self->size); } -void canvas_framebuffer_resize_check(Canvas* self) -{ - if (self->previousSize != self->size) - _canvas_framebuffer_set(self, self->size); +void canvas_grid_draw(Canvas* self, GLuint& shader, mat4& transform, ivec2& size, ivec2& offset, vec4& color) { + mat4 inverseTransform = glm::inverse(transform); + + glUseProgram(shader); + + glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_MODEL), 1, GL_FALSE, glm::value_ptr(inverseTransform)); + glUniform2f(glGetUniformLocation(shader, SHADER_UNIFORM_SIZE), size.x, size.y); + glUniform2f(glGetUniformLocation(shader, SHADER_UNIFORM_OFFSET), offset.x, offset.y); + glUniform4f(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), color.r, color.g, color.b, color.a); + + glBindVertexArray(self->gridVAO); + glDrawArrays(GL_TRIANGLES, 0, 3); + glBindVertexArray(0); + + glUseProgram(0); } -void canvas_grid_draw(Canvas* self, GLuint& shader, mat4& transform, ivec2& size, ivec2& offset, vec4& color) -{ - mat4 inverseTransform = glm::inverse(transform); +void canvas_texture_draw(Canvas* self, GLuint& shader, GLuint& texture, mat4& transform, const float* vertices, vec4 tint, vec3 colorOffset) { + glUseProgram(shader); - glUseProgram(shader); + glBindVertexArray(self->textureVAO); - glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_MODEL), 1, GL_FALSE, glm::value_ptr(inverseTransform)); - glUniform2f(glGetUniformLocation(shader, SHADER_UNIFORM_SIZE), size.x, size.y); - glUniform2f(glGetUniformLocation(shader, SHADER_UNIFORM_OFFSET), offset.x, offset.y); - glUniform4f(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), color.r, color.g, color.b, color.a); + glBindBuffer(GL_ARRAY_BUFFER, self->textureVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_TEXTURE_VERTICES), vertices, GL_DYNAMIC_DRAW); - glBindVertexArray(self->gridVAO); - glDrawArrays(GL_TRIANGLES, 0, 3); - glBindVertexArray(0); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture); - glUseProgram(0); + glUniform1i(glGetUniformLocation(shader, SHADER_UNIFORM_TEXTURE), 0); + glUniform3fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR_OFFSET), 1, value_ptr(colorOffset)); + glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TINT), 1, value_ptr(tint)); + glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glUseProgram(0); } -void canvas_texture_draw(Canvas* self, GLuint& shader, GLuint& texture, mat4& transform, const f32* vertices, vec4 tint, vec3 colorOffset) -{ - glUseProgram(shader); - - glBindVertexArray(self->textureVAO); - - glBindBuffer(GL_ARRAY_BUFFER, self->textureVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_TEXTURE_VERTICES), vertices, GL_DYNAMIC_DRAW); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture); +void canvas_rect_draw(Canvas* self, const GLuint& shader, const mat4& transform, const vec4& color) { + glUseProgram(shader); - glUniform1i(glGetUniformLocation(shader, SHADER_UNIFORM_TEXTURE), 0); - glUniform3fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR_OFFSET), 1, value_ptr(colorOffset)); - glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TINT), 1, value_ptr(tint)); - glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); - - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindTexture(GL_TEXTURE_2D, 0); - glUseProgram(0); + glBindVertexArray(self->rectVAO); + + glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); + glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), 1, value_ptr(color)); + + glDrawArrays(GL_LINE_LOOP, 0, 4); + + glBindVertexArray(0); + glUseProgram(0); } -void canvas_rect_draw(Canvas* self, const GLuint& shader, const mat4& transform, const vec4& color) -{ - glUseProgram(shader); +void canvas_axes_draw(Canvas* self, GLuint& shader, mat4& transform, vec4& color) { + vec4 originNDC = transform * vec4(0.0f, 0.0f, 0.0f, 1.0f); + originNDC /= originNDC.w; - glBindVertexArray(self->rectVAO); - - glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); - glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), 1, value_ptr(color)); - - glDrawArrays(GL_LINE_LOOP, 0, 4); - - glBindVertexArray(0); - glUseProgram(0); + glUseProgram(shader); + glBindVertexArray(self->axisVAO); + glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), 1, value_ptr(color)); + glUniform2f(glGetUniformLocation(shader, SHADER_UNIFORM_ORIGIN_NDC), originNDC.x, originNDC.y); + glUniform1i(glGetUniformLocation(shader, SHADER_UNIFORM_AXIS), 0); + glDrawArrays(GL_LINES, 0, 2); + glUniform1i(glGetUniformLocation(shader, SHADER_UNIFORM_AXIS), 1); + glDrawArrays(GL_LINES, 0, 2); + glBindVertexArray(0); + glUseProgram(0); } +void canvas_bind(Canvas* self) { glBindFramebuffer(GL_FRAMEBUFFER, self->fbo); } -void canvas_axes_draw(Canvas* self, GLuint& shader, mat4& transform, vec4& color) -{ - vec4 originNDC = transform * vec4(0.0f, 0.0f, 0.0f, 1.0f); - originNDC /= originNDC.w; +void canvas_unbind(void) { glBindFramebuffer(GL_FRAMEBUFFER, 0); } - glUseProgram(shader); - glBindVertexArray(self->axisVAO); - glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), 1, value_ptr(color)); - glUniform2f(glGetUniformLocation(shader, SHADER_UNIFORM_ORIGIN_NDC), originNDC.x, originNDC.y); - glUniform1i(glGetUniformLocation(shader, SHADER_UNIFORM_AXIS), 0); - glDrawArrays(GL_LINES, 0, 2); - glUniform1i(glGetUniformLocation(shader, SHADER_UNIFORM_AXIS), 1); - glDrawArrays(GL_LINES, 0, 2); - glBindVertexArray(0); - glUseProgram(0); -} +void canvas_free(Canvas* self) { + if (!self->isInit) + return; -void canvas_bind(Canvas* self) -{ - glBindFramebuffer(GL_FRAMEBUFFER, self->fbo); -} - -void canvas_unbind(void) -{ - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} - -void canvas_free(Canvas* self) -{ - if (!self->isInit) return; - - glDeleteFramebuffers(1, &self->fbo); - glDeleteRenderbuffers(1, &self->rbo); - glDeleteTextures(1, &self->framebuffer); - glDeleteVertexArrays(1, &self->axisVAO); - glDeleteVertexArrays(1, &self->rectVAO); - glDeleteVertexArrays(1, &self->gridVAO); - glDeleteVertexArrays(1, &self->textureVAO); - glDeleteBuffers(1, &self->axisVBO); - glDeleteBuffers(1, &self->rectVBO); - glDeleteBuffers(1, &self->gridVBO); - glDeleteBuffers(1, &self->textureVBO); - glDeleteBuffers(1, &self->textureEBO); + glDeleteFramebuffers(1, &self->fbo); + glDeleteRenderbuffers(1, &self->rbo); + glDeleteTextures(1, &self->framebuffer); + glDeleteVertexArrays(1, &self->axisVAO); + glDeleteVertexArrays(1, &self->rectVAO); + glDeleteVertexArrays(1, &self->gridVAO); + glDeleteVertexArrays(1, &self->textureVAO); + glDeleteBuffers(1, &self->axisVBO); + glDeleteBuffers(1, &self->rectVBO); + glDeleteBuffers(1, &self->gridVBO); + glDeleteBuffers(1, &self->textureVBO); + glDeleteBuffers(1, &self->textureEBO); } \ No newline at end of file diff --git a/src/canvas.h b/src/canvas.h index 06a9d2f..d7f58e2 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -13,64 +13,40 @@ const inline vec2 CANVAS_PIVOT_SIZE = {4, 4}; const inline vec2 CANVAS_SCALE_DEFAULT = {1.0f, 1.0f}; -const inline f32 CANVAS_AXIS_VERTICES[] = {-1.0f, 1.0f}; +const inline float CANVAS_AXIS_VERTICES[] = {-1.0f, 1.0f}; -const inline f32 CANVAS_GRID_VERTICES[] = -{ - -1.0f, -1.0f, - 3.0f, -1.0f, - -1.0f, 3.0f +const inline float CANVAS_GRID_VERTICES[] = {-1.0f, -1.0f, 3.0f, -1.0f, -1.0f, 3.0f}; + +const inline float CANVAS_RECT_VERTICES[] = {0, 0, 1, 0, 1, 1, 0, 1}; + +const inline float CANVAS_TEXTURE_VERTICES[] = {0, 0, 0.0f, 0.0f, 1, 0, 1.0f, 0.0f, 1, 1, 1.0f, 1.0f, 0, 1, 0.0f, 1.0f}; + +struct Canvas { + GLuint fbo{}; + GLuint rbo{}; + GLuint axisVAO{}; + GLuint axisVBO{}; + GLuint rectVAO{}; + GLuint rectVBO{}; + GLuint gridVAO{}; + GLuint gridVBO{}; + GLuint framebuffer{}; + GLuint textureVAO{}; + GLuint textureVBO{}; + GLuint textureEBO{}; + ivec2 size{}; + ivec2 previousSize{}; + bool isInit = false; }; -const inline f32 CANVAS_RECT_VERTICES[] = -{ - 0, 0, - 1, 0, - 1, 1, - 0, 1 -}; - -const inline f32 CANVAS_TEXTURE_VERTICES[] = -{ - 0, 0, 0.0f, 0.0f, - 1, 0, 1.0f, 0.0f, - 1, 1, 1.0f, 1.0f, - 0, 1, 0.0f, 1.0f -}; - -struct Canvas -{ - GLuint fbo{}; - GLuint rbo{}; - GLuint axisVAO{}; - GLuint axisVBO{}; - GLuint rectVAO{}; - GLuint rectVBO{}; - GLuint gridVAO{}; - GLuint gridVBO{}; - GLuint framebuffer{}; - GLuint textureVAO{}; - GLuint textureVBO{}; - GLuint textureEBO{}; - ivec2 size{}; - ivec2 previousSize{}; - bool isInit = false; -}; - -#define UV_VERTICES(uvMin, uvMax) \ -{ \ - 0, 0, uvMin.x, uvMin.y, \ - 1, 0, uvMax.x, uvMin.y, \ - 1, 1, uvMax.x, uvMax.y, \ - 0, 1, uvMin.x, uvMax.y \ -} +#define UV_VERTICES(uvMin, uvMax) {0, 0, uvMin.x, uvMin.y, 1, 0, uvMax.x, uvMin.y, 1, 1, uvMax.x, uvMax.y, 0, 1, uvMin.x, uvMax.y} #define ATLAS_UV_MIN(type) (ATLAS_POSITION(type) / TEXTURE_ATLAS_SIZE) #define ATLAS_UV_MAX(type) ((ATLAS_POSITION(type) + ATLAS_SIZE(type)) / TEXTURE_ATLAS_SIZE) #define ATLAS_UV_ARGS(type) ATLAS_UV_MIN(type), ATLAS_UV_MAX(type) #define ATLAS_UV_VERTICES(type) UV_VERTICES(ATLAS_UV_MIN(type), ATLAS_UV_MAX(type)) -mat4 canvas_transform_get(Canvas* self, vec2 pan, f32 zoom, OriginType origin); +mat4 canvas_transform_get(Canvas* self, vec2 pan, float zoom, OriginType origin); void canvas_axes_draw(Canvas* self, GLuint& shader, mat4& transform, vec4& color); void canvas_bind(Canvas* self); void canvas_clear(vec4& color); @@ -83,13 +59,5 @@ void canvas_framebuffer_resize_check(Canvas* self); void canvas_unbind(void); void canvas_viewport_set(Canvas* self); -void canvas_texture_draw -( - Canvas* self, - GLuint& shader, - GLuint& texture, - mat4& transform, - const f32* vertices = CANVAS_TEXTURE_VERTICES, - vec4 tint = COLOR_OPAQUE, - vec3 colorOffset = COLOR_OFFSET_NONE -); \ No newline at end of file +void canvas_texture_draw(Canvas* self, GLuint& shader, GLuint& texture, mat4& transform, const float* vertices = CANVAS_TEXTURE_VERTICES, + vec4 tint = COLOR_OPAQUE, vec3 colorOffset = COLOR_OFFSET_NONE); \ No newline at end of file diff --git a/src/clipboard.cpp b/src/clipboard.cpp index 874db01..3e5d09d 100644 --- a/src/clipboard.cpp +++ b/src/clipboard.cpp @@ -1,113 +1,102 @@ #include "clipboard.h" -void clipboard_copy(Clipboard* self) -{ - std::string clipboardText{}; - - auto clipboard_text_set = [&]() - { - if (!SDL_SetClipboardText(clipboardText.c_str())) - log_warning(std::format(CLIPBOARD_TEXT_SET_WARNING, SDL_GetError())); - }; - - switch (self->type) - { - case CLIPBOARD_FRAME: - { - Anm2Reference* reference = std::get_if(&self->location); - if (!reference) break; - Anm2Frame* frame = anm2_frame_from_reference(self->anm2, reference); - if (!frame) break; - anm2_frame_serialize_to_string(frame, reference->itemType, &clipboardText); - clipboard_text_set(); - break; - } - case CLIPBOARD_ANIMATION: - { - s32* id = std::get_if(&self->location); - if (!id) break; - Anm2Animation* animation = map_find(self->anm2->animations, *id); - if (!animation) break; - anm2_animation_serialize_to_string(animation, &clipboardText); - clipboard_text_set(); - break; - } - break; - default: - break; - } +void clipboard_copy(Clipboard* self) { + std::string clipboardText{}; + + auto clipboard_text_set = [&]() { + if (!SDL_SetClipboardText(clipboardText.c_str())) + log_warning(std::format(CLIPBOARD_TEXT_SET_WARNING, SDL_GetError())); + }; + + switch (self->type) { + case CLIPBOARD_FRAME: { + Anm2Reference* reference = std::get_if(&self->location); + if (!reference) + break; + Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *reference); + if (!frame) + break; + anm2_frame_serialize_to_string(frame, reference->itemType, &clipboardText); + clipboard_text_set(); + break; + } + case CLIPBOARD_ANIMATION: { + int* id = std::get_if(&self->location); + if (!id) + break; + Anm2Animation* animation = map_find(self->anm2->animations, *id); + if (!animation) + break; + anm2_animation_serialize_to_string(animation, &clipboardText); + clipboard_text_set(); + break; + } break; + default: + break; + } } -void clipboard_cut(Clipboard* self) -{ - clipboard_copy(self); +void clipboard_cut(Clipboard* self) { + clipboard_copy(self); - switch (self->type) - { - case CLIPBOARD_FRAME: - { - Anm2Reference* reference = std::get_if(&self->location); - if (!reference) break; - anm2_frame_remove(self->anm2, reference); - break; - } - case CLIPBOARD_ANIMATION: - { - s32* id = std::get_if(&self->location); - if (!id) break; - anm2_animation_remove(self->anm2, *id); - break; - } - default: - break; - } + switch (self->type) { + case CLIPBOARD_FRAME: { + Anm2Reference* reference = std::get_if(&self->location); + if (!reference) + break; + anm2_frame_remove(self->anm2, *reference); + break; + } + case CLIPBOARD_ANIMATION: { + int* id = std::get_if(&self->location); + if (!id) + break; + anm2_animation_remove(self->anm2, *id); + break; + } + default: + break; + } } -bool clipboard_paste(Clipboard* self) -{ - auto clipboard_string = [&]() - { - char* clipboardText = SDL_GetClipboardText(); - std::string clipboardString = std::string(clipboardText); - SDL_free(clipboardText); - return clipboardString; - }; +bool clipboard_paste(Clipboard* self) { + auto clipboard_string = [&]() { + char* clipboardText = SDL_GetClipboardText(); + std::string clipboardString = std::string(clipboardText); + SDL_free(clipboardText); + return clipboardString; + }; - switch (self->type) - { - case CLIPBOARD_FRAME: - { - Anm2Reference* reference = std::get_if(&self->location); - if (!reference) break; - Anm2Frame frame; - if (anm2_frame_deserialize_from_xml(&frame, clipboard_string())) - anm2_frame_add(self->anm2, &frame, reference); - else return false; - break; - } - case CLIPBOARD_ANIMATION: - { - s32* id = std::get_if(&self->location); - if (!id) break; - Anm2Animation animation; - if (anm2_animation_deserialize_from_xml(&animation, clipboard_string())) - anm2_animation_add(self->anm2, &animation, *id); - else return false; - break; - } - default: - break; - } + switch (self->type) { + case CLIPBOARD_FRAME: { + Anm2Reference* reference = std::get_if(&self->location); + if (!reference) + break; + Anm2Frame frame; + if (anm2_frame_deserialize_from_xml(&frame, clipboard_string())) + anm2_frame_add(self->anm2, &frame, *reference); + else + return false; + break; + } + case CLIPBOARD_ANIMATION: { + int* id = std::get_if(&self->location); + if (!id) + break; + Anm2Animation animation; + if (anm2_animation_deserialize_from_xml(&animation, clipboard_string())) + anm2_animation_add(self->anm2, &animation, *id); + else + return false; + break; + } + default: + break; + } - return true; + return true; } -void clipboard_init(Clipboard* self, Anm2* anm2) -{ - self->anm2 = anm2; -} +void clipboard_init(Clipboard* self, Anm2* anm2) { self->anm2 = anm2; } -bool clipboard_is_value(void) -{ - return SDL_HasClipboardText(); -} \ No newline at end of file +bool clipboard_is_value(void) { return SDL_HasClipboardText(); } \ No newline at end of file diff --git a/src/clipboard.h b/src/clipboard.h index d269ce7..98621e1 100644 --- a/src/clipboard.h +++ b/src/clipboard.h @@ -4,20 +4,14 @@ #define CLIPBOARD_TEXT_SET_WARNING "Unable to set clipboard text! ({})" -enum ClipboardType -{ - CLIPBOARD_NONE, - CLIPBOARD_FRAME, - CLIPBOARD_ANIMATION -}; +enum ClipboardType { CLIPBOARD_NONE, CLIPBOARD_FRAME, CLIPBOARD_ANIMATION }; -using ClipboardLocation = std::variant; +using ClipboardLocation = std::variant; -struct Clipboard -{ - Anm2* anm2 = nullptr; - ClipboardType type; - ClipboardLocation location; +struct Clipboard { + Anm2* anm2 = nullptr; + ClipboardType type; + ClipboardLocation location; }; bool clipboard_is_value(void); diff --git a/src/dialog.cpp b/src/dialog.cpp index f3a1449..1db4a23 100644 --- a/src/dialog.cpp +++ b/src/dialog.cpp @@ -1,91 +1,70 @@ #include "dialog.h" #ifdef _WIN32 - #include +#include #endif -static void _dialog_callback(void* userdata, const char* const* filelist, s32 filter) -{ - Dialog* self; +static void _dialog_callback(void* userdata, const char* const* filelist, int filter) { + Dialog* self; - self = (Dialog*)userdata; + self = (Dialog*)userdata; - if (filelist && filelist[0] && strlen(filelist[0]) > 0) - { - self->path = filelist[0]; - self->isSelected = true; - self->selectedFilter = filter; - } - else - { - self->isSelected = false; - self->selectedFilter = INDEX_NONE; - } + if (filelist && filelist[0] && strlen(filelist[0]) > 0) { + self->path = filelist[0]; + self->isSelected = true; + self->selectedFilter = filter; + } else { + self->isSelected = false; + self->selectedFilter = INDEX_NONE; + } } -void dialog_init(Dialog* self, SDL_Window* window) -{ - self->window = window; +void dialog_init(Dialog* self, SDL_Window* window) { self->window = window; } + +void dialog_anm2_open(Dialog* self) { + SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_ANM2, std::size(DIALOG_FILE_FILTER_ANM2), nullptr, false); + self->type = DIALOG_ANM2_OPEN; } -void dialog_anm2_open(Dialog* self) -{ - SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_ANM2, std::size(DIALOG_FILE_FILTER_ANM2), nullptr, false); - self->type = DIALOG_ANM2_OPEN; +void dialog_anm2_save(Dialog* self) { + SDL_ShowSaveFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_ANM2, std::size(DIALOG_FILE_FILTER_ANM2), nullptr); + self->type = DIALOG_ANM2_SAVE; } -void dialog_anm2_save(Dialog* self) -{ - SDL_ShowSaveFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_ANM2, std::size(DIALOG_FILE_FILTER_ANM2), nullptr); - self->type = DIALOG_ANM2_SAVE; +void dialog_spritesheet_add(Dialog* self) { + SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_PNG, std::size(DIALOG_FILE_FILTER_PNG), nullptr, false); + self->type = DIALOG_SPRITESHEET_ADD; } -void dialog_spritesheet_add(Dialog* self) -{ - SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_PNG, std::size(DIALOG_FILE_FILTER_PNG), nullptr, false); - self->type = DIALOG_SPRITESHEET_ADD; +void dialog_spritesheet_replace(Dialog* self, int id) { + SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_PNG, std::size(DIALOG_FILE_FILTER_PNG), nullptr, false); + self->replaceID = id; + self->type = DIALOG_SPRITESHEET_REPLACE; } -void dialog_spritesheet_replace(Dialog* self, s32 id) -{ - SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_PNG, std::size(DIALOG_FILE_FILTER_PNG), nullptr, false); - self->replaceID = id; - self->type = DIALOG_SPRITESHEET_REPLACE; +void dialog_render_path_set(Dialog* self, RenderType type) { + SDL_DialogFileFilter filter = DIALOG_RENDER_FILE_FILTERS[type]; + + if (type == RENDER_PNG) + SDL_ShowOpenFolderDialog(_dialog_callback, self, self->window, nullptr, false); + else + SDL_ShowSaveFileDialog(_dialog_callback, self, self->window, &filter, 1, nullptr); + self->type = DIALOG_RENDER_PATH_SET; } -void dialog_render_path_set(Dialog* self, RenderType type) -{ - SDL_DialogFileFilter filter = DIALOG_RENDER_FILE_FILTERS[type]; - - if (type == RENDER_PNG) - SDL_ShowOpenFolderDialog(_dialog_callback, self, self->window, nullptr, false); - else - SDL_ShowSaveFileDialog(_dialog_callback, self, self->window, &filter, 1, nullptr); - self->type = DIALOG_RENDER_PATH_SET; +void dialog_ffmpeg_path_set(Dialog* self) { + SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_FFMPEG, std::size(DIALOG_FILE_FILTER_FFMPEG), nullptr, false); + self->type = DIALOG_FFMPEG_PATH_SET; } -void dialog_ffmpeg_path_set(Dialog* self) -{ - SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_FFMPEG, std::size(DIALOG_FILE_FILTER_FFMPEG), nullptr, false); - self->type = DIALOG_FFMPEG_PATH_SET; -} - -void dialog_explorer_open(const std::string& path) -{ +void dialog_explorer_open(const std::string& path) { #ifdef _WIN32 - ShellExecuteA(NULL, DIALOG_FILE_EXPLORER_COMMAND, path.c_str(), NULL, NULL, SW_SHOWNORMAL); -#else - char command[DIALOG_FILE_EXPLORER_COMMAND_SIZE]; - snprintf(command, sizeof(command), DIALOG_FILE_EXPLORER_COMMAND, path.c_str()); - system(command); + ShellExecuteA(NULL, DIALOG_FILE_EXPLORER_COMMAND, path.c_str(), NULL, NULL, SW_SHOWNORMAL); +#else + char command[DIALOG_FILE_EXPLORER_COMMAND_SIZE]; + snprintf(command, sizeof(command), DIALOG_FILE_EXPLORER_COMMAND, path.c_str()); + system(command); #endif } -void -dialog_reset(Dialog* self) -{ - self->replaceID = ID_NONE; - self->type = DIALOG_NONE; - self->path.clear(); - self->isSelected = false; -} \ No newline at end of file +void dialog_reset(Dialog* self) { *self = {self->window}; } \ No newline at end of file diff --git a/src/dialog.h b/src/dialog.h index f624e17..c965e0a 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -7,30 +7,17 @@ #ifdef _WIN32 #define DIALOG_FILE_EXPLORER_COMMAND "open" -#else +#else #define DIALOG_FILE_EXPLORER_COMMAND "xdg-open \"%s\" &" #endif -const SDL_DialogFileFilter DIALOG_FILE_FILTER_ANM2[] = -{ - {"Anm2 file", "anm2;xml"} -}; +const SDL_DialogFileFilter DIALOG_FILE_FILTER_ANM2[] = {{"Anm2 file", "anm2;xml"}}; -const SDL_DialogFileFilter DIALOG_FILE_FILTER_PNG[] = -{ - {"PNG image", "png"} -}; +const SDL_DialogFileFilter DIALOG_FILE_FILTER_PNG[] = {{"PNG image", "png"}}; -const SDL_DialogFileFilter DIALOG_RENDER_FILE_FILTERS[] = -{ - {"PNG image", "png"}, - {"GIF image", "gif"}, - {"WebM video", "webm"}, - {"MP4 video", "mp4"} -}; +const SDL_DialogFileFilter DIALOG_RENDER_FILE_FILTERS[] = {{"PNG image", "png"}, {"GIF image", "gif"}, {"WebM video", "webm"}, {"MP4 video", "mp4"}}; -const SDL_DialogFileFilter DIALOG_FILE_FILTER_FFMPEG[] = -{ +const SDL_DialogFileFilter DIALOG_FILE_FILTER_FFMPEG[] = { #ifdef _WIN32 {"Executable", "exe"} #else @@ -38,31 +25,29 @@ const SDL_DialogFileFilter DIALOG_FILE_FILTER_FFMPEG[] = #endif }; -enum DialogType -{ - DIALOG_NONE, - DIALOG_ANM2_OPEN, - DIALOG_ANM2_SAVE, - DIALOG_SPRITESHEET_ADD, - DIALOG_SPRITESHEET_REPLACE, - DIALOG_RENDER_PATH_SET, - DIALOG_FFMPEG_PATH_SET +enum DialogType { + DIALOG_NONE, + DIALOG_ANM2_OPEN, + DIALOG_ANM2_SAVE, + DIALOG_SPRITESHEET_ADD, + DIALOG_SPRITESHEET_REPLACE, + DIALOG_RENDER_PATH_SET, + DIALOG_FFMPEG_PATH_SET }; -struct Dialog -{ - SDL_Window* window = nullptr; - s32 selectedFilter = ID_NONE; - std::string path{}; - s32 replaceID = ID_NONE; - DialogType type = DIALOG_NONE; - bool isSelected = false; +struct Dialog { + SDL_Window* window = nullptr; + std::string path{}; + int selectedFilter = ID_NONE; + int replaceID = ID_NONE; + DialogType type = DIALOG_NONE; + bool isSelected{}; }; void dialog_init(Dialog* self, SDL_Window* window); void dialog_anm2_open(Dialog* self); void dialog_spritesheet_add(Dialog* self); -void dialog_spritesheet_replace(Dialog* self, s32 id); +void dialog_spritesheet_replace(Dialog* self, int id); void dialog_anm2_save(Dialog* self); void dialog_render_path_set(Dialog* self, RenderType type); void dialog_render_directory_set(Dialog* self); diff --git a/src/editor.cpp b/src/editor.cpp index 02e2a13..7bd0d3a 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1,61 +1,54 @@ #include "editor.h" -void editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings) -{ - self->anm2 = anm2; - self->reference = reference; - self->resources = resources; - self->settings = settings; +void editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings) { + self->anm2 = anm2; + self->reference = reference; + self->resources = resources; + self->settings = settings; - canvas_init(&self->canvas, vec2()); + canvas_init(&self->canvas, vec2()); } -void editor_draw(Editor* self) -{ - ivec2& gridSize = self->settings->editorGridSize; - ivec2& gridOffset = self->settings->editorGridOffset; - vec4& gridColor = self->settings->editorGridColor; - GLuint& shaderLine = self->resources->shaders[SHADER_LINE]; - GLuint& shaderTexture = self->resources->shaders[SHADER_TEXTURE]; - GLuint& shaderGrid = self->resources->shaders[SHADER_GRID]; - mat4 transform = canvas_transform_get(&self->canvas, self->settings->editorPan, self->settings->editorZoom, ORIGIN_TOP_LEFT); - - canvas_framebuffer_resize_check(&self->canvas); - - canvas_bind(&self->canvas); - canvas_viewport_set(&self->canvas); - canvas_clear(self->settings->editorBackgroundColor); +void editor_draw(Editor* self) { + ivec2& gridSize = self->settings->editorGridSize; + ivec2& gridOffset = self->settings->editorGridOffset; + vec4& gridColor = self->settings->editorGridColor; + GLuint& shaderLine = self->resources->shaders[SHADER_LINE]; + GLuint& shaderTexture = self->resources->shaders[SHADER_TEXTURE]; + GLuint& shaderGrid = self->resources->shaders[SHADER_GRID]; + mat4 transform = canvas_transform_get(&self->canvas, self->settings->editorPan, self->settings->editorZoom, ORIGIN_TOP_LEFT); - if (Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->spritesheetID)) - { - Texture& texture = spritesheet->texture; - - mat4 spritesheetTransform = transform * quad_model_get(texture.size); - canvas_texture_draw(&self->canvas, shaderTexture, texture.id, spritesheetTransform); + canvas_framebuffer_resize_check(&self->canvas); - if (self->settings->editorIsBorder) - canvas_rect_draw(&self->canvas, shaderLine, spritesheetTransform, EDITOR_BORDER_COLOR); + canvas_bind(&self->canvas); + canvas_viewport_set(&self->canvas); + canvas_clear(self->settings->editorBackgroundColor); - Anm2Frame* frame = (Anm2Frame*)anm2_frame_from_reference(self->anm2, self->reference); - - if (frame) - { - mat4 cropTransform = transform * quad_model_get(frame->size, frame->crop); - canvas_rect_draw(&self->canvas, shaderLine, cropTransform, EDITOR_FRAME_COLOR); + if (Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->spritesheetID)) { + Texture& texture = spritesheet->texture; - mat4 pivotTransform = transform * quad_model_get(CANVAS_PIVOT_SIZE, frame->crop + frame->pivot, CANVAS_PIVOT_SIZE * 0.5f); - f32 vertices[] = ATLAS_UV_VERTICES(ATLAS_PIVOT); - canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, pivotTransform, vertices, EDITOR_PIVOT_COLOR); - } + mat4 spritesheetTransform = transform * quad_model_get(texture.size); + canvas_texture_draw(&self->canvas, shaderTexture, texture.id, spritesheetTransform); + + if (self->settings->editorIsBorder) + canvas_rect_draw(&self->canvas, shaderLine, spritesheetTransform, EDITOR_BORDER_COLOR); + + Anm2Frame* frame = (Anm2Frame*)anm2_frame_from_reference(self->anm2, *self->reference); + + if (frame) { + mat4 cropTransform = transform * quad_model_get(frame->size, frame->crop); + canvas_rect_draw(&self->canvas, shaderLine, cropTransform, EDITOR_FRAME_COLOR); + + mat4 pivotTransform = transform * quad_model_get(CANVAS_PIVOT_SIZE, frame->crop + frame->pivot, CANVAS_PIVOT_SIZE * 0.5f); + float vertices[] = ATLAS_UV_VERTICES(ATLAS_PIVOT); + canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, pivotTransform, vertices, EDITOR_PIVOT_COLOR); } + } - if (self->settings->editorIsGrid) - canvas_grid_draw(&self->canvas, shaderGrid, transform, gridSize, gridOffset, gridColor); + if (self->settings->editorIsGrid) + canvas_grid_draw(&self->canvas, shaderGrid, transform, gridSize, gridOffset, gridColor); - canvas_unbind(); + canvas_unbind(); } -void editor_free(Editor* self) -{ - canvas_free(&self->canvas); -} \ No newline at end of file +void editor_free(Editor* self) { canvas_free(&self->canvas); } \ No newline at end of file diff --git a/src/editor.h b/src/editor.h index 8963e0b..c4a84e8 100644 --- a/src/editor.h +++ b/src/editor.h @@ -17,26 +17,25 @@ static const vec4 EDITOR_BORDER_COLOR = COLOR_OPAQUE; static const vec4 EDITOR_FRAME_COLOR = COLOR_RED; static const vec4 EDITOR_PIVOT_COLOR = COLOR_PINK; -struct Editor -{ - Anm2* anm2 = nullptr; - Anm2Reference* reference = nullptr; - Resources* resources = nullptr; - Settings* settings = nullptr; - Canvas canvas; - GLuint fbo; - GLuint rbo; - GLuint gridVAO; - GLuint gridVBO; - GLuint texture; - GLuint textureEBO; - GLuint textureVAO; - GLuint textureVBO; - GLuint borderVAO; - GLuint borderVBO; - s32 spritesheetID = ID_NONE; +struct Editor { + Anm2* anm2 = nullptr; + Anm2Reference* reference = nullptr; + Resources* resources = nullptr; + Settings* settings = nullptr; + Canvas canvas; + GLuint fbo; + GLuint rbo; + GLuint gridVAO; + GLuint gridVBO; + GLuint texture; + GLuint textureEBO; + GLuint textureVAO; + GLuint textureVBO; + GLuint borderVAO; + GLuint borderVBO; + int spritesheetID = ID_NONE; }; -void editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings); +void editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings); void editor_draw(Editor* self); void editor_free(Editor* self); \ No newline at end of file diff --git a/src/ffmpeg.cpp b/src/ffmpeg.cpp index 36edf68..b8ff2ee 100644 --- a/src/ffmpeg.cpp +++ b/src/ffmpeg.cpp @@ -1,69 +1,56 @@ #include "ffmpeg.h" -bool -ffmpeg_render -( - const std::string& ffmpegPath, - const std::string& outputPath, - const std::vector& frames, - ivec2 size, - s32 fps, - enum RenderType type -) -{ - if (frames.empty() || size.x <= 0 || size.y <= 0 || fps <= 0 || ffmpegPath.empty() || outputPath.empty()) return false; - - std::string command{}; +bool ffmpeg_render(const std::string& ffmpegPath, const std::string& outputPath, const std::vector& frames, ivec2 size, int fps, + enum RenderType type) { + if (frames.empty() || size.x <= 0 || size.y <= 0 || fps <= 0 || ffmpegPath.empty() || outputPath.empty()) + return false; - switch (type) - { - case RENDER_GIF: - command = std::format(FFMPEG_GIF_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath); - break; - case RENDER_WEBM: - command = std::format(FFMPEG_WEBM_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath); - break; - case RENDER_MP4: - command = std::format(FFMPEG_MP4_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath); - break; - default: - break; - } + std::string command{}; + + switch (type) { + case RENDER_GIF: + command = std::format(FFMPEG_GIF_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath); + break; + case RENDER_WEBM: + command = std::format(FFMPEG_WEBM_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath); + break; + case RENDER_MP4: + command = std::format(FFMPEG_MP4_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath); + break; + default: + break; + } #if _WIN32 - command = string_quote(command); + command = string_quote(command); #endif - log_command(command); + log_command(command); - FILE* fp = POPEN(command.c_str(), PWRITE_MODE); + FILE* fp = POPEN(command.c_str(), PWRITE_MODE); - if (!fp) - { - log_error(std::format(FFMPEG_POPEN_ERROR, strerror(errno))); - return false; - } - - size_t frameBytes = size.x * size.y * TEXTURE_CHANNELS; + if (!fp) { + log_error(std::format(FFMPEG_POPEN_ERROR, strerror(errno))); + return false; + } - for (const auto& frame : frames) - { - std::vector rgba = texture_download(&frame); + size_t frameBytes = size.x * size.y * TEXTURE_CHANNELS; - if (rgba.size() != frameBytes) - { - PCLOSE(fp); - return false; - } + for (const auto& frame : frames) { + std::vector rgba = texture_download(&frame); - if (fwrite(rgba.data(), 1, frameBytes, fp) != frameBytes) - { - PCLOSE(fp); - return false; - } + if (rgba.size() != frameBytes) { + PCLOSE(fp); + return false; } - const int code = PCLOSE(fp); + if (fwrite(rgba.data(), 1, frameBytes, fp) != frameBytes) { + PCLOSE(fp); + return false; + } + } - return (code == 0); + const int code = PCLOSE(fp); + + return (code == 0); } \ No newline at end of file diff --git a/src/ffmpeg.h b/src/ffmpeg.h index 2747a57..099978e 100644 --- a/src/ffmpeg.h +++ b/src/ffmpeg.h @@ -5,34 +5,22 @@ #define FFMPEG_POPEN_ERROR "popen() (for FFmpeg) failed!\n{}" -static constexpr const char* FFMPEG_GIF_FORMAT = -"\"{0}\" -y " -"-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " -"-lavfi \"split[s0][s1];" -"[s0]palettegen=stats_mode=full[p];" -"[s1][p]paletteuse=dither=floyd_steinberg\" " -"-loop 0 \"{4}\""; +static constexpr const char* FFMPEG_GIF_FORMAT = "\"{0}\" -y " + "-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " + "-lavfi \"split[s0][s1];" + "[s0]palettegen=stats_mode=full[p];" + "[s1][p]paletteuse=dither=floyd_steinberg\" " + "-loop 0 \"{4}\""; -static constexpr const char* FFMPEG_WEBM_FORMAT = -"\"{0}\" -y " -"-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " -"-c:v libvpx-vp9 -crf 30 -b:v 0 -pix_fmt yuva420p -row-mt 1 -threads 0 -speed 2 " -"-auto-alt-ref 0 -an \"{4}\""; +static constexpr const char* FFMPEG_WEBM_FORMAT = "\"{0}\" -y " + "-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " + "-c:v libvpx-vp9 -crf 30 -b:v 0 -pix_fmt yuva420p -row-mt 1 -threads 0 -speed 2 " + "-auto-alt-ref 0 -an \"{4}\""; -static constexpr const char* FFMPEG_MP4_FORMAT = -"\"{0}\" -y " -"-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " -"-vf \"format=yuv420p,scale=trunc(iw/2)*2:trunc(ih/2)*2\" " -"-c:v libx265 -crf 20 -preset slow " -"-tag:v hvc1 -movflags +faststart -an \"{4}\""; +static constexpr const char* FFMPEG_MP4_FORMAT = "\"{0}\" -y " + "-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " + "-vf \"format=yuv420p,scale=trunc(iw/2)*2:trunc(ih/2)*2\" " + "-c:v libx265 -crf 20 -preset slow " + "-tag:v hvc1 -movflags +faststart -an \"{4}\""; -bool -ffmpeg_render -( - const std::string& ffmpegPath, - const std::string& outputPath, - const std::vector& frames, - ivec2 size, - s32 fps, - enum RenderType type -); \ No newline at end of file +bool ffmpeg_render(const std::string& ffmpegPath, const std::string& outputPath, const std::vector& frames, ivec2 size, int fps, enum RenderType type); \ No newline at end of file diff --git a/src/generate_preview.cpp b/src/generate_preview.cpp index 7faa101..0d2ffe7 100644 --- a/src/generate_preview.cpp +++ b/src/generate_preview.cpp @@ -1,57 +1,50 @@ #include "generate_preview.h" -void generate_preview_init(GeneratePreview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings) -{ - self->anm2 = anm2; - self->reference = reference; - self->resources = resources; - self->settings = settings; +void generate_preview_init(GeneratePreview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings) { + self->anm2 = anm2; + self->reference = reference; + self->resources = resources; + self->settings = settings; - canvas_init(&self->canvas, GENERATE_PREVIEW_SIZE); + canvas_init(&self->canvas, GENERATE_PREVIEW_SIZE); } -void generate_preview_draw(GeneratePreview* self) -{ - static auto& columns = self->settings->generateColumns; - static auto& count = self->settings->generateCount; - static GLuint& shaderTexture = self->resources->shaders[SHADER_TEXTURE]; - const mat4 transform = canvas_transform_get(&self->canvas, {}, CANVAS_ZOOM_DEFAULT, ORIGIN_CENTER); - - vec2 startPosition = {self->settings->generateStartPosition.x, self->settings->generateStartPosition.y}; - vec2 size = {self->settings->generateSize.x, self->settings->generateSize.y}; - vec2 pivot = {self->settings->generatePivot.x, self->settings->generatePivot.y}; +void generate_preview_draw(GeneratePreview* self) { + static auto& columns = self->settings->generateColumns; + static auto& count = self->settings->generateCount; + static GLuint& shaderTexture = self->resources->shaders[SHADER_TEXTURE]; + const mat4 transform = canvas_transform_get(&self->canvas, {}, CANVAS_ZOOM_DEFAULT, ORIGIN_CENTER); - canvas_bind(&self->canvas); - canvas_viewport_set(&self->canvas); - canvas_clear(self->settings->previewBackgroundColor); - - Anm2Item* item = anm2_item_from_reference(self->anm2, self->reference); + vec2 startPosition = {self->settings->generateStartPosition.x, self->settings->generateStartPosition.y}; + vec2 size = {self->settings->generateSize.x, self->settings->generateSize.y}; + vec2 pivot = {self->settings->generatePivot.x, self->settings->generatePivot.y}; - if (item) - { - if (Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->anm2->layers[self->reference->itemID].spritesheetID)) - { - Texture& texture = spritesheet->texture; + canvas_bind(&self->canvas); + canvas_viewport_set(&self->canvas); + canvas_clear(self->settings->previewBackgroundColor); - const s32 index = std::clamp((s32)(self->time * count), 0, count); - const s32 row = index / columns; - const s32 column = index % columns; - vec2 crop = startPosition + vec2(size.x * column, size.y * row); + Anm2Item* item = anm2_item_from_reference(self->anm2, *self->reference); - vec2 textureSize = vec2(texture.size); - vec2 uvMin = (crop + vec2(0.5f)) / textureSize; - vec2 uvMax = (crop + size - vec2(0.5f)) / textureSize; - f32 vertices[] = UV_VERTICES(uvMin, uvMax); + if (item) { + if (Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->anm2->layers[self->reference->itemID].spritesheetID)) { + Texture& texture = spritesheet->texture; - mat4 generateTransform = transform * quad_model_get(size, {}, pivot); - canvas_texture_draw(&self->canvas, shaderTexture, texture.id, generateTransform, vertices, COLOR_OPAQUE, COLOR_OFFSET_NONE); - } + const int index = std::clamp((int)(self->time * count), 0, count); + const int row = index / columns; + const int column = index % columns; + vec2 crop = startPosition + vec2(size.x * column, size.y * row); + + vec2 textureSize = vec2(texture.size); + vec2 uvMin = (crop + vec2(0.5f)) / textureSize; + vec2 uvMax = (crop + size - vec2(0.5f)) / textureSize; + float vertices[] = UV_VERTICES(uvMin, uvMax); + + mat4 generateTransform = transform * quad_model_get(size, {}, pivot); + canvas_texture_draw(&self->canvas, shaderTexture, texture.id, generateTransform, vertices, COLOR_OPAQUE, COLOR_OFFSET_NONE); } - - canvas_unbind(); + } + + canvas_unbind(); } -void generate_preview_free(GeneratePreview* self) -{ - canvas_free(&self->canvas); -} \ No newline at end of file +void generate_preview_free(GeneratePreview* self) { canvas_free(&self->canvas); } \ No newline at end of file diff --git a/src/generate_preview.h b/src/generate_preview.h index fa1b576..6539991 100644 --- a/src/generate_preview.h +++ b/src/generate_preview.h @@ -1,23 +1,22 @@ #pragma once #include "anm2.h" +#include "canvas.h" #include "resources.h" #include "settings.h" -#include "canvas.h" #define GENERATE_PREVIEW_TIME_MIN 0.0f #define GENERATE_PREVIEW_TIME_MAX 1.0f const vec2 GENERATE_PREVIEW_SIZE = {325, 215}; -struct GeneratePreview -{ - Anm2* anm2 = nullptr; - Anm2Reference* reference = nullptr; - Resources* resources = nullptr; - Settings* settings = nullptr; - Canvas canvas; - f32 time{}; +struct GeneratePreview { + Anm2* anm2 = nullptr; + Anm2Reference* reference = nullptr; + Resources* resources = nullptr; + Settings* settings = nullptr; + Canvas canvas; + float time{}; }; void generate_preview_init(GeneratePreview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings); diff --git a/src/imgui.cpp b/src/imgui.cpp index c6203fa..c8b420f 100644 --- a/src/imgui.cpp +++ b/src/imgui.cpp @@ -1,3246 +1,3059 @@ #include "imgui.h" -static bool _imgui_chord_pressed(ImGuiKeyChord chord) -{ - if (chord == IMGUI_CHORD_NONE) return false; - ImGuiKey key = (ImGuiKey)(chord & ~ImGuiMod_Mask_); - if (key == ImGuiKey_None) return false; - if (key < ImGuiKey_NamedKey_BEGIN || key >= ImGuiKey_NamedKey_END) return false; +static void _imgui_anm2_open(Imgui* self, const std::string& path) { + imgui_anm2_new(self); - return ImGui::IsKeyChordPressed(chord); + if (anm2_deserialize(self->anm2, path)) { + window_title_from_path_set(self->window, path); + imgui_log_push(self, std::format(IMGUI_LOG_FILE_OPEN_FORMAT, path)); + } else + imgui_log_push(self, std::format(IMGUI_LOG_FILE_OPEN_FORMAT, path)); } -static const char* _imgui_f32_format_get(const ImguiItem& item, f32& value) -{ - if (item.isEmptyFormat) return ""; - return f32_format_get(value); +static void _imgui_spritesheet_add(Imgui* self, const std::string& path) { + imgui_snapshot(self, IMGUI_ACTION_ADD_SPRITESHEET); + WorkingDirectory workingDirectory(self->anm2->path); + std::string spritesheetPath = path; + std::string anm2WorkingPath = working_directory_from_file_set(self->anm2->path); + spritesheetPath = std::filesystem::relative(path, anm2WorkingPath).string(); + Texture texture; + if (texture_from_path_init(&texture, spritesheetPath)) { + int id = map_next_id_get(self->anm2->spritesheets); + self->anm2->spritesheets[id] = Anm2Spritesheet{}; + self->anm2->spritesheets[id].path = spritesheetPath; + self->anm2->spritesheets[id].texture = texture; + } else + imgui_log_push(self, std::format(IMGUI_LOG_ADD_SPRITESHEET_ERROR, path)); } -static const char* _imgui_vec2_format_get(const ImguiItem& item, vec2& value) -{ - if (item.isEmptyFormat) return ""; - return vec2_format_get(value); +static bool _imgui_is_window_hovered(void) { return ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } +static bool _imgui_is_window_hovered_and_click(void) { return _imgui_is_window_hovered() && ImGui::IsMouseClicked(0); } +static bool _imgui_is_no_click_on_item(void) { return ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered(); } + +static bool _imgui_is_input_begin(void) { + return ImGui::IsItemHovered() && (ImGui::IsKeyPressed(IMGUI_INPUT_RENAME) || ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)); } -static bool _imgui_window_color_from_position_get(SDL_Window* self, const vec2& position, vec4& color) -{ - ImGuiIO& io = ImGui::GetIO(); - ivec2 fbPosition = {(s32)(position.x * io.DisplayFramebufferScale.x), (s32)(position.y * io.DisplayFramebufferScale.y)}; - ivec2 size{}; - SDL_GetWindowSizeInPixels(self, &size.x, &size.y); - - if (fbPosition.x < 0 || fbPosition.y < 0 || fbPosition.x >= size.x || fbPosition.y >= size.y) return false; - - uint8_t rgba[4]; - - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(fbPosition.x, size.y - 1 - fbPosition.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba); - - color = vec4(U8_TO_FLOAT(rgba[0]), U8_TO_FLOAT(rgba[1]), U8_TO_FLOAT(rgba[2]), U8_TO_FLOAT(rgba[3])); - - return true; +static bool _imgui_is_input_default(void) { + return ImGui::IsItemHovered() && (ImGui::IsKeyPressed(IMGUI_INPUT_DEFAULT) || ImGui::IsMouseClicked(IMGUI_MOUSE_DEFAULT)); } -static void _imgui_anm2_open(Imgui* self, const std::string& path) -{ - imgui_anm2_new(self); +static bool _imgui_chord_pressed(ImGuiKeyChord chord) { + if (chord == IMGUI_CHORD_NONE) + return false; + ImGuiKey key = (ImGuiKey)(chord & ~ImGuiMod_Mask_); + if (key == ImGuiKey_None) + return false; + if (key < ImGuiKey_NamedKey_BEGIN || key >= ImGuiKey_NamedKey_END) + return false; - if (anm2_deserialize(self->anm2, path)) - { - window_title_from_path_set(self->window, path); - imgui_log_push(self, std::format(IMGUI_LOG_FILE_OPEN_FORMAT, path)); - } - else - imgui_log_push(self, std::format(IMGUI_LOG_FILE_OPEN_FORMAT, path)); + return ImGui::IsKeyChordPressed(chord); } -static void _imgui_spritesheet_add(Imgui* self, const std::string& path) -{ - if (self->anm2->path.empty()) - { - imgui_log_push(self, IMGUI_LOG_NO_ANM2_PATH); - return; - } +static bool _imgui_is_focus_window(const std::string& focus) { + ImGuiContext* context = ImGui::GetCurrentContext(); + if (!context || !context->NavWindow) + return false; - imgui_snapshot(self, IMGUI_ACTION_ADD_SPRITESHEET); - - std::filesystem::path workingPath = std::filesystem::current_path(); - std::string spritesheetPath = path; - std::string anm2WorkingPath = working_directory_from_file_set(self->anm2->path); - spritesheetPath = std::filesystem::relative(path, anm2WorkingPath).string(); - s32 id = map_next_id_get(self->anm2->spritesheets); - self->anm2->spritesheets[id] = Anm2Spritesheet{}; - self->anm2->spritesheets[id].path = spritesheetPath; - texture_from_path_init(&self->anm2->spritesheets[id].texture, spritesheetPath); - - std::filesystem::current_path(workingPath); + std::string_view name(context->NavWindow->Name); + return name.find(focus) != std::string_view::npos; } -static bool _imgui_is_window_hovered(void) -{ - return ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); +static vec2 _imgui_item_spacing_get(const ImguiItem& self) { return self.itemSpacing.has_value() ? *self.itemSpacing : vec2(ImGui::GetStyle().ItemSpacing); } +static vec2 _imgui_window_padding_get(const ImguiItem& self) { + return self.windowPadding.has_value() ? *self.windowPadding : vec2(ImGui::GetStyle().WindowPadding); +} +static vec2 _imgui_cursor_position_get(const ImguiItem& self) { return self.cursorPosition.has_value() ? *self.cursorPosition : vec2(ImGui::GetCursorPos()); } + +static vec2 _imgui_item_size_get(const ImguiItem& self, ImguiItemType type) { + vec2 size{}; + + if (!self.size.has_value()) { + switch (type) { + case IMGUI_ATLAS_BUTTON: + size = self.size.has_value() ? *self.size : vec2(ATLAS_SIZE(self.atlas)); + break; + default: + if (self.rowCount.has_value()) + size.x = (ImGui::GetWindowSize().x - (_imgui_item_spacing_get(self).x * (*self.rowCount + 1))) / *self.rowCount; + else if (self.isSizeToText) + size.x = (ImGui::CalcTextSize(self.label_get().c_str()).x + ImGui::GetStyle().FramePadding.x); + else if (self.isSizeToRegion) + size.x = ImGui::GetContentRegionAvail().x; + else + size.x = ImGui::CalcItemWidth(); + + if (type != IMGUI_BUTTON) + size.y = ImGui::GetTextLineHeight() + IMGUI_TEXT_HEIGHT_PADDING; + break; + } + } else + size = *self.size; + + return size; } -static bool _imgui_is_window_hovered_and_click(void) -{ - return _imgui_is_window_hovered() && ImGui::IsMouseClicked(0); +static void _imgui_item_style_push(const ImguiItem& self) { + if (self.windowPadding.has_value()) + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, *self.windowPadding); + if (self.itemSpacing.has_value()) + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, *self.itemSpacing); } -static bool _imgui_is_window_hovered_and_click_no_anm2_path(Imgui* self) -{ - return _imgui_is_window_hovered_and_click() && self->anm2->path.empty(); +static void _imgui_item_style_pop(const ImguiItem& self) { + if (self.windowPadding.has_value()) + ImGui::PopStyleVar(); + if (self.itemSpacing.has_value()) + ImGui::PopStyleVar(); } -static bool _imgui_is_no_click_on_item(void) -{ - return ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered(); +static const char* _imgui_float_format_get(const ImguiItem& item, float& value) { + if (item.isEmptyFormat) + return ""; + return float_format_get(value); } -static bool _imgui_is_input_begin(void) -{ - return ImGui::IsItemHovered() && (ImGui::IsKeyPressed(IMGUI_INPUT_RENAME) || ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)); +static const char* _imgui_vec2_format_get(const ImguiItem& item, vec2& value) { + if (item.isEmptyFormat) + return ""; + return vec2_format_get(value); } -static bool _imgui_is_input_default(void) -{ - return ImGui::IsItemHovered() && (ImGui::IsKeyPressed(IMGUI_INPUT_DEFAULT) || ImGui::IsMouseClicked(IMGUI_MOUSE_DEFAULT)); +static void _imgui_item_pre(const ImguiItem& self, ImguiItemType type) { + switch (type) { + case IMGUI_ITEM: + case IMGUI_TEXT: + case IMGUI_WINDOW: + case IMGUI_DOCKSPACE: + case IMGUI_BEGIN_CHILD: + case IMGUI_END_CHILD: + case IMGUI_CONFIRM_POPUP: + case IMGUI_TABLE: + break; + default: + ImGui::BeginDisabled(self.isDisabled); + break; + } + + switch (type) { + case IMGUI_SELECTABLE: + case IMGUI_INPUT_INT: + case IMGUI_INPUT_TEXT: + case IMGUI_INPUT_FLOAT: + case IMGUI_DRAG_FLOAT: + case IMGUI_SLIDER_FLOAT: + case IMGUI_COLOR_EDIT: + ImGui::SetNextItemWidth(_imgui_item_size_get(self, type).x); + break; + default: + break; + } + + switch (type) { + case IMGUI_BUTTON: + case IMGUI_ATLAS_BUTTON: + if (self.border.has_value()) { + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, *self.border); + if (self.color.border.has_value()) + ImGui::PushStyleColor(ImGuiCol_Border, *self.color.border); + } + break; + default: + break; + } + + switch (type) { + case IMGUI_BEGIN_CHILD: + if (self.color.normal.has_value()) + ImGui::PushStyleColor(ImGuiCol_ChildBg, *self.color.normal); + break; + case IMGUI_SELECTABLE: + if (self.isSelected && self.color.normal.has_value()) + ImGui::PushStyleColor(ImGuiCol_Header, *self.color.normal); + break; + case IMGUI_BUTTON: + case IMGUI_ATLAS_BUTTON: + if (self.color.normal.has_value()) + ImGui::PushStyleColor(ImGuiCol_Button, *self.color.normal); + if (self.color.active.has_value()) + ImGui::PushStyleColor(ImGuiCol_ButtonActive, *self.color.active); + if (self.color.hovered.has_value()) + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, *self.color.hovered); + if (self.isSelected) { + if (self.color.active.has_value()) + ImGui::PushStyleColor(ImGuiCol_Button, *self.color.active); + else + ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]); + } + break; + default: + break; + } + + switch (type) { + case IMGUI_END_CHILD: + break; + default: + _imgui_item_style_push(self); + break; + } + + switch (type) { + case IMGUI_WINDOW: + break; + default: + ImGui::SetCursorPos(self.cursorPosition.value_or(vec2(ImGui::GetCursorPos())) + self.cursorOffset); + break; + } } -static bool _imgui_is_focus_window(const std::string& focus) -{ - ImGuiContext* ctx = ImGui::GetCurrentContext(); - if (!ctx || !ctx->NavWindow) return false; +static void _imgui_item_post(const ImguiItem& self, Imgui* imgui, ImguiItemType type, bool& isActivated) { + if (self.is_mnemonic() && !self.isMnemonicDisabled) { + ImVec2 position = ImGui::GetItemRectMin(); + ImFont* font = ImGui::GetFont(); + float fontSize = ImGui::GetFontSize(); + const char* start = self.label.c_str(); + const char* charPointer = start + self.mnemonicIndex; - std::string_view name(ctx->NavWindow->Name); - return name.find(focus) != std::string_view::npos; + position.x += ImGui::GetStyle().FramePadding.x; + + float offset = font->CalcTextSizeA(fontSize, FLT_MAX, 0.0f, start, charPointer).x; + float charWidth = font->CalcTextSizeA(fontSize, FLT_MAX, 0.0f, charPointer, charPointer + 1).x; + + ImVec2 lineStart = ImVec2(position.x + offset, position.y + fontSize + 1.0f); + ImVec2 lineEnd = ImVec2(lineStart.x + charWidth, lineStart.y); + + ImU32 color = ImGui::GetColorU32(ImGuiCol_Text); + ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, color, 1.0f); + + if (_imgui_chord_pressed(ImGuiMod_Alt | self.mnemonicKey)) { + if (!self.isDisabled) + isActivated = true; + imgui_close_current_popup(imgui); + } + } + + if (self.isUseItemActivated && !self.isDisabled) + isActivated = ImGui::IsItemActivated(); + + if (imgui->isContextualActionsEnabled && _imgui_chord_pressed(self.chord_get()) && + (self.focusWindow.has_value() && _imgui_is_focus_window(*self.focusWindow))) + if (!self.isDisabled) + isActivated = true; + + if (!self.tooltip.empty() && ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) { + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, imgui->style.WindowPadding); + ImGui::SetTooltip("%s", self.tooltip_get().c_str()); + ImGui::PopStyleVar(); + } + + if (isActivated) { + if (self.snapshotAction.has_value()) + imgui_snapshot(imgui, *self.snapshotAction); + if (self.function) + self.function(imgui); + + if (!self.popup.empty()) { + imgui->pendingPopup = self.popup; + imgui->pendingPopupType = self.popupType; + imgui->pendingPopupPosition = ImVec2(ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y + ImGui::GetItemRectSize().y); + } + } + + switch (type) { + case IMGUI_END_CHILD: + if (self.color.normal.has_value()) + ImGui::PopStyleColor(); + break; + case IMGUI_SELECTABLE: + if (self.isSelected && self.color.normal.has_value()) + ImGui::PopStyleColor(); + break; + case IMGUI_BUTTON: + case IMGUI_ATLAS_BUTTON: + if (self.color.normal.has_value()) + ImGui::PopStyleColor(); + if (self.color.active.has_value()) + ImGui::PopStyleColor(); + if (self.color.hovered.has_value()) + ImGui::PopStyleColor(); + if (self.isSelected) + ImGui::PopStyleColor(); + break; + default: + break; + } + + switch (type) { + case IMGUI_BUTTON: + case IMGUI_ATLAS_BUTTON: + if (self.border.has_value()) { + ImGui::PopStyleVar(); + if (self.color.border.has_value()) + ImGui::PopStyleColor(); + } + default: + break; + } + + switch (type) { + case IMGUI_ITEM: + case IMGUI_TEXT: + case IMGUI_WINDOW: + case IMGUI_DOCKSPACE: + case IMGUI_BEGIN_CHILD: + case IMGUI_END_CHILD: + case IMGUI_CONFIRM_POPUP: + case IMGUI_TABLE: + break; + default: + ImGui::EndDisabled(); + } + + if (self.isSameLine) + ImGui::SameLine(); + if (self.isSeparator) + ImGui::Separator(); + + switch (type) { + case IMGUI_BEGIN_CHILD: + break; + default: + _imgui_item_style_pop(self); + break; + } } -static void _imgui_atlas(const AtlasType& self, Imgui* imgui) -{ - ImGui::Image(imgui->resources->atlas.id, ATLAS_SIZE(self), ATLAS_UV_ARGS(self)); -} +#define IMGUI_ITEM_BASE(NAME, TYPE, BODY) \ + static bool NAME(const ImguiItem& self, Imgui* imgui) { \ + ImguiItemType type = TYPE; \ + _imgui_item_pre(self, type); \ + bool isActivated = false; \ + do { \ + BODY \ + } while (0); \ + _imgui_item_post(self, imgui, type, isActivated); \ + return isActivated; \ + } -static ImVec2 _imgui_item_size_get(const ImguiItem& self, ImguiItemType type) -{ - ImVec2 size = self.size; +#define IMGUI_ITEM_VALUE_BASE(NAME, TYPE, VALUE_TYPE, BODY) \ + static bool NAME(const ImguiItem& self, Imgui* imgui, VALUE_TYPE& inValue) { \ + ImguiItemType type = TYPE; \ + _imgui_item_pre(self, type); \ + bool isActivated = false; \ + do { \ + VALUE_TYPE value = inValue; \ + BODY if (_imgui_is_input_default()) { \ + value = VALUE_TYPE(self.value); \ + isActivated = true; \ + } \ + inValue = value; \ + } while (0); \ + _imgui_item_post(self, imgui, type, isActivated); \ + return isActivated; \ + } - switch (type) - { - case IMGUI_ATLAS_BUTTON: - size = self.is_size() ? self.size : ImVec2(ATLAS_SIZE(self.atlas)); - break; - default: - if (self.is_row()) - size.x = (ImGui::GetWindowSize().x - (ImGui::GetStyle().ItemSpacing.x * (self.rowCount + 1))) / self.rowCount; - else if (self.isSizeToText) - size.x = (ImGui::CalcTextSize(self.label_get().c_str()).x + ImGui::GetStyle().FramePadding.x); - else if (!self.is_size()) - size.x = ImGui::CalcItemWidth(); - break; - } +#define IMGUI_ITEM_VOID_FUNCTION(NAME, TYPE, BODY) IMGUI_ITEM_BASE(NAME, TYPE, { ([&] { BODY; })(); }) +#define IMGUI_ITEM_BOOL_FUNCTION(NAME, TYPE, BODY) IMGUI_ITEM_BASE(NAME, TYPE, { isActivated = ([&] { return BODY; })(); }) +#define IMGUI_ITEM_VALUE_FUNCTION(NAME, TYPE, VALUE_TYPE, BODY) IMGUI_ITEM_VALUE_BASE(NAME, TYPE, VALUE_TYPE, { isActivated = ([&] { return BODY; })(); }) - return size; -} +#define IMGUI_ITEM_VALUE_CLAMP_FUNCTION(NAME, TYPE, VALUE_TYPE, BODY) \ + IMGUI_ITEM_VALUE_BASE(NAME, TYPE, VALUE_TYPE, { \ + isActivated = ([&] { return BODY; })(); \ + if (self.is_range()) \ + value = glm::clamp(value, VALUE_TYPE(*self.min), VALUE_TYPE(*self.max)); \ + }) -static void _imgui_item_pre(const ImguiItem& self, ImguiItemType type) -{ - ImVec2 size = _imgui_item_size_get(self, type); +#define IMGUI_ITEM_STRING_FUNCTION(NAME, TYPE, BODY) \ + static bool NAME(const ImguiItem& self, Imgui* imgui, std::string& inValue) { \ + ImguiItemType type = TYPE; \ + _imgui_item_pre(self, type); \ + bool isActivated = false; \ + do { \ + std::string value = inValue; \ + isActivated = ([&] { return BODY; })(); \ + /* no VALUE_TYPE(self.value) here, strings don’t come from self.value */ \ + inValue = value; \ + } while (0); \ + _imgui_item_post(self, imgui, type, isActivated); \ + return isActivated; \ + } - switch (type) - { - case IMGUI_ITEM: - case IMGUI_TEXT: - case IMGUI_WINDOW: - case IMGUI_DOCKSPACE: - case IMGUI_CHILD: - case IMGUI_CONFIRM_POPUP: - break; - default: - ImGui::BeginDisabled(self.isDisabled); - } - - switch (type) - { - case IMGUI_CHILD: - if (self.color.is_normal()) ImGui::PushStyleColor(ImGuiCol_ChildBg, self.color.normal); - break; - case IMGUI_INPUT_INT: - case IMGUI_INPUT_TEXT: - case IMGUI_INPUT_FLOAT: - case IMGUI_DRAG_FLOAT: - case IMGUI_SLIDER_FLOAT: - case IMGUI_COLOR_EDIT: - ImGui::SetNextItemWidth(size.x); - break; - case IMGUI_BUTTON: - case IMGUI_ATLAS_BUTTON: - if (self.is_border()) - { - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, self.border); - if (self.color.is_border()) ImGui::PushStyleColor(ImGuiCol_Border, self.color.border); - } - if (self.color.is_normal()) ImGui::PushStyleColor(ImGuiCol_Button, self.color.normal); - if (self.color.is_active()) ImGui::PushStyleColor(ImGuiCol_ButtonActive, self.color.active); - if (self.color.is_hovered()) ImGui::PushStyleColor(ImGuiCol_ButtonHovered, self.color.hovered); - if (self.isSelected) - { - if (self.color.is_active()) - ImGui::PushStyleColor(ImGuiCol_Button, self.color.active); - else - ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]); - } - break; - default: - break; - } -} +IMGUI_ITEM_VOID_FUNCTION(_imgui_dockspace, IMGUI_DOCKSPACE, ImGui::DockSpace(ImGui::GetID(self.label_get().c_str()), *self.size, self.flags)); +IMGUI_ITEM_VOID_FUNCTION(_imgui_begin_child, IMGUI_BEGIN_CHILD, ImGui::BeginChild(self.label_get().c_str(), *self.size, self.flags, self.windowFlags)); +IMGUI_ITEM_VOID_FUNCTION(_imgui_end_child, IMGUI_END_CHILD, ImGui::EndChild()); +IMGUI_ITEM_VOID_FUNCTION(_imgui_text, IMGUI_TEXT, ImGui::Text("%s", self.label_get().c_str())); +IMGUI_ITEM_BOOL_FUNCTION(_imgui_button, IMGUI_BUTTON, ImGui::Button(self.label_get().c_str(), _imgui_item_size_get(self, type))); +IMGUI_ITEM_BOOL_FUNCTION(_imgui_begin_table, IMGUI_TABLE, ImGui::BeginTable(self.label_get().c_str(), self.value, self.flags)); +IMGUI_ITEM_BOOL_FUNCTION(_imgui_selectable, IMGUI_SELECTABLE, + ImGui::Selectable(self.label_get().c_str(), self.isSelected, self.flags, _imgui_item_size_get(self, type))); +IMGUI_ITEM_BOOL_FUNCTION(_imgui_begin, IMGUI_WINDOW, ImGui::Begin(self.label_get().c_str(), nullptr, self.flags)); +IMGUI_ITEM_VOID_FUNCTION(_imgui_image, IMGUI_IMAGE, ImGui::Image(self.textureID, _imgui_item_size_get(self, IMGUI_IMAGE), self.uvMin, self.uvMax)); -static void _imgui_item_post(const ImguiItem& self, Imgui* imgui, ImguiItemType type, bool& isActivated) -{ - if (self.is_mnemonic() && !self.isMnemonicDisabled) - { - ImVec2 position = ImGui::GetItemRectMin(); - ImFont* font = ImGui::GetFont(); - f32 fontSize = ImGui::GetFontSize(); - const char* start = self.label.c_str(); - const char* charPointer = start + self.mnemonicIndex; - - position.x += ImGui::GetStyle().FramePadding.x; - - f32 offset = font->CalcTextSizeA(fontSize, FLT_MAX, 0.0f, start, charPointer).x; - f32 charWidth = font->CalcTextSizeA(fontSize, FLT_MAX, 0.0f, charPointer, charPointer + 1).x; - - ImVec2 lineStart = ImVec2(position.x + offset, position.y + fontSize + 1.0f); - ImVec2 lineEnd = ImVec2(lineStart.x + charWidth, lineStart.y); - - ImU32 color = ImGui::GetColorU32(ImGuiCol_Text); - ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, color, 1.0f); - - if (_imgui_chord_pressed(ImGuiMod_Alt | self.mnemonicKey)) - { - if (!self.isDisabled) isActivated = true; - imgui_close_current_popup(imgui); - } - } - - if (self.isUseItemActivated && !self.isDisabled) isActivated = ImGui::IsItemActivated(); - - if - ( - imgui->isContextualActionsEnabled && _imgui_chord_pressed(self.chord_get()) && - (self.is_focus_window() && _imgui_is_focus_window(self.focusWindow)) - ) - if (!self.isDisabled) isActivated = true; - - if (self.is_tooltip() && ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) - ImGui::SetTooltip(self.tooltip_get().c_str()); - - if (isActivated) - { - if (self.is_undoable()) imgui_snapshot(imgui, self.snapshotAction); - if (self.is_function()) self.function(imgui); - - if (self.is_popup()) - { - imgui->pendingPopup = self.popup; - imgui->pendingPopupType = self.popupType; - imgui->pendingPopupPosition = ImVec2(ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y + ImGui::GetItemRectSize().y); - } - } - - switch (type) - { - case IMGUI_CHILD: - if (self.color.is_normal()) ImGui::PopStyleColor(); - break; - case IMGUI_BUTTON: - case IMGUI_ATLAS_BUTTON: - if (self.is_border()) - { - ImGui::PopStyleVar(); - if (self.color.is_border()) ImGui::PopStyleColor(); - } - if (self.color.is_normal()) ImGui::PopStyleColor(); - if (self.color.is_active()) ImGui::PopStyleColor(); - if (self.color.is_hovered()) ImGui::PopStyleColor(); - if (self.isSelected) ImGui::PopStyleColor(); - break; - default: - break; - } - - switch (type) - { - case IMGUI_ITEM: - case IMGUI_TEXT: - case IMGUI_WINDOW: - case IMGUI_DOCKSPACE: - case IMGUI_CHILD: - case IMGUI_CONFIRM_POPUP: - break; - default: - ImGui::EndDisabled(); - } - - if (self.isSameLine) ImGui::SameLine(); - if (self.isSeparator) ImGui::Separator(); -} - -#define IMGUI_ITEM_FUNCTION(NAME, TYPE, FUNCTION) \ -static bool NAME(ImguiItem self, Imgui* imgui) \ -{ \ - ImguiItemType type = TYPE; \ - _imgui_item_pre(self, type); \ - bool isActivated = ([&] { return FUNCTION; })(); \ - _imgui_item_post(self, imgui, type, isActivated); \ - return isActivated; \ -} - -#define IMGUI_ITEM_VOID_FUNCTION(NAME, TYPE, FUNCTION) \ -static void NAME(const ImguiItem& self, Imgui* imgui) \ -{ \ - ImguiItemType type = TYPE; \ - bool isActivated = false; \ - _imgui_item_pre(self, type); \ - ([&] { FUNCTION; })(); \ - _imgui_item_post(self, imgui, type, isActivated); \ -} - -#define IMGUI_ITEM_VALUE_FUNCTION(NAME, TYPE, VALUE, FUNCTION) \ -static bool NAME(const ImguiItem& self, Imgui* imgui, VALUE& inValue) \ -{ \ - ImguiItemType type = TYPE; \ - VALUE value = inValue; \ - _imgui_item_pre(self, type); \ - bool isActivated = ([&](VALUE& value) { return FUNCTION; })(value); \ - if (_imgui_is_input_default()) \ - { \ - value = VALUE(self.value); \ - isActivated = true; \ - } \ - _imgui_item_post(self, imgui, type, isActivated); \ - inValue = value; \ - return isActivated; \ -} - -#define IMGUI_ITEM_VALUE_CLAMP_FUNCTION(NAME, TYPE, VALUE, FUNCTION) \ -static bool NAME(const ImguiItem& self, Imgui* imgui, VALUE& inValue) \ -{ \ - ImguiItemType type = TYPE; \ - VALUE value = inValue; \ - _imgui_item_pre(self, type); \ - bool isActivated = ([&](VALUE& value) { return FUNCTION; })(value); \ - if (_imgui_is_input_default()) \ - { \ - value = VALUE(self.value); \ - isActivated = true; \ - } \ - if (self.is_range()) value = glm::clamp(value, VALUE(self.min), VALUE(self.max)); \ - _imgui_item_post(self, imgui, type, isActivated); \ - inValue = value; \ - return isActivated; \ -} - -#define IMGUI_ITEM_CUSTOM_FUNCTION(NAME, TYPE, BODY) \ -static bool NAME(const ImguiItem& self, Imgui* imgui) \ -{ \ - ImguiItemType type = TYPE; \ - _imgui_item_pre(self, type); \ - bool isActivated = false; \ - do { BODY } while (0); \ - _imgui_item_post(self, imgui, type, isActivated); \ - return isActivated; \ -} - -#define IMGUI_ITEM_CUSTOM_FUNCTION_WITH_VALUE(NAME, TYPE, VALUE, BODY) \ -static bool NAME(const ImguiItem& self, Imgui* imgui, VALUE& inValue) \ -{ \ - ImguiItemType type = TYPE; \ - _imgui_item_pre(self, type); \ - bool isActivated = false; \ - do { BODY } while (0); \ - _imgui_item_post(self, imgui, type, isActivated); \ - return isActivated; \ -} - -#define IMGUI_ITEM_ATLAS_FUNCTION(NAME, FUNCTION) \ -static bool NAME(const ImguiItem& self, Imgui* imgui) \ -{ \ - _imgui_atlas(self.atlas, imgui); \ - ImGui::SameLine(); \ - bool isActivated = ([&] { return FUNCTION; })(); \ - return isActivated; \ -} - -#define IMGUI_ITEM_ATLAS_VALUE_FUNCTION(NAME, VALUE, FUNCTION) \ -static bool NAME(const ImguiItem& self, Imgui* imgui, VALUE& value) \ -{ \ - _imgui_atlas(self.atlas, imgui); \ - ImGui::SameLine(); \ - bool isActivated = ([&](VALUE& value) { return FUNCTION; })(value); \ - return isActivated; \ -} - -#define IMGUI_ITEM_CHECKBOX_FUNCTION(NAME, FUNCTION) \ -static bool NAME(const ImguiItem& self, Imgui* imgui, bool& boolValue) \ -{ \ - ImguiItem checkboxItem = self.copy \ - ({.label = std::format(IMGUI_INVISIBLE_FORMAT, self.label), .isMnemonicDisabled = true}); \ - checkboxItem.isDisabled = false; \ - checkboxItem.isSeparator = false; \ - checkboxItem.value = 0; \ - bool isCheckboxActivated = _imgui_checkbox(checkboxItem, imgui, boolValue); \ - ImGui::SameLine(); \ - bool isActivated = ([&] { return FUNCTION; })(); \ - if (isActivated) boolValue = !boolValue; \ - if (isCheckboxActivated) isActivated = true; \ - return isActivated; \ -} - -#define IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(NAME, VALUE, FUNCTION) \ -static bool NAME(const ImguiItem& self, Imgui* imgui, VALUE& value, bool& boolValue) \ -{ \ - ImguiItem checkboxItem = self.copy \ - ({.label = std::format(IMGUI_INVISIBLE_FORMAT, self.label), .isMnemonicDisabled = true}); \ - checkboxItem.isDisabled = false; \ - checkboxItem.isSeparator = false; \ - checkboxItem.value = 0; \ - bool isCheckboxActivated = _imgui_checkbox(checkboxItem, imgui, boolValue); \ - ImGui::SameLine(); \ - bool isActivated = ([&](VALUE& value) { return FUNCTION; })(value); \ - if (isCheckboxActivated) isActivated = true; \ - return isActivated; \ -} - -#define IMGUI_ITEM_AND_CHECKBOX_FUNCTION(NAME, VALUE, FUNCTION) \ -static bool NAME(const ImguiItem& self, const ImguiItem& checkboxItem, Imgui* imgui, VALUE& value, bool& boolValue) \ -{ \ - bool isCheckboxActivated = _imgui_checkbox(checkboxItem, imgui, boolValue); \ - ImGui::SameLine(); \ - bool isActivated = ([&](VALUE& value) { return FUNCTION; })(value); \ - if (isCheckboxActivated) isActivated = true; \ - return isActivated; \ -} - -#define IMGUI_ITEM_DISABLED_GET(VALUE, ITEM, CONDITION) ImguiItem VALUE = ITEM; VALUE.isDisabled = CONDITION; - -IMGUI_ITEM_FUNCTION(_imgui_begin, IMGUI_WINDOW, ImGui::Begin(self.label_get().c_str(), nullptr, self.flags)); -#define IMGUI_BEGIN_OR_RETURN(item, imgui) if (!_imgui_begin(item, imgui)) { _imgui_end(); return; } -static void _imgui_end(void){ImGui::End();} -IMGUI_ITEM_VOID_FUNCTION(_imgui_dockspace, IMGUI_DOCKSPACE, ImGui::DockSpace(ImGui::GetID(self.label_get().c_str()), self.size, self.flags)); -IMGUI_ITEM_FUNCTION(_imgui_begin_child, IMGUI_CHILD, ImGui::BeginChild(self.label_get().c_str(), self.size, self.flags, self.windowFlags)); -static void _imgui_end_child(void) {ImGui::EndChild(); } -IMGUI_ITEM_VOID_FUNCTION(_imgui_text, IMGUI_TEXT, ImGui::Text(self.label_get().c_str())); -IMGUI_ITEM_FUNCTION(_imgui_button, IMGUI_BUTTON, ImGui::Button(self.label_get().c_str(), _imgui_item_size_get(self, type))); -IMGUI_ITEM_FUNCTION(_imgui_begin_table, IMGUI_TABLE, ImGui::BeginTable(self.label_get().c_str(), self.value, self.flags)); -static void _imgui_end_table(void) {ImGui::EndTable(); } -static void _imgui_table_setup_column(const char* text) {ImGui::TableSetupColumn(text); } -static void _imgui_table_headers_row(void) {ImGui::TableHeadersRow(); } -static void _imgui_table_next_row(void) {ImGui::TableNextRow(); } -static void _imgui_table_set_column_index(s32 index) {ImGui::TableSetColumnIndex(index); } -IMGUI_ITEM_FUNCTION(_imgui_selectable, IMGUI_SELECTABLE, ImGui::Selectable(self.label_get().c_str(), self.isSelected, self.flags, _imgui_item_size_get(self, type))); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_radio_button, IMGUI_RADIO_BUTTON, s32, ImGui::RadioButton(self.label_get().c_str(), &value, self.value)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_button, IMGUI_COLOR_BUTTON, vec4, ImGui::ColorButton(self.label_get().c_str(), ImVec4(value), self.flags)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_checkbox, IMGUI_CHECKBOX, bool, ImGui::Checkbox(self.label_get().c_str(), &value)); -IMGUI_ITEM_VALUE_CLAMP_FUNCTION(_imgui_input_int, IMGUI_INPUT_INT, s32, ImGui::InputInt(self.label_get().c_str(), &value, self.step, self.stepFast, self.flags)); +IMGUI_ITEM_VALUE_CLAMP_FUNCTION(_imgui_input_int, IMGUI_INPUT_INT, int, + ImGui::InputInt(self.label_get().c_str(), &value, self.step, self.stepFast, self.flags)); IMGUI_ITEM_VALUE_CLAMP_FUNCTION(_imgui_input_int2, IMGUI_INPUT_INT, ivec2, ImGui::InputInt2(self.label_get().c_str(), value_ptr(value), self.flags)); -IMGUI_ITEM_VALUE_CLAMP_FUNCTION(_imgui_input_float, IMGUI_INPUT_FLOAT, f32, ImGui::InputFloat(self.label_get().c_str(), &value, self.step, self.stepFast, _imgui_f32_format_get(self, value), self.flags)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_slider_float, IMGUI_SLIDER_FLOAT, f32, ImGui::SliderFloat(self.label_get().c_str(), &value, self.min, self.max, _imgui_f32_format_get(self, value), self.flags)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_drag_float, IMGUI_DRAG_FLOAT, f32, ImGui::DragFloat(self.label_get().c_str(), &value, self.speed, self.min, self.max, _imgui_f32_format_get(self, value))); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_drag_float2, IMGUI_DRAG_FLOAT, vec2, ImGui::DragFloat2(self.label_get().c_str(), value_ptr(value), self.speed, self.min, self.max, _imgui_vec2_format_get(self, value))); +IMGUI_ITEM_VALUE_CLAMP_FUNCTION(_imgui_input_float, IMGUI_INPUT_FLOAT, float, + ImGui::InputFloat(self.label_get().c_str(), &value, self.step, self.stepFast, _imgui_float_format_get(self, value), + self.flags)); +IMGUI_ITEM_VALUE_FUNCTION(_imgui_checkbox, IMGUI_CHECKBOX, bool, ImGui::Checkbox(self.label_get().c_str(), &value)); +IMGUI_ITEM_VALUE_FUNCTION(_imgui_slider_float, IMGUI_SLIDER_FLOAT, float, + ImGui::SliderFloat(self.label_get().c_str(), &value, *self.min, *self.max, _imgui_float_format_get(self, value), self.flags)); + +IMGUI_ITEM_STRING_FUNCTION(_imgui_input_text, IMGUI_INPUT_TEXT, + (value.resize(*self.max), ImGui::InputText(self.label_get().c_str(), value.data(), *self.max, self.flags))); + +#define IMGUI_BEGIN_OR_RETURN(item, imgui) \ + if (!_imgui_begin(item, imgui)) { \ + _imgui_end(); \ + return; \ + } + +/* +IMGUI_ITEM_VALUE_FUNCTION(_imgui_radio_button, IMGUI_RADIO_BUTTON, int, ImGui::RadioButton(self.label_get().c_str(), &value, self.value)); +IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_button, IMGUI_COLOR_BUTTON, vec4, ImGui::ColorButton(self.label_get().c_str(), ImVec4(value), self.flags)); + +IMGUI_ITEM_VALUE_FUNCTION(_imgui_drag_float, IMGUI_DRAG_FLOAT, float, + ImGui::DragFloat(self.label_get().c_str(), &value, self.speed, *self.min, *self.max, _imgui_float_format_get(self, value))); +IMGUI_ITEM_VALUE_FUNCTION(_imgui_drag_float2, IMGUI_DRAG_FLOAT, vec2, + ImGui::DragFloat2(self.label_get().c_str(), value_ptr(value), self.speed, *self.min, *self.max, _imgui_vec2_format_get(self, value))); IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_edit3, IMGUI_COLOR_EDIT, vec3, ImGui::ColorEdit3(self.label_get().c_str(), value_ptr(value), self.flags)); IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_edit4, IMGUI_COLOR_EDIT, vec4, ImGui::ColorEdit4(self.label_get().c_str(), value_ptr(value), self.flags)); +*/ + +/* IMGUI_ITEM_CHECKBOX_FUNCTION(_imgui_checkbox_selectable, _imgui_selectable(self, imgui)); IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_checkbox, bool, _imgui_checkbox(self, imgui, value)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_input_int, s32, _imgui_input_int(self, imgui, value)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_drag_float, f32, _imgui_drag_float(self, imgui, value)); +IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_input_int, int, _imgui_input_int(self, imgui, value)); +IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_drag_float, float, _imgui_drag_float(self, imgui, value)); IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_drag_float2, vec2, _imgui_drag_float2(self, imgui, value)); IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_color_edit3, vec3, _imgui_color_edit3(self, imgui, value)); IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_color_edit4, vec4, _imgui_color_edit4(self, imgui, value)); +*/ -static bool _imgui_input_text(const ImguiItem& self, Imgui* imgui, std::string& value) -{ - value.resize(self.max); - _imgui_item_pre(self, IMGUI_INPUT_TEXT); - bool isActivated = ImGui::InputText(self.label_get().c_str(), value.data(), self.max, self.flags); - _imgui_item_post(self, imgui, IMGUI_INPUT_TEXT, isActivated); - return isActivated; -} +static void _imgui_end(void) { ImGui::End(); } +static void _imgui_end_table(void) { ImGui::EndTable(); } +static void _imgui_table_setup_column(const char* text) { ImGui::TableSetupColumn(text); } +static void _imgui_table_headers_row(void) { ImGui::TableHeadersRow(); } +static void _imgui_table_next_row(void) { ImGui::TableNextRow(); } +static void _imgui_table_set_column_index(int index) { ImGui::TableSetColumnIndex(index); } -static bool _imgui_combo(ImguiItem self, Imgui* imgui, s32* value) -{ - std::vector cStrings; - cStrings.reserve(self.items.size()); - for (auto& string : self.items) - cStrings.emplace_back(string.c_str()); +static bool _imgui_combo(ImguiItem self, Imgui* imgui, int* value) { + std::vector cStrings; + cStrings.reserve(self.items.size()); + for (auto& string : self.items) + cStrings.emplace_back(string.c_str()); - _imgui_item_pre(self, IMGUI_COMBO); + _imgui_item_pre(self, IMGUI_COMBO); - bool isActivated = ImGui::Combo(self.label_get().c_str(), value, cStrings.data(), (s32)self.items.size()); - if (_imgui_is_input_default()) - { - *value = self.value; - isActivated = true; - } + bool isActivated = ImGui::Combo(self.label_get().c_str(), value, cStrings.data(), (int)self.items.size()); + if (_imgui_is_input_default()) { + *value = self.value; + isActivated = true; + } - _imgui_item_post(self, imgui, IMGUI_COMBO, isActivated); - - return isActivated; + _imgui_item_post(self, imgui, IMGUI_COMBO, isActivated); + + return isActivated; }; -IMGUI_ITEM_CUSTOM_FUNCTION(_imgui_atlas_button, IMGUI_ATLAS_BUTTON, -{ - ImVec2 size = _imgui_item_size_get(self, type); +static void _imgui_atlas_text(const ImguiItem& self, Imgui* imgui) { + _imgui_image(self.copy({.textureID = imgui->resources->atlas.id, + .size = ATLAS_SIZE(self.atlas) * imgui->settings->displayScale, + .uvMin = ATLAS_UV_MIN(self.atlas), + .uvMax = ATLAS_UV_MAX(self.atlas)}), + imgui); - if (self.is_size()) - { - isActivated = ImGui::Button(self.label_get().c_str(), size); - - ImVec2 start = ImGui::GetItemRectMin() + self.atlasOffset; - ImVec2 end = start + ImVec2(ATLAS_SIZE(self.atlas)); + _imgui_text(self.copy({.cursorPosition = _imgui_cursor_position_get(self) + + vec2(ATLAS_SIZE(self.atlas).x + (_imgui_item_spacing_get(self).x * imgui->settings->displayScale), 0.0f)}), + imgui); +} - ImGui::GetWindowDrawList()->AddImage(imgui->resources->atlas.id, start, end, ATLAS_UV_ARGS(self.atlas)); - } - else - isActivated = ImGui::ImageButton(self.label_get().c_str(), imgui->resources->atlas.id, size, ATLAS_UV_ARGS(self.atlas)); +/* +IMGUI_ITEM_CUSTOM_FUNCTION(_imgui_atlas_button, IMGUI_ATLAS_BUTTON, { + ImVec2 size = _imgui_item_size_get(self, type); + + if (self.size.has_value()) { + isActivated = ImGui::Button(self.label_get().c_str(), size); + + ImVec2 start = ImGui::GetItemRectMin() + self.atlasOffset; + ImVec2 end = start + ImVec2(ATLAS_SIZE(self.atlas)); + + ImGui::GetWindowDrawList()->AddImage(imgui->resources->atlas.id, start, end, ATLAS_UV_ARGS(self.atlas)); + } else + isActivated = ImGui::ImageButton(self.label_get().c_str(), imgui->resources->atlas.id, size, ATLAS_UV_ARGS(self.atlas)); }); +*/ -static bool _imgui_selectable_input_int(const ImguiItem& self, Imgui* imgui, s32& value) -{ - static s32 temp; - static s32 id = ID_NONE; - ImguiItem selectable = self.copy({.label = std::format(IMGUI_SELECTABLE_INPUT_INT_FORMAT, value)}); - ImVec2 size = _imgui_item_size_get(selectable, IMGUI_SELECTABLE); - bool isActivated = false; - - if (id == self.id) - { - isActivated = _imgui_input_int(IMGUI_CHANGE_INPUT_INT.copy({.size = size}), imgui, temp); - imgui_contextual_actions_disable(imgui); - - if (isActivated || _imgui_is_no_click_on_item()) - { - value = temp; - id = ID_NONE; - imgui_contextual_actions_enable(imgui); - } - } - else - { - isActivated = _imgui_selectable(selectable, imgui); - - if (_imgui_is_input_begin()) - { - temp = value; - id = self.id; - ImGui::SetKeyboardFocusHere(-1); - } - } +/* +static bool _imgui_selectable_input_int(const ImguiItem& self, Imgui* imgui, int& value) { + static int temp; + static int id = ID_NONE; + ImguiItem selectable = self.copy({.label = std::format(IMGUI_SELECTABLE_INPUT_INT_FORMAT, value)}); + ImVec2 size = _imgui_item_size_get(selectable, IMGUI_SELECTABLE); + bool isActivated = false; - return isActivated; + if (id == self.id) { + isActivated = _imgui_input_int(IMGUI_CHANGE_INPUT_INT.copy({.size = size}), imgui, temp); + imgui_contextual_actions_disable(imgui); + + if (isActivated || _imgui_is_no_click_on_item()) { + value = temp; + id = ID_NONE; + imgui_contextual_actions_enable(imgui); + } + } else { + isActivated = _imgui_selectable(selectable, imgui); + + if (_imgui_is_input_begin()) { + temp = value; + id = self.id; + ImGui::SetKeyboardFocusHere(-1); + } + } + + return isActivated; }; -static bool _imgui_selectable_input_text(const ImguiItem& self, Imgui* imgui, std::string& value) -{ - static std::string buffer{}; - static s32 id = ID_NONE; - ImguiItem selectable = self.copy({}); - ImVec2 size = _imgui_item_size_get(selectable, IMGUI_SELECTABLE); - bool isActivated = false; - - if (id == self.id) - { - isActivated = _imgui_input_text(IMGUI_CHANGE_INPUT_TEXT.copy({.size = size}), imgui, buffer); - imgui_contextual_actions_disable(imgui); - - if (isActivated || _imgui_is_no_click_on_item()) - { - value = buffer; - buffer.clear(); - id = ID_NONE; - imgui_contextual_actions_enable(imgui); - } - } - else - { - isActivated = _imgui_selectable(selectable, imgui); - - if (_imgui_is_input_begin()) - { - buffer = value; - buffer.resize(IMGUI_CHANGE_INPUT_TEXT.max); - id = self.id; - ImGui::SetKeyboardFocusHere(-1); - } - } +static bool _imgui_selectable_input_text(const ImguiItem& self, Imgui* imgui, std::string& value) { + static std::string buffer{}; + static int id = ID_NONE; + ImguiItem selectable = self.copy({}); + ImVec2 size = _imgui_item_size_get(selectable, IMGUI_SELECTABLE); + bool isActivated = false; - return isActivated; + if (id == self.id) { + isActivated = _imgui_input_text(IMGUI_CHANGE_INPUT_TEXT.copy({.size = size}), imgui, buffer); + imgui_contextual_actions_disable(imgui); + + if (isActivated || _imgui_is_no_click_on_item()) { + value = buffer; + buffer.clear(); + id = ID_NONE; + imgui_contextual_actions_enable(imgui); + } + } else { + isActivated = _imgui_selectable(selectable, imgui); + + if (_imgui_is_input_begin()) { + buffer = value; + buffer.resize(IMGUI_CHANGE_INPUT_TEXT.max); + id = self.id; + ImGui::SetKeyboardFocusHere(-1); + } + } + + return isActivated; }; +*/ -IMGUI_ITEM_ATLAS_FUNCTION(_imgui_atlas_selectable, _imgui_selectable(self, imgui)); -IMGUI_ITEM_ATLAS_VALUE_FUNCTION(_imgui_atlas_selectable_input_int, s32, _imgui_selectable_input_int(self, imgui, value)); -IMGUI_ITEM_ATLAS_VALUE_FUNCTION(_imgui_atlas_selectable_input_text, std::string, _imgui_selectable_input_text(self, imgui, value)); +static bool _imgui_confirm_popup(ImguiItem self, Imgui* imgui, ImguiPopupState* state = nullptr, bool isOnlyConfirm = false) { + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); -static bool _imgui_confirm_popup(ImguiItem self, Imgui* imgui, ImguiPopupState* state = nullptr, bool isOnlyConfirm = false) -{ - ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); - - if (state) *state = IMGUI_POPUP_STATE_CLOSED; + if (state) + *state = IMGUI_POPUP_STATE_CLOSED; - if (imgui_begin_popup_modal(self.label_get().c_str(), imgui)) - { - if (state) *state = IMGUI_POPUP_STATE_OPEN; - - ImGui::Text(self.text_get()); - ImGui::Separator(); + if (imgui_begin_popup_modal(self.label_get().c_str(), imgui)) { + if (state) + *state = IMGUI_POPUP_STATE_OPEN; - if (_imgui_button(IMGUI_POPUP_OK.copy({.rowCount = isOnlyConfirm ? 1 : IMGUI_CONFIRM_POPUP_ROW_COUNT}), imgui)) - { - imgui_close_current_popup(imgui); - imgui_end_popup(imgui); - if (state) *state = isOnlyConfirm ? IMGUI_POPUP_STATE_CANCEL : IMGUI_POPUP_STATE_CONFIRM; - return true; - } + ImGui::Text("%s", self.text_get()); + ImGui::Separator(); - ImGui::SameLine(); - - if (!isOnlyConfirm) - { - if (_imgui_button(IMGUI_POPUP_CANCEL, imgui)) - { - imgui_close_current_popup(imgui); - if (state) *state = IMGUI_POPUP_STATE_CANCEL; - } - } + if (_imgui_button(IMGUI_POPUP_OK.copy({.rowCount = isOnlyConfirm ? 1 : IMGUI_CONFIRM_POPUP_ROW_COUNT}), imgui)) { + imgui_close_current_popup(imgui); + imgui_end_popup(imgui); + if (state) + *state = isOnlyConfirm ? IMGUI_POPUP_STATE_CANCEL : IMGUI_POPUP_STATE_CONFIRM; + return true; + } - imgui_end_popup(imgui); - } + ImGui::SameLine(); - return false; + if (!isOnlyConfirm) { + if (_imgui_button(IMGUI_POPUP_CANCEL, imgui)) { + imgui_close_current_popup(imgui); + if (state) + *state = IMGUI_POPUP_STATE_CANCEL; + } + } + + imgui_end_popup(imgui); + } + + return false; } -static void _imgui_no_anm2_path_check(Imgui* self) -{ - if (_imgui_is_window_hovered_and_click_no_anm2_path(self) && !imgui_is_any_popup_open()) - imgui_open_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION.label); - _imgui_confirm_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION, self, nullptr, true); +static void _imgui_no_anm2_path_check(Imgui* self) { + if (self->anm2->path.empty()) + imgui_open_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION.label); } -static void _imgui_context_menu(Imgui* self) -{ - if (!self->isContextualActionsEnabled) return; - - if (_imgui_is_window_hovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) - imgui_open_popup(IMGUI_CONTEXT_MENU.label_get()); - - if (imgui_begin_popup(IMGUI_CONTEXT_MENU.label_get(), self)) - { - _imgui_selectable(IMGUI_CUT, self); - _imgui_selectable(IMGUI_COPY, self); - _imgui_selectable(IMGUI_PASTE.copy({!clipboard_is_value()}), self); - - imgui_end_popup(self); - } +static void _imgui_no_anm2_path_click_check(Imgui* self) { + if (_imgui_is_window_hovered_and_click() && self->anm2->path.empty() && !imgui_is_any_popup_open()) + imgui_open_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION.label); } -static void _imgui_spritesheet_editor_set(Imgui* self, s32 id) -{ - if (self->anm2->spritesheets.contains(id)) self->editor->spritesheetID = id; +static void _imgui_context_menu(Imgui* self) { + if (!self->isContextualActionsEnabled) + return; + + if (_imgui_is_window_hovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) + imgui_open_popup(IMGUI_CONTEXT_MENU.label_get()); + + if (imgui_begin_popup(IMGUI_CONTEXT_MENU.label_get(), self)) { + _imgui_selectable(IMGUI_CUT, self); + _imgui_selectable(IMGUI_COPY, self); + _imgui_selectable(IMGUI_PASTE.copy({.isDisabled = !clipboard_is_value()}), self); + + imgui_end_popup(self); + } } -static void _imgui_timeline(Imgui* self) -{ - static const ImU32 frameColor = ImGui::GetColorU32(IMGUI_TIMELINE_FRAME_COLOR); - static const ImU32 frameMultipleColor = ImGui::GetColorU32(IMGUI_TIMELINE_FRAME_MULTIPLE_COLOR); - static const ImU32 headerFrameColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_COLOR); - static const ImU32 headerFrameMultipleColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_COLOR); - static const ImU32 headerFrameInactiveColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_INACTIVE_COLOR); - static const ImU32 headerFrameMultipleInactiveColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_INACTIVE_COLOR); - static const ImU32 textColor = ImGui::GetColorU32(ImGuiCol_Text); - static Anm2Reference hoverReference; - static Anm2Reference swapItemReference; - static Anm2Type& itemType = self->reference->itemType; - static ImVec2 itemMin{}; - static ImVec2 localMousePos{}; - static ImVec2 mousePos{}; - static ImVec2 playheadPos{}; - static ImVec2 scroll{}; - static bool isItemSwap = false; - static const ImVec2& frameSize = IMGUI_TIMELINE_FRAME_SIZE; - static f32& time = self->preview->time; - static s32 frameTime{}; - static s32& itemID = self->reference->itemID; - - IMGUI_BEGIN_OR_RETURN(IMGUI_TIMELINE, self); - _imgui_no_anm2_path_check(self); - - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference); - - if (!animation) - { - ImGui::Text(IMGUI_TIMELINE_ANIMATION_NONE); - _imgui_end(); // IMGUI_TIMELINE - return; - } - - s32 length = animation->frameNum; - s32 actualLength = anm2_animation_length_get(animation); - - ImVec2 actualFramesSize = {actualLength * frameSize.x, frameSize.y}; - ImVec2 framesSize = {length * frameSize.x, frameSize.y}; - - ImVec2 defaultItemSpacing = ImGui::GetStyle().ItemSpacing; - ImVec2 defaultWindowPadding = ImGui::GetStyle().WindowPadding; - ImVec2 defaultFramePadding = ImGui::GetStyle().FramePadding; - - vec2 windowSize = ImGui::GetContentRegionAvail(); - vec2 childSize = {windowSize.x, windowSize.y - IMGUI_FOOTER_CHILD.size.y}; - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); - - _imgui_begin_child(IMGUI_TIMELINE_CHILD.copy({.size = childSize}), self); - ImVec2 clipRectMin = ImGui::GetWindowDrawList()->GetClipRectMin(); - ImVec2 clipRectMax = ImGui::GetWindowDrawList()->GetClipRectMax(); - clipRectMin.x += IMGUI_TIMELINE_ITEM_SIZE.x; - - ImVec2 scrollDelta{}; - - if (_imgui_is_window_hovered() && !imgui_is_any_popup_open()) - { - ImGuiIO& io = ImGui::GetIO(); - f32 lineHeight = ImGui::GetTextLineHeight(); - - scrollDelta.x -= io.MouseWheelH * lineHeight; - scrollDelta.y -= io.MouseWheel * lineHeight; - } - - std::function timeline_header = [&]() - { - static bool isPlayheadDrag = false; - _imgui_begin_child(IMGUI_TIMELINE_HEADER_CHILD, self); - - ImGui::SetScrollX(scroll.x); - - itemMin = ImGui::GetItemRectMin(); - mousePos = ImGui::GetMousePos(); - localMousePos = ImVec2(mousePos.x - itemMin.x + scroll.x, mousePos.y - itemMin.y); - frameTime = (s32)(localMousePos.x / frameSize.x); - - if (ImGui::IsMouseDown(0) && _imgui_is_window_hovered()) isPlayheadDrag = true; - - if (isPlayheadDrag) - { - if (self->settings->playbackIsClampPlayhead) - time = std::clamp(frameTime, 0, std::max(0, length - 1)); - else - time = std::max(frameTime, 0); - - if (ImGui::IsMouseReleased(0)) - isPlayheadDrag = false; - } - - ImVec2 cursorPos = ImGui::GetCursorScreenPos(); - playheadPos = {cursorPos.x + (time * frameSize.x), cursorPos.y}; - - ImDrawList* drawList = ImGui::GetWindowDrawList(); - - ImVec2 dummySize = actualFramesSize.x > framesSize.x ? actualFramesSize : framesSize; - ImGui::Dummy(dummySize); - - f32 viewWidth = ImGui::GetWindowContentRegionMax().x - ImGui::GetWindowContentRegionMin().x; - s32 start = (s32)std::floor(scroll.x / frameSize.x) - 1; - start = (start < 0) ? 0 : start; - - s32 end = (s32)std::ceil((scroll.x + viewWidth) / frameSize.x) + 1; - end = (end > ANM2_FRAME_NUM_MAX) ? ANM2_FRAME_NUM_MAX : end; - - playheadPos = ImVec2(cursorPos.x + time * frameSize.x, cursorPos.y); - - for (s32 i = start; i < end; i++) - { - bool isMultiple = (i % IMGUI_TIMELINE_FRAME_MULTIPLE) == 0; - bool isInactive = i >= length; - - f32 startX = cursorPos.x + i * frameSize.x; - f32 endX = startX + frameSize.x; - ImVec2 positionStart(startX, cursorPos.y); - ImVec2 positionEnd(endX, cursorPos.y + frameSize.y); - - ImU32 bgColor = isInactive - ? (isMultiple ? headerFrameMultipleInactiveColor : headerFrameInactiveColor) - : (isMultiple ? headerFrameMultipleColor : headerFrameColor); - - drawList->AddRectFilled(positionStart, positionEnd, bgColor); - - if (isMultiple) - { - std::string buffer = std::to_string(i); - ImVec2 textSize = ImGui::CalcTextSize(buffer.c_str()); - ImVec2 textPosition(startX + (frameSize.x - textSize.x) * 0.5f, cursorPos.y + (frameSize.y - textSize.y) * 0.5f); - drawList->AddText(textPosition, textColor, buffer.c_str()); - } - - drawList->AddImage(self->resources->atlas.id, positionStart, positionEnd, ATLAS_UV_ARGS(ATLAS_FRAME_ALT)); - } - - _imgui_end_child(); // IMGUI_TIMELINE_HEADER_CHILD - - ImGui::SetNextWindowPos(ImGui::GetWindowPos()); - ImGui::SetNextWindowSize(ImGui::GetWindowSize()); - _imgui_begin(IMGUI_PLAYHEAD, self); - - ImVec2& pos = playheadPos; - - ImVec2 lineStart = {pos.x + (frameSize.x * 0.5f) - (IMGUI_PLAYHEAD_LINE_WIDTH * 0.5f), pos.y + frameSize.y}; - ImVec2 lineEnd = {lineStart.x + IMGUI_PLAYHEAD_LINE_WIDTH, lineStart.y + childSize.y - frameSize.y}; - - drawList = ImGui::GetWindowDrawList(); - - drawList->PushClipRect(clipRectMin, clipRectMax, true); - drawList->AddImage(self->resources->atlas.id, pos, ImVec2(pos.x + frameSize.x, pos.y + frameSize.y), ATLAS_UV_ARGS(ATLAS_PICKER)); - drawList->AddRectFilled(lineStart, lineEnd, IMGUI_PLAYHEAD_LINE_COLOR); - drawList->PopClipRect(); - - _imgui_end(); // IMGUI_PLAYHEAD - }; - - std::function timeline_item_child = [&](Anm2Reference reference, s32& index) - { - Anm2Item* item = anm2_item_from_reference(self->anm2, &reference); - Anm2Type& type = reference.itemType; - if (!item) return; - if (!self->settings->timelineIsShowUnused && item->frames.empty() && (type == ANM2_LAYER || type == ANM2_NULL)) return; - - ImVec2 buttonSize = ImVec2(ATLAS_SIZE_NORMAL) + (defaultFramePadding * ImVec2(2, 2)); - - Anm2Layer* layer = nullptr; - Anm2Null* null = nullptr; - s32 buttonCount = type == ANM2_NULL ? 2 : 1; - f32 buttonAreaWidth = buttonCount * buttonSize.x + (buttonCount - 1) * defaultItemSpacing.x; - bool isSelected = (self->reference->itemID == reference.itemID && self->reference->itemType == type); - - ImGui::PushID(reference.itemID); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, defaultItemSpacing); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, defaultWindowPadding); - - ImVec2 childPos = ImGui::GetCursorScreenPos(); - _imgui_begin_child(*IMGUI_TIMELINE_ITEM_CHILDS[type], self); - ImVec2 childSize = ImGui::GetContentRegionAvail(); - - std::string dragDrop = IMGUI_TIMELINE_ITEM_SELECTABLES[type]->dragDrop; - - switch (type) - { - case ANM2_ROOT: - case ANM2_TRIGGERS: - if (_imgui_atlas_selectable(IMGUI_TIMELINE_ITEM_SELECTABLES[type]->copy({.isSelected = isSelected}), self)) - *self->reference = reference; - break; - case ANM2_LAYER: - layer = &self->anm2->layers[reference.itemID]; - if - ( - _imgui_atlas_selectable(IMGUI_TIMELINE_ITEM_SELECTABLES[type]->copy - ({ - .isSelected = isSelected, - .label = std::format(IMGUI_TIMELINE_ITEM_CHILD_FORMAT, reference.itemID, layer->name) - }), - self - ) - ) - *self->reference = reference; - - break; - case ANM2_NULL: - null = &self->anm2->nulls[reference.itemID]; - if - ( - _imgui_atlas_selectable(IMGUI_TIMELINE_ITEM_SELECTABLES[type]->copy - ({ - .isSelected = isSelected, - .label = std::format(IMGUI_TIMELINE_ITEM_CHILD_FORMAT, reference.itemID, null->name) - }), - self) - ) - *self->reference = reference; - break; - default: - break; - } - - if (imgui_begin_popup_modal(IMGUI_POPUP_ITEM_PROPERTIES, self, IMGUI_POPUP_ITEM_PROPERTIES_SIZE)) - { - static s32 selectedLayerID = ID_NONE; - static s32 selectedNullID = ID_NONE; - Anm2Type& type = reference.itemType; - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, self); - - _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER.copy({true}), self, (s32&)type); - _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL.copy({true}), self, (s32&)type); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, self); - - switch (type) - { - case ANM2_LAYER: - default: - { - for (auto & [id, layer] : self->anm2->layers) - { - if (id == reference.itemID) continue; - - ImGui::PushID(id); - - ImguiItem layerItem = IMGUI_LAYER.copy - ({ - .isSelected = selectedLayerID == id, - .label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), - .id = id - }); - if (_imgui_atlas_selectable(layerItem, self)) selectedLayerID = id; - - ImGui::PopID(); - }; - break; - } - case ANM2_NULL: - { - for (auto & [id, null] : self->anm2->nulls) - { - if (id == reference.itemID) continue; - - ImGui::PushID(id); - - ImguiItem nullItem = IMGUI_NULL.copy - ({ - .isSelected = selectedNullID == id, - .label = std::format(IMGUI_NULL_FORMAT, id, null.name), - .id = id - }); - if (_imgui_atlas_selectable(nullItem, self)) selectedNullID = id; - - ImGui::PopID(); - }; - break; - } - } - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD, self); - - if (self->anm2->layers.size() == 0) selectedLayerID = ID_NONE; - if (self->anm2->nulls.size() == 0) selectedNullID = ID_NONE; - - bool isDisabled = type == ANM2_NONE || - (type == ANM2_LAYER && selectedLayerID == ID_NONE) || - (type == ANM2_NULL && selectedNullID == ID_NONE); - - if (_imgui_button(IMGUI_TIMELINE_ITEM_PROPERTIES_CONFIRM.copy({isDisabled}), self)) - { - switch (type) - { - case ANM2_LAYER: - if (!map_find(animation->layerAnimations, selectedLayerID)) - { - anm2_animation_layer_animation_add(animation, selectedLayerID); - anm2_animation_layer_animation_remove(animation, reference.itemID); - } - else - map_swap(animation->layerAnimations, selectedLayerID, reference.itemID); - - *self->reference = {self->reference->animationID, ANM2_LAYER, selectedLayerID}; - break; - case ANM2_NULL: - if (!map_find(animation->nullAnimations, selectedNullID)) - { - anm2_animation_null_animation_add(animation, selectedNullID); - anm2_animation_null_animation_remove(animation, reference.itemID); - - } - else - map_swap(animation->nullAnimations, selectedNullID, reference.itemID); - - *self->reference = {self->reference->animationID, ANM2_NULL, selectedNullID}; - break; - default: break; - } - - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) imgui_close_current_popup(self); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD - - imgui_end_popup(self); - } - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None) && !dragDrop.empty()) - { - *self->reference = reference; - - ImGui::SetDragDropPayload(dragDrop.c_str(), &reference, sizeof(Anm2Reference)); - timeline_item_child(reference, index); - ImGui::EndDragDropSource(); - } - ImGui::PopStyleVar(); - - if (ImGui::BeginDragDropTarget()) - { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(dragDrop.c_str())) - { - Anm2Reference checkReference = *(Anm2Reference*)payload->Data; - if (checkReference != reference) - { - swapItemReference = reference; - isItemSwap = true; - } - } - - ImGui::EndDragDropTarget(); - } - - ImGui::SetCursorScreenPos({childPos.x + childSize.x - buttonAreaWidth, childPos.y + defaultWindowPadding.y}); - - if (type == ANM2_NULL) - { - const ImguiItem& rectItem = null->isShowRect ? IMGUI_TIMELINE_ITEM_SHOW_RECT : IMGUI_TIMELINE_ITEM_HIDE_RECT; - if (_imgui_atlas_button(rectItem, self)) null->isShowRect = !null->isShowRect; - ImGui::SameLine(0.0f, defaultItemSpacing.x); - } - - const ImguiItem& visibleItem = item->isVisible ? IMGUI_TIMELINE_ITEM_VISIBLE : IMGUI_TIMELINE_ITEM_INVISIBLE; - if (_imgui_atlas_button(visibleItem, self)) item->isVisible = !item->isVisible; - - ImGui::PopStyleVar(2); - - _imgui_end_child(); // itemChild - - ImGui::PopID(); - - index++; - }; - - std::function timeline_items_child = [&]() - { - static s32& animationID = self->reference->animationID; - s32 index = 0; - - _imgui_begin_child(IMGUI_TIMELINE_ITEMS_CHILD, self); - ImGui::SetScrollY(scroll.y); - - timeline_item_child({animationID, ANM2_ROOT}, index); - - for (auto& id : std::ranges::reverse_view(animation->layerOrder)) - timeline_item_child({animationID, ANM2_LAYER, id}, index); - - for (auto & [id, null] : animation->nullAnimations) - timeline_item_child({animationID, ANM2_NULL, id}, index); - - timeline_item_child({animationID, ANM2_TRIGGERS}, index); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEMS_CHILD - - if (isItemSwap) - { - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference); - - imgui_snapshot(self, IMGUI_ACTION_ITEM_SWAP); - - switch (swapItemReference.itemType) - { - case ANM2_LAYER: - vector_value_swap(animation->layerOrder, self->reference->itemID, swapItemReference.itemID); - break; - case ANM2_NULL: - map_swap(animation->nullAnimations, self->reference->itemID, swapItemReference.itemID); - break; - default: break; - } - - self->reference->itemID = swapItemReference.itemID; - anm2_reference_clear(&swapItemReference); - isItemSwap = false; - } - }; - - std::function timeline_item_frames = [&](Anm2Reference reference, s32& index) - { - Anm2Item* item = anm2_item_from_reference(self->anm2, &reference); - if (!item) return; - Anm2Type& type = reference.itemType; - if (!self->settings->timelineIsShowUnused && item->frames.empty() && (type == ANM2_LAYER || type == ANM2_NULL)) return; - - ImGui::PushID(index); - - ImDrawList* drawList = ImGui::GetWindowDrawList(); - - f32 viewWidth = ImGui::GetWindowContentRegionMax().x - ImGui::GetWindowContentRegionMin().x; - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_FRAMES_CHILD.copy({.size = actualFramesSize.x > framesSize.x ? actualFramesSize : framesSize}), self); - - ImVec2 startPos = ImGui::GetCursorPos(); - ImVec2 cursorPos = ImGui::GetCursorScreenPos(); - - if (_imgui_is_window_hovered()) - { - hoverReference = reference; - hoverReference.time = frameTime; - hoverReference.frameIndex = anm2_frame_index_from_time(self->anm2, reference, frameTime); - self->clipboard->location = hoverReference; - self->clipboard->type = CLIPBOARD_FRAME; - - if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) - { - *self->reference = reference; - if (reference.itemType == ANM2_LAYER && reference.itemID != ID_NONE) - _imgui_spritesheet_editor_set(self, self->anm2->layers[self->reference->itemID].spritesheetID); - } - } - - s32 start = (s32)std::floor(scroll.x / frameSize.x) - 1; - if (start < 0) start = 0; - - s32 end = (s32)std::ceil((scroll.x + viewWidth) / frameSize.x) + 1; - if (end > ANM2_FRAME_NUM_MAX) end = ANM2_FRAME_NUM_MAX; - - for (s32 i = start; i < end; i++) - { - bool isMultiple = (i % IMGUI_TIMELINE_FRAME_MULTIPLE) == 0; - ImU32 bgColor = isMultiple ? frameMultipleColor : frameColor; - - f32 startX = cursorPos.x + i * frameSize.x; - f32 endX = startX + frameSize.x; - ImVec2 startPosition(startX, cursorPos.y); - ImVec2 endPosition(endX, cursorPos.y + frameSize.y); - - drawList->AddRectFilled(startPosition, endPosition, bgColor); - drawList->AddImage(self->resources->atlas.id, startPosition, endPosition, ATLAS_UV_ARGS(ATLAS_FRAME)); - } - - ImGui::SetCursorPos(startPos); - - std::function timeline_item_frame = [&](s32 i, Anm2Frame& frame) - { - static s32 frameDelayStart{}; - static f32 frameDelayTimeStart{}; - const bool isModCtrl = ImGui::IsKeyDown(IMGUI_INPUT_CTRL); - static bool isFrameSwap = false; - static bool isDrag = false; - - ImGui::PushID(i); - reference.frameIndex = i; - ImVec2 framePos = ImGui::GetCursorPos(); - AtlasType atlas = frame.isInterpolated ? ATLAS_CIRCLE : ATLAS_SQUARE; - - if (type == ANM2_TRIGGERS) - { - framePos.x = startPos.x + (frameSize.x * frame.atFrame); - atlas = ATLAS_TRIGGER; - } - - ImguiItem frameButton = IMGUI_TIMELINE_FRAMES[type]->copy - ({.isSelected = reference == *self->reference, .size = {frameSize.x * frame.delay, frameSize.y}, .id = i, .atlas = atlas}); - - ImGui::SetCursorPos(framePos); - - if (_imgui_atlas_button(frameButton, self)) - { - *self->reference = reference; - frameDelayStart = frame.delay; - frameDelayTimeStart = frameTime; - } - - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoDisableHover)) - { - if (!isDrag) - { - *self->reference = reference; - frameDelayStart = frame.delay; - frameDelayTimeStart = frameTime; - isFrameSwap = false; - isDrag = true; - } - - ImGui::SetDragDropPayload(frameButton.drag_drop_get(), &reference, sizeof(Anm2Reference)); - if (!isModCtrl) timeline_item_frame(i, frame); - ImGui::EndDragDropSource(); - } - - if (isDrag) - { - if (Anm2Frame* referenceFrame = anm2_frame_from_reference(self->anm2, self->reference)) - { - switch (self->reference->itemType) - { - case ANM2_TRIGGERS: - { - referenceFrame->atFrame = std::max(frameTime, 0); - for (auto& trigger : animation->triggers.frames) - { - if (&trigger == referenceFrame) continue; - if (trigger.atFrame == referenceFrame->atFrame) - { - referenceFrame->atFrame++; - break; - } - } - break; - } - case ANM2_ROOT: - case ANM2_LAYER: - case ANM2_NULL: - { - if (isModCtrl) - referenceFrame->delay = std::max(frameDelayStart + (s32)(frameTime - frameDelayTimeStart), ANM2_FRAME_NUM_MIN); - break; - } - default: break; - } - } - } - - if (ImGui::BeginDragDropTarget()) - { - ImGui::AcceptDragDropPayload(frameButton.drag_drop_get()); - ImGui::EndDragDropTarget(); - } - - if (isDrag && ImGui::IsMouseReleased(0)) - { - if - ( !isFrameSwap && - *self->reference != hoverReference && - self->reference->itemType == hoverReference.itemType - ) - { - imgui_snapshot(self, IMGUI_ACTION_FRAME_MOVE); - if (Anm2Frame* referenceFrame = anm2_frame_from_reference(self->anm2, self->reference)) - { - Anm2Reference addReference = hoverReference; - addReference.frameIndex = hoverReference.frameIndex < self->reference->frameIndex ? - std::min(0, addReference.frameIndex - 2) : - std::min(0, addReference.frameIndex - 1); - Anm2Frame addFrame = *referenceFrame; - anm2_frame_remove(self->anm2, self->reference); - anm2_frame_add(self->anm2, &addFrame, &hoverReference); - *self->reference = hoverReference; - hoverReference = Anm2Reference(); - } - } - - isDrag = false; - } - - - if (i < (s32)item->frames.size() - 1) ImGui::SameLine(); - - ImGui::PopID(); - }; - - for (auto [i, frame] : std::views::enumerate(item->frames)) - timeline_item_frame(i, frame); - - _imgui_end_child(); // itemFramesChild - - ImGui::PopID(); - - index++; - }; - - std::function timeline_frames_child = [&]() - { - s32& animationID = self->reference->animationID; - s32 index = 0; - - _imgui_begin_child(IMGUI_TIMELINE_FRAMES_CHILD, self); - scroll.x = ImGui::GetScrollX() + scrollDelta.x; - scroll.y = ImGui::GetScrollY() + scrollDelta.y; - ImGui::SetScrollX(scroll.x); - ImGui::SetScrollY(scroll.y); - - timeline_item_frames(Anm2Reference(animationID, ANM2_ROOT), index); - - for (auto& id : std::ranges::reverse_view(animation->layerOrder)) - timeline_item_frames(Anm2Reference(animationID, ANM2_LAYER, id), index); - - for (auto & [id, null] : animation->nullAnimations) - timeline_item_frames(Anm2Reference(animationID, ANM2_NULL, id), index); - - timeline_item_frames(Anm2Reference(animationID, ANM2_TRIGGERS), index); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, defaultItemSpacing); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, defaultWindowPadding); - _imgui_context_menu(self); - ImGui::PopStyleVar(2); - - _imgui_end_child(); // IMGUI_TIMELINE_FRAMES_CHILD - }; - - // In order to set scroll properly timeline_frames_child must be called first - ImGui::SetCursorPos(ImVec2(IMGUI_TIMELINE_ITEM_SIZE)); - timeline_frames_child(); - ImGui::SetCursorPos(ImVec2()); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, defaultItemSpacing); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, defaultWindowPadding); - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_CHILD, self); - - const ImguiItem& unusedItem = self->settings->timelineIsShowUnused ? IMGUI_TIMELINE_SHOW_UNUSED : IMGUI_TIMELINE_HIDE_UNUSED; - if (_imgui_atlas_button(unusedItem, self)) self->settings->timelineIsShowUnused = !self->settings->timelineIsShowUnused; - ImGui::PopStyleVar(2); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_CHILD - ImGui::SameLine(); - timeline_header(); - - timeline_items_child(); - - ImGui::PopStyleVar(2); - - _imgui_end_child(); // IMGUI_TIMELINE_CHILD - - Anm2Frame* frame = anm2_frame_from_reference(self->anm2, self->reference); - Anm2Item* item = anm2_item_from_reference(self->anm2, self->reference); - _imgui_begin_child(IMGUI_TIMELINE_ITEM_FOOTER_CHILD, self); - - _imgui_button(IMGUI_TIMELINE_ADD_ITEM, self); - - if (imgui_begin_popup_modal(IMGUI_TIMELINE_ADD_ITEM.popup, self, IMGUI_TIMELINE_ADD_ITEM.popupSize)) - { - static s32 selectedLayerID = ID_NONE; - static s32 selectedNullID = ID_NONE; - s32& type = self->settings->timelineAddItemType; - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, self); - - _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER, self, type); - _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL, self, type); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, self); - - switch (type) - { - case ANM2_LAYER: - default: - { - for (auto & [id, layer] : self->anm2->layers) - { - ImGui::PushID(id); - - ImguiItem layerItem = IMGUI_LAYER.copy - ({ - .isSelected = selectedLayerID == id, - .label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), - .id = id - }); - if (_imgui_atlas_selectable(layerItem, self)) selectedLayerID = id; - - ImGui::PopID(); - }; - break; - } - case ANM2_NULL: - { - for (auto & [id, null] : self->anm2->nulls) - { - ImGui::PushID(id); - - ImguiItem nullItem = IMGUI_NULL.copy - ({ - .isSelected = selectedNullID == id, - .label = std::format(IMGUI_NULL_FORMAT, id, null.name), - .id = id - }); - if (_imgui_atlas_selectable(nullItem, self)) selectedNullID = id; - - ImGui::PopID(); - }; - break; - } - } - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD, self); - - if (self->anm2->layers.size() == 0) selectedLayerID = ID_NONE; - if (self->anm2->nulls.size() == 0) selectedNullID = ID_NONE; - - bool isDisabled = type == ANM2_NONE || - (type == ANM2_LAYER && selectedLayerID == ID_NONE) || - (type == ANM2_NULL && selectedNullID == ID_NONE); - - if (_imgui_button(IMGUI_TIMELINE_ITEM_PROPERTIES_CONFIRM.copy({isDisabled}), self)) - { - switch (type) - { - case ANM2_LAYER: - anm2_animation_layer_animation_add(animation, selectedLayerID); - *self->reference = {self->reference->animationID, ANM2_LAYER, selectedLayerID}; - break; - case ANM2_NULL: - anm2_animation_null_animation_add(animation, selectedNullID); - *self->reference = {self->reference->animationID, ANM2_NULL, selectedNullID}; - break; - default: break; - } - - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) imgui_close_current_popup(self); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD - - imgui_end_popup(self); - } - - if (_imgui_button(IMGUI_TIMELINE_REMOVE_ITEM.copy({!item || itemType == ANM2_ROOT || itemType == ANM2_TRIGGERS}), self)) - { - switch (itemType) - { - case ANM2_LAYER: anm2_animation_layer_animation_remove(animation, itemID); break; - case ANM2_NULL: anm2_animation_null_animation_remove(animation, itemID); break; - default: break; - } - - anm2_reference_item_clear(self->reference); - } - - _imgui_end_child(); //IMGUI_TIMELINE_FOOTER_ITEM_CHILD - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - ImGui::SameLine(); - ImGui::PopStyleVar(); - - _imgui_begin_child(IMGUI_TIMELINE_OPTIONS_FOOTER_CHILD, self); - - if (_imgui_button(self->preview->isPlaying ? IMGUI_PAUSE : IMGUI_PLAY, self)) - { - if (!self->preview->isPlaying && time >= animation->frameNum - 1) - time = 0.0f; - self->preview->isPlaying = !self->preview->isPlaying; - } - - if (_imgui_button(IMGUI_ADD_FRAME.copy({!item}), self)) - { - Anm2Reference frameReference = *self->reference; - frameReference.frameIndex = item->frames.empty() ? 0 : std::clamp(frameReference.frameIndex, 0, (s32)(item->frames.size() - 1)); - Anm2Frame* addFrame = anm2_frame_from_reference(self->anm2, &frameReference); - anm2_frame_add(self->anm2, addFrame, &frameReference); - } - - if(_imgui_button(IMGUI_REMOVE_FRAME.copy({!frame}), self)) - { - anm2_frame_remove(self->anm2, self->reference); - anm2_reference_frame_clear(self->reference); - } - - _imgui_button(IMGUI_BAKE.copy({!frame || itemType == ANM2_TRIGGERS}), self); - - if (imgui_begin_popup_modal(IMGUI_BAKE.popup, self, IMGUI_BAKE.popupSize)) - { - static s32& interval = self->settings->bakeInterval; - static bool& isRoundScale = self->settings->bakeIsRoundScale; - static bool& isRoundRotation = self->settings->bakeIsRoundRotation; - - _imgui_begin_child(IMGUI_BAKE_CHILD, self); - - _imgui_input_int(IMGUI_BAKE_INTERVAL.copy({.max = frame->delay}), self, interval); - _imgui_checkbox(IMGUI_BAKE_ROUND_SCALE, self, isRoundScale); - _imgui_checkbox(IMGUI_BAKE_ROUND_ROTATION, self, isRoundRotation); - - if (_imgui_button(IMGUI_BAKE_CONFIRM, self)) - { - anm2_frame_bake(self->anm2, self->reference, interval, isRoundScale, isRoundRotation); - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) imgui_close_current_popup(self); - - _imgui_end_child(); //IMGUI_BAKE_CHILD) - - imgui_end_popup(self); - } - - if (_imgui_button(IMGUI_FIT_ANIMATION_LENGTH, self)) anm2_animation_length_set(animation); - - _imgui_input_int(IMGUI_ANIMATION_LENGTH, self, animation->frameNum); - _imgui_input_int(IMGUI_FPS, self, self->anm2->fps); - _imgui_checkbox(IMGUI_LOOP, self, animation->isLoop); - _imgui_selectable_input_text(IMGUI_CREATED_BY.copy({.label = self->anm2->createdBy}), self, self->anm2->createdBy); - - _imgui_end_child(); // IMGUI_TIMELINE_FOOTER_OPTIONS_CHILD - - _imgui_end(); // IMGUI_TIMELINE -} - -static void _imgui_onionskin(Imgui* self) -{ - IMGUI_BEGIN_OR_RETURN(IMGUI_ONIONSKIN, self); - - static auto& isEnabled = self->settings->onionskinIsEnabled; - static auto& beforeCount = self->settings->onionskinBeforeCount; - static auto& afterCount = self->settings->onionskinAfterCount; - static auto& beforeColorOffset = self->settings->onionskinBeforeColorOffset; - static auto& afterColorOffset = self->settings->onionskinAfterColorOffset; - static auto& drawOrder = self->settings->onionskinDrawOrder; - - _imgui_checkbox(IMGUI_ONIONSKIN_ENABLED, self, isEnabled); - - auto onionskin_section = [&](auto& text, auto& count, auto& colorOffset) - { - ImGui::PushID(text.label.c_str()); - _imgui_text(text, self); - _imgui_input_int(IMGUI_ONIONSKIN_COUNT.copy({!isEnabled}), self, count); - _imgui_color_edit3(IMGUI_ONIONSKIN_COLOR_OFFSET.copy({!isEnabled}), self, colorOffset); - ImGui::PopID(); +/* +static void _imgui_timeline(Imgui* self) { + static const ImU32 frameColor = ImGui::GetColorU32(IMGUI_TIMELINE_FRAME_COLOR); + static const ImU32 frameMultipleColor = ImGui::GetColorU32(IMGUI_TIMELINE_FRAME_MULTIPLE_COLOR); + static const ImU32 headerFrameColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_COLOR); + static const ImU32 headerFrameMultipleColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_COLOR); + static const ImU32 headerFrameInactiveColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_INACTIVE_COLOR); + static const ImU32 headerFrameMultipleInactiveColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_INACTIVE_COLOR); + static const ImU32 textColor = ImGui::GetColorU32(ImGuiCol_Text); + static Anm2Reference hoverReference; + static Anm2Reference swapItemReference; + static Anm2Type& itemType = self->reference->itemType; + static ImVec2 itemMin{}; + static ImVec2 localMousePos{}; + static ImVec2 mousePos{}; + static ImVec2 playheadPos{}; + static ImVec2 scroll{}; + static bool isItemSwap = false; + static const ImVec2& frameSize = IMGUI_TIMELINE_FRAME_SIZE; + static float& time = self->preview->time; + static int frameTime{}; + static int& itemID = self->reference->itemID; + + IMGUI_BEGIN_OR_RETURN(IMGUI_TIMELINE, self); + _imgui_no_anm2_path_click_check(self); + + Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); + + if (!animation) { + ImGui::Text(IMGUI_TIMELINE_ANIMATION_NONE); + _imgui_end(); // IMGUI_TIMELINE + return; + } + + int length = animation->frameNum; + int actualLength = anm2_animation_length_get(animation); + + ImVec2 actualFramesSize = {actualLength * frameSize.x, frameSize.y}; + ImVec2 framesSize = {length * frameSize.x, frameSize.y}; + + ImVec2 defaultItemSpacing = ImGui::GetStyle().ItemSpacing; + ImVec2 defaultWindowPadding = ImGui::GetStyle().WindowPadding; + ImVec2 defaultFramePadding = ImGui::GetStyle().FramePadding; + + vec2 windowSize = ImGui::GetContentRegionAvail(); + vec2 childSize = {windowSize.x, windowSize.y - IMGUI_FOOTER_CHILD.size->y}; + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); + + _imgui_begin_child(IMGUI_TIMELINE_CHILD.copy({.size = childSize}), self); + ImVec2 clipRectMin = ImGui::GetWindowDrawList()->GetClipRectMin(); + ImVec2 clipRectMax = ImGui::GetWindowDrawList()->GetClipRectMax(); + clipRectMin.x += IMGUI_TIMELINE_ITEM_SIZE.x; + + ImVec2 scrollDelta{}; + + if (_imgui_is_window_hovered() && !imgui_is_any_popup_open()) { + ImGuiIO& io = ImGui::GetIO(); + float lineHeight = ImGui::GetTextLineHeight(); + + scrollDelta.x -= io.MouseWheelH * lineHeight; + scrollDelta.y -= io.MouseWheel * lineHeight; + } + + std::function timeline_header = [&]() { + static bool isPlayheadDrag = false; + _imgui_begin_child(IMGUI_TIMELINE_HEADER_CHILD, self); + + ImGui::SetScrollX(scroll.x); + + itemMin = ImGui::GetItemRectMin(); + mousePos = ImGui::GetMousePos(); + localMousePos = ImVec2(mousePos.x - itemMin.x + scroll.x, mousePos.y - itemMin.y); + frameTime = (int)(localMousePos.x / frameSize.x); + + if (ImGui::IsMouseDown(0) && _imgui_is_window_hovered()) + isPlayheadDrag = true; + + if (isPlayheadDrag) { + if (self->settings->playbackIsClampPlayhead) + time = std::clamp(frameTime, 0, std::max(0, length - 1)); + else + time = std::max(frameTime, 0); + + if (ImGui::IsMouseReleased(0)) + isPlayheadDrag = false; + } + + ImVec2 cursorPos = ImGui::GetCursorScreenPos(); + playheadPos = {cursorPos.x + (time * frameSize.x), cursorPos.y}; + + ImDrawList* drawList = ImGui::GetWindowDrawList(); + + ImVec2 dummySize = actualFramesSize.x > framesSize.x ? actualFramesSize : framesSize; + ImGui::Dummy(dummySize); + + float viewWidth = ImGui::GetContentRegionAvail().x; + int start = (int)std::floor(scroll.x / frameSize.x) - 1; + start = (start < 0) ? 0 : start; + + int end = (int)std::ceil((scroll.x + viewWidth) / frameSize.x) + 1; + end = (end > ANM2_FRAME_NUM_MAX) ? ANM2_FRAME_NUM_MAX : end; + + playheadPos = ImVec2(cursorPos.x + time * frameSize.x, cursorPos.y); + + for (int i = start; i < end; i++) { + bool isMultiple = (i % IMGUI_TIMELINE_FRAME_MULTIPLE) == 0; + bool isInactive = i >= length; + + float startX = cursorPos.x + i * frameSize.x; + float endX = startX + frameSize.x; + ImVec2 positionStart(startX, cursorPos.y); + ImVec2 positionEnd(endX, cursorPos.y + frameSize.y); + + ImU32 bgColor = + isInactive ? (isMultiple ? headerFrameMultipleInactiveColor : headerFrameInactiveColor) : (isMultiple ? headerFrameMultipleColor : headerFrameColor); + + drawList->AddRectFilled(positionStart, positionEnd, bgColor); + + if (isMultiple) { + std::string buffer = std::to_string(i); + ImVec2 textSize = ImGui::CalcTextSize(buffer.c_str()); + ImVec2 textPosition(startX + (frameSize.x - textSize.x) * 0.5f, cursorPos.y + (frameSize.y - textSize.y) * 0.5f); + drawList->AddText(textPosition, textColor, buffer.c_str()); + } + + drawList->AddImage(self->resources->atlas.id, positionStart, positionEnd, ATLAS_UV_ARGS(ATLAS_FRAME_ALT)); + } + + _imgui_end_child(); // IMGUI_TIMELINE_HEADER_CHILD + + ImGui::SetNextWindowPos(ImGui::GetWindowPos()); + ImGui::SetNextWindowSize(ImGui::GetWindowSize()); + _imgui_begin(IMGUI_PLAYHEAD, self); + + ImVec2& pos = playheadPos; + + ImVec2 lineStart = {pos.x + (frameSize.x * 0.5f) - (IMGUI_PLAYHEAD_LINE_WIDTH * 0.5f), pos.y + frameSize.y}; + ImVec2 lineEnd = {lineStart.x + IMGUI_PLAYHEAD_LINE_WIDTH, lineStart.y + childSize.y - frameSize.y}; + + drawList = ImGui::GetWindowDrawList(); + + drawList->PushClipRect(clipRectMin, clipRectMax, true); + drawList->AddImage(self->resources->atlas.id, pos, ImVec2(pos.x + frameSize.x, pos.y + frameSize.y), ATLAS_UV_ARGS(ATLAS_PICKER)); + drawList->AddRectFilled(lineStart, lineEnd, IMGUI_PLAYHEAD_LINE_COLOR); + drawList->PopClipRect(); + + _imgui_end(); // IMGUI_PLAYHEAD + }; + + std::function timeline_item_child = [&](Anm2Reference reference, int& index) { + Anm2Item* item = anm2_item_from_reference(self->anm2, reference); + Anm2Type& type = reference.itemType; + if (!item) + return; + if (!self->settings->timelineIsShowUnused && item->frames.empty() && (type == ANM2_LAYER || type == ANM2_NULL)) + return; + + ImVec2 buttonSize = ImVec2(ATLAS_SIZE_NORMAL) + (defaultFramePadding * ImVec2(2, 2)); + + Anm2Layer* layer = nullptr; + Anm2Null* null = nullptr; + int buttonCount = type == ANM2_NULL ? 2 : 1; + float buttonAreaWidth = buttonCount * buttonSize.x + (buttonCount - 1) * defaultItemSpacing.x; + bool isSelected = (self->reference->itemID == reference.itemID && self->reference->itemType == type); + + ImGui::PushID(reference.itemID); + + ImVec2 childPos = ImGui::GetCursorScreenPos(); + _imgui_begin_child(*IMGUI_TIMELINE_ITEM_CHILDS[type], self); + ImVec2 childSize = ImGui::GetContentRegionAvail(); + + const ImguiItem* selectable = IMGUI_TIMELINE_ITEM_SELECTABLES[type]; + + std::string dragDrop = selectable->drag_drop_get(); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, defaultItemSpacing); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, defaultWindowPadding); + + _imgui_selectable(selectable->copy({.isSelected = isSelected}), self); + + if (imgui_begin_popup_modal(IMGUI_POPUP_ITEM_PROPERTIES, self, IMGUI_POPUP_ITEM_PROPERTIES_SIZE)) { + static int selectedLayerID = ID_NONE; + static int selectedNullID = ID_NONE; + Anm2Type& type = reference.itemType; + + _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, self); + + _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER.copy({.isDisabled = true}), self, (int&)type); + _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL.copy({.isDisabled = true}), self, (int&)type); + + _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD + + _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, self); + + switch (type) { + case ANM2_LAYER: + default: { + for (auto& [id, layer] : self->anm2->layers) { + if (id == reference.itemID) + continue; + + ImGui::PushID(id); + + ImguiItem layerItem = IMGUI_LAYER.copy({.label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), .isSelected = selectedLayerID = id, .id = id}); + if (_imgui_atlas_selectable(layerItem, self)) + selectedLayerID = id; + + ImGui::PopID(); + }; + break; + } + case ANM2_NULL: { + for (auto& [id, null] : self->anm2->nulls) { + if (id == reference.itemID) + continue; + + ImGui::PushID(id); + + ImguiItem nullItem = IMGUI_NULL.copy({.label = std::format(IMGUI_NULL_FORMAT, id, null.name), .isSelected = selectedNullID == id, .id = id}); + if (_imgui_atlas_selectable(nullItem, self)) + selectedNullID = id; + + ImGui::PopID(); + }; + break; + } + } + + _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD + + _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD, self); + + if (self->anm2->layers.size() == 0) + selectedLayerID = ID_NONE; + if (self->anm2->nulls.size() == 0) + selectedNullID = ID_NONE; + + bool isDisabled = type == ANM2_NONE || (type == ANM2_LAYER && selectedLayerID == ID_NONE) || (type == ANM2_NULL && selectedNullID == ID_NONE); + + if (_imgui_button(IMGUI_TIMELINE_ITEM_PROPERTIES_CONFIRM.copy({.isDisabled = isDisabled}), self)) { + switch (type) { + case ANM2_LAYER: + if (!map_find(animation->layerAnimations, selectedLayerID)) { + anm2_animation_layer_animation_add(animation, selectedLayerID); + anm2_animation_layer_animation_remove(animation, reference.itemID); + } else + map_swap(animation->layerAnimations, selectedLayerID, reference.itemID); + + *self->reference = {self->reference->animationID, ANM2_LAYER, selectedLayerID}; + selectedLayerID = ID_NONE; + break; + case ANM2_NULL: + if (!map_find(animation->nullAnimations, selectedNullID)) { + anm2_animation_null_animation_add(animation, selectedNullID); + anm2_animation_null_animation_remove(animation, reference.itemID); + + } else + map_swap(animation->nullAnimations, selectedNullID, reference.itemID); + + *self->reference = {self->reference->animationID, ANM2_NULL, selectedNullID}; + selectedNullID = ID_NONE; + break; + default: + break; + } + + imgui_close_current_popup(self); + } + + if (_imgui_button(IMGUI_POPUP_CANCEL, self)) + imgui_close_current_popup(self); + + _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD + + imgui_end_popup(self); + } + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None) && !dragDrop.empty()) { + *self->reference = reference; + + ImGui::SetDragDropPayload(dragDrop.c_str(), &reference, sizeof(Anm2Reference)); + timeline_item_child(reference, index); + ImGui::EndDragDropSource(); + } + ImGui::PopStyleVar(); + + if (ImGui::BeginDragDropTarget()) { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(dragDrop.c_str())) { + Anm2Reference checkReference = *(Anm2Reference*)payload->Data; + if (checkReference != reference) { + swapItemReference = reference; + isItemSwap = true; + } + } + + ImGui::EndDragDropTarget(); + } + + ImGui::SetCursorScreenPos({childPos.x + childSize.x - buttonAreaWidth, childPos.y + defaultWindowPadding.y}); + + if (type == ANM2_NULL && null) { + const ImguiItem& rectItem = null->isShowRect ? IMGUI_TIMELINE_ITEM_SHOW_RECT : IMGUI_TIMELINE_ITEM_HIDE_RECT; + if (_imgui_atlas_button(rectItem, self)) + null->isShowRect = !null->isShowRect; + ImGui::SameLine(0.0f, defaultItemSpacing.x); + } + + const ImguiItem& visibleItem = item->isVisible ? IMGUI_TIMELINE_ITEM_VISIBLE : IMGUI_TIMELINE_ITEM_INVISIBLE; + if (_imgui_atlas_button(visibleItem, self)) + item->isVisible = !item->isVisible; + + ImGui::PopStyleVar(2); + + _imgui_end_child(); // itemChild + + ImGui::PopID(); + + index++; + }; + + std::function timeline_items_child = [&]() { + static int& animationID = self->reference->animationID; + int index = 0; + + _imgui_begin_child(IMGUI_TIMELINE_ITEMS_CHILD, self); + ImGui::SetScrollY(scroll.y); + + timeline_item_child({animationID, ANM2_ROOT}, index); + + for (auto& id : std::ranges::reverse_view(animation->layerOrder)) + timeline_item_child({animationID, ANM2_LAYER, id}, index); + + for (auto& [id, null] : animation->nullAnimations) + timeline_item_child({animationID, ANM2_NULL, id}, index); + + timeline_item_child({animationID, ANM2_TRIGGER}, index); + + _imgui_end_child(); // IMGUI_TIMELINE_ITEMS_CHILD + + if (isItemSwap) { + Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); + + imgui_snapshot(self, IMGUI_ACTION_ITEM_SWAP); + + switch (swapItemReference.itemType) { + case ANM2_LAYER: + vector_value_swap(animation->layerOrder, self->reference->itemID, swapItemReference.itemID); + break; + case ANM2_NULL: + map_swap(animation->nullAnimations, self->reference->itemID, swapItemReference.itemID); + break; + default: + break; + } + + self->reference->itemID = swapItemReference.itemID; + swapItemReference = Anm2Reference(); + isItemSwap = false; + } + }; + + std::function timeline_item_frames = [&](Anm2Reference reference, int& index) { + Anm2Item* item = anm2_item_from_reference(self->anm2, reference); + if (!item) + return; + Anm2Type& type = reference.itemType; + if (!self->settings->timelineIsShowUnused && item->frames.empty() && (type == ANM2_LAYER || type == ANM2_NULL)) + return; + + ImGui::PushID(index); + + ImDrawList* drawList = ImGui::GetWindowDrawList(); + + float viewWidth = ImGui::GetContentRegionAvail().x; + + _imgui_begin_child(IMGUI_TIMELINE_ITEM_FRAMES_CHILD.copy({.size = actualFramesSize.x > framesSize.x ? actualFramesSize : framesSize}), self); + + ImVec2 startPos = ImGui::GetCursorPos(); + ImVec2 cursorPos = ImGui::GetCursorScreenPos(); + + if (_imgui_is_window_hovered()) { + hoverReference = reference; + hoverReference.frameIndex = anm2_frame_index_from_time(self->anm2, reference, frameTime); + self->clipboard->location = hoverReference; + self->clipboard->type = CLIPBOARD_FRAME; + + if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) { + *self->reference = reference; + if (reference.itemType == ANM2_LAYER && reference.itemID != ID_NONE) + self->editor->spritesheetID = self->anm2->layers[self->reference->itemID].spritesheetID; + } + } + + int start = (int)std::floor(scroll.x / frameSize.x) - 1; + if (start < 0) + start = 0; + + int end = (int)std::ceil((scroll.x + viewWidth) / frameSize.x) + 1; + if (end > ANM2_FRAME_NUM_MAX) + end = ANM2_FRAME_NUM_MAX; + + for (int i = start; i < end; i++) { + bool isMultiple = (i % IMGUI_TIMELINE_FRAME_MULTIPLE) == 0; + ImU32 bgColor = isMultiple ? frameMultipleColor : frameColor; + + float startX = cursorPos.x + i * frameSize.x; + float endX = startX + frameSize.x; + ImVec2 startPosition(startX, cursorPos.y); + ImVec2 endPosition(endX, cursorPos.y + frameSize.y); + + drawList->AddRectFilled(startPosition, endPosition, bgColor); + drawList->AddImage(self->resources->atlas.id, startPosition, endPosition, ATLAS_UV_ARGS(ATLAS_FRAME)); + } + + ImGui::SetCursorPos(startPos); + + std::function timeline_item_frame = [&](int i, Anm2Frame& frame) { + static int frameDelayStart{}; + static float frameDelayTimeStart{}; + const bool isModCtrl = ImGui::IsKeyDown(IMGUI_INPUT_CTRL); + const bool isModAlt = ImGui::IsKeyDown(IMGUI_INPUT_ALT); + static bool isDrag = false; + + ImGui::PushID(i); + reference.frameIndex = i; + ImVec2 framePos = ImGui::GetCursorPos(); + AtlasType atlas = frame.isInterpolated ? ATLAS_CIRCLE : ATLAS_SQUARE; + + if (type == ANM2_TRIGGER) { + framePos.x = startPos.x + (frameSize.x * frame.atFrame); + atlas = ATLAS_TRIGGER; + } + + ImguiItem frameButton = IMGUI_TIMELINE_FRAMES[type]->copy( + {.atlas = atlas, .size = vec2(frameSize.x * frame.delay, frameSize.y), .isSelected = reference == *self->reference, .id = i}); + + ImGui::SetCursorPos(framePos); + + if (_imgui_atlas_button(frameButton, self)) { + if (isModAlt) + frame.isInterpolated = !frame.isInterpolated; + else { + *self->reference = reference; + frameDelayStart = frame.delay; + frameDelayTimeStart = frameTime; + self->preview->time = frameTime; + } + } + + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoPreviewTooltip)) { + if (!isDrag) { + *self->reference = reference; + frameDelayStart = frame.delay; + frameDelayTimeStart = frameTime; + isDrag = true; + } + + ImGui::SetDragDropPayload(frameButton.drag_drop_get(), &reference, sizeof(Anm2Reference)); + if (!isModCtrl && type != ANM2_TRIGGER) { + ImGui::BeginTooltip(); + _imgui_atlas_button(frameButton, self); + ImGui::EndTooltip(); + } + ImGui::EndDragDropSource(); + } + + if (isDrag) { + self->pendingCursor = SDL_SYSTEM_CURSOR_POINTER; + + if (Anm2Frame* referenceFrame = anm2_frame_from_reference(self->anm2, *self->reference)) { + switch (self->reference->itemType) { + case ANM2_TRIGGER: { + referenceFrame->atFrame = std::max(frameTime, 0); + for (auto& trigger : animation->triggers.frames) { + if (&trigger == referenceFrame) + continue; + if (trigger.atFrame == referenceFrame->atFrame) { + referenceFrame->atFrame++; + break; + } + } + break; + } + case ANM2_ROOT: + case ANM2_LAYER: + case ANM2_NULL: { + if (isModCtrl) + referenceFrame->delay = std::max(frameDelayStart + (int)(frameTime - frameDelayTimeStart), ANM2_FRAME_NUM_MIN); + break; + } + default: + break; + } + } + } + + if (ImGui::BeginDragDropTarget()) { + ImGui::AcceptDragDropPayload(frameButton.drag_drop_get()); + ImGui::EndDragDropTarget(); + } + + if (isDrag && ImGui::IsMouseReleased(0)) { + if (!isModCtrl && *self->reference != hoverReference && self->reference->itemType == hoverReference.itemType) { + imgui_snapshot(self, IMGUI_ACTION_FRAME_MOVE); + if (Anm2Frame* referenceFrame = anm2_frame_from_reference(self->anm2, *self->reference)) { + Anm2Reference addReference = hoverReference; + addReference.frameIndex = + hoverReference.frameIndex < self->reference->frameIndex ? std::min(0, addReference.frameIndex - 2) : std::min(0, addReference.frameIndex - 1); + Anm2Frame addFrame = *referenceFrame; + anm2_frame_remove(self->anm2, *self->reference); + anm2_frame_add(self->anm2, &addFrame, hoverReference); + *self->reference = hoverReference; + hoverReference = Anm2Reference(); + } + } + + isDrag = false; + } + + if (i < (int)item->frames.size() - 1) + ImGui::SameLine(); + + ImGui::PopID(); }; - onionskin_section(IMGUI_ONIONSKIN_BEFORE, beforeCount, beforeColorOffset); - onionskin_section(IMGUI_ONIONSKIN_AFTER, afterCount, afterColorOffset); - - ImGui::Separator(); + for (auto [i, frame] : std::views::enumerate(item->frames)) + timeline_item_frame(i, frame); - _imgui_text(IMGUI_ONIONSKIN_DRAW_ORDER, self); - _imgui_radio_button(IMGUI_ONIONSKIN_BELOW.copy({!isEnabled}), self, drawOrder); - _imgui_radio_button(IMGUI_ONIONSKIN_ABOVE.copy({!isEnabled}), self, drawOrder); + _imgui_end_child(); // itemFramesChild - _imgui_end(); // IMGUI_ONIONSKIN + ImGui::PopID(); + + index++; + }; + + std::function timeline_frames_child = [&]() { + int& animationID = self->reference->animationID; + int index = 0; + + _imgui_begin_child(IMGUI_TIMELINE_FRAMES_CHILD, self); + scroll.x = ImGui::GetScrollX() + scrollDelta.x; + scroll.y = ImGui::GetScrollY() + scrollDelta.y; + ImGui::SetScrollX(scroll.x); + ImGui::SetScrollY(scroll.y); + + timeline_item_frames(Anm2Reference(animationID, ANM2_ROOT), index); + + for (auto& id : std::ranges::reverse_view(animation->layerOrder)) + timeline_item_frames(Anm2Reference(animationID, ANM2_LAYER, id), index); + + for (auto& [id, null] : animation->nullAnimations) + timeline_item_frames(Anm2Reference(animationID, ANM2_NULL, id), index); + + timeline_item_frames(Anm2Reference(animationID, ANM2_TRIGGER), index); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, defaultItemSpacing); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, defaultWindowPadding); + _imgui_context_menu(self); + ImGui::PopStyleVar(2); + + _imgui_end_child(); // IMGUI_TIMELINE_FRAMES_CHILD + }; + + // In order to set scroll properly timeline_frames_child must be called first + ImGui::SetCursorPos(ImVec2(IMGUI_TIMELINE_ITEM_SIZE)); + timeline_frames_child(); + ImGui::SetCursorPos(ImVec2()); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, defaultItemSpacing); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, defaultWindowPadding); + + _imgui_begin_child(IMGUI_TIMELINE_ITEM_CHILD, self); + + const ImguiItem& unusedItem = self->settings->timelineIsShowUnused ? IMGUI_TIMELINE_SHOW_UNUSED : IMGUI_TIMELINE_HIDE_UNUSED; + if (_imgui_atlas_button(unusedItem, self)) + self->settings->timelineIsShowUnused = !self->settings->timelineIsShowUnused; + ImGui::PopStyleVar(2); + + _imgui_end_child(); // IMGUI_TIMELINE_ITEM_CHILD + ImGui::SameLine(); + timeline_header(); + + timeline_items_child(); + + ImGui::PopStyleVar(2); + + _imgui_end_child(); // IMGUI_TIMELINE_CHILD + + Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *self->reference); + Anm2Item* item = anm2_item_from_reference(self->anm2, *self->reference); + _imgui_begin_child(IMGUI_TIMELINE_ITEM_FOOTER_CHILD, self); + + _imgui_button(IMGUI_TIMELINE_ADD_ITEM, self); + + if (imgui_begin_popup_modal(IMGUI_TIMELINE_ADD_ITEM.popup, self, IMGUI_TIMELINE_ADD_ITEM.popupSize)) { + static int selectedLayerID = ID_NONE; + static int selectedNullID = ID_NONE; + int& type = self->settings->timelineAddItemType; + + _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, self); + + _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER, self, type); + _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL, self, type); + + _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD + + _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, self); + + switch (type) { + case ANM2_LAYER: + default: { + for (auto& [id, layer] : self->anm2->layers) { + ImGui::PushID(id); + + ImguiItem layerItem = IMGUI_LAYER.copy({.label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), .isSelected = selectedLayerID == id, .id = id}); + if (_imgui_atlas_selectable(layerItem, self)) + selectedLayerID = id; + + ImGui::PopID(); + }; + break; + } + case ANM2_NULL: { + for (auto& [id, null] : self->anm2->nulls) { + ImGui::PushID(id); + + ImguiItem nullItem = IMGUI_NULL.copy({.label = std::format(IMGUI_NULL_FORMAT, id, null.name), .isSelected = selectedNullID == id, .id = id}); + if (_imgui_atlas_selectable(nullItem, self)) + selectedNullID = id; + + ImGui::PopID(); + }; + break; + } + } + + _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD + + _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD, self); + + if (self->anm2->layers.size() == 0) + selectedLayerID = ID_NONE; + if (self->anm2->nulls.size() == 0) + selectedNullID = ID_NONE; + + bool isDisabled = type == ANM2_NONE || (type == ANM2_LAYER && selectedLayerID == ID_NONE) || (type == ANM2_NULL && selectedNullID == ID_NONE); + + if (_imgui_button(IMGUI_TIMELINE_ITEM_PROPERTIES_CONFIRM.copy({.isDisabled = isDisabled}), self)) { + switch (type) { + case ANM2_LAYER: + anm2_animation_layer_animation_add(animation, selectedLayerID); + *self->reference = {self->reference->animationID, ANM2_LAYER, selectedLayerID}; + selectedLayerID = ID_NONE; + break; + case ANM2_NULL: + anm2_animation_null_animation_add(animation, selectedNullID); + *self->reference = {self->reference->animationID, ANM2_NULL, selectedNullID}; + selectedNullID = ID_NONE; + break; + default: + break; + } + + imgui_close_current_popup(self); + } + + if (_imgui_button(IMGUI_POPUP_CANCEL, self)) + imgui_close_current_popup(self); + + _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD + + imgui_end_popup(self); + } + + if (_imgui_button(IMGUI_TIMELINE_REMOVE_ITEM.copy({.isDisabled = !item || itemType == ANM2_ROOT || itemType == ANM2_TRIGGER}), self)) { + switch (itemType) { + case ANM2_LAYER: + anm2_animation_layer_animation_remove(animation, itemID); + break; + case ANM2_NULL: + anm2_animation_null_animation_remove(animation, itemID); + break; + default: + break; + } + + *self->reference = {self->reference->animationID}; + } + + _imgui_end_child(); // IMGUI_TIMELINE_FOOTER_ITEM_CHILD + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); + ImGui::SameLine(); + ImGui::PopStyleVar(); + + _imgui_begin_child(IMGUI_TIMELINE_OPTIONS_FOOTER_CHILD, self); + + if (_imgui_button(self->preview->isPlaying ? IMGUI_PAUSE : IMGUI_PLAY, self)) { + if (!self->preview->isPlaying && time >= animation->frameNum - 1) + time = 0.0f; + self->preview->isPlaying = !self->preview->isPlaying; + } + + if (_imgui_button(IMGUI_INSERT_FRAME.copy({.isDisabled = !item}), self)) { + Anm2Reference frameReference = *self->reference; + Anm2Frame addFrame = Anm2Frame(); + + switch (self->reference->itemType) { + case ANM2_ROOT: + case ANM2_LAYER: + case ANM2_NULL: + frameReference.frameIndex = item->frames.empty() ? 0 : std::clamp(frameReference.frameIndex, 0, (int)(item->frames.size() - 1)); + + addFrame = *anm2_frame_from_reference(self->anm2, frameReference); + break; + case ANM2_TRIGGER: + addFrame.atFrame = (int)self->preview->time; + break; + default: + break; + } + + anm2_frame_add(self->anm2, &addFrame, frameReference); + } + + if (_imgui_button(IMGUI_REMOVE_FRAME.copy({.isDisabled = !frame}), self)) { + anm2_frame_remove(self->anm2, *self->reference); + self->reference->frameIndex = ID_NONE; + } + + _imgui_button(IMGUI_BAKE.copy({.isDisabled = !frame || itemType == ANM2_TRIGGER}), self); + + if (imgui_begin_popup_modal(IMGUI_BAKE.popup, self, IMGUI_BAKE.popupSize)) { + static int& interval = self->settings->bakeInterval; + static bool& isRoundScale = self->settings->bakeIsRoundScale; + static bool& isRoundRotation = self->settings->bakeIsRoundRotation; + + _imgui_begin_child(IMGUI_BAKE_CHILD, self); + + _imgui_input_int(IMGUI_BAKE_INTERVAL.copy({.max = frame->delay}), self, interval); + _imgui_checkbox(IMGUI_BAKE_ROUND_SCALE, self, isRoundScale); + _imgui_checkbox(IMGUI_BAKE_ROUND_ROTATION, self, isRoundRotation); + + if (_imgui_button(IMGUI_BAKE_CONFIRM, self)) { + anm2_frame_bake(self->anm2, *self->reference, interval, isRoundScale, isRoundRotation); + imgui_close_current_popup(self); + } + + if (_imgui_button(IMGUI_POPUP_CANCEL, self)) + imgui_close_current_popup(self); + + _imgui_end_child(); // IMGUI_BAKE_CHILD) + + imgui_end_popup(self); + } + + if (_imgui_button(IMGUI_FIT_ANIMATION_LENGTH, self)) + anm2_animation_length_set(animation); + + _imgui_input_int(IMGUI_ANIMATION_LENGTH, self, animation->frameNum); + _imgui_input_int(IMGUI_FPS, self, self->anm2->fps); + _imgui_checkbox(IMGUI_LOOP, self, animation->isLoop); + _imgui_selectable_input_text(IMGUI_CREATED_BY.copy({.label = self->anm2->createdBy}), self, self->anm2->createdBy); + + _imgui_end_child(); // IMGUI_TIMELINE_FOOTER_OPTIONS_CHILD + + _imgui_end(); // IMGUI_TIMELINE } -static void _imgui_taskbar(Imgui* self) -{ - static ImguiPopupState exitConfirmState = IMGUI_POPUP_STATE_CLOSED; +static void _imgui_onionskin(Imgui* self) { + IMGUI_BEGIN_OR_RETURN(IMGUI_ONIONSKIN, self); - ImGuiViewport* viewport = ImGui::GetMainViewport(); - ImguiItem taskbar = IMGUI_TASKBAR; - ImGui::SetNextWindowSize({viewport->Size.x, IMGUI_TASKBAR.size.y}); - ImGui::SetNextWindowPos(viewport->Pos); - _imgui_begin(taskbar, self); + static auto& isEnabled = self->settings->onionskinIsEnabled; + static auto& beforeCount = self->settings->onionskinBeforeCount; + static auto& afterCount = self->settings->onionskinAfterCount; + static auto& beforeColorOffset = self->settings->onionskinBeforeColorOffset; + static auto& afterColorOffset = self->settings->onionskinAfterColorOffset; + static auto& drawOrder = self->settings->onionskinDrawOrder; - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference); - Anm2Item* item = anm2_item_from_reference(self->anm2, self->reference); + _imgui_checkbox(IMGUI_ONIONSKIN_ENABLED, self, isEnabled); - _imgui_selectable(IMGUI_FILE, self); - - if (imgui_begin_popup(IMGUI_FILE.popup, self)) - { - _imgui_selectable(IMGUI_NEW, self); - _imgui_selectable(IMGUI_OPEN, self); - _imgui_selectable(IMGUI_SAVE.copy({self->anm2->path.empty()}), self); - _imgui_selectable(IMGUI_SAVE_AS.copy({self->anm2->path.empty()}), self); - _imgui_selectable(IMGUI_EXPLORE_ANM2_LOCATION.copy({self->anm2->path.empty()}), self); - _imgui_selectable(IMGUI_EXIT, self); - imgui_end_popup(self); - } + auto onionskin_section = [&](auto& text, auto& count, auto& colorOffset) { + ImGui::PushID(text.label.c_str()); + _imgui_text(text, self); + _imgui_input_int(IMGUI_ONIONSKIN_COUNT.copy({.isDisabled = !isEnabled}), self, count); + _imgui_color_edit3(IMGUI_ONIONSKIN_COLOR_OFFSET.copy({.isDisabled = !isEnabled}), self, colorOffset); + ImGui::PopID(); + }; - if (self->dialog->isSelected && self->dialog->type == DIALOG_ANM2_OPEN) - { - _imgui_anm2_open(self, self->dialog->path); - dialog_reset(self->dialog); - } + onionskin_section(IMGUI_ONIONSKIN_BEFORE, beforeCount, beforeColorOffset); + onionskin_section(IMGUI_ONIONSKIN_AFTER, afterCount, afterColorOffset); - if (self->dialog->isSelected && self->dialog->type == DIALOG_ANM2_SAVE) - { - anm2_serialize(self->anm2, self->dialog->path); - window_title_from_path_set(self->window, self->dialog->path); - imgui_log_push(self, std::format(IMGUI_LOG_FILE_SAVE_FORMAT, self->dialog->path)); - dialog_reset(self->dialog); - } + ImGui::Separator(); - if (self->isTryQuit) imgui_open_popup(IMGUI_EXIT_CONFIRMATION.label); + _imgui_text(IMGUI_ONIONSKIN_DRAW_ORDER, self); + _imgui_radio_button(IMGUI_ONIONSKIN_BELOW.copy({.isDisabled = !isEnabled}), self, drawOrder); + _imgui_radio_button(IMGUI_ONIONSKIN_ABOVE.copy({.isDisabled = !isEnabled}), self, drawOrder); - _imgui_confirm_popup(IMGUI_EXIT_CONFIRMATION, self, &exitConfirmState); + _imgui_end(); // IMGUI_ONIONSKIN +} +*/ - switch (exitConfirmState) - { - case IMGUI_POPUP_STATE_CONFIRM: self->isQuit = true; break; - case IMGUI_POPUP_STATE_CANCEL: self->isTryQuit = false; break; - default: break; - } +static void _imgui_taskbar(Imgui* self) { + static ImguiPopupState exitConfirmState = IMGUI_POPUP_STATE_CLOSED; + static float& displayScale = self->settings->displayScale; - _imgui_selectable(IMGUI_WIZARD.copy({}), self); - - if (imgui_begin_popup(IMGUI_WIZARD.popup, self)) - { - _imgui_selectable(IMGUI_GENERATE_ANIMATION_FROM_GRID.copy({!item || (self->reference->itemType != ANM2_LAYER)}), self); - _imgui_selectable(IMGUI_CHANGE_ALL_FRAME_PROPERTIES.copy({!item}), self); - _imgui_selectable(IMGUI_SCALE_ANM2.copy({self->anm2->animations.empty()}), self); - _imgui_selectable(IMGUI_RENDER_ANIMATION.copy({!animation}), self); - - imgui_end_popup(self); - } + ImGuiViewport* viewport = ImGui::GetMainViewport(); + ImguiItem taskbar = IMGUI_TASKBAR; + ImGui::SetNextWindowSize({viewport->Size.x, IMGUI_TASKBAR.size->y * displayScale}); + ImGui::SetNextWindowPos(viewport->Pos); + _imgui_begin(taskbar, self); - if (imgui_begin_popup_modal(IMGUI_GENERATE_ANIMATION_FROM_GRID.popup, self, IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize)) - { - static auto& startPosition = self->settings->generateStartPosition; - static auto& size = self->settings->generateSize; - static auto& pivot = self->settings->generatePivot; - static auto& rows = self->settings->generateRows; - static auto& columns = self->settings->generateColumns; - static auto& count = self->settings->generateCount; - static auto& delay = self->settings->generateDelay; - static f32& time = self->generatePreview->time; + Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); + Anm2Item* item = anm2_item_from_reference(self->anm2, *self->reference); - _imgui_begin_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_OPTIONS_CHILD, self); - _imgui_input_int2(IMGUI_GENERATE_ANIMATION_FROM_GRID_START_POSITION, self, startPosition); - _imgui_input_int2(IMGUI_GENERATE_ANIMATION_FROM_GRID_SIZE, self, size); - _imgui_input_int2(IMGUI_GENERATE_ANIMATION_FROM_GRID_PIVOT, self, pivot); - _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_ROWS, self, rows); - _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_COLUMNS, self, columns); - _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_COUNT.copy({.max = rows * columns}), self, count); - _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_DELAY, self, delay); - _imgui_end_child(); //IMGUI_GENERATE_ANIMATION_FROM_GRID_OPTIONS_CHILD - - ImGui::SameLine(); + _imgui_selectable(IMGUI_FILE, self); - _imgui_begin_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_PREVIEW_CHILD, self); - - generate_preview_draw(self->generatePreview); - ImGui::Image(self->generatePreview->canvas.framebuffer, GENERATE_PREVIEW_SIZE); + if (imgui_begin_popup(IMGUI_FILE.popup, self)) { + _imgui_selectable(IMGUI_NEW, self); + _imgui_selectable(IMGUI_OPEN, self); + _imgui_selectable(IMGUI_SAVE.copy({.isDisabled = self->anm2->path.empty()}), self); + _imgui_selectable(IMGUI_SAVE_AS.copy({.isDisabled = self->anm2->path.empty()}), self); + _imgui_selectable(IMGUI_EXPLORE_ANM2_LOCATION.copy({.isDisabled = self->anm2->path.empty()}), self); + _imgui_selectable(IMGUI_EXIT, self); + imgui_end_popup(self); + } - _imgui_begin_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER_CHILD, self); - _imgui_slider_float(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER, self, time); - _imgui_end_child(); // IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER_CHILD + if (self->dialog->isSelected && self->dialog->type == DIALOG_ANM2_OPEN) { + _imgui_anm2_open(self, self->dialog->path); + dialog_reset(self->dialog); + } - _imgui_end_child(); //IMGUI_GENERATE_ANIMATION_FROM_GRID_PREVIEW_CHILD - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - if (_imgui_button(IMGUI_GENERATE_ANIMATION_FROM_GRID_GENERATE, self)) - { - anm2_generate_from_grid(self->anm2, self->reference, startPosition, size, pivot, columns, count, delay); - imgui_close_current_popup(self); - } - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) imgui_close_current_popup(self); - _imgui_end_child(); // IMGUI_FOOTER_CHILD + if (self->dialog->isSelected && self->dialog->type == DIALOG_ANM2_SAVE) { + anm2_serialize(self->anm2, self->dialog->path); + window_title_from_path_set(self->window, self->dialog->path); + imgui_log_push(self, std::format(IMGUI_LOG_FILE_SAVE_FORMAT, self->dialog->path)); + dialog_reset(self->dialog); + } - imgui_end_popup(self); - } + if (self->isTryQuit && !imgui_is_popup_open(IMGUI_EXIT_CONFIRMATION.label)) + imgui_open_popup(IMGUI_EXIT_CONFIRMATION.label); - if (imgui_begin_popup_modal(IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popup, self, IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popupSize)) - { - static auto& isCrop = self->settings->changeIsCrop; - static auto& isSize = self->settings->changeIsSize; - static auto& isPosition = self->settings->changeIsPosition; - static auto& isPivot = self->settings->changeIsPivot; - static auto& isScale = self->settings->changeIsScale; - static auto& isRotation = self->settings->changeIsRotation; - static auto& isColorOffset = self->settings->changeIsColorOffset; - static auto& isTint = self->settings->changeIsTint; - static auto& isVisibleSet = self->settings->changeIsVisibleSet; - static auto& isInterpolatedSet = self->settings->changeIsInterpolatedSet; - static auto& crop = self->settings->changeCrop; - static auto& size = self->settings->changeSize; - static auto& position = self->settings->changePosition; - static auto& pivot = self->settings->changePivot; - static auto& scale = self->settings->changeScale; - static auto& rotation = self->settings->changeRotation; - static auto& isDelay = self->settings->changeIsDelay; - static auto& delay = self->settings->changeDelay; - static auto& tint = self->settings->changeTint; - static auto& colorOffset = self->settings->changeColorOffset; - static auto& isVisible = self->settings->changeIsVisible; - static auto& isInterpolated = self->settings->changeIsInterpolated; - static auto& isFromSelectedFrame = self->settings->changeIsFromSelectedFrame; - static auto& numberFrames = self->settings->changeNumberFrames; - s32 start = std::max(self->reference->frameIndex, 0); - s32 max = isFromSelectedFrame ? - std::max(ANM2_FRAME_NUM_MIN, (s32)item->frames.size() - start) : (s32)item->frames.size(); + _imgui_confirm_popup(IMGUI_EXIT_CONFIRMATION, self, &exitConfirmState); - auto change_frames = [&](Anm2ChangeType type) - { - anm2_item_frame_set - ( - self->anm2, self->reference, - Anm2FrameChange - { - isVisibleSet ? std::optional{isVisible} : std::nullopt, - isInterpolatedSet ? std::optional{isInterpolated} : std::nullopt, - isRotation ? std::optional{rotation} : std::nullopt, - isDelay ? std::optional{delay} : std::nullopt, - isCrop ? std::optional{crop} : std::nullopt, - isPivot ? std::optional{pivot} : std::nullopt, - isPosition ? std::optional{position} : std::nullopt, - isSize ? std::optional{size} : std::nullopt, - isScale ? std::optional{scale} : std::nullopt, - isColorOffset ? std::optional{colorOffset} : std::nullopt, - isTint ? std::optional{tint} : std::nullopt - }, - type, start, numberFrames - ); + switch (exitConfirmState) { + case IMGUI_POPUP_STATE_CONFIRM: + self->isQuit = true; + break; + case IMGUI_POPUP_STATE_CANCEL: + self->isTryQuit = false; + break; + default: + break; + } - imgui_close_current_popup(self); - }; + _imgui_selectable(IMGUI_WIZARD.copy({}), self); - _imgui_begin_child(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CHILD, self); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_CROP.copy({!isCrop}), self, crop, isCrop); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_SIZE.copy({!isSize}), self, size, isSize); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_POSITION.copy({!isPosition}), self, position, isPosition); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_PIVOT.copy({!isPivot}), self, pivot, isPivot); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_SCALE.copy({!isScale}), self, scale, isScale); - _imgui_checkbox_drag_float(IMGUI_FRAME_PROPERTIES_ROTATION.copy({!isRotation}), self, rotation, isRotation); - _imgui_checkbox_input_int(IMGUI_FRAME_PROPERTIES_DELAY.copy({!isDelay}), self, delay, isDelay); - _imgui_checkbox_color_edit4(IMGUI_FRAME_PROPERTIES_TINT.copy({!isTint}), self, tint, isTint); - _imgui_checkbox_color_edit3(IMGUI_FRAME_PROPERTIES_COLOR_OFFSET.copy({!isColorOffset}), self, colorOffset, isColorOffset); - _imgui_checkbox_checkbox(IMGUI_FRAME_PROPERTIES_VISIBLE.copy({!isVisibleSet}), self, isVisible, isVisibleSet); - ImGui::NewLine(); - _imgui_checkbox_checkbox(IMGUI_FRAME_PROPERTIES_INTERPOLATED.copy({!isInterpolatedSet}), self, isInterpolated, isInterpolatedSet); - _imgui_end_child(); // IMGUI_FOOTER_CHILD + if (imgui_begin_popup(IMGUI_WIZARD.popup, self)) { + _imgui_selectable(IMGUI_GENERATE_ANIMATION_FROM_GRID.copy({.isDisabled = !item || (self->reference->itemType != ANM2_LAYER)}), self); + _imgui_selectable(IMGUI_CHANGE_ALL_FRAME_PROPERTIES.copy({.isDisabled = !item}), self); + _imgui_selectable(IMGUI_SCALE_ANM2.copy({.isDisabled = self->anm2->animations.empty()}), self); + _imgui_selectable(IMGUI_RENDER_ANIMATION.copy({.isDisabled = !animation}), self); - _imgui_begin_child(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS_CHILD, self); - _imgui_text(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS, self); - _imgui_checkbox(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_FROM_SELECTED_FRAME, self, isFromSelectedFrame); - _imgui_input_int(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_NUMBER_FRAMES.copy({.max = max, .value = max}), self, numberFrames); - _imgui_end_child(); // IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS_CHILD + imgui_end_popup(self); + } - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_ADD, self)) change_frames(ANM2_CHANGE_ADD); - if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SUBTRACT, self)) change_frames(ANM2_CHANGE_SUBTRACT); - if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SET, self)) change_frames(ANM2_CHANGE_SET); - if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CANCEL, self)) imgui_close_current_popup(self); - _imgui_end_child(); // IMGUI_FOOTER_CHILD - - imgui_end_popup(self); - } + if (imgui_begin_popup_modal(IMGUI_GENERATE_ANIMATION_FROM_GRID.popup, self, IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize)) { + static auto& startPosition = self->settings->generateStartPosition; + static auto& size = self->settings->generateSize; + static auto& pivot = self->settings->generatePivot; + static auto& rows = self->settings->generateRows; + static auto& columns = self->settings->generateColumns; + static auto& count = self->settings->generateCount; + static auto& delay = self->settings->generateDelay; + static float& time = self->generatePreview->time; - if (imgui_begin_popup_modal(IMGUI_SCALE_ANM2.popup, self, IMGUI_SCALE_ANM2.popupSize)) - { - _imgui_begin_child(IMGUI_SCALE_ANM2_OPTIONS_CHILD, self); - _imgui_input_float(IMGUI_SCALE_ANM2_VALUE, self, self->settings->scaleValue); - _imgui_end_child(); // IMGUI_SCALE_ANM2_OPTIONS_CHILD - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - if (_imgui_button(IMGUI_SCALE_ANM2_SCALE, self)) - { - anm2_scale(self->anm2, self->settings->scaleValue); - imgui_close_current_popup(self); - } - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) imgui_close_current_popup(self); - _imgui_end_child(); // IMGUI_FOOTER_CHILD + _imgui_begin_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_OPTIONS_CHILD, self); + _imgui_input_int2(IMGUI_GENERATE_ANIMATION_FROM_GRID_START_POSITION, self, startPosition); + _imgui_input_int2(IMGUI_GENERATE_ANIMATION_FROM_GRID_SIZE, self, size); + _imgui_input_int2(IMGUI_GENERATE_ANIMATION_FROM_GRID_PIVOT, self, pivot); + _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_ROWS, self, rows); + _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_COLUMNS, self, columns); + _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_COUNT.copy({.max = rows * columns}), self, count); + _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_DELAY, self, delay); + _imgui_end_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_OPTIONS_CHILD, self); - imgui_end_popup(self); - } + ImGui::SameLine(); - if (imgui_begin_popup_modal(IMGUI_RENDER_ANIMATION.popup, self, IMGUI_RENDER_ANIMATION.popupSize)) - { - static DialogType& dialogType = self->dialog->type; - static bool& dialogIsSelected = self->dialog->isSelected; - static s32& type = self->settings->renderType; - static f32& scale = self->settings->renderScale; - static bool& isUseAnimationBounds = self->settings->renderIsUseAnimationBounds; - static std::string& dialogPath = self->dialog->path; - static std::string& ffmpegPath = self->settings->renderFFmpegPath; - static std::string& format = self->settings->renderFormat; - static std::string& path = self->settings->renderPath; + _imgui_begin_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_PREVIEW_CHILD, self); - _imgui_begin_child(IMGUI_RENDER_ANIMATION_CHILD, self); + generate_preview_draw(self->generatePreview); + ImGui::Image(self->generatePreview->canvas.framebuffer, GENERATE_PREVIEW_SIZE); - if (_imgui_atlas_button(IMGUI_RENDER_ANIMATION_LOCATION_BROWSE, self)) - dialog_render_path_set(self->dialog, (RenderType)type); + _imgui_begin_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER_CHILD, self); + _imgui_slider_float(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER, self, time); + _imgui_end_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER_CHILD, self); + _imgui_end_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_PREVIEW_CHILD, self); - if (dialogIsSelected && (dialogType == DIALOG_RENDER_PATH_SET)) - { - path = path_extension_change(dialogPath, RENDER_EXTENSIONS[type]); - dialog_reset(self->dialog); - } + _imgui_begin_child(IMGUI_FOOTER_CHILD, self); + if (_imgui_button(IMGUI_GENERATE_ANIMATION_FROM_GRID_GENERATE, self)) { + anm2_generate_from_grid(self->anm2, *self->reference, startPosition, size, pivot, columns, count, delay); + imgui_close_current_popup(self); + } + if (_imgui_button(IMGUI_POPUP_CANCEL, self)) + imgui_close_current_popup(self); + _imgui_end_child(IMGUI_FOOTER_CHILD, self); - _imgui_input_text(IMGUI_RENDER_ANIMATION_LOCATION, self, path); - - if (_imgui_atlas_button(IMGUI_RENDER_ANIMATION_FFMPEG_BROWSE, self)) - dialog_ffmpeg_path_set(self->dialog); + imgui_end_popup(self); + } - if (dialogIsSelected && dialogType == DIALOG_FFMPEG_PATH_SET) - { - ffmpegPath = self->dialog->path; - dialog_reset(self->dialog); - } - - _imgui_input_text(IMGUI_RENDER_ANIMATION_FFMPEG_PATH, self, ffmpegPath); - _imgui_combo(IMGUI_RENDER_ANIMATION_OUTPUT, self, &type); - _imgui_input_text(IMGUI_RENDER_ANIMATION_FORMAT.copy({type != RENDER_PNG}), self, format); - _imgui_checkbox(IMGUI_RENDER_ANIMATION_IS_USE_ANIMATION_BOUNDS, self, isUseAnimationBounds); - _imgui_input_float(IMGUI_RENDER_ANIMATION_SCALE.copy({!isUseAnimationBounds}), self, scale); + if (imgui_begin_popup_modal(IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popup, self, IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popupSize)) { + static auto& isCrop = self->settings->changeIsCrop; + static auto& isSize = self->settings->changeIsSize; + static auto& isPosition = self->settings->changeIsPosition; + static auto& isPivot = self->settings->changeIsPivot; + static auto& isScale = self->settings->changeIsScale; + static auto& isRotation = self->settings->changeIsRotation; + static auto& isColorOffset = self->settings->changeIsColorOffset; + static auto& isTint = self->settings->changeIsTint; + static auto& isVisibleSet = self->settings->changeIsVisibleSet; + static auto& isInterpolatedSet = self->settings->changeIsInterpolatedSet; + static auto& crop = self->settings->changeCrop; + static auto& size = self->settings->changeSize; + static auto& position = self->settings->changePosition; + static auto& pivot = self->settings->changePivot; + static auto& scale = self->settings->changeScale; + static auto& rotation = self->settings->changeRotation; + static auto& isDelay = self->settings->changeIsDelay; + static auto& delay = self->settings->changeDelay; + static auto& tint = self->settings->changeTint; + static auto& colorOffset = self->settings->changeColorOffset; + static auto& isVisible = self->settings->changeIsVisible; + static auto& isInterpolated = self->settings->changeIsInterpolated; + static auto& isFromSelectedFrame = self->settings->changeIsFromSelectedFrame; + static auto& numberFrames = self->settings->changeNumberFrames; + int start = std::max(self->reference->frameIndex, 0); + int max = isFromSelectedFrame ? std::max(ANM2_FRAME_NUM_MIN, (int)item->frames.size() - start) : (int)item->frames.size(); - _imgui_end_child(); // IMGUI_RENDER_ANIMATION_CHILD - - _imgui_begin_child(IMGUI_RENDER_ANIMATION_FOOTER_CHILD, self); + auto change_frames = [&](Anm2ChangeType type) { + Anm2FrameChange frameChange = { + .isVisible = isVisibleSet ? std::optional{isVisible} : std::nullopt, + .isInterpolated = isInterpolatedSet ? std::optional{isInterpolated} : std::nullopt, + .rotation = isRotation ? std::optional{rotation} : std::nullopt, + .delay = isDelay ? std::optional{delay} : std::nullopt, + .crop = isCrop ? std::optional{crop} : std::nullopt, + .pivot = isPivot ? std::optional{pivot} : std::nullopt, + .position = isPosition ? std::optional{position} : std::nullopt, + .size = isSize ? std::optional{size} : std::nullopt, + .scale = isScale ? std::optional{scale} : std::nullopt, + .offsetRGB = isColorOffset ? std::optional{colorOffset} : std::nullopt, + .tintRGBA = isTint ? std::optional{tint} : std::nullopt, + }; + anm2_item_frame_set(self->anm2, *self->reference, frameChange, type, start, numberFrames); - if (_imgui_button(IMGUI_RENDER_ANIMATION_CONFIRM, self)) - { - bool isRenderStart = true; + imgui_close_current_popup(self); + }; - if (!std::filesystem::exists(ffmpegPath)) - { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_FFMPEG_PATH_ERROR); - isRenderStart = false; - } + _imgui_begin_child(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CHILD, self); + /* + _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_CROP.copy({.isDisabled = !isCrop}), self, crop, isCrop); + _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_SIZE.copy({.isDisabled = !isSize}), self, size, isSize); + _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_POSITION.copy({.isDisabled = !isPosition}), self, position, isPosition); + _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_PIVOT.copy({.isDisabled = !isPivot}), self, pivot, isPivot); + _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_SCALE.copy({.isDisabled = !isScale}), self, scale, isScale); + _imgui_checkbox_drag_float(IMGUI_FRAME_PROPERTIES_ROTATION.copy({.isDisabled = !isRotation}), self, rotation, isRotation); + _imgui_checkbox_input_int(IMGUI_FRAME_PROPERTIES_DELAY.copy({.isDisabled = !isDelay}), self, delay, isDelay); + _imgui_checkbox_color_edit4(IMGUI_FRAME_PROPERTIES_TINT.copy({.isDisabled = !isTint}), self, tint, isTint); + _imgui_checkbox_color_edit3(IMGUI_FRAME_PROPERTIES_COLOR_OFFSET.copy({.isDisabled = !isColorOffset}), self, colorOffset, isColorOffset); + _imgui_checkbox_checkbox(IMGUI_FRAME_PROPERTIES_VISIBLE.copy({.isDisabled = !isVisibleSet}), self, isVisible, isVisibleSet); + ImGui::NewLine(); + _imgui_checkbox_checkbox(IMGUI_FRAME_PROPERTIES_INTERPOLATED.copy({.isDisabled = !isInterpolatedSet}), self, isInterpolated, isInterpolatedSet); + */ + _imgui_end_child(IMGUI_FOOTER_CHILD, self); - if (isRenderStart) - { - switch (self->settings->renderType) - { - case RENDER_PNG: - if (!std::filesystem::is_directory(path)) - { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_DIRECTORY_ERROR); - isRenderStart = false; - } - break; - case RENDER_GIF: - case RENDER_WEBM: - case RENDER_MP4: - if (!path_is_valid(path)) - { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_PATH_ERROR); - isRenderStart = false; - } - default: - break; - } - } + _imgui_begin_child(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS_CHILD, self); + _imgui_text(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS, self); + _imgui_checkbox(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_FROM_SELECTED_FRAME, self, isFromSelectedFrame); + _imgui_input_int(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_NUMBER_FRAMES.copy({.max = max, .value = max}), self, numberFrames); + _imgui_end_child(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS_CHILD, self); - if (isRenderStart) - preview_render_start(self->preview); - else - self->preview->isRenderCancelled = true; - - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) - imgui_close_current_popup(self); + _imgui_begin_child(IMGUI_FOOTER_CHILD, self); + if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_ADD, self)) + change_frames(ANM2_CHANGE_ADD); + if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SUBTRACT, self)) + change_frames(ANM2_CHANGE_SUBTRACT); + if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SET, self)) + change_frames(ANM2_CHANGE_SET); + if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CANCEL, self)) + imgui_close_current_popup(self); + _imgui_end_child(IMGUI_FOOTER_CHILD, self); - _imgui_end_child(); // IMGUI_RENDER_ANIMATION_FOOTER_CHILD - - imgui_end_popup(self); - } + imgui_end_popup(self); + } - if (imgui_begin_popup_modal(IMGUI_RENDER_ANIMATION_CONFIRM.popup, self, IMGUI_RENDER_ANIMATION_CONFIRM.popupSize)) - { - static s32& type = self->settings->renderType; - static std::string& format = self->settings->renderFormat; + if (imgui_begin_popup_modal(IMGUI_SCALE_ANM2.popup, self, IMGUI_SCALE_ANM2.popupSize)) { + _imgui_begin_child(IMGUI_SCALE_ANM2_OPTIONS_CHILD, self); + _imgui_input_float(IMGUI_SCALE_ANM2_VALUE, self, self->settings->scaleValue); + _imgui_end_child(IMGUI_SCALE_ANM2_OPTIONS_CHILD, self); - auto rendering_end = [&]() - { - preview_render_end(self->preview); - imgui_close_current_popup(self); - }; - - std::vector& frames = self->preview->renderFrames; - std::string path = std::string(self->settings->renderPath.c_str()); - - if (self->preview->isRenderCancelled) - { - rendering_end(); - self->preview->isRenderCancelled = false; - } + _imgui_begin_child(IMGUI_FOOTER_CHILD, self); + if (_imgui_button(IMGUI_SCALE_ANM2_SCALE, self)) { + anm2_scale(self->anm2, self->settings->scaleValue); + imgui_close_current_popup(self); + } + if (_imgui_button(IMGUI_POPUP_CANCEL, self)) + imgui_close_current_popup(self); + _imgui_end_child(IMGUI_FOOTER_CHILD, self); - if (!animation) - { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_NO_ANIMATION_ERROR); - rendering_end(); - } + imgui_end_popup(self); + } - _imgui_begin_child(IMGUI_RENDERING_ANIMATION_CHILD, self); + if (imgui_begin_popup_modal(IMGUI_RENDER_ANIMATION.popup, self, IMGUI_RENDER_ANIMATION.popupSize)) { + static DialogType& dialogType = self->dialog->type; + static bool& dialogIsSelected = self->dialog->isSelected; + static int& type = self->settings->renderType; + static float& scale = self->settings->renderScale; + static bool& isUseAnimationBounds = self->settings->renderIsUseAnimationBounds; + static std::string& dialogPath = self->dialog->path; + static std::string& ffmpegPath = self->settings->renderFFmpegPath; + static std::string& format = self->settings->renderFormat; + static std::string& path = self->settings->renderPath; - f32 progress = self->preview->time / (animation->frameNum - 1); - ImGui::ProgressBar(progress); + _imgui_begin_child(IMGUI_RENDER_ANIMATION_CHILD, self); - _imgui_text(IMGUI_RENDERING_ANIMATION_INFO, self); + /* + if (_imgui_atlas_button(IMGUI_RENDER_ANIMATION_LOCATION_BROWSE, self)) + dialog_render_path_set(self->dialog, (RenderType)type); + */ - _imgui_end_child(); //IMGUI_RENDERING_ANIMATION_CHILD + if (dialogIsSelected && (dialogType == DIALOG_RENDER_PATH_SET)) { + path = path_extension_change(dialogPath, RENDER_EXTENSIONS[type]); + dialog_reset(self->dialog); + } - if (_imgui_button(IMGUI_RENDERING_ANIMATION_CANCEL, self)) - self->preview->isRenderCancelled = true; + _imgui_input_text(IMGUI_RENDER_ANIMATION_LOCATION, self, path); - if (self->preview->isRenderFinished && frames.empty()) - { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_NO_FRAMES_ERROR); - rendering_end(); - } - - if (self->preview->isRenderFinished) - { - switch (type) - { - case RENDER_PNG: - { - std::filesystem::path workingPath = std::filesystem::current_path(); - std::filesystem::current_path(path); + /* + if (_imgui_atlas_button(IMGUI_RENDER_ANIMATION_FFMPEG_BROWSE, self)) + dialog_ffmpeg_path_set(self->dialog); + */ - for (auto [i, frame] : std::views::enumerate(frames)) - { - std::string framePath = std::vformat(format, std::make_format_args(i)); - framePath = path_extension_change(framePath, RENDER_EXTENSIONS[type]); - if (!frame.isInvalid) texture_from_gl_write(&frame, framePath); - } + if (dialogIsSelected && dialogType == DIALOG_FFMPEG_PATH_SET) { + ffmpegPath = self->dialog->path; + dialog_reset(self->dialog); + } - std::filesystem::current_path(workingPath); - imgui_log_push(self, std::format(IMGUI_LOG_RENDER_ANIMATION_FRAMES_SAVE_FORMAT, path)); - break; - } - case RENDER_GIF: - case RENDER_WEBM: - case RENDER_MP4: - { - std::string ffmpegPath = std::string(self->settings->renderFFmpegPath.c_str()); - path = path_extension_change(path, RENDER_EXTENSIONS[self->settings->renderType]); - - if (ffmpeg_render(ffmpegPath, path, frames, self->preview->canvas.size, self->anm2->fps, (RenderType)type)) - imgui_log_push(self, std::format(IMGUI_LOG_RENDER_ANIMATION_SAVE_FORMAT, path)); - else - imgui_log_push(self, std::format(IMGUI_LOG_RENDER_ANIMATION_FFMPEG_ERROR, path)); - break; - } - default: - break; - } - - rendering_end(); - } + _imgui_input_text(IMGUI_RENDER_ANIMATION_FFMPEG_PATH, self, ffmpegPath); + _imgui_combo(IMGUI_RENDER_ANIMATION_OUTPUT, self, &type); + _imgui_input_text(IMGUI_RENDER_ANIMATION_FORMAT.copy({.isDisabled = type != RENDER_PNG}), self, format); + _imgui_checkbox(IMGUI_RENDER_ANIMATION_IS_USE_ANIMATION_BOUNDS, self, isUseAnimationBounds); + _imgui_input_float(IMGUI_RENDER_ANIMATION_SCALE.copy({.isDisabled = !isUseAnimationBounds}), self, scale); - imgui_end_popup(self); - } + _imgui_end_child(IMGUI_RENDER_ANIMATION_CHILD, self); - _imgui_selectable(IMGUI_PLAYBACK.copy({}), self); + _imgui_begin_child(IMGUI_RENDER_ANIMATION_FOOTER_CHILD, self); - if (imgui_begin_popup(IMGUI_PLAYBACK.popup, self, IMGUI_PLAYBACK.popupSize)) - { - _imgui_checkbox_selectable(IMGUI_ALWAYS_LOOP, self, self->settings->playbackIsLoop); - _imgui_checkbox_selectable(IMGUI_CLAMP_PLAYHEAD, self, self->settings->playbackIsClampPlayhead); - imgui_end_popup(self); - } + if (_imgui_button(IMGUI_RENDER_ANIMATION_CONFIRM, self)) { + bool isRenderStart = true; - _imgui_selectable(IMGUI_SETTINGS.copy({}), self); + if (!std::filesystem::exists(ffmpegPath)) { + imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_FFMPEG_PATH_ERROR); + isRenderStart = false; + } - if (imgui_begin_popup(IMGUI_SETTINGS.popup, self, IMGUI_SETTINGS.popupSize)) - { - if (_imgui_checkbox_selectable(IMGUI_VSYNC, self, self->settings->isVsync)) window_vsync_set(self->settings->isVsync); - _imgui_selectable(IMGUI_HOTKEYS, self); - if (_imgui_selectable(IMGUI_DEFAULT_SETTINGS, self)) *self->settings = Settings(); - imgui_end_popup(self); - } + if (isRenderStart) { + switch (self->settings->renderType) { + case RENDER_PNG: + if (!std::filesystem::is_directory(path)) { + imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_DIRECTORY_ERROR); + isRenderStart = false; + } + break; + case RENDER_GIF: + case RENDER_WEBM: + case RENDER_MP4: + if (!path_is_valid(path)) { + imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_PATH_ERROR); + isRenderStart = false; + } + default: + break; + } + } - if (imgui_begin_popup_modal(IMGUI_HOTKEYS.popup, self, IMGUI_HOTKEYS.popupSize)) - { - _imgui_begin_child(IMGUI_HOTKEYS_CHILD, self); + if (isRenderStart) + preview_render_start(self->preview); + else + self->preview->isRenderCancelled = true; - if (_imgui_begin_table(IMGUI_HOTKEYS_TABLE, self)) - { - static s32 selectedIndex = INDEX_NONE; + imgui_close_current_popup(self); + } - _imgui_table_setup_column(IMGUI_HOTKEYS_FUNCTION); - _imgui_table_setup_column(IMGUI_HOTKEYS_HOTKEY); - _imgui_table_headers_row(); + if (_imgui_button(IMGUI_POPUP_CANCEL, self)) + imgui_close_current_popup(self); - for (s32 i = 0; i < HOTKEY_COUNT; i++) - { - if (!SETTINGS_HOTKEY_MEMBERS[i]) continue; + _imgui_end_child(IMGUI_RENDER_ANIMATION_FOOTER_CHILD, self); - bool isSelected = selectedIndex == i; - const char* string = HOTKEY_STRINGS[i]; - std::string* settingString = &(self->settings->*SETTINGS_HOTKEY_MEMBERS[i]); - std::string chordString = isSelected ? IMGUI_HOTKEY_CHANGE : *settingString; - - ImGui::PushID(i); - _imgui_table_next_row(); - _imgui_table_set_column_index(0); - ImGui::TextUnformatted(string); - _imgui_table_set_column_index(1); + imgui_end_popup(self); + } - if (ImGui::Selectable(chordString.c_str(), isSelected)) selectedIndex = i; - ImGui::PopID(); + if (imgui_begin_popup_modal(IMGUI_RENDER_ANIMATION_CONFIRM.popup, self, IMGUI_RENDER_ANIMATION_CONFIRM.popupSize)) { + static int& type = self->settings->renderType; + static std::string& format = self->settings->renderFormat; - if (isSelected) - { - ImGuiKeyChord chord = IMGUI_CHORD_NONE; + auto rendering_end = [&]() { + preview_render_end(self->preview); + imgui_close_current_popup(self); + }; - if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) chord |= ImGuiMod_Ctrl; - if (ImGui::IsKeyDown(ImGuiMod_Shift)) chord |= ImGuiMod_Shift; - if (ImGui::IsKeyDown(ImGuiMod_Alt)) chord |= ImGuiMod_Alt; - if (ImGui::IsKeyDown(ImGuiMod_Super)) chord |= ImGuiMod_Super; + std::vector& frames = self->preview->renderFrames; + std::string path = std::string(self->settings->renderPath.c_str()); - for (auto& [_, key] : IMGUI_KEY_MAP) - { - if (ImGui::IsKeyPressed(key)) - { - chord |= key; - imgui_hotkey_chord_registry()[i] = chord; - *settingString = imgui_string_from_chord_get(chord); - selectedIndex = INDEX_NONE; - break; - } - } - } - } + if (self->preview->isRenderCancelled) { + rendering_end(); + self->preview->isRenderCancelled = false; + } - _imgui_end_table(); - } + if (!animation) { + imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_NO_ANIMATION_ERROR); + rendering_end(); + } - _imgui_end_child(); // IMGUI_HOTKEYS_CHILD; + _imgui_begin_child(IMGUI_RENDERING_ANIMATION_CHILD, self); - _imgui_begin_child(IMGUI_HOTKEYS_OPTIONS_CHILD, self); - if (_imgui_button(IMGUI_HOTKEYS_CONFIRM, self)) imgui_close_current_popup(self); - _imgui_end_child(); // IMGUI_HOTKEYS_OPTIONS_CHILD - - imgui_end_popup(self); - } - - _imgui_end(); + float progress = self->preview->time / (animation->frameNum - 1); + ImGui::ProgressBar(progress); + + _imgui_text(IMGUI_RENDERING_ANIMATION_INFO, self); + + _imgui_end_child(IMGUI_RENDERING_ANIMATION_CHILD, self); + + if (_imgui_button(IMGUI_RENDERING_ANIMATION_CANCEL, self)) + self->preview->isRenderCancelled = true; + + if (self->preview->isRenderFinished && frames.empty()) { + imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_NO_FRAMES_ERROR); + rendering_end(); + } + + if (self->preview->isRenderFinished) { + switch (type) { + case RENDER_PNG: { + std::filesystem::path workingPath = std::filesystem::current_path(); + std::filesystem::current_path(path); + + for (auto [i, frame] : std::views::enumerate(frames)) { + std::string framePath = std::vformat(format, std::make_format_args(i)); + framePath = path_extension_change(framePath, RENDER_EXTENSIONS[type]); + if (!frame.isInvalid) + texture_from_gl_write(&frame, framePath); + } + + std::filesystem::current_path(workingPath); + imgui_log_push(self, std::format(IMGUI_LOG_RENDER_ANIMATION_FRAMES_SAVE_FORMAT, path)); + break; + } + case RENDER_GIF: + case RENDER_WEBM: + case RENDER_MP4: { + std::string ffmpegPath = std::string(self->settings->renderFFmpegPath.c_str()); + path = path_extension_change(path, RENDER_EXTENSIONS[self->settings->renderType]); + + if (ffmpeg_render(ffmpegPath, path, frames, self->preview->canvas.size, self->anm2->fps, (RenderType)type)) + imgui_log_push(self, std::format(IMGUI_LOG_RENDER_ANIMATION_SAVE_FORMAT, path)); + else + imgui_log_push(self, std::format(IMGUI_LOG_RENDER_ANIMATION_FFMPEG_ERROR, path)); + break; + } + default: + break; + } + + rendering_end(); + } + + imgui_end_popup(self); + } + + _imgui_selectable(IMGUI_PLAYBACK.copy({}), self); + + if (imgui_begin_popup(IMGUI_PLAYBACK.popup, self, IMGUI_PLAYBACK.popupSize)) { + /* + _imgui_checkbox_selectable(IMGUI_ALWAYS_LOOP, self, self->settings->playbackIsLoop); + _imgui_checkbox_selectable(IMGUI_CLAMP_PLAYHEAD, self, self->settings->playbackIsClampPlayhead); + */ + imgui_end_popup(self); + } + + _imgui_selectable(IMGUI_SETTINGS.copy({}), self); + + /* + if (imgui_begin_popup(IMGUI_SETTINGS.popup, self, IMGUI_SETTINGS.popupSize)) { + if (_imgui_checkbox_selectable(IMGUI_VSYNC, self, self->settings->isVsync)) + window_vsync_set(self->settings->isVsync); + _imgui_selectable(IMGUI_HOTKEYS, self); + if (_imgui_selectable(IMGUI_DEFAULT_SETTINGS, self)) + *self->settings = Settings(); + imgui_end_popup(self); + } + */ + + if (imgui_begin_popup_modal(IMGUI_HOTKEYS.popup, self, IMGUI_HOTKEYS.popupSize)) { + _imgui_begin_child(IMGUI_HOTKEYS_CHILD, self); + + if (_imgui_begin_table(IMGUI_HOTKEYS_TABLE, self)) { + static int selectedIndex = INDEX_NONE; + + ImGui::TableSetupScrollFreeze(0, 1); + _imgui_table_setup_column(IMGUI_HOTKEYS_FUNCTION); + _imgui_table_setup_column(IMGUI_HOTKEYS_HOTKEY); + _imgui_table_headers_row(); + + for (int i = 0; i < HOTKEY_COUNT; i++) { + if (!SETTINGS_HOTKEY_MEMBERS[i]) + continue; + + bool isSelected = selectedIndex == i; + const char* string = HOTKEY_STRINGS[i]; + std::string* settingString = &(self->settings->*SETTINGS_HOTKEY_MEMBERS[i]); + std::string chordString = isSelected ? IMGUI_HOTKEY_CHANGE : *settingString; + + ImGui::PushID(i); + _imgui_table_next_row(); + _imgui_table_set_column_index(0); + ImGui::TextUnformatted(string); + _imgui_table_set_column_index(1); + + if (ImGui::Selectable(chordString.c_str(), isSelected)) + selectedIndex = i; + ImGui::PopID(); + + if (isSelected) { + ImGuiKeyChord chord = IMGUI_CHORD_NONE; + + if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) + chord |= ImGuiMod_Ctrl; + if (ImGui::IsKeyDown(ImGuiMod_Shift)) + chord |= ImGuiMod_Shift; + if (ImGui::IsKeyDown(ImGuiMod_Alt)) + chord |= ImGuiMod_Alt; + if (ImGui::IsKeyDown(ImGuiMod_Super)) + chord |= ImGuiMod_Super; + + for (auto& [_, key] : IMGUI_KEY_MAP) { + if (ImGui::IsKeyPressed(key)) { + chord |= key; + imgui_hotkey_chord_registry()[i] = chord; + *settingString = imgui_string_from_chord_get(chord); + selectedIndex = INDEX_NONE; + break; + } + } + } + } + + _imgui_end_table(); + } + + _imgui_end_child(IMGUI_HOTKEYS_CHILD, self); + + _imgui_begin_child(IMGUI_HOTKEYS_OPTIONS_CHILD, self); + if (_imgui_button(IMGUI_HOTKEYS_CONFIRM, self)) + imgui_close_current_popup(self); + _imgui_end_child(IMGUI_HOTKEYS_OPTIONS_CHILD, self); + + imgui_end_popup(self); + } + + _imgui_end(); } -static void _imgui_tools(Imgui* self) -{ - ImGuiStyle style = ImGui::GetStyle(); +/* +static void _imgui_tools(Imgui* self) { + ImGuiStyle style = ImGui::GetStyle(); - IMGUI_BEGIN_OR_RETURN(IMGUI_TOOLS, self); + IMGUI_BEGIN_OR_RETURN(IMGUI_TOOLS, self); - f32 availableWidth = ImGui::GetContentRegionAvail().x; - f32 usedWidth = style.FramePadding.x; + float availableWidth = ImGui::GetContentRegionAvail().x; + float usedWidth = style.FramePadding.x; - for (s32 i = 0; i < TOOL_COUNT; i++) - { - ImguiItem item = *IMGUI_TOOL_ITEMS[i]; + for (int i = 0; i < TOOL_COUNT; i++) { + ImguiItem item = *IMGUI_TOOL_ITEMS[i]; - if (i > 0 && usedWidth + ImGui::GetItemRectSize().x < availableWidth) - ImGui::SameLine(); - else - usedWidth = 0; + if (i > 0 && usedWidth + ImGui::GetItemRectSize().x < availableWidth) + ImGui::SameLine(); + else + usedWidth = 0; - item.isSelected = self->settings->tool == (ToolType)i; - - switch ((ToolType)i) - { - case TOOL_UNDO: item.isDisabled = self->snapshots->undoStack.is_empty(); break; - case TOOL_REDO: item.isDisabled = self->snapshots->redoStack.is_empty(); break; - default: break; - } + item.isSelected = self->settings->tool == (ToolType)i; - if (i != TOOL_COLOR) - _imgui_atlas_button(item, self); - else - _imgui_color_edit4(item, self, self->settings->toolColor); - - usedWidth += ImGui::GetItemRectSize().x + style.ItemSpacing.x; - } + switch ((ToolType)i) { + case TOOL_UNDO: + item.isDisabled = self->snapshots->undoStack.is_empty(); + break; + case TOOL_REDO: + item.isDisabled = self->snapshots->redoStack.is_empty(); + break; + default: + break; + } - _imgui_end(); // IMGUI_TOOLS + if (i != TOOL_COLOR) + _imgui_atlas_button(item, self); + else + _imgui_color_edit4(item, self, self->settings->toolColor); + + usedWidth += ImGui::GetItemRectSize().x + style.ItemSpacing.x; + } + + _imgui_end(); // IMGUI_TOOLS } -static void _imgui_layers(Imgui* self) -{ - static s32 selectedLayerID = ID_NONE; +static void _imgui_layers(Imgui* self) { + static int selectedLayerID = ID_NONE; - IMGUI_BEGIN_OR_RETURN(IMGUI_LAYERS, self); - _imgui_no_anm2_path_check(self); - - ImVec2 size = ImGui::GetContentRegionAvail(); + IMGUI_BEGIN_OR_RETURN(IMGUI_LAYERS, self); + _imgui_no_anm2_path_click_check(self); - _imgui_begin_child(IMGUI_LAYERS_CHILD.copy({.size = {size.x, size.y - IMGUI_FOOTER_CHILD.size.y}}), self); - ImGui::SetScrollX(0.0f); + ImVec2 size = ImGui::GetContentRegionAvail(); - for (auto & [id, layer] : self->anm2->layers) - { - ImGui::PushID(id); + _imgui_begin_child(IMGUI_LAYERS_CHILD.copy({.size = vec2(size.x, size.y - IMGUI_FOOTER_CHILD.size->y)}), self); - ImguiItem layerItem = IMGUI_LAYER.copy - ({ - .isSelected = selectedLayerID == id, - .label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), - .size = {ImGui::GetContentRegionAvail().x - (IMGUI_LAYER_SPRITESHEET_ID.size.x * 2.0f), 0}, - .id = id - }); - if (_imgui_atlas_selectable_input_text(layerItem, self, layer.name)) selectedLayerID = id; + for (auto& [id, layer] : self->anm2->layers) { + ImGui::PushID(id); - ImGui::SameLine(); + ImguiItem layerItem = IMGUI_LAYER.copy({.label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), + .size = vec2(ImGui::GetContentRegionAvail().x - (IMGUI_LAYER_SPRITESHEET_ID.size->x * 2.0f), 0), + .isSelected = selectedLayerID == id, + .id = id}); + if (_imgui_atlas_selectable_input_text(layerItem, self, layer.name)) + selectedLayerID = id; - ImguiItem spritesheetItem = IMGUI_LAYER_SPRITESHEET_ID.copy - ({ - .isSelected = selectedLayerID == id, - .label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), - .id = id - }); - _imgui_atlas_selectable_input_int(spritesheetItem, self, layer.spritesheetID); - - ImGui::PopID(); - }; + ImGui::SameLine(); - _imgui_end_child(); // layersChild - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - - if (_imgui_button(IMGUI_LAYER_ADD.copy({self->anm2->path.empty()}), self)) - selectedLayerID = anm2_layer_add(self->anm2); + ImguiItem spritesheetItem = + IMGUI_LAYER_SPRITESHEET_ID.copy({.label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), .isSelected = selectedLayerID == id, .id = id}); + _imgui_atlas_selectable_input_int(spritesheetItem, self, layer.spritesheetID); - if (_imgui_button(IMGUI_LAYER_REMOVE.copy({selectedLayerID == ID_NONE}), self)) - { - anm2_layer_remove(self->anm2, selectedLayerID); - selectedLayerID = ID_NONE; - } - - _imgui_end_child(); // IMGUI_FOOTER_CHILD - _imgui_end(); // IMGUI_LAYERS + ImGui::PopID(); + }; + + _imgui_end_child(); // layersChild + + _imgui_begin_child(IMGUI_FOOTER_CHILD, self); + + if (_imgui_button(IMGUI_LAYER_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) + selectedLayerID = anm2_layer_add(self->anm2); + + if (_imgui_button(IMGUI_LAYER_REMOVE.copy({.isDisabled = selectedLayerID == ID_NONE}), self)) { + anm2_layer_remove(self->anm2, selectedLayerID); + selectedLayerID = ID_NONE; + } + + _imgui_end_child(); // IMGUI_FOOTER_CHILD + _imgui_end(); // IMGUI_LAYERS } -static void _imgui_nulls(Imgui* self) -{ - static s32 selectedNullID = ID_NONE; +static void _imgui_nulls(Imgui* self) { + static int selectedNullID = ID_NONE; - IMGUI_BEGIN_OR_RETURN(IMGUI_NULLS, self); - _imgui_no_anm2_path_check(self); - - ImVec2 size = ImGui::GetContentRegionAvail(); + IMGUI_BEGIN_OR_RETURN(IMGUI_NULLS, self); + _imgui_no_anm2_path_click_check(self); - _imgui_begin_child(IMGUI_NULLS_CHILD.copy({.size = {size.x, size.y - IMGUI_FOOTER_CHILD.size.y}}), self); + ImVec2 size = ImGui::GetContentRegionAvail(); - for (auto & [id, null] : self->anm2->nulls) - { - ImGui::PushID(id); + _imgui_begin_child(IMGUI_NULLS_CHILD.copy({.size = vec2(size.x, size.y - IMGUI_FOOTER_CHILD.size->y)}), self); - ImguiItem nullItem = IMGUI_NULL.copy - ({ - .isSelected = selectedNullID == id, - .label = std::format(IMGUI_NULL_FORMAT, id, null.name), - .id = id - }); + for (auto& [id, null] : self->anm2->nulls) { + ImGui::PushID(id); - if (_imgui_atlas_selectable_input_text(nullItem, self, null.name)) selectedNullID = id; - - ImGui::PopID(); - }; + ImguiItem nullItem = IMGUI_NULL.copy({.label = std::format(IMGUI_NULL_FORMAT, id, null.name), .isSelected = selectedNullID == id, .id = id}); - _imgui_end_child(); // nullsChild - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - - if (_imgui_button(IMGUI_NULL_ADD.copy({self->anm2->path.empty()}), self)) - selectedNullID = anm2_null_add(self->anm2); + if (_imgui_atlas_selectable_input_text(nullItem, self, null.name)) + selectedNullID = id; - if (_imgui_button(IMGUI_NULL_REMOVE.copy({selectedNullID == ID_NONE}), self)) - { - anm2_null_remove(self->anm2, selectedNullID); - selectedNullID = ID_NONE; - } - - _imgui_end_child(); // IMGUI_FOOTER_CHILD - _imgui_end(); // IMGUI_NULLS + ImGui::PopID(); + }; + + _imgui_end_child(); // nullsChild + + _imgui_begin_child(IMGUI_FOOTER_CHILD, self); + + if (_imgui_button(IMGUI_NULL_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) + selectedNullID = anm2_null_add(self->anm2); + + if (_imgui_button(IMGUI_NULL_REMOVE.copy({.isDisabled = selectedNullID == ID_NONE}), self)) { + anm2_null_remove(self->anm2, selectedNullID); + selectedNullID = ID_NONE; + } + + _imgui_end_child(); // IMGUI_FOOTER_CHILD + _imgui_end(); // IMGUI_NULLS } -static void _imgui_animations(Imgui* self) -{ - IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATIONS, self); - _imgui_no_anm2_path_check(self); - - ImVec2 size = ImGui::GetContentRegionAvail(); +static void _imgui_animations(Imgui* self) { + IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATIONS, self); + _imgui_no_anm2_path_click_check(self); - _imgui_begin_child(IMGUI_ANIMATIONS_CHILD.copy({.size = {size.x, size.y - IMGUI_FOOTER_CHILD.size.y}}), self); + ImVec2 size = ImGui::GetContentRegionAvail(); - for (auto & [id, animation] : self->anm2->animations) - { - ImGui::PushID(id); + _imgui_begin_child(IMGUI_ANIMATIONS_CHILD.copy({.size = vec2(size.x, size.y - IMGUI_FOOTER_CHILD.size->y)}), self); - ImguiItem animationItem = IMGUI_ANIMATION.copy - ({ - .isSelected = self->reference->animationID == id, - .label = self->anm2->defaultAnimationID == id ? std::format(IMGUI_ANIMATION_DEFAULT_FORMAT, animation.name) : animation.name, - .id = id - }); - - if (_imgui_atlas_selectable_input_text(animationItem, self, animation.name)) - { - self->reference->animationID = id; - anm2_reference_item_clear(self->reference); - } + for (auto& [id, animation] : self->anm2->animations) { + ImGui::PushID(id); - if (ImGui::IsItemHovered()) - { - self->clipboard->type = CLIPBOARD_ANIMATION; - self->clipboard->location = (s32)id; - } - - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) - { - if (ImGui::IsDragDropActive()) ImGui::SetNextItemWidth(_imgui_item_size_get(animationItem, IMGUI_SELECTABLE).x); - ImGui::SetDragDropPayload(animationItem.drag_drop_get(), &id, sizeof(s32)); - _imgui_atlas_selectable(animationItem, self); - ImGui::EndDragDropSource(); - } + ImguiItem animationItem = + IMGUI_ANIMATION.copy({.label = self->anm2->defaultAnimationID == id ? std::format(IMGUI_ANIMATION_DEFAULT_FORMAT, animation.name) : animation.name, + .isSelected = self->reference->animationID == id, + .id = id}); - if (ImGui::BeginDragDropTarget()) - { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(animationItem.drag_drop_get())) - { - s32 sourceID = *(s32*)payload->Data; - if (sourceID != id) - { - imgui_snapshot(self, IMGUI_ACTION_ANIMATION_SWAP); - map_swap(self->anm2->animations, sourceID, id); - } - } + if (_imgui_atlas_selectable_input_text(animationItem, self, animation.name)) + *self->reference = {id}; - ImGui::EndDragDropTarget(); - } - - ImGui::PopID(); - }; + if (ImGui::IsItemHovered()) { + self->clipboard->type = CLIPBOARD_ANIMATION; + self->clipboard->location = (int)id; + } - _imgui_context_menu(self); + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { + if (ImGui::IsDragDropActive()) + ImGui::SetNextItemWidth(_imgui_item_size_get(animationItem, IMGUI_SELECTABLE).x); + ImGui::SetDragDropPayload(animationItem.drag_drop_get(), &id, sizeof(int)); + _imgui_atlas_selectable(animationItem, self); + ImGui::EndDragDropSource(); + } - _imgui_end_child(); // animationsChild - - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference); - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - - if (_imgui_button(IMGUI_ANIMATION_ADD.copy({self->anm2->path.empty()}), self)) - { - s32 id = anm2_animation_add(self->anm2); - self->reference->animationID = id; + if (ImGui::BeginDragDropTarget()) { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(animationItem.drag_drop_get())) { + int sourceID = *(int*)payload->Data; + if (sourceID != id) { + imgui_snapshot(self, IMGUI_ACTION_ANIMATION_SWAP); + map_swap(self->anm2->animations, sourceID, id); + } + } - if (self->anm2->animations.size() == 1) - self->anm2->defaultAnimationID = id; - } + ImGui::EndDragDropTarget(); + } - if (_imgui_button(IMGUI_ANIMATION_DUPLICATE.copy({!animation}), self)) - self->reference->animationID = anm2_animation_add(self->anm2, animation, self->reference->animationID); + ImGui::PopID(); + }; - _imgui_button(IMGUI_ANIMATION_MERGE.copy({!animation}), self); - - if (imgui_begin_popup_modal(IMGUI_ANIMATION_MERGE.popup, self, IMGUI_ANIMATION_MERGE.popupSize)) - { - const bool isModCtrl = ImGui::IsKeyDown(IMGUI_INPUT_CTRL); - const bool isModShift = ImGui::IsKeyDown(IMGUI_INPUT_SHIFT); - static bool& isDeleteAnimationsAfter = self->settings->mergeIsDeleteAnimationsAfter; - static s32 lastClickedID = ID_NONE; - static s32& mergeType = self->settings->mergeType; - static size_t lastAnimationCount = 0; - static std::vector animationIDs; - static std::vector sortedIDs; - - if (self->anm2->animations.size() != lastAnimationCount) - { - sortedIDs.clear(); - for (const auto& [id, _] : self->anm2->animations) - sortedIDs.push_back(id); - std::sort(sortedIDs.begin(), sortedIDs.end()); - lastAnimationCount = self->anm2->animations.size(); - } + _imgui_context_menu(self); - _imgui_begin_child(IMGUI_MERGE_ANIMATIONS_CHILD, self); + _imgui_end_child(); // animationsChild - for (const auto& [id, animation] : self->anm2->animations) - { - ImGui::PushID(id); + Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); - if - ( - _imgui_atlas_selectable - ( - IMGUI_ANIMATION.copy - ({ - .isSelected = std::find(animationIDs.begin(), animationIDs.end(), id) != animationIDs.end(), - .label = animation.name - }), - self - ) - ) - { - if (isModCtrl) - { - auto it = std::find(animationIDs.begin(), animationIDs.end(), id); - if (it != animationIDs.end()) - animationIDs.erase(it); - else - animationIDs.push_back(id); + _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - lastClickedID = id; - } - else if (isModShift) - { - auto it1 = std::find(sortedIDs.begin(), sortedIDs.end(), lastClickedID); - auto it2 = std::find(sortedIDs.begin(), sortedIDs.end(), id); - if (it1 != sortedIDs.end() && it2 != sortedIDs.end()) - { - auto begin = std::min(it1, it2); - auto end = std::max(it1, it2); - for (auto it = begin; it <= end; ++it) - { - if (std::find(animationIDs.begin(), animationIDs.end(), *it) == animationIDs.end()) - animationIDs.push_back(*it); - } - } - } - else - { - animationIDs.clear(); - animationIDs.push_back(id); - lastClickedID = id; - } - } + if (_imgui_button(IMGUI_ANIMATION_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) { + int id = anm2_animation_add(self->anm2); + self->reference->animationID = id; - ImGui::PopID(); - } + if (self->anm2->animations.size() == 1) + self->anm2->defaultAnimationID = id; + } - _imgui_end_child(); //IMGUI_MERGE_ANIMATIONS_CHILD - - _imgui_begin_child(IMGUI_MERGE_ON_CONFLICT_CHILD, self); - _imgui_text(IMGUI_MERGE_ON_CONFLICT, self); - _imgui_radio_button(IMGUI_MERGE_APPEND_FRAMES, self, mergeType); - _imgui_radio_button(IMGUI_MERGE_REPLACE_FRAMES, self, mergeType); - _imgui_radio_button(IMGUI_MERGE_PREPEND_FRAMES, self, mergeType); - _imgui_radio_button(IMGUI_MERGE_IGNORE, self, mergeType); - _imgui_end_child(); //IMGUI_MERGE_ON_CONFLICT_CHILD - - _imgui_begin_child(IMGUI_MERGE_OPTIONS_CHILD, self); + if (_imgui_button(IMGUI_ANIMATION_DUPLICATE.copy({.isDisabled = !animation}), self)) + self->reference->animationID = anm2_animation_add(self->anm2, animation, self->reference->animationID); - _imgui_checkbox(IMGUI_MERGE_DELETE_ANIMATIONS_AFTER, self, isDeleteAnimationsAfter); + _imgui_button(IMGUI_ANIMATION_MERGE.copy({.isDisabled = !animation}), self); - _imgui_end_child(); //IMGUI_MERGE_OPTIONS_CHILD - - if (_imgui_button(IMGUI_MERGE_CONFIRM.copy({animationIDs.empty()}), self)) - { - anm2_animation_merge(self->anm2, self->reference->animationID, animationIDs, (Anm2MergeType)mergeType); + if (imgui_begin_popup_modal(IMGUI_ANIMATION_MERGE.popup, self, IMGUI_ANIMATION_MERGE.popupSize)) { + const bool isModCtrl = ImGui::IsKeyDown(IMGUI_INPUT_CTRL); + const bool isModShift = ImGui::IsKeyDown(IMGUI_INPUT_SHIFT); + static bool& isDeleteAnimationsAfter = self->settings->mergeIsDeleteAnimationsAfter; + static int lastClickedID = ID_NONE; + static int& mergeType = self->settings->mergeType; + static size_t lastAnimationCount = 0; + static std::vector animationIDs; + static std::vector sortedIDs; - if (isDeleteAnimationsAfter) - for (s32 id : animationIDs) - if (id != self->reference->animationID) - self->anm2->animations.erase(id); + if (self->anm2->animations.size() != lastAnimationCount) { + sortedIDs.clear(); + for (const auto& [id, _] : self->anm2->animations) + sortedIDs.push_back(id); + std::sort(sortedIDs.begin(), sortedIDs.end()); + lastAnimationCount = self->anm2->animations.size(); + } - animationIDs.clear(); - imgui_close_current_popup(self); - } + _imgui_begin_child(IMGUI_MERGE_ANIMATIONS_CHILD, self); - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) - { - animationIDs.clear(); - imgui_close_current_popup(self); - } - - imgui_end_popup(self); - } + for (const auto& [id, animation] : self->anm2->animations) { + ImGui::PushID(id); - if (_imgui_button(IMGUI_ANIMATION_REMOVE.copy({!animation}), self)) - { - anm2_animation_remove(self->anm2, self->reference->animationID); - anm2_reference_clear(self->reference); - } - - if (_imgui_button(IMGUI_ANIMATION_DEFAULT.copy({!animation}), self)) - self->anm2->defaultAnimationID = self->reference->animationID; + if (_imgui_atlas_selectable(IMGUI_ANIMATION.copy({.label = animation.name, .isSelected = vector_find(animationIDs, id)}), self)) { + if (isModCtrl) { + auto it = std::find(animationIDs.begin(), animationIDs.end(), id); + if (it != animationIDs.end()) + animationIDs.erase(it); + else + animationIDs.push_back(id); - _imgui_end_child(); // IMGUI_FOOTER_CHILD - _imgui_end(); // IMGUI_ANIMATIONS + lastClickedID = id; + } else if (isModShift) { + auto it1 = std::find(sortedIDs.begin(), sortedIDs.end(), lastClickedID); + auto it2 = std::find(sortedIDs.begin(), sortedIDs.end(), id); + if (it1 != sortedIDs.end() && it2 != sortedIDs.end()) { + auto begin = std::min(it1, it2); + auto end = std::max(it1, it2); + for (auto it = begin; it <= end; ++it) { + if (std::find(animationIDs.begin(), animationIDs.end(), *it) == animationIDs.end()) + animationIDs.push_back(*it); + } + } + } else { + animationIDs.clear(); + animationIDs.push_back(id); + lastClickedID = id; + } + } + + ImGui::PopID(); + } + + _imgui_end_child(); // IMGUI_MERGE_ANIMATIONS_CHILD + + _imgui_begin_child(IMGUI_MERGE_ON_CONFLICT_CHILD, self); + _imgui_text(IMGUI_MERGE_ON_CONFLICT, self); + _imgui_radio_button(IMGUI_MERGE_APPEND_FRAMES, self, mergeType); + _imgui_radio_button(IMGUI_MERGE_REPLACE_FRAMES, self, mergeType); + _imgui_radio_button(IMGUI_MERGE_PREPEND_FRAMES, self, mergeType); + _imgui_radio_button(IMGUI_MERGE_IGNORE, self, mergeType); + _imgui_end_child(); // IMGUI_MERGE_ON_CONFLICT_CHILD + + _imgui_begin_child(IMGUI_MERGE_OPTIONS_CHILD, self); + + _imgui_checkbox(IMGUI_MERGE_DELETE_ANIMATIONS_AFTER, self, isDeleteAnimationsAfter); + + _imgui_end_child(); // IMGUI_MERGE_OPTIONS_CHILD + + if (_imgui_button(IMGUI_MERGE_CONFIRM.copy({.isDisabled = animationIDs.empty()}), self)) { + anm2_animation_merge(self->anm2, self->reference->animationID, animationIDs, (Anm2MergeType)mergeType); + + if (isDeleteAnimationsAfter) + for (int id : animationIDs) + if (id != self->reference->animationID) + self->anm2->animations.erase(id); + + animationIDs.clear(); + imgui_close_current_popup(self); + } + + if (_imgui_button(IMGUI_POPUP_CANCEL, self)) { + animationIDs.clear(); + imgui_close_current_popup(self); + } + + imgui_end_popup(self); + } + + if (_imgui_button(IMGUI_ANIMATION_REMOVE.copy({.isDisabled = !animation}), self)) { + anm2_animation_remove(self->anm2, self->reference->animationID); + *self->reference = Anm2Reference(); + } + + if (_imgui_button(IMGUI_ANIMATION_DEFAULT.copy({.isDisabled = !animation}), self)) + self->anm2->defaultAnimationID = self->reference->animationID; + + _imgui_end_child(); // IMGUI_FOOTER_CHILD + _imgui_end(); // IMGUI_ANIMATIONS } -static void _imgui_events(Imgui* self) -{ - static s32 selectedID = ID_NONE; - - IMGUI_BEGIN_OR_RETURN(IMGUI_EVENTS, self); - _imgui_no_anm2_path_check(self); - - ImVec2 windowSize = ImGui::GetContentRegionAvail(); +static void _imgui_events(Imgui* self) { + static int selectedID = ID_NONE; - _imgui_begin_child(IMGUI_EVENTS_CHILD.copy({.size = {windowSize.x, windowSize.y - IMGUI_FOOTER_CHILD.size.y}}), self); + IMGUI_BEGIN_OR_RETURN(IMGUI_EVENTS, self); + _imgui_no_anm2_path_click_check(self); - std::function event_item = [&](s32 id, Anm2Event& event) - { - ImGui::PushID(id); + ImVec2 windowSize = ImGui::GetContentRegionAvail(); - if (_imgui_atlas_selectable_input_text(IMGUI_EVENT.copy({.isSelected = id == selectedID, .label = event.name, .id = id}), self, event.name)) - selectedID = id; + _imgui_begin_child(IMGUI_EVENTS_CHILD.copy({.size = vec2(windowSize.x, windowSize.y - IMGUI_FOOTER_CHILD.size->y)}), self); - ImGui::PopID(); - }; + std::function event_item = [&](int id, Anm2Event& event) { + ImGui::PushID(id); - for (auto& [id, event] : self->anm2->events) - event_item(id, event); + if (_imgui_atlas_selectable_input_text(IMGUI_EVENT.copy({.label = event.name, .isSelected = id == selectedID, .id = id}), self, event.name)) + selectedID = id; - _imgui_end_child(); // eventsChild - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - - if (_imgui_button(IMGUI_EVENTS_ADD.copy({self->anm2->path.empty()}), self)) - { - s32 id = map_next_id_get(self->anm2->events); - self->anm2->events[id] = Anm2Event{}; - selectedID = id; - } + ImGui::PopID(); + }; - if (_imgui_button(IMGUI_EVENTS_REMOVE_UNUSED.copy({self->anm2->events.empty()}), self)) - { - std::unordered_set usedEventIDs; + for (auto& [id, event] : self->anm2->events) + event_item(id, event); - for (auto& [id, animation] : self->anm2->animations) - for (auto& trigger : animation.triggers.frames) - if (trigger.eventID != ID_NONE) - usedEventIDs.insert(trigger.eventID); + _imgui_end_child(); // eventsChild - for (auto it = self->anm2->events.begin(); it != self->anm2->events.end(); ) - { - if (!usedEventIDs.count(it->first)) - it = self->anm2->events.erase(it); - else - it++; - } - } - - _imgui_end_child(); // IMGUI_ANIMATIONS_OPTIONS_CHILD) - _imgui_end(); // IMGUI_EVENTS + _imgui_begin_child(IMGUI_FOOTER_CHILD, self); + + if (_imgui_button(IMGUI_EVENTS_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) { + int id = map_next_id_get(self->anm2->events); + self->anm2->events[id] = Anm2Event{}; + selectedID = id; + } + + if (_imgui_button(IMGUI_EVENTS_REMOVE_UNUSED.copy({.isDisabled = self->anm2->events.empty()}), self)) { + std::unordered_set usedEventIDs; + + for (auto& [id, animation] : self->anm2->animations) + for (auto& trigger : animation.triggers.frames) + if (trigger.eventID != ID_NONE) + usedEventIDs.insert(trigger.eventID); + + for (auto it = self->anm2->events.begin(); it != self->anm2->events.end();) { + if (!usedEventIDs.count(it->first)) + it = self->anm2->events.erase(it); + else + it++; + } + } + + _imgui_end_child(); // IMGUI_ANIMATIONS_OPTIONS_CHILD) + _imgui_end(); // IMGUI_EVENTS +} +*/ + +static void _imgui_spritesheets(Imgui* self) { + IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEETS, self); + _imgui_no_anm2_path_click_check(self); + + static std::unordered_set selectedIDs; + float displayScale = self->settings->displayScale; + vec2 childSize = ImGui::GetContentRegionAvail() - *IMGUI_SPRITESHEETS_FOOTER_CHILD.size * displayScale; + + _imgui_begin_child(IMGUI_SPRITESHEETS_CHILD.copy({.size = childSize}), self); + + std::function spritesheet_draw = [&](int id, Anm2Spritesheet& spritesheet) { + ImGui::PushID(id); + vec2 itemSize = {childSize.x, IMGUI_SPRITESHEET_PREVIEW.size->y}; + _imgui_begin_child(IMGUI_SPRITESHEET_CHILD.copy({.size = itemSize}), self); + + Texture& texture = spritesheet.texture; + bool& isInvalid = texture.isInvalid; + + ImVec2 cursorPos = ImGui::GetCursorPos(); + + if (_imgui_selectable(IMGUI_SPRITESHEET.copy({.tooltip = spritesheet.path, .size = itemSize, .isSelected = selectedIDs.contains(id)}), self)) { + if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) + unordered_set_id_toggle(selectedIDs, id); + else + selectedIDs = {id}; + } + + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { + ImGui::SetDragDropPayload(IMGUI_SPRITESHEET.drag_drop_get(), &id, sizeof(int)); + spritesheet_draw(id, spritesheet); + ImGui::EndDragDropSource(); + } + + if (ImGui::BeginDragDropTarget()) { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_SPRITESHEET.drag_drop_get())) { + int sourceID = *(int*)payload->Data; + if (sourceID != id) { + imgui_snapshot(self, IMGUI_ACTION_SPRITESHEET_SWAP); + map_swap(self->anm2->spritesheets, sourceID, id); + } + } + ImGui::EndDragDropTarget(); + } + + ImVec2 spritesheetPreviewSize = *IMGUI_SPRITESHEET_PREVIEW.size; + float spritesheetAspect = (float)texture.size.x / texture.size.y; + + if ((IMGUI_SPRITESHEET_PREVIEW.size->x / IMGUI_SPRITESHEET_PREVIEW.size->y) > spritesheetAspect) + spritesheetPreviewSize.x = IMGUI_SPRITESHEET_PREVIEW.size->y * spritesheetAspect; + else + spritesheetPreviewSize.y = IMGUI_SPRITESHEET_PREVIEW.size->x / spritesheetAspect; + + _imgui_image(IMGUI_SPRITESHEET_PREVIEW.copy({.textureID = isInvalid ? self->resources->atlas.id : spritesheet.texture.id, + .size = spritesheetPreviewSize, + .uvMin = isInvalid ? ATLAS_UV_MIN(ATLAS_NONE) : vec2(), + .uvMax = isInvalid ? ATLAS_UV_MAX(ATLAS_NONE) : vec2(1.0f), + .cursorPosition = cursorPos}), + self); + + _imgui_atlas_text(IMGUI_SPRITESHEET_TEXT.copy({.label = std::format(IMGUI_SPRITESHEET_FORMAT, id, spritesheet.path), + .cursorPosition = vec2(IMGUI_SPRITESHEET_PREVIEW.size->x, + (IMGUI_SPRITESHEET_PREVIEW.size->y * 0.5f) - (ImGui::GetTextLineHeight() * 0.5f))}), + self); + + _imgui_end_child(IMGUI_SPRITESHEET_CHILD, self); + ImGui::PopID(); + }; + + for (auto& [id, spritesheet] : self->anm2->spritesheets) + spritesheet_draw(id, spritesheet); + + _imgui_end_child(IMGUI_SPRITESHEETS_CHILD, self); + + _imgui_begin_child(IMGUI_SPRITESHEETS_FOOTER_CHILD.copy({.size = *IMGUI_SPRITESHEETS_FOOTER_CHILD.size * displayScale}), self); + + if (_imgui_button(IMGUI_SPRITESHEET_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) + dialog_spritesheet_add(self->dialog); + + if (self->dialog->isSelected && self->dialog->type == DIALOG_SPRITESHEET_ADD) { + _imgui_spritesheet_add(self, self->dialog->path); + dialog_reset(self->dialog); + } + + if (_imgui_button(IMGUI_SPRITESHEETS_RELOAD.copy({.isDisabled = selectedIDs.empty()}), self)) { + for (auto& id : selectedIDs) { + WorkingDirectory workingDirectory(self->anm2->path); + Texture texture; + texture_from_path_init(&texture, self->anm2->spritesheets[id].path); + self->anm2->spritesheets[id].texture = texture; + } + imgui_log_push(self, IMGUI_LOG_RELOAD_SPRITESHEET); + } + + if (_imgui_button(IMGUI_SPRITESHEETS_REPLACE.copy({.isDisabled = selectedIDs.size() > 1}), self)) + dialog_spritesheet_replace(self->dialog, *selectedIDs.begin()); + + if (self->dialog->isSelected && self->dialog->type == DIALOG_SPRITESHEET_REPLACE) { + + imgui_snapshot(self, IMGUI_ACTION_REPLACE_SPRITESHEET); + + WorkingDirectory workingDirectory(self->anm2->path); + std::string anm2WorkingPath = working_directory_from_file_set(self->anm2->path); + std::string spritesheetPath = std::filesystem::relative(self->dialog->path, anm2WorkingPath).string(); + self->anm2->spritesheets[self->dialog->replaceID].path = spritesheetPath; + Texture texture; + texture_from_path_init(&texture, spritesheetPath); + self->anm2->spritesheets[self->dialog->replaceID].texture = texture; + dialog_reset(self->dialog); + } + + if (_imgui_button(IMGUI_SPRITESHEETS_REMOVE_UNUSED.copy({.isDisabled = self->anm2->spritesheets.empty()}), self)) { + std::unordered_set usedSpritesheetIDs; + + for (auto& [layerID, layer] : self->anm2->layers) + if (layer.spritesheetID != ID_NONE) + usedSpritesheetIDs.insert(layer.spritesheetID); + + for (auto it = self->anm2->spritesheets.begin(); it != self->anm2->spritesheets.end();) { + if (!usedSpritesheetIDs.count(it->first)) { + texture_free(&self->anm2->spritesheets[it->first].texture); + it = self->anm2->spritesheets.erase(it); + } else + it++; + } + } + + if (_imgui_button(IMGUI_SPRITESHEETS_SELECT_ALL.copy({.isDisabled = selectedIDs.size() == self->anm2->spritesheets.size()}), self)) + for (auto [id, _] : self->anm2->spritesheets) + selectedIDs.insert(id); + + if (_imgui_button(IMGUI_SPRITESHEETS_SELECT_NONE.copy({.isDisabled = selectedIDs.empty()}), self)) + selectedIDs.clear(); + + if (_imgui_button(IMGUI_SPRITESHEET_SAVE.copy({.isDisabled = selectedIDs.empty()}), self)) { + for (auto& id : selectedIDs) { + WorkingDirectory workingDirectory(self->anm2->path); + Anm2Spritesheet& spritesheet = self->anm2->spritesheets[id]; + texture_from_gl_write(&spritesheet.texture, spritesheet.path); + imgui_log_push(self, std::format(IMGUI_LOG_SPRITESHEET_SAVE_FORMAT, id, spritesheet.path)); + } + } + + _imgui_end_child(IMGUI_SPRITESHEETS_FOOTER_CHILD, self); + _imgui_end(); // IMGUI_SPRITESHEETS } -static void _imgui_spritesheets(Imgui* self) -{ - static std::unordered_set selectedIDs; - static s32 highlightedID = ID_NONE; +/* +static void _imgui_animation_preview(Imgui* self) { + static int& tool = self->settings->tool; + static float& zoom = self->settings->previewZoom; + static vec2& pan = self->settings->previewPan; + static ivec2& size = self->preview->canvas.size; + static vec2 mousePos{}; - IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEETS, self); - _imgui_no_anm2_path_check(self); + std::string mousePositionString = std::format(IMGUI_POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y); - ImVec2 windowSize = ImGui::GetContentRegionAvail(); + IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATION_PREVIEW, self); - _imgui_begin_child(IMGUI_SPRITESHEETS_CHILD.copy({.size = {windowSize.x, windowSize.y - IMGUI_SPRITESHEETS_FOOTER_CHILD.size.y}}), self); - - std::function spritesheet_item = [&](s32 id, Anm2Spritesheet& spritesheet) - { - ImGui::PushID(id); - - Texture& texture = spritesheet.texture; - bool isContains = selectedIDs.contains(id); - - _imgui_begin_child(IMGUI_SPRITESHEET_CHILD, self); + _imgui_begin_child(IMGUI_CANVAS_GRID_CHILD, self); + _imgui_checkbox(IMGUI_CANVAS_GRID, self, self->settings->previewIsGrid); + ImGui::SameLine(); + _imgui_color_edit4(IMGUI_CANVAS_GRID_COLOR, self, self->settings->previewGridColor); + _imgui_input_int2(IMGUI_CANVAS_GRID_SIZE, self, self->settings->previewGridSize); + _imgui_input_int2(IMGUI_CANVAS_GRID_OFFSET, self, self->settings->previewGridOffset); + _imgui_end_child(); // IMGUI_CANVAS_GRID_CHILD - if (_imgui_checkbox(IMGUI_SPRITESHEET_SELECTED, self, isContains)) - { - if (isContains) - selectedIDs.insert(id); - else - selectedIDs.erase(id); - } + ImGui::SameLine(); - if (_imgui_atlas_selectable(IMGUI_SPRITESHEET.copy({.isSelected = id == highlightedID, .label = std::format(IMGUI_SPRITESHEET_FORMAT, id, spritesheet.path)}), self)) - highlightedID = id; + _imgui_begin_child(IMGUI_CANVAS_VIEW_CHILD, self); + _imgui_drag_float(IMGUI_CANVAS_ZOOM, self, zoom); + if (_imgui_button(IMGUI_ANIMATION_PREVIEW_CENTER_VIEW.copy({.isDisabled = pan == vec2()}), self)) + pan = vec2(); + if (_imgui_button(IMGUI_ANIMATION_PREVIEW_FIT.copy({.isDisabled = self->reference->animationID == ID_NONE}), self)) { + vec4 rect = anm2_animation_rect_get(self->anm2, *self->reference, self->settings->previewIsRootTransform); - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) - { - ImGui::SetDragDropPayload(IMGUI_SPRITESHEET.drag_drop_get(), &id, sizeof(s32)); - spritesheet_item(id, spritesheet); - ImGui::EndDragDropSource(); - } + if (rect != vec4(-1.0f) && (rect.z > 0 && rect.w > 0)) { + float scaleX = self->preview->canvas.size.x / rect.z; + float scaleY = self->preview->canvas.size.y / rect.w; + float fitScale = std::min(scaleX, scaleY); - if (ImGui::BeginDragDropTarget()) - { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_SPRITESHEET.drag_drop_get())) - { - s32 sourceID = *(s32*)payload->Data; - if (sourceID != id) - map_swap(self->anm2->spritesheets, sourceID, id); - } - ImGui::EndDragDropTarget(); - } + zoom = UNIT_TO_PERCENT(fitScale); - ImVec2 spritesheetPreviewSize = IMGUI_SPRITESHEET_PREVIEW_SIZE; - f32 spritesheetAspect = (f32)texture.size.x / texture.size.y; + vec2 rectCenter = {rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f}; + pan = -rectCenter * fitScale; + } + } + ImGui::Text("%s", mousePositionString.c_str()); + _imgui_end_child(); // IMGUI_CANVAS_VIEW_CHILD - if ((IMGUI_SPRITESHEET_PREVIEW_SIZE.x / IMGUI_SPRITESHEET_PREVIEW_SIZE.y) > spritesheetAspect) - spritesheetPreviewSize.x = IMGUI_SPRITESHEET_PREVIEW_SIZE.y * spritesheetAspect; - else - spritesheetPreviewSize.y = IMGUI_SPRITESHEET_PREVIEW_SIZE.x / spritesheetAspect; + ImGui::SameLine(); - if (texture.isInvalid) - _imgui_atlas(ATLAS_NONE, self); - else - ImGui::Image(texture.id, spritesheetPreviewSize); - - _imgui_end_child(); // IMGUI_SPRITESHEET_CHILD + _imgui_begin_child(IMGUI_CANVAS_VISUAL_CHILD, self); + _imgui_color_edit4(IMGUI_CANVAS_BACKGROUND_COLOR, self, self->settings->previewBackgroundColor); - ImGui::PopID(); - }; - - for (auto& [id, spritesheet] : self->anm2->spritesheets) - spritesheet_item(id, spritesheet); + std::vector animationIDs; + ImguiItem animationOverlayItem = IMGUI_CANVAS_ANIMATION_OVERLAY; - _imgui_end_child(); // spritesheetsChild - - _imgui_begin_child(IMGUI_SPRITESHEETS_FOOTER_CHILD, self); - - if (_imgui_button(IMGUI_SPRITESHEET_ADD.copy({self->anm2->path.empty()}), self)) - dialog_spritesheet_add(self->dialog); + animationIDs.emplace_back(ID_NONE); + animationOverlayItem.items.emplace_back(IMGUI_NONE); - if (self->dialog->isSelected && self->dialog->type == DIALOG_SPRITESHEET_ADD) - { - _imgui_spritesheet_add(self, self->dialog->path); - dialog_reset(self->dialog); - } - - if (_imgui_button(IMGUI_SPRITESHEETS_RELOAD.copy({selectedIDs.empty()}), self)) - { - for (auto& id : selectedIDs) - { - std::filesystem::path workingPath = std::filesystem::current_path(); - working_directory_from_file_set(self->anm2->path); - Texture texture; - texture_from_path_init(&texture, self->anm2->spritesheets[id].path); - self->anm2->spritesheets[id].texture = texture; - std::filesystem::current_path(workingPath); - } + for (auto& [id, animation] : self->anm2->animations) { + animationIDs.emplace_back(id); + animationOverlayItem.items.emplace_back(animation.name); + } - imgui_log_push(self, IMGUI_LOG_RELOAD_SPRITESHEET); - } + int animationIndex = 0; - if (_imgui_button(IMGUI_SPRITESHEETS_REPLACE.copy({highlightedID == ID_NONE}), self)) - dialog_spritesheet_replace(self->dialog, highlightedID); + if (self->preview->animationOverlayID != ID_NONE) + animationIndex = std::find(animationIDs.begin(), animationIDs.end(), self->preview->animationOverlayID) - animationIDs.begin(); - if (self->dialog->isSelected && self->dialog->type == DIALOG_SPRITESHEET_REPLACE) - { - imgui_snapshot(self, IMGUI_ACTION_REPLACE_SPRITESHEET); - - std::filesystem::path workingPath = std::filesystem::current_path(); - std::string anm2WorkingPath = working_directory_from_file_set(self->anm2->path); - std::string spritesheetPath = std::filesystem::relative(self->dialog->path, anm2WorkingPath).string(); - - self->anm2->spritesheets[self->dialog->replaceID].path = spritesheetPath; - Texture texture; - texture_from_path_init(&texture, spritesheetPath); - self->anm2->spritesheets[self->dialog->replaceID].texture = texture; - dialog_reset(self->dialog); - std::filesystem::current_path(workingPath); - } + if (_imgui_combo(animationOverlayItem, self, &animationIndex)) + self->preview->animationOverlayID = animationIDs[animationIndex]; - if (_imgui_button(IMGUI_SPRITESHEETS_REMOVE_UNUSED.copy({self->anm2->spritesheets.empty()}), self)) - { - std::unordered_set usedSpritesheetIDs; + _imgui_drag_float(IMGUI_CANVAS_ANIMATION_OVERLAY_TRANSPARENCY, self, self->settings->previewOverlayTransparency); + _imgui_end_child(); // IMGUI_CANVAS_VISUAL_CHILD - for (auto& [layerID, layer] : self->anm2->layers) - if (layer.spritesheetID != ID_NONE) - usedSpritesheetIDs.insert(layer.spritesheetID); + ImGui::SameLine(); - for (auto it = self->anm2->spritesheets.begin(); it != self->anm2->spritesheets.end(); ) - { - if (!usedSpritesheetIDs.count(it->first)) - { - texture_free(&self->anm2->spritesheets[it->first].texture); - it = self->anm2->spritesheets.erase(it); - } - else - it++; - } - } + _imgui_begin_child(IMGUI_CANVAS_HELPER_CHILD, self); + _imgui_checkbox(IMGUI_CANVAS_AXES, self, self->settings->previewIsAxes); + ImGui::SameLine(); + _imgui_color_edit4(IMGUI_CANVAS_AXES_COLOR, self, self->settings->previewAxesColor); + ImGui::SameLine(); + _imgui_checkbox(IMGUI_CANVAS_ALT_ICONS, self, self->settings->previewIsAltIcons); + _imgui_checkbox(IMGUI_CANVAS_ROOT_TRANSFORM, self, self->settings->previewIsRootTransform); + ImGui::SameLine(); + _imgui_checkbox(IMGUI_CANVAS_TRIGGERS, self, self->settings->previewIsTriggers); + _imgui_checkbox(IMGUI_CANVAS_PIVOTS, self, self->settings->previewIsPivots); + ImGui::SameLine(); + _imgui_checkbox(IMGUI_CANVAS_ICONS, self, self->settings->previewIsIcons); + ImGui::SameLine(); + _imgui_checkbox(IMGUI_CANVAS_BORDER, self, self->settings->previewIsBorder); + _imgui_end_child(); // IMGUI_CANVAS_HELPER_CHILD - if (_imgui_button(IMGUI_SPRITESHEETS_SELECT_ALL.copy({selectedIDs.size() == self->anm2->spritesheets.size()}), self)) - for (auto [id, _] : self->anm2->spritesheets) - selectedIDs.insert(id); + ImVec2 previewCursorScreenPos = ImGui::GetCursorScreenPos(); - if (_imgui_button(IMGUI_SPRITESHEETS_SELECT_NONE.copy({selectedIDs.empty()}), self)) - selectedIDs.clear(); + if (!self->preview->isRender) + size = ivec2(vec2(ImGui::GetContentRegionAvail())); - if (_imgui_button(IMGUI_SPRITESHEET_SAVE.copy({selectedIDs.empty()}), self)) - { - for (auto& id : selectedIDs) - { - Anm2Spritesheet& spritesheet = self->anm2->spritesheets[id]; - std::filesystem::path workingPath = std::filesystem::current_path(); - working_directory_from_file_set(self->anm2->path); - texture_from_gl_write(&spritesheet.texture, spritesheet.path); - imgui_log_push(self, std::format(IMGUI_LOG_SPRITESHEET_SAVE_FORMAT, id, spritesheet.path)); - std::filesystem::current_path(workingPath); - } - } + preview_draw(self->preview); + ImGui::Image(self->preview->canvas.framebuffer, vec2(size)); - if (_imgui_is_no_click_on_item()) highlightedID = ID_NONE; + if (self->settings->previewIsTriggers) { + Anm2Frame trigger; + anm2_frame_from_time(self->anm2, &trigger, {self->reference->animationID, ANM2_TRIGGER}, self->preview->time); - _imgui_end_child(); //IMGUI_SPRITESHEETS_FOOTER_CHILD - _imgui_end(); // IMGUI_SPRITESHEETS + if (trigger.eventID != ID_NONE) { + ImVec2 textPos = previewCursorScreenPos + ImGui::GetStyle().ItemSpacing; + ImGui::PushFont(NULL, ImGui::GetStyle().FontSizeBase * IMGUI_TRIGGERS_FONT_SCALE); + ImGui::GetWindowDrawList()->AddText(textPos, IMGUI_TRIGGERS_EVENT_COLOR, self->anm2->events[trigger.eventID].name.c_str()); + ImGui::PopFont(); + } + } + + if (ImGui::IsItemHovered()) { + self->pendingCursor = TOOL_CURSORS[tool]; + imgui_keyboard_nav_disable(); + } else { + _imgui_end(); // IMGUI_ANIMATION_EDITOR + imgui_keyboard_nav_enable(); + return; + } + + _imgui_end(); // IMGUI_ANIMATION_PREVIEW + + mousePos = vec2(ImGui::GetMousePos() - previewCursorScreenPos - pan - (vec2(size) * 0.5f)) / PERCENT_TO_UNIT(zoom); + + const bool isLeft = ImGui::IsKeyPressed(IMGUI_INPUT_LEFT); + const bool isRight = ImGui::IsKeyPressed(IMGUI_INPUT_RIGHT); + const bool isUp = ImGui::IsKeyPressed(IMGUI_INPUT_UP); + const bool isDown = ImGui::IsKeyPressed(IMGUI_INPUT_DOWN); + const bool isMod = ImGui::IsKeyDown(IMGUI_INPUT_SHIFT); + const bool isZoomIn = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_IN]); + const bool isZoomOut = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_OUT]); + const bool isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); + const bool isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); + const bool isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); + const ImVec2 mouseDelta = ImGui::GetIO().MouseDelta; + const float mouseWheel = ImGui::GetIO().MouseWheel; + + Anm2Frame* frame = nullptr; + + if (self->reference->itemType != ANM2_TRIGGER) + frame = anm2_frame_from_reference(self->anm2, *self->reference); + + float step = isMod ? TOOL_STEP_MOD : TOOL_STEP; + + if ((tool == TOOL_PAN && isMouseDown) || isMouseMiddleDown) + pan += vec2(mouseDelta.x, mouseDelta.y); + + switch (tool) { + case TOOL_MOVE: + if (!frame) + break; + + if (isMouseClick || isLeft || isRight || isUp || isDown) + imgui_snapshot(self, IMGUI_ACTION_MOVE); + + if (isMouseDown) + frame->position = vec2(mousePos); + else { + if (isLeft) + frame->position.x -= step; + if (isRight) + frame->position.x += step; + if (isUp) + frame->position.y -= step; + if (isDown) + frame->position.y += step; + } + break; + case TOOL_ROTATE: + if (!frame) + break; + + if (isMouseClick || isLeft || isRight || isUp || isDown) + imgui_snapshot(self, IMGUI_ACTION_ROTATE); + + if (isMouseDown) + frame->rotation += mouseDelta.x; + else { + if (isLeft || isUp) + frame->rotation -= step; + if (isRight || isDown) + frame->rotation += step; + } + break; + case TOOL_SCALE: + if (!frame) + break; + + if (isMouseClick || isLeft || isRight || isUp || isDown) + imgui_snapshot(self, IMGUI_ACTION_SCALE); + + if (isMouseDown) + frame->scale += vec2(mouseDelta.x, mouseDelta.y); + else { + if (isLeft) + frame->scale.x -= step; + if (isRight) + frame->scale.x += step; + if (isUp) + frame->scale.y -= step; + if (isDown) + frame->scale.y += step; + } + break; + default: + break; + } + + if (mouseWheel != 0 || isZoomIn || isZoomOut) { + float delta = (mouseWheel > 0 || isZoomIn) ? CANVAS_ZOOM_STEP : -CANVAS_ZOOM_STEP; + zoom = std::clamp(ROUND_NEAREST_MULTIPLE(zoom + delta, CANVAS_ZOOM_STEP), CANVAS_ZOOM_MIN, CANVAS_ZOOM_MAX); + } } -static void _imgui_animation_preview(Imgui* self) -{ - static s32& tool = self->settings->tool; - static f32& zoom = self->settings->previewZoom; - static vec2& pan = self->settings->previewPan; - static ivec2& size = self->preview->canvas.size; - static vec2 mousePos{}; - static vec2 previewPos{}; +static void _imgui_spritesheet_editor(Imgui* self) { + static vec2 mousePos = {0, 0}; + static int& tool = self->settings->tool; + static vec4& toolColor = self->settings->toolColor; + static ivec2& gridSize = self->settings->editorGridSize; + static ivec2& gridOffset = self->settings->editorGridOffset; + static vec2& pan = self->settings->editorPan; + static float& zoom = self->settings->editorZoom; + static ivec2& size = self->editor->canvas.size; - std::string mousePositionString = std::format(IMGUI_POSITION_FORMAT, (s32)mousePos.x, (s32)mousePos.y); - - IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATION_PREVIEW, self); + std::string mousePositionString = std::format(IMGUI_POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y); - _imgui_begin_child(IMGUI_CANVAS_GRID_CHILD, self); - _imgui_checkbox(IMGUI_CANVAS_GRID, self, self->settings->previewIsGrid); - ImGui::SameLine(); - _imgui_color_edit4(IMGUI_CANVAS_GRID_COLOR, self, self->settings->previewGridColor); - _imgui_input_int2(IMGUI_CANVAS_GRID_SIZE, self, self->settings->previewGridSize); - _imgui_input_int2(IMGUI_CANVAS_GRID_OFFSET, self, self->settings->previewGridOffset); - _imgui_end_child(); // IMGUI_CANVAS_GRID_CHILD - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_VIEW_CHILD, self); - _imgui_drag_float(IMGUI_CANVAS_ZOOM, self, zoom); - if (_imgui_button(IMGUI_ANIMATION_PREVIEW_CENTER_VIEW.copy({pan == vec2()}), self)) pan = vec2(); - if (_imgui_button(IMGUI_ANIMATION_PREVIEW_FIT.copy({self->reference->animationID == ID_NONE}), self)) - { - vec4 rect = anm2_animation_rect_get(self->anm2, self->reference, self->settings->previewIsRootTransform); - - if (rect != vec4(-1.0f) && (rect.z > 0 && rect.w > 0)) - { - f32 scaleX = self->preview->canvas.size.x / rect.z; - f32 scaleY = self->preview->canvas.size.y / rect.w; - f32 fitScale = std::min(scaleX, scaleY); + IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEET_EDITOR, self); - zoom = UNIT_TO_PERCENT(fitScale); + _imgui_begin_child(IMGUI_CANVAS_GRID_CHILD, self); + _imgui_checkbox(IMGUI_CANVAS_GRID, self, self->settings->editorIsGrid); + ImGui::SameLine(); + _imgui_checkbox(IMGUI_CANVAS_GRID_SNAP, self, self->settings->editorIsGridSnap); + ImGui::SameLine(); + _imgui_color_edit4(IMGUI_CANVAS_GRID_COLOR, self, self->settings->editorGridColor); + _imgui_input_int2(IMGUI_CANVAS_GRID_SIZE, self, gridSize); + _imgui_input_int2(IMGUI_CANVAS_GRID_OFFSET, self, gridOffset); + _imgui_end_child(); - vec2 rectCenter = { rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f }; - pan = -rectCenter * fitScale; - } - } - ImGui::Text(mousePositionString.c_str()); - _imgui_end_child(); //IMGUI_CANVAS_VIEW_CHILD + ImGui::SameLine(); - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_VISUAL_CHILD, self); - _imgui_color_edit4(IMGUI_CANVAS_BACKGROUND_COLOR, self, self->settings->previewBackgroundColor); - - std::vector animationIDs; - ImguiItem animationOverlayItem = IMGUI_CANVAS_ANIMATION_OVERLAY; + _imgui_begin_child(IMGUI_CANVAS_VIEW_CHILD, self); + _imgui_drag_float(IMGUI_CANVAS_ZOOM, self, zoom); + if (_imgui_button(IMGUI_SPRITESHEET_EDITOR_CENTER_VIEW.copy({.isDisabled = pan == vec2()}), self)) + pan = vec2(); + if (_imgui_button(IMGUI_SPRITESHEET_EDITOR_FIT.copy({.isDisabled = self->editor->spritesheetID == ID_NONE}), self)) { + vec4 rect = {0, 0, self->anm2->spritesheets[self->editor->spritesheetID].texture.size.x, + self->anm2->spritesheets[self->editor->spritesheetID].texture.size.y}; - animationIDs.emplace_back(ID_NONE); - animationOverlayItem.items.emplace_back(IMGUI_NONE); + if ((rect.z > 0 && rect.w > 0)) { + float scaleX = self->editor->canvas.size.x / rect.z; + float scaleY = self->editor->canvas.size.y / rect.w; + float fitScale = std::min(scaleX, scaleY); - for (auto& [id, animation] : self->anm2->animations) - { - animationIDs.emplace_back(id); - animationOverlayItem.items.emplace_back(animation.name); - } + zoom = UNIT_TO_PERCENT(fitScale); + pan = {}; + } + } + ImGui::Text("%s", mousePositionString.c_str()); + _imgui_end_child(); // IMGUI_CANVAS_VIEW_CHILD - s32 animationIndex = 0; + ImGui::SameLine(); - if (self->preview->animationOverlayID != ID_NONE) - animationIndex = std::find(animationIDs.begin(), animationIDs.end(), self->preview->animationOverlayID) - animationIDs.begin(); - - if (_imgui_combo(animationOverlayItem, self, &animationIndex)) - self->preview->animationOverlayID = animationIDs[animationIndex]; + _imgui_begin_child(IMGUI_CANVAS_VISUAL_CHILD, self); + _imgui_color_edit4(IMGUI_CANVAS_BACKGROUND_COLOR, self, self->settings->editorBackgroundColor); + _imgui_checkbox(IMGUI_CANVAS_BORDER, self, self->settings->editorIsBorder); + _imgui_end_child(); // IMGUI_CANVAS_VISUAL_CHILD - _imgui_drag_float(IMGUI_CANVAS_ANIMATION_OVERLAY_TRANSPARENCY, self, self->settings->previewOverlayTransparency); - _imgui_end_child(); //IMGUI_CANVAS_VISUAL_CHILD + ImVec2 editorCursorScreenPos = ImGui::GetCursorScreenPos(); + size = ivec2(vec2(ImGui::GetContentRegionAvail())); + editor_draw(self->editor); + ImGui::Image(self->editor->canvas.framebuffer, vec2(size)); - ImGui::SameLine(); + if (ImGui::IsItemHovered()) { + self->pendingCursor = TOOL_CURSORS[tool]; + imgui_keyboard_nav_disable(); + } else { + _imgui_end(); // IMGUI_SPRITESHEET_EDITOR + imgui_keyboard_nav_enable(); + return; + } - _imgui_begin_child(IMGUI_CANVAS_HELPER_CHILD, self); - _imgui_checkbox(IMGUI_CANVAS_AXES, self, self->settings->previewIsAxes); - ImGui::SameLine(); - _imgui_color_edit4(IMGUI_CANVAS_AXES_COLOR, self, self->settings->previewAxesColor); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_ALT_ICONS, self, self->settings->previewIsAltIcons); - _imgui_checkbox(IMGUI_CANVAS_ROOT_TRANSFORM, self, self->settings->previewIsRootTransform); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_TRIGGERS, self, self->settings->previewIsTriggers); - _imgui_checkbox(IMGUI_CANVAS_PIVOTS, self, self->settings->previewIsPivots); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_ICONS, self, self->settings->previewIsIcons); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_BORDER, self, self->settings->previewIsBorder); - _imgui_end_child(); // IMGUI_CANVAS_HELPER_CHILD + _imgui_end(); // IMGUI_SPRITESHEET_EDITOR - ImVec2 previewCursorScreenPos = ImGui::GetCursorScreenPos(); - - if (!self->preview->isRender) size = ivec2(vec2(ImGui::GetContentRegionAvail())); - - preview_draw(self->preview); - ImGui::Image(self->preview->canvas.framebuffer, vec2(size)); - - if (self->settings->previewIsTriggers) - { - Anm2Frame trigger; - anm2_frame_from_time(self->anm2, &trigger, {self->reference->animationID, ANM2_TRIGGERS}, self->preview->time); + mousePos = vec2(ImGui::GetMousePos() - editorCursorScreenPos - pan) / PERCENT_TO_UNIT(zoom); - if (trigger.eventID != ID_NONE) - { - f32 textScale = ImGui::GetCurrentWindow()->FontWindowScale; - ImVec2 textPos = previewCursorScreenPos + ImGui::GetStyle().ItemSpacing; - ImGui::SetWindowFontScale(IMGUI_TRIGGERS_FONT_SCALE); - ImGui::GetWindowDrawList()->AddText(textPos, IMGUI_TRIGGERS_EVENT_COLOR, self->anm2->events[trigger.eventID].name.c_str()); - ImGui::SetWindowFontScale(textScale); - } - } + const bool isLeft = ImGui::IsKeyPressed(IMGUI_INPUT_LEFT); + const bool isRight = ImGui::IsKeyPressed(IMGUI_INPUT_RIGHT); + const bool isUp = ImGui::IsKeyPressed(IMGUI_INPUT_UP); + const bool isDown = ImGui::IsKeyPressed(IMGUI_INPUT_DOWN); + const bool isShift = ImGui::IsKeyDown(IMGUI_INPUT_SHIFT); + const bool isCtrl = ImGui::IsKeyDown(IMGUI_INPUT_CTRL); + const bool isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); + const bool isMouseRightClick = ImGui::IsMouseClicked(ImGuiMouseButton_Right); + const bool isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); + const bool isMouseRightDown = ImGui::IsMouseDown(ImGuiMouseButton_Right); + const bool isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); + const bool isZoomIn = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_IN]); + const bool isZoomOut = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_OUT]); + const float mouseWheel = ImGui::GetIO().MouseWheel; + const ImVec2 mouseDelta = ImGui::GetIO().MouseDelta; - if (ImGui::IsItemHovered()) - { - self->pendingCursor = TOOL_CURSORS[tool]; - imgui_keyboard_nav_disable(); - } - else - { - _imgui_end(); // IMGUI_ANIMATION_EDITOR - imgui_keyboard_nav_enable(); - return; - } + Anm2Frame* frame = nullptr; + if (self->reference->itemType == ANM2_LAYER) + frame = anm2_frame_from_reference(self->anm2, *self->reference); - _imgui_end(); // IMGUI_ANIMATION_PREVIEW + Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->editor->spritesheetID); + Texture* texture = spritesheet ? &spritesheet->texture : nullptr; - mousePos = vec2(ImGui::GetMousePos() - previewCursorScreenPos - pan - (vec2(size) * 0.5f)) / PERCENT_TO_UNIT(zoom); - - const bool isLeft = ImGui::IsKeyPressed(IMGUI_INPUT_LEFT); - const bool isRight = ImGui::IsKeyPressed(IMGUI_INPUT_RIGHT); - const bool isUp = ImGui::IsKeyPressed(IMGUI_INPUT_UP); - const bool isDown = ImGui::IsKeyPressed(IMGUI_INPUT_DOWN); - const bool isMod = ImGui::IsKeyDown(IMGUI_INPUT_SHIFT); - const bool isZoomIn = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_IN]); - const bool isZoomOut = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_OUT]); - const bool isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); - const bool isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); - const bool isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); - const ImVec2 mouseDelta = ImGui::GetIO().MouseDelta; - const f32 mouseWheel = ImGui::GetIO().MouseWheel; - - Anm2Frame* frame = nullptr; - - if (self->reference->itemType != ANM2_TRIGGERS) - frame = anm2_frame_from_reference(self->anm2, self->reference); + vec2 position = mousePos; + float step = isShift ? TOOL_STEP_MOD : TOOL_STEP; - f32 step = isMod ? TOOL_STEP_MOD : TOOL_STEP; - - if ((tool == TOOL_PAN && isMouseDown) || isMouseMiddleDown) - pan += vec2(mouseDelta.x, mouseDelta.y); + if ((tool == TOOL_PAN && isMouseDown) || isMouseMiddleDown) + pan += vec2(mouseDelta.x, mouseDelta.y); - switch (tool) - { - case TOOL_MOVE: - if (!frame) break; - - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_MOVE); - - if (isMouseDown) - frame->position = vec2(mousePos); - else - { - if (isLeft) frame->position.x -= step; - if (isRight) frame->position.x += step; - if (isUp) frame->position.y -= step; - if (isDown) frame->position.y += step; - } - break; - case TOOL_ROTATE: - if (!frame) break; + auto spritesheet_editor_move = [&](bool isPrimary = true) { + bool isActivated = isPrimary ? isMouseClick || isLeft || isRight || isUp || isDown : isMouseRightClick; + bool isUseMouseDown = isPrimary ? isMouseDown : isMouseRightDown; - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_ROTATE); - - if (isMouseDown) - frame->rotation += mouseDelta.x; - else - { - if (isLeft || isUp) frame->rotation -= step; - if (isRight || isDown) frame->rotation += step; - } - break; - case TOOL_SCALE: - if (!frame) break; + if (isActivated) + imgui_snapshot(self, IMGUI_ACTION_MOVE); - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_SCALE); - - if (isMouseDown) - frame->scale += vec2(mouseDelta.x, mouseDelta.y); - else - { - if (isLeft) frame->scale.x -= step; - if (isRight) frame->scale.x += step; - if (isUp) frame->scale.y -= step; - if (isDown) frame->scale.y += step; - } - break; - default: - break; - } + if (isUseMouseDown) + frame->pivot = position - frame->crop; + else if (isPrimary) { + if (isLeft) + frame->pivot.x -= step; + if (isRight) + frame->pivot.x += step; + if (isUp) + frame->pivot.y -= step; + if (isDown) + frame->pivot.y += step; + } + }; - if (mouseWheel != 0 || isZoomIn || isZoomOut) - { - f32 delta = (mouseWheel > 0 || isZoomIn) ? CANVAS_ZOOM_STEP : -CANVAS_ZOOM_STEP; - zoom = std::clamp(ROUND_NEAREST_MULTIPLE(zoom + delta, CANVAS_ZOOM_STEP), CANVAS_ZOOM_MIN, CANVAS_ZOOM_MAX); - } + auto spritesheet_editor_crop = [&](bool isPrimary = true) { + bool isActivated = isPrimary ? isMouseClick || isLeft || isRight || isUp || isDown : isMouseRightClick; + bool isUseMouseClick = isPrimary ? isMouseClick : isMouseRightClick; + bool isUseMouseDown = isPrimary ? isMouseDown : isMouseRightDown; + + vec2 cropPosition = self->settings->editorIsGridSnap ? vec2(roundf(position.x / gridSize.x) * gridSize.x + gridOffset.x - (gridSize.x * 0.5f), + roundf(position.y / gridSize.y) * gridSize.y + gridOffset.y - (gridSize.y * 0.5f)) + : position; + + if (isActivated) + imgui_snapshot(self, IMGUI_ACTION_MOVE); + + if (isUseMouseClick) { + frame->crop = cropPosition; + frame->size = ivec2(); + } else if (isUseMouseDown) + frame->size = position - frame->crop; + else if (isPrimary) { + if (isCtrl) { + if (isLeft) + frame->crop.x -= step; + if (isRight) + frame->crop.x += step; + if (isUp) + frame->crop.y -= step; + if (isDown) + frame->crop.y += step; + } else { + if (isLeft) + frame->size.x -= step; + if (isRight) + frame->size.x += step; + if (isUp) + frame->size.y -= step; + if (isDown) + frame->size.y += step; + } + + frame->size.x = std::max({}, frame->size.x); + frame->size.y = std::max({}, frame->size.y); + } + }; + + auto spritesheet_editor_draw = [&](vec4 color) { + if (isMouseClick || isMouseRightClick) + imgui_snapshot(self, color != vec4() ? IMGUI_ACTION_DRAW : IMGUI_ACTION_ERASE); + + if (isMouseDown || isMouseRightDown) + texture_pixel_set(texture, position, color); + }; + + switch (tool) { + case TOOL_MOVE: + if (!texture || !frame) + break; + spritesheet_editor_move(true); + spritesheet_editor_crop(false); + break; + case TOOL_CROP: + if (!texture || !frame) + break; + spritesheet_editor_crop(true); + spritesheet_editor_move(false); + break; + case TOOL_DRAW: + case TOOL_ERASE: + if (!texture) + break; + spritesheet_editor_draw(tool == TOOL_DRAW && !isMouseRightDown ? self->settings->toolColor : vec4()); + break; + case TOOL_COLOR_PICKER: + if (isMouseDown) { + SDL_GetMouseState(&mousePos.x, &mousePos.y); + + ImGuiIO& io = ImGui::GetIO(); + ivec2 fbPosition = {(int)(position.x * io.DisplayFramebufferScale.x), (int)(position.y * io.DisplayFramebufferScale.y)}; + ivec2 size{}; + SDL_GetWindowSizeInPixels(self, &size.x, &size.y); + + if (fbPosition.x < 0 || fbPosition.y < 0 || fbPosition.x >= size.x || fbPosition.y >= size.y) + return false; + + uint8_t rgba[4]; + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(fbPosition.x, size.y - 1 - fbPosition.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba); + + color = vec4(UINT8_TO_FLOAT(rgba[0]), UINT8_TO_FLOAT(rgba[1]), UINT8_TO_FLOAT(rgba[2]), UINT8_TO_FLOAT(rgba[3])); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); + ImGui::BeginTooltip(); + _imgui_color_button(IMGUI_COLOR_PICKER_BUTTON, self, toolColor); + ImGui::EndTooltip(); + ImGui::PopStyleVar(); + } + break; + default: + break; + } + + if (mouseWheel != 0 || isZoomIn || isZoomOut) { + float delta = (mouseWheel > 0 || isZoomIn) ? CANVAS_ZOOM_STEP : -CANVAS_ZOOM_STEP; + zoom = std::clamp(ROUND_NEAREST_MULTIPLE(zoom + delta, CANVAS_ZOOM_STEP), CANVAS_ZOOM_MIN, CANVAS_ZOOM_MAX); + } } -static void _imgui_spritesheet_editor(Imgui* self) -{ - static vec2 mousePos = {0, 0}; - static s32& tool = self->settings->tool; - static vec4& toolColor = self->settings->toolColor; - static ivec2& gridSize = self->settings->editorGridSize; - static ivec2& gridOffset = self->settings->editorGridOffset; - static vec2& pan = self->settings->editorPan; - static f32& zoom = self->settings->editorZoom; - static ivec2& size = self->editor->canvas.size; - - std::string mousePositionString = std::format(IMGUI_POSITION_FORMAT, (s32)mousePos.x, (s32)mousePos.y); +static void _imgui_frame_properties(Imgui* self) { + static Anm2Type& type = self->reference->itemType; - IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEET_EDITOR, self); - - _imgui_begin_child(IMGUI_CANVAS_GRID_CHILD, self); - _imgui_checkbox(IMGUI_CANVAS_GRID, self, self->settings->editorIsGrid); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_GRID_SNAP, self, self->settings->editorIsGridSnap); - ImGui::SameLine(); - _imgui_color_edit4(IMGUI_CANVAS_GRID_COLOR, self, self->settings->editorGridColor); - _imgui_input_int2(IMGUI_CANVAS_GRID_SIZE, self, gridSize); - _imgui_input_int2(IMGUI_CANVAS_GRID_OFFSET, self, gridOffset); - _imgui_end_child(); - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_VIEW_CHILD, self); - _imgui_drag_float(IMGUI_CANVAS_ZOOM, self, zoom); - if (_imgui_button(IMGUI_SPRITESHEET_EDITOR_CENTER_VIEW.copy({pan == vec2()}), self)) pan = vec2(); - if (_imgui_button(IMGUI_SPRITESHEET_EDITOR_FIT.copy({self->editor->spritesheetID == ID_NONE}), self)) - { - vec4 rect = {0, 0, self->anm2->spritesheets[self->editor->spritesheetID].texture.size.x, - self->anm2->spritesheets[self->editor->spritesheetID].texture.size.y}; + IMGUI_BEGIN_OR_RETURN(IMGUI_FRAME_PROPERTIES, self); - if ((rect.z > 0 && rect.w > 0)) - { - f32 scaleX = self->editor->canvas.size.x / rect.z; - f32 scaleY = self->editor->canvas.size.y / rect.w; - f32 fitScale = std::min(scaleX, scaleY); + Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *self->reference); - zoom = UNIT_TO_PERCENT(fitScale); - pan = {}; - } - } - ImGui::Text(mousePositionString.c_str()); - _imgui_end_child(); // IMGUI_CANVAS_VIEW_CHILD - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_VISUAL_CHILD, self); - _imgui_color_edit4(IMGUI_CANVAS_BACKGROUND_COLOR, self, self->settings->editorBackgroundColor); - _imgui_checkbox(IMGUI_CANVAS_BORDER, self, self->settings->editorIsBorder); - _imgui_end_child(); // IMGUI_CANVAS_VISUAL_CHILD - - ImVec2 editorCursorScreenPos = ImGui::GetCursorScreenPos(); - size = ivec2(vec2(ImGui::GetContentRegionAvail())); - editor_draw(self->editor); - ImGui::Image(self->editor->canvas.framebuffer, vec2(size)); - - if (ImGui::IsItemHovered()) - { - self->pendingCursor = TOOL_CURSORS[tool]; - imgui_keyboard_nav_disable(); - } - else - { - _imgui_end(); // IMGUI_SPRITESHEET_EDITOR - imgui_keyboard_nav_enable(); - return; - } + bool isLayerFrame = frame && type == ANM2_LAYER; - _imgui_end(); // IMGUI_SPRITESHEET_EDITOR + if (!frame || type != ANM2_TRIGGER) { + _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_CROP.copy({.isDisabled = !isLayerFrame}), self, !isLayerFrame ? dummy_value() : frame->crop); + _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_SIZE.copy({.isDisabled = !isLayerFrame}), self, !isLayerFrame ? dummy_value() : frame->size); + _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_POSITION.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->position); + _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_PIVOT.copy({.isDisabled = !isLayerFrame}), self, !isLayerFrame ? dummy_value() : frame->pivot); + _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_SCALE.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->scale); + _imgui_drag_float(IMGUI_FRAME_PROPERTIES_ROTATION.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->rotation); + _imgui_input_int(IMGUI_FRAME_PROPERTIES_DELAY.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->delay); + _imgui_color_edit4(IMGUI_FRAME_PROPERTIES_TINT.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->tintRGBA); + _imgui_color_edit3(IMGUI_FRAME_PROPERTIES_COLOR_OFFSET.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->offsetRGB); + _imgui_checkbox(IMGUI_FRAME_PROPERTIES_VISIBLE.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->isVisible); + _imgui_checkbox(IMGUI_FRAME_PROPERTIES_INTERPOLATED.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->isInterpolated); + _imgui_checkbox(IMGUI_FRAME_PROPERTIES_ROUND.copy({.isDisabled = !frame}), self, self->settings->propertiesIsRound); + if (_imgui_button(IMGUI_FRAME_PROPERTIES_FLIP_X.copy({.isDisabled = !frame}), self)) + frame->scale.x = -frame->scale.x; + if (_imgui_button(IMGUI_FRAME_PROPERTIES_FLIP_Y.copy({.isDisabled = !frame}), self)) + frame->scale.y = -frame->scale.y; - mousePos = vec2(ImGui::GetMousePos() - editorCursorScreenPos - pan) / PERCENT_TO_UNIT(zoom); + if (self->settings->propertiesIsRound && frame) { + frame->position = glm::trunc(frame->position); + frame->pivot = glm::trunc(frame->pivot); + frame->crop = glm::trunc(frame->crop); + frame->scale = glm::trunc(frame->scale); + frame->rotation = glm::trunc(frame->rotation); + } + } else { + std::vector eventIDs; + ImguiItem eventItem = IMGUI_FRAME_PROPERTIES_EVENT.copy({.isDisabled = !frame}); - const bool isLeft = ImGui::IsKeyPressed(IMGUI_INPUT_LEFT); - const bool isRight = ImGui::IsKeyPressed(IMGUI_INPUT_RIGHT); - const bool isUp = ImGui::IsKeyPressed(IMGUI_INPUT_UP); - const bool isDown = ImGui::IsKeyPressed(IMGUI_INPUT_DOWN); - const bool isShift = ImGui::IsKeyDown(IMGUI_INPUT_SHIFT); - const bool isCtrl = ImGui::IsKeyDown(IMGUI_INPUT_CTRL); - const bool isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); - const bool isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); - const bool isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); - const bool isZoomIn = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_IN]); - const bool isZoomOut = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_OUT]); - const f32 mouseWheel = ImGui::GetIO().MouseWheel; - const ImVec2 mouseDelta = ImGui::GetIO().MouseDelta; - - Anm2Frame* frame = nullptr; - if (self->reference->itemType == ANM2_LAYER) - frame = anm2_frame_from_reference(self->anm2, self->reference); + eventIDs.emplace_back(ID_NONE); + eventItem.items.emplace_back(IMGUI_NONE); - Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->editor->spritesheetID); - Texture* texture = spritesheet ? &spritesheet->texture : nullptr; + for (auto& [id, event] : self->anm2->events) { + eventIDs.emplace_back(id); + eventItem.items.emplace_back(event.name); + } - vec2 position = mousePos; - f32 step = isShift ? TOOL_STEP_MOD : TOOL_STEP; - - if ((tool == TOOL_PAN && isMouseDown) || isMouseMiddleDown) - pan += vec2(mouseDelta.x, mouseDelta.y); - - switch (tool) - { - case TOOL_MOVE: - if (!texture || !frame) break; + int eventIndex = std::find(eventIDs.begin(), eventIDs.end(), frame->eventID) - eventIDs.begin(); - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_MOVE); + if (_imgui_combo(eventItem, self, &eventIndex)) + frame->eventID = eventIDs[eventIndex]; - if (isMouseDown) - { - if (self->settings->editorIsGridSnap) - { - position.x = roundf((position.x - gridSize.x) / gridSize.x) * gridSize.x + gridOffset.x - (gridSize.x * 0.5f); - position.y = roundf((position.y - gridSize.y) / gridSize.y) * gridSize.y + gridOffset.y - (gridSize.y * 0.5f); - } + _imgui_input_int(IMGUI_FRAME_PROPERTIES_AT_FRAME.copy({.isDisabled = !frame}), self, frame->atFrame); + } - frame->pivot = position - frame->crop; - } - else - { - if (isLeft) frame->pivot.x -= step; - if (isRight) frame->pivot.x += step; - if (isUp) frame->pivot.y -= step; - if (isDown) frame->pivot.y += step; - } - break; - case TOOL_CROP: - if (!texture || !frame) break; + _imgui_end(); // IMGUI_FRAME_PROPERTIES +} +*/ - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_MOVE); +static void _imgui_log(Imgui* self) { + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle& style = ImGui::GetStyle(); + ImVec4 borderColor = style.Colors[ImGuiCol_Border]; + ImVec4 textColor = style.Colors[ImGuiCol_Text]; - if (self->settings->editorIsGridSnap) - { - position.x = roundf(position.x / gridSize.x) * gridSize.x + gridOffset.x - (gridSize.x * 0.5f); - position.y = roundf(position.y / gridSize.y) * gridSize.y + gridOffset.y - (gridSize.y * 0.5f); - } - - if (isMouseClick) - { - frame->crop = position; - frame->size = ivec2(0,0); - } - else if (isMouseDown) - frame->size = position - frame->crop; - else - { - if (isCtrl) - { - if (isLeft) frame->crop.x -= step; - if (isRight) frame->crop.x += step; - if (isUp) frame->crop.y -= step; - if (isDown) frame->crop.y += step; - } - else - { - if (isLeft) frame->size.x -= step; - if (isRight) frame->size.x += step; - if (isUp) frame->size.y -= step; - if (isDown) frame->size.y += step; - } + ImVec2 position = {io.DisplaySize.x - IMGUI_LOG_PADDING, io.DisplaySize.y - IMGUI_LOG_PADDING}; - frame->size.x = std::max({}, frame->size.x); - frame->size.y = std::max({}, frame->size.y); - } - break; - case TOOL_DRAW: - case TOOL_ERASE: - { - if (!texture) break; - - vec4 color = tool == TOOL_ERASE ? COLOR_TRANSPARENT : toolColor; + for (int i = (int)self->log.size() - 1; i >= 0; --i) { + ImguiLogItem& item = self->log[i]; + float lifetime = item.timeRemaining / IMGUI_LOG_DURATION; + borderColor.w = lifetime; + textColor.w = lifetime; - if (isMouseClick) - imgui_snapshot(self, tool == TOOL_DRAW ? IMGUI_ACTION_DRAW : IMGUI_ACTION_ERASE); + item.timeRemaining -= io.DeltaTime; - if (isMouseDown) - texture_pixel_set(texture, position, color); - break; - } - case TOOL_COLOR_PICKER: - if (isMouseDown) - { - SDL_GetMouseState(&mousePos.x, &mousePos.y); - _imgui_window_color_from_position_get(self->window, mousePos, toolColor); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); - ImGui::BeginTooltip(); - _imgui_color_button(IMGUI_COLOR_PICKER_BUTTON, self, toolColor); - ImGui::EndTooltip(); - ImGui::PopStyleVar(); - } - break; - default: - break; - } - - if (mouseWheel != 0 || isZoomIn || isZoomOut) - { - f32 delta = (mouseWheel > 0 || isZoomIn) ? CANVAS_ZOOM_STEP : -CANVAS_ZOOM_STEP; - zoom = std::clamp(ROUND_NEAREST_MULTIPLE(zoom + delta, CANVAS_ZOOM_STEP), CANVAS_ZOOM_MIN, CANVAS_ZOOM_MAX); - } + if (item.timeRemaining <= 0.0f) { + self->log.erase(self->log.begin() + i); + continue; + } + + ImGui::SetNextWindowPos(position, ImGuiCond_Always, {1.0f, 1.0f}); + ImGui::PushStyleColor(ImGuiCol_Border, borderColor); + ImGui::PushStyleColor(ImGuiCol_Text, textColor); + ImGui::SetNextWindowBgAlpha(lifetime); + + _imgui_begin(IMGUI_LOG_WINDOW.copy({.label = std::format(IMGUI_LOG_FORMAT, i)}), self); + ImGui::TextUnformatted(item.text.c_str()); + ImVec2 windowSize = ImGui::GetWindowSize(); + _imgui_end(); // IMGUI_LOG_WINDOW + + ImGui::PopStyleColor(2); + + position.y -= windowSize.y + IMGUI_LOG_PADDING; + } } -static void _imgui_frame_properties(Imgui* self) -{ - static Anm2Type& type = self->reference->itemType; - - IMGUI_BEGIN_OR_RETURN(IMGUI_FRAME_PROPERTIES, self); +static void _imgui_dock(Imgui* self) { + ImguiItem window = IMGUI_WINDOW_MAIN; + ImGuiViewport* viewport = ImGui::GetMainViewport(); - Anm2Frame* frame = anm2_frame_from_reference(self->anm2, self->reference); - - bool isLayerFrame = frame && type == ANM2_LAYER; - - if (!frame || type != ANM2_TRIGGERS) - { - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_CROP.copy({!isLayerFrame}), self, !isLayerFrame ? dummy_value() : frame->crop); - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_SIZE.copy({!isLayerFrame}), self, !isLayerFrame ? dummy_value() : frame->size); - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_POSITION.copy({!frame}), self, !frame ? dummy_value() : frame->position); - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_PIVOT.copy({!isLayerFrame}), self, !isLayerFrame ? dummy_value() : frame->pivot); - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_SCALE.copy({!frame}), self, !frame ? dummy_value() : frame->scale); - _imgui_drag_float(IMGUI_FRAME_PROPERTIES_ROTATION.copy({!frame}), self, !frame ? dummy_value() : frame->rotation); - _imgui_input_int(IMGUI_FRAME_PROPERTIES_DELAY.copy({!frame}), self, !frame ? dummy_value() : frame->delay); - _imgui_color_edit4(IMGUI_FRAME_PROPERTIES_TINT.copy({!frame}), self, !frame ? dummy_value() : frame->tintRGBA); - _imgui_color_edit3(IMGUI_FRAME_PROPERTIES_COLOR_OFFSET.copy({!frame}), self, !frame ? dummy_value() : frame->offsetRGB); - _imgui_checkbox(IMGUI_FRAME_PROPERTIES_VISIBLE.copy({!frame}), self, !frame ? dummy_value() : frame->isVisible); - _imgui_checkbox(IMGUI_FRAME_PROPERTIES_INTERPOLATED.copy({!frame}), self, !frame ? dummy_value() : frame->isInterpolated); - _imgui_checkbox(IMGUI_FRAME_PROPERTIES_ROUND.copy({!frame}), self, self->settings->propertiesIsRound); - if (_imgui_button(IMGUI_FRAME_PROPERTIES_FLIP_X.copy({!frame}), self)) frame->scale.x = -frame->scale.x; - if (_imgui_button(IMGUI_FRAME_PROPERTIES_FLIP_Y.copy({!frame}), self)) frame->scale.y = -frame->scale.y; - - if (self->settings->propertiesIsRound && frame) - { - frame->position = glm::trunc(frame->position); - frame->pivot = glm::trunc(frame->pivot); - frame->crop = glm::trunc(frame->crop); - frame->scale = glm::trunc(frame->scale); - frame->rotation = glm::trunc(frame->rotation); - frame->tintRGBA = glm::trunc(frame->tintRGBA); - frame->offsetRGB = glm::trunc(frame->offsetRGB); - } - } - else - { - std::vector eventIDs; - ImguiItem eventItem = IMGUI_FRAME_PROPERTIES_EVENT.copy({!frame}); - - eventIDs.emplace_back(ID_NONE); - eventItem.items.emplace_back(IMGUI_NONE); - - for (auto & [id, event] : self->anm2->events) - { - eventIDs.emplace_back(id); - eventItem.items.emplace_back(event.name); - } - - s32 eventIndex = std::find(eventIDs.begin(), eventIDs.end(), frame->eventID) - eventIDs.begin(); - - if (_imgui_combo(eventItem, self, &eventIndex)) - frame->eventID = eventIDs[eventIndex]; + ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + IMGUI_TASKBAR.size->y)); + ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, viewport->Size.y - IMGUI_TASKBAR.size->y)); + ImGui::SetNextWindowViewport(viewport->ID); - _imgui_input_int(IMGUI_FRAME_PROPERTIES_AT_FRAME.copy({!frame}), self, frame->atFrame); - } + _imgui_begin(window, self); + _imgui_dockspace(IMGUI_DOCKSPACE_MAIN, self); - _imgui_end(); // IMGUI_FRAME_PROPERTIES + //_imgui_tools(self); + //_imgui_animations(self); + //_imgui_events(self); + _imgui_spritesheets(self); + //_imgui_animation_preview(self); + //_imgui_spritesheet_editor(self); + //_imgui_layers(self); + //_imgui_nulls(self); + //_imgui_timeline(self); + //_imgui_onionskin(self); + //_imgui_frame_properties(self); + + _imgui_end(); // IMGUI_WINDOW_MAIN } -static void _imgui_log(Imgui* self) -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle& style = ImGui::GetStyle(); - ImVec4 borderColor = style.Colors[ImGuiCol_Border]; - ImVec4 textColor = style.Colors[ImGuiCol_Text]; +void imgui_init(Imgui* self, Dialog* dialog, Resources* resources, Anm2* anm2, Anm2Reference* reference, Editor* editor, Preview* preview, + GeneratePreview* generatePreview, Settings* settings, Snapshots* snapshots, Clipboard* clipboard, SDL_Window* window, + SDL_GLContext* glContext) { + self->dialog = dialog; + self->resources = resources; + self->anm2 = anm2; + self->reference = reference; + self->editor = editor; + self->preview = preview; + self->generatePreview = generatePreview; + self->settings = settings; + self->snapshots = snapshots; + self->clipboard = clipboard; + self->window = window; + self->glContext = glContext; - ImVec2 position = {io.DisplaySize.x - IMGUI_LOG_PADDING, io.DisplaySize.y - IMGUI_LOG_PADDING}; - - for (s32 i = (s32)self->log.size() - 1; i >= 0; --i) - { - ImguiLogItem& item = self->log[i]; - f32 lifetime = item.timeRemaining / IMGUI_LOG_DURATION; - borderColor.w = lifetime; - textColor.w = lifetime; + self->saveAnm2 = *anm2; - item.timeRemaining -= io.DeltaTime; + ImGui::CreateContext(); + ImGui::StyleColorsDark(); - if (item.timeRemaining <= 0.0f) - { - self->log.erase(self->log.begin() + i); - continue; - } - - ImGui::SetNextWindowPos(position, ImGuiCond_Always, {1.0f, 1.0f}); - ImGui::PushStyleColor(ImGuiCol_Border, borderColor); - ImGui::PushStyleColor(ImGuiCol_Text, textColor); - ImGui::SetNextWindowBgAlpha(lifetime); + ImGui_ImplSDL3_InitForOpenGL(self->window, *self->glContext); + ImGui_ImplOpenGL3_Init(IMGUI_OPENGL_VERSION); - _imgui_begin(IMGUI_LOG_WINDOW.copy({.label = std::format(IMGUI_LOG_FORMAT, i)}), self); - ImGui::TextUnformatted(item.text.c_str()); - ImVec2 windowSize = ImGui::GetWindowSize(); - _imgui_end(); // IMGUI_LOG_WINDOW + ImGuiIO& io = ImGui::GetIO(); + io.IniFilename = nullptr; + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + io.ConfigWindowsMoveFromTitleBarOnly = true; - ImGui::PopStyleColor(2); + ImGui::GetStyle().FontScaleMain = self->settings->displayScale; + io.Fonts->AddFontFromFileTTF(FONT_PATH, FONT_SIZE); - position.y -= windowSize.y + IMGUI_LOG_PADDING; - } + self->style = ImGui::GetStyle(); + + imgui_keyboard_nav_enable(); + + ImGui::LoadIniSettingsFromDisk(settings_path_get().c_str()); + + for (int i = 0; i < HOTKEY_COUNT; i++) { + if (!SETTINGS_HOTKEY_MEMBERS[i]) + continue; + imgui_hotkey_chord_registry()[i] = imgui_chord_from_string_get(*&(self->settings->*SETTINGS_HOTKEY_MEMBERS[i])); + } } -static void _imgui_dock(Imgui* self) -{ - ImguiItem window = IMGUI_WINDOW_MAIN; - ImGuiViewport* viewport = ImGui::GetMainViewport(); +void imgui_update(Imgui* self) { + ImGui_ImplSDL3_NewFrame(); + ImGui_ImplOpenGL3_NewFrame(); + ImGui::NewFrame(); - ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + IMGUI_TASKBAR.size.y)); - ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, viewport->Size.y - IMGUI_TASKBAR.size.y)); - ImGui::SetNextWindowViewport(viewport->ID); - - _imgui_begin(window, self); - _imgui_dockspace(IMGUI_DOCKSPACE_MAIN, self); + _imgui_taskbar(self); + _imgui_dock(self); + _imgui_log(self); - _imgui_tools(self); - _imgui_animations(self); - _imgui_events(self); - _imgui_spritesheets(self); - _imgui_animation_preview(self); - _imgui_spritesheet_editor(self); - _imgui_layers(self); - _imgui_nulls(self); - _imgui_timeline(self); - _imgui_onionskin(self); - _imgui_frame_properties(self); + if (self->isContextualActionsEnabled) { + for (const auto& item : imgui_item_registry()) { + if (item->is_chord() && _imgui_chord_pressed(item->chord_get()) && !item->focusWindow.has_value()) { + if (item->snapshotAction.has_value()) + imgui_snapshot(self, *item->snapshotAction); + if (item->function) + item->function(self); + } + } + } - _imgui_end(); // IMGUI_WINDOW_MAIN + imgui_contextual_actions_enable(self); + + if (self->pendingCursor != self->cursor) { + SDL_SetCursor(SDL_CreateSystemCursor(self->pendingCursor)); + self->cursor = self->pendingCursor; + } + + self->pendingCursor = CURSOR_DEFAULT; + + SDL_Event event; + + while (SDL_PollEvent(&event)) { + ImGui_ImplSDL3_ProcessEvent(&event); + + switch (event.type) { + case SDL_EVENT_DROP_FILE: { + const char* droppedFile = event.drop.data; + + if (path_is_extension(droppedFile, ANM2_EXTENSION)) + _imgui_anm2_open(self, droppedFile); + else if (path_is_extension(droppedFile, ANM2_SPRITESHEET_EXTENSION)) { + if (self->anm2->path.empty()) { + _imgui_no_anm2_path_check(self); + break; + } + _imgui_spritesheet_add(self, droppedFile); + } else + imgui_log_push(self, IMGUI_LOG_DRAG_DROP_ERROR); + + break; + } + case SDL_EVENT_QUIT: + if (self->isTryQuit) + self->isQuit = true; + else + imgui_quit(self); + break; + default: + break; + } + } + + _imgui_confirm_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION, self, nullptr, true); } -void imgui_init -( - Imgui* self, - Dialog* dialog, - Resources* resources, - Anm2* anm2, - Anm2Reference* reference, - Editor* editor, - Preview* preview, - GeneratePreview* generatePreview, - Settings* settings, - Snapshots* snapshots, - Clipboard* clipboard, - SDL_Window* window, - SDL_GLContext* glContext -) -{ - IMGUI_CHECKVERSION(); - - self->dialog = dialog; - self->resources = resources; - self->anm2 = anm2; - self->reference = reference; - self->editor = editor; - self->preview = preview; - self->generatePreview = generatePreview; - self->settings = settings; - self->snapshots = snapshots; - self->clipboard = clipboard; - self->window = window; - self->glContext = glContext; - - self->saveAnm2 = *anm2; - - ImGui::CreateContext(); - ImGui::StyleColorsDark(); - - ImGui_ImplSDL3_InitForOpenGL(self->window, *self->glContext); - ImGui_ImplOpenGL3_Init(IMGUI_OPENGL_VERSION); - - ImGuiIO& io = ImGui::GetIO(); - io.IniFilename = nullptr; - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; - io.ConfigWindowsMoveFromTitleBarOnly = true; - - imgui_keyboard_nav_enable(); - - ImGui::LoadIniSettingsFromDisk(settings_path_get().c_str()); - - for (s32 i = 0; i < HOTKEY_COUNT; i++) - { - if (!SETTINGS_HOTKEY_MEMBERS[i]) continue; - imgui_hotkey_chord_registry()[i] = imgui_chord_from_string_get(*&(self->settings->*SETTINGS_HOTKEY_MEMBERS[i])); - } - +void imgui_draw(void) { + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); } -void imgui_update(Imgui* self) -{ - ImGui_ImplSDL3_NewFrame(); - ImGui_ImplOpenGL3_NewFrame(); - ImGui::NewFrame(); +void imgui_free(void) { + if (!ImGui::GetCurrentContext()) + return; - _imgui_taskbar(self); - _imgui_dock(self); - _imgui_log(self); - - if (self->isContextualActionsEnabled) - { - for (const auto& item : imgui_item_registry()) - { - if (item->is_chord() && _imgui_chord_pressed(item->chord_get()) && !item->is_focus_window()) - { - if (item->is_undoable()) imgui_snapshot(self, item->snapshotAction); - if (item->is_function()) item->function(self); - } - } - } - - imgui_contextual_actions_enable(self); - - if (self->pendingCursor != self->cursor) - { - SDL_SetCursor(SDL_CreateSystemCursor(self->pendingCursor)); - self->cursor = self->pendingCursor; - } - - self->pendingCursor = CURSOR_DEFAULT; - - SDL_Event event; - - while(SDL_PollEvent(&event)) - { - ImGui_ImplSDL3_ProcessEvent(&event); - - switch (event.type) - { - case SDL_EVENT_DROP_FILE: - { - const char* droppedFile = event.drop.data; - - if (path_is_extension(droppedFile, ANM2_EXTENSION)) _imgui_anm2_open(self, droppedFile); - else if (path_is_extension(droppedFile, ANM2_SPRITESHEET_EXTENSION)) _imgui_spritesheet_add(self, droppedFile); - else imgui_log_push(self, IMGUI_LOG_DRAG_DROP_ERROR); - - break; - } - case SDL_EVENT_QUIT: - if (self->isTryQuit) self->isQuit = true; - else imgui_quit(self); - break; - default: - break; - } - } -} - -void imgui_draw(void) -{ - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); -} - -void imgui_free(void) -{ - if (!ImGui::GetCurrentContext()) return; - - ImGui_ImplSDL3_Shutdown(); - ImGui_ImplOpenGL3_Shutdown(); - ImGui::SaveIniSettingsToDisk(settings_path_get().c_str()); - ImGui::DestroyContext(); + ImGui_ImplSDL3_Shutdown(); + ImGui_ImplOpenGL3_Shutdown(); + ImGui::SaveIniSettingsToDisk(settings_path_get().c_str()); + ImGui::DestroyContext(); } \ No newline at end of file diff --git a/src/imgui.h b/src/imgui.h index 1ccc1f5..bf561a5 100644 --- a/src/imgui.h +++ b/src/imgui.h @@ -1,61 +1,93 @@ #pragma once +#include "canvas.h" #include "clipboard.h" #include "dialog.h" #include "editor.h" #include "ffmpeg.h" -#include "preview.h" #include "generate_preview.h" +#include "preview.h" #include "resources.h" #include "settings.h" #include "snapshots.h" #include "tool.h" #include "window.h" +#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS +#define IMGUI_DEBUG_PARANOID #define IMGUI_IMPL_OPENGL_LOADER_CUSTOM #define IMGUI_ENABLE_DOCKING -#define IM_VEC2_CLASS_EXTRA \ - inline bool operator==(const ImVec2& rhs) const { return x == rhs.x && y == rhs.y; } \ - inline bool operator!=(const ImVec2& rhs) const { return !(*this == rhs); } \ - inline ImVec2 operator+(const ImVec2& rhs) const { return ImVec2(x + rhs.x, y + rhs.y); } \ - inline ImVec2 operator-(const ImVec2& rhs) const { return ImVec2(x - rhs.x, y - rhs.y); } \ - inline ImVec2 operator*(const ImVec2& rhs) const { return ImVec2(x * rhs.x, y * rhs.y); } \ - inline ImVec2 operator*(float s) const { return ImVec2(x * s, y * s); } \ - friend inline ImVec2 operator*(float s, const ImVec2& v) { return ImVec2(v.x * s, v.y * s); } \ - inline ImVec2& operator+=(const ImVec2& rhs) { x += rhs.x; y += rhs.y; return *this; } \ - inline ImVec2& operator-=(const ImVec2& rhs) { x -= rhs.x; y -= rhs.y; return *this; } \ - inline ImVec2& operator*=(float s) { x *= s; y *= s; return *this; } \ - inline ImVec2(const vec2& v) : x(v.x), y(v.y) {} \ - inline operator vec2() const { return vec2(x, y); } +#define IM_VEC2_CLASS_EXTRA \ + inline bool operator==(const ImVec2& rhs) const { return x == rhs.x && y == rhs.y; } \ + inline bool operator!=(const ImVec2& rhs) const { return !(*this == rhs); } \ + inline ImVec2 operator+(const ImVec2& rhs) const { return ImVec2(x + rhs.x, y + rhs.y); } \ + inline ImVec2 operator-(const ImVec2& rhs) const { return ImVec2(x - rhs.x, y - rhs.y); } \ + inline ImVec2 operator*(const ImVec2& rhs) const { return ImVec2(x * rhs.x, y * rhs.y); } \ + inline ImVec2 operator*(float s) const { return ImVec2(x * s, y * s); } \ + friend inline ImVec2 operator*(float s, const ImVec2& v) { return ImVec2(v.x * s, v.y * s); } \ + inline ImVec2& operator+=(const ImVec2& rhs) { \ + x += rhs.x; \ + y += rhs.y; \ + return *this; \ + } \ + inline ImVec2& operator-=(const ImVec2& rhs) { \ + x -= rhs.x; \ + y -= rhs.y; \ + return *this; \ + } \ + inline ImVec2& operator*=(float s) { \ + x *= s; \ + y *= s; \ + return *this; \ + } \ + inline ImVec2(const vec2& v) : x(v.x), y(v.y) {} \ + inline operator vec2() const { return vec2(x, y); } -#define IM_VEC4_CLASS_EXTRA \ - inline bool operator==(const ImVec4& rhs) const { return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; } \ - inline bool operator!=(const ImVec4& rhs) const { return !(*this == rhs); } \ - inline ImVec4 operator+(const ImVec4& rhs) const { return ImVec4(x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w); } \ - inline ImVec4 operator-(const ImVec4& rhs) const { return ImVec4(x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w); } \ - inline ImVec4 operator*(const ImVec4& rhs) const { return ImVec4(x * rhs.x, y * rhs.y, z * rhs.z, w * rhs.w); } \ - inline ImVec4 operator*(float s) const { return ImVec4(x * s, y * s, z * s, w * s); } \ - friend inline ImVec4 operator*(float s, const ImVec4& v) { return ImVec4(v.x * s, v.y * s, v.z * s, v.w * s); } \ - inline ImVec4& operator+=(const ImVec4& rhs) { x += rhs.x; y += rhs.y; z += rhs.z; w += rhs.w; return *this; } \ - inline ImVec4& operator-=(const ImVec4& rhs) { x -= rhs.x; y -= rhs.y; z -= rhs.z; w -= rhs.w; return *this; } \ - inline ImVec4& operator*=(float s) { x *= s; y *= s; z *= s; w *= s; return *this; } \ - inline ImVec4(const vec4& v) : x(v.x), y(v.y), z(v.z), w(v.w) {} \ - inline operator vec4() const { return vec4(x, y, z, w); } - +#define IM_VEC4_CLASS_EXTRA \ + inline bool operator==(const ImVec4& rhs) const { return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; } \ + inline bool operator!=(const ImVec4& rhs) const { return !(*this == rhs); } \ + inline ImVec4 operator+(const ImVec4& rhs) const { return ImVec4(x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w); } \ + inline ImVec4 operator-(const ImVec4& rhs) const { return ImVec4(x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w); } \ + inline ImVec4 operator*(const ImVec4& rhs) const { return ImVec4(x * rhs.x, y * rhs.y, z * rhs.z, w * rhs.w); } \ + inline ImVec4 operator*(float s) const { return ImVec4(x * s, y * s, z * s, w * s); } \ + friend inline ImVec4 operator*(float s, const ImVec4& v) { return ImVec4(v.x * s, v.y * s, v.z * s, v.w * s); } \ + inline ImVec4& operator+=(const ImVec4& rhs) { \ + x += rhs.x; \ + y += rhs.y; \ + z += rhs.z; \ + w += rhs.w; \ + return *this; \ + } \ + inline ImVec4& operator-=(const ImVec4& rhs) { \ + x -= rhs.x; \ + y -= rhs.y; \ + z -= rhs.z; \ + w -= rhs.w; \ + return *this; \ + } \ + inline ImVec4& operator*=(float s) { \ + x *= s; \ + y *= s; \ + z *= s; \ + w *= s; \ + return *this; \ + } \ + inline ImVec4(const vec4& v) : x(v.x), y(v.y), z(v.z), w(v.w) {} \ + inline operator vec4() const { return vec4(x, y, z, w); } + +#include +#include #include #include -#include -#include #define IMGUI_CHORD_NONE (ImGuiMod_None) -#define IMGUI_EVENTS_FOOTER_HEIGHT 40 #define IMGUI_FRAME_BORDER 2.0f #define IMGUI_LOG_DURATION 3.0f #define IMGUI_LOG_PADDING 10.0f +#define IMGUI_TEXT_HEIGHT_PADDING 4.0f #define IMGUI_PLAYHEAD_LINE_COLOR IM_COL32(UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX) #define IMGUI_TRIGGERS_EVENT_COLOR IM_COL32(UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, 128) #define IMGUI_PLAYHEAD_LINE_WIDTH 2.0f -#define IMGUI_SPRITESHEETS_FOOTER_HEIGHT 65 #define IMGUI_TIMELINE_FRAME_MULTIPLE 5 #define IMGUI_TIMELINE_MERGE #define IMGUI_TOOL_COLOR_PICKER_DURATION 0.25f @@ -77,6 +109,7 @@ #define IMGUI_ACTION_CROP "Crop" #define IMGUI_ACTION_ADD_SPRITESHEET "Add Spritesheet" #define IMGUI_ACTION_REPLACE_SPRITESHEET "Replace Spritesheet" +#define IMGUI_ACTION_SPRITESHEET_SWAP "Spritesheet Swap" #define IMGUI_ACTION_OPEN_FILE "Open File" #define IMGUI_SET_ITEM_PROPERTIES_POPUP "Item Properties" @@ -84,22 +117,27 @@ #define IMGUI_POPUP_MODAL_FLAGS ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize #define IMGUI_LOG_NO_ANM2_PATH "Please save the .anm2 to a path first!" -#define IMGUI_LOG_FILE_OPEN_FORMAT "Opened anm2: {}" -#define IMGUI_LOG_FILE_SAVE_FORMAT "Saved anm2 to: {}" +#define IMGUI_LOG_FILE_OPEN_FORMAT "Opened anm2: {}" +#define IMGUI_LOG_FILE_SAVE_FORMAT "Saved anm2 to: {}" #define IMGUI_LOG_SPRITESHEET_RELOAD "Reloaded selected spritesheets" -#define IMGUI_LOG_RENDER_ANIMATION_FRAMES_SAVE_FORMAT "Saved rendered frames to: {}" -#define IMGUI_LOG_RENDER_ANIMATION_SAVE_FORMAT "Saved rendered animation to: {}" +#define IMGUI_LOG_RENDER_ANIMATION_FRAMES_SAVE_FORMAT "Saved rendered frames to: {}" +#define IMGUI_LOG_RENDER_ANIMATION_SAVE_FORMAT "Saved rendered animation to: {}" #define IMGUI_LOG_RENDER_ANIMATION_NO_ANIMATION_ERROR "No animation selected; rendering cancelled." #define IMGUI_LOG_RENDER_ANIMATION_NO_FRAMES_ERROR "No frames to render; rendering cancelled." #define IMGUI_LOG_RENDER_ANIMATION_DIRECTORY_ERROR "Invalid directory! Make sure it exists and you have write permissions." #define IMGUI_LOG_RENDER_ANIMATION_PATH_ERROR "Invalid path! Make sure it's valid and you have write permissions." -#define IMGUI_LOG_RENDER_ANIMATION_FFMPEG_PATH_ERROR "Invalid FFmpeg path! Make sure you have it installed and the path is correct." -#define IMGUI_LOG_RENDER_ANIMATION_FFMPEG_ERROR "FFmpeg could not render animation! Check paths or your FFmpeg installation." -#define IMGUI_LOG_SPRITESHEET_SAVE_FORMAT "Saved spritesheet #{} to: {}" +#define IMGUI_LOG_RENDER_ANIMATION_FFMPEG_PATH_ERROR \ + "Invalid FFmpeg path! Make sure you have it installed and the path is " \ + "correct." +#define IMGUI_LOG_RENDER_ANIMATION_FFMPEG_ERROR \ + "FFmpeg could not render animation! Check paths or your FFmpeg " \ + "installation." +#define IMGUI_LOG_SPRITESHEET_SAVE_FORMAT "Saved spritesheet #{} to: {}" #define IMGUI_LOG_DRAG_DROP_ERROR "Invalid file for dragging/dropping!" #define IMGUI_LOG_ANIMATION_PASTE_ERROR "Failed to parse clipboard text as an animation." #define IMGUI_LOG_FRAME_PASTE_ERROR "Failed to parse clipboard text as a frame." #define IMGUI_LOG_RELOAD_SPRITESHEET "Reloaded spritesheet(s)." +#define IMGUI_LOG_ADD_SPRITESHEET_ERROR "Failed to add spritesheet: {}. Make sure it's a valid PNG file." #define IMGUI_NONE "None" #define IMGUI_ANIMATION_DEFAULT_FORMAT "(*) {}" @@ -141,7 +179,6 @@ const ImVec4 IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_INACTIVE_COLOR = {0.113, 0.184 const ImVec4 IMGUI_ACTIVE_COLOR = {1.0, 1.0, 1.0, 1.0}; const ImVec4 IMGUI_INACTIVE_COLOR = {1.0, 1.0, 1.0, 0.25}; -const ImVec2 IMGUI_SPRITESHEET_PREVIEW_SIZE = {50.0, 50.0}; const ImVec2 IMGUI_TOOLTIP_OFFSET = {16, 8}; const vec2 IMGUI_SPRITESHEET_EDITOR_CROP_FORGIVENESS = {1, 1}; @@ -152,6 +189,7 @@ const ImGuiKey IMGUI_INPUT_UP = ImGuiKey_UpArrow; const ImGuiKey IMGUI_INPUT_DOWN = ImGuiKey_DownArrow; const ImGuiKey IMGUI_INPUT_SHIFT = ImGuiMod_Shift; const ImGuiKey IMGUI_INPUT_CTRL = ImGuiMod_Ctrl; +const ImGuiKey IMGUI_INPUT_ALT = ImGuiMod_Alt; const ImGuiKey IMGUI_INPUT_ZOOM_IN = ImGuiKey_1; const ImGuiKey IMGUI_INPUT_ZOOM_OUT = ImGuiKey_2; const ImGuiKey IMGUI_INPUT_ENTER = ImGuiKey_Enter; @@ -159,2427 +197,1432 @@ const ImGuiKey IMGUI_INPUT_RENAME = ImGuiKey_F2; const ImGuiKey IMGUI_INPUT_DEFAULT = ImGuiKey_Home; const ImGuiMouseButton IMGUI_MOUSE_DEFAULT = ImGuiMouseButton_Middle; -enum ImguiPopupType -{ - IMGUI_POPUP_NONE, - IMGUI_POPUP_BY_ITEM, - IMGUI_POPUP_CENTER_WINDOW +enum ImguiPopupType { IMGUI_POPUP_NONE, IMGUI_POPUP_BY_ITEM, IMGUI_POPUP_CENTER_WINDOW }; +enum ImguiPopupState { IMGUI_POPUP_STATE_CLOSED, IMGUI_POPUP_STATE_OPEN, IMGUI_POPUP_STATE_CONFIRM, IMGUI_POPUP_STATE_CANCEL }; + +struct ImguiColorSet { + std::optional normal = {}; + std::optional active = {}; + std::optional hovered = {}; + std::optional border = {}; }; -enum ImguiPopupState -{ - IMGUI_POPUP_STATE_CLOSED, - IMGUI_POPUP_STATE_OPEN, - IMGUI_POPUP_STATE_CONFIRM, - IMGUI_POPUP_STATE_CANCEL +struct ImguiLogItem { + std::string text; + float timeRemaining; }; -struct ImguiColorSet -{ - ImVec4 normal{}; - ImVec4 active{}; - ImVec4 hovered{}; - ImVec4 border{}; - - bool is_normal() const { return normal != ImVec4(); } - bool is_active() const { return active != ImVec4(); } - bool is_hovered() const { return hovered != ImVec4(); } - bool is_border() const { return border != ImVec4(); } +struct Imgui { + Dialog* dialog = nullptr; + Resources* resources = nullptr; + Anm2* anm2 = nullptr; + Anm2Reference* reference = nullptr; + Editor* editor = nullptr; + Preview* preview = nullptr; + GeneratePreview* generatePreview = nullptr; + Settings* settings = nullptr; + Snapshots* snapshots = nullptr; + Clipboard* clipboard = nullptr; + SDL_Window* window = nullptr; + SDL_GLContext* glContext = nullptr; + std::string pendingPopup{}; + ImguiPopupType pendingPopupType = IMGUI_POPUP_NONE; + ImVec2 pendingPopupPosition{}; + std::vector log; + ImGuiStyle style; + Anm2 saveAnm2; + SDL_SystemCursor cursor; + SDL_SystemCursor pendingCursor; + bool isCursorSet = false; + bool isContextualActionsEnabled = true; + bool isQuit = false; + bool isTryQuit = false; }; -struct ImguiLogItem -{ - std::string text; - f32 timeRemaining; -}; - -struct Imgui -{ - Dialog* dialog = nullptr; - Resources* resources = nullptr; - Anm2* anm2 = nullptr; - Anm2Reference* reference = nullptr; - Editor* editor = nullptr; - Preview* preview = nullptr; - GeneratePreview* generatePreview = nullptr; - Settings* settings = nullptr; - Snapshots* snapshots = nullptr; - Clipboard* clipboard = nullptr; - SDL_Window* window = nullptr; - SDL_GLContext* glContext = nullptr; - std::string pendingPopup{}; - ImguiPopupType pendingPopupType = IMGUI_POPUP_NONE; - ImVec2 pendingPopupPosition{}; - std::vector log; - Anm2 saveAnm2; - SDL_SystemCursor cursor; - SDL_SystemCursor pendingCursor; - bool isCursorSet = false; - bool isContextualActionsEnabled = true; - bool isQuit = false; - bool isTryQuit = false; -}; - -static inline void imgui_snapshot(Imgui* self, const std::string& action = SNAPSHOT_ACTION) -{ - self->snapshots->action = action; - Snapshot snapshot = snapshot_get(self->snapshots); - snapshots_undo_push(self->snapshots, &snapshot); +static inline void imgui_snapshot(Imgui* self, const std::string& action = SNAPSHOT_ACTION) { + self->snapshots->action = action; + Snapshot snapshot = snapshot_get(self->snapshots); + snapshots_undo_push(self->snapshots, &snapshot); } -static void imgui_log_push(Imgui* self, const std::string& text) -{ - self->log.push_back({text, IMGUI_LOG_DURATION}); - log_imgui(text); +static void imgui_log_push(Imgui* self, const std::string& text) { + self->log.push_back({text, IMGUI_LOG_DURATION}); + log_imgui(text); } -static inline void imgui_anm2_new(Imgui* self) -{ - anm2_reference_clear(self->reference); - anm2_free(self->anm2); - anm2_new(self->anm2); +static inline void imgui_anm2_new(Imgui* self) { + *self->reference = Anm2Reference(); + anm2_free(self->anm2); + anm2_new(self->anm2); } -static inline void imgui_file_open(Imgui* self) -{ - dialog_anm2_open(self->dialog); +static inline void imgui_file_open(Imgui* self) { dialog_anm2_open(self->dialog); } + +static inline void imgui_file_save(Imgui* self) { + if (self->anm2->path.empty()) + dialog_anm2_save(self->dialog); + else { + anm2_serialize(self->anm2, self->anm2->path); + imgui_log_push(self, std::format(IMGUI_LOG_FILE_SAVE_FORMAT, self->anm2->path)); + } + + self->saveAnm2 = *self->anm2; } -static inline void imgui_file_save(Imgui* self) -{ - if (self->anm2->path.empty()) - dialog_anm2_save(self->dialog); - else - { - anm2_serialize(self->anm2, self->anm2->path); - imgui_log_push(self, std::format(IMGUI_LOG_FILE_SAVE_FORMAT, self->anm2->path)); +static inline void imgui_file_new(Imgui* self) { + std::string path = self->anm2->path; + imgui_anm2_new(self); + self->anm2->path = path; + imgui_file_save(self); +} + +static inline void imgui_file_save_as(Imgui* self) { dialog_anm2_save(self->dialog); } + +static inline void imgui_quit(Imgui* self) { + if (self->saveAnm2 != *self->anm2) + self->isTryQuit = true; + else + self->isQuit = true; +} + +static inline void imgui_explore(Imgui* self) { + std::filesystem::path filePath = self->anm2->path; + std::filesystem::path parentPath = filePath.parent_path(); + dialog_explorer_open(parentPath.string()); +} + +static inline void imgui_tool_pan_set(Imgui* self) { self->settings->tool = TOOL_PAN; } +static inline void imgui_tool_move_set(Imgui* self) { self->settings->tool = TOOL_MOVE; } +static inline void imgui_tool_rotate_set(Imgui* self) { self->settings->tool = TOOL_ROTATE; } +static inline void imgui_tool_scale_set(Imgui* self) { self->settings->tool = TOOL_SCALE; } +static inline void imgui_tool_crop_set(Imgui* self) { self->settings->tool = TOOL_CROP; } +static inline void imgui_tool_draw_set(Imgui* self) { self->settings->tool = TOOL_DRAW; } +static inline void imgui_tool_erase_set(Imgui* self) { self->settings->tool = TOOL_ERASE; } +static inline void imgui_tool_color_picker_set(Imgui* self) { self->settings->tool = TOOL_COLOR_PICKER; } + +static inline void imgui_undo(Imgui* self) { + if (self->snapshots->undoStack.top == 0) + return; + + snapshots_undo(self->snapshots); + imgui_log_push(self, std::format(IMGUI_LOG_UNDO_FORMAT, self->snapshots->action)); +} + +static inline void imgui_redo(Imgui* self) { + if (self->snapshots->redoStack.top == 0) + return; + + std::string action = self->snapshots->action; + snapshots_redo(self->snapshots); + imgui_log_push(self, std::format(IMGUI_LOG_REDO_FORMAT, action)); +} + +static inline void imgui_cut(Imgui* self) { clipboard_cut(self->clipboard); } + +static inline void imgui_copy(Imgui* self) { clipboard_copy(self->clipboard); } + +static inline void imgui_paste(Imgui* self) { + if (!clipboard_paste(self->clipboard)) { + switch (self->clipboard->type) { + case CLIPBOARD_FRAME: + imgui_log_push(self, IMGUI_LOG_FRAME_PASTE_ERROR); + break; + case CLIPBOARD_ANIMATION: + imgui_log_push(self, IMGUI_LOG_ANIMATION_PASTE_ERROR); + break; + default: + break; } - - self->saveAnm2 = *self->anm2; + } } -static inline void imgui_file_new(Imgui* self) -{ - std::string path = self->anm2->path; - imgui_anm2_new(self); - self->anm2->path = path; - imgui_file_save(self); +static inline void imgui_onionskin_toggle(Imgui* self) { self->settings->onionskinIsEnabled = !self->settings->onionskinIsEnabled; } + +static std::unordered_map IMGUI_KEY_MAP = {{"A", ImGuiKey_A}, + {"B", ImGuiKey_B}, + {"C", ImGuiKey_C}, + {"D", ImGuiKey_D}, + {"E", ImGuiKey_E}, + {"F", ImGuiKey_F}, + {"G", ImGuiKey_G}, + {"H", ImGuiKey_H}, + {"I", ImGuiKey_I}, + {"J", ImGuiKey_J}, + {"K", ImGuiKey_K}, + {"L", ImGuiKey_L}, + {"M", ImGuiKey_M}, + {"N", ImGuiKey_N}, + {"O", ImGuiKey_O}, + {"P", ImGuiKey_P}, + {"Q", ImGuiKey_Q}, + {"R", ImGuiKey_R}, + {"S", ImGuiKey_S}, + {"T", ImGuiKey_T}, + {"U", ImGuiKey_U}, + {"V", ImGuiKey_V}, + {"W", ImGuiKey_W}, + {"X", ImGuiKey_X}, + {"Y", ImGuiKey_Y}, + {"Z", ImGuiKey_Z}, + + {"0", ImGuiKey_0}, + {"1", ImGuiKey_1}, + {"2", ImGuiKey_2}, + {"3", ImGuiKey_3}, + {"4", ImGuiKey_4}, + {"5", ImGuiKey_5}, + {"6", ImGuiKey_6}, + {"7", ImGuiKey_7}, + {"8", ImGuiKey_8}, + {"9", ImGuiKey_9}, + + {"Num0", ImGuiKey_Keypad0}, + {"Num1", ImGuiKey_Keypad1}, + {"Num2", ImGuiKey_Keypad2}, + {"Num3", ImGuiKey_Keypad3}, + {"Num4", ImGuiKey_Keypad4}, + {"Num5", ImGuiKey_Keypad5}, + {"Num6", ImGuiKey_Keypad6}, + {"Num7", ImGuiKey_Keypad7}, + {"Num8", ImGuiKey_Keypad8}, + {"Num9", ImGuiKey_Keypad9}, + {"NumAdd", ImGuiKey_KeypadAdd}, + {"NumSubtract", ImGuiKey_KeypadSubtract}, + {"NumMultiply", ImGuiKey_KeypadMultiply}, + {"NumDivide", ImGuiKey_KeypadDivide}, + {"NumEnter", ImGuiKey_KeypadEnter}, + {"NumDecimal", ImGuiKey_KeypadDecimal}, + + {"F1", ImGuiKey_F1}, + {"F2", ImGuiKey_F2}, + {"F3", ImGuiKey_F3}, + {"F4", ImGuiKey_F4}, + {"F5", ImGuiKey_F5}, + {"F6", ImGuiKey_F6}, + {"F7", ImGuiKey_F7}, + {"F8", ImGuiKey_F8}, + {"F9", ImGuiKey_F9}, + {"F10", ImGuiKey_F10}, + {"F11", ImGuiKey_F11}, + {"F12", ImGuiKey_F12}, + + {"Up", ImGuiKey_UpArrow}, + {"Down", ImGuiKey_DownArrow}, + {"Left", ImGuiKey_LeftArrow}, + {"Right", ImGuiKey_RightArrow}, + + {"Space", ImGuiKey_Space}, + {"Enter", ImGuiKey_Enter}, + {"Escape", ImGuiKey_Escape}, + {"Tab", ImGuiKey_Tab}, + {"Backspace", ImGuiKey_Backspace}, + {"Delete", ImGuiKey_Delete}, + {"Insert", ImGuiKey_Insert}, + {"Home", ImGuiKey_Home}, + {"End", ImGuiKey_End}, + {"PageUp", ImGuiKey_PageUp}, + {"PageDown", ImGuiKey_PageDown}, + + {"Minus", ImGuiKey_Minus}, + {"Equal", ImGuiKey_Equal}, + {"LeftBracket", ImGuiKey_LeftBracket}, + {"RightBracket", ImGuiKey_RightBracket}, + {"Semicolon", ImGuiKey_Semicolon}, + {"Apostrophe", ImGuiKey_Apostrophe}, + {"Comma", ImGuiKey_Comma}, + {"Period", ImGuiKey_Period}, + {"Slash", ImGuiKey_Slash}, + {"Backslash", ImGuiKey_Backslash}, + {"GraveAccent", ImGuiKey_GraveAccent}, + + {"MouseLeft", ImGuiKey_MouseLeft}, + {"MouseRight", ImGuiKey_MouseRight}, + {"MouseMiddle", ImGuiKey_MouseMiddle}, + {"MouseX1", ImGuiKey_MouseX1}, + {"MouseX2", ImGuiKey_MouseX2}}; + +static std::unordered_map IMGUI_MOD_MAP = { + {"Ctrl", ImGuiMod_Ctrl}, + {"Shift", ImGuiMod_Shift}, + {"Alt", ImGuiMod_Alt}, + {"Super", ImGuiMod_Super}, +}; + +static inline ImGuiKey imgui_key_from_char_get(char c) { + if (c >= 'a' && c <= 'z') + c -= 'a' - 'A'; + if (c >= 'A' && c <= 'Z') + return (ImGuiKey)(ImGuiKey_A + (c - 'A')); + return ImGuiKey_None; } -static inline void imgui_file_save_as(Imgui* self) -{ - dialog_anm2_save(self->dialog); -} +static inline std::string imgui_string_from_chord_get(ImGuiKeyChord chord) { + std::string result; -static inline void imgui_quit(Imgui* self) -{ - if (self->saveAnm2 != *self->anm2) - self->isTryQuit = true; + if (chord & ImGuiMod_Ctrl) + result += "Ctrl+"; + if (chord & ImGuiMod_Shift) + result += "Shift+"; + if (chord & ImGuiMod_Alt) + result += "Alt+"; + if (chord & ImGuiMod_Super) + result += "Super+"; + + ImGuiKey key = (ImGuiKey)(chord & ~ImGuiMod_Mask_); + + if (key != ImGuiKey_None) { + const char* name = ImGui::GetKeyName(key); + if (name && *name) + result += name; else - self->isQuit = true; + result += "Unknown"; + } + + if (!result.empty() && result.back() == '+') + result.pop_back(); + + return result; } -static inline void imgui_explore(Imgui* self) -{ - std::filesystem::path filePath = self->anm2->path; - std::filesystem::path parentPath = filePath.parent_path(); - dialog_explorer_open(parentPath.string()); -} +static inline ImGuiKeyChord imgui_chord_from_string_get(const std::string& str) { + ImGuiKeyChord chord = 0; + ImGuiKey baseKey = ImGuiKey_None; -static inline void imgui_tool_pan_set(Imgui* self) -{ - self->settings->tool = TOOL_PAN; -} + std::stringstream ss(str); + std::string token; + while (std::getline(ss, token, '+')) { + // trim + token.erase(0, token.find_first_not_of(" \t\r\n")); + token.erase(token.find_last_not_of(" \t\r\n") + 1); -static inline void imgui_tool_move_set(Imgui* self) -{ - self->settings->tool = TOOL_MOVE; -} + if (token.empty()) + continue; -static inline void imgui_tool_rotate_set(Imgui* self) -{ - self->settings->tool = TOOL_ROTATE; -} - -static inline void imgui_tool_scale_set(Imgui* self) -{ - self->settings->tool = TOOL_SCALE; -} - -static inline void imgui_tool_crop_set(Imgui* self) -{ - self->settings->tool = TOOL_CROP; -} - -static inline void imgui_tool_draw_set(Imgui* self) -{ - self->settings->tool = TOOL_DRAW; -} - -static inline void imgui_tool_erase_set(Imgui* self) -{ - self->settings->tool = TOOL_ERASE; -} - -static inline void imgui_tool_color_picker_set(Imgui* self) -{ - self->settings->tool = TOOL_COLOR_PICKER; -} - -static inline void imgui_undo(Imgui* self) -{ - if (self->snapshots->undoStack.top == 0) return; - - snapshots_undo(self->snapshots); - imgui_log_push(self, std::format(IMGUI_LOG_UNDO_FORMAT, self->snapshots->action)); -} - -static inline void imgui_redo(Imgui* self) -{ - if (self->snapshots->redoStack.top == 0) return; - - std::string action = self->snapshots->action; - snapshots_redo(self->snapshots); - imgui_log_push(self, std::format(IMGUI_LOG_REDO_FORMAT, action)); -} - -static inline void imgui_cut(Imgui* self) -{ - clipboard_cut(self->clipboard); -} - -static inline void imgui_copy(Imgui* self) -{ - clipboard_copy(self->clipboard); -} - -static inline void imgui_paste(Imgui* self) -{ - if (!clipboard_paste(self->clipboard)) - { - switch (self->clipboard->type) - { - case CLIPBOARD_FRAME: imgui_log_push(self, IMGUI_LOG_FRAME_PASTE_ERROR); break; - case CLIPBOARD_ANIMATION: imgui_log_push(self, IMGUI_LOG_ANIMATION_PASTE_ERROR); break; - default: break; - } + if (auto it = IMGUI_MOD_MAP.find(token); it != IMGUI_MOD_MAP.end()) { + chord |= it->second; + } else if (baseKey == ImGuiKey_None) { + if (auto it2 = IMGUI_KEY_MAP.find(token); it2 != IMGUI_KEY_MAP.end()) + baseKey = it2->second; } -} + } -static inline void imgui_onionskin_toggle(Imgui* self) -{ - self->settings->onionskinIsEnabled = !self->settings->onionskinIsEnabled; -} + if (baseKey != ImGuiKey_None) + chord |= baseKey; -static const std::unordered_map IMGUI_KEY_MAP = -{ - { "A", ImGuiKey_A }, - { "B", ImGuiKey_B }, - { "C", ImGuiKey_C }, - { "D", ImGuiKey_D }, - { "E", ImGuiKey_E }, - { "F", ImGuiKey_F }, - { "G", ImGuiKey_G }, - { "H", ImGuiKey_H }, - { "I", ImGuiKey_I }, - { "J", ImGuiKey_J }, - { "K", ImGuiKey_K }, - { "L", ImGuiKey_L }, - { "M", ImGuiKey_M }, - { "N", ImGuiKey_N }, - { "O", ImGuiKey_O }, - { "P", ImGuiKey_P }, - { "Q", ImGuiKey_Q }, - { "R", ImGuiKey_R }, - { "S", ImGuiKey_S }, - { "T", ImGuiKey_T }, - { "U", ImGuiKey_U }, - { "V", ImGuiKey_V }, - { "W", ImGuiKey_W }, - { "X", ImGuiKey_X }, - { "Y", ImGuiKey_Y }, - { "Z", ImGuiKey_Z }, - - { "0", ImGuiKey_0 }, - { "1", ImGuiKey_1 }, - { "2", ImGuiKey_2 }, - { "3", ImGuiKey_3 }, - { "4", ImGuiKey_4 }, - { "5", ImGuiKey_5 }, - { "6", ImGuiKey_6 }, - { "7", ImGuiKey_7 }, - { "8", ImGuiKey_8 }, - { "9", ImGuiKey_9 }, - - { "Num0", ImGuiKey_Keypad0 }, - { "Num1", ImGuiKey_Keypad1 }, - { "Num2", ImGuiKey_Keypad2 }, - { "Num3", ImGuiKey_Keypad3 }, - { "Num4", ImGuiKey_Keypad4 }, - { "Num5", ImGuiKey_Keypad5 }, - { "Num6", ImGuiKey_Keypad6 }, - { "Num7", ImGuiKey_Keypad7 }, - { "Num8", ImGuiKey_Keypad8 }, - { "Num9", ImGuiKey_Keypad9 }, - { "NumAdd", ImGuiKey_KeypadAdd }, - { "NumSubtract", ImGuiKey_KeypadSubtract }, - { "NumMultiply", ImGuiKey_KeypadMultiply }, - { "NumDivide", ImGuiKey_KeypadDivide }, - { "NumEnter", ImGuiKey_KeypadEnter }, - { "NumDecimal", ImGuiKey_KeypadDecimal }, - - { "F1", ImGuiKey_F1 }, - { "F2", ImGuiKey_F2 }, - { "F3", ImGuiKey_F3 }, - { "F4", ImGuiKey_F4 }, - { "F5", ImGuiKey_F5 }, - { "F6", ImGuiKey_F6 }, - { "F7", ImGuiKey_F7 }, - { "F8", ImGuiKey_F8 }, - { "F9", ImGuiKey_F9 }, - { "F10", ImGuiKey_F10 }, - { "F11", ImGuiKey_F11 }, - { "F12", ImGuiKey_F12 }, - - { "Up", ImGuiKey_UpArrow }, - { "Down", ImGuiKey_DownArrow }, - { "Left", ImGuiKey_LeftArrow }, - { "Right", ImGuiKey_RightArrow }, - - { "Space", ImGuiKey_Space }, - { "Enter", ImGuiKey_Enter }, - { "Escape", ImGuiKey_Escape }, - { "Tab", ImGuiKey_Tab }, - { "Backspace", ImGuiKey_Backspace }, - { "Delete", ImGuiKey_Delete }, - { "Insert", ImGuiKey_Insert }, - { "Home", ImGuiKey_Home }, - { "End", ImGuiKey_End }, - { "PageUp", ImGuiKey_PageUp }, - { "PageDown", ImGuiKey_PageDown }, - - { "Minus", ImGuiKey_Minus }, - { "Equal", ImGuiKey_Equal }, - { "LeftBracket", ImGuiKey_LeftBracket }, - { "RightBracket", ImGuiKey_RightBracket }, - { "Semicolon", ImGuiKey_Semicolon }, - { "Apostrophe", ImGuiKey_Apostrophe }, - { "Comma", ImGuiKey_Comma }, - { "Period", ImGuiKey_Period }, - { "Slash", ImGuiKey_Slash }, - { "Backslash", ImGuiKey_Backslash }, - { "GraveAccent", ImGuiKey_GraveAccent }, - - { "MouseLeft", ImGuiKey_MouseLeft }, - { "MouseRight", ImGuiKey_MouseRight }, - { "MouseMiddle", ImGuiKey_MouseMiddle }, - { "MouseX1", ImGuiKey_MouseX1 }, - { "MouseX2", ImGuiKey_MouseX2 } -}; - -static std::unordered_map IMGUI_MOD_MAP = -{ - { "Ctrl", ImGuiMod_Ctrl }, - { "Shift", ImGuiMod_Shift }, - { "Alt", ImGuiMod_Alt }, - { "Super", ImGuiMod_Super }, -}; - -static inline ImGuiKey imgui_key_from_char_get(char c) -{ - if (c >= 'a' && c <= 'z') c -= 'a' - 'A'; - if (c >= 'A' && c <= 'Z') return (ImGuiKey)(ImGuiKey_A + (c - 'A')); - return ImGuiKey_None; -} - -static inline std::string imgui_string_from_chord_get(ImGuiKeyChord chord) -{ - std::string result; - - if (chord & ImGuiMod_Ctrl) result += "Ctrl+"; - if (chord & ImGuiMod_Shift) result += "Shift+"; - if (chord & ImGuiMod_Alt) result += "Alt+"; - if (chord & ImGuiMod_Super) result += "Super+"; - - ImGuiKey key = (ImGuiKey)(chord & ~ImGuiMod_Mask_); - - if (key != ImGuiKey_None) - { - const char* name = ImGui::GetKeyName(key); - if (name && *name) - result += name; - else - result += "Unknown"; - } - - if (!result.empty() && result.back() == '+') - result.pop_back(); - - return result; -} - -static inline ImGuiKeyChord imgui_chord_from_string_get(const std::string& str) -{ - ImGuiKeyChord chord = 0; - ImGuiKey baseKey = ImGuiKey_None; - - std::stringstream ss(str); - std::string token; - while (std::getline(ss, token, '+')) - { - // trim - token.erase(0, token.find_first_not_of(" \t\r\n")); - token.erase(token.find_last_not_of(" \t\r\n") + 1); - - if (token.empty()) - continue; - - if (auto it = IMGUI_MOD_MAP.find(token); it != IMGUI_MOD_MAP.end()) { - chord |= it->second; - } - else if (baseKey == ImGuiKey_None) { - if (auto it2 = IMGUI_KEY_MAP.find(token); it2 != IMGUI_KEY_MAP.end()) - baseKey = it2->second; - } - } - - if (baseKey != ImGuiKey_None) - chord |= baseKey; - - return chord; + return chord; } static inline void imgui_keyboard_nav_enable(void) { ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; } static inline void imgui_keyboard_nav_disable(void) { ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NavEnableKeyboard; } static inline void imgui_contextual_actions_enable(Imgui* self) { self->isContextualActionsEnabled = true; } -static inline void imgui_contextual_actions_disable(Imgui* self){ self->isContextualActionsEnabled = false; } +static inline void imgui_contextual_actions_disable(Imgui* self) { self->isContextualActionsEnabled = false; } static inline bool imgui_is_popup_open(const std::string& label) { return ImGui::IsPopupOpen(label.c_str()); } - -static inline bool imgui_is_any_popup_open(void) -{ - return ImGui::IsPopupOpen(nullptr, ImGuiPopupFlags_AnyPopupId); -} - +static inline bool imgui_is_any_popup_open(void) { return ImGui::IsPopupOpen(nullptr, ImGuiPopupFlags_AnyPopupId); } static inline void imgui_open_popup(const std::string& label) { ImGui::OpenPopup(label.c_str()); } -static inline void imgui_pending_popup_process(Imgui* self) -{ - if (self->pendingPopup.empty()) return; +static inline void imgui_pending_popup_process(Imgui* self) { + if (self->pendingPopup.empty()) + return; - switch (self->pendingPopupType) - { - case IMGUI_POPUP_CENTER_WINDOW: - ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); - break; - case IMGUI_POPUP_BY_ITEM: - default: - ImGui::SetNextWindowPos(self->pendingPopupPosition); - break; - } + switch (self->pendingPopupType) { + case IMGUI_POPUP_CENTER_WINDOW: + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); + break; + case IMGUI_POPUP_BY_ITEM: + default: + ImGui::SetNextWindowPos(self->pendingPopupPosition); + break; + } - imgui_open_popup(self->pendingPopup.c_str()); + if (!imgui_is_any_popup_open()) + imgui_open_popup(self->pendingPopup.c_str()); - self->pendingPopup.clear(); - self->pendingPopupType = IMGUI_POPUP_NONE; - self->pendingPopupPosition = ImVec2(); + self->pendingPopup.clear(); + self->pendingPopupType = IMGUI_POPUP_NONE; + self->pendingPopupPosition = ImVec2(); } -static inline bool imgui_begin_popup(const std::string& label, Imgui* imgui, ImVec2 size = ImVec2()) -{ - imgui_pending_popup_process(imgui); - if (size != ImVec2()) ImGui::SetNextWindowSizeConstraints(size, ImVec2(FLT_MAX, FLT_MAX)); - bool isActivated = ImGui::BeginPopup(label.c_str(), IMGUI_POPUP_FLAGS); - return isActivated; +static inline bool imgui_begin_popup(const std::string& label, Imgui* imgui, ImVec2 size = ImVec2()) { + imgui_pending_popup_process(imgui); + if (size != ImVec2()) + ImGui::SetNextWindowSizeConstraints(size, ImVec2(FLT_MAX, FLT_MAX)); + bool isActivated = ImGui::BeginPopup(label.c_str(), IMGUI_POPUP_FLAGS); + return isActivated; } -static inline bool imgui_begin_popup_modal(const std::string& label, Imgui* imgui, ImVec2 size = ImVec2()) -{ - imgui_pending_popup_process(imgui); - if (size != ImVec2()) ImGui::SetNextWindowSizeConstraints(size, ImVec2(FLT_MAX, FLT_MAX)); - bool isActivated = ImGui::BeginPopupModal(label.c_str(), nullptr, IMGUI_POPUP_MODAL_FLAGS); - if (isActivated) imgui_contextual_actions_disable(imgui); - return isActivated; +static inline bool imgui_begin_popup_modal(const std::string& label, Imgui* imgui, ImVec2 size = ImVec2()) { + imgui_pending_popup_process(imgui); + if (size != ImVec2()) + ImGui::SetNextWindowSizeConstraints(size, ImVec2(FLT_MAX, FLT_MAX)); + bool isActivated = ImGui::BeginPopupModal(label.c_str(), nullptr, IMGUI_POPUP_MODAL_FLAGS); + if (isActivated) + imgui_contextual_actions_disable(imgui); + return isActivated; } -static inline void imgui_close_current_popup(Imgui* imgui) -{ - imgui_contextual_actions_enable(imgui); - ImGui::CloseCurrentPopup(); +static inline void imgui_close_current_popup(Imgui* imgui) { + imgui_contextual_actions_enable(imgui); + ImGui::CloseCurrentPopup(); } -static inline void imgui_end_popup(Imgui* imgui) -{ - ImGui::EndPopup(); - imgui_pending_popup_process(imgui); +static inline void imgui_end_popup(Imgui* imgui) { + ImGui::EndPopup(); + imgui_pending_popup_process(imgui); } -enum ImguiItemType -{ - IMGUI_ITEM, - IMGUI_TEXT, - IMGUI_WINDOW, - IMGUI_DOCKSPACE, - IMGUI_CHILD, - IMGUI_TABLE, - IMGUI_CONFIRM_POPUP, - IMGUI_SELECTABLE, - IMGUI_BUTTON, - IMGUI_RADIO_BUTTON, - IMGUI_COLOR_BUTTON, - IMGUI_CHECKBOX, - IMGUI_INPUT_INT, - IMGUI_INPUT_TEXT, - IMGUI_INPUT_FLOAT, - IMGUI_SLIDER_FLOAT, - IMGUI_DRAG_FLOAT, - IMGUI_COLOR_EDIT, - IMGUI_COMBO, - IMGUI_ATLAS_BUTTON -}; - -struct ImguiItemOverride -{ - bool isDisabled{}; - bool isSelected{}; - std::string label{}; - ImVec2 size{}; - s32 id{}; - s32 max{}; - AtlasType atlas = ATLAS_NONE; - bool isMnemonicDisabled{}; - s32 value{}; - s32 rowCount{}; +enum ImguiItemType { + IMGUI_ITEM, + IMGUI_TEXT, + IMGUI_IMAGE, + IMGUI_WINDOW, + IMGUI_DOCKSPACE, + IMGUI_BEGIN_CHILD, + IMGUI_END_CHILD, + IMGUI_TABLE, + IMGUI_CONFIRM_POPUP, + IMGUI_SELECTABLE, + IMGUI_BUTTON, + IMGUI_RADIO_BUTTON, + IMGUI_COLOR_BUTTON, + IMGUI_CHECKBOX, + IMGUI_INPUT_INT, + IMGUI_INPUT_TEXT, + IMGUI_INPUT_FLOAT, + IMGUI_SLIDER_FLOAT, + IMGUI_DRAG_FLOAT, + IMGUI_COLOR_EDIT, + IMGUI_COMBO, + IMGUI_ATLAS_TEXT, + IMGUI_ATLAS_BUTTON }; struct ImguiItem; -static std::vector& imgui_item_registry(void) -{ - static std::vector registry; - return registry; +static std::vector& imgui_item_registry(void) { + static std::vector registry; + return registry; } -static ImGuiKeyChord* imgui_hotkey_chord_registry(void) -{ - static ImGuiKeyChord registry[HOTKEY_COUNT]; - return registry; +static ImGuiKeyChord* imgui_hotkey_chord_registry(void) { + static ImGuiKeyChord registry[HOTKEY_COUNT]; + return registry; } -typedef void(*ImguiFunction)(Imgui*); +typedef void (*ImguiFunction)(Imgui*); -// Item -struct ImguiItem -{ - std::string label{}; - std::string tooltip{}; - std::string& text = tooltip; - std::string snapshotAction{}; - std::string popup{}; - std::string dragDrop{}; - std::string focusWindow{}; - std::vector items{}; - AtlasType atlas = ATLAS_NONE; - ImGuiKeyChord chord = IMGUI_CHORD_NONE; - HotkeyType hotkey = HOTKEY_NONE; - ImGuiKey mnemonicKey = ImGuiKey_None; - s32 mnemonicIndex = INDEX_NONE; - ImVec2 size{}; - ImVec2 popupSize{}; - ImguiColorSet color{}; - ImguiFunction function = nullptr; - ImguiPopupType popupType = IMGUI_POPUP_CENTER_WINDOW; - bool isDisabled = false; - bool isMnemonicDisabled = false; - bool isEmptyFormat = false; - bool isSelected = false; - bool isUseItemActivated = false; - bool isSizeToText = false; - bool isHotkeyInLabel = false; - bool isSameLine = false; - bool isSeparator = false; - s32 id = 0; - s32 idOffset{}; - f32 speed = 0.25f; - s32 step = 1; - s32 stepFast = 10; - s32 min{}; - s32 max{}; - s32 value{}; - vec2 atlasOffset{}; - s32 border{}; - s32 flags{}; - s32 windowFlags{}; - s32 rowCount = 0; +#define IMGUI_ITEM_MEMBERS \ + X(label, std::string, false, {}) \ + X(tooltip, std::string, false, {}) \ + X(snapshotAction, std::string, true, {}) \ + X(popup, std::string, false, {}) \ + X(dragDrop, std::string, true, {}) \ + X(focusWindow, std::string, true, {}) \ + X(items, std::vector, false, {}) \ + X(atlas, AtlasType, false, ATLAS_NONE) \ + X(textureID, int, false, ID_NONE) \ + X(chord, ImGuiKeyChord, true, {}) \ + X(hotkey, HotkeyType, true, {}) \ + X(mnemonicKey, ImGuiKey, false, ImGuiKey_None) \ + X(mnemonicIndex, int, false, INDEX_NONE) \ + X(size, vec2, true, {}) \ + X(uvMin, vec2, false, vec2()) \ + X(uvMax, vec2, false, vec2(1.0f)) \ + X(popupSize, vec2, false, {}) \ + X(color, ImguiColorSet, false, {}) \ + X(function, ImguiFunction, false, {}) \ + X(popupType, ImguiPopupType, false, IMGUI_POPUP_CENTER_WINDOW) \ + X(isDisabled, bool, false, false) \ + X(isSelected, bool, false, false) \ + X(isMnemonicDisabled, bool, false, false) \ + X(isEmptyFormat, bool, false, false) \ + X(isUseItemActivated, bool, false, false) \ + X(isSizeToText, bool, false, false) \ + X(isSizeToRegion, bool, false, false) \ + X(isHotkeyInLabel, bool, false, false) \ + X(isSameLine, bool, false, false) \ + X(isSeparator, bool, false, false) \ + X(id, int, false, 0) \ + X(idOffset, int, false, {}) \ + X(speed, float, false, 0.25f) \ + X(step, float, false, 1.0f) \ + X(stepFast, float, false, 10.0f) \ + X(min, int, true, {}) \ + X(max, int, true, {}) \ + X(value, int, false, {}) \ + X(atlasOffset, vec2, false, {}) \ + X(cursorPosition, vec2, true, {}) \ + X(cursorOffset, vec2, false, {}) \ + X(itemSpacing, vec2, true, {}) \ + X(windowPadding, vec2, true, {}) \ + X(framePadding, vec2, true, {}) \ + X(border, int, true, {}) \ + X(flags, int, false, {}) \ + X(windowFlags, int, false, {}) \ + X(rowCount, int, true, {}) - bool is_border() const { return border != 0; } - bool is_row() const { return rowCount != 0; } - bool is_hotkey() const { return hotkey != HOTKEY_NONE; } - bool is_chord() const { return chord != IMGUI_CHORD_NONE || is_hotkey(); } - bool is_drag_drop() const { return !dragDrop.empty(); } - bool is_focus_window() const { return !focusWindow.empty(); } - bool is_popup() const { return !popup.empty(); } - bool is_function() const { return function; } - bool is_size() const { return size != ImVec2(); } - bool is_popup_size() const { return popupSize != ImVec2(); } - bool is_tooltip() const { return !tooltip.empty(); } - bool is_undoable() const { return !snapshotAction.empty(); } - bool is_mnemonic() const { return mnemonicKey != ImGuiKey_None; } - bool is_range() const { return min != 0 || max != 0; } - const char* drag_drop_get() const { return dragDrop.c_str(); } - const char* text_get() const { return text.c_str(); } - - void construct() - { - static s32 idNew = 0; - id = idNew++; - - imgui_item_registry().push_back(this); - - std::string labelNew{}; - - for (s32 i = 0; i < (s32)label.size(); i++) - { - if (label[i] == '&') - { - if (label[i + 1] == '&') - { - labelNew += '&'; - i++; - } - else if (label[i + 1] != '\0') - { - mnemonicKey = imgui_key_from_char_get(label[i + 1]); - mnemonicIndex = (s32)labelNew.size(); - labelNew += label[i + 1]; - i++; - } - } - else - labelNew += label[i]; - } - - label = labelNew; - } - - ImguiItem copy(const ImguiItemOverride& override) const - { - ImguiItem out = *this; - if (override.isDisabled) out.isDisabled = override.isDisabled; - if(override.isSelected) out.isSelected = override.isSelected; - if (is_popup() && imgui_is_popup_open(popup)) out.isSelected = true; - if (id != ID_NONE) out.id = id + idOffset + override.id; - if (!override.label.empty()) out.label = override.label; - if (override.size != ImVec2{}) out.size = override.size; - if (override.max != 0) out.max = override.max; - if (override.value != 0) out.value = override.value; - if (override.rowCount != 0) out.rowCount = override.rowCount; - if (override.atlas != ATLAS_NONE) out.atlas = override.atlas; - if (override.isMnemonicDisabled) out.isMnemonicDisabled = override.isMnemonicDisabled; - return out; - } - - ImGuiKeyChord chord_get() const - { - if (is_hotkey()) return imgui_hotkey_chord_registry()[hotkey]; - return chord; - } - - std::string label_get() const - { - std::string newLabel = label; - if (isHotkeyInLabel) - newLabel += std::format(IMGUI_LABEL_HOTKEY_FORMAT, imgui_string_from_chord_get(chord_get())); - return newLabel; - } - - std::string tooltip_get() const - { - std::string newTooltip = tooltip; - if (is_chord()) - newTooltip += std::format(IMGUI_TOOLTIP_HOTKEY_FORMAT, imgui_string_from_chord_get(chord_get())); - return newTooltip; - } +struct ImguiItemOverride { +#define X(name, type, isOptional, ...) std::optional name = {}; + IMGUI_ITEM_MEMBERS +#undef X }; -#define IMGUI_ITEM(NAME, ...) const inline ImguiItem NAME = []{ ImguiItem self; __VA_ARGS__; self.construct(); return self; }() +struct ImguiItem { +#define X(name, type, isOptional, ...) std::conditional_t, type> name = __VA_ARGS__; + IMGUI_ITEM_MEMBERS +#undef X -IMGUI_ITEM(IMGUI_WINDOW_MAIN, - self.label = "## Window", - self.flags = ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoCollapse | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoBringToFrontOnFocus | - ImGuiWindowFlags_NoNavFocus -); + bool is_chord() const { return chord.has_value() || hotkey.has_value(); } + bool is_mnemonic() const { return mnemonicKey != ImGuiKey_None; } + bool is_range() const { return min != 0 || max != 0; } + const char* drag_drop_get() const { return dragDrop->c_str(); } + const char* text_get() const { return tooltip.c_str(); } -IMGUI_ITEM(IMGUI_DOCKSPACE_MAIN, - self.label = "## Dockspace", - self.flags = ImGuiDockNodeFlags_PassthruCentralNode -); + void construct() { + static int idNew = 0; + id = idNew++; -IMGUI_ITEM(IMGUI_FOOTER_CHILD, - self.label = "## Footer Child", - self.size = {0, 36}, - self.flags = true -); + imgui_item_registry().push_back(this); -IMGUI_ITEM(IMGUI_TASKBAR, - self.label = "Taskbar", - self.size = {0, 32}, - self.flags = ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse | - ImGuiWindowFlags_NoSavedSettings -); + std::string labelNew{}; -IMGUI_ITEM(IMGUI_FILE, - self.label = "&File", - self.tooltip = "Opens the file menu, for reading/writing anm2 files.", - self.popup = "## File Popup", - self.popupType = IMGUI_POPUP_BY_ITEM, - self.isSizeToText = true, - self.isSameLine = true -); + for (int i = 0; i < (int)label.size(); i++) { + if (label[i] == '&') { + if (label[i + 1] == '&') { + labelNew += '&'; + i++; + } else if (label[i + 1] != '\0') { + mnemonicKey = imgui_key_from_char_get(label[i + 1]); + mnemonicIndex = (int)labelNew.size(); + labelNew += label[i + 1]; + i++; + } + } else + labelNew += label[i]; + } -IMGUI_ITEM(IMGUI_NEW, - self.label = "&New ", - self.tooltip = "Load a blank .anm2 file to edit.", - self.function = imgui_file_new, - self.hotkey = HOTKEY_NEW, - self.isSizeToText = true, - self.isHotkeyInLabel = true -); + label = labelNew; + } -IMGUI_ITEM(IMGUI_OPEN, - self.label = "&Open ", - self.tooltip = "Open an existing .anm2 file to edit.", - self.function = imgui_file_open, - self.hotkey = HOTKEY_OPEN, - self.isSizeToText = true, - self.isHotkeyInLabel = true -); + ImguiItem copy(const ImguiItemOverride& override) const { + ImguiItem out = *this; -IMGUI_ITEM(IMGUI_SAVE, - self.label = "&Save ", - self.tooltip = "Saves the current .anm2 file to its path.\nIf no path exists, one can be chosen.", - self.function = imgui_file_save, - self.hotkey = HOTKEY_SAVE, - self.isSizeToText = true, - self.isHotkeyInLabel = true -); +#define X(name, type, value, isOptional) \ + if (override.name.has_value()) \ + out.name = *override.name; + IMGUI_ITEM_MEMBERS +#undef X -IMGUI_ITEM(IMGUI_SAVE_AS, - self.label = "S&ave As ", - self.tooltip = "Saves the current .anm2 file to a chosen path.", - self.function = imgui_file_save_as, - self.hotkey = HOTKEY_SAVE_AS, - self.isSizeToText = true, - self.isHotkeyInLabel = true -); + return out; + } -IMGUI_ITEM(IMGUI_EXPLORE_ANM2_LOCATION, - self.label = "E&xplore Anm2 Location", - self.tooltip = "Open the system's file explorer in the anm2's path.", - self.function = imgui_explore, - self.isSizeToText = true, - self.isSeparator = true -); + ImGuiKeyChord chord_get() const { + if (hotkey.has_value()) + return imgui_hotkey_chord_registry()[*hotkey]; + if (chord.has_value()) + return *chord; + return ImGuiKey_None; + } -IMGUI_ITEM(IMGUI_EXIT, - self.label = "&Exit ", - self.tooltip = "Exits the program.", - self.function = imgui_quit, - self.hotkey = HOTKEY_EXIT, - self.isSizeToText = true, - self.isHotkeyInLabel = true -); + std::string label_get() const { + std::string newLabel = label; + if (isHotkeyInLabel) + newLabel += std::format(IMGUI_LABEL_HOTKEY_FORMAT, imgui_string_from_chord_get(chord_get())); + return newLabel; + } -IMGUI_ITEM(IMGUI_EXIT_CONFIRMATION, - self.label = "Exit Confirmation", - self.text = "Unsaved changes will be lost!\nAre you sure you want to exit?" -); + std::string tooltip_get() const { + std::string newTooltip = tooltip; + if (is_chord()) + newTooltip += std::format(IMGUI_TOOLTIP_HOTKEY_FORMAT, imgui_string_from_chord_get(chord_get())); + return newTooltip; + } +}; -IMGUI_ITEM(IMGUI_OPEN_CONFIRMATION, - self.label = "Open Confirmation", - self.text = "Unsaved changes will be lost!\nAre you sure you open a new file?" -); +#define IMGUI_ITEM(NAME, ...) \ + const inline ImguiItem NAME = [] { \ + ImguiItem self; \ + __VA_ARGS__; \ + self.construct(); \ + return self; \ + }() -IMGUI_ITEM(IMGUI_NO_ANM2_PATH_CONFIRMATION, - self.label = "No Anm2 Path", - self.text = "You will need to load or make a new .anm2 file first!\n" -); +IMGUI_ITEM(IMGUI_WINDOW_MAIN, self.label = "## Window", + self.flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus); -IMGUI_ITEM(IMGUI_WIZARD, - self.label = "&Wizard", - self.tooltip = "Opens the wizard menu, for neat functions related to the .anm2.", - self.popup = "## Wizard Popup", - self.popupType = IMGUI_POPUP_BY_ITEM, - self.isSizeToText = true, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_DOCKSPACE_MAIN, self.label = "## Dockspace", self.flags = ImGuiDockNodeFlags_PassthruCentralNode); + +IMGUI_ITEM(IMGUI_FOOTER_CHILD, self.label = "## Footer Child", self.size = {0, 42}, self.flags = true); + +IMGUI_ITEM(IMGUI_TASKBAR, self.label = "Taskbar", self.size = {0, 32}, + self.flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoSavedSettings); + +IMGUI_ITEM(IMGUI_FILE, self.label = "&File", self.tooltip = "Opens the file menu, for reading/writing anm2 files.", self.popup = "## File Popup", + self.popupType = IMGUI_POPUP_BY_ITEM, self.isSizeToText = true, self.isSameLine = true); + +IMGUI_ITEM(IMGUI_NEW, self.label = "&New", self.tooltip = "Load a blank .anm2 file to edit.", self.function = imgui_file_new, self.hotkey = HOTKEY_NEW, + self.isSizeToText = true, self.isHotkeyInLabel = true); + +IMGUI_ITEM(IMGUI_OPEN, self.label = "&Open", self.tooltip = "Open an existing .anm2 file to edit.", self.function = imgui_file_open, self.hotkey = HOTKEY_OPEN, + self.isSizeToText = true, self.isHotkeyInLabel = true); + +IMGUI_ITEM(IMGUI_SAVE, self.label = "&Save", + self.tooltip = "Saves the current .anm2 file to its path.\nIf no " + "path exists, one can be chosen.", + self.function = imgui_file_save, self.hotkey = HOTKEY_SAVE, self.isSizeToText = true, self.isHotkeyInLabel = true); + +IMGUI_ITEM(IMGUI_SAVE_AS, self.label = "S&ave As", self.tooltip = "Saves the current .anm2 file to a chosen path.", self.function = imgui_file_save_as, + self.hotkey = HOTKEY_SAVE_AS, self.isSizeToText = true, self.isHotkeyInLabel = true); + +IMGUI_ITEM(IMGUI_EXPLORE_ANM2_LOCATION, self.label = "E&xplore Anm2 Location", self.tooltip = "Open the system's file explorer in the anm2's path.", + self.function = imgui_explore, self.isSizeToText = true, self.isSeparator = true); + +IMGUI_ITEM(IMGUI_EXIT, self.label = "&Exit", self.tooltip = "Exits the program.", self.function = imgui_quit, self.hotkey = HOTKEY_EXIT, + self.isSizeToText = true, self.isHotkeyInLabel = true); + +IMGUI_ITEM(IMGUI_EXIT_CONFIRMATION, self.label = "Exit Confirmation", self.tooltip = "Unsaved changes will be lost!\nAre you sure you want to exit?"); + +IMGUI_ITEM(IMGUI_OPEN_CONFIRMATION, self.label = "Open Confirmation", self.tooltip = "Unsaved changes will be lost!\nAre you sure you open a new file?"); + +IMGUI_ITEM(IMGUI_NO_ANM2_PATH_CONFIRMATION, self.label = "No Anm2 Path", self.tooltip = "You will need to load or make a new .anm2 file first!\n"); + +IMGUI_ITEM(IMGUI_WIZARD, self.label = "&Wizard", self.tooltip = "Opens the wizard menu, for neat functions related to the .anm2.", + self.popup = "## Wizard Popup", self.popupType = IMGUI_POPUP_BY_ITEM, self.isSizeToText = true, self.isSameLine = true); #define IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING 40 -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID, - self.label = "&Generate Animation from Grid", - self.tooltip = "Generate a new animation from grid values.", - self.popup = "Generate Animation from Grid", - self.popupType = IMGUI_POPUP_CENTER_WINDOW, - self.popupSize = - { - (GENERATE_PREVIEW_SIZE.x * 2) + IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING, - GENERATE_PREVIEW_SIZE.y + (IMGUI_FOOTER_CHILD.size.y * 2) + (IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING / 2) - } -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID, self.label = "&Generate Animation from Grid", self.tooltip = "Generate a new animation from grid values.", + self.popup = "Generate Animation from Grid", self.popupType = IMGUI_POPUP_CENTER_WINDOW, + self.popupSize = {(GENERATE_PREVIEW_SIZE.x * 2) + IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING, + GENERATE_PREVIEW_SIZE.y + (IMGUI_FOOTER_CHILD.size->y * 2) + (IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING * 0.5f)}); -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_OPTIONS_CHILD, - self.label = "## Generate Animation From Grid Options Child", - self.size = - { - IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.x / 2, - IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.y - IMGUI_FOOTER_CHILD.size.y - }, - self.flags = true -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_OPTIONS_CHILD, self.label = "## Generate Animation From Grid Options Child", + self.size = {IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.x * 0.5f, IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.y - IMGUI_FOOTER_CHILD.size->y}, + self.flags = true); -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_START_POSITION, - self.label = "Start Position", - self.tooltip = "Set the starting position on the layer's spritesheet for the generated animation." -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_START_POSITION, self.label = "Start Position", + self.tooltip = "Set the starting position on the layer's " + "spritesheet for the generated animation."); -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_SIZE, - self.label = "Size", - self.tooltip = "Set the size of each frame in the generated animation." -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_SIZE, self.label = "Size", self.tooltip = "Set the size of each frame in the generated animation."); -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_PIVOT, - self.label = "Pivot", - self.tooltip = "Set the pivot of each frame in the generated animation." -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_PIVOT, self.label = "Pivot", self.tooltip = "Set the pivot of each frame in the generated animation."); -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_ROWS, - self.label = "Rows", - self.tooltip = "Set how many rows will be used in the generated animation.", - self.min = 1, - self.max = 1000 -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_ROWS, self.label = "Rows", self.tooltip = "Set how many rows will be used in the generated animation.", + self.min = 1, self.max = 1000); -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_COLUMNS, - self.label = "Columns", - self.tooltip = "Set how many columns will be used in the generated animation.", - self.min = 1, - self.max = 1000 -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_COLUMNS, self.label = "Columns", self.tooltip = "Set how many columns will be used in the generated animation.", + self.min = 1, self.max = 1000); -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_COUNT, - self.label = "Count", - self.tooltip = "Set how many frames will be made for the generated animation.", - self.value = ANM2_FRAME_NUM_MIN -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_COUNT, self.label = "Count", self.tooltip = "Set how many frames will be made for the generated animation.", + self.value = ANM2_FRAME_NUM_MIN); -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_DELAY, - self.label = "Delay", - self.tooltip = "Set the delay of each frame in the generated animation.", - self.max = 1000 -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_DELAY, self.label = "Delay", self.tooltip = "Set the delay of each frame in the generated animation.", + self.max = 1000); -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_PREVIEW_CHILD, - self.label = "## Generate Animation From Grid Preview Child", - self.size = - { - IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.x / 2, - IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.y - IMGUI_FOOTER_CHILD.size.y - }, - self.flags = true -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_PREVIEW_CHILD, self.label = "## Generate Animation From Grid Preview Child", + self.size = {IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.x * 0.5f, IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.y - IMGUI_FOOTER_CHILD.size->y}, + self.flags = true); -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER_CHILD, - self.label = "## Generate Animation From Grid Slider Child", - self.size = - { - (IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.x / 2) - (IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING / 2), - IMGUI_FOOTER_CHILD.size.y - }, - self.flags = true -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER_CHILD, self.label = "## Generate Animation From Grid Slider Child", + self.size = {(IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.x * 0.5f) - (IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING * 0.5f), + IMGUI_FOOTER_CHILD.size->y}, + self.flags = true); -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER, - self.label = "## Generate Animation From Grid Slider", - self.tooltip = "Change the time of the generated animation preview.", - self.min = GENERATE_PREVIEW_TIME_MIN, - self.max = GENERATE_PREVIEW_TIME_MAX, - self.value = GENERATE_PREVIEW_TIME_MIN, - self.rowCount = 1, - self.isEmptyFormat = true, - self.flags = ImGuiSliderFlags_NoInput -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER, self.label = "## Generate Animation From Grid Slider", + self.tooltip = "Change the time of the generated animation preview.", self.min = GENERATE_PREVIEW_TIME_MIN, self.max = GENERATE_PREVIEW_TIME_MAX, + self.value = GENERATE_PREVIEW_TIME_MIN, self.rowCount = 1, self.isEmptyFormat = true, self.flags = ImGuiSliderFlags_NoInput); -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_GENERATE, - self.label = "Generate", - self.tooltip = "Generate an animation with the used settings.", - self.snapshotAction = "Generate Animation from Grid", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_GENERATE, self.label = "Generate", self.tooltip = "Generate an animation with the used settings.", + self.snapshotAction = "Generate Animation from Grid", self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES, - self.label = "&Change All Frame Properties", - self.tooltip = "Change all frame properties in the selected animation item (or selected frame).", - self.popup = "Change All Frame Properties", - self.popupType = IMGUI_POPUP_CENTER_WINDOW, - self.popupSize = {500, 405} -); +IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES, self.label = "&Change All Frame Properties", + self.tooltip = "Change all frame properties in the selected " + "animation item (or selected frame).", + self.popup = "Change All Frame Properties", self.popupType = IMGUI_POPUP_CENTER_WINDOW, self.popupSize = {500, 405}); -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CHILD, - self.label = "## Change All Frame Properties Child", - self.size = - { - IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popupSize.x, - 275 - }, - self.flags = true -); +IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CHILD, self.label = "## Change All Frame Properties Child", + self.size = {IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popupSize.x, 275}, self.flags = true); -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS_CHILD, - self.label = "## Change All Frame Properties Settings Child", - self.size = - { - IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popupSize.x, - 55 - }, - self.flags = true -); +IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS_CHILD, self.label = "## Change All Frame Properties Settings Child", + self.size = {IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popupSize.x, 55}, self.flags = true); IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS, self.label = "Settings"); -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_FROM_SELECTED_FRAME, - self.label = "From Selected Frames", - self.tooltip = "The set frame properties will start from the selected frame.", - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_FROM_SELECTED_FRAME, self.label = "From Selected Frames", + self.tooltip = "The set frame properties will start from the selected frame.", self.isSameLine = true); -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_NUMBER_FRAMES, - self.label = "# of Frames", - self.tooltip = "Set the amount of frames that the set frame properties will apply to.", - self.size = {200, 0}, - self.value = ANM2_FRAME_NUM_MIN, - self.max = 1000 -); +IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_NUMBER_FRAMES, self.label = "# of Frames", + self.tooltip = "Set the amount of frames that the set frame properties will apply to.", self.size = {200, 0}, self.value = ANM2_FRAME_NUM_MIN, + self.max = 1000); #define IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT 4 -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_ADD, - self.label = "Add", - self.tooltip = "The specified values will be added to all specified frames.", - self.snapshotAction = "Add Frame Properties", - self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_ADD, self.label = "Add", self.tooltip = "The specified values will be added to all specified frames.", + self.snapshotAction = "Add Frame Properties", self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SUBTRACT, - self.label = "Subtract", - self.tooltip = "The specified values will be subtracted from all selected frames.", - self.snapshotAction = "Subtract Frame Properties", - self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SUBTRACT, self.label = "Subtract", + self.tooltip = "The specified values will be subtracted from all selected frames.", self.snapshotAction = "Subtract Frame Properties", + self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SET, - self.label = "Set", - self.tooltip = "The specified values will be set to the specified value in selected frames.", - self.snapshotAction = "Set Frame Properties", - self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SET, self.label = "Set", + self.tooltip = "The specified values will be set to the specified " + "value in selected frames.", + self.snapshotAction = "Set Frame Properties", self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CANCEL, - self.label = "Cancel", - self.tooltip = "Cancel changing all frame properties.", - self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT -); +IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CANCEL, self.label = "Cancel", self.tooltip = "Cancel changing all frame properties.", + self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT); -IMGUI_ITEM(IMGUI_SCALE_ANM2, - self.label = "S&cale Anm2", - self.tooltip = "Scale up all size and position-related frame properties in the anm2.", - self.popup = "Scale Anm2", - self.popupType = IMGUI_POPUP_CENTER_WINDOW, - self.popupSize = {260, 75}, - self.isSizeToText = true, - self.isSeparator = true -); +IMGUI_ITEM(IMGUI_SCALE_ANM2, self.label = "S&cale Anm2", self.tooltip = "Scale up all size and position-related frame properties in the anm2.", + self.popup = "Scale Anm2", self.popupType = IMGUI_POPUP_CENTER_WINDOW, self.popupSize = {260, 75}, self.isSizeToText = true, + self.isSeparator = true); -IMGUI_ITEM(IMGUI_SCALE_ANM2_OPTIONS_CHILD, - self.label = "## Scale Anm2 Options Child", - self.size = {IMGUI_SCALE_ANM2.popupSize.x, IMGUI_SCALE_ANM2.popupSize.y - IMGUI_FOOTER_CHILD.size.y}, - self.flags = true -); +IMGUI_ITEM(IMGUI_SCALE_ANM2_OPTIONS_CHILD, self.label = "## Scale Anm2 Options Child", + self.size = {IMGUI_SCALE_ANM2.popupSize.x, IMGUI_SCALE_ANM2.popupSize.y - IMGUI_FOOTER_CHILD.size->y}, self.flags = true); -IMGUI_ITEM(IMGUI_SCALE_ANM2_VALUE, - self.label = "Value", - self.tooltip = "The size and position-related frame properties in the anm2 will be scaled by this value.", - self.value = 1, - self.step = 0.25, - self.stepFast = 1 -); +IMGUI_ITEM(IMGUI_SCALE_ANM2_VALUE, self.label = "Value", + self.tooltip = "The size and position-related frame properties in " + "the anm2 will be scaled by this value.", + self.value = 1, self.step = 0.25, self.stepFast = 1); -IMGUI_ITEM(IMGUI_SCALE_ANM2_SCALE, - self.label = "Scale", - self.tooltip = "Scale the anm2 with the value specified.", - self.snapshotAction = "Scale Anm2", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_SCALE_ANM2_SCALE, self.label = "Scale", self.tooltip = "Scale the anm2 with the value specified.", self.snapshotAction = "Scale Anm2", + self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION, - self.label = "&Render Animation", - self.tooltip = "Renders the current animation preview; output options can be customized.", - self.popup = "Render Animation", - self.popupSize = {500, 170}, - self.popupType = IMGUI_POPUP_CENTER_WINDOW -); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION, self.label = "&Render Animation", + self.tooltip = "Renders the current animation preview; output " + "options can be customized.", + self.popup = "Render Animation", self.popupSize = {500, 170}, self.popupType = IMGUI_POPUP_CENTER_WINDOW); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_CHILD, - self.label = "## Render Animation Child", - self.size = {IMGUI_RENDER_ANIMATION.popupSize.x, IMGUI_RENDER_ANIMATION.popupSize.y - IMGUI_FOOTER_CHILD.size.y}, - self.flags = true -); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_CHILD, self.label = "## Render Animation Child", + self.size = {IMGUI_RENDER_ANIMATION.popupSize.x, IMGUI_RENDER_ANIMATION.popupSize.y - IMGUI_FOOTER_CHILD.size->y}, self.flags = true); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FOOTER_CHILD, - self.label = "## Render Animation Footer Child", - self.size = {IMGUI_RENDER_ANIMATION.popupSize.x, IMGUI_FOOTER_CHILD.size.y}, - self.flags = true -); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FOOTER_CHILD, self.label = "## Render Animation Footer Child", + self.size = {IMGUI_RENDER_ANIMATION.popupSize.x, IMGUI_FOOTER_CHILD.size->y}, self.flags = true); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_LOCATION_BROWSE, - self.label = "## Location Browse", - self.tooltip = "Open file explorer to pick rendered animation location.", - self.atlas = ATLAS_FOLDER, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_LOCATION_BROWSE, self.label = "## Location Browse", self.tooltip = "Open file explorer to pick rendered animation location.", + self.atlas = ATLAS_FOLDER, self.isSameLine = true); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_LOCATION, - self.label = "Location", - self.tooltip = "Select the location of the rendered animation.\nFor PNG images, this should be a directory, otherwise, a filepath.", - self.max = 1024 -); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_LOCATION, self.label = "Location", + self.tooltip = "Select the location of the rendered animation.\nFor PNG " + "images, this should be a directory, otherwise, a filepath.", + self.max = 1024); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FFMPEG_BROWSE, - self.label = "## FFMpeg Browse", - self.tooltip = "Open file explorer to pick the path of FFmpeg", - self.atlas = ATLAS_FOLDER, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FFMPEG_BROWSE, self.label = "## FFMpeg Browse", self.tooltip = "Open file explorer to pick the path of FFmpeg", + self.atlas = ATLAS_FOLDER, self.isSameLine = true); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FFMPEG_PATH, - self.label = "FFmpeg Path", - self.tooltip = "Sets the path FFmpeg currently resides in.\nFFmpeg is required for rendering animations.\nDownload it from https://ffmpeg.org/, your package manager, or wherever else.", - self.max = 1024 -); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FFMPEG_PATH, self.label = "FFmpeg Path", + self.tooltip = "Sets the path FFmpeg currently resides in.\nFFmpeg is required " + "for rendering animations.\nDownload it from " + "https://ffmpeg.org/, your package manager, or wherever else.", + self.max = 1024); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_OUTPUT, - self.label = "Output", - self.tooltip = "Select the rendered animation output.\nIt can either be one animated image or a sequence of frames.", - self.items = {std::begin(RENDER_TYPE_STRINGS), std::end(RENDER_TYPE_STRINGS)}, - self.value = RENDER_PNG -); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_OUTPUT, self.label = "Output", + self.tooltip = "Select the rendered animation output.\nIt can either be " + "one animated image or a sequence of frames.", + self.items = {std::begin(RENDER_TYPE_STRINGS), std::end(RENDER_TYPE_STRINGS)}, self.value = RENDER_PNG); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FORMAT, - self.label = "Format", - self.tooltip = "(PNG images only).\nSet the format of each output frame; i.e., its filename.\nThe format will only take one argument; that being the frame's index.\nFor example, a format like \"{}.png\" will export a frame of index 0 as \"0.png\".", - self.max = UCHAR_MAX -); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FORMAT, self.label = "Format", + self.tooltip = "(PNG images only).\nSet the format of each output frame; i.e., " + "its filename.\nThe format will only take one argument; that " + "being the frame's index.\nFor example, a format like " + "\"{}.png\" will export a frame of index 0 as \"0.png\".", + self.max = UCHAR_MAX); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_IS_USE_ANIMATION_BOUNDS, - self.label = "Use Animation Bounds", - self.tooltip = "Instead of using the animation preview's bounds, the rendered animation will use the animation's bounds.\nNOTE: If you're looking to make a transparent animation, set the preview background to be transparent\nand toggle off other drawn things.", - self.value = SETTINGS_RENDER_IS_USE_ANIMATION_BOUNDS_DEFAULT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_IS_USE_ANIMATION_BOUNDS, self.label = "Use Animation Bounds", + self.tooltip = "Instead of using the animation preview's bounds, the rendered " + "animation will use the animation's bounds.\nNOTE: If you're looking " + "to make a transparent animation, set the preview background to be " + "transparent\nand toggle off other drawn things.", + self.value = SETTINGS_RENDER_IS_USE_ANIMATION_BOUNDS_DEFAULT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_SCALE, - self.label = "Scale", - self.tooltip = "Change the scale the animation will be rendered at.", - self.value = SETTINGS_RENDER_SCALE_DEFAULT, - self.size = {125, 0} -); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_SCALE, self.label = "Scale", self.tooltip = "Change the scale the animation will be rendered at.", + self.value = SETTINGS_RENDER_SCALE_DEFAULT, self.size = {125, 0}); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_CONFIRM, - self.label = "Render", - self.tooltip = "Render the animation, with the used settings.", - self.popup = "Rendering Animation...", - self.popupType = IMGUI_POPUP_CENTER_WINDOW, - self.popupSize = {300, 60}, - self.isSameLine = true, - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT -); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_CONFIRM, self.label = "Render", self.tooltip = "Render the animation, with the used settings.", + self.popup = "Rendering Animation...", self.popupType = IMGUI_POPUP_CENTER_WINDOW, self.popupSize = {300, 60}, self.isSameLine = true, + self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT); -IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_CHILD, - self.label = "##Rendering Child", - self.size = {400.0f, 65.0f}, - self.flags = true -); +IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_CHILD, self.label = "##Rendering Child", self.size = {400.0f, 65.0f}, self.flags = true); -IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_INFO, self.label = "Recording frames. Once done, the program may halt\nas FFmpeg renders the animation. Please be patient!"); -IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_CANCEL, - self.label = "Cancel", - self.tooltip = "Cancel rendering the animation.", - self.rowCount = 1 -); +IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_INFO, self.label = "Recording frames. Once done, the program may halt\nas " + "FFmpeg renders the animation. Please be patient!"); +IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_CANCEL, self.label = "Cancel", self.tooltip = "Cancel rendering the animation.", self.rowCount = 1); -IMGUI_ITEM(IMGUI_PLAYBACK, - self.label = "&Playback", - self.tooltip = "Opens the playback menu, for configuring playback settings.", - self.popup = "## Playback Popup", - self.popupType = IMGUI_POPUP_BY_ITEM, - self.isSizeToText = true, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_PLAYBACK, self.label = "&Playback", self.tooltip = "Opens the playback menu, for configuring playback settings.", + self.popup = "## Playback Popup", self.popupType = IMGUI_POPUP_BY_ITEM, self.isSizeToText = true, self.isSameLine = true); -IMGUI_ITEM(IMGUI_ALWAYS_LOOP, - self.label = "&Always Loop", - self.tooltip = "Sets the animation playback to always loop, regardless of the animation's loop setting.", - self.isSizeToText = true -); +IMGUI_ITEM(IMGUI_ALWAYS_LOOP, self.label = "&Always Loop", + self.tooltip = "Sets the animation playback to always loop, " + "regardless of the animation's loop setting.", + self.isSizeToText = true); -IMGUI_ITEM(IMGUI_CLAMP_PLAYHEAD, - self.label = "&Clamp Playhead", - self.tooltip = "The playhead (draggable icon on timeline) won't be able to exceed the animation length.", - self.isSizeToText = true -); +IMGUI_ITEM(IMGUI_CLAMP_PLAYHEAD, self.label = "&Clamp Playhead", + self.tooltip = "The playhead (draggable icon on timeline) won't be " + "able to exceed the animation length.", + self.isSizeToText = true); -IMGUI_ITEM(IMGUI_SETTINGS, - self.label = "&Settings", - self.tooltip = "Opens the setting menu, for configuring general program settings.", - self.popup = "## Settings Popup", - self.popupType = IMGUI_POPUP_BY_ITEM, - self.isSizeToText = true -); +IMGUI_ITEM(IMGUI_SETTINGS, self.label = "&Settings", self.tooltip = "Opens the setting menu, for configuring general program settings.", + self.popup = "## Settings Popup", self.popupType = IMGUI_POPUP_BY_ITEM, self.isSizeToText = true); -IMGUI_ITEM(IMGUI_VSYNC, - self.label = "&Vsync", - self.tooltip = "Toggle vertical sync; synchronizes program framerate with your monitor's refresh rate.", - self.isSizeToText = true, - self.isSeparator = true -); +IMGUI_ITEM(IMGUI_VSYNC, self.label = "&Vsync", + self.tooltip = "Toggle vertical sync; synchronizes program " + "framerate with your monitor's refresh rate.", + self.isSizeToText = true, self.isSeparator = true); -IMGUI_ITEM(IMGUI_HOTKEYS, - self.label = "&Hotkeys", - self.tooltip = "Change the program's hotkeys.", - self.popup = "Hotkeys", - self.popupSize = {500, 405}, - self.isSizeToText = true, - self.isSeparator = true -); +IMGUI_ITEM(IMGUI_HOTKEYS, self.label = "&Hotkeys", self.tooltip = "Change the program's hotkeys.", self.popup = "Hotkeys", self.popupSize = {500, 405}, + self.isSizeToText = true, self.isSeparator = true); -IMGUI_ITEM(IMGUI_HOTKEYS_CHILD, - self.label = "## Hotkeys Child", - self.size = {IMGUI_HOTKEYS.popupSize.x, IMGUI_HOTKEYS.popupSize.y - 35}, - self.flags = true -); +IMGUI_ITEM(IMGUI_HOTKEYS_CHILD, self.label = "## Hotkeys Child", self.size = {IMGUI_HOTKEYS.popupSize.x, IMGUI_HOTKEYS.popupSize.y - 35}, self.flags = true); #define IMGUI_HOTKEYS_FUNCTION "Function" #define IMGUI_HOTKEYS_HOTKEY "Hotkey" -IMGUI_ITEM(IMGUI_HOTKEYS_TABLE, - self.label = "## Hotkeys Table", - self.value = 2, - self.flags = ImGuiTableFlags_Borders -); +IMGUI_ITEM(IMGUI_HOTKEYS_TABLE, self.label = "## Hotkeys Table", self.value = 2, self.flags = ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY); -IMGUI_ITEM(IMGUI_HOTKEYS_OPTIONS_CHILD, - self.label = "## Merge Options Child", - self.size = {IMGUI_HOTKEYS.popupSize.x, 35}, - self.flags = true -); +IMGUI_ITEM(IMGUI_HOTKEYS_OPTIONS_CHILD, self.label = "## Merge Options Child", self.size = {IMGUI_HOTKEYS.popupSize.x, 35}, self.flags = true); -IMGUI_ITEM(IMGUI_HOTKEYS_CONFIRM, - self.label = "Confirm", - self.tooltip = "Use these hotkeys.", - self.rowCount = 1 -); +IMGUI_ITEM(IMGUI_HOTKEYS_CONFIRM, self.label = "Confirm", self.tooltip = "Use these hotkeys.", self.rowCount = 1); -IMGUI_ITEM(IMGUI_DEFAULT_SETTINGS, - self.label = "&Reset to Default Settings", - self.tooltip = "Reset the program's settings to their default state.", - self.isSizeToText = true -); +IMGUI_ITEM(IMGUI_DEFAULT_SETTINGS, self.label = "&Reset to Default Settings", self.tooltip = "Reset the program's settings to their default state.", + self.isSizeToText = true); -IMGUI_ITEM(IMGUI_LAYERS, - self.label = "Layers", - self.flags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_LAYERS, self.label = "Layers", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); IMGUI_ITEM(IMGUI_LAYERS_CHILD, self.label = "## Layers Child", self.flags = true); -IMGUI_ITEM(IMGUI_LAYER, - self.label = "## Layer Item", - self.dragDrop = "## Layer Drag Drop", - self.atlas = ATLAS_LAYER, - self.idOffset = 3000 -); +IMGUI_ITEM(IMGUI_LAYER, self.label = "## Layer Item", self.dragDrop = "## Layer Drag Drop", self.atlas = ATLAS_LAYER, self.isSizeToRegion = true, + self.idOffset = 3000); -IMGUI_ITEM(IMGUI_LAYER_SPRITESHEET_ID, - self.label = "## Spritesheet ID", - self.tooltip = "Change the spritesheet ID this layer uses.", - self.atlas = ATLAS_SPRITESHEET, - self.size = {50, 0} -); +IMGUI_ITEM(IMGUI_LAYER_SPRITESHEET_ID, self.label = "## Spritesheet ID", self.tooltip = "Change the spritesheet ID this layer uses.", + self.atlas = ATLAS_SPRITESHEET, self.size = {50, 0}); #define IMGUI_LAYERS_OPTIONS_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_LAYER_ADD, - self.label = "Add", - self.tooltip = "Adds a new layer.", - self.snapshotAction = "Add Layer", - self.rowCount = IMGUI_LAYERS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_LAYER_ADD, self.label = "Add", self.tooltip = "Adds a new layer.", self.snapshotAction = "Add Layer", + self.rowCount = IMGUI_LAYERS_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_LAYER_REMOVE, - self.label = "Remove", - self.tooltip = "Removes the selected layer.\nThis will remove all layer animations that use this layer from all animations.", - self.snapshotAction = "Remove Layer", - self.chord = ImGuiKey_Delete, - self.focusWindow = IMGUI_LAYERS.label, - self.rowCount = IMGUI_LAYERS_OPTIONS_ROW_COUNT -); +IMGUI_ITEM(IMGUI_LAYER_REMOVE, self.label = "Remove", + self.tooltip = "Removes the selected layer.\nThis will remove all layer " + "animations that use this layer from all animations.", + self.snapshotAction = "Remove Layer", self.chord = ImGuiKey_Delete, self.focusWindow = IMGUI_LAYERS.label, + self.rowCount = IMGUI_LAYERS_OPTIONS_ROW_COUNT); -IMGUI_ITEM(IMGUI_NULLS, - self.label = "Nulls", - self.flags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_NULLS, self.label = "Nulls", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); IMGUI_ITEM(IMGUI_NULLS_CHILD, self.label = "## Nulls Child", self.flags = true); -IMGUI_ITEM(IMGUI_NULL, - self.label = "## Null Item", - self.dragDrop = "## Null Drag Drop", - self.atlas = ATLAS_NULL, - self.idOffset = 4000 -); +IMGUI_ITEM(IMGUI_NULL, self.label = "## Null Item", self.dragDrop = "## Null Drag Drop", self.atlas = ATLAS_NULL, self.idOffset = 4000); #define IMGUI_NULLS_OPTIONS_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_NULL_ADD, - self.label = "Add", - self.tooltip = "Adds a null layer.", - self.snapshotAction = "Add Null", - self.rowCount = IMGUI_NULLS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_NULL_ADD, self.label = "Add", self.tooltip = "Adds a null layer.", self.snapshotAction = "Add Null", + self.rowCount = IMGUI_NULLS_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_NULL_REMOVE, - self.label = "Remove", - self.tooltip = "Removes the selected null.\nThis will remove all null animations that use this null from all animations.", - self.snapshotAction = "Remove Null", - self.chord = ImGuiKey_Delete, - self.focusWindow = IMGUI_NULLS.label, - self.rowCount = IMGUI_NULLS_OPTIONS_ROW_COUNT -); +IMGUI_ITEM(IMGUI_NULL_REMOVE, self.label = "Remove", + self.tooltip = "Removes the selected null.\nThis will remove all null " + "animations that use this null from all animations.", + self.snapshotAction = "Remove Null", self.chord = ImGuiKey_Delete, self.focusWindow = IMGUI_NULLS.label, + self.rowCount = IMGUI_NULLS_OPTIONS_ROW_COUNT); -IMGUI_ITEM(IMGUI_ANIMATIONS, - self.label = "Animations", - self.flags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_ANIMATIONS, self.label = "Animations", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); IMGUI_ITEM(IMGUI_ANIMATIONS_CHILD, self.label = "## Animations Child", self.flags = true); -IMGUI_ITEM(IMGUI_ANIMATION, - self.label = "## Animation Item", - self.dragDrop = "## Animation Drag Drop", - self.atlas = ATLAS_ANIMATION, - self.idOffset = 2000 -); +IMGUI_ITEM(IMGUI_ANIMATION, self.label = "## Animation Item", self.dragDrop = "## Animation Drag Drop", self.atlas = ATLAS_ANIMATION, + self.isSizeToRegion = true, self.idOffset = 2000); #define IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT 5 -IMGUI_ITEM(IMGUI_ANIMATION_ADD, - self.label = "Add", - self.tooltip = "Adds a new animation.", - self.snapshotAction = "Add Animation", - self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_ANIMATION_ADD, self.label = "Add", self.tooltip = "Adds a new animation.", self.snapshotAction = "Add Animation", + self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_ANIMATION_DUPLICATE, - self.label = "Duplicate", - self.tooltip = "Duplicates the selected animation, placing it after.", - self.snapshotAction = "Duplicate Animation", - self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_ANIMATION_DUPLICATE, self.label = "Duplicate", self.tooltip = "Duplicates the selected animation, placing it after.", + self.snapshotAction = "Duplicate Animation", self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_ANIMATION_MERGE, - self.label = "Merge", - self.tooltip = "Open the animation merge popup, to merge animations together.", - self.popup = "Merge Animations", - self.popupSize = {300, 400}, - self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_ANIMATION_MERGE, self.label = "Merge", self.tooltip = "Open the animation merge popup, to merge animations together.", + self.popup = "Merge Animations", self.popupSize = {300, 400}, self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_MERGE_ANIMATIONS_CHILD, - self.label = "## Merge Animations", - self.size = {IMGUI_ANIMATION_MERGE.popupSize.x, 250}, - self.flags = true -); +IMGUI_ITEM(IMGUI_MERGE_ANIMATIONS_CHILD, self.label = "## Merge Animations", self.size = {IMGUI_ANIMATION_MERGE.popupSize.x, 250}, self.flags = true); -IMGUI_ITEM(IMGUI_MERGE_ON_CONFLICT_CHILD, - self.label = "## Merge On Conflict Child", - self.size = {IMGUI_ANIMATION_MERGE.popupSize.x, 75}, - self.flags = true -); +IMGUI_ITEM(IMGUI_MERGE_ON_CONFLICT_CHILD, self.label = "## Merge On Conflict Child", self.size = {IMGUI_ANIMATION_MERGE.popupSize.x, 75}, self.flags = true); IMGUI_ITEM(IMGUI_MERGE_ON_CONFLICT, self.label = "On Conflict"); -IMGUI_ITEM(IMGUI_MERGE_APPEND_FRAMES, - self.label = "Append Frames ", - self.tooltip = "On frame conflict, the merged animation will have the selected animations' frames appended.", - self.value = ANM2_MERGE_APPEND, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_MERGE_APPEND_FRAMES, self.label = "Append Frames ", + self.tooltip = "On frame conflict, the merged animation will have " + "the selected animations' frames appended.", + self.value = ANM2_MERGE_APPEND, self.isSameLine = true); -IMGUI_ITEM(IMGUI_MERGE_REPLACE_FRAMES, - self.label = "Replace Frames", - self.tooltip = "On frame conflict, the merged animation will have the latest selected animations' frames.", - self.value = ANM2_MERGE_REPLACE -); +IMGUI_ITEM(IMGUI_MERGE_REPLACE_FRAMES, self.label = "Replace Frames", + self.tooltip = "On frame conflict, the merged animation will have " + "the latest selected animations' frames.", + self.value = ANM2_MERGE_REPLACE); -IMGUI_ITEM(IMGUI_MERGE_PREPEND_FRAMES, - self.label = "Prepend Frames", - self.tooltip = "On frame conflict, the merged animation will have the selected animations' frames prepended.", - self.value = ANM2_MERGE_PREPEND, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_MERGE_PREPEND_FRAMES, self.label = "Prepend Frames", + self.tooltip = "On frame conflict, the merged animation will have " + "the selected animations' frames prepended.", + self.value = ANM2_MERGE_PREPEND, self.isSameLine = true); -IMGUI_ITEM(IMGUI_MERGE_IGNORE, - self.label = "Ignore ", - self.tooltip = "On frame conflict, the merged animation will ignore the other selected animations' frames.", - self.value = ANM2_MERGE_IGNORE -); +IMGUI_ITEM(IMGUI_MERGE_IGNORE, self.label = "Ignore ", + self.tooltip = "On frame conflict, the merged animation will ignore " + "the other selected animations' frames.", + self.value = ANM2_MERGE_IGNORE); -IMGUI_ITEM(IMGUI_MERGE_OPTIONS_CHILD, - self.label = "## Merge Options Child", - self.size = {IMGUI_ANIMATION_MERGE.popupSize.x, 35}, - self.flags = true -); +IMGUI_ITEM(IMGUI_MERGE_OPTIONS_CHILD, self.label = "## Merge Options Child", self.size = {IMGUI_ANIMATION_MERGE.popupSize.x, 35}, self.flags = true); -IMGUI_ITEM(IMGUI_MERGE_DELETE_ANIMATIONS_AFTER, - self.label = "Delete Animations After Merging", - self.tooltip = "After merging, the selected animations (besides the original) will be deleted." -); +IMGUI_ITEM(IMGUI_MERGE_DELETE_ANIMATIONS_AFTER, self.label = "Delete Animations After Merging", + self.tooltip = "After merging, the selected animations (besides the " + "original) will be deleted."); -IMGUI_ITEM(IMGUI_MERGE_CONFIRM, - self.label = "Merge", - self.tooltip = "Merge the selected animations with the options set.", - self.snapshotAction = "Merge Animations", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_MERGE_CONFIRM, self.label = "Merge", self.tooltip = "Merge the selected animations with the options set.", + self.snapshotAction = "Merge Animations", self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_ANIMATION_REMOVE, - self.label = "Remove", - self.tooltip = "Remove the selected animation.", - self.snapshotAction = "Remove Animation", - self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, - self.chord = ImGuiKey_Delete, - self.focusWindow = IMGUI_ANIMATIONS.label, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_ANIMATION_REMOVE, self.label = "Remove", self.tooltip = "Remove the selected animation.", self.snapshotAction = "Remove Animation", + self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, self.chord = ImGuiKey_Delete, self.focusWindow = IMGUI_ANIMATIONS.label, self.isSameLine = true); -IMGUI_ITEM(IMGUI_ANIMATION_DEFAULT, - self.label = "Default", - self.tooltip = "Set the selected animation as the default one.", - self.snapshotAction = "Default Animation", - self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_ANIMATION_DEFAULT, self.label = "Default", self.tooltip = "Set the selected animation as the default one.", + self.snapshotAction = "Default Animation", self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_EVENTS, - self.label = "Events", - self.flags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_EVENTS, self.label = "Events", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); IMGUI_ITEM(IMGUI_EVENTS_CHILD, self.label = "## Events Child", self.flags = true); -IMGUI_ITEM(IMGUI_EVENT, - self.label = "## Event", - self.atlas = ATLAS_EVENT, - self.idOffset = 1000 -); +IMGUI_ITEM(IMGUI_EVENT, self.label = "## Event", self.atlas = ATLAS_EVENT, self.idOffset = 1000); #define IMGUI_EVENTS_OPTIONS_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_EVENTS_ADD, - self.label = "Add", - self.tooltip = "Adds a new event.", - self.snapshotAction = "Add Event", - self.rowCount = IMGUI_EVENTS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_EVENTS_ADD, self.label = "Add", self.tooltip = "Adds a new event.", self.snapshotAction = "Add Event", + self.rowCount = IMGUI_EVENTS_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_EVENTS_REMOVE_UNUSED, - self.label = "Remove Unused", - self.tooltip = "Removes all unused events (i.e., not being used in any triggers in any animation).", - self.snapshotAction = "Remove Unused Events", - self.rowCount = IMGUI_EVENTS_OPTIONS_ROW_COUNT -); +IMGUI_ITEM(IMGUI_EVENTS_REMOVE_UNUSED, self.label = "Remove Unused", + self.tooltip = "Removes all unused events (i.e., not being used in " + "any triggers in any animation).", + self.snapshotAction = "Remove Unused Events", self.rowCount = IMGUI_EVENTS_OPTIONS_ROW_COUNT); -IMGUI_ITEM(IMGUI_SPRITESHEETS, - self.label = "Spritesheets", - self.flags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); +// Spritesheets +IMGUI_ITEM(IMGUI_SPRITESHEET_PREVIEW, self.label = "## Spritesheet Preview", self.size = {65, 65}); +IMGUI_ITEM(IMGUI_SPRITESHEETS, self.label = "Spritesheets", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); +IMGUI_ITEM(IMGUI_SPRITESHEETS_CHILD, self.label = "## Spritesheets Child", self.flags = true, self.itemSpacing = vec2(), self.windowPadding = vec2()); +IMGUI_ITEM(IMGUI_SPRITESHEET_CHILD, self.label = "## Spritesheet Child", self.flags = true, self.itemSpacing = vec2(), self.windowPadding = vec2()); +IMGUI_ITEM(IMGUI_SPRITESHEET, self.label = "## Spritesheet", self.dragDrop = "## Spritesheet Drag Drop"); +IMGUI_ITEM(IMGUI_SPRITESHEET_TEXT, self.label = "## Spritesheet Text", self.atlas = ATLAS_SPRITESHEET, self.itemSpacing = vec2(8, 0)); -IMGUI_ITEM(IMGUI_SPRITESHEETS_CHILD, self.label = "## Spritesheets Child", self.flags = true); - -IMGUI_ITEM(IMGUI_SPRITESHEET_CHILD, - self.label = "## Spritesheet Child", - self.rowCount = 1, - self.size = {0, IMGUI_SPRITESHEET_PREVIEW_SIZE.y + 40}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_SPRITESHEET_SELECTED, self.label = "## Spritesheet Selected", self.isSameLine = true); - -IMGUI_ITEM(IMGUI_SPRITESHEET, - self.label = "## Spritesheet", - self.dragDrop = "## Spritesheet Drag Drop", - self.atlas = ATLAS_SPRITESHEET, - self.isSizeToText = true -); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_FOOTER_CHILD, - self.label = "## Spritesheets Footer Child", - self.size = {0, 60}, - self.flags = true -); +IMGUI_ITEM(IMGUI_SPRITESHEETS_FOOTER_CHILD, self.label = "## Spritesheets Footer Child", self.size = {0, IMGUI_FOOTER_CHILD.size->y * 1.66f}, + self.flags = true); #define IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT 4 #define IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT 3 -IMGUI_ITEM(IMGUI_SPRITESHEET_ADD, - self.label = "Add", - self.tooltip = "Select a .png image to add as a spritesheet.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_SPRITESHEET_ADD, self.label = "Add", self.tooltip = "Select a .png image to add as a spritesheet.", + self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_SPRITESHEETS_RELOAD, - self.label = "Reload", - self.tooltip = "Reload the selected spritesheet(s).", - self.snapshotAction = "Reload Spritesheet(s)", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_SPRITESHEETS_RELOAD, self.label = "Reload", self.tooltip = "Reload the selected spritesheet(s).", + self.snapshotAction = "Reload Spritesheet(s)", self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_SPRITESHEETS_REPLACE, - self.label = "Replace", - self.tooltip = "Replace the highlighted spritesheet with another.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_SPRITESHEETS_REPLACE, self.label = "Replace", self.tooltip = "Replace the highlighted spritesheet with another.", + self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_SPRITESHEETS_REMOVE_UNUSED, - self.label = "Remove Unused", - self.tooltip = "Remove all unused spritesheets in the anm2 (i.e., no layer in any animation uses the spritesheet).", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT -); +IMGUI_ITEM(IMGUI_SPRITESHEETS_REMOVE_UNUSED, self.label = "Remove Unused", + self.tooltip = "Remove all unused spritesheets in the anm2 (i.e., " + "the spritesheet isn't used in any layer animations).", + self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT); -IMGUI_ITEM(IMGUI_SPRITESHEETS_SELECT_ALL, - self.label = "Select All", - self.tooltip = "Select all spritesheets.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_SPRITESHEETS_SELECT_ALL, self.label = "Select All", self.tooltip = "Select all spritesheets.", self.chord = ImGuiMod_Ctrl + ImGuiKey_A, + self.focusWindow = IMGUI_SPRITESHEETS.label, self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_SPRITESHEETS_SELECT_NONE, - self.label = "Select None", - self.tooltip = "Unselect all spritesheets.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_SPRITESHEETS_SELECT_NONE, self.label = "Select None", self.tooltip = "Unselect all spritesheets.", self.chord = ImGuiKey_Escape, + self.focusWindow = IMGUI_SPRITESHEETS.label, self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_SPRITESHEET_SAVE, - self.label = "Save", - self.tooltip = "Save the selected spritesheets to their original locations.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT -); +IMGUI_ITEM(IMGUI_SPRITESHEET_SAVE, self.label = "Save", self.tooltip = "Save the selected spritesheets to their original locations.", + self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT); const ImVec2 IMGUI_CANVAS_CHILD_SIZE = {230, 85}; -IMGUI_ITEM(IMGUI_CANVAS_GRID_CHILD, - self.label = "## Canvas Grid Child", - self.size = IMGUI_CANVAS_CHILD_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_CANVAS_GRID_CHILD, self.label = "## Canvas Grid Child", self.size = IMGUI_CANVAS_CHILD_SIZE, self.flags = true, + self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_CANVAS_GRID, - self.label = "Grid", - self.tooltip = "Toggles the visiblity of the canvas' grid." -); +IMGUI_ITEM(IMGUI_CANVAS_GRID, self.label = "Grid", self.tooltip = "Toggles the visiblity of the canvas' grid."); -IMGUI_ITEM(IMGUI_CANVAS_GRID_SNAP, - self.label = "Snap", - self.tooltip = "Using the crop tool will snap the points to the nearest grid point." -); +IMGUI_ITEM(IMGUI_CANVAS_GRID_SNAP, self.label = "Snap", self.tooltip = "Using the crop tool will snap the points to the nearest grid point."); -IMGUI_ITEM(IMGUI_CANVAS_GRID_COLOR, - self.label = "Color", - self.tooltip = "Change the color of the canvas' grid.", - self.flags = ImGuiColorEditFlags_NoInputs -); +IMGUI_ITEM(IMGUI_CANVAS_GRID_COLOR, self.label = "Color", self.tooltip = "Change the color of the canvas' grid.", self.flags = ImGuiColorEditFlags_NoInputs); -IMGUI_ITEM(IMGUI_CANVAS_GRID_SIZE, - self.label = "Size", - self.tooltip = "Change the size of the canvas' grid.", - self.min = CANVAS_GRID_MIN, - self.max = CANVAS_GRID_MAX, - self.value = CANVAS_GRID_DEFAULT -); +IMGUI_ITEM(IMGUI_CANVAS_GRID_SIZE, self.label = "Size", self.tooltip = "Change the size of the canvas' grid.", self.min = CANVAS_GRID_MIN, + self.max = CANVAS_GRID_MAX, self.value = CANVAS_GRID_DEFAULT); -IMGUI_ITEM(IMGUI_CANVAS_GRID_OFFSET, - self.label = "Offset", - self.tooltip = "Change the offset of the canvas' grid, in pixels." -); +IMGUI_ITEM(IMGUI_CANVAS_GRID_OFFSET, self.label = "Offset", self.tooltip = "Change the offset of the canvas' grid, in pixels."); -IMGUI_ITEM(IMGUI_CANVAS_VIEW_CHILD, - self.label = "## View Child", - self.size = IMGUI_CANVAS_CHILD_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_CANVAS_VIEW_CHILD, self.label = "## View Child", self.size = IMGUI_CANVAS_CHILD_SIZE, self.flags = true, + self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_CANVAS_ZOOM, - self.label = "Zoom", - self.tooltip = "Change the zoom of the canvas.", - self.min = CANVAS_ZOOM_MIN, - self.max = CANVAS_ZOOM_MAX, - self.speed = 1.0f, - self.value = CANVAS_ZOOM_DEFAULT -); +IMGUI_ITEM(IMGUI_CANVAS_ZOOM, self.label = "Zoom", self.tooltip = "Change the zoom of the canvas.", self.min = CANVAS_ZOOM_MIN, self.max = CANVAS_ZOOM_MAX, + self.speed = 1.0f, self.value = CANVAS_ZOOM_DEFAULT); -IMGUI_ITEM(IMGUI_CANVAS_VISUAL_CHILD, - self.label = "## Animation Preview Visual Child", - self.size = IMGUI_CANVAS_CHILD_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_CANVAS_VISUAL_CHILD, self.label = "## Animation Preview Visual Child", self.size = IMGUI_CANVAS_CHILD_SIZE, self.flags = true, + self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_CANVAS_BACKGROUND_COLOR, - self.label = "Background Color", - self.tooltip = "Change the background color of the canvas.", - self.flags = ImGuiColorEditFlags_NoInputs -); +IMGUI_ITEM(IMGUI_CANVAS_BACKGROUND_COLOR, self.label = "Background Color", self.tooltip = "Change the background color of the canvas.", + self.flags = ImGuiColorEditFlags_NoInputs); -IMGUI_ITEM(IMGUI_CANVAS_ANIMATION_OVERLAY, - self.label = "Overlay", - self.tooltip = "Choose an animation to overlay over the previewed animation, for reference." -); +IMGUI_ITEM(IMGUI_CANVAS_ANIMATION_OVERLAY, self.label = "Overlay", + self.tooltip = "Choose an animation to overlay over the previewed " + "animation, for reference."); -IMGUI_ITEM(IMGUI_CANVAS_ANIMATION_OVERLAY_TRANSPARENCY, - self.label = "Alpha", - self.tooltip = "Set the transparency of the animation overlay.", - self.value = SETTINGS_PREVIEW_OVERLAY_TRANSPARENCY_DEFAULT, - self.max = UCHAR_MAX -); +IMGUI_ITEM(IMGUI_CANVAS_ANIMATION_OVERLAY_TRANSPARENCY, self.label = "Alpha", self.tooltip = "Set the transparency of the animation overlay.", + self.value = SETTINGS_PREVIEW_OVERLAY_TRANSPARENCY_DEFAULT, self.max = UCHAR_MAX); -IMGUI_ITEM(IMGUI_CANVAS_HELPER_CHILD, - self.label = "## Animation Preview Helper Child", - self.size = IMGUI_CANVAS_CHILD_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_CANVAS_HELPER_CHILD, self.label = "## Animation Preview Helper Child", self.size = IMGUI_CANVAS_CHILD_SIZE, self.flags = true, + self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_CANVAS_AXES, - self.label = "Axes", - self.tooltip = "Toggle the display of the X/Y axes." -); +IMGUI_ITEM(IMGUI_CANVAS_AXES, self.label = "Axes", self.tooltip = "Toggle the display of the X/Y axes."); -IMGUI_ITEM(IMGUI_CANVAS_AXES_COLOR, - self.label = "Color", - self.tooltip = "Change the color of the axes.", - self.flags = ImGuiColorEditFlags_NoInputs -); +IMGUI_ITEM(IMGUI_CANVAS_AXES_COLOR, self.label = "Color", self.tooltip = "Change the color of the axes.", self.flags = ImGuiColorEditFlags_NoInputs); -IMGUI_ITEM(IMGUI_CANVAS_ROOT_TRANSFORM, - self.label = "Root Transform", - self.tooltip = "Toggles the root frames's attributes transforming the other items in an animation.", - self.value = SETTINGS_PREVIEW_IS_ROOT_TRANSFORM_DEFAULT -); +IMGUI_ITEM(IMGUI_CANVAS_ROOT_TRANSFORM, self.label = "Root Transform", + self.tooltip = "Toggles the root frames's attributes transforming " + "the other items in an animation.", + self.value = SETTINGS_PREVIEW_IS_ROOT_TRANSFORM_DEFAULT); -IMGUI_ITEM(IMGUI_CANVAS_TRIGGERS, - self.label = "Triggers", - self.tooltip = "Toggles activated triggers drawing their event name.", - self.value = SETTINGS_PREVIEW_IS_TRIGGERS_DEFAULT -); +IMGUI_ITEM(IMGUI_CANVAS_TRIGGERS, self.label = "Triggers", self.tooltip = "Toggles activated triggers drawing their event name.", + self.value = SETTINGS_PREVIEW_IS_TRIGGERS_DEFAULT); -IMGUI_ITEM(IMGUI_CANVAS_PIVOTS, - self.label = "Pivots", - self.tooltip = "Toggles drawing each layer's pivot.", - self.value = SETTINGS_PREVIEW_IS_PIVOTS_DEFAULT -); +IMGUI_ITEM(IMGUI_CANVAS_PIVOTS, self.label = "Pivots", self.tooltip = "Toggles drawing each layer's pivot.", self.value = SETTINGS_PREVIEW_IS_PIVOTS_DEFAULT); -IMGUI_ITEM(IMGUI_CANVAS_ICONS, - self.label = "Icons", - self.tooltip = "Toggles drawing the the colored root/null icons.", - self.value = SETTINGS_PREVIEW_IS_ICONS_DEFAULT -); +IMGUI_ITEM(IMGUI_CANVAS_ICONS, self.label = "Icons", self.tooltip = "Toggles drawing the the colored root/null icons.", + self.value = SETTINGS_PREVIEW_IS_ICONS_DEFAULT); -IMGUI_ITEM(IMGUI_CANVAS_ALT_ICONS, - self.label = "Alt Icons", - self.tooltip = "Toggles the use of alternate icons for the targets (the colored root/null icons).", - self.value = SETTINGS_PREVIEW_IS_ALT_ICONS_DEFAULT -); +IMGUI_ITEM(IMGUI_CANVAS_ALT_ICONS, self.label = "Alt Icons", + self.tooltip = "Toggles the use of alternate icons for the targets " + "(the colored root/null icons).", + self.value = SETTINGS_PREVIEW_IS_ALT_ICONS_DEFAULT); -IMGUI_ITEM(IMGUI_CANVAS_BORDER, - self.label = "Border", - self.tooltip = "Toggles the appearance of a border around the items.", - self.value = SETTINGS_PREVIEW_IS_BORDER_DEFAULT -); +IMGUI_ITEM(IMGUI_CANVAS_BORDER, self.label = "Border", self.tooltip = "Toggles the appearance of a border around the items.", + self.value = SETTINGS_PREVIEW_IS_BORDER_DEFAULT); -IMGUI_ITEM(IMGUI_ANIMATION_PREVIEW, - self.label = "Animation Preview", - self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_ANIMATION_PREVIEW, self.label = "Animation Preview", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); #define IMGUI_ANIMATION_PREVIEW_VIEW_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_ANIMATION_PREVIEW_CENTER_VIEW, - self.label = "Center View", - self.tooltip = "Centers the current view on the animation preview.", - self.hotkey = HOTKEY_CENTER_VIEW, - self.focusWindow = IMGUI_ANIMATION_PREVIEW.label, - self.rowCount = IMGUI_ANIMATION_PREVIEW_VIEW_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_ANIMATION_PREVIEW_CENTER_VIEW, self.label = "Center View", self.tooltip = "Centers the current view on the animation preview.", + self.hotkey = HOTKEY_CENTER_VIEW, self.focusWindow = IMGUI_ANIMATION_PREVIEW.label, self.rowCount = IMGUI_ANIMATION_PREVIEW_VIEW_ROW_COUNT, + self.isSameLine = true); -IMGUI_ITEM(IMGUI_ANIMATION_PREVIEW_FIT, - self.label = "Fit", - self.tooltip = "Adjust the view/pan based on the size of the animation, to fit the canvas' size.", - self.hotkey = HOTKEY_FIT, - self.focusWindow = IMGUI_ANIMATION_PREVIEW.label, - self.rowCount = IMGUI_ANIMATION_PREVIEW_VIEW_ROW_COUNT -); +IMGUI_ITEM(IMGUI_ANIMATION_PREVIEW_FIT, self.label = "Fit", + self.tooltip = "Adjust the view/pan based on the size of the " + "animation, to fit the canvas' size.", + self.hotkey = HOTKEY_FIT, self.focusWindow = IMGUI_ANIMATION_PREVIEW.label, self.rowCount = IMGUI_ANIMATION_PREVIEW_VIEW_ROW_COUNT); -IMGUI_ITEM(IMGUI_SPRITESHEET_EDITOR, - self.label = "Spritesheet Editor", - self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_SPRITESHEET_EDITOR, self.label = "Spritesheet Editor", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); #define IMGUI_SPRITESHEET_EDITOR_VIEW_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_SPRITESHEET_EDITOR_CENTER_VIEW, - self.label = "Center View", - self.tooltip = "Centers the current view on the spritesheet editor.", - self.hotkey = HOTKEY_CENTER_VIEW, - self.focusWindow = IMGUI_SPRITESHEET_EDITOR.label, - self.rowCount = IMGUI_SPRITESHEET_EDITOR_VIEW_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_SPRITESHEET_EDITOR_CENTER_VIEW, self.label = "Center View", self.tooltip = "Centers the current view on the spritesheet editor.", + self.hotkey = HOTKEY_CENTER_VIEW, self.focusWindow = IMGUI_SPRITESHEET_EDITOR.label, self.rowCount = IMGUI_SPRITESHEET_EDITOR_VIEW_ROW_COUNT, + self.isSameLine = true); -IMGUI_ITEM(IMGUI_SPRITESHEET_EDITOR_FIT, - self.label = "Fit", - self.tooltip = "Adjust the view/pan based on the size of the spritesheet, to fit the canvas' size.", - self.hotkey = HOTKEY_FIT, - self.focusWindow = IMGUI_SPRITESHEET_EDITOR.label, - self.rowCount = IMGUI_SPRITESHEET_EDITOR_VIEW_ROW_COUNT -); +IMGUI_ITEM(IMGUI_SPRITESHEET_EDITOR_FIT, self.label = "Fit", + self.tooltip = "Adjust the view/pan based on the size of the " + "spritesheet, to fit the canvas' size.", + self.hotkey = HOTKEY_FIT, self.focusWindow = IMGUI_SPRITESHEET_EDITOR.label, self.rowCount = IMGUI_SPRITESHEET_EDITOR_VIEW_ROW_COUNT); IMGUI_ITEM(IMGUI_FRAME_PROPERTIES, self.label = "Frame Properties"); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_POSITION, - self.label = "Position", - self.tooltip = "Change the position of the selected frame.", - self.snapshotAction = "Frame Position", - self.isUseItemActivated = true -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_POSITION, self.label = "Position", self.tooltip = "Change the position of the selected frame.", + self.snapshotAction = "Frame Position", self.isUseItemActivated = true); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_CROP, - self.label = "Crop", - self.tooltip = "Change the crop position of the selected frame.", - self.snapshotAction = "Frame Crop", - self.isUseItemActivated = true -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_CROP, self.label = "Crop", self.tooltip = "Change the crop position of the selected frame.", + self.snapshotAction = "Frame Crop", self.isUseItemActivated = true); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_SIZE, - self.label = "Size", - self.tooltip = "Change the size of the crop of the selected frame.", - self.snapshotAction = "Frame Size", - self.isUseItemActivated = true -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_SIZE, self.label = "Size", self.tooltip = "Change the size of the crop of the selected frame.", + self.snapshotAction = "Frame Size", self.isUseItemActivated = true); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_PIVOT, - self.label = "Pivot", - self.tooltip = "Change the pivot of the selected frame.", - self.snapshotAction = "Frame Pivot", - self.isUseItemActivated = true -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_PIVOT, self.label = "Pivot", self.tooltip = "Change the pivot of the selected frame.", self.snapshotAction = "Frame Pivot", + self.isUseItemActivated = true); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_SCALE, - self.label = "Scale", - self.tooltip = "Change the scale of the selected frame.", - self.snapshotAction = "Frame Scale", - self.isUseItemActivated = true -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_SCALE, self.label = "Scale", self.tooltip = "Change the scale of the selected frame.", self.snapshotAction = "Frame Scale", + self.isUseItemActivated = true); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_ROTATION, - self.label = "Rotation", - self.tooltip = "Change the rotation of the selected frame.", - self.snapshotAction = "Frame Rotation", - self.isUseItemActivated = true -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_ROTATION, self.label = "Rotation", self.tooltip = "Change the rotation of the selected frame.", + self.snapshotAction = "Frame Rotation", self.isUseItemActivated = true); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_DELAY, - self.label = "Duration", - self.tooltip = "Change the duration of the selected frame.", - self.snapshotAction = "Frame Duration", - self.isUseItemActivated = true, - self.min = ANM2_FRAME_NUM_MIN, - self.max = ANM2_FRAME_NUM_MAX, - self.value = ANM2_FRAME_NUM_MIN -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_DELAY, self.label = "Duration", self.tooltip = "Change the duration of the selected frame.", + self.snapshotAction = "Frame Duration", self.isUseItemActivated = true, self.min = ANM2_FRAME_NUM_MIN, self.max = ANM2_FRAME_NUM_MAX, + self.value = ANM2_FRAME_NUM_MIN); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_TINT, - self.label = "Tint", - self.tooltip = "Change the tint of the selected frame.", - self.snapshotAction = "Frame Tint", - self.isUseItemActivated = true, - self.value = 1 -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_TINT, self.label = "Tint", self.tooltip = "Change the tint of the selected frame.", self.snapshotAction = "Frame Tint", + self.isUseItemActivated = true, self.value = 1); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_COLOR_OFFSET, - self.label = "Color Offset", - self.tooltip = "Change the color offset of the selected frame.", - self.snapshotAction = "Frame Color Offset", - self.isUseItemActivated = true, - self.value = 0 -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_COLOR_OFFSET, self.label = "Color Offset", self.tooltip = "Change the color offset of the selected frame.", + self.snapshotAction = "Frame Color Offset", self.isUseItemActivated = true, self.value = 0); #define IMGUI_FRAME_PROPERTIES_FLIP_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_FLIP_X, - self.label = "Flip X", - self.tooltip = "Change the sign of the X scale, to cheat flipping the layer horizontally.\n(Anm2 doesn't support flipping directly.)", - self.snapshotAction = "Frame Flip X", - self.rowCount = IMGUI_FRAME_PROPERTIES_FLIP_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_FLIP_X, self.label = "Flip X", + self.tooltip = "Change the sign of the X scale, to cheat flipping the layer " + "horizontally.\n(Anm2 doesn't support flipping directly.)", + self.snapshotAction = "Frame Flip X", self.rowCount = IMGUI_FRAME_PROPERTIES_FLIP_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_FLIP_Y, - self.label = "Flip Y", - self.tooltip = "Change the sign of the Y scale, to cheat flipping the layer vertically.\n(Anm2 doesn't support flipping directly.)", - self.snapshotAction = "Frame Flip Y", - self.rowCount = IMGUI_FRAME_PROPERTIES_FLIP_ROW_COUNT -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_FLIP_Y, self.label = "Flip Y", + self.tooltip = "Change the sign of the Y scale, to cheat flipping the layer " + "vertically.\n(Anm2 doesn't support flipping directly.)", + self.snapshotAction = "Frame Flip Y", self.rowCount = IMGUI_FRAME_PROPERTIES_FLIP_ROW_COUNT); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_VISIBLE, - self.label = "Visible", - self.tooltip = "Toggles the visibility of the selected frame.", - self.snapshotAction = "Frame Visibility", - self.isSameLine = true, - self.value = true -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_VISIBLE, self.label = "Visible", self.tooltip = "Toggles the visibility of the selected frame.", + self.snapshotAction = "Frame Visibility", self.isSameLine = true, self.value = true); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_INTERPOLATED, - self.label = "Interpolation", - self.tooltip = "Toggles the interpolation of the selected frame.", - self.snapshotAction = "Frame Interpolation", - self.isSameLine = true, - self.value = true -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_INTERPOLATED, self.label = "Interpolation", self.tooltip = "Toggles the interpolation of the selected frame.", + self.snapshotAction = "Frame Interpolation", self.isSameLine = true, self.value = true); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_ROUND, - self.label = "Round", - self.tooltip = "Values will be rounded to the nearest integer.", - self.value = SETTINGS_PROPERTIES_IS_ROUND_DEFAULT -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_ROUND, self.label = "Round", self.tooltip = "Values will be rounded to the nearest integer.", + self.value = SETTINGS_PROPERTIES_IS_ROUND_DEFAULT); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_EVENT, - self.label = "Event", - self.tooltip = "Change the event the trigger uses.", - self.snapshotAction = "Trigger Event" -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_EVENT, self.label = "Event", self.tooltip = "Change the event the trigger uses.", self.snapshotAction = "Trigger Event"); -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_AT_FRAME, - self.label = "At Frame", - self.tooltip = "Change the frame where the trigger occurs.", - self.snapshotAction = "Trigger At Frame" -); +IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_AT_FRAME, self.label = "At Frame", self.tooltip = "Change the frame where the trigger occurs.", + self.snapshotAction = "Trigger At Frame"); IMGUI_ITEM(IMGUI_TOOLS, self.label = "Tools"); -IMGUI_ITEM(IMGUI_TOOL_PAN, - self.label = "## Pan", - self.tooltip = "Use the pan tool.\nWill shift the view as the cursor is dragged.\nYou can also use the middle mouse button to pan at any time.", - self.function = imgui_tool_pan_set, - self.hotkey = HOTKEY_PAN, - self.atlas = ATLAS_PAN -); +IMGUI_ITEM(IMGUI_TOOL_PAN, self.label = "## Pan", + self.tooltip = "Use the pan tool.\nWill shift the view as the cursor is dragged.\nYou " + "can also use the middle mouse button to pan at any time.", + self.function = imgui_tool_pan_set, self.hotkey = HOTKEY_PAN, self.atlas = ATLAS_PAN); -IMGUI_ITEM(IMGUI_TOOL_MOVE, - self.label = "## Move", - self.tooltip = "Use the move tool.\nWhen in animation preview, will move the position of the frame.\nWhen in spritesheet editor, will move the pivot instead.\nUse mouse or directional keys to change the value.", - self.function = imgui_tool_move_set, - self.hotkey = HOTKEY_MOVE, - self.atlas = ATLAS_MOVE -); +IMGUI_ITEM(IMGUI_TOOL_MOVE, self.label = "## Move", + self.tooltip = "Use the move tool.\nAnimation Preview: Will move the position " + "of the frame." + "\nSpritesheet Editor: Will move the pivot, and holding right " + "click will use the Crop functionality instead." + "\nUse mouse or directional keys to change the value.", + self.function = imgui_tool_move_set, self.hotkey = HOTKEY_MOVE, self.atlas = ATLAS_MOVE); -IMGUI_ITEM(IMGUI_TOOL_ROTATE, - self.label = "## Rotate", - self.tooltip = "Use the rotate tool.\nWill rotate the selected item as the cursor is dragged, or directional keys are pressed.\n(Animation Preview only.)", - self.function = imgui_tool_rotate_set, - self.hotkey = HOTKEY_ROTATE, - self.atlas = ATLAS_ROTATE -); +IMGUI_ITEM(IMGUI_TOOL_ROTATE, self.label = "## Rotate", + self.tooltip = "Use the rotate tool.\nWill rotate the selected item as the cursor is " + "dragged, or directional keys are pressed.\n(Animation Preview only.)", + self.function = imgui_tool_rotate_set, self.hotkey = HOTKEY_ROTATE, self.atlas = ATLAS_ROTATE); -IMGUI_ITEM(IMGUI_TOOL_SCALE, - self.label = "## Scale", - self.tooltip = "Use the scale tool.\nWill scale the selected item as the cursor is dragged, or directional keys are pressed.\n(Animation Preview only.)", - self.function = imgui_tool_scale_set, - self.hotkey = HOTKEY_SCALE, - self.atlas = ATLAS_SCALE -); +IMGUI_ITEM(IMGUI_TOOL_SCALE, self.label = "## Scale", + self.tooltip = "Use the scale tool.\nWill scale the selected item as the cursor is " + "dragged, or directional keys are pressed.\n(Animation Preview only.)", + self.function = imgui_tool_scale_set, self.hotkey = HOTKEY_SCALE, self.atlas = ATLAS_SCALE); -IMGUI_ITEM(IMGUI_TOOL_CROP, - self.label = "## Crop", - self.tooltip = "Use the crop tool.\nWill produce a crop rectangle based on how the cursor is dragged.\nAlternatively, you can use the arrow keys and Ctrl/Shift to move the size/position, respectively.\n(Spritesheet Editor only.)", - self.function = imgui_tool_crop_set, - self.hotkey = HOTKEY_CROP, - self.atlas = ATLAS_CROP -); +IMGUI_ITEM(IMGUI_TOOL_CROP, self.label = "## Crop", + self.tooltip = "Use the crop tool.\nWill produce a crop rectangle based on how " + "the cursor is dragged." + "\nAlternatively, you can use the arrow keys and Ctrl/Shift to " + "move the size/position, respectively." + "\nHolding right click will use the Move tool's functionality." + "\n(Spritesheet Editor only.)", + self.function = imgui_tool_crop_set, self.hotkey = HOTKEY_CROP, self.atlas = ATLAS_CROP); -IMGUI_ITEM(IMGUI_TOOL_DRAW, - self.label = "## Draw", - self.tooltip = "Draws pixels onto the selected spritesheet, with the current color.\n(Spritesheet Editor only.)", - self.function = imgui_tool_draw_set, - self.hotkey = HOTKEY_DRAW, - self.atlas = ATLAS_DRAW -); +IMGUI_ITEM(IMGUI_TOOL_DRAW, self.label = "## Draw", + self.tooltip = "Draws pixels onto the selected spritesheet, with " + "the current color.\n(Spritesheet Editor only.)", + self.function = imgui_tool_draw_set, self.hotkey = HOTKEY_DRAW, self.atlas = ATLAS_DRAW); -IMGUI_ITEM(IMGUI_TOOL_ERASE, - self.label = "## Erase", - self.tooltip = "Erases pixels from the selected spritesheet.\n(Spritesheet Editor only.)", - self.function = imgui_tool_erase_set, - self.hotkey = HOTKEY_ERASE, - self.atlas = ATLAS_ERASE -); +IMGUI_ITEM(IMGUI_TOOL_ERASE, self.label = "## Erase", + self.tooltip = "Erases pixels from the selected " + "spritesheet.\n(Spritesheet Editor only.)", + self.function = imgui_tool_erase_set, self.hotkey = HOTKEY_ERASE, self.atlas = ATLAS_ERASE); -IMGUI_ITEM(IMGUI_TOOL_COLOR_PICKER, - self.label = "## Color Picker", - self.tooltip = "Selects a color from the canvas, to be used for drawing.\n(Spritesheet Editor only).", - self.function = imgui_tool_color_picker_set, - self.hotkey = HOTKEY_COLOR_PICKER, - self.atlas = ATLAS_COLOR_PICKER -); +IMGUI_ITEM(IMGUI_TOOL_COLOR_PICKER, self.label = "## Color Picker", + self.tooltip = "Selects a color from the canvas, to be used for " + "drawing.\n(Spritesheet Editor only).", + self.function = imgui_tool_color_picker_set, self.hotkey = HOTKEY_COLOR_PICKER, self.atlas = ATLAS_COLOR_PICKER); -IMGUI_ITEM(IMGUI_TOOL_UNDO, - self.label = "## Undo", - self.tooltip = "Undo the last action.", - self.function = imgui_undo, - self.hotkey = HOTKEY_UNDO, - self.atlas = ATLAS_UNDO -); +IMGUI_ITEM(IMGUI_TOOL_UNDO, self.label = "## Undo", self.tooltip = "Undo the last action.", self.function = imgui_undo, self.hotkey = HOTKEY_UNDO, + self.atlas = ATLAS_UNDO); -IMGUI_ITEM(IMGUI_TOOL_REDO, - self.label = "## Redo", - self.tooltip = "Redo the last action.", - self.function = imgui_redo, - self.hotkey = HOTKEY_REDO, - self.atlas = ATLAS_REDO -); +IMGUI_ITEM(IMGUI_TOOL_REDO, self.label = "## Redo", self.tooltip = "Redo the last action.", self.function = imgui_redo, self.hotkey = HOTKEY_REDO, + self.atlas = ATLAS_REDO); -IMGUI_ITEM(IMGUI_TOOL_COLOR, - self.label = "## Color", - self.tooltip = "Set the color, to be used by the draw tool.", - self.flags = ImGuiColorEditFlags_NoInputs -); +IMGUI_ITEM(IMGUI_TOOL_COLOR, self.label = "## Color", self.tooltip = "Set the color, to be used by the draw tool.", self.flags = ImGuiColorEditFlags_NoInputs); -const inline ImguiItem* IMGUI_TOOL_ITEMS[TOOL_COUNT] = -{ - &IMGUI_TOOL_PAN, - &IMGUI_TOOL_MOVE, - &IMGUI_TOOL_ROTATE, - &IMGUI_TOOL_SCALE, - &IMGUI_TOOL_CROP, - &IMGUI_TOOL_DRAW, - &IMGUI_TOOL_ERASE, - &IMGUI_TOOL_COLOR_PICKER, - &IMGUI_TOOL_UNDO, - &IMGUI_TOOL_REDO, - &IMGUI_TOOL_COLOR -}; +const inline ImguiItem* IMGUI_TOOL_ITEMS[TOOL_COUNT] = {&IMGUI_TOOL_PAN, &IMGUI_TOOL_MOVE, &IMGUI_TOOL_ROTATE, &IMGUI_TOOL_SCALE, + &IMGUI_TOOL_CROP, &IMGUI_TOOL_DRAW, &IMGUI_TOOL_ERASE, &IMGUI_TOOL_COLOR_PICKER, + &IMGUI_TOOL_UNDO, &IMGUI_TOOL_REDO, &IMGUI_TOOL_COLOR}; IMGUI_ITEM(IMGUI_COLOR_PICKER_BUTTON, self.label = "## Color Picker Button"); -IMGUI_ITEM(IMGUI_TIMELINE, - self.label = "Timeline", - self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_TIMELINE, self.label = "Timeline", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_TIMELINE_CHILD, - self.label = "## Timeline Child", - self.flags = true -); +IMGUI_ITEM(IMGUI_TIMELINE_CHILD, self.label = "## Timeline Child", self.flags = true); -IMGUI_ITEM(IMGUI_TIMELINE_HEADER_CHILD, - self.label = "## Timeline Header Child", - self.size = {0, IMGUI_TIMELINE_FRAME_SIZE.y}, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_TIMELINE_HEADER_CHILD, self.label = "## Timeline Header Child", self.size = {0, IMGUI_TIMELINE_FRAME_SIZE.y}, + self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_PLAYHEAD, - self.label = "## Playhead", - self.flags = ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoBackground | - ImGuiWindowFlags_NoInputs -); +IMGUI_ITEM(IMGUI_PLAYHEAD, self.label = "## Playhead", + self.flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground | + ImGuiWindowFlags_NoInputs); -IMGUI_ITEM(IMGUI_TIMELINE_ITEMS_CHILD, - self.label = "## Timeline Items", - self.size = {IMGUI_TIMELINE_ITEM_SIZE.x, 0}, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEMS_CHILD, self.label = "## Timeline Items", self.size = {IMGUI_TIMELINE_ITEM_SIZE.x, 0}, + self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_CHILD, - self.label = "## Timeline Item Child", - self.size = IMGUI_TIMELINE_ITEM_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_CHILD, self.label = "## Timeline Item Child", self.size = IMGUI_TIMELINE_ITEM_SIZE, self.flags = true, + self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_ROOT_CHILD, - self.label = "## Root Item Child", - self.color = {{0.045f, 0.08f, 0.11f, 1.0f}}, - self.size = IMGUI_TIMELINE_ITEM_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_ROOT_CHILD, self.label = "## Root Item Child", self.color.normal = {0.045f, 0.08f, 0.11f, 1.0f}, + self.size = IMGUI_TIMELINE_ITEM_SIZE, self.flags = true, self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_LAYER_CHILD, - self.label = "## Layer Item Child", - self.color = {{0.0875f, 0.05f, 0.015f, 1.0f}}, - self.size = IMGUI_TIMELINE_ITEM_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_LAYER_CHILD, self.label = "## Layer Item Child", self.color.normal = {0.0875f, 0.05f, 0.015f, 1.0f}, + self.size = IMGUI_TIMELINE_ITEM_SIZE, self.flags = true, self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_NULL_CHILD, - self.label = "## Null Item Child", - self.color = {{0.055f, 0.10f, 0.055f, 1.0f}}, - self.size = IMGUI_TIMELINE_ITEM_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_NULL_CHILD, self.label = "## Null Item Child", self.color.normal = {0.055f, 0.10f, 0.055f, 1.0f}, + self.size = IMGUI_TIMELINE_ITEM_SIZE, self.flags = true, self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_TRIGGERS_CHILD, - self.label = "## Triggers Item Child", - self.color = {{0.10f, 0.0375f, 0.07f, 1.0f}}, - self.size = IMGUI_TIMELINE_ITEM_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_TRIGGERS_CHILD, self.label = "## Triggers Item Child", self.color.normal = {0.10f, 0.0375f, 0.07f, 1.0f}, + self.size = IMGUI_TIMELINE_ITEM_SIZE, self.flags = true, self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -const inline ImguiItem* IMGUI_TIMELINE_ITEM_CHILDS[ANM2_COUNT] -{ - &IMGUI_TIMELINE_ITEM_CHILD, - &IMGUI_TIMELINE_ITEM_ROOT_CHILD, - &IMGUI_TIMELINE_ITEM_LAYER_CHILD, - &IMGUI_TIMELINE_ITEM_NULL_CHILD, - &IMGUI_TIMELINE_ITEM_TRIGGERS_CHILD -}; +const inline ImguiItem* IMGUI_TIMELINE_ITEM_CHILDS[ANM2_COUNT]{&IMGUI_TIMELINE_ITEM_CHILD, &IMGUI_TIMELINE_ITEM_ROOT_CHILD, &IMGUI_TIMELINE_ITEM_LAYER_CHILD, + &IMGUI_TIMELINE_ITEM_NULL_CHILD, &IMGUI_TIMELINE_ITEM_TRIGGERS_CHILD}; #define IMGUI_POPUP_ITEM_PROPERTIES "Item Properties" #define IMGUI_POPUP_ITEM_PROPERTIES_TYPE IMGUI_POPUP_CENTER_WINDOW const ImVec2 IMGUI_POPUP_ITEM_PROPERTIES_SIZE = {300, 350}; -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, - self.label = "## Item Properties Type Child", - self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 35}, - self.flags = true -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, self.label = "## Item Properties Type Child", self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 35}, + self.flags = true); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER, - self.label = "Layer", - self.tooltip = "The item will be a layer item.\nA layer item is a primary graphical item, using a spritesheet.", - self.isSizeToText = true, - self.value = ANM2_LAYER, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER, self.label = "Layer", + self.tooltip = "The item will be a layer item.\nA layer item is a " + "primary graphical item, using a spritesheet.", + self.isSizeToText = true, self.value = ANM2_LAYER, self.isSameLine = true); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL, - self.label = "Null", - self.tooltip = "The item will be a null item.\nA null item is an invisible item, often accessed by a game engine.", - self.isSizeToText = true, - self.value = ANM2_NULL -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL, self.label = "Null", + self.tooltip = "The item will be a null item.\nA null item is an " + "invisible item, often accessed by a game engine.", + self.isSizeToText = true, self.value = ANM2_NULL); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, - self.label = "## Item Properties Items", - self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 250}, - self.flags = true -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, self.label = "## Item Properties Items", self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 250}, + self.flags = true); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD, - self.label = "## Item Properties Options Child", - self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 35}, - self.flags = true -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD, self.label = "## Item Properties Options Child", self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 35}, + self.flags = true); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_CONFIRM, - self.label = "Confirm", - self.tooltip = "Set the timeline item's properties.", - self.snapshotAction = "Timeline Item Change", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_CONFIRM, self.label = "Confirm", self.tooltip = "Set the timeline item's properties.", + self.snapshotAction = "Timeline Item Change", self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_SELECTABLE, - self.label = "## Selectable", - self.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_SELECTABLE, self.label = "## Selectable", self.size = IMGUI_TIMELINE_ITEM_SIZE); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_ROOT_SELECTABLE, - self.label = "Root", - self.tooltip = "The root item of an animation.\nChanging its properties will transform the rest of the animation.", - self.atlas = ATLAS_ROOT, - self.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_ROOT_SELECTABLE, self.label = "Root", + self.tooltip = "The root item of an animation.\nChanging its properties " + "will transform the rest of the animation.", + self.size = IMGUI_TIMELINE_ITEM_SIZE); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_LAYER_SELECTABLE, - self.label = "## Layer Selectable", - self.tooltip = "A layer item.\nA graphical item within the animation.", - self.dragDrop = "## Layer Drag Drop", - self.popup = IMGUI_POPUP_ITEM_PROPERTIES, - self.popupType = IMGUI_POPUP_ITEM_PROPERTIES_TYPE, - self.atlas = ATLAS_LAYER, - self.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_LAYER_SELECTABLE, self.label = "## Layer Selectable", self.tooltip = "A layer item.\nA graphical item within the animation.", + self.dragDrop = "## Layer Drag Drop", self.color.active = {0.45f, 0.18f, 0.07f, 1.0f}, self.popup = IMGUI_POPUP_ITEM_PROPERTIES, + self.popupType = IMGUI_POPUP_ITEM_PROPERTIES_TYPE, self.size = IMGUI_TIMELINE_ITEM_SIZE); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_NULL_SELECTABLE, - self.label = "## Null Selectable", - self.tooltip = "A null item.\nAn invisible item within the animation that is accessible via a game engine.", - self.dragDrop = "## Null Drag Drop", - self.popup = IMGUI_POPUP_ITEM_PROPERTIES, - self.popupType = IMGUI_POPUP_ITEM_PROPERTIES_TYPE, - self.atlas = ATLAS_NULL, - self.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_NULL_SELECTABLE, self.label = "## Null Selectable", + self.tooltip = "A null item.\nAn invisible item within the " + "animation that is accessible via a game engine.", + self.dragDrop = "## Null Drag Drop", self.popup = IMGUI_POPUP_ITEM_PROPERTIES, self.popupType = IMGUI_POPUP_ITEM_PROPERTIES_TYPE, + self.size = IMGUI_TIMELINE_ITEM_SIZE); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_TRIGGERS_SELECTABLE, - self.label = "Triggers", - self.tooltip = "The animation's triggers.\nWill fire based on an event.", - self.atlas = ATLAS_TRIGGERS, - self.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_TRIGGERS_SELECTABLE, self.label = "Triggers", self.tooltip = "The animation's triggers.\nWill fire based on an event.", + self.size = IMGUI_TIMELINE_ITEM_SIZE); -const inline ImguiItem* IMGUI_TIMELINE_ITEM_SELECTABLES[ANM2_COUNT] -{ - &IMGUI_TIMELINE_ITEM_SELECTABLE, - &IMGUI_TIMELINE_ITEM_ROOT_SELECTABLE, - &IMGUI_TIMELINE_ITEM_LAYER_SELECTABLE, - &IMGUI_TIMELINE_ITEM_NULL_SELECTABLE, - &IMGUI_TIMELINE_ITEM_TRIGGERS_SELECTABLE -}; +const inline ImguiItem* IMGUI_TIMELINE_ITEM_SELECTABLES[ANM2_COUNT]{&IMGUI_TIMELINE_ITEM_SELECTABLE, &IMGUI_TIMELINE_ITEM_ROOT_SELECTABLE, + &IMGUI_TIMELINE_ITEM_LAYER_SELECTABLE, &IMGUI_TIMELINE_ITEM_NULL_SELECTABLE, + &IMGUI_TIMELINE_ITEM_TRIGGERS_SELECTABLE}; -IMGUI_ITEM(IMGUI_TIMELINE_SHOW_UNUSED, - self.label = "## Show Unused", - self.tooltip = "Layers/nulls without any frames will be hidden.", - self.snapshotAction = "Hide Unused", - self.atlas = ATLAS_SHOW_UNUSED -); +IMGUI_ITEM(IMGUI_TIMELINE_SHOW_UNUSED, self.label = "## Show Unused", self.tooltip = "Layers/nulls without any frames will be hidden.", + self.snapshotAction = "Hide Unused", self.atlas = ATLAS_SHOW_UNUSED); -IMGUI_ITEM(IMGUI_TIMELINE_HIDE_UNUSED, - self.label = "## Hide Unused", - self.tooltip = "Layers/nulls without any frames will be shown.", - self.snapshotAction = "Show Unused", - self.atlas = ATLAS_HIDE_UNUSED -); +IMGUI_ITEM(IMGUI_TIMELINE_HIDE_UNUSED, self.label = "## Hide Unused", self.tooltip = "Layers/nulls without any frames will be shown.", + self.snapshotAction = "Show Unused", self.atlas = ATLAS_HIDE_UNUSED); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_VISIBLE, - self.label = "## Visible", - self.tooltip = "The item is visible.\nPress to set to invisible.", - self.snapshotAction = "Item Invisible", - self.atlas = ATLAS_VISIBLE -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_VISIBLE, self.label = "## Visible", self.tooltip = "The item is visible.\nPress to set to invisible.", + self.snapshotAction = "Item Invisible", self.atlas = ATLAS_VISIBLE); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_INVISIBLE, - self.label = "## Invisible", - self.tooltip = "The item is invisible.\nPress to set to visible.", - self.snapshotAction = "Item Visible", - self.atlas = ATLAS_INVISIBLE -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_INVISIBLE, self.label = "## Invisible", self.tooltip = "The item is invisible.\nPress to set to visible.", + self.snapshotAction = "Item Visible", self.atlas = ATLAS_INVISIBLE); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_SHOW_RECT, - self.label = "## Show Rect", - self.tooltip = "The rect is shown.\nPress to hide rect.", - self.snapshotAction = "Hide Rect", - self.atlas = ATLAS_SHOW_RECT -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_SHOW_RECT, self.label = "## Show Rect", self.tooltip = "The rect is shown.\nPress to hide rect.", + self.snapshotAction = "Hide Rect", self.atlas = ATLAS_SHOW_RECT); -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_HIDE_RECT, - self.label = "## Hide Rect", - self.tooltip = "The rect is hidden.\nPress to show rect.", - self.snapshotAction = "Show Rect", - self.atlas = ATLAS_HIDE_RECT -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_HIDE_RECT, self.label = "## Hide Rect", self.tooltip = "The rect is hidden.\nPress to show rect.", + self.snapshotAction = "Show Rect", self.atlas = ATLAS_HIDE_RECT); +IMGUI_ITEM(IMGUI_TIMELINE_FRAMES_CHILD, self.label = "## Timeline Frames Child", + self.windowFlags = ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_HorizontalScrollbar); -IMGUI_ITEM(IMGUI_TIMELINE_FRAMES_CHILD, - self.label = "## Timeline Frames Child", - self.windowFlags = ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_HorizontalScrollbar -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_FRAMES_CHILD, - self.label = "## Timeline Item Frames Child", - self.size = {0, IMGUI_TIMELINE_FRAME_SIZE.y} -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_FRAMES_CHILD, self.label = "## Timeline Item Frames Child", self.size = {0, IMGUI_TIMELINE_FRAME_SIZE.y}); IMGUI_ITEM(IMGUI_TIMELINE_FRAME, self.label = "## Frame"); #define IMGUI_TIMELINE_FRAME_BORDER 5 static const vec4 IMGUI_FRAME_BORDER_COLOR = {1.0f, 1.0f, 1.0f, 0.25f}; -IMGUI_ITEM(IMGUI_TIMELINE_ROOT_FRAME, - self.label = "## Root Frame", - self.snapshotAction = "Root Frame", - self.color = {{0.14f, 0.27f, 0.39f, 1.0f}, {0.28f, 0.54f, 0.78f, 1.0f}, {0.36f, 0.70f, 0.95f, 1.0f}, IMGUI_FRAME_BORDER_COLOR}, - self.size = IMGUI_TIMELINE_FRAME_SIZE, - self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, - self.border = IMGUI_FRAME_BORDER -); +IMGUI_ITEM(IMGUI_TIMELINE_ROOT_FRAME, self.label = "## Root Frame", self.snapshotAction = "Root Frame", + self.color = {vec4(0.14f, 0.27f, 0.39f, 1.0f), vec4(0.28f, 0.54f, 0.78f, 1.0f), vec4(0.36f, 0.70f, 0.95f, 1.0f), IMGUI_FRAME_BORDER_COLOR}, + self.size = IMGUI_TIMELINE_FRAME_SIZE, self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, self.border = IMGUI_FRAME_BORDER); -IMGUI_ITEM(IMGUI_TIMELINE_LAYER_FRAME, - self.label = "## Layer Frame", - self.dragDrop = "## Layer Frame Drag Drop", - self.snapshotAction = "Layer Frame", - self.color = {{0.45f, 0.18f, 0.07f, 1.0f}, {0.78f, 0.32f, 0.12f, 1.0f}, {0.95f, 0.40f, 0.15f, 1.0f}, IMGUI_FRAME_BORDER_COLOR}, - self.size = IMGUI_TIMELINE_FRAME_SIZE, - self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, - self.border = IMGUI_FRAME_BORDER -); +IMGUI_ITEM(IMGUI_TIMELINE_LAYER_FRAME, self.label = "## Layer Frame", self.dragDrop = "## Layer Frame Drag Drop", self.snapshotAction = "Layer Frame", + self.color = {vec4(0.45f, 0.18f, 0.07f, 1.0f), vec4(0.78f, 0.32f, 0.12f, 1.0f), vec4(0.95f, 0.40f, 0.15f, 1.0f), IMGUI_FRAME_BORDER_COLOR}, + self.size = IMGUI_TIMELINE_FRAME_SIZE, self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, self.border = IMGUI_FRAME_BORDER); -IMGUI_ITEM(IMGUI_TIMELINE_NULL_FRAME, - self.label = "## Null Frame", - self.dragDrop = "## Null Frame Drag Drop", - self.snapshotAction = "Null Frame", - self.color = {{0.17f, 0.33f, 0.17f, 1.0f}, {0.34f, 0.68f, 0.34f, 1.0f}, {0.44f, 0.88f, 0.44f, 1.0f}, IMGUI_FRAME_BORDER_COLOR}, - self.size = IMGUI_TIMELINE_FRAME_SIZE, - self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, - self.border = IMGUI_FRAME_BORDER -); +IMGUI_ITEM(IMGUI_TIMELINE_NULL_FRAME, self.label = "## Null Frame", self.dragDrop = "## Null Frame Drag Drop", self.snapshotAction = "Null Frame", + self.color = {vec4(0.17f, 0.33f, 0.17f, 1.0f), vec4(0.34f, 0.68f, 0.34f, 1.0f), vec4(0.44f, 0.88f, 0.44f, 1.0f), IMGUI_FRAME_BORDER_COLOR}, + self.size = IMGUI_TIMELINE_FRAME_SIZE, self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, self.border = IMGUI_FRAME_BORDER); -IMGUI_ITEM(IMGUI_TIMELINE_TRIGGERS_FRAME, - self.label = "## Triggers Frame", - self.snapshotAction = "Trigger", - self.color = {{0.36f, 0.14f, 0.24f, 1.0f}, {0.72f, 0.28f, 0.48f, 1.0f}, {0.92f, 0.36f, 0.60f, 1.0f}, IMGUI_FRAME_BORDER_COLOR}, - self.size = IMGUI_TIMELINE_FRAME_SIZE, - self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, - self.border = IMGUI_FRAME_BORDER -); +IMGUI_ITEM(IMGUI_TIMELINE_TRIGGERS_FRAME, self.label = "## Triggers Frame", self.snapshotAction = "Trigger", + self.color = {vec4(0.36f, 0.14f, 0.24f, 1.0f), vec4(0.72f, 0.28f, 0.48f, 1.0f), vec4(0.92f, 0.36f, 0.60f, 1.0f), IMGUI_FRAME_BORDER_COLOR}, + self.size = IMGUI_TIMELINE_FRAME_SIZE, self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, self.border = IMGUI_FRAME_BORDER); -const inline ImguiItem* IMGUI_TIMELINE_FRAMES[ANM2_COUNT] -{ - &IMGUI_TIMELINE_FRAME, - &IMGUI_TIMELINE_ROOT_FRAME, - &IMGUI_TIMELINE_LAYER_FRAME, - &IMGUI_TIMELINE_NULL_FRAME, - &IMGUI_TIMELINE_TRIGGERS_FRAME -}; +const inline ImguiItem* IMGUI_TIMELINE_FRAMES[ANM2_COUNT]{&IMGUI_TIMELINE_FRAME, &IMGUI_TIMELINE_ROOT_FRAME, &IMGUI_TIMELINE_LAYER_FRAME, + &IMGUI_TIMELINE_NULL_FRAME, &IMGUI_TIMELINE_TRIGGERS_FRAME}; -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_FOOTER_CHILD, - self.label = "## Item Footer Child", - self.size = {IMGUI_TIMELINE_ITEM_CHILD.size.x, IMGUI_FOOTER_CHILD.size.y}, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); -IMGUI_ITEM(IMGUI_TIMELINE_OPTIONS_FOOTER_CHILD, - self.label = "## Options Footer Child", - self.size = {0, IMGUI_FOOTER_CHILD.size.y}, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); +IMGUI_ITEM(IMGUI_TIMELINE_ITEM_FOOTER_CHILD, self.label = "## Item Footer Child", self.size = {IMGUI_TIMELINE_ITEM_CHILD.size->x, IMGUI_FOOTER_CHILD.size->y}, + self.flags = true, self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); +IMGUI_ITEM(IMGUI_TIMELINE_OPTIONS_FOOTER_CHILD, self.label = "## Options Footer Child", self.size = {0, IMGUI_FOOTER_CHILD.size->y}, self.flags = true, + self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); #define IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT 2 -IMGUI_ITEM(IMGUI_TIMELINE_ADD_ITEM, - self.label = "Add", - self.tooltip = "Adds an item (layer or null) to the animation.\nMake sure to add a Layer/Null first in the Layers or Nulls windows.", - self.popup = "Add Item", - self.popupType = IMGUI_POPUP_ITEM_PROPERTIES_TYPE, - self.popupSize = {300, 350}, - self.rowCount = IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_TIMELINE_ADD_ITEM, self.label = "Add", + self.tooltip = "Adds an item (layer or null) to the animation.\nMake sure " + "to add a Layer/Null first in the Layers or Nulls windows.", + self.popup = "Add Item", self.popupType = IMGUI_POPUP_ITEM_PROPERTIES_TYPE, self.popupSize = {300, 350}, + self.rowCount = IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT, self.isSameLine = true); - - -IMGUI_ITEM(IMGUI_TIMELINE_REMOVE_ITEM, - self.label = "Remove", - self.tooltip = "Removes the selected item (layer or null) from the animation.", - self.snapshotAction = "Remove Item", - self.chord = ImGuiKey_Delete, - self.focusWindow = IMGUI_TIMELINE_ITEMS_CHILD.label, - self.rowCount = IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT -); +IMGUI_ITEM(IMGUI_TIMELINE_REMOVE_ITEM, self.label = "Remove", self.tooltip = "Removes the selected item (layer or null) from the animation.", + self.snapshotAction = "Remove Item", self.chord = ImGuiKey_Delete, self.focusWindow = IMGUI_TIMELINE_ITEMS_CHILD.label, + self.rowCount = IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT); #define IMGUI_TIMELINE_OPTIONS_ROW_COUNT 10 -IMGUI_ITEM(IMGUI_PLAY, - self.label = "|> Play", - self.tooltip = "Play the current animation, if paused.", - self.focusWindow = IMGUI_TIMELINE.label, - self.hotkey = HOTKEY_PLAY_PAUSE, - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_PLAY, self.label = "|> Play", self.tooltip = "Play the current animation, if paused.", self.focusWindow = IMGUI_TIMELINE.label, + self.hotkey = HOTKEY_PLAY_PAUSE, self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_PAUSE, - self.label = "|| Pause", - self.tooltip = "Pause the current animation, if playing.", - self.focusWindow = IMGUI_TIMELINE.label, - self.hotkey = HOTKEY_PLAY_PAUSE, - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_PAUSE, self.label = "|| Pause", self.tooltip = "Pause the current animation, if playing.", self.focusWindow = IMGUI_TIMELINE.label, + self.hotkey = HOTKEY_PLAY_PAUSE, self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_ADD_FRAME, - self.label = "+ Insert Frame", - self.tooltip = "Inserts a frame in the selected animation item, based on the preview time.", - self.snapshotAction = "Insert Frame", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_INSERT_FRAME, self.label = "+ Insert Frame", + self.tooltip = "Inserts a frame in the selected animation item, " + "based on the preview time.", + self.snapshotAction = "Insert Frame", self.hotkey = HOTKEY_INSERT_FRAME, self.focusWindow = IMGUI_TIMELINE.label, + self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_REMOVE_FRAME, - self.label = "- Delete Frame", - self.tooltip = "Removes the selected frame from the selected animation item.", - self.snapshotAction = "Delete Frame", - self.focusWindow = IMGUI_TIMELINE.label, - self.chord = ImGuiKey_Delete, - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_REMOVE_FRAME, self.label = "- Delete Frame", self.tooltip = "Removes the selected frame from the selected animation item.", + self.snapshotAction = "Delete Frame", self.focusWindow = IMGUI_TIMELINE.label, self.chord = ImGuiKey_Delete, + self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_BAKE, - self.label = "Bake", - self.tooltip = "Opens the bake popup menu, if a frame is selected.\nBaking a frame takes the currently interpolated values at the time between it and the next frame and separates them based on the interval.", - self.popup = "Bake Frames", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.popupSize = {260, 145}, - self.isSameLine = true -); +static inline void imgui_shorten_frame(Imgui* self) { + if (self->reference->itemType == ANM2_TRIGGER) + return; + if (Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *self->reference)) + frame->delay = std::max(ANM2_FRAME_DELAY_MIN, frame->delay - 1); +} -IMGUI_ITEM(IMGUI_BAKE_CHILD, - self.label = "## Bake Child", - self.flags = true -); +IMGUI_ITEM(IMGUI_SHORTEN_FRAME, self.label = "## Shorten Frame", self.snapshotAction = "Shorten Frame", self.hotkey = HOTKEY_SHORTEN_FRAME, + self.function = imgui_shorten_frame); -IMGUI_ITEM(IMGUI_BAKE_INTERVAL, - self.label = "Interval", - self.tooltip = "Sets the delay of the baked frames the selected frame will be separated out into.", - self.min = ANM2_FRAME_DELAY_MIN, - self.value = ANM2_FRAME_DELAY_MIN -); +static inline void imgui_extend_frame(Imgui* self) { + if (self->reference->itemType == ANM2_TRIGGER) + return; + if (Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *self->reference)) + frame->delay++; +} -IMGUI_ITEM(IMGUI_BAKE_ROUND_SCALE, - self.label = "Round Scale", - self.tooltip = "The scale of the baked frames will be rounded to the nearest integer.", - self.value = true -); +IMGUI_ITEM(IMGUI_EXTEND_FRAME, self.label = "## Extend Frame", self.snapshotAction = "Extend Frame", self.hotkey = HOTKEY_EXTEND_FRAME, + self.function = imgui_extend_frame); -IMGUI_ITEM(IMGUI_BAKE_ROUND_ROTATION, - self.label = "Round Rotation", - self.tooltip = "The rotation of the baked frames will be rounded to the nearest integer.", - self.value = true, - self.isSeparator = true -); +static inline void imgui_next_frame(Imgui* self) { + if (Anm2Item* item = anm2_item_from_reference(self->anm2, *self->reference)) { + self->reference->frameIndex = std::min((int)(item->frames.size() - 1), self->reference->frameIndex + 1); + self->preview->time = anm2_time_from_reference(self->anm2, *self->reference); + } +} -IMGUI_ITEM(IMGUI_BAKE_CONFIRM, - self.label = "Bake", - self.tooltip = "Bake the selected frame with the options selected.", - self.snapshotAction = "Bake Frames", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_NEXT_FRAME, self.label = "## Next Frame", self.hotkey = HOTKEY_NEXT_FRAME, self.function = imgui_next_frame); -IMGUI_ITEM(IMGUI_FIT_ANIMATION_LENGTH, - self.label = "Fit Animation Length", - self.tooltip = "Sets the animation's length to the latest frame.", - self.snapshotAction = "Fit Animation Length", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.isSameLine = true -); +static inline void imgui_previous_frame(Imgui* self) { + if (anm2_item_from_reference(self->anm2, *self->reference)) { + self->reference->frameIndex = std::max(0, self->reference->frameIndex - 1); + self->preview->time = anm2_time_from_reference(self->anm2, *self->reference); + } +} -IMGUI_ITEM(IMGUI_ANIMATION_LENGTH, - self.label = "Length", - self.tooltip = "Sets the animation length.\n(Will not change frames.)", - self.snapshotAction = "Set Animation Length", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.min = ANM2_FRAME_NUM_MIN, - self.max = ANM2_FRAME_NUM_MAX, - self.value = ANM2_FRAME_NUM_MIN, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_PREVIOUS_FRAME, self.label = "## Previous Frame", self.hotkey = HOTKEY_PREVIOUS_FRAME, self.function = imgui_previous_frame); -IMGUI_ITEM(IMGUI_FPS, - self.label = "FPS", - self.tooltip = "Sets the animation's frames per second (its speed).", - self.snapshotAction = "Set FPS", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.min = ANM2_FPS_MIN, - self.max = ANM2_FPS_MAX, - self.value = ANM2_FPS_DEFAULT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_BAKE, self.label = "Bake", + self.tooltip = "Opens the bake popup menu, if a frame is selected.\nBaking a frame " + "takes the currently interpolated values at the time between it and " + "the next frame and separates them based on the interval.", + self.popup = "Bake Frames", self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.popupSize = {260, 145}, self.isSameLine = true); -IMGUI_ITEM(IMGUI_LOOP, - self.label = "Loop", - self.tooltip = "Toggles the animation looping.", - self.snapshotAction = "Set Loop", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.value = true, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_BAKE_CHILD, self.label = "## Bake Child", self.flags = true); -IMGUI_ITEM(IMGUI_CREATED_BY, - self.label = "Author", - self.tooltip = "Sets the author of the animation.", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.max = UCHAR_MAX -); +IMGUI_ITEM(IMGUI_BAKE_INTERVAL, self.label = "Interval", + self.tooltip = "Sets the delay of the baked frames the selected " + "frame will be separated out into.", + self.min = ANM2_FRAME_DELAY_MIN, self.value = ANM2_FRAME_DELAY_MIN); + +IMGUI_ITEM(IMGUI_BAKE_ROUND_SCALE, self.label = "Round Scale", self.tooltip = "The scale of the baked frames will be rounded to the nearest integer.", + self.value = true); + +IMGUI_ITEM(IMGUI_BAKE_ROUND_ROTATION, self.label = "Round Rotation", + self.tooltip = "The rotation of the baked frames will be rounded to " + "the nearest integer.", + self.value = true, self.isSeparator = true); + +IMGUI_ITEM(IMGUI_BAKE_CONFIRM, self.label = "Bake", self.tooltip = "Bake the selected frame with the options selected.", self.snapshotAction = "Bake Frames", + self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, self.isSameLine = true); + +IMGUI_ITEM(IMGUI_FIT_ANIMATION_LENGTH, self.label = "Fit Animation Length", self.tooltip = "Sets the animation's length to the latest frame.", + self.snapshotAction = "Fit Animation Length", self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.isSameLine = true); + +IMGUI_ITEM(IMGUI_ANIMATION_LENGTH, self.label = "Length", self.tooltip = "Sets the animation length.\n(Will not change frames.)", + self.snapshotAction = "Set Animation Length", self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.min = ANM2_FRAME_NUM_MIN, + self.max = ANM2_FRAME_NUM_MAX, self.value = ANM2_FRAME_NUM_MIN, self.isSameLine = true); + +IMGUI_ITEM(IMGUI_FPS, self.label = "FPS", self.tooltip = "Sets the animation's frames per second (its speed).", self.snapshotAction = "Set FPS", + self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.min = ANM2_FPS_MIN, self.max = ANM2_FPS_MAX, self.value = ANM2_FPS_DEFAULT, + self.isSameLine = true); + +IMGUI_ITEM(IMGUI_LOOP, self.label = "Loop", self.tooltip = "Toggles the animation looping.", self.snapshotAction = "Set Loop", + self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.value = true, self.isSameLine = true); + +IMGUI_ITEM(IMGUI_CREATED_BY, self.label = "Author", self.tooltip = "Sets the author of the animation.", self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, + self.max = UCHAR_MAX); #define IMGUI_ONIONSKIN_ROW_COUNT 3 IMGUI_ITEM(IMGUI_ONIONSKIN, self.label = "Onionskin"); -IMGUI_ITEM(IMGUI_ONIONSKIN_ENABLED, - self.label = "Enabled", - self.tooltip = "Toggle onionskin (previews of frames before/after the current one.)", - self.function = imgui_onionskin_toggle, - self.hotkey = HOTKEY_ONIONSKIN, - self.isSeparator = true -); +IMGUI_ITEM(IMGUI_ONIONSKIN_ENABLED, self.label = "Enabled", self.tooltip = "Toggle onionskin (previews of frames before/after the current one.)", + self.function = imgui_onionskin_toggle, self.hotkey = HOTKEY_ONIONSKIN, self.isSeparator = true); IMGUI_ITEM(IMGUI_ONIONSKIN_BEFORE, self.label = "-- Before -- "); IMGUI_ITEM(IMGUI_ONIONSKIN_AFTER, self.label = "-- After -- "); -IMGUI_ITEM(IMGUI_ONIONSKIN_COUNT, - self.label = "Count", - self.tooltip = "Set the number of previewed frames appearing.", - self.min = 0, - self.max = 100, - self.value = SETTINGS_ONIONSKIN_BEFORE_COUNT_DEFAULT, - self.rowCount = IMGUI_ONIONSKIN_ROW_COUNT, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_ONIONSKIN_COUNT, self.label = "Count", self.tooltip = "Set the number of previewed frames appearing.", self.min = 0, self.max = 100, + self.value = SETTINGS_ONIONSKIN_BEFORE_COUNT_DEFAULT, self.rowCount = IMGUI_ONIONSKIN_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_ONIONSKIN_COLOR_OFFSET, - self.label = "Color Offset", - self.tooltip = "Set the color offset of the previewed frames.", - self.flags = ImGuiColorEditFlags_NoInputs, - self.rowCount = IMGUI_ONIONSKIN_ROW_COUNT -); +IMGUI_ITEM(IMGUI_ONIONSKIN_COLOR_OFFSET, self.label = "Color Offset", self.tooltip = "Set the color offset of the previewed frames.", + self.flags = ImGuiColorEditFlags_NoInputs, self.rowCount = IMGUI_ONIONSKIN_ROW_COUNT); -IMGUI_ITEM(IMGUI_ONIONSKIN_DRAW_ORDER, - self.label = "Draw Order", - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_ONIONSKIN_DRAW_ORDER, self.label = "Draw Order", self.isSameLine = true); -IMGUI_ITEM(IMGUI_ONIONSKIN_BELOW, - self.label = "Below", - self.tooltip = "The onionskin frames will draw below the base frame.", - self.value = ONIONSKIN_BELOW, - self.isSameLine = true -); +IMGUI_ITEM(IMGUI_ONIONSKIN_BELOW, self.label = "Below", self.tooltip = "The onionskin frames will draw below the base frame.", self.value = ONIONSKIN_BELOW, + self.isSameLine = true); -IMGUI_ITEM(IMGUI_ONIONSKIN_ABOVE, - self.label = "Above", - self.tooltip = "The onionskin frames will draw above the base frame.", - self.value = ONIONSKIN_ABOVE -); +IMGUI_ITEM(IMGUI_ONIONSKIN_ABOVE, self.label = "Above", self.tooltip = "The onionskin frames will draw above the base frame.", self.value = ONIONSKIN_ABOVE); IMGUI_ITEM(IMGUI_CONTEXT_MENU, self.label = "## Context Menu"); -IMGUI_ITEM(IMGUI_CUT, - self.label = "Cut", - self.tooltip = "Cuts the currently selected contextual element; removing it and putting it to the clipboard.", - self.snapshotAction = "Cut", - self.function = imgui_cut, - self.hotkey = HOTKEY_CUT, - self.isSizeToText = true -); +IMGUI_ITEM(IMGUI_CUT, self.label = "Cut", + self.tooltip = "Cuts the currently selected contextual element; " + "removing it and putting it to the clipboard.", + self.snapshotAction = "Cut", self.function = imgui_cut, self.hotkey = HOTKEY_CUT, self.isSizeToText = true); -IMGUI_ITEM(IMGUI_COPY, - self.label = "Copy", - self.tooltip = "Copies the currently selected contextual element to the clipboard.", - self.snapshotAction = "Copy", - self.function = imgui_copy, - self.hotkey = HOTKEY_COPY, - self.isSizeToText = true -); +IMGUI_ITEM(IMGUI_COPY, self.label = "Copy", self.tooltip = "Copies the currently selected contextual element to the clipboard.", self.snapshotAction = "Copy", + self.function = imgui_copy, self.hotkey = HOTKEY_COPY, self.isSizeToText = true); -IMGUI_ITEM(IMGUI_PASTE, - self.label = "Paste", - self.tooltip = "Pastes the currently selection contextual element from the clipboard.", - self.snapshotAction = "Paste", - self.function = imgui_paste, - self.hotkey = HOTKEY_PASTE, - self.isSizeToText = true -); +IMGUI_ITEM(IMGUI_PASTE, self.label = "Paste", self.tooltip = "Pastes the currently selection contextual element from the clipboard.", + self.snapshotAction = "Paste", self.function = imgui_paste, self.hotkey = HOTKEY_PASTE, self.isSizeToText = true); -IMGUI_ITEM(IMGUI_CHANGE_INPUT_TEXT, - self.label = "## Input Text", - self.tooltip = "Rename the selected item.", - self.snapshotAction = "Rename Item", - self.flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue, - self.max = UCHAR_MAX -); +IMGUI_ITEM(IMGUI_CHANGE_INPUT_TEXT, self.label = "## Input Text", self.tooltip = "Rename the selected item.", self.snapshotAction = "Rename Item", + self.flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue, self.max = UCHAR_MAX); -IMGUI_ITEM(IMGUI_CHANGE_INPUT_INT, - self.label = "## Input Int", - self.tooltip = "Change the selected item's value.", - self.snapshotAction = "Change Value", - self.step = 0 -); +IMGUI_ITEM(IMGUI_CHANGE_INPUT_INT, self.label = "## Input Int", self.tooltip = "Change the selected item's value.", self.snapshotAction = "Change Value", + self.step = 0); #define IMGUI_CONFIRM_POPUP_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_POPUP_OK, - self.label = "OK", - self.tooltip = "Confirm the action.", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT -); +IMGUI_ITEM(IMGUI_POPUP_OK, self.label = "OK", self.tooltip = "Confirm the action.", self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT); -IMGUI_ITEM(IMGUI_POPUP_CANCEL, - self.label = "Cancel", - self.tooltip = "Cancel the action.", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT -); +IMGUI_ITEM(IMGUI_POPUP_CANCEL, self.label = "Cancel", self.tooltip = "Cancel the action.", self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT); -IMGUI_ITEM(IMGUI_LOG_WINDOW, - self.label = "## Log Window", - self.flags = ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoSavedSettings | - ImGuiWindowFlags_AlwaysAutoResize | - ImGuiWindowFlags_NoFocusOnAppearing | - ImGuiWindowFlags_NoNav | - ImGuiWindowFlags_NoInputs -); +IMGUI_ITEM(IMGUI_LOG_WINDOW, self.label = "## Log Window", + self.flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | + ImGuiWindowFlags_NoInputs); -void imgui_init -( - Imgui* self, - Dialog* dialog, - Resources* resources, - Anm2* anm2, - Anm2Reference* reference, - Editor* editor, - Preview* preview, - GeneratePreview* generatePreview, - Settings* settings, - Snapshots* snapshots, - Clipboard* clipboard, - SDL_Window* window, - SDL_GLContext* glContext -); +IMGUI_ITEM(IMGUI_ATLAS, self.label = "## Atlas Image", self.atlas = ATLAS_NONE); + +void imgui_init(Imgui* self, Dialog* dialog, Resources* resources, Anm2* anm2, Anm2Reference* reference, Editor* editor, Preview* preview, + GeneratePreview* generatePreview, Settings* settings, Snapshots* snapshots, Clipboard* clipboard, SDL_Window* window, SDL_GLContext* glContext); void imgui_update(Imgui* self); void imgui_draw(); diff --git a/src/main.cpp b/src/main.cpp index 42cffed..0970bdf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,61 +1,51 @@ #include "main.h" -static bool _anm2_rescale(const std::string& file, f32 scale) -{ - Anm2 anm2; +static bool _anm2_rescale(const std::string& file, float scale) { + Anm2 anm2; - if (!anm2_deserialize(&anm2, file, false)) return false; - anm2_scale(&anm2, scale); - return anm2_serialize(&anm2, file); + if (!anm2_deserialize(&anm2, file, false)) + return false; + anm2_scale(&anm2, scale); + return anm2_serialize(&anm2, file); } -s32 -main(s32 argc, char* argv[]) -{ - State state; +int main(int argc, char* argv[]) { + State state; - log_init(); + log_init(); - if (argc > 0 && argv[1]) - { - if (std::string(argv[1]) == ARGUMENT_RESCALE) - { - if (argv[2] && argv[3]) - { - if (_anm2_rescale(std::string(argv[2]), atof(argv[3]))) - { - log_info(std::format(ARGUMENT_RESCALE_ANM2_INFO, argv[2], argv[3])); - return EXIT_SUCCESS; - } - else - log_error(ARGUMENT_RESCALE_ANM2_ERROR); - } - else - log_error(ARGUMENT_RESCALE_ARGUMENT_ERROR); - - return EXIT_FAILURE; - } - else if (std::string(argv[1]) == ARGUMENT_TEST && argv[2]) - { - if (anm2_deserialize(&state.anm2, std::string(argv[2]), false)) return EXIT_SUCCESS; - return EXIT_FAILURE; - } - else if (std::string(argv[1]) == ARGUMENT_TEST_GL && argv[2]) - { - if (!sdl_init(&state, true)) return EXIT_FAILURE; - if (anm2_deserialize(&state.anm2, std::string(argv[2]))) return EXIT_SUCCESS; - return EXIT_FAILURE; - } - else - if (argv[1]) state.argument = argv[1]; - } + if (argc > 0 && argv[1]) { + if (std::string(argv[1]) == ARGUMENT_RESCALE) { + if (argv[2] && argv[3]) { + if (_anm2_rescale(std::string(argv[2]), atof(argv[3]))) { + log_info(std::format(ARGUMENT_RESCALE_ANM2_INFO, argv[2], argv[3])); + return EXIT_SUCCESS; + } else + log_error(ARGUMENT_RESCALE_ANM2_ERROR); + } else + log_error(ARGUMENT_RESCALE_ARGUMENT_ERROR); - init(&state); + return EXIT_FAILURE; + } else if (std::string(argv[1]) == ARGUMENT_TEST && argv[2]) { + if (anm2_deserialize(&state.anm2, std::string(argv[2]), false)) + return EXIT_SUCCESS; + return EXIT_FAILURE; + } else if (std::string(argv[1]) == ARGUMENT_TEST_GL && argv[2]) { + if (!sdl_init(&state, true)) + return EXIT_FAILURE; + if (anm2_deserialize(&state.anm2, std::string(argv[2]))) + return EXIT_SUCCESS; + return EXIT_FAILURE; + } else if (argv[1]) + state.argument = argv[1]; + } - while (state.isRunning) - loop(&state); + init(&state); - quit(&state); + while (state.isRunning) + loop(&state); - return EXIT_SUCCESS; + quit(&state); + + return EXIT_SUCCESS; } \ No newline at end of file diff --git a/src/preview.cpp b/src/preview.cpp index 6ef404e..ef13be7 100644 --- a/src/preview.cpp +++ b/src/preview.cpp @@ -1,282 +1,259 @@ #include "preview.h" -static void _preview_render_textures_free(Preview* self) -{ - for (auto& texture : self->renderFrames) - texture_free(&texture); +static void _preview_render_textures_free(Preview* self) { + for (auto& texture : self->renderFrames) + texture_free(&texture); - self->renderFrames.clear(); + self->renderFrames.clear(); } -void preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings) -{ - self->anm2 = anm2; - self->reference = reference; - self->resources = resources; - self->settings = settings; +void preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings) { + self->anm2 = anm2; + self->reference = reference; + self->resources = resources; + self->settings = settings; - canvas_init(&self->canvas, vec2()); + canvas_init(&self->canvas, vec2()); } -void preview_tick(Preview* self) -{ - f32& time = self->time; - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference); +void preview_tick(Preview* self) { + float& time = self->time; + Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); - if (animation) - { - if (self->isPlaying) - { - if (self->isRender) - { - ivec2& size = self->canvas.size; - u32 framebufferPixelCount = size.x * size.y * TEXTURE_CHANNELS; - std::vector framebufferPixels(framebufferPixelCount); - Texture frameTexture; + if (animation) { + if (self->isPlaying) { + if (self->isRender) { + ivec2& size = self->canvas.size; + u32 framebufferPixelCount = size.x * size.y * TEXTURE_CHANNELS; + std::vector framebufferPixels(framebufferPixelCount); + Texture frameTexture; - glBindFramebuffer(GL_READ_FRAMEBUFFER, self->canvas.fbo); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ROW_LENGTH, 0); - glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, framebufferPixels.data()); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, self->canvas.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, framebufferPixels.data()); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - texture_from_rgba_init(&frameTexture, size, framebufferPixels.data()); - self->renderFrames.push_back(frameTexture); - } + texture_from_rgba_init(&frameTexture, size, framebufferPixels.data()); + self->renderFrames.push_back(frameTexture); + } - time += (f32)self->anm2->fps / TICK_DELAY; + time += (float)self->anm2->fps / TICK_DELAY; - if (time >= (f32)animation->frameNum - 1) - { - if (self->isRender) - { - self->isRender = false; - self->isRenderFinished = true; - time = 0.0f; - self->isPlaying = false; - } - else - { - if (self->settings->playbackIsLoop) - time = 0.0f; - else - { - time = std::clamp(time, 0.0f, std::max(0.0f, (f32)animation->frameNum - 1)); - self->isPlaying = false; - } - } - } + if (time >= (float)animation->frameNum - 1) { + if (self->isRender) { + self->isRender = false; + self->isRenderFinished = true; + time = 0.0f; + self->isPlaying = false; + } else { + if (self->settings->playbackIsLoop) + time = 0.0f; + else { + time = std::clamp(time, 0.0f, std::max(0.0f, (float)animation->frameNum - 1)); + self->isPlaying = false; + } } - - if (self->settings->playbackIsClampPlayhead) - time = std::clamp(time, 0.0f, std::max(0.0f, (f32)animation->frameNum - 1)); - else - time = std::max(time, 0.0f); + } } + + if (self->settings->playbackIsClampPlayhead) + time = std::clamp(time, 0.0f, std::max(0.0f, (float)animation->frameNum - 1)); + else + time = std::max(time, 0.0f); + } } -void preview_draw(Preview* self) -{ - ivec2& gridSize = self->settings->previewGridSize; - ivec2& gridOffset = self->settings->previewGridOffset; - vec4& gridColor = self->settings->previewGridColor; - GLuint& shaderLine = self->resources->shaders[SHADER_LINE]; - GLuint& shaderAxis = self->resources->shaders[SHADER_AXIS]; - GLuint& shaderTexture = self->resources->shaders[SHADER_TEXTURE]; - GLuint& shaderGrid = self->resources->shaders[SHADER_GRID]; - mat4 transform = canvas_transform_get(&self->canvas, self->settings->previewPan, self->settings->previewZoom, ORIGIN_CENTER); - - canvas_framebuffer_resize_check(&self->canvas); - - canvas_bind(&self->canvas); - canvas_viewport_set(&self->canvas); - canvas_clear(self->settings->previewBackgroundColor); - - if (self->settings->previewIsGrid) - canvas_grid_draw(&self->canvas, shaderGrid, transform, gridSize, gridOffset, gridColor); +void preview_draw(Preview* self) { + ivec2& gridSize = self->settings->previewGridSize; + ivec2& gridOffset = self->settings->previewGridOffset; + vec4& gridColor = self->settings->previewGridColor; + GLuint& shaderLine = self->resources->shaders[SHADER_LINE]; + GLuint& shaderAxis = self->resources->shaders[SHADER_AXIS]; + GLuint& shaderTexture = self->resources->shaders[SHADER_TEXTURE]; + GLuint& shaderGrid = self->resources->shaders[SHADER_GRID]; + mat4 transform = canvas_transform_get(&self->canvas, self->settings->previewPan, self->settings->previewZoom, ORIGIN_CENTER); - if (self->settings->previewIsAxes) - canvas_axes_draw(&self->canvas, shaderAxis, transform, self->settings->previewAxesColor); + canvas_framebuffer_resize_check(&self->canvas); - auto animation_draw = [&](s32 animationID) - { - Anm2Animation* animation = map_find(self->anm2->animations, animationID); - if (!animation) return; + canvas_bind(&self->canvas); + canvas_viewport_set(&self->canvas); + canvas_clear(self->settings->previewBackgroundColor); - auto root_draw = [&](Anm2Frame root, vec3 colorOffset = {}, f32 alphaOffset = {}, bool isOnionskin = {}) - { - mat4 model = quad_model_get(PREVIEW_TARGET_SIZE, root.position, PREVIEW_TARGET_SIZE * 0.5f, PERCENT_TO_UNIT(root.scale), root.rotation); - mat4 rootTransform = transform * model; - vec4 color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : PREVIEW_ROOT_COLOR; - AtlasType atlas = self->settings->previewIsAltIcons ? ATLAS_TARGET_ALT : ATLAS_TARGET; - f32 vertices[] = ATLAS_UV_VERTICES(atlas); - canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, rootTransform, vertices, color); - }; + if (self->settings->previewIsGrid) + canvas_grid_draw(&self->canvas, shaderGrid, transform, gridSize, gridOffset, gridColor); - auto layer_draw = [&](mat4 rootModel, s32 id, f32 time, vec3 colorOffset = {}, f32 alphaOffset = {}, bool isOnionskin = {}) - { - Anm2Item& layerAnimation = animation->layerAnimations[id]; - if (!layerAnimation.isVisible || layerAnimation.frames.size() <= 0) return; + if (self->settings->previewIsAxes) + canvas_axes_draw(&self->canvas, shaderAxis, transform, self->settings->previewAxesColor); - Anm2Frame frame; - anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_LAYER, id}, time); - if (!frame.isVisible) return; + auto animation_draw = [&](int animationID) { + Anm2Animation* animation = map_find(self->anm2->animations, animationID); + if (!animation) + return; - mat4 model = quad_model_get(frame.size, frame.position, frame.pivot, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 layerTransform = transform * (rootModel * model); - vec3 frameColorOffset = frame.offsetRGB + colorOffset; - vec4 frameTint = frame.tintRGBA; - frameTint.a = std::max(0.0f, frameTint.a - alphaOffset); - - Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->anm2->layers[id].spritesheetID); - if (!spritesheet) return; - - Texture& texture = spritesheet->texture; - if (texture.isInvalid) return; - - vec2 inset = 0.5f / vec2(texture.size); - vec2 uvMin = frame.crop / vec2(texture.size) + inset; - vec2 uvMax = (frame.crop + frame.size) / vec2(texture.size) - inset; - f32 vertices[] = UV_VERTICES(uvMin, uvMax); - canvas_texture_draw(&self->canvas, shaderTexture, texture.id, layerTransform, vertices, frameTint, frameColorOffset); - - if (self->settings->previewIsBorder) - { - vec4 borderColor = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : PREVIEW_BORDER_COLOR; - canvas_rect_draw(&self->canvas, shaderLine, layerTransform, borderColor); - } - - if (self->settings->previewIsPivots) - { - vec4 pivotColor = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : PREVIEW_PIVOT_COLOR; - f32 vertices[] = ATLAS_UV_VERTICES(ATLAS_PIVOT); - mat4 pivotModel = quad_model_get(CANVAS_PIVOT_SIZE, frame.position, CANVAS_PIVOT_SIZE * 0.5f, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 pivotTransform = transform * (rootModel * pivotModel); - canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, pivotTransform, vertices, pivotColor); - } - }; - - auto null_draw = [&](mat4 rootModel, s32 id, f32 time, vec3 colorOffset = {}, f32 alphaOffset = {}, bool isOnionskin = {}) - { - Anm2Item& nullAnimation = animation->nullAnimations[id]; - if (!nullAnimation.isVisible || nullAnimation.frames.size() <= 0) return; - - Anm2Frame frame; - anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_NULL, id}, time); - if (!frame.isVisible) return; - - Anm2Null null = self->anm2->nulls[id]; - - vec4 color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : - (self->reference->itemType == ANM2_NULL && self->reference->itemID == id) ? - PREVIEW_NULL_SELECTED_COLOR : PREVIEW_NULL_COLOR; - - vec2 size = null.isShowRect ? CANVAS_PIVOT_SIZE : PREVIEW_TARGET_SIZE; - AtlasType atlas = null.isShowRect ? ATLAS_SQUARE : self->settings->previewIsAltIcons ? ATLAS_TARGET_ALT : ATLAS_TARGET; - - mat4 model = quad_model_get(size, frame.position, size * 0.5f, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 nullTransform = transform * (rootModel * model); - - f32 vertices[] = ATLAS_UV_VERTICES(atlas); - - canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, nullTransform, vertices, color); - - if (null.isShowRect) - { - mat4 rectModel = quad_model_get(PREVIEW_NULL_RECT_SIZE, frame.position, PREVIEW_NULL_RECT_SIZE * 0.5f, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 rectTransform = transform * (rootModel * rectModel); - canvas_rect_draw(&self->canvas, shaderLine, rectTransform, color); - } - }; - - auto base_draw = [&](f32 time, vec3 colorOffset = {}, f32 alphaOffset = {}, bool isOnionskin = {}) - { - Anm2Frame root; - anm2_frame_from_time(self->anm2, &root, Anm2Reference{animationID, ANM2_ROOT}, time); - - mat4 rootModel = self->settings->previewIsRootTransform ? - quad_model_parent_get(root.position, {}, PERCENT_TO_UNIT(root.scale), root.rotation) : mat4(1.0f); - - if (self->settings->previewIsIcons && animation->rootAnimation.isVisible && root.isVisible) - root_draw(root, colorOffset, alphaOffset, isOnionskin); - - for (auto id : animation->layerOrder) - layer_draw(rootModel, id, time, colorOffset, alphaOffset, isOnionskin); - - if (self->settings->previewIsIcons) - for (auto& [id, _] : animation->nullAnimations) - null_draw(rootModel, id, time, colorOffset, alphaOffset, isOnionskin); - }; - - auto onionskin_draw = [&](s32 count, s32 direction, vec3 colorOffset) - { - for (s32 i = 1; i <= count; i++) - { - f32 time = self->time + (f32)(direction * i); - f32 alphaOffset = (1.0f / (count + 1)) * i; - base_draw(time, colorOffset, alphaOffset, true); - } - }; - - auto onionskins_draw = [&]() - { - if (!self->settings->onionskinIsEnabled) return; - onionskin_draw(self->settings->onionskinBeforeCount, -1, self->settings->onionskinBeforeColorOffset); - onionskin_draw(self->settings->onionskinAfterCount, 1, self->settings->onionskinAfterColorOffset); - }; - - if (self->settings->onionskinDrawOrder == ONIONSKIN_BELOW) onionskins_draw(); - base_draw(self->time); - if (self->settings->onionskinDrawOrder == ONIONSKIN_ABOVE) onionskins_draw(); + auto root_draw = [&](Anm2Frame root, vec3 colorOffset = {}, float alphaOffset = {}, bool isOnionskin = {}) { + mat4 model = quad_model_get(PREVIEW_TARGET_SIZE, root.position, PREVIEW_TARGET_SIZE * 0.5f, PERCENT_TO_UNIT(root.scale), root.rotation); + mat4 rootTransform = transform * model; + vec4 color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : PREVIEW_ROOT_COLOR; + AtlasType atlas = self->settings->previewIsAltIcons ? ATLAS_TARGET_ALT : ATLAS_TARGET; + float vertices[] = ATLAS_UV_VERTICES(atlas); + canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, rootTransform, vertices, color); }; - animation_draw(self->reference->animationID); - animation_draw(self->animationOverlayID); + auto layer_draw = [&](mat4 rootModel, int id, float time, vec3 colorOffset = {}, float alphaOffset = {}, bool isOnionskin = {}) { + Anm2Item& layerAnimation = animation->layerAnimations[id]; + if (!layerAnimation.isVisible || layerAnimation.frames.size() <= 0) + return; - canvas_unbind(); + Anm2Frame frame; + anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_LAYER, id}, time); + if (!frame.isVisible) + return; + + mat4 model = quad_model_get(frame.size, frame.position, frame.pivot, PERCENT_TO_UNIT(frame.scale), frame.rotation); + mat4 layerTransform = transform * (rootModel * model); + vec3 frameColorOffset = frame.offsetRGB + colorOffset; + vec4 frameTint = frame.tintRGBA; + frameTint.a = std::max(0.0f, frameTint.a - alphaOffset); + + Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->anm2->layers[id].spritesheetID); + if (!spritesheet) + return; + + Texture& texture = spritesheet->texture; + if (texture.isInvalid) + return; + + vec2 inset = 0.5f / vec2(texture.size); + vec2 uvMin = frame.crop / vec2(texture.size) + inset; + vec2 uvMax = (frame.crop + frame.size) / vec2(texture.size) - inset; + float vertices[] = UV_VERTICES(uvMin, uvMax); + canvas_texture_draw(&self->canvas, shaderTexture, texture.id, layerTransform, vertices, frameTint, frameColorOffset); + + if (self->settings->previewIsBorder) { + vec4 borderColor = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : PREVIEW_BORDER_COLOR; + canvas_rect_draw(&self->canvas, shaderLine, layerTransform, borderColor); + } + + if (self->settings->previewIsPivots) { + vec4 pivotColor = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : PREVIEW_PIVOT_COLOR; + float vertices[] = ATLAS_UV_VERTICES(ATLAS_PIVOT); + mat4 pivotModel = quad_model_get(CANVAS_PIVOT_SIZE, frame.position, CANVAS_PIVOT_SIZE * 0.5f, PERCENT_TO_UNIT(frame.scale), frame.rotation); + mat4 pivotTransform = transform * (rootModel * pivotModel); + canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, pivotTransform, vertices, pivotColor); + } + }; + + auto null_draw = [&](mat4 rootModel, int id, float time, vec3 colorOffset = {}, float alphaOffset = {}, bool isOnionskin = {}) { + Anm2Item& nullAnimation = animation->nullAnimations[id]; + if (!nullAnimation.isVisible || nullAnimation.frames.size() <= 0) + return; + + Anm2Frame frame; + anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_NULL, id}, time); + if (!frame.isVisible) + return; + + Anm2Null null = self->anm2->nulls[id]; + + vec4 color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) + : (self->reference->itemType == ANM2_NULL && self->reference->itemID == id) ? PREVIEW_NULL_SELECTED_COLOR + : PREVIEW_NULL_COLOR; + + vec2 size = null.isShowRect ? CANVAS_PIVOT_SIZE : PREVIEW_TARGET_SIZE; + AtlasType atlas = null.isShowRect ? ATLAS_SQUARE : self->settings->previewIsAltIcons ? ATLAS_TARGET_ALT : ATLAS_TARGET; + + mat4 model = quad_model_get(size, frame.position, size * 0.5f, PERCENT_TO_UNIT(frame.scale), frame.rotation); + mat4 nullTransform = transform * (rootModel * model); + + float vertices[] = ATLAS_UV_VERTICES(atlas); + + canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, nullTransform, vertices, color); + + if (null.isShowRect) { + mat4 rectModel = quad_model_get(PREVIEW_NULL_RECT_SIZE, frame.position, PREVIEW_NULL_RECT_SIZE * 0.5f, PERCENT_TO_UNIT(frame.scale), frame.rotation); + mat4 rectTransform = transform * (rootModel * rectModel); + canvas_rect_draw(&self->canvas, shaderLine, rectTransform, color); + } + }; + + auto base_draw = [&](float time, vec3 colorOffset = {}, float alphaOffset = {}, bool isOnionskin = {}) { + Anm2Frame root; + anm2_frame_from_time(self->anm2, &root, Anm2Reference{animationID, ANM2_ROOT}, time); + + mat4 rootModel = + self->settings->previewIsRootTransform ? quad_model_parent_get(root.position, {}, PERCENT_TO_UNIT(root.scale), root.rotation) : mat4(1.0f); + + if (self->settings->previewIsIcons && animation->rootAnimation.isVisible && root.isVisible) + root_draw(root, colorOffset, alphaOffset, isOnionskin); + + for (auto id : animation->layerOrder) + layer_draw(rootModel, id, time, colorOffset, alphaOffset, isOnionskin); + + if (self->settings->previewIsIcons) + for (auto& [id, _] : animation->nullAnimations) + null_draw(rootModel, id, time, colorOffset, alphaOffset, isOnionskin); + }; + + auto onionskin_draw = [&](int count, int direction, vec3 colorOffset) { + for (int i = 1; i <= count; i++) { + float time = self->time + (float)(direction * i); + float alphaOffset = (1.0f / (count + 1)) * i; + base_draw(time, colorOffset, alphaOffset, true); + } + }; + + auto onionskins_draw = [&]() { + if (!self->settings->onionskinIsEnabled) + return; + onionskin_draw(self->settings->onionskinBeforeCount, -1, self->settings->onionskinBeforeColorOffset); + onionskin_draw(self->settings->onionskinAfterCount, 1, self->settings->onionskinAfterColorOffset); + }; + + if (self->settings->onionskinDrawOrder == ONIONSKIN_BELOW) + onionskins_draw(); + base_draw(self->time); + if (self->settings->onionskinDrawOrder == ONIONSKIN_ABOVE) + onionskins_draw(); + }; + + animation_draw(self->reference->animationID); + animation_draw(self->animationOverlayID); + + canvas_unbind(); } -void preview_render_start(Preview* self) -{ - self->isRender = true; - self->isPlaying = true; - self->time = 0.0f; - _preview_render_textures_free(self); - - self->normalCanvasSize = self->canvas.size; - self->normalCanvasPan = self->settings->previewPan; - self->normalCanvasZoom = self->settings->previewZoom; +void preview_render_start(Preview* self) { + self->isRender = true; + self->isPlaying = true; + self->time = 0.0f; + _preview_render_textures_free(self); - if (self->settings->renderIsUseAnimationBounds) - { - vec4 rect = anm2_animation_rect_get(self->anm2, self->reference, self->settings->previewIsRootTransform); + self->normalCanvasSize = self->canvas.size; + self->normalCanvasPan = self->settings->previewPan; + self->normalCanvasZoom = self->settings->previewZoom; - self->canvas.size = ivec2 - ( - ceilf(rect.z * self->settings->renderScale), - ceilf(rect.w * self->settings->renderScale) - ); + if (self->settings->renderIsUseAnimationBounds) { + vec4 rect = anm2_animation_rect_get(self->anm2, *self->reference, self->settings->previewIsRootTransform); - vec2 rectCenter = vec2(rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f); - self->settings->previewPan = -rectCenter * self->settings->renderScale; - self->settings->previewZoom = UNIT_TO_PERCENT(self->settings->renderScale); - } + self->canvas.size = ivec2(ceilf(rect.z * self->settings->renderScale), ceilf(rect.w * self->settings->renderScale)); + + vec2 rectCenter = vec2(rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f); + self->settings->previewPan = -rectCenter * self->settings->renderScale; + self->settings->previewZoom = UNIT_TO_PERCENT(self->settings->renderScale); + } } -void preview_render_end(Preview* self) -{ - self->isRender = false; - self->isPlaying = false; - self->isRenderFinished = false; - _preview_render_textures_free(self); - - self->canvas.size = self->normalCanvasSize; - self->settings->previewPan = self->normalCanvasPan; - self->settings->previewZoom = self->normalCanvasZoom; +void preview_render_end(Preview* self) { + self->isRender = false; + self->isPlaying = false; + self->isRenderFinished = false; + _preview_render_textures_free(self); + + self->canvas.size = self->normalCanvasSize; + self->settings->previewPan = self->normalCanvasPan; + self->settings->previewZoom = self->normalCanvasZoom; } -void preview_free(Preview* self) -{ - canvas_free(&self->canvas); -} \ No newline at end of file +void preview_free(Preview* self) { canvas_free(&self->canvas); } \ No newline at end of file diff --git a/src/preview.h b/src/preview.h index 7fcfa26..de54696 100644 --- a/src/preview.h +++ b/src/preview.h @@ -1,9 +1,9 @@ #pragma once #include "anm2.h" +#include "canvas.h" #include "resources.h" #include "settings.h" -#include "canvas.h" const vec2 PREVIEW_SIZE = {2000, 2000}; const vec2 PREVIEW_CANVAS_SIZE = {2000, 2000}; @@ -26,23 +26,22 @@ const vec4 PREVIEW_NULL_COLOR = COLOR_BLUE; const vec4 PREVIEW_NULL_SELECTED_COLOR = COLOR_RED; const vec4 PREVIEW_PIVOT_COLOR = COLOR_RED; -struct Preview -{ - Anm2* anm2 = nullptr; - Anm2Reference* reference = nullptr; - Resources* resources = nullptr; - Settings* settings = nullptr; - s32 animationOverlayID = ID_NONE; - Canvas canvas; - vec2 normalCanvasSize{}; - vec2 normalCanvasPan{}; - f32 normalCanvasZoom{}; - bool isPlaying = false; - bool isRender = false; - bool isRenderFinished = false; - bool isRenderCancelled = false; - std::vector renderFrames; - f32 time{}; +struct Preview { + Anm2* anm2 = nullptr; + Anm2Reference* reference = nullptr; + Resources* resources = nullptr; + Settings* settings = nullptr; + int animationOverlayID = ID_NONE; + Canvas canvas; + vec2 normalCanvasSize{}; + vec2 normalCanvasPan{}; + float normalCanvasZoom{}; + bool isPlaying = false; + bool isRender = false; + bool isRenderFinished = false; + bool isRenderCancelled = false; + std::vector renderFrames; + float time{}; }; void preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings); diff --git a/src/resources.cpp b/src/resources.cpp index 09f0ea5..c338e88 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -1,17 +1,15 @@ #include "resources.h" -void resources_init(Resources* self) -{ - texture_from_encoded_data_init(&self->atlas, TEXTURE_ATLAS_SIZE, (u8*)TEXTURE_ATLAS, TEXTURE_ATLAS_LENGTH); - - for (s32 i = 0; i < SHADER_COUNT; i++) - shader_init(&self->shaders[i], SHADER_DATA[i].vertex, SHADER_DATA[i].fragment); +void resources_init(Resources* self) { + texture_from_path_init(&self->atlas, ATLAS_PATH); + + for (int i = 0; i < SHADER_COUNT; i++) + shader_init(&self->shaders[i], SHADER_DATA[i].vertex, SHADER_DATA[i].fragment); } -void resources_free(Resources* self) -{ - for (auto& shader : self->shaders) - shader_free(&shader); +void resources_free(Resources* self) { + for (auto& shader : self->shaders) + shader_free(&shader); - texture_free(&self->atlas); + texture_free(&self->atlas); } \ No newline at end of file diff --git a/src/resources.h b/src/resources.h index 912ceca..af0dbcb 100644 --- a/src/resources.h +++ b/src/resources.h @@ -1,15 +1,14 @@ #pragma once -#include "PACKED.h" -#include "texture.h" +#include "RESOURCE.h" #include "shader.h" +#include "texture.h" #define RESOURCES_TEXTURES_FREE_INFO "Freed texture resources" -struct Resources -{ - GLuint shaders[SHADER_COUNT]; - Texture atlas; +struct Resources { + GLuint shaders[SHADER_COUNT]; + Texture atlas; }; void resources_init(Resources* self); diff --git a/src/settings.cpp b/src/settings.cpp index 81347d9..d1b31e2 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1,276 +1,305 @@ #include "settings.h" -static void _settings_setting_load(Settings* self, const std::string& line) -{ - for (s32 i = 0; i < SETTINGS_COUNT; i++) - { - const auto& entry = SETTINGS_ENTRIES[i]; - const std::string& key = entry.key; - void* target = (u8*)self + entry.offset; +static void _settings_setting_load(Settings* self, const std::string& line) { + for (int i = 0; i < SETTINGS_COUNT; i++) { + const auto& entry = SETTINGS_ENTRIES[i]; + const std::string& key = entry.key; + void* target = (u8*)self + entry.offset; - auto match_key = [&](const std::string& full) -> const char* - { - if (!line.starts_with(full)) - return nullptr; + auto match_key = [&](const std::string& full) -> const char* { + if (!line.starts_with(full)) + return nullptr; - size_t p = full.size(); - while (p < line.size() && std::isspace((u8)line[p])) ++p; - if (p < line.size() && line[p] == '=') - return line.c_str() + p + 1; - return nullptr; - }; + size_t p = full.size(); + while (p < line.size() && std::isspace((u8)line[p])) + ++p; + if (p < line.size() && line[p] == '=') + return line.c_str() + p + 1; + return nullptr; + }; - const char* value = nullptr; + const char* value = nullptr; - switch (entry.type) - { - case TYPE_INT: - if ((value = match_key(key))) { *(s32*)target = std::atoi(value); return; } - break; - case TYPE_BOOL: - if ((value = match_key(key))) { *(bool*)target = string_to_bool(value); return; } - break; - case TYPE_FLOAT: - if ((value = match_key(key))) { *(f32*)target = std::atof(value); return; } - break; - case TYPE_STRING: - if ((value = match_key(key))) { *(std::string*)target = value; return; } - break; - case TYPE_IVEC2: - { - ivec2* v = (ivec2*)target; - if ((value = match_key(key + "X"))) { v->x = std::atoi(value); return; } - if ((value = match_key(key + "Y"))) { v->y = std::atoi(value); return; } - break; - } - case TYPE_IVEC2_WH: - { - ivec2* v = (ivec2*)target; - if ((value = match_key(key + "W"))) { v->x = std::atoi(value); return; } - if ((value = match_key(key + "H"))) { v->y = std::atoi(value); return; } - break; - }; - case TYPE_VEC2: - { - vec2* v = (vec2*)target; - if ((value = match_key(key + "X"))) { v->x = std::atof(value); return; } - if ((value = match_key(key + "Y"))) { v->y = std::atof(value); return; } - break; - } - case TYPE_VEC2_WH: - { - vec2* v = (vec2*)target; - if ((value = match_key(key + "W"))) { v->x = std::atof(value); return; } - if ((value = match_key(key + "H"))) { v->y = std::atof(value); return; } - break; - }; - case TYPE_VEC3: - { - vec3* v = (vec3*)target; - if ((value = match_key(key + "R"))) { v->x = std::atof(value); return; } - if ((value = match_key(key + "G"))) { v->y = std::atof(value); return; } - if ((value = match_key(key + "B"))) { v->z = std::atof(value); return; } - break; - } - case TYPE_VEC4: - { - vec4* v = (vec4*)target; - if ((value = match_key(key + "R"))) { v->x = std::atof(value); return; } - if ((value = match_key(key + "G"))) { v->y = std::atof(value); return; } - if ((value = match_key(key + "B"))) { v->z = std::atof(value); return; } - if ((value = match_key(key + "A"))) { v->w = std::atof(value); return; } - break; - } - default: - break; - } - } - - log_warning(std::format(SETTINGS_VALUE_INIT_WARNING, line)); -} - -std::string settings_path_get(void) -{ - std::string filePath = preferences_path_get() + SETTINGS_PATH; - return filePath; -} - -static void _settings_setting_write(Settings* self, std::ostream& out, SettingsEntry entry) -{ - u8* selfPointer = (u8*)self; - std::string value; - - switch (entry.type) - { - case TYPE_INT: - value = std::format("{}", *(s32*)(selfPointer + entry.offset)); - out << entry.key << "=" << value << "\n"; - break; - case TYPE_BOOL: - value = std::format("{}", *(bool*)(selfPointer + entry.offset)); - out << entry.key << "=" << value << "\n"; - break; - case TYPE_FLOAT: - value = std::format("{:.3f}", *(f32*)(selfPointer + entry.offset)); - out << entry.key << "=" << value << "\n"; - break; - case TYPE_STRING: - { - const std::string data = *reinterpret_cast(selfPointer + entry.offset); - if (!data.empty()) - out << entry.key << "=" << data.c_str() << "\n"; - break; - } - case TYPE_IVEC2: - { - ivec2* data = (ivec2*)(selfPointer + entry.offset); - out << entry.key << "X=" << data->x << "\n"; - out << entry.key << "Y=" << data->y << "\n"; - break; - } - case TYPE_IVEC2_WH: - { - ivec2* data = (ivec2*)(selfPointer + entry.offset); - out << entry.key << "W=" << data->x << "\n"; - out << entry.key << "H=" << data->y << "\n"; - break; - } - case TYPE_VEC2: - { - vec2* data = (vec2*)(selfPointer + entry.offset); - out << entry.key << "X=" << std::format(SETTINGS_FLOAT_FORMAT, data->x) << "\n"; - out << entry.key << "Y=" << std::format(SETTINGS_FLOAT_FORMAT, data->y) << "\n"; - break; - } - case TYPE_VEC2_WH: - { - vec2* data = (vec2*)(selfPointer + entry.offset); - out << entry.key << "W=" << std::format(SETTINGS_FLOAT_FORMAT, data->x) << "\n"; - out << entry.key << "H=" << std::format(SETTINGS_FLOAT_FORMAT, data->y) << "\n"; - break; - } - case TYPE_VEC3: - { - vec3* data = (vec3*)(selfPointer + entry.offset); - out << entry.key << "R=" << std::format(SETTINGS_FLOAT_FORMAT, data->r) << "\n"; - out << entry.key << "G=" << std::format(SETTINGS_FLOAT_FORMAT, data->g) << "\n"; - out << entry.key << "B=" << std::format(SETTINGS_FLOAT_FORMAT, data->b) << "\n"; - break; - } - case TYPE_VEC4: - { - vec4* data = (vec4*)(selfPointer + entry.offset); - out << entry.key << "R=" << std::format(SETTINGS_FLOAT_FORMAT, data->r) << "\n"; - out << entry.key << "G=" << std::format(SETTINGS_FLOAT_FORMAT, data->g) << "\n"; - out << entry.key << "B=" << std::format(SETTINGS_FLOAT_FORMAT, data->b) << "\n"; - out << entry.key << "A=" << std::format(SETTINGS_FLOAT_FORMAT, data->a) << "\n"; - break; - } - default: - break; - } -} - -void settings_save(Settings* self) -{ - const std::string path = settings_path_get(); - const std::filesystem::path filesystemPath(path); - const std::filesystem::path directory = filesystemPath.parent_path(); - - if (!directory.empty()) - { - std::error_code errorCode; - std::filesystem::create_directories(directory, errorCode); - if (errorCode) - { - log_error(std::format(SETTINGS_DIRECTORY_ERROR, directory.string(), errorCode.message())); - return; - } - } - - std::string data; - if (std::filesystem::exists(filesystemPath)) - { - if (std::ifstream in(path, std::ios::binary); in) - data.assign(std::istreambuf_iterator(in), std::istreambuf_iterator()); - } - - std::filesystem::path temp = filesystemPath; - temp += SETTINGS_TEMPORARY_EXTENSION; - - std::ofstream out(temp, std::ios::binary | std::ios::trunc); - if (!out) - { - log_error(std::format(SETTINGS_INIT_ERROR, temp.string())); + switch (entry.type) { + case TYPE_INT: + if ((value = match_key(key))) { + *(int*)target = std::atoi(value); return; - } - - out << SETTINGS_SECTION << "\n"; - for (s32 i = 0; i < SETTINGS_COUNT; i++) - _settings_setting_write(self, out, SETTINGS_ENTRIES[i]); - - out << "\n" << SETTINGS_SECTION_IMGUI << "\n"; - out << data; - - out.flush(); - - if (!out.good()) - { - log_error(std::format(SETTINGS_SAVE_ERROR, temp.string())); + } + break; + case TYPE_BOOL: + if ((value = match_key(key))) { + *(bool*)target = string_to_bool(value); return; + } + break; + case TYPE_FLOAT: + if ((value = match_key(key))) { + *(f32*)target = std::atof(value); + return; + } + break; + case TYPE_STRING: + if ((value = match_key(key))) { + *(std::string*)target = value; + return; + } + break; + case TYPE_IVEC2: { + ivec2* v = (ivec2*)target; + if ((value = match_key(key + "X"))) { + v->x = std::atoi(value); + return; + } + if ((value = match_key(key + "Y"))) { + v->y = std::atoi(value); + return; + } + break; } + case TYPE_IVEC2_WH: { + ivec2* v = (ivec2*)target; + if ((value = match_key(key + "W"))) { + v->x = std::atoi(value); + return; + } + if ((value = match_key(key + "H"))) { + v->y = std::atoi(value); + return; + } + break; + }; + case TYPE_VEC2: { + vec2* v = (vec2*)target; + if ((value = match_key(key + "X"))) { + v->x = std::atof(value); + return; + } + if ((value = match_key(key + "Y"))) { + v->y = std::atof(value); + return; + } + break; + } + case TYPE_VEC2_WH: { + vec2* v = (vec2*)target; + if ((value = match_key(key + "W"))) { + v->x = std::atof(value); + return; + } + if ((value = match_key(key + "H"))) { + v->y = std::atof(value); + return; + } + break; + }; + case TYPE_VEC3: { + vec3* v = (vec3*)target; + if ((value = match_key(key + "R"))) { + v->x = std::atof(value); + return; + } + if ((value = match_key(key + "G"))) { + v->y = std::atof(value); + return; + } + if ((value = match_key(key + "B"))) { + v->z = std::atof(value); + return; + } + break; + } + case TYPE_VEC4: { + vec4* v = (vec4*)target; + if ((value = match_key(key + "R"))) { + v->x = std::atof(value); + return; + } + if ((value = match_key(key + "G"))) { + v->y = std::atof(value); + return; + } + if ((value = match_key(key + "B"))) { + v->z = std::atof(value); + return; + } + if ((value = match_key(key + "A"))) { + v->w = std::atof(value); + return; + } + break; + } + default: + break; + } + } - out.close(); + log_warning(std::format(SETTINGS_VALUE_INIT_WARNING, line)); +} +std::string settings_path_get(void) { + std::string filePath = preferences_path_get() + SETTINGS_PATH; + return filePath; +} + +static void _settings_setting_write(Settings* self, std::ostream& out, SettingsEntry entry) { + u8* selfPointer = (u8*)self; + std::string value; + + switch (entry.type) { + case TYPE_INT: + value = std::format("{}", *(int*)(selfPointer + entry.offset)); + out << entry.key << "=" << value << "\n"; + break; + case TYPE_BOOL: + value = std::format("{}", *(bool*)(selfPointer + entry.offset)); + out << entry.key << "=" << value << "\n"; + break; + case TYPE_FLOAT: + value = std::format("{:.3f}", *(f32*)(selfPointer + entry.offset)); + out << entry.key << "=" << value << "\n"; + break; + case TYPE_STRING: { + const std::string data = *reinterpret_cast(selfPointer + entry.offset); + if (!data.empty()) + out << entry.key << "=" << data.c_str() << "\n"; + break; + } + case TYPE_IVEC2: { + ivec2* data = (ivec2*)(selfPointer + entry.offset); + out << entry.key << "X=" << data->x << "\n"; + out << entry.key << "Y=" << data->y << "\n"; + break; + } + case TYPE_IVEC2_WH: { + ivec2* data = (ivec2*)(selfPointer + entry.offset); + out << entry.key << "W=" << data->x << "\n"; + out << entry.key << "H=" << data->y << "\n"; + break; + } + case TYPE_VEC2: { + vec2* data = (vec2*)(selfPointer + entry.offset); + out << entry.key << "X=" << std::format(SETTINGS_FLOAT_FORMAT, data->x) << "\n"; + out << entry.key << "Y=" << std::format(SETTINGS_FLOAT_FORMAT, data->y) << "\n"; + break; + } + case TYPE_VEC2_WH: { + vec2* data = (vec2*)(selfPointer + entry.offset); + out << entry.key << "W=" << std::format(SETTINGS_FLOAT_FORMAT, data->x) << "\n"; + out << entry.key << "H=" << std::format(SETTINGS_FLOAT_FORMAT, data->y) << "\n"; + break; + } + case TYPE_VEC3: { + vec3* data = (vec3*)(selfPointer + entry.offset); + out << entry.key << "R=" << std::format(SETTINGS_FLOAT_FORMAT, data->r) << "\n"; + out << entry.key << "G=" << std::format(SETTINGS_FLOAT_FORMAT, data->g) << "\n"; + out << entry.key << "B=" << std::format(SETTINGS_FLOAT_FORMAT, data->b) << "\n"; + break; + } + case TYPE_VEC4: { + vec4* data = (vec4*)(selfPointer + entry.offset); + out << entry.key << "R=" << std::format(SETTINGS_FLOAT_FORMAT, data->r) << "\n"; + out << entry.key << "G=" << std::format(SETTINGS_FLOAT_FORMAT, data->g) << "\n"; + out << entry.key << "B=" << std::format(SETTINGS_FLOAT_FORMAT, data->b) << "\n"; + out << entry.key << "A=" << std::format(SETTINGS_FLOAT_FORMAT, data->a) << "\n"; + break; + } + default: + break; + } +} + +void settings_save(Settings* self) { + const std::string path = settings_path_get(); + const std::filesystem::path filesystemPath(path); + const std::filesystem::path directory = filesystemPath.parent_path(); + + if (!directory.empty()) { std::error_code errorCode; - std::filesystem::rename(temp, filesystemPath, errorCode); - if (errorCode) - { - // Windows can block rename if target exists; try remove+rename - std::filesystem::remove(filesystemPath, errorCode); - errorCode = {}; - std::filesystem::rename(temp, filesystemPath, errorCode); - if (errorCode) - { - log_error(std::format(SETTINGS_SAVE_FINALIZE_ERROR, filesystemPath.string(), errorCode.message())); - std::filesystem::remove(temp); - return; - } + std::filesystem::create_directories(directory, errorCode); + if (errorCode) { + log_error(std::format(SETTINGS_DIRECTORY_ERROR, directory.string(), errorCode.message())); + return; } + } - log_info(std::format(SETTINGS_SAVE_INFO, path)); + std::string data; + if (std::filesystem::exists(filesystemPath)) { + if (std::ifstream in(path, std::ios::binary); in) + data.assign(std::istreambuf_iterator(in), std::istreambuf_iterator()); + } + + std::filesystem::path temp = filesystemPath; + temp += SETTINGS_TEMPORARY_EXTENSION; + + std::ofstream out(temp, std::ios::binary | std::ios::trunc); + if (!out) { + log_error(std::format(SETTINGS_INIT_ERROR, temp.string())); + return; + } + + out << SETTINGS_SECTION << "\n"; + for (int i = 0; i < SETTINGS_COUNT; i++) + _settings_setting_write(self, out, SETTINGS_ENTRIES[i]); + + out << "\n" << SETTINGS_SECTION_IMGUI << "\n"; + out << data; + + out.flush(); + + if (!out.good()) { + log_error(std::format(SETTINGS_SAVE_ERROR, temp.string())); + return; + } + + out.close(); + + std::error_code errorCode; + std::filesystem::rename(temp, filesystemPath, errorCode); + if (errorCode) { + // Windows can block rename if target exists; try remove+rename + std::filesystem::remove(filesystemPath, errorCode); + errorCode = {}; + std::filesystem::rename(temp, filesystemPath, errorCode); + if (errorCode) { + log_error(std::format(SETTINGS_SAVE_FINALIZE_ERROR, filesystemPath.string(), errorCode.message())); + std::filesystem::remove(temp); + return; + } + } + + log_info(std::format(SETTINGS_SAVE_INFO, path)); } -void settings_init(Settings* self) -{ - const std::string path = settings_path_get(); - std::ifstream file(path, std::ios::binary); +void settings_init(Settings* self) { + const std::string path = settings_path_get(); + std::ifstream file(path, std::ios::binary); - if (file) - log_info(std::format(SETTINGS_INIT_INFO, path)); - else - { - log_warning(std::format(SETTINGS_INIT_WARNING, path)); - settings_save(self); - std::ofstream out(path, std::ios::binary | std::ios::app); - out << SETTINGS_IMGUI_DEFAULT; - out.flush(); - out.close(); - file.open(path, std::ios::binary); - } - - std::string line; - bool inSettingsSection = false; - - while (std::getline(file, line)) - { - if (line == SETTINGS_SECTION) - { - inSettingsSection = true; - continue; - } - if (line.empty()) continue; - if (line == SETTINGS_SECTION_IMGUI) break; - if (inSettingsSection) _settings_setting_load(self, line); + if (file) + log_info(std::format(SETTINGS_INIT_INFO, path)); + else { + log_warning(std::format(SETTINGS_INIT_WARNING, path)); + settings_save(self); + std::ofstream out(path, std::ios::binary | std::ios::app); + out << SETTINGS_IMGUI_DEFAULT; + out.flush(); + out.close(); + file.open(path, std::ios::binary); + } + + std::string line; + bool inSettingsSection = false; + + while (std::getline(file, line)) { + if (line == SETTINGS_SECTION) { + inSettingsSection = true; + continue; } + if (line.empty()) + continue; + if (line == SETTINGS_SECTION_IMGUI) + break; + if (inSettingsSection) + _settings_setting_load(self, line); + } } \ No newline at end of file diff --git a/src/settings.h b/src/settings.h index d56edd9..5271063 100644 --- a/src/settings.h +++ b/src/settings.h @@ -26,235 +26,240 @@ #define SETTINGS_RENDER_FFMPEG_PATH_VALUE_DEFAULT "/usr/bin/ffmpeg" #endif -#define SETTINGS_LIST \ - /* name, symbol, type, defaultValue */ \ - X(windowSize, WINDOW_SIZE, TYPE_IVEC2_WH, {1600, 900}) \ - X(isVsync, IS_VSYNC, TYPE_BOOL, true) \ - \ - X(hotkeyCenterView, HOTKEY_CENTER_VIEW, TYPE_STRING, "Home") \ - X(hotkeyFit, HOTKEY_FIT, TYPE_STRING, "F") \ - X(hotkeyZoomIn, HOTKEY_ZOOM_IN, TYPE_STRING, "Ctrl++") \ - X(hotkeyZoomOut, HOTKEY_ZOOM_OUT, TYPE_STRING, "Ctrl+-") \ - X(hotkeyPlayPause, HOTKEY_PLAY_PAUSE, TYPE_STRING, "Space") \ - X(hotkeyOnionskin, HOTKEY_ONIONSKIN, TYPE_STRING, "O") \ - X(hotkeyNew, HOTKEY_NEW, TYPE_STRING, "Ctrl+N") \ - X(hotkeyOpen, HOTKEY_OPEN, TYPE_STRING, "Ctrl+O") \ - X(hotkeySave, HOTKEY_SAVE, TYPE_STRING, "Ctrl+S") \ - X(hotkeySaveAs, HOTKEY_SAVE_AS, TYPE_STRING, "Ctrl+Shift+S") \ - X(hotkeyExit, HOTKEY_EXIT, TYPE_STRING, "Alt+F4") \ - X(hotkeyPan, HOTKEY_PAN, TYPE_STRING, "P") \ - X(hotkeyMove, HOTKEY_MOVE, TYPE_STRING, "V") \ - X(hotkeyRotate, HOTKEY_ROTATE, TYPE_STRING, "R") \ - X(hotkeyScale, HOTKEY_SCALE, TYPE_STRING, "S") \ - X(hotkeyCrop, HOTKEY_CROP, TYPE_STRING, "C") \ - X(hotkeyDraw, HOTKEY_DRAW, TYPE_STRING, "B") \ - X(hotkeyErase, HOTKEY_ERASE, TYPE_STRING, "E") \ - X(hotkeyColorPicker, HOTKEY_COLOR_PICKER, TYPE_STRING, "I") \ - X(hotkeyUndo, HOTKEY_UNDO, TYPE_STRING, "Ctrl+Z") \ - X(hotkeyRedo, HOTKEY_REDO, TYPE_STRING, "Ctrl+Shift+Z") \ - X(hotkeyCopy, HOTKEY_COPY, TYPE_STRING, "Ctrl+C") \ - X(hotkeyCut, HOTKEY_CUT, TYPE_STRING, "Ctrl+X") \ - X(hotkeyPaste, HOTKEY_PASTE, TYPE_STRING, "Ctrl+V") \ - \ - X(playbackIsLoop, PLAYBACK_IS_LOOP, TYPE_BOOL, true) \ - X(playbackIsClampPlayhead,PLAYBACK_IS_CLAMP_PLAYHEAD, TYPE_BOOL, true) \ - \ - X(changeIsCrop, CHANGE_IS_CROP, TYPE_BOOL, false) \ - X(changeIsSize, CHANGE_IS_SIZE, TYPE_BOOL, false) \ - X(changeIsPosition, CHANGE_IS_POSITION, TYPE_BOOL, false) \ - X(changeIsPivot, CHANGE_IS_PIVOT, TYPE_BOOL, false) \ - X(changeIsScale, CHANGE_IS_SCALE, TYPE_BOOL, false) \ - X(changeIsRotation, CHANGE_IS_ROTATION, TYPE_BOOL, false) \ - X(changeIsDelay, CHANGE_IS_DELAY, TYPE_BOOL, false) \ - X(changeIsTint, CHANGE_IS_TINT, TYPE_BOOL, false) \ - X(changeIsColorOffset, CHANGE_IS_COLOR_OFFSET, TYPE_BOOL, false) \ - X(changeIsVisibleSet, CHANGE_IS_VISIBLE_SET, TYPE_BOOL, false) \ - X(changeIsInterpolatedSet,CHANGE_IS_INTERPOLATED_SET, TYPE_BOOL, false) \ - X(changeIsFromSelectedFrame,CHANGE_IS_FROM_SELECTED_FRAME,TYPE_BOOL, false) \ - X(changeCrop, CHANGE_CROP, TYPE_VEC2, {}) \ - X(changeSize, CHANGE_SIZE, TYPE_VEC2, {}) \ - X(changePosition, CHANGE_POSITION, TYPE_VEC2, {}) \ - X(changePivot, CHANGE_PIVOT, TYPE_VEC2, {}) \ - X(changeScale, CHANGE_SCALE, TYPE_VEC2, {}) \ - X(changeRotation, CHANGE_ROTATION, TYPE_FLOAT, 0.0f) \ - X(changeDelay, CHANGE_DELAY, TYPE_INT, 0) \ - X(changeTint, CHANGE_TINT, TYPE_VEC4, {}) \ - X(changeColorOffset, CHANGE_COLOR_OFFSET, TYPE_VEC3, {}) \ - X(changeIsVisible, CHANGE_IS_VISIBLE, TYPE_BOOL, false) \ - X(changeIsInterpolated, CHANGE_IS_INTERPOLATED, TYPE_BOOL, false) \ - X(changeNumberFrames, CHANGE_NUMBER_FRAMES, TYPE_INT, 1) \ - \ - X(scaleValue, SCALE_VALUE, TYPE_FLOAT, 1.0f) \ - \ - X(previewIsAxes, PREVIEW_IS_AXES, TYPE_BOOL, true) \ - X(previewIsGrid, PREVIEW_IS_GRID, TYPE_BOOL, true) \ - X(previewIsRootTransform, PREVIEW_IS_ROOT_TRANSFORM, TYPE_BOOL, true) \ - X(previewIsTriggers, PREVIEW_IS_TRIGGERS, TYPE_BOOL, true) \ - X(previewIsPivots, PREVIEW_IS_PIVOTS, TYPE_BOOL, false) \ - X(previewIsIcons, PREVIEW_IS_ICONS, TYPE_BOOL, true) \ - X(previewIsBorder, PREVIEW_IS_BORDER, TYPE_BOOL, false) \ - X(previewIsAltIcons, PREVIEW_IS_ALT_ICONS, TYPE_BOOL, false) \ - X(previewOverlayTransparency,PREVIEW_OVERLAY_TRANSPARENCY,TYPE_FLOAT, 255.0f) \ - X(previewZoom, PREVIEW_ZOOM, TYPE_FLOAT, 200.0f) \ - X(previewPan, PREVIEW_PAN, TYPE_VEC2, {}) \ - X(previewGridSize, PREVIEW_GRID_SIZE, TYPE_IVEC2, {32,32}) \ - X(previewGridOffset, PREVIEW_GRID_OFFSET, TYPE_IVEC2, {}) \ - X(previewGridColor, PREVIEW_GRID_COLOR, TYPE_VEC4, {1.0,1.0,1.0,0.125}) \ - X(previewAxesColor, PREVIEW_AXES_COLOR, TYPE_VEC4, {1.0,1.0,1.0,0.125}) \ - X(previewBackgroundColor, PREVIEW_BACKGROUND_COLOR, TYPE_VEC4, {0.113,0.184,0.286,1.0}) \ - \ - X(propertiesIsRound, PROPERTIES_IS_ROUND, TYPE_BOOL, false) \ - \ - X(generateStartPosition, GENERATE_START_POSITION, TYPE_IVEC2, {}) \ - X(generateSize, GENERATE_SIZE, TYPE_IVEC2, {64,64}) \ - X(generatePivot, GENERATE_PIVOT, TYPE_IVEC2, {32,32}) \ - X(generateRows, GENERATE_ROWS, TYPE_INT, 4) \ - X(generateColumns, GENERATE_COLUMNS, TYPE_INT, 4) \ - X(generateCount, GENERATE_COUNT, TYPE_INT, 16) \ - X(generateDelay, GENERATE_DELAY, TYPE_INT, 1) \ - \ - X(editorIsGrid, EDITOR_IS_GRID, TYPE_BOOL, true) \ - X(editorIsGridSnap, EDITOR_IS_GRID_SNAP, TYPE_BOOL, true) \ - X(editorIsBorder, EDITOR_IS_BORDER, TYPE_BOOL, true) \ - X(editorZoom, EDITOR_ZOOM, TYPE_FLOAT, 200.0f) \ - X(editorPan, EDITOR_PAN, TYPE_VEC2, {0.0,0.0}) \ - X(editorGridSize, EDITOR_GRID_SIZE, TYPE_IVEC2, {32,32}) \ - X(editorGridOffset, EDITOR_GRID_OFFSET, TYPE_IVEC2, {32,32}) \ - X(editorGridColor, EDITOR_GRID_COLOR, TYPE_VEC4, {1.0,1.0,1.0,0.125}) \ - X(editorBackgroundColor, EDITOR_BACKGROUND_COLOR, TYPE_VEC4, {0.113,0.184,0.286,1.0}) \ - \ - X(mergeType, MERGE_TYPE, TYPE_INT, ANM2_MERGE_APPEND) \ - X(mergeIsDeleteAnimationsAfter,MERGE_IS_DELETE_ANIMATIONS_AFTER,TYPE_BOOL, false) \ - \ - X(bakeInterval, BAKE_INTERVAL, TYPE_INT, 1) \ - X(bakeIsRoundScale, BAKE_IS_ROUND_SCALE, TYPE_BOOL, true) \ - X(bakeIsRoundRotation, BAKE_IS_ROUND_ROTATION, TYPE_BOOL, true) \ - \ - X(timelineAddItemType, TIMELINE_ADD_ITEM_TYPE, TYPE_INT, ANM2_LAYER) \ - X(timelineIsShowUnused, TIMELINE_IS_SHOW_UNUSED, TYPE_BOOL, true) \ - \ - X(onionskinIsEnabled, ONIONSKIN_IS_ENABLED, TYPE_BOOL, false) \ - X(onionskinDrawOrder, ONIONSKIN_DRAW_ORDER, TYPE_INT, ONIONSKIN_BELOW) \ - X(onionskinBeforeCount, ONIONSKIN_BEFORE_COUNT, TYPE_INT, 0) \ - X(onionskinAfterCount, ONIONSKIN_AFTER_COUNT, TYPE_INT, 0) \ - X(onionskinBeforeColorOffset,ONIONSKIN_BEFORE_COLOR_OFFSET,TYPE_VEC3, COLOR_RED) \ - X(onionskinAfterColorOffset, ONIONSKIN_AFTER_COLOR_OFFSET,TYPE_VEC3, COLOR_BLUE) \ - \ - X(tool, TOOL, TYPE_INT, TOOL_PAN) \ - X(toolColor, TOOL_COLOR, TYPE_VEC4, {1.0,1.0,1.0,1.0}) \ - \ - X(renderType, RENDER_TYPE, TYPE_INT, RENDER_PNG) \ - X(renderPath, RENDER_PATH, TYPE_STRING, ".") \ - X(renderFormat, RENDER_FORMAT, TYPE_STRING, "{}.png") \ - X(renderIsUseAnimationBounds,RENDER_IS_USE_ANIMATION_BOUNDS,TYPE_BOOL, true) \ - X(renderIsTransparent, RENDER_IS_TRANSPARENT, TYPE_BOOL, true) \ - X(renderScale, RENDER_SCALE, TYPE_FLOAT, 1.0f) \ - X(renderFFmpegPath, RENDER_FFMPEG_PATH, TYPE_STRING, SETTINGS_RENDER_FFMPEG_PATH_VALUE_DEFAULT) +#define SETTINGS_LIST \ + /* Symbol / Name / Type / Default */ \ + X(WINDOW_SIZE, windowSize, TYPE_IVEC2_WH, {1600, 900}) \ + X(IS_VSYNC, isVsync, TYPE_BOOL, true) \ + X(DISPLAY_SCALE, displayScale, TYPE_FLOAT, 1.0f) \ + \ + X(HOTKEY_CENTER_VIEW, hotkeyCenterView, TYPE_STRING, "Home") \ + X(HOTKEY_FIT, hotkeyFit, TYPE_STRING, "F") \ + X(HOTKEY_ZOOM_IN, hotkeyZoomIn, TYPE_STRING, "Ctrl++") \ + X(HOTKEY_ZOOM_OUT, hotkeyZoomOut, TYPE_STRING, "Ctrl+-") \ + X(HOTKEY_PLAY_PAUSE, hotkeyPlayPause, TYPE_STRING, "Space") \ + X(HOTKEY_ONIONSKIN, hotkeyOnionskin, TYPE_STRING, "O") \ + X(HOTKEY_NEW, hotkeyNew, TYPE_STRING, "Ctrl+N") \ + X(HOTKEY_OPEN, hotkeyOpen, TYPE_STRING, "Ctrl+O") \ + X(HOTKEY_SAVE, hotkeySave, TYPE_STRING, "Ctrl+S") \ + X(HOTKEY_SAVE_AS, hotkeySaveAs, TYPE_STRING, "Ctrl+Shift+S") \ + X(HOTKEY_EXIT, hotkeyExit, TYPE_STRING, "Alt+F4") \ + X(HOTKEY_SHORTEN_FRAME, hotkeyShortenFrame, TYPE_STRING, "F4") \ + X(HOTKEY_EXTEND_FRAME, hotkeyExtendFrame, TYPE_STRING, "F5") \ + X(HOTKEY_INSERT_FRAME, hotkeyInsertFrame, TYPE_STRING, "F6") \ + X(HOTKEY_PREVIOUS_FRAME, hotkeyPreviousFrame, TYPE_STRING, "Comma") \ + X(HOTKEY_NEXT_FRAME, hotkeyNextFrame, TYPE_STRING, "Period") \ + X(HOTKEY_PAN, hotkeyPan, TYPE_STRING, "P") \ + X(HOTKEY_MOVE, hotkeyMove, TYPE_STRING, "V") \ + X(HOTKEY_ROTATE, hotkeyRotate, TYPE_STRING, "R") \ + X(HOTKEY_SCALE, hotkeyScale, TYPE_STRING, "S") \ + X(HOTKEY_CROP, hotkeyCrop, TYPE_STRING, "C") \ + X(HOTKEY_DRAW, hotkeyDraw, TYPE_STRING, "B") \ + X(HOTKEY_ERASE, hotkeyErase, TYPE_STRING, "E") \ + X(HOTKEY_COLOR_PICKER, hotkeyColorPicker, TYPE_STRING, "I") \ + X(HOTKEY_UNDO, hotkeyUndo, TYPE_STRING, "Ctrl+Z") \ + X(HOTKEY_REDO, hotkeyRedo, TYPE_STRING, "Ctrl+Shift+Z") \ + X(HOTKEY_COPY, hotkeyCopy, TYPE_STRING, "Ctrl+C") \ + X(HOTKEY_CUT, hotkeyCut, TYPE_STRING, "Ctrl+X") \ + X(HOTKEY_PASTE, hotkeyPaste, TYPE_STRING, "Ctrl+V") \ + \ + X(PLAYBACK_IS_LOOP, playbackIsLoop, TYPE_BOOL, true) \ + X(PLAYBACK_IS_CLAMP_PLAYHEAD, playbackIsClampPlayhead, TYPE_BOOL, true) \ + \ + X(CHANGE_IS_CROP, changeIsCrop, TYPE_BOOL, false) \ + X(CHANGE_IS_SIZE, changeIsSize, TYPE_BOOL, false) \ + X(CHANGE_IS_POSITION, changeIsPosition, TYPE_BOOL, false) \ + X(CHANGE_IS_PIVOT, changeIsPivot, TYPE_BOOL, false) \ + X(CHANGE_IS_SCALE, changeIsScale, TYPE_BOOL, false) \ + X(CHANGE_IS_ROTATION, changeIsRotation, TYPE_BOOL, false) \ + X(CHANGE_IS_DELAY, changeIsDelay, TYPE_BOOL, false) \ + X(CHANGE_IS_TINT, changeIsTint, TYPE_BOOL, false) \ + X(CHANGE_IS_COLOR_OFFSET, changeIsColorOffset, TYPE_BOOL, false) \ + X(CHANGE_IS_VISIBLE_SET, changeIsVisibleSet, TYPE_BOOL, false) \ + X(CHANGE_IS_INTERPOLATED_SET, changeIsInterpolatedSet, TYPE_BOOL, false) \ + X(CHANGE_IS_FROM_SELECTED_FRAME, changeIsFromSelectedFrame, TYPE_BOOL, false) \ + X(CHANGE_CROP, changeCrop, TYPE_VEC2, {}) \ + X(CHANGE_SIZE, changeSize, TYPE_VEC2, {}) \ + X(CHANGE_POSITION, changePosition, TYPE_VEC2, {}) \ + X(CHANGE_PIVOT, changePivot, TYPE_VEC2, {}) \ + X(CHANGE_SCALE, changeScale, TYPE_VEC2, {}) \ + X(CHANGE_ROTATION, changeRotation, TYPE_FLOAT, 0.0f) \ + X(CHANGE_DELAY, changeDelay, TYPE_INT, 0) \ + X(CHANGE_TINT, changeTint, TYPE_VEC4, {}) \ + X(CHANGE_COLOR_OFFSET, changeColorOffset, TYPE_VEC3, {}) \ + X(CHANGE_IS_VISIBLE, changeIsVisible, TYPE_BOOL, false) \ + X(CHANGE_IS_INTERPOLATED, changeIsInterpolated, TYPE_BOOL, false) \ + X(CHANGE_NUMBER_FRAMES, changeNumberFrames, TYPE_INT, 1) \ + \ + X(SCALE_VALUE, scaleValue, TYPE_FLOAT, 1.0f) \ + \ + X(PREVIEW_IS_AXES, previewIsAxes, TYPE_BOOL, true) \ + X(PREVIEW_IS_GRID, previewIsGrid, TYPE_BOOL, true) \ + X(PREVIEW_IS_ROOT_TRANSFORM, previewIsRootTransform, TYPE_BOOL, true) \ + X(PREVIEW_IS_TRIGGERS, previewIsTriggers, TYPE_BOOL, true) \ + X(PREVIEW_IS_PIVOTS, previewIsPivots, TYPE_BOOL, false) \ + X(PREVIEW_IS_ICONS, previewIsIcons, TYPE_BOOL, true) \ + X(PREVIEW_IS_BORDER, previewIsBorder, TYPE_BOOL, false) \ + X(PREVIEW_IS_ALT_ICONS, previewIsAltIcons, TYPE_BOOL, false) \ + X(PREVIEW_OVERLAY_TRANSPARENCY, previewOverlayTransparency, TYPE_FLOAT, 255.0f) \ + X(PREVIEW_ZOOM, previewZoom, TYPE_FLOAT, 200.0f) \ + X(PREVIEW_PAN, previewPan, TYPE_VEC2, {}) \ + X(PREVIEW_GRID_SIZE, previewGridSize, TYPE_IVEC2, {32, 32}) \ + X(PREVIEW_GRID_OFFSET, previewGridOffset, TYPE_IVEC2, {}) \ + X(PREVIEW_GRID_COLOR, previewGridColor, TYPE_VEC4, {1.0, 1.0, 1.0, 0.125}) \ + X(PREVIEW_AXES_COLOR, previewAxesColor, TYPE_VEC4, {1.0, 1.0, 1.0, 0.125}) \ + X(PREVIEW_BACKGROUND_COLOR, previewBackgroundColor, TYPE_VEC4, {0.113, 0.184, 0.286, 1.0}) \ + \ + X(PROPERTIES_IS_ROUND, propertiesIsRound, TYPE_BOOL, false) \ + \ + X(GENERATE_START_POSITION, generateStartPosition, TYPE_IVEC2, {}) \ + X(GENERATE_SIZE, generateSize, TYPE_IVEC2, {64, 64}) \ + X(GENERATE_PIVOT, generatePivot, TYPE_IVEC2, {32, 32}) \ + X(GENERATE_ROWS, generateRows, TYPE_INT, 4) \ + X(GENERATE_COLUMNS, generateColumns, TYPE_INT, 4) \ + X(GENERATE_COUNT, generateCount, TYPE_INT, 16) \ + X(GENERATE_DELAY, generateDelay, TYPE_INT, 1) \ + \ + X(EDITOR_IS_GRID, editorIsGrid, TYPE_BOOL, true) \ + X(EDITOR_IS_GRID_SNAP, editorIsGridSnap, TYPE_BOOL, true) \ + X(EDITOR_IS_BORDER, editorIsBorder, TYPE_BOOL, true) \ + X(EDITOR_ZOOM, editorZoom, TYPE_FLOAT, 200.0f) \ + X(EDITOR_PAN, editorPan, TYPE_VEC2, {0.0, 0.0}) \ + X(EDITOR_GRID_SIZE, editorGridSize, TYPE_IVEC2, {32, 32}) \ + X(EDITOR_GRID_OFFSET, editorGridOffset, TYPE_IVEC2, {32, 32}) \ + X(EDITOR_GRID_COLOR, editorGridColor, TYPE_VEC4, {1.0, 1.0, 1.0, 0.125}) \ + X(EDITOR_BACKGROUND_COLOR, editorBackgroundColor, TYPE_VEC4, {0.113, 0.184, 0.286, 1.0}) \ + \ + X(MERGE_TYPE, mergeType, TYPE_INT, ANM2_MERGE_APPEND) \ + X(MERGE_IS_DELETE_ANIMATIONS_AFTER, mergeIsDeleteAnimationsAfter, TYPE_BOOL, false) \ + \ + X(BAKE_INTERVAL, bakeInterval, TYPE_INT, 1) \ + X(BAKE_IS_ROUND_SCALE, bakeIsRoundScale, TYPE_BOOL, true) \ + X(BAKE_IS_ROUND_ROTATION, bakeIsRoundRotation, TYPE_BOOL, true) \ + \ + X(TIMELINE_ADD_ITEM_TYPE, timelineAddItemType, TYPE_INT, ANM2_LAYER) \ + X(TIMELINE_IS_SHOW_UNUSED, timelineIsShowUnused, TYPE_BOOL, true) \ + \ + X(ONIONSKIN_IS_ENABLED, onionskinIsEnabled, TYPE_BOOL, false) \ + X(ONIONSKIN_DRAW_ORDER, onionskinDrawOrder, TYPE_INT, ONIONSKIN_BELOW) \ + X(ONIONSKIN_BEFORE_COUNT, onionskinBeforeCount, TYPE_INT, 0) \ + X(ONIONSKIN_AFTER_COUNT, onionskinAfterCount, TYPE_INT, 0) \ + X(ONIONSKIN_BEFORE_COLOR_OFFSET, onionskinBeforeColorOffset, TYPE_VEC3, COLOR_RED) \ + X(ONIONSKIN_AFTER_COLOR_OFFSET, onionskinAfterColorOffset, TYPE_VEC3, COLOR_BLUE) \ + \ + X(TOOL, tool, TYPE_INT, TOOL_PAN) \ + X(TOOL_COLOR, toolColor, TYPE_VEC4, {1.0, 1.0, 1.0, 1.0}) \ + \ + X(RENDER_TYPE, renderType, TYPE_INT, RENDER_PNG) \ + X(RENDER_PATH, renderPath, TYPE_STRING, ".") \ + X(RENDER_FORMAT, renderFormat, TYPE_STRING, "{}.png") \ + X(RENDER_IS_USE_ANIMATION_BOUNDS, renderIsUseAnimationBounds, TYPE_BOOL, true) \ + X(RENDER_IS_TRANSPARENT, renderIsTransparent, TYPE_BOOL, true) \ + X(RENDER_SCALE, renderScale, TYPE_FLOAT, 1.0f) \ + X(RENDER_FFMPEG_PATH, renderFFmpegPath, TYPE_STRING, SETTINGS_RENDER_FFMPEG_PATH_VALUE_DEFAULT) -#define X(name, symbol, type, ...) \ -const inline DATATYPE_TO_CTYPE(type) SETTINGS_##symbol##_DEFAULT = __VA_ARGS__; +#define X(symbol, name, type, ...) const inline DATATYPE_TO_CTYPE(type) SETTINGS_##symbol##_DEFAULT = __VA_ARGS__; SETTINGS_LIST #undef X -struct Settings -{ - #define X(name, symbol, type, ...) \ - DATATYPE_TO_CTYPE(type) name = SETTINGS_##symbol##_DEFAULT; +struct Settings { +#define X(symbol, name, type, ...) DATATYPE_TO_CTYPE(type) name = SETTINGS_##symbol##_DEFAULT; + SETTINGS_LIST +#undef X +}; + +struct SettingsEntry { + std::string key; + DataType type; + int offset; +}; + +const inline SettingsEntry SETTINGS_ENTRIES[] = { +#define X(symbol, name, type, ...) {#name, type, offsetof(Settings, name)}, SETTINGS_LIST - #undef X -}; - -struct SettingsEntry -{ - std::string key; - DataType type; - s32 offset; +#undef X }; -const inline SettingsEntry SETTINGS_ENTRIES[] = -{ - #define X(name, symbol, type, ...) \ - { #name, type, offsetof(Settings, name) }, - SETTINGS_LIST - #undef X -}; +constexpr int SETTINGS_COUNT = (int)std::size(SETTINGS_ENTRIES); -constexpr s32 SETTINGS_COUNT = (s32)std::size(SETTINGS_ENTRIES); +#define HOTKEY_LIST \ + X(NONE, "None") \ + X(CENTER_VIEW, "Center View") \ + X(FIT, "Fit") \ + X(ZOOM_IN, "Zoom In") \ + X(ZOOM_OUT, "Zoom Out") \ + X(PLAY_PAUSE, "Play/Pause") \ + X(ONIONSKIN, "Onionskin") \ + X(NEW, "New") \ + X(OPEN, "Open") \ + X(SAVE, "Save") \ + X(SAVE_AS, "Save As") \ + X(EXIT, "Exit") \ + X(SHORTEN_FRAME, "Shorten Frame") \ + X(EXTEND_FRAME, "Extend Frame") \ + X(INSERT_FRAME, "Insert Frame") \ + X(PREVIOUS_FRAME, "Previous Frame") \ + X(NEXT_FRAME, "Next Frame") \ + X(PAN, "Pan") \ + X(MOVE, "Move") \ + X(ROTATE, "Rotate") \ + X(SCALE, "Scale") \ + X(CROP, "Crop") \ + X(DRAW, "Draw") \ + X(ERASE, "Erase") \ + X(COLOR_PICKER, "Color Picker") \ + X(UNDO, "Undo") \ + X(REDO, "Redo") \ + X(COPY, "Copy") \ + X(CUT, "Cut") \ + X(PASTE, "Paste") -#define HOTKEY_LIST \ - X(NONE, "None") \ - X(CENTER_VIEW, "Center View") \ - X(FIT, "Fit") \ - X(ZOOM_IN, "Zoom In") \ - X(ZOOM_OUT, "Zoom Out") \ - X(PLAY_PAUSE, "Play/Pause") \ - X(ONIONSKIN, "Onionskin") \ - X(NEW, "New") \ - X(OPEN, "Open") \ - X(SAVE, "Save") \ - X(SAVE_AS, "Save As") \ - X(EXIT, "Exit") \ - X(PAN, "Pan") \ - X(MOVE, "Move") \ - X(ROTATE, "Rotate") \ - X(SCALE, "Scale") \ - X(CROP, "Crop") \ - X(DRAW, "Draw") \ - X(ERASE, "Erase") \ - X(COLOR_PICKER, "Color Picker") \ - X(UNDO, "Undo") \ - X(REDO, "Redo") \ - X(COPY, "Copy") \ - X(CUT, "Cut") \ - X(PASTE, "Paste") \ - -typedef enum -{ - #define X(name, str) HOTKEY_##name, - HOTKEY_LIST - #undef X - HOTKEY_COUNT +typedef enum { +#define X(name, str) HOTKEY_##name, + HOTKEY_LIST +#undef X + HOTKEY_COUNT } HotkeyType; -const inline char* HOTKEY_STRINGS[] = -{ - #define X(name, str) str, +const inline char* HOTKEY_STRINGS[] = { +#define X(name, str) str, HOTKEY_LIST - #undef X +#undef X }; using HotkeyMember = std::string Settings::*; -const inline HotkeyMember SETTINGS_HOTKEY_MEMBERS[HOTKEY_COUNT] = -{ - nullptr, - &Settings::hotkeyCenterView, - &Settings::hotkeyFit, - &Settings::hotkeyZoomIn, - &Settings::hotkeyZoomOut, - &Settings::hotkeyPlayPause, - &Settings::hotkeyOnionskin, - &Settings::hotkeyNew, - &Settings::hotkeyOpen, - &Settings::hotkeySave, - &Settings::hotkeySaveAs, - &Settings::hotkeyExit, - &Settings::hotkeyPan, - &Settings::hotkeyMove, - &Settings::hotkeyRotate, - &Settings::hotkeyScale, - &Settings::hotkeyCrop, - &Settings::hotkeyDraw, - &Settings::hotkeyErase, - &Settings::hotkeyColorPicker, - &Settings::hotkeyUndo, - &Settings::hotkeyRedo, - &Settings::hotkeyCopy, - &Settings::hotkeyCut, - &Settings::hotkeyPaste -}; +const inline HotkeyMember SETTINGS_HOTKEY_MEMBERS[HOTKEY_COUNT] = {nullptr, + &Settings::hotkeyCenterView, + &Settings::hotkeyFit, + &Settings::hotkeyZoomIn, + &Settings::hotkeyZoomOut, + &Settings::hotkeyPlayPause, + &Settings::hotkeyOnionskin, + &Settings::hotkeyNew, + &Settings::hotkeyOpen, + &Settings::hotkeySave, + &Settings::hotkeySaveAs, + &Settings::hotkeyExit, + &Settings::hotkeyShortenFrame, + &Settings::hotkeyExtendFrame, + &Settings::hotkeyInsertFrame, + &Settings::hotkeyPreviousFrame, + &Settings::hotkeyNextFrame, + &Settings::hotkeyPan, + &Settings::hotkeyMove, + &Settings::hotkeyRotate, + &Settings::hotkeyScale, + &Settings::hotkeyCrop, + &Settings::hotkeyDraw, + &Settings::hotkeyErase, + &Settings::hotkeyColorPicker, + &Settings::hotkeyUndo, + &Settings::hotkeyRedo, + &Settings::hotkeyCopy, + &Settings::hotkeyCut, + &Settings::hotkeyPaste}; -const std::string SETTINGS_IMGUI_DEFAULT = R"( +const inline std::string SETTINGS_IMGUI_DEFAULT = R"( # Dear ImGui [Window][## Window] Pos=0,32 diff --git a/src/shader.cpp b/src/shader.cpp index 514265b..2eac5ec 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -1,53 +1,49 @@ #include "shader.h" -static bool _shader_compile(GLuint* self, const std::string& text) -{ - s32 isCompile; - const GLchar* source = text.c_str(); +static bool _shader_compile(GLuint* self, const std::string& text) { + int isCompile; + const GLchar* source = text.c_str(); - glShaderSource(*self, 1, &source, nullptr); - glCompileShader(*self); - glGetShaderiv(*self, GL_COMPILE_STATUS, &isCompile); + glShaderSource(*self, 1, &source, nullptr); + glCompileShader(*self); + glGetShaderiv(*self, GL_COMPILE_STATUS, &isCompile); - if (!isCompile) - { - std::string compileLog(SHADER_INFO_LOG_MAX, '\0'); - glGetShaderInfoLog(*self, SHADER_INFO_LOG_MAX, nullptr, compileLog.data()); - log_error(std::format(SHADER_INIT_ERROR, *self, compileLog.c_str())); - return false; - } + if (!isCompile) { + std::string compileLog(SHADER_INFO_LOG_MAX, '\0'); + glGetShaderInfoLog(*self, SHADER_INFO_LOG_MAX, nullptr, compileLog.data()); + log_error(std::format(SHADER_INIT_ERROR, *self, compileLog.c_str())); + return false; + } - return true; + return true; } -// Initializes a given shader with vertex/fragment -bool shader_init(GLuint* self, const std::string& vertex, const std::string& fragment) -{ - GLuint vertexHandle; - GLuint fragmentHandle; +bool shader_init(GLuint* self, const std::string& vertex, const std::string& fragment) { + GLuint vertexHandle; + GLuint fragmentHandle; - vertexHandle = glCreateShader(GL_VERTEX_SHADER); - fragmentHandle = glCreateShader(GL_FRAGMENT_SHADER); + vertexHandle = glCreateShader(GL_VERTEX_SHADER); + fragmentHandle = glCreateShader(GL_FRAGMENT_SHADER); - if (!_shader_compile(&vertexHandle, vertex) || !_shader_compile(&fragmentHandle, fragment)) - return false; + if (!_shader_compile(&vertexHandle, vertex) || !_shader_compile(&fragmentHandle, fragment)) + return false; - *self = glCreateProgram(); + *self = glCreateProgram(); - glAttachShader(*self, vertexHandle); - glAttachShader(*self, fragmentHandle); + glAttachShader(*self, vertexHandle); + glAttachShader(*self, fragmentHandle); - glLinkProgram(*self); + glLinkProgram(*self); - glDeleteShader(vertexHandle); - glDeleteShader(fragmentHandle); + glDeleteShader(vertexHandle); + glDeleteShader(fragmentHandle); - return true; + return true; } -void shader_free(GLuint* self) -{ - if (*self == GL_ID_NONE) return; - - glDeleteProgram(*self); +void shader_free(GLuint* self) { + if (*self == GL_ID_NONE) + return; + + glDeleteProgram(*self); } \ No newline at end of file diff --git a/src/snapshots.cpp b/src/snapshots.cpp index 2c8cf46..a928af6 100644 --- a/src/snapshots.cpp +++ b/src/snapshots.cpp @@ -1,77 +1,67 @@ #include "snapshots.h" -static void _snapshot_stack_push(SnapshotStack* stack, Snapshot* snapshot) -{ - if (stack->top >= SNAPSHOT_STACK_MAX) - { - for (s32 i = 0; i < SNAPSHOT_STACK_MAX - 1; i++) - stack->snapshots[i] = stack->snapshots[i + 1]; - stack->top = SNAPSHOT_STACK_MAX - 1; - } - stack->snapshots[stack->top++] = *snapshot; +static void _snapshot_stack_push(SnapshotStack* stack, Snapshot* snapshot) { + if (stack->top >= SNAPSHOT_STACK_MAX) { + for (int i = 0; i < SNAPSHOT_STACK_MAX - 1; i++) + stack->snapshots[i] = stack->snapshots[i + 1]; + stack->top = SNAPSHOT_STACK_MAX - 1; + } + stack->snapshots[stack->top++] = *snapshot; } -static Snapshot* _snapshot_stack_pop(SnapshotStack* stack) -{ - if (stack->top == 0) return nullptr; - return &stack->snapshots[--stack->top]; +static Snapshot* _snapshot_stack_pop(SnapshotStack* stack) { + if (stack->top == 0) + return nullptr; + return &stack->snapshots[--stack->top]; } -static void _snapshot_set(Snapshots* self, Snapshot* snapshot) -{ - if (!snapshot) return; +static void _snapshot_set(Snapshots* self, Snapshot* snapshot) { + if (!snapshot) + return; - *self->anm2 = snapshot->anm2; - *self->reference = snapshot->reference; - self->preview->time = snapshot->time; - self->action = snapshot->action; + *self->anm2 = snapshot->anm2; + *self->reference = snapshot->reference; + self->preview->time = snapshot->time; + self->action = snapshot->action; - anm2_spritesheet_texture_pixels_upload(self->anm2); + anm2_spritesheet_texture_pixels_upload(self->anm2); } -Snapshot snapshot_get(Snapshots* self) -{ - Snapshot snapshot = {*self->anm2, *self->reference, self->preview->time, self->action}; - anm2_spritesheet_texture_pixels_download(&snapshot.anm2); - return snapshot; +Snapshot snapshot_get(Snapshots* self) { + Snapshot snapshot = {*self->anm2, *self->reference, self->preview->time, self->action}; + anm2_spritesheet_texture_pixels_download(&snapshot.anm2); + return snapshot; } -void snapshots_init(Snapshots* self, Anm2* anm2, Anm2Reference* reference, Preview* preview) -{ - self->anm2 = anm2; - self->reference = reference; - self->preview = preview; +void snapshots_init(Snapshots* self, Anm2* anm2, Anm2Reference* reference, Preview* preview) { + self->anm2 = anm2; + self->reference = reference; + self->preview = preview; } -void snapshots_reset(Snapshots* self) -{ - self->undoStack = SnapshotStack{}; - self->redoStack = SnapshotStack{}; - self->action.clear(); +void snapshots_reset(Snapshots* self) { + self->undoStack = SnapshotStack{}; + self->redoStack = SnapshotStack{}; + self->action.clear(); } -void snapshots_undo_push(Snapshots* self, Snapshot* snapshot) -{ - self->redoStack.top = 0; - _snapshot_stack_push(&self->undoStack, snapshot); +void snapshots_undo_push(Snapshots* self, Snapshot* snapshot) { + self->redoStack.top = 0; + _snapshot_stack_push(&self->undoStack, snapshot); } -void snapshots_undo(Snapshots* self) -{ - if (Snapshot* snapshot = _snapshot_stack_pop(&self->undoStack)) - { - Snapshot current = snapshot_get(self); - _snapshot_stack_push(&self->redoStack, ¤t); - _snapshot_set(self, snapshot); - } +void snapshots_undo(Snapshots* self) { + if (Snapshot* snapshot = _snapshot_stack_pop(&self->undoStack)) { + Snapshot current = snapshot_get(self); + _snapshot_stack_push(&self->redoStack, ¤t); + _snapshot_set(self, snapshot); + } } -void snapshots_redo(Snapshots* self) -{ - if (Snapshot* snapshot = _snapshot_stack_pop(&self->redoStack)) - { - Snapshot current = snapshot_get(self); - _snapshot_stack_push(&self->undoStack, ¤t); - _snapshot_set(self, snapshot); - } +void snapshots_redo(Snapshots* self) { + if (Snapshot* snapshot = _snapshot_stack_pop(&self->redoStack)) { + Snapshot current = snapshot_get(self); + _snapshot_stack_push(&self->undoStack, ¤t); + _snapshot_set(self, snapshot); + } } \ No newline at end of file diff --git a/src/snapshots.h b/src/snapshots.h index 3399a9d..b7d2cf9 100644 --- a/src/snapshots.h +++ b/src/snapshots.h @@ -2,35 +2,31 @@ #include "anm2.h" #include "preview.h" -#include "texture.h" #define SNAPSHOT_STACK_MAX 100 #define SNAPSHOT_ACTION "Action" -struct Snapshot -{ - Anm2 anm2; - Anm2Reference reference; - f32 time = 0.0f; - std::string action = SNAPSHOT_ACTION; +struct Snapshot { + Anm2 anm2; + Anm2Reference reference; + float time = 0.0f; + std::string action = SNAPSHOT_ACTION; }; -struct SnapshotStack -{ - Snapshot snapshots[SNAPSHOT_STACK_MAX]; - s32 top = 0; +struct SnapshotStack { + Snapshot snapshots[SNAPSHOT_STACK_MAX]; + int top = 0; - bool is_empty() const { return top == 0; } + bool is_empty() const { return top == 0; } }; -struct Snapshots -{ - Anm2* anm2 = nullptr; - Preview* preview = nullptr; - Anm2Reference* reference = nullptr; - std::string action = SNAPSHOT_ACTION; - SnapshotStack undoStack; - SnapshotStack redoStack; +struct Snapshots { + Anm2* anm2 = nullptr; + Preview* preview = nullptr; + Anm2Reference* reference = nullptr; + std::string action = SNAPSHOT_ACTION; + SnapshotStack undoStack; + SnapshotStack redoStack; }; void snapshots_undo_push(Snapshots* self, Snapshot* snapshot); diff --git a/src/state.h b/src/state.h index 79fbe9c..8a084ad 100644 --- a/src/state.h +++ b/src/state.h @@ -27,29 +27,28 @@ #define STATE_GL_VERSION_MAJOR 3 #define STATE_GL_VERSION_MINOR 3 -struct State -{ - SDL_Window* window; - SDL_GLContext glContext; - Imgui imgui; - Dialog dialog; - Editor editor; - Preview preview; - GeneratePreview generatePreview; - Anm2 anm2; - Anm2Reference reference; - Resources resources; - Settings settings; - Snapshots snapshots; - Clipboard clipboard; - std::string argument{}; - std::string lastAction{}; - u64 lastTick{}; - u64 tick{}; - u64 update{}; - u64 lastUpdate{}; - bool isRunning = true; -}; +struct State { + SDL_Window* window; + SDL_GLContext glContext; + Imgui imgui; + Dialog dialog; + Editor editor; + Preview preview; + GeneratePreview generatePreview; + Anm2 anm2; + Anm2Reference reference; + Resources resources; + Settings settings; + Snapshots snapshots; + Clipboard clipboard; + std::string argument{}; + std::string lastAction{}; + uint64_t lastTick{}; + uint64_t tick{}; + uint64_t update{}; + uint64_t lastUpdate{}; + bool isRunning = true; +}; bool sdl_init(State* self, bool isTestMode); void init(State* state); diff --git a/src/texture.cpp b/src/texture.cpp index 8b80bb2..1f2d52e 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -1,129 +1,100 @@ #if defined(__clang__) || defined(__GNUC__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wmissing-field-initializers" - #pragma GCC diagnostic ignored "-Wunused-function" - #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif #include "texture.h" -#define STBI_ONLY_PNG -#define STBI_NO_FAILURE_STRINGS +#define STBI_ONLY_PNG +#define STBI_NO_FAILURE_STRINGS #define STBI_NO_HDR #define STB_IMAGE_IMPLEMENTATION #include #define STB_IMAGE_WRITE_IMPLEMENTATION #include -static void _texture_gl_set(Texture* self, const u8* data) -{ - if (self->id == GL_ID_NONE) glGenTextures(1, &self->id); - - glBindTexture(GL_TEXTURE_2D, self->id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self->size.x, self->size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glBindTexture(GL_TEXTURE_2D, 0); +static void _texture_gl_set(Texture* self, const uint8_t* data) { + if (self->id == GL_ID_NONE) + glGenTextures(1, &self->id); + + glBindTexture(GL_TEXTURE_2D, self->id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self->size.x, self->size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glBindTexture(GL_TEXTURE_2D, 0); } -std::vector texture_download(const Texture* self) -{ - std::vector pixels(self->size.x * self->size.y * TEXTURE_CHANNELS); - - glBindTexture(GL_TEXTURE_2D, self->id); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ROW_LENGTH, 0); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); - - return pixels; +std::vector texture_download(const Texture* self) { + std::vector pixels(self->size.x * self->size.y * TEXTURE_CHANNELS); + + glBindTexture(GL_TEXTURE_2D, self->id); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + + return pixels; } -bool texture_from_path_init(Texture* self, const std::string& path) -{ - u8* data = stbi_load(path.c_str(), &self->size.x, &self->size.y, nullptr, TEXTURE_CHANNELS); - - if (!data) - { - log_error(std::format(TEXTURE_INIT_ERROR, path)); - return false; - } +bool texture_from_path_init(Texture* self, const std::string& path) { + uint8_t* data = stbi_load(path.c_str(), &self->size.x, &self->size.y, nullptr, TEXTURE_CHANNELS); - self->isInvalid = false; + if (!data) { + log_error(std::format(TEXTURE_INIT_ERROR, path)); + return false; + } - log_info(std::format(TEXTURE_INIT_INFO, path)); + self->isInvalid = false; - _texture_gl_set(self, data); + log_info(std::format(TEXTURE_INIT_INFO, path)); - return true; + _texture_gl_set(self, data); + + return true; } -bool texture_from_encoded_data_init(Texture* self, ivec2 size, const u8* data, u32 length) -{ - *self = Texture{}; - self->size = size; +bool texture_from_rgba_init(Texture* self, ivec2 size, const uint8_t* data) { + *self = Texture{}; + self->size = size; + self->isInvalid = false; - u8* textureData = stbi_load_from_memory(data, length, &self->size.x, &self->size.y, nullptr, TEXTURE_CHANNELS); + _texture_gl_set(self, data); - if (!textureData) - { - self->isInvalid = true; - return false; - } - - _texture_gl_set(self, textureData); - - return true; + return true; } -bool texture_from_rgba_init(Texture* self, ivec2 size, const u8* data) -{ - *self = Texture{}; - self->size = size; - self->isInvalid = false; +bool texture_from_rgba_write(const std::string& path, const uint8_t* data, ivec2 size) { + bool isSuccess = stbi_write_png(path.c_str(), size.x, size.y, TEXTURE_CHANNELS, data, size.x * TEXTURE_CHANNELS); + if (!isSuccess) + log_error(std::format(TEXTURE_SAVE_ERROR, path)); + else + log_info(std::format(TEXTURE_SAVE_INFO, path)); - _texture_gl_set(self, data); - - return true; + return isSuccess; } -bool texture_from_rgba_write(const std::string& path, const u8* data, ivec2 size) -{ - bool isSuccess = stbi_write_png(path.c_str(), size.x, size.y, TEXTURE_CHANNELS, data, size.x * TEXTURE_CHANNELS); - if (!isSuccess) log_error(std::format(TEXTURE_SAVE_ERROR, path)); - else log_info(std::format(TEXTURE_SAVE_INFO, path)); - - return isSuccess; +bool texture_from_gl_write(Texture* self, const std::string& path) { return texture_from_rgba_write(path, texture_download(self).data(), self->size); } + +void texture_free(Texture* self) { + if (self->isInvalid) + return; + + glDeleteTextures(1, &self->id); + *self = Texture{}; } -bool texture_from_gl_write(Texture* self, const std::string& path) -{ - return texture_from_rgba_write(path, texture_download(self).data(), self->size); -} - -void texture_free(Texture* self) -{ - if (self->isInvalid) return; - - glDeleteTextures(1, &self->id); - *self = Texture{}; -} - -bool texture_pixel_set(Texture* self, ivec2 position, vec4 color) -{ - if - ( - position.x < 0 || position.y < 0 || - position.x >= self->size.x || position.y >= self->size.y - ) - return false; - - uint8_t rgba8[4] = {FLOAT_TO_U8(color.r), FLOAT_TO_U8(color.g), FLOAT_TO_U8(color.b), FLOAT_TO_U8(color.a)}; - - glBindTexture(GL_TEXTURE_2D, self->id); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexSubImage2D(GL_TEXTURE_2D, 0,position.x, position.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba8); - - return true; +bool texture_pixel_set(Texture* self, ivec2 position, vec4 color) { + if (position.x < 0 || position.y < 0 || position.x >= self->size.x || position.y >= self->size.y) + return false; + + uint8_t rgba8[4] = {FLOAT_TO_UINT8(color.r), FLOAT_TO_UINT8(color.g), FLOAT_TO_UINT8(color.b), FLOAT_TO_UINT8(color.a)}; + + glBindTexture(GL_TEXTURE_2D, self->id); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, position.x, position.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba8); + + return true; } diff --git a/src/texture.h b/src/texture.h index 3c55c1a..8c2e3a2 100644 --- a/src/texture.h +++ b/src/texture.h @@ -8,16 +8,14 @@ #define TEXTURE_SAVE_INFO "Saved texture to: {}" #define TEXTURE_SAVE_ERROR "Failed to save texture to: {}" -struct Texture -{ - GLuint id = GL_ID_NONE; - ivec2 size{}; - bool isInvalid = true; +struct Texture { + GLuint id = GL_ID_NONE; + ivec2 size{}; + bool isInvalid = true; - auto operator<=>(const Texture&) const = default; + auto operator<=>(const Texture&) const = default; }; -bool texture_from_encoded_data_init(Texture* self, ivec2 size, const u8* data, u32 length); bool texture_from_gl_write(Texture* self, const std::string& path); bool texture_from_path_init(Texture* self, const std::string& path); bool texture_from_rgba_init(Texture* self, ivec2 size, const u8* data); diff --git a/src/window.cpp b/src/window.cpp index 553d0f4..6654c77 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1,17 +1,11 @@ #include "window.h" +#include -void window_title_from_path_set(SDL_Window* self, const std::string& path) -{ - if (!path.empty()) - SDL_SetWindowTitle(self, std::format(WINDOW_TITLE_FORMAT, path).c_str()); - else - SDL_SetWindowTitle(self, WINDOW_TITLE); +void window_title_from_path_set(SDL_Window* self, const std::string& path) { + if (!path.empty()) + SDL_SetWindowTitle(self, std::format(WINDOW_TITLE_FORMAT, path).c_str()); + else + SDL_SetWindowTitle(self, WINDOW_TITLE); } -void window_vsync_set(bool isVsync) -{ - if (isVsync) - SDL_GL_SetSwapInterval(1); - else - SDL_GL_SetSwapInterval(0); -} \ No newline at end of file +void window_vsync_set(bool isVsync) { SDL_GL_SetSwapInterval(isVsync); } \ No newline at end of file From 62c5dcf6eaf3f8bd41a16fb9433896be2f0431c8 Mon Sep 17 00:00:00 2001 From: shweet Date: Fri, 19 Sep 2025 22:19:48 -0400 Subject: [PATCH 02/15] fix git modules --- .clang-format | 4 +++ .gitmodules | 8 +++--- .vscode/settings.json | 5 ++++ CMakeLists.txt | 20 ++++++++------- include/glm | 1 - include/imgui | 1 - include/tinyxml2 | 1 - src/COMMON.h | 8 +++--- src/imgui.cpp | 60 ++++++++++++++++++++++++++++--------------- src/imgui.h | 5 +++- 10 files changed, 71 insertions(+), 42 deletions(-) create mode 100644 .clang-format create mode 100644 .vscode/settings.json delete mode 160000 include/glm delete mode 160000 include/imgui delete mode 160000 include/tinyxml2 diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..01273ba --- /dev/null +++ b/.clang-format @@ -0,0 +1,4 @@ +BasedOnStyle: LLVM +ColumnLimit: 160 +PointerAlignment: Left +ReferenceAlignment: Left \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 8b36230..1d29dd3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,10 +1,10 @@ -[submodule "include/imgui"] - path = include/imgui - url = https://github.com/ocornut/imgui - branch = docking [submodule "include/glm"] path = include/glm url = https://github.com/g-truc/glm [submodule "include/tinyxml2"] path = include/tinyxml2 url = https://github.com/leethomason/tinyxml2 +[submodule "include/imgui"] + path = include/imgui + url = https://github.com/ocornut/imgui/tree/docking + diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3991cfc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "C_Cpp.formatting": "clangFormat", + "editor.formatOnSave": true, + "clang-format.style": "file" +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c0d633..e71e068 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,16 +15,16 @@ set(GLAD_SRC ) set(IMGUI_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui/imgui.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui/imgui_draw.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui/imgui_widgets.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui/imgui_tables.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui/backends/imgui_impl_sdl3.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui/backends/imgui_impl_opengl3.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui/imgui.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui/imgui_draw.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui/imgui_widgets.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui/imgui_tables.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui/backends/imgui_impl_sdl3.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui/backends/imgui_impl_opengl3.cpp ) set(TINYXML2_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/include/tinyxml2/tinyxml2.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/external/tinyxml2/tinyxml2.cpp ) file(GLOB PROJECT_SRC @@ -50,8 +50,10 @@ target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include/glad - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui - ${CMAKE_CURRENT_SOURCE_DIR}/include/tinyxml2 + ${CMAKE_CURRENT_SOURCE_DIR}/external + ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui + ${CMAKE_CURRENT_SOURCE_DIR}/external/glm + ${CMAKE_CURRENT_SOURCE_DIR}/external/tinyxml2 ${CMAKE_CURRENT_SOURCE_DIR}/src ) diff --git a/include/glm b/include/glm deleted file mode 160000 index 2d4c4b4..0000000 --- a/include/glm +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2d4c4b4dd31fde06cfffad7915c2b3006402322f diff --git a/include/imgui b/include/imgui deleted file mode 160000 index d896eab..0000000 --- a/include/imgui +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d896eab16620f80e3cae9b164eb62f71b47f6e45 diff --git a/include/tinyxml2 b/include/tinyxml2 deleted file mode 160000 index e6caeae..0000000 --- a/include/tinyxml2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e6caeae85799003f4ca74ff26ee16a789bc2af48 diff --git a/src/COMMON.h b/src/COMMON.h index 2c7999a..f93035a 100644 --- a/src/COMMON.h +++ b/src/COMMON.h @@ -222,12 +222,12 @@ template static inline void map_swap(Map& map, cons } }; -template static inline void map_insert_shift(std::map& map, int index, const T& value) { - const int insertIndex = index + 1; +template static inline void map_insert_shift(std::map& map, int id, const T& value) { + const int insertID = id + 1; std::vector> toShift; for (auto it = map.rbegin(); it != map.rend(); ++it) { - if (it->first < insertIndex) + if (it->first < insertID) break; toShift.emplace_back(it->first + 1, std::move(it->second)); } @@ -238,7 +238,7 @@ template static inline void map_insert_shift(std::map& map, for (auto& [newKey, val] : toShift) map[newKey] = std::move(val); - map[insertIndex] = value; + map[insertID] = value; } template static inline T* vector_find(std::vector& v, const T& value) { diff --git a/src/imgui.cpp b/src/imgui.cpp index c8b420f..37fc548 100644 --- a/src/imgui.cpp +++ b/src/imgui.cpp @@ -52,10 +52,14 @@ static bool _imgui_chord_pressed(ImGuiKeyChord chord) { static bool _imgui_is_focus_window(const std::string& focus) { ImGuiContext* context = ImGui::GetCurrentContext(); - if (!context || !context->NavWindow) + if (!context) return false; - std::string_view name(context->NavWindow->Name); + ImGuiWindow* window = context->NavWindow; + if (!window || !window->Name) + return false; + + std::string_view name(window->Name); return name.find(focus) != std::string_view::npos; } @@ -208,6 +212,7 @@ static void _imgui_item_pre(const ImguiItem& self, ImguiItemType type) { } static void _imgui_item_post(const ImguiItem& self, Imgui* imgui, ImguiItemType type, bool& isActivated) { + if (self.is_mnemonic() && !self.isMnemonicDisabled) { ImVec2 position = ImGui::GetItemRectMin(); ImFont* font = ImGui::GetFont(); @@ -387,7 +392,6 @@ IMGUI_ITEM_BOOL_FUNCTION(_imgui_button, IMGUI_BUTTON, ImGui::Button(self.label_g IMGUI_ITEM_BOOL_FUNCTION(_imgui_begin_table, IMGUI_TABLE, ImGui::BeginTable(self.label_get().c_str(), self.value, self.flags)); IMGUI_ITEM_BOOL_FUNCTION(_imgui_selectable, IMGUI_SELECTABLE, ImGui::Selectable(self.label_get().c_str(), self.isSelected, self.flags, _imgui_item_size_get(self, type))); -IMGUI_ITEM_BOOL_FUNCTION(_imgui_begin, IMGUI_WINDOW, ImGui::Begin(self.label_get().c_str(), nullptr, self.flags)); IMGUI_ITEM_VOID_FUNCTION(_imgui_image, IMGUI_IMAGE, ImGui::Image(self.textureID, _imgui_item_size_get(self, IMGUI_IMAGE), self.uvMin, self.uvMax)); IMGUI_ITEM_VALUE_CLAMP_FUNCTION(_imgui_input_int, IMGUI_INPUT_INT, int, @@ -403,8 +407,11 @@ IMGUI_ITEM_VALUE_FUNCTION(_imgui_slider_float, IMGUI_SLIDER_FLOAT, float, IMGUI_ITEM_STRING_FUNCTION(_imgui_input_text, IMGUI_INPUT_TEXT, (value.resize(*self.max), ImGui::InputText(self.label_get().c_str(), value.data(), *self.max, self.flags))); -#define IMGUI_BEGIN_OR_RETURN(item, imgui) \ - if (!_imgui_begin(item, imgui)) { \ +static bool _imgui_begin(const ImguiItem& self) { return ImGui::Begin(self.label_get().c_str(), nullptr, self.flags); } +static void _imgui_end(void) { ImGui::End(); } + +#define IMGUI_BEGIN_OR_RETURN(item) \ + if (!_imgui_begin(item)) { \ _imgui_end(); \ return; \ } @@ -431,7 +438,6 @@ IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_color_edit3, vec3, _imgui_col IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_color_edit4, vec4, _imgui_color_edit4(self, imgui, value)); */ -static void _imgui_end(void) { ImGui::End(); } static void _imgui_end_table(void) { ImGui::EndTable(); } static void _imgui_table_setup_column(const char* text) { ImGui::TableSetupColumn(text); } static void _imgui_table_headers_row(void) { ImGui::TableHeadersRow(); } @@ -633,7 +639,7 @@ static void _imgui_timeline(Imgui* self) { static int frameTime{}; static int& itemID = self->reference->itemID; - IMGUI_BEGIN_OR_RETURN(IMGUI_TIMELINE, self); + IMGUI_BEGIN_OR_RETURN(IMGUI_TIMELINE); _imgui_no_anm2_path_click_check(self); Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); @@ -744,7 +750,7 @@ static void _imgui_timeline(Imgui* self) { ImGui::SetNextWindowPos(ImGui::GetWindowPos()); ImGui::SetNextWindowSize(ImGui::GetWindowSize()); - _imgui_begin(IMGUI_PLAYHEAD, self); + _imgui_begin(IMGUI_PLAYHEAD); ImVec2& pos = playheadPos; @@ -1383,7 +1389,7 @@ static void _imgui_timeline(Imgui* self) { } static void _imgui_onionskin(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_ONIONSKIN, self); + IMGUI_BEGIN_OR_RETURN(IMGUI_ONIONSKIN); static auto& isEnabled = self->settings->onionskinIsEnabled; static auto& beforeCount = self->settings->onionskinBeforeCount; @@ -1423,7 +1429,7 @@ static void _imgui_taskbar(Imgui* self) { ImguiItem taskbar = IMGUI_TASKBAR; ImGui::SetNextWindowSize({viewport->Size.x, IMGUI_TASKBAR.size->y * displayScale}); ImGui::SetNextWindowPos(viewport->Pos); - _imgui_begin(taskbar, self); + _imgui_begin(taskbar); Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); Anm2Item* item = anm2_item_from_reference(self->anm2, *self->reference); @@ -1888,7 +1894,7 @@ static void _imgui_taskbar(Imgui* self) { static void _imgui_tools(Imgui* self) { ImGuiStyle style = ImGui::GetStyle(); - IMGUI_BEGIN_OR_RETURN(IMGUI_TOOLS, self); + IMGUI_BEGIN_OR_RETURN(IMGUI_TOOLS); float availableWidth = ImGui::GetContentRegionAvail().x; float usedWidth = style.FramePadding.x; @@ -1928,7 +1934,7 @@ static void _imgui_tools(Imgui* self) { static void _imgui_layers(Imgui* self) { static int selectedLayerID = ID_NONE; - IMGUI_BEGIN_OR_RETURN(IMGUI_LAYERS, self); + IMGUI_BEGIN_OR_RETURN(IMGUI_LAYERS); _imgui_no_anm2_path_click_check(self); ImVec2 size = ImGui::GetContentRegionAvail(); @@ -1973,7 +1979,7 @@ static void _imgui_layers(Imgui* self) { static void _imgui_nulls(Imgui* self) { static int selectedNullID = ID_NONE; - IMGUI_BEGIN_OR_RETURN(IMGUI_NULLS, self); + IMGUI_BEGIN_OR_RETURN(IMGUI_NULLS); _imgui_no_anm2_path_click_check(self); ImVec2 size = ImGui::GetContentRegionAvail(); @@ -2008,7 +2014,7 @@ static void _imgui_nulls(Imgui* self) { } static void _imgui_animations(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATIONS, self); + IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATIONS); _imgui_no_anm2_path_click_check(self); ImVec2 size = ImGui::GetContentRegionAvail(); @@ -2179,7 +2185,7 @@ static void _imgui_animations(Imgui* self) { static void _imgui_events(Imgui* self) { static int selectedID = ID_NONE; - IMGUI_BEGIN_OR_RETURN(IMGUI_EVENTS, self); + IMGUI_BEGIN_OR_RETURN(IMGUI_EVENTS); _imgui_no_anm2_path_click_check(self); ImVec2 windowSize = ImGui::GetContentRegionAvail(); @@ -2230,7 +2236,7 @@ static void _imgui_events(Imgui* self) { */ static void _imgui_spritesheets(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEETS, self); + IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEETS); _imgui_no_anm2_path_click_check(self); static std::unordered_set selectedIDs; @@ -2385,7 +2391,7 @@ static void _imgui_animation_preview(Imgui* self) { std::string mousePositionString = std::format(IMGUI_POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y); - IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATION_PREVIEW, self); + IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATION_PREVIEW); _imgui_begin_child(IMGUI_CANVAS_GRID_CHILD, self); _imgui_checkbox(IMGUI_CANVAS_GRID, self, self->settings->previewIsGrid); @@ -2598,7 +2604,7 @@ static void _imgui_spritesheet_editor(Imgui* self) { std::string mousePositionString = std::format(IMGUI_POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y); - IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEET_EDITOR, self); + IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEET_EDITOR); _imgui_begin_child(IMGUI_CANVAS_GRID_CHILD, self); _imgui_checkbox(IMGUI_CANVAS_GRID, self, self->settings->editorIsGrid); @@ -2815,7 +2821,7 @@ static void _imgui_spritesheet_editor(Imgui* self) { static void _imgui_frame_properties(Imgui* self) { static Anm2Type& type = self->reference->itemType; - IMGUI_BEGIN_OR_RETURN(IMGUI_FRAME_PROPERTIES, self); + IMGUI_BEGIN_OR_RETURN(IMGUI_FRAME_PROPERTIES); Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *self->reference); @@ -2896,7 +2902,7 @@ static void _imgui_log(Imgui* self) { ImGui::PushStyleColor(ImGuiCol_Text, textColor); ImGui::SetNextWindowBgAlpha(lifetime); - _imgui_begin(IMGUI_LOG_WINDOW.copy({.label = std::format(IMGUI_LOG_FORMAT, i)}), self); + _imgui_begin(IMGUI_LOG_WINDOW.copy({.label = std::format(IMGUI_LOG_FORMAT, i)})); ImGui::TextUnformatted(item.text.c_str()); ImVec2 windowSize = ImGui::GetWindowSize(); _imgui_end(); // IMGUI_LOG_WINDOW @@ -2915,7 +2921,7 @@ static void _imgui_dock(Imgui* self) { ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, viewport->Size.y - IMGUI_TASKBAR.size->y)); ImGui::SetNextWindowViewport(viewport->ID); - _imgui_begin(window, self); + _imgui_begin(window); _imgui_dockspace(IMGUI_DOCKSPACE_MAIN, self); //_imgui_tools(self); @@ -2936,6 +2942,7 @@ static void _imgui_dock(Imgui* self) { void imgui_init(Imgui* self, Dialog* dialog, Resources* resources, Anm2* anm2, Anm2Reference* reference, Editor* editor, Preview* preview, GeneratePreview* generatePreview, Settings* settings, Snapshots* snapshots, Clipboard* clipboard, SDL_Window* window, SDL_GLContext* glContext) { + self->dialog = dialog; self->resources = resources; self->anm2 = anm2; @@ -2951,9 +2958,12 @@ void imgui_init(Imgui* self, Dialog* dialog, Resources* resources, Anm2* anm2, A self->saveAnm2 = *anm2; + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGui::StyleColorsDark(); + log_info(std::format(IMGUI_LOG_INIT, ImGui::GetVersion())); + ImGui_ImplSDL3_InitForOpenGL(self->window, *self->glContext); ImGui_ImplOpenGL3_Init(IMGUI_OPENGL_VERSION); @@ -2983,6 +2993,13 @@ void imgui_update(Imgui* self) { ImGui_ImplOpenGL3_NewFrame(); ImGui::NewFrame(); + auto* ctx = ImGui::GetCurrentContext(); + IM_ASSERT(ctx); + IM_ASSERT(ctx->WithinFrameScope); + IM_ASSERT(ctx->CurrentWindowStack.Size >= 1); + IM_ASSERT(ImGui::GetIO().BackendPlatformUserData && "SDL3 backend not initialized?"); + IM_ASSERT(ImGui::GetIO().BackendRendererUserData && "OpenGL3 backend not initialized?"); + _imgui_taskbar(self); _imgui_dock(self); _imgui_log(self); @@ -3052,6 +3069,7 @@ void imgui_free(void) { if (!ImGui::GetCurrentContext()) return; + log_info(IMGUI_LOG_FREE); ImGui_ImplSDL3_Shutdown(); ImGui_ImplOpenGL3_Shutdown(); ImGui::SaveIniSettingsToDisk(settings_path_get().c_str()); diff --git a/src/imgui.h b/src/imgui.h index bf561a5..54c8272 100644 --- a/src/imgui.h +++ b/src/imgui.h @@ -116,6 +116,9 @@ #define IMGUI_POPUP_FLAGS ImGuiWindowFlags_NoMove #define IMGUI_POPUP_MODAL_FLAGS ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize +#define IMGUI_LOG_INIT "Initialized ImGui {}" +#define IMGUI_LOG_FREE "Freed ImGui" + #define IMGUI_LOG_NO_ANM2_PATH "Please save the .anm2 to a path first!" #define IMGUI_LOG_FILE_OPEN_FORMAT "Opened anm2: {}" #define IMGUI_LOG_FILE_SAVE_FORMAT "Saved anm2 to: {}" @@ -1092,7 +1095,7 @@ IMGUI_ITEM(IMGUI_EVENTS_REMOVE_UNUSED, self.label = "Remove Unused", // Spritesheets IMGUI_ITEM(IMGUI_SPRITESHEET_PREVIEW, self.label = "## Spritesheet Preview", self.size = {65, 65}); IMGUI_ITEM(IMGUI_SPRITESHEETS, self.label = "Spritesheets", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_SPRITESHEETS_CHILD, self.label = "## Spritesheets Child", self.flags = true, self.itemSpacing = vec2(), self.windowPadding = vec2()); +IMGUI_ITEM(IMGUI_SPRITESHEETS_CHILD, self.label = "## Spritesheets Child", self.flags = true, self.windowPadding = vec2()); IMGUI_ITEM(IMGUI_SPRITESHEET_CHILD, self.label = "## Spritesheet Child", self.flags = true, self.itemSpacing = vec2(), self.windowPadding = vec2()); IMGUI_ITEM(IMGUI_SPRITESHEET, self.label = "## Spritesheet", self.dragDrop = "## Spritesheet Drag Drop"); IMGUI_ITEM(IMGUI_SPRITESHEET_TEXT, self.label = "## Spritesheet Text", self.atlas = ATLAS_SPRITESHEET, self.itemSpacing = vec2(8, 0)); From 8039df667cc0da6c646fbf235c4bdd10eae20daf Mon Sep 17 00:00:00 2001 From: shweet Date: Fri, 19 Sep 2025 22:42:08 -0400 Subject: [PATCH 03/15] submodules please --- .gitmodules | 18 ++++++++++-------- external/glm | 1 + external/imgui | 1 + external/tinyxml2 | 1 + 4 files changed, 13 insertions(+), 8 deletions(-) create mode 160000 external/glm create mode 160000 external/imgui create mode 160000 external/tinyxml2 diff --git a/.gitmodules b/.gitmodules index 1d29dd3..8922adb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,10 +1,12 @@ -[submodule "include/glm"] - path = include/glm +[submodule "external/glm"] + path = external/glm url = https://github.com/g-truc/glm -[submodule "include/tinyxml2"] - path = include/tinyxml2 - url = https://github.com/leethomason/tinyxml2 -[submodule "include/imgui"] - path = include/imgui - url = https://github.com/ocornut/imgui/tree/docking +[submodule "external/imgui"] + path = external/imgui + url = https://github.com/ocornut/imgui + branch = docking +[submodule "external/tinyxml2"] + path = external/tinyxml2 + url = https://github.com/external/tinyxml2 + diff --git a/external/glm b/external/glm new file mode 160000 index 0000000..2d4c4b4 --- /dev/null +++ b/external/glm @@ -0,0 +1 @@ +Subproject commit 2d4c4b4dd31fde06cfffad7915c2b3006402322f diff --git a/external/imgui b/external/imgui new file mode 160000 index 0000000..1ad9de5 --- /dev/null +++ b/external/imgui @@ -0,0 +1 @@ +Subproject commit 1ad9de5aae5a7508f1bd7eb024b8f045c5844d34 diff --git a/external/tinyxml2 b/external/tinyxml2 new file mode 160000 index 0000000..36ff404 --- /dev/null +++ b/external/tinyxml2 @@ -0,0 +1 @@ +Subproject commit 36ff404c346acadd8a42c135f096ebd5437610b1 From 7f07eaa1283c5ba3fe46c61aed56869fbc30e8a7 Mon Sep 17 00:00:00 2001 From: shweet Date: Sun, 21 Sep 2025 23:57:17 -0400 Subject: [PATCH 04/15] slowly getting back...also, static linking --- .gitignore | 7 +- .gitmodules | 7 +- .vscode/settings.json | 5 +- CMakeLists.txt | 93 +- compile_commands.json | 2 +- src/COMMON.h | 75 +- src/RESOURCE.h | 3797 ++++++++++++++++++++++++++++++++++++++++- src/anm2.cpp | 96 +- src/anm2.h | 17 +- src/clipboard.cpp | 77 +- src/clipboard.h | 6 +- src/imgui.cpp | 795 ++++----- src/imgui.h | 168 +- src/preview.cpp | 12 +- src/render.h | 15 +- src/resources.cpp | 3 +- src/settings.h | 10 +- src/snapshots.h | 2 +- src/texture.cpp | 16 + src/texture.h | 7 +- 20 files changed, 4579 insertions(+), 631 deletions(-) diff --git a/.gitignore b/.gitignore index 4a0b47c..620ce6f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,9 @@ release/ packed/ vcpkg_installed/ out/ -include/imgui/ -include/glm/ -include/tinyxml2 +external/ +external/ +external/ +external/ workshop/resources .vs/ diff --git a/.gitmodules b/.gitmodules index 8922adb..2650de6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,6 +7,7 @@ branch = docking [submodule "external/tinyxml2"] path = external/tinyxml2 - url = https://github.com/external/tinyxml2 - - + url = https://github.com/leethomason/tinyxml2 +[submodule "external/SDL"] + path = external/SDL + url = https://github.com/libsdl-org/SDL.git diff --git a/.vscode/settings.json b/.vscode/settings.json index 3991cfc..73ffdc7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,8 @@ { "C_Cpp.formatting": "clangFormat", "editor.formatOnSave": true, - "clang-format.style": "file" + "clang-format.style": "file", + "clangd.arguments": [ + "--compile-commands-dir=build" + ] } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e71e068..af48cca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,35 +1,39 @@ cmake_minimum_required(VERSION 3.15) +project(anm2ed CXX) +# Optional: auto-pick up vcpkg toolchain on Windows if(WIN32 AND DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE) set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "Vcpkg toolchain file") endif() -project(anm2ed CXX) - -find_package(SDL3 REQUIRED) find_package(OpenGL REQUIRED) -set(GLAD_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/include/glad/glad.cpp -) +# Export compile_commands.json (for clangd, etc.) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +if(CMAKE_EXPORT_COMPILE_COMMANDS) + execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink + ${CMAKE_BINARY_DIR}/compile_commands.json + ${CMAKE_SOURCE_DIR}/compile_commands.json + ) +endif() + +set(GLAD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/include/glad/glad.cpp) set(IMGUI_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui/imgui.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui/imgui_draw.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui/imgui_widgets.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui/imgui_tables.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui/backends/imgui_impl_sdl3.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui/backends/imgui_impl_opengl3.cpp + external/imgui/imgui.cpp + external/imgui/imgui_draw.cpp + external/imgui/imgui_widgets.cpp + external/imgui/imgui_tables.cpp + external/imgui/backends/imgui_impl_sdl3.cpp + external/imgui/backends/imgui_impl_opengl3.cpp ) -set(TINYXML2_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/external/tinyxml2/tinyxml2.cpp -) +set(TINYXML2_SRC external/tinyxml2/tinyxml2.cpp) -file(GLOB PROJECT_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h +file(GLOB PROJECT_SRC CONFIGURE_DEPENDS + src/*.cpp + src/*.h ) add_executable(${PROJECT_NAME} @@ -39,39 +43,48 @@ add_executable(${PROJECT_NAME} ${PROJECT_SRC} ) +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) +set(SDL_SHARED OFF CACHE BOOL "" FORCE) +set(SDL_STATIC ON CACHE BOOL "" FORCE) +add_subdirectory(external/SDL EXCLUDE_FROM_ALL) + if(WIN32) enable_language(RC) target_sources(${PROJECT_NAME} PRIVATE Icon.rc) set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE TRUE) -endif() -target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) + set_property(TARGET ${PROJECT_NAME} PROPERTY + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") -target_include_directories(${PROJECT_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_CURRENT_SOURCE_DIR}/include/glad - ${CMAKE_CURRENT_SOURCE_DIR}/external - ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui - ${CMAKE_CURRENT_SOURCE_DIR}/external/glm - ${CMAKE_CURRENT_SOURCE_DIR}/external/tinyxml2 - ${CMAKE_CURRENT_SOURCE_DIR}/src -) - -if(MSVC) - target_compile_options(${PROJECT_NAME} PRIVATE /std:c++latest /EHsc) + target_compile_options(${PROJECT_NAME} PRIVATE /EHsc) target_link_options(${PROJECT_NAME} PRIVATE /STACK:0xffffff) else() - target_compile_options(${PROJECT_NAME} PRIVATE -O2 -std=c++23 -Wall -Wextra -pedantic -fmax-errors=1) + target_compile_options(${PROJECT_NAME} PRIVATE + -O2 -Wall -Wextra -pedantic -fmax-errors=1 + ) if(CMAKE_BUILD_TYPE STREQUAL "Debug") - target_compile_options(${PROJECT_NAME} PRIVATE -DDEBUG -g) - else() - set(CMAKE_BUILD_TYPE "Release") + target_compile_definitions(${PROJECT_NAME} PRIVATE DEBUG) + target_compile_options(${PROJECT_NAME} PRIVATE -g) endif() target_link_libraries(${PROJECT_NAME} PRIVATE m) endif() -target_link_libraries(${PROJECT_NAME} PRIVATE OpenGL::GL SDL3::SDL3) +target_compile_definitions(${PROJECT_NAME} PRIVATE IMGUI_DISABLE_OBSOLETE_FUNCTIONS IMGUI_DEBUG_PARANOID IMGUI_ENABLE_DOCKING) -message("System: ${CMAKE_SYSTEM_NAME}") -message("Project: ${PROJECT_NAME}") -message("Build: ${CMAKE_BUILD_TYPE}") +target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) + +target_include_directories(${PROJECT_NAME} PRIVATE + external + external/imgui + external/glm + external/tinyxml2 + include + include/glad + src +) + +target_link_libraries(${PROJECT_NAME} PRIVATE OpenGL::GL SDL3::SDL3-static) + +message(STATUS "System: ${CMAKE_SYSTEM_NAME}") +message(STATUS "Project: ${PROJECT_NAME}") +message(STATUS "Build: ${CMAKE_BUILD_TYPE}") \ No newline at end of file diff --git a/compile_commands.json b/compile_commands.json index 25eb4b2..5e95284 120000 --- a/compile_commands.json +++ b/compile_commands.json @@ -1 +1 @@ -build/compile_commands.json \ No newline at end of file +/home/anon/sda/Personal/Repos/anm2ed/build/compile_commands.json \ No newline at end of file diff --git a/src/COMMON.h b/src/COMMON.h index f93035a..03b777f 100644 --- a/src/COMMON.h +++ b/src/COMMON.h @@ -1,5 +1,6 @@ #pragma once +#include #define GLAD_GL_IMPLEMENTATION #include #include @@ -10,7 +11,6 @@ #include #include -#include #include #include #include @@ -241,6 +241,35 @@ template static inline void map_insert_shift(std::map& map, map[insertID] = value; } +template auto map_keys_to_set(const Map& m) { + using Key = typename Map::key_type; + std::unordered_set s; + s.reserve(m.size()); + for (const auto& [key, _] : m) { + s.insert(key); + } + return s; +} + +template Set set_symmetric_difference(const Set& a, const Set& b) { + Set result; + result.reserve(a.size() + b.size()); + + for (const auto& x : a) { + if (!b.contains(x)) { + result.insert(x); + } + } + + for (const auto& x : b) { + if (!a.contains(x)) { + result.insert(x); + } + } + + return result; +} + template static inline T* vector_find(std::vector& v, const T& value) { auto it = std::find(v.begin(), v.end(), value); return (it != v.end()) ? &(*it) : nullptr; @@ -257,11 +286,49 @@ template static inline void vector_value_swap(std::vector& v, co } } -static inline void unordered_set_id_toggle(std::unordered_set& set, int id) { - if (auto it = set.find(id); it != set.end()) +template static inline T* vector_get(std::vector& v, size_t index) { + if (index < v.size()) + return &v[index]; + return nullptr; +} + +template static inline void vector_move(std::vector& v, size_t from, size_t to) { + if (from >= v.size() || to >= v.size() || from == to) + return; + + if (from < to) { + std::rotate(v.begin() + from, v.begin() + from + 1, v.begin() + to + 1); + } else { + std::rotate(v.begin() + to, v.begin() + from, v.begin() + from + 1); + } +} + +template void vector_erase_indices(std::vector& v, const std::set& indices) { + size_t i = 0; + v.erase(std::remove_if(v.begin(), v.end(), [&](const T&) { return indices.count(i++) > 0; }), v.end()); +} + +template static inline void set_key_toggle(std::set& set, T key) { + if (auto it = set.find(key); it != set.end()) set.erase(it); else - set.insert(id); + set.insert(key); +} + +template static inline void set_list(std::set& s, const T& key, bool isCtrl, bool isShift, T* lastSelected) { + if (isShift && lastSelected) { + s.clear(); + T a = std::min(*lastSelected, key); + T b = std::max(*lastSelected, key); + for (T i = a; i <= b; i++) + s.insert(i); + } else if (isCtrl) { + set_key_toggle(s, key); + *lastSelected = key; + } else { + s = {key}; + *lastSelected = key; + } } static inline mat4 quad_model_get(vec2 size = {}, vec2 position = {}, vec2 pivot = {}, vec2 scale = vec2(1.0f), float rotation = {}) { diff --git a/src/RESOURCE.h b/src/RESOURCE.h index 25b0346..21852db 100644 --- a/src/RESOURCE.h +++ b/src/RESOURCE.h @@ -3,7 +3,8 @@ #include "COMMON.h" #define ATLAS_PATH "resources/atlas.png" -#define FONT_PATH "resources/font.ttf" +#define FONT_REGULAR_PATH "resources/font_regular.ttf" +#define FONT_BOLD_PATH "resources/font_bold.ttf" #define FONT_SIZE 16 const vec2 TEXTURE_ATLAS_SIZE = {96, 160}; @@ -195,3 +196,3797 @@ const ShaderData SHADER_DATA[SHADER_COUNT] = {{SHADER_VERTEX, SHADER_FRAGMENT}, {SHADER_VERTEX, SHADER_TEXTURE_FRAGMENT}, {SHADER_AXIS_VERTEX, SHADER_FRAGMENT}, {SHADER_GRID_VERTEX, SHADER_GRID_FRAGMENT}}; + +enum FontType { FONT_REGULAR, FONT_ITALICS, FONT_BOLD, FONT_BOLD_ITALICS, FONT_COUNT }; + +struct Font { + const void* data; + size_t length; +}; + +const inline uint8_t TEXTURE_ATLAS[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xa0, 0x04, 0x03, + 0x00, 0x00, 0x00, 0x01, 0x5e, 0x74, 0xbf, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, + 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x0f, 0x50, 0x4c, 0x54, 0x45, 0x00, 0x00, 0x00, 0x76, 0x76, 0x76, 0xff, 0xff, 0xff, 0x60, 0x60, 0x60, 0xff, 0xff, 0xff, 0x3e, + 0xd5, 0x47, 0x6d, 0x00, 0x00, 0x00, 0x03, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x00, 0x00, 0xfa, 0x76, 0xc4, 0xde, 0x00, 0x00, 0x04, 0x62, 0x49, 0x44, 0x41, 0x54, + 0x58, 0xc3, 0xed, 0x59, 0x5b, 0x6e, 0x24, 0x37, 0x0c, 0x2c, 0x80, 0xbc, 0x40, 0xee, 0x90, 0x03, 0x10, 0x20, 0x0f, 0xc0, 0x80, 0x75, 0xff, 0x33, 0xe5, 0x83, + 0xa2, 0x5a, 0x63, 0xcf, 0xae, 0xa7, 0x37, 0xb1, 0x03, 0x6c, 0xac, 0x0f, 0x77, 0x6b, 0x5a, 0xd5, 0x7c, 0x15, 0x49, 0xb5, 0x0c, 0xfc, 0xc2, 0x20, 0x9f, 0xff, + 0xae, 0xd9, 0xd7, 0x28, 0x00, 0xe0, 0xb1, 0x9e, 0x04, 0x40, 0x9a, 0x92, 0x76, 0xac, 0x27, 0xf3, 0x78, 0x21, 0xbd, 0x00, 0x01, 0xa0, 0x04, 0x98, 0xd0, 0x46, + 0x26, 0x00, 0x04, 0x49, 0xe8, 0x9e, 0x36, 0xc0, 0x95, 0x80, 0x2e, 0x51, 0x64, 0xdf, 0xee, 0x15, 0xa4, 0x92, 0x83, 0x58, 0x2a, 0x29, 0x4b, 0xd8, 0x00, 0x9d, + 0x17, 0xf6, 0x02, 0xc9, 0x56, 0x68, 0xe6, 0x6d, 0x4b, 0xbf, 0xa2, 0x67, 0x4c, 0x4d, 0x35, 0xec, 0xb5, 0x89, 0x41, 0x24, 0x9e, 0x01, 0x94, 0xd0, 0xd4, 0xb6, + 0x34, 0x35, 0x7b, 0x81, 0x78, 0x90, 0xe5, 0xf6, 0x08, 0x28, 0x40, 0x13, 0xcc, 0x13, 0x50, 0x08, 0x03, 0x20, 0xee, 0x51, 0xee, 0x06, 0x48, 0xfb, 0x8e, 0x61, + 0x64, 0x02, 0x9a, 0x4a, 0x1c, 0x00, 0xe1, 0xf2, 0xb8, 0xb8, 0xbb, 0x1b, 0x80, 0x48, 0xad, 0xb6, 0x75, 0x59, 0xcf, 0x04, 0xda, 0x4b, 0x00, 0x12, 0x03, 0x30, + 0x77, 0x37, 0x33, 0x21, 0x01, 0xd2, 0xae, 0xc0, 0x75, 0xd4, 0x2e, 0x40, 0xb0, 0x00, 0x40, 0x44, 0xc4, 0x45, 0xa0, 0x4c, 0x40, 0x99, 0x17, 0x60, 0x02, 0x37, + 0x5e, 0xd2, 0x15, 0x5f, 0x98, 0x99, 0xd9, 0x13, 0xc0, 0xa2, 0x86, 0xb4, 0xdf, 0xed, 0x22, 0x8d, 0x88, 0x00, 0x10, 0x5a, 0xff, 0xe1, 0xc7, 0xe4, 0x83, 0xe1, + 0x8b, 0xc6, 0xd0, 0x5c, 0xde, 0x48, 0x94, 0x07, 0x72, 0x5f, 0xf3, 0xa1, 0xf9, 0xdb, 0xe7, 0x93, 0x17, 0xc1, 0xa6, 0x80, 0x93, 0xa4, 0x5f, 0x9c, 0x92, 0xe5, + 0x13, 0xbc, 0x71, 0x2f, 0x0a, 0x00, 0x02, 0x08, 0x02, 0xac, 0xcd, 0x5a, 0x09, 0xba, 0xb3, 0xec, 0x12, 0x45, 0x77, 0x27, 0x81, 0x26, 0x28, 0x40, 0xeb, 0x3c, + 0x19, 0x40, 0x3f, 0xb7, 0x2d, 0x4a, 0xe8, 0x1e, 0xa4, 0x0d, 0x40, 0x3a, 0x4f, 0x6c, 0xab, 0xd4, 0xcf, 0x01, 0x68, 0xb9, 0x47, 0x42, 0xcb, 0x9d, 0x15, 0x39, + 0x80, 0xc9, 0x93, 0xa1, 0xf9, 0x7e, 0x2e, 0x15, 0x51, 0x15, 0xa6, 0xe5, 0x41, 0x8f, 0x44, 0x42, 0xb3, 0x01, 0x4a, 0x68, 0x0e, 0xcd, 0xf7, 0x73, 0x9a, 0x6a, + 0xa6, 0x30, 0xd2, 0x59, 0xae, 0xd5, 0x00, 0xd9, 0x79, 0x32, 0x34, 0xd7, 0x72, 0x96, 0x47, 0x42, 0x52, 0x4d, 0x52, 0x4d, 0x4b, 0x09, 0x8c, 0x4a, 0x57, 0x9e, + 0xc0, 0xdc, 0x1d, 0x80, 0x66, 0xd0, 0xa1, 0x09, 0x28, 0x48, 0x24, 0x84, 0x2c, 0xf7, 0x65, 0x34, 0x09, 0x21, 0x13, 0x4e, 0x53, 0x29, 0xb1, 0x9e, 0x97, 0x39, + 0x01, 0x48, 0x01, 0x61, 0x00, 0xe9, 0xee, 0xed, 0x56, 0x8d, 0x4a, 0x90, 0x10, 0xa7, 0x81, 0x66, 0x6b, 0x6e, 0xe2, 0xb4, 0x0e, 0x6d, 0x01, 0x50, 0xba, 0xaf, + 0xc0, 0x95, 0x66, 0x20, 0x08, 0x67, 0x39, 0x28, 0xc7, 0x3c, 0xfd, 0x19, 0x35, 0x4c, 0x4d, 0xb2, 0xa9, 0x01, 0x53, 0x24, 0xd4, 0x24, 0x05, 0x24, 0xf9, 0xc0, + 0xbf, 0x83, 0x5c, 0x64, 0xcf, 0xdd, 0xcf, 0x8c, 0xb9, 0xe6, 0xbf, 0xca, 0xf7, 0xb9, 0xbe, 0xdc, 0x1f, 0xd6, 0x75, 0xa9, 0xa6, 0x49, 0x4d, 0x5e, 0x57, 0x00, + 0x40, 0x57, 0xc2, 0x29, 0xa1, 0x47, 0xed, 0xc6, 0x94, 0x9d, 0x7d, 0x5d, 0xc5, 0xcd, 0xde, 0xab, 0xb6, 0xd8, 0xa9, 0xfd, 0x86, 0x5d, 0x11, 0x01, 0x40, 0xcd, + 0xed, 0xf4, 0xce, 0x2a, 0xba, 0xec, 0x6a, 0xd7, 0x45, 0x71, 0xcc, 0x4a, 0x00, 0x28, 0x0a, 0x80, 0x0c, 0x93, 0x52, 0x6c, 0x96, 0xae, 0xc2, 0xa5, 0x00, 0xa2, + 0x25, 0x6d, 0x0d, 0x82, 0x06, 0x68, 0x16, 0x10, 0x9a, 0x9a, 0x88, 0x82, 0xa6, 0x76, 0xfa, 0xa5, 0x2e, 0x09, 0x87, 0x4a, 0xc5, 0x4a, 0x80, 0x99, 0x9a, 0xba, + 0x12, 0x91, 0xa4, 0x76, 0x8c, 0xba, 0x09, 0xc5, 0xa9, 0x92, 0x06, 0x03, 0xcf, 0x01, 0xd9, 0x12, 0x98, 0x38, 0x55, 0x6a, 0x01, 0x4f, 0x55, 0xa2, 0x32, 0xb5, + 0x99, 0xd5, 0x2a, 0x69, 0x26, 0xd0, 0x02, 0xde, 0x19, 0x2d, 0x4c, 0xb0, 0x7b, 0x76, 0x8e, 0x77, 0x3a, 0x6f, 0xb4, 0xf2, 0x0d, 0xe9, 0xc6, 0xad, 0xb9, 0xda, + 0xf4, 0x14, 0x9c, 0xbe, 0x67, 0xc6, 0x73, 0x4e, 0x29, 0x93, 0xcc, 0x01, 0xe4, 0x05, 0xe0, 0xdb, 0x2d, 0xc2, 0xa6, 0xc6, 0x29, 0x61, 0xab, 0x24, 0x91, 0x3f, + 0x22, 0x5f, 0xef, 0x08, 0x94, 0x4c, 0x6a, 0x02, 0xd4, 0xa4, 0xe6, 0x43, 0xe9, 0xbe, 0x4d, 0xef, 0x7f, 0x3a, 0x0e, 0x39, 0xba, 0xb3, 0xf7, 0xb1, 0x8b, 0x2d, + 0xfd, 0xd4, 0xa2, 0x1e, 0x15, 0x5b, 0xf7, 0xf4, 0x01, 0x58, 0xff, 0xb0, 0xe6, 0x52, 0x5c, 0x3d, 0xe2, 0xec, 0x19, 0xd0, 0xea, 0x38, 0x09, 0x6b, 0x3d, 0x94, + 0x58, 0x8b, 0x62, 0xf7, 0x83, 0x69, 0x03, 0x4c, 0xb0, 0x37, 0x0c, 0x10, 0xa6, 0x5a, 0x2f, 0xf4, 0xae, 0x64, 0x50, 0xb0, 0xb0, 0x38, 0x88, 0x7d, 0x33, 0xb5, + 0x27, 0x3c, 0xb5, 0x2b, 0x9f, 0x04, 0xe9, 0x6d, 0xad, 0xda, 0x74, 0x9c, 0x01, 0x24, 0x9c, 0x4e, 0x27, 0x84, 0x4e, 0x76, 0x4a, 0x1b, 0xbb, 0x75, 0x69, 0xd7, + 0xd9, 0xde, 0xb5, 0xf5, 0x0e, 0x46, 0x89, 0x01, 0x28, 0x49, 0x46, 0x02, 0x10, 0xea, 0x08, 0xb0, 0x8c, 0xe5, 0x19, 0x4d, 0x9d, 0xbd, 0x59, 0x1b, 0x0c, 0x05, + 0xd9, 0xfc, 0x0e, 0xe6, 0x08, 0xd0, 0x1d, 0x87, 0x01, 0x00, 0x70, 0x77, 0x77, 0x87, 0x82, 0xac, 0x55, 0x41, 0x29, 0x23, 0xe0, 0x08, 0xc0, 0x0e, 0x87, 0x01, + 0x02, 0x81, 0x92, 0x5e, 0xab, 0xc4, 0xb6, 0x1f, 0x1e, 0x0a, 0xc4, 0xb2, 0xe1, 0x04, 0xa4, 0x7a, 0x0d, 0xab, 0x97, 0x26, 0x79, 0xf1, 0x9d, 0xd7, 0x26, 0x76, + 0x01, 0xba, 0x26, 0x74, 0xe0, 0xcb, 0x05, 0x86, 0x38, 0x13, 0xe4, 0x00, 0x2c, 0x1b, 0x00, 0x19, 0x80, 0xb8, 0xd9, 0x63, 0xc9, 0x9c, 0x48, 0x7f, 0x15, 0xdd, + 0xf1, 0x3e, 0xbd, 0x24, 0x5f, 0x04, 0x0c, 0x68, 0x95, 0xd3, 0xb1, 0xc0, 0xba, 0xbe, 0x82, 0xf5, 0x03, 0xc0, 0x2a, 0xa7, 0xcc, 0x8f, 0x00, 0x57, 0x5d, 0x99, + 0x52, 0xf1, 0x1a, 0x40, 0xb9, 0xdb, 0x74, 0xfe, 0x04, 0x70, 0xd4, 0xc6, 0xb2, 0x01, 0x74, 0x33, 0x69, 0x00, 0xd7, 0xde, 0x6f, 0xae, 0xdb, 0x06, 0xd9, 0x1f, + 0x4d, 0x9d, 0x9b, 0x3f, 0x03, 0x6c, 0x22, 0xd4, 0x00, 0xea, 0xc7, 0x80, 0x63, 0x38, 0x73, 0x01, 0xca, 0x2e, 0x95, 0xdc, 0x59, 0xee, 0x57, 0x3e, 0x1c, 0x05, + 0x79, 0xdc, 0xba, 0x32, 0xf5, 0xb9, 0xd1, 0xba, 0xea, 0xed, 0xe9, 0xd6, 0x36, 0xfe, 0x63, 0xc0, 0xaa, 0x83, 0x6b, 0xfd, 0x0b, 0x80, 0xfe, 0xd4, 0xc0, 0xec, + 0x0a, 0xc4, 0x6d, 0xed, 0x10, 0x1e, 0x36, 0x3b, 0xa7, 0x4a, 0xaf, 0x91, 0xf5, 0xb1, 0x0b, 0xdd, 0x18, 0xfe, 0x66, 0xd8, 0xfb, 0x57, 0x3f, 0x07, 0x8c, 0x05, + 0x1f, 0x02, 0x82, 0x13, 0xe2, 0xaf, 0x02, 0xe0, 0x1b, 0xf0, 0x7b, 0x00, 0xd6, 0xde, 0xef, 0x65, 0x80, 0xae, 0xae, 0xfd, 0x32, 0x80, 0xa9, 0x7c, 0xd8, 0x7e, + 0x7c, 0x08, 0xe8, 0xcf, 0xbf, 0x97, 0x01, 0xfd, 0xbd, 0x78, 0x9e, 0x07, 0xfc, 0x7b, 0x00, 0x3e, 0x19, 0xff, 0x31, 0xe0, 0xf3, 0x8d, 0xfe, 0xc5, 0x38, 0xdc, + 0x8f, 0xf4, 0x6d, 0x2e, 0xdd, 0x66, 0xeb, 0xef, 0x99, 0xd3, 0x73, 0x36, 0xf6, 0x32, 0x60, 0xce, 0x93, 0x5e, 0x07, 0xac, 0xd3, 0x9f, 0x97, 0xfb, 0xc3, 0x9c, + 0x6b, 0xdc, 0x00, 0xf4, 0x97, 0xe2, 0x0d, 0x40, 0x9f, 0x59, 0xde, 0x01, 0x88, 0xe1, 0x5d, 0x37, 0xfd, 0x29, 0xe0, 0x7b, 0x7c, 0x8f, 0xaf, 0x19, 0x77, 0x3f, + 0xb6, 0xf6, 0x3f, 0x15, 0x5e, 0x1c, 0xca, 0x9b, 0x04, 0x27, 0x70, 0xeb, 0xc0, 0x63, 0x8e, 0x1d, 0x3e, 0x0f, 0xb0, 0x56, 0xfe, 0x99, 0x77, 0x00, 0x7f, 0xdc, + 0x05, 0xfc, 0xf5, 0xe9, 0x12, 0x6e, 0x01, 0x3e, 0xdf, 0xad, 0xb7, 0x23, 0x7d, 0x9f, 0x4b, 0xb7, 0xd9, 0x7a, 0x3f, 0x1f, 0xbe, 0xc7, 0xff, 0x75, 0xfc, 0x0d, + 0x3b, 0xd4, 0xd5, 0x4b, 0x3b, 0xfe, 0xb6, 0x75, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82}; +const inline size_t TEXTURE_ATLAS_LENGTH = 1242; + +const inline uint8_t FONT_REGULAR_DATA[] = { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x05, 0xd0, 0x02, 0xf1, 0x00, 0x00, 0x4f, 0xd8, 0x00, 0x00, + 0x00, 0x56, 0x47, 0x50, 0x4f, 0x53, 0x28, 0x98, 0x0a, 0xef, 0x00, 0x00, 0x50, 0x30, 0x00, 0x00, 0x07, 0xb2, 0x47, 0x53, 0x55, 0x42, 0x39, 0x7a, 0x34, 0x30, + 0x00, 0x00, 0x57, 0xe4, 0x00, 0x00, 0x01, 0x50, 0x4f, 0x53, 0x2f, 0x32, 0x69, 0x4f, 0x5e, 0x78, 0x00, 0x00, 0x3c, 0xe0, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, + 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, 0x20, 0x3e, 0x0e, 0x1b, 0x37, 0x00, 0x00, 0x4c, 0x88, + 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, 0x0b, 0x83, 0x00, 0x00, 0x3d, 0x74, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x4f, 0xd0, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0xaf, 0xdf, 0xf8, 0x38, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x38, 0x4e, + 0x68, 0x65, 0x61, 0x64, 0x28, 0x83, 0xdb, 0xfe, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00, 0x00, 0x36, 0x68, 0x68, 0x65, 0x61, 0x0c, 0xb3, 0x0b, 0xe0, 0x00, 0x00, + 0x3c, 0xbc, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0xe7, 0xb3, 0x14, 0xa5, 0x00, 0x00, 0x3a, 0xd0, 0x00, 0x00, 0x01, 0xea, 0x6c, 0x6f, 0x63, 0x61, + 0x0d, 0xd0, 0xff, 0xd0, 0x00, 0x00, 0x39, 0x8c, 0x00, 0x00, 0x01, 0x0a, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x55, 0x10, 0x75, 0x00, 0x00, 0x39, 0x6c, 0x00, 0x00, + 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2a, 0x6f, 0x43, 0x21, 0x00, 0x00, 0x4d, 0xb4, 0x00, 0x00, 0x01, 0xfc, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x9f, 0x00, 0x32, + 0x00, 0x00, 0x4f, 0xb0, 0x00, 0x00, 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0x44, 0x7e, 0xc6, 0xb9, 0x00, 0x00, 0x4b, 0x80, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, + 0x00, 0x48, 0xff, 0xf2, 0x00, 0xc4, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, + 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x24, 0x23, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x37, 0x23, 0x03, 0x33, 0x03, 0x34, 0x36, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0xa3, 0x39, 0x19, 0x6b, 0x74, 0x24, 0x1a, 0x19, 0x25, 0x25, 0x19, 0x1a, 0x24, 0xc9, 0x02, 0x01, 0xfd, + 0x6c, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x02, 0x00, 0x41, 0x01, 0xc8, 0x01, 0x57, 0x02, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x40, 0x21, + 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x05, 0x03, 0x04, 0x03, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, + 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0x21, 0x03, 0x23, 0x03, 0xa0, 0x14, 0x37, 0x14, 0x01, 0x16, 0x14, 0x37, 0x14, 0x02, + 0xca, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x00, 0x19, 0x00, 0x00, 0x02, 0x6c, 0x02, 0xca, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, + 0x40, 0x44, 0x0c, 0x0a, 0x02, 0x08, 0x0f, 0x10, 0x0d, 0x03, 0x07, 0x00, 0x08, 0x07, 0x68, 0x0e, 0x06, 0x02, 0x00, 0x05, 0x03, 0x02, 0x01, 0x02, 0x00, 0x01, + 0x67, 0x0b, 0x01, 0x09, 0x09, 0x6a, 0x4d, 0x04, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, 0x1c, 0x00, 0x1b, 0x00, 0x1b, 0x1a, 0x19, + 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0d, 0x1f, 0x2b, 0x01, 0x07, 0x33, 0x15, 0x23, 0x07, 0x23, + 0x37, 0x23, 0x07, 0x23, 0x37, 0x23, 0x35, 0x33, 0x37, 0x23, 0x35, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, 0x15, 0x05, 0x33, 0x37, 0x23, 0x01, + 0xe0, 0x1f, 0x89, 0x96, 0x29, 0x47, 0x29, 0x8f, 0x27, 0x46, 0x26, 0x7e, 0x8b, 0x20, 0x86, 0x92, 0x28, 0x48, 0x28, 0x90, 0x28, 0x45, 0x28, 0x7f, 0xfe, 0x7f, + 0x8f, 0x1f, 0x8f, 0x01, 0xb4, 0xa0, 0x43, 0xd1, 0xd1, 0xd1, 0xd1, 0x43, 0xa0, 0x42, 0xd4, 0xd4, 0xd4, 0xd4, 0x42, 0xa0, 0xa0, 0x00, 0x00, 0x03, 0x00, 0x3e, + 0xff, 0xc6, 0x02, 0x04, 0x02, 0xf7, 0x00, 0x22, 0x00, 0x29, 0x00, 0x30, 0x00, 0x69, 0x40, 0x14, 0x30, 0x2a, 0x29, 0x23, 0x19, 0x18, 0x15, 0x14, 0x08, 0x04, + 0x0a, 0x01, 0x02, 0x20, 0x03, 0x02, 0x00, 0x01, 0x02, 0x4c, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x1c, 0x04, 0x01, 0x02, 0x03, 0x01, 0x03, 0x02, 0x01, 0x80, + 0x00, 0x05, 0x00, 0x05, 0x86, 0x00, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x6a, 0x00, 0x03, 0x03, 0x6c, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x03, 0x02, 0x03, + 0x85, 0x04, 0x01, 0x02, 0x01, 0x02, 0x85, 0x00, 0x05, 0x00, 0x05, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x62, 0x00, 0x00, 0x01, + 0x00, 0x52, 0x59, 0x40, 0x09, 0x1f, 0x11, 0x11, 0x16, 0x15, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x37, 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x35, 0x26, 0x26, + 0x35, 0x34, 0x36, 0x37, 0x35, 0x33, 0x15, 0x16, 0x16, 0x17, 0x07, 0x26, 0x26, 0x27, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x15, 0x23, 0x11, 0x06, 0x06, + 0x15, 0x14, 0x16, 0x17, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0xfd, 0x37, 0x68, 0x20, 0x22, 0x6a, 0x33, 0x63, 0x5c, 0x67, 0x58, 0x40, 0x35, 0x57, 0x24, + 0x1b, 0x20, 0x4d, 0x28, 0x42, 0x58, 0x2d, 0x68, 0x5f, 0x40, 0x36, 0x33, 0x2d, 0x3c, 0x40, 0x3b, 0x36, 0x30, 0x41, 0x31, 0x01, 0x11, 0x0f, 0x55, 0x10, 0x18, + 0x01, 0xca, 0x1b, 0x52, 0x47, 0x4a, 0x54, 0x05, 0x58, 0x57, 0x01, 0x15, 0x0f, 0x4a, 0x0d, 0x13, 0x03, 0xc9, 0x13, 0x2b, 0x3f, 0x32, 0x46, 0x57, 0x0a, 0x6f, + 0x02, 0x8c, 0x04, 0x2a, 0x21, 0x28, 0x2b, 0x0f, 0xfe, 0xe2, 0x06, 0x2b, 0x22, 0x26, 0x27, 0x10, 0x00, 0x05, 0x00, 0x31, 0xff, 0xf6, 0x03, 0x0e, 0x02, 0xd4, + 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x25, 0x00, 0x2f, 0x00, 0x99, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x2c, 0x0d, 0x01, 0x06, 0x0e, 0x01, 0x08, 0x05, + 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, 0x0b, 0x03, 0x0a, 0x03, 0x00, 0x00, 0x70, 0x4d, 0x00, + 0x09, 0x09, 0x02, 0x61, 0x07, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x34, 0x0d, 0x01, 0x06, 0x0e, 0x01, 0x08, 0x05, 0x06, 0x08, 0x6a, 0x00, 0x05, + 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0b, 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, 0x0a, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x02, + 0x02, 0x6b, 0x4d, 0x00, 0x09, 0x09, 0x07, 0x61, 0x00, 0x07, 0x07, 0x71, 0x07, 0x4e, 0x59, 0x40, 0x2b, 0x27, 0x26, 0x1b, 0x1a, 0x11, 0x10, 0x0c, 0x0c, 0x01, + 0x00, 0x2d, 0x2b, 0x26, 0x2f, 0x27, 0x2f, 0x21, 0x1f, 0x1a, 0x25, 0x1b, 0x25, 0x17, 0x15, 0x10, 0x19, 0x11, 0x19, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, + 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x05, 0x01, 0x23, 0x01, 0x05, + 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x35, 0x34, 0x05, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, + 0x16, 0x33, 0x32, 0x35, 0x34, 0xc3, 0x4a, 0x4c, 0x49, 0x4d, 0x47, 0x4b, 0x46, 0x02, 0x15, 0xfe, 0x74, 0x4d, 0x01, 0x8c, 0xfe, 0x84, 0x26, 0x23, 0x23, 0x26, + 0x4d, 0x01, 0x68, 0x49, 0x4d, 0x49, 0x4d, 0x47, 0x4b, 0x46, 0x4c, 0x26, 0x23, 0x23, 0x26, 0x4d, 0x02, 0xd4, 0x75, 0x6a, 0x6a, 0x77, 0x77, 0x6a, 0x6a, 0x75, + 0x0a, 0xfd, 0x36, 0x02, 0xca, 0x34, 0x51, 0x50, 0x50, 0x52, 0xa2, 0xa1, 0xe0, 0x75, 0x6a, 0x6a, 0x77, 0x77, 0x6a, 0x6a, 0x75, 0x3f, 0x50, 0x50, 0x51, 0x51, + 0xa2, 0xa0, 0x00, 0x03, 0x00, 0x35, 0xff, 0xf6, 0x02, 0xda, 0x02, 0xd5, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x35, 0x00, 0x7a, 0x40, 0x0f, 0x26, 0x1a, 0x06, 0x03, + 0x01, 0x04, 0x35, 0x11, 0x0e, 0x07, 0x04, 0x05, 0x01, 0x02, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x23, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, + 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, + 0x4e, 0x1b, 0x40, 0x21, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6b, 0x4d, + 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x59, 0x40, 0x17, 0x21, 0x20, 0x01, 0x00, 0x33, 0x31, 0x20, 0x2b, 0x21, 0x2b, 0x15, 0x13, + 0x10, 0x0f, 0x0b, 0x0a, 0x00, 0x1f, 0x01, 0x1f, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, + 0x07, 0x17, 0x23, 0x27, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x36, + 0x36, 0x35, 0x34, 0x26, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x01, 0x30, 0x50, 0x5d, 0x51, 0x3e, 0xc1, 0x1a, 0x21, 0x0b, 0x59, 0x10, + 0x30, 0x26, 0x92, 0x77, 0x57, 0x2f, 0x74, 0x53, 0x67, 0x7a, 0x53, 0x47, 0x20, 0x37, 0x63, 0x52, 0x2a, 0x35, 0x26, 0x24, 0x3b, 0x33, 0x30, 0x52, 0x36, 0x3d, + 0x4a, 0x3e, 0x40, 0x5c, 0x1f, 0x02, 0xd5, 0x51, 0x49, 0x3f, 0x58, 0x24, 0xba, 0x1f, 0x51, 0x2f, 0x40, 0x6e, 0x29, 0x8e, 0x54, 0x2a, 0x34, 0x66, 0x5e, 0x4d, + 0x5d, 0x28, 0x24, 0x52, 0x37, 0x4a, 0x52, 0x48, 0x2c, 0x27, 0x24, 0x3d, 0x25, 0x22, 0x3d, 0x28, 0x24, 0x2e, 0xfe, 0xc8, 0x20, 0x42, 0x36, 0x37, 0x42, 0x2a, + 0x1d, 0x00, 0x00, 0x01, 0x00, 0x41, 0x01, 0xc8, 0x00, 0xa0, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, + 0x01, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0xa0, 0x14, 0x37, 0x14, 0x02, 0xca, 0xfe, + 0xfe, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, 0x62, 0x01, 0x0e, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, 0x00, 0x01, 0x00, 0x01, 0x86, 0x00, + 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x16, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x13, 0x34, 0x36, 0x37, 0x33, 0x06, 0x06, 0x15, 0x14, 0x16, 0x17, 0x23, 0x26, 0x26, 0x28, + 0x47, 0x4c, 0x53, 0x46, 0x47, 0x47, 0x45, 0x52, 0x4c, 0x47, 0x01, 0x12, 0x7a, 0xe3, 0x5b, 0x5e, 0xe2, 0x77, 0x74, 0xdf, 0x5e, 0x58, 0xdf, 0x00, 0x00, 0x01, + 0x00, 0x1e, 0xff, 0x62, 0x01, 0x04, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x01, 0x00, 0x86, 0x00, 0x01, 0x01, 0x6a, 0x01, 0x4e, 0x16, + 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x23, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x01, 0x04, 0x47, 0x4c, 0x52, 0x45, 0x47, + 0x47, 0x46, 0x53, 0x4c, 0x47, 0x01, 0x12, 0x79, 0xdf, 0x58, 0x5e, 0xdf, 0x74, 0x77, 0xe2, 0x5e, 0x5b, 0xe3, 0x00, 0x01, 0x00, 0x29, 0x01, 0x36, 0x01, 0xfc, + 0x02, 0xf8, 0x00, 0x0e, 0x00, 0x33, 0x40, 0x10, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x0d, 0x00, 0x49, 0x4b, 0xb0, + 0x29, 0x50, 0x58, 0xb6, 0x01, 0x01, 0x00, 0x00, 0x6c, 0x00, 0x4e, 0x1b, 0xb4, 0x01, 0x01, 0x00, 0x00, 0x76, 0x59, 0x40, 0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x0e, 0x02, 0x0d, 0x16, 0x2b, 0x01, 0x07, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x27, 0x01, 0x42, 0x14, 0xc0, 0x0e, 0xb8, + 0x77, 0x56, 0x55, 0x4d, 0x59, 0x75, 0xb6, 0x0e, 0xbe, 0x15, 0x02, 0xf8, 0xc0, 0x36, 0x5c, 0x0f, 0x9e, 0x2f, 0xaf, 0xaf, 0x2f, 0x9e, 0x0f, 0x5c, 0x36, 0xc0, + 0x00, 0x01, 0x00, 0x32, 0x00, 0x6f, 0x02, 0x08, 0x02, 0x53, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x00, 0x05, 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, + 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, 0x05, 0x02, 0x5f, 0x00, 0x02, 0x05, 0x02, 0x4f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, + 0x01, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, 0x01, 0x41, 0xc7, 0xc7, 0x48, 0xc7, 0xc7, 0x48, 0x01, 0x84, 0x47, 0xce, 0xce, 0x47, + 0xcf, 0x00, 0x00, 0x01, 0x00, 0x29, 0xff, 0x7f, 0x00, 0xc0, 0x00, 0x74, 0x00, 0x08, 0x00, 0x18, 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, + 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x13, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x37, 0x06, 0x06, 0x07, 0x23, 0x36, 0x36, 0x37, 0x33, 0xc0, 0x0d, 0x31, + 0x18, 0x41, 0x0e, 0x1d, 0x07, 0x5e, 0x69, 0x35, 0x7f, 0x36, 0x39, 0x88, 0x34, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0xe5, 0x01, 0x1a, 0x01, 0x33, 0x00, 0x03, + 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, 0x35, 0x33, 0x15, 0x28, 0xf2, 0xe5, 0x4e, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x48, 0xff, 0xf2, 0x00, 0xc4, 0x00, 0x79, + 0x00, 0x0b, 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x22, 0x02, 0x0d, 0x18, 0x2b, 0x37, 0x34, 0x36, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x48, 0x24, 0x19, 0x1a, 0x25, 0x25, 0x1a, 0x19, 0x24, 0x36, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, + 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x6a, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, + 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x01, 0x01, 0x23, 0x01, 0x01, 0x6a, 0xfe, 0xf6, 0x56, 0x01, 0x0a, 0x02, 0xca, + 0xfd, 0x36, 0x02, 0xca, 0x00, 0x02, 0x00, 0x31, 0xff, 0xf6, 0x02, 0x0b, 0x02, 0xd5, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, + 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x24, 0x25, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, + 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, + 0x0b, 0x30, 0x68, 0x56, 0x79, 0x73, 0x2f, 0x68, 0x55, 0x78, 0x76, 0xfe, 0x7e, 0x43, 0x51, 0x50, 0x45, 0x45, 0x50, 0x51, 0x43, 0x01, 0x66, 0x73, 0xa5, 0x58, + 0xc3, 0xad, 0x74, 0xa4, 0x57, 0xc1, 0xae, 0x93, 0x92, 0x91, 0x94, 0x92, 0x92, 0x92, 0x00, 0x01, 0x00, 0x59, 0x00, 0x00, 0x01, 0x63, 0x02, 0xca, 0x00, 0x0c, + 0x00, 0x1b, 0x40, 0x18, 0x0a, 0x09, 0x05, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1a, 0x10, 0x02, + 0x0d, 0x18, 0x2b, 0x21, 0x23, 0x11, 0x34, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, 0x01, 0x63, 0x56, 0x02, 0x02, 0x10, 0x1a, 0x14, 0x4c, 0x2e, + 0xc1, 0x49, 0x01, 0xf3, 0x2b, 0x34, 0x1c, 0x10, 0x16, 0x11, 0x3e, 0x3b, 0x96, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x00, 0x02, 0x08, 0x02, 0xd4, 0x00, 0x1b, + 0x00, 0x2a, 0x40, 0x27, 0x0e, 0x0d, 0x02, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, + 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x27, 0x25, 0x28, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x3e, 0x02, 0x35, 0x34, + 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x15, 0x21, 0x02, 0x08, 0xfe, 0x28, 0xbb, 0x36, 0x4a, + 0x26, 0x46, 0x38, 0x34, 0x4f, 0x29, 0x2f, 0x2a, 0x6d, 0x44, 0x64, 0x74, 0x2e, 0x52, 0x37, 0x95, 0x01, 0x69, 0x49, 0xbd, 0x36, 0x54, 0x51, 0x30, 0x3b, 0x3d, + 0x24, 0x20, 0x3b, 0x23, 0x31, 0x65, 0x59, 0x38, 0x62, 0x5f, 0x36, 0x93, 0x04, 0x00, 0x00, 0x01, 0x00, 0x2d, 0xff, 0xf6, 0x02, 0x03, 0x02, 0xd4, 0x00, 0x2a, + 0x00, 0x40, 0x40, 0x3d, 0x24, 0x01, 0x03, 0x04, 0x03, 0x01, 0x02, 0x03, 0x0f, 0x01, 0x01, 0x02, 0x0e, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x25, 0x01, 0x04, 0x01, + 0x4b, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x25, 0x24, 0x21, 0x24, 0x25, 0x2a, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, + 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, + 0x36, 0x36, 0x33, 0x32, 0x16, 0x01, 0xed, 0x50, 0x44, 0x56, 0x54, 0x3a, 0x79, 0x5f, 0x38, 0x60, 0x2c, 0x2d, 0x68, 0x30, 0x60, 0x55, 0x69, 0x5f, 0x45, 0x46, + 0x58, 0x5b, 0x46, 0x3c, 0x3a, 0x52, 0x28, 0x2c, 0x26, 0x71, 0x48, 0x70, 0x6d, 0x02, 0x23, 0x48, 0x55, 0x0e, 0x04, 0x0a, 0x58, 0x47, 0x3e, 0x61, 0x36, 0x11, + 0x16, 0x52, 0x16, 0x19, 0x4b, 0x42, 0x43, 0x3b, 0x4b, 0x4a, 0x3d, 0x34, 0x39, 0x22, 0x1a, 0x3c, 0x1e, 0x2c, 0x64, 0x00, 0x00, 0x02, 0x00, 0x15, 0x00, 0x00, + 0x02, 0x28, 0x02, 0xce, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x2b, 0x40, 0x28, 0x0e, 0x01, 0x04, 0x03, 0x06, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x05, 0x01, 0x04, 0x02, + 0x01, 0x00, 0x01, 0x04, 0x00, 0x68, 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x19, 0x11, 0x12, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, + 0x2b, 0x25, 0x23, 0x15, 0x23, 0x35, 0x21, 0x35, 0x01, 0x33, 0x11, 0x33, 0x27, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x07, 0x03, 0x21, 0x02, 0x28, 0x68, 0x55, + 0xfe, 0xaa, 0x01, 0x50, 0x5b, 0x68, 0xbd, 0x04, 0x01, 0x04, 0x08, 0x18, 0x0b, 0xd6, 0x01, 0x00, 0xa2, 0xa2, 0xa2, 0x4b, 0x01, 0xe1, 0xfe, 0x23, 0xe1, 0x34, + 0x49, 0x21, 0x13, 0x2c, 0x0f, 0xfe, 0xcf, 0x00, 0x00, 0x01, 0x00, 0x3f, 0xff, 0xf6, 0x02, 0x03, 0x02, 0xca, 0x00, 0x1e, 0x00, 0x44, 0x40, 0x41, 0x1c, 0x17, + 0x02, 0x03, 0x00, 0x16, 0x0a, 0x02, 0x02, 0x03, 0x09, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x03, 0x02, 0x00, 0x03, 0x69, 0x00, 0x05, 0x05, + 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x01, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x14, 0x12, + 0x0e, 0x0c, 0x07, 0x05, 0x00, 0x1e, 0x01, 0x1e, 0x07, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, + 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x15, 0x21, 0x07, 0x36, 0x36, 0x01, 0x13, 0x6e, 0x82, 0x8d, 0x7e, 0x37, 0x61, 0x21, + 0x24, 0x67, 0x2f, 0x4f, 0x61, 0x56, 0x5d, 0x1c, 0x48, 0x16, 0x2c, 0x1b, 0x01, 0x66, 0xfe, 0xe5, 0x11, 0x11, 0x3a, 0x01, 0xb6, 0x6e, 0x64, 0x6f, 0x7f, 0x14, + 0x13, 0x53, 0x16, 0x19, 0x4b, 0x4f, 0x46, 0x4b, 0x0a, 0x05, 0x1c, 0x01, 0x51, 0x50, 0xcf, 0x03, 0x08, 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x0d, + 0x02, 0xd4, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x3e, 0x40, 0x3b, 0x08, 0x01, 0x01, 0x00, 0x09, 0x01, 0x02, 0x01, 0x11, 0x01, 0x04, 0x05, 0x03, 0x4c, 0x00, 0x02, + 0x00, 0x05, 0x04, 0x02, 0x05, 0x69, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x70, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, + 0x03, 0x4e, 0x20, 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x24, 0x27, 0x25, 0x24, 0x07, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, + 0x15, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x26, 0x17, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x37, 0x1b, 0x47, 0x80, 0x65, 0x15, 0x33, 0x10, 0x12, 0x2d, 0x17, 0x45, 0x5c, 0x35, 0x18, 0x03, 0x06, + 0x17, 0x52, 0x40, 0x5d, 0x72, 0x7b, 0x68, 0x44, 0x6e, 0x41, 0xf2, 0x3f, 0x4e, 0x45, 0x45, 0x2f, 0x46, 0x27, 0x22, 0x44, 0x01, 0x31, 0x4d, 0x95, 0x79, 0x48, + 0x04, 0x05, 0x4b, 0x06, 0x06, 0x2e, 0x50, 0x68, 0x3b, 0x23, 0x31, 0x71, 0x68, 0x70, 0x80, 0x44, 0x8c, 0x86, 0x51, 0x55, 0x44, 0x50, 0x27, 0x3c, 0x20, 0x2b, + 0x55, 0x37, 0x00, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x02, 0x0b, 0x02, 0xca, 0x00, 0x06, 0x00, 0x25, 0x40, 0x22, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x00, + 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, + 0x2b, 0x33, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x88, 0x01, 0x25, 0xfe, 0x7f, 0x01, 0xdf, 0xfe, 0xde, 0x02, 0x7a, 0x50, 0x44, 0xfd, 0x7a, 0x00, 0x00, 0x03, + 0x00, 0x31, 0xff, 0xf6, 0x02, 0x0a, 0x02, 0xd4, 0x00, 0x1b, 0x00, 0x28, 0x00, 0x35, 0x00, 0x36, 0x40, 0x33, 0x33, 0x23, 0x15, 0x07, 0x04, 0x03, 0x02, 0x01, + 0x4c, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1d, 0x1c, + 0x01, 0x00, 0x2d, 0x2b, 0x1c, 0x28, 0x1d, 0x28, 0x0f, 0x0d, 0x00, 0x1b, 0x01, 0x1b, 0x06, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, + 0x1e, 0x02, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, + 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x27, 0x06, 0x06, 0x01, 0x1d, 0x5e, 0x78, 0x25, 0x3e, 0x25, + 0x2c, 0x48, 0x2b, 0x7f, 0x6b, 0x73, 0x7c, 0x29, 0x44, 0x27, 0x34, 0x49, 0x38, 0x60, 0x3c, 0x37, 0x47, 0x23, 0x3c, 0x24, 0x34, 0x47, 0x46, 0xcf, 0x4a, 0x4d, + 0x49, 0x4d, 0x52, 0x44, 0x10, 0x42, 0x45, 0x02, 0xd4, 0x58, 0x53, 0x2b, 0x40, 0x31, 0x13, 0x15, 0x35, 0x46, 0x31, 0x5a, 0x69, 0x65, 0x5b, 0x31, 0x48, 0x34, + 0x12, 0x1e, 0x55, 0x42, 0x37, 0x4b, 0x28, 0x47, 0x35, 0x32, 0x25, 0x32, 0x23, 0x10, 0x16, 0x3e, 0x36, 0x32, 0x35, 0xfe, 0x28, 0x34, 0x45, 0x45, 0x37, 0x34, + 0x45, 0x1a, 0x06, 0x1c, 0x49, 0x00, 0x00, 0x02, 0x00, 0x32, 0xff, 0xf6, 0x02, 0x08, 0x02, 0xd4, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x3e, 0x40, 0x3b, 0x10, 0x01, + 0x05, 0x04, 0x09, 0x01, 0x01, 0x02, 0x08, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, + 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x20, 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x25, 0x27, + 0x24, 0x24, 0x07, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, + 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x27, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x26, 0x02, 0x08, 0x1b, + 0x47, 0x81, 0x65, 0x14, 0x35, 0x11, 0x27, 0x31, 0x46, 0x5b, 0x36, 0x18, 0x02, 0x06, 0x16, 0x53, 0x41, 0x5c, 0x71, 0x39, 0x66, 0x45, 0x44, 0x6e, 0x40, 0xf2, + 0x3e, 0x4f, 0x43, 0x46, 0x30, 0x46, 0x27, 0x22, 0x44, 0x01, 0x99, 0x4d, 0x95, 0x79, 0x48, 0x05, 0x05, 0x4b, 0x0d, 0x2e, 0x4f, 0x69, 0x3a, 0x22, 0x31, 0x71, + 0x67, 0x4b, 0x6c, 0x3a, 0x45, 0x8b, 0x86, 0x52, 0x54, 0x45, 0x4f, 0x27, 0x3c, 0x20, 0x2b, 0x54, 0x38, 0x00, 0x00, 0x02, 0x00, 0x48, 0xff, 0xf2, 0x00, 0xc4, + 0x02, 0x26, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, + 0x03, 0x03, 0x71, 0x03, 0x4e, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x11, + 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x48, 0x24, 0x19, 0x1a, 0x25, 0x25, 0x1a, 0x19, 0x24, 0x24, 0x19, 0x1a, 0x25, 0x25, 0x1a, + 0x19, 0x24, 0x01, 0xe2, 0x26, 0x1e, 0x1e, 0x26, 0x24, 0x20, 0x20, 0xfe, 0x78, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x02, 0x00, 0x1f, 0xff, 0x7f, + 0x00, 0xc2, 0x02, 0x26, 0x00, 0x0b, 0x00, 0x15, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x02, 0x03, 0x02, 0x63, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x73, 0x01, 0x4e, 0x14, 0x15, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x13, 0x06, + 0x06, 0x07, 0x23, 0x3e, 0x02, 0x37, 0x33, 0x46, 0x24, 0x19, 0x1a, 0x25, 0x25, 0x1a, 0x19, 0x24, 0x71, 0x0d, 0x31, 0x18, 0x42, 0x0a, 0x13, 0x11, 0x05, 0x5e, + 0x01, 0xe2, 0x26, 0x1e, 0x1e, 0x26, 0x24, 0x20, 0x20, 0xfe, 0xab, 0x34, 0x81, 0x35, 0x26, 0x57, 0x55, 0x23, 0x00, 0x01, 0x00, 0x32, 0x00, 0x74, 0x02, 0x09, + 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, 0x32, 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, 0x05, 0x02, 0x09, 0xfe, 0x29, 0x01, 0xd7, 0xfe, + 0x87, 0x01, 0x79, 0x74, 0xcf, 0x32, 0xeb, 0x4e, 0xb2, 0x9e, 0x00, 0x02, 0x00, 0x38, 0x00, 0xd9, 0x02, 0x02, 0x01, 0xe7, 0x00, 0x03, 0x00, 0x07, 0x00, 0x2f, + 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, + 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, + 0x35, 0x21, 0x15, 0x38, 0x01, 0xca, 0xfe, 0x36, 0x01, 0xca, 0x01, 0xa0, 0x47, 0x47, 0xc7, 0x47, 0x47, 0x00, 0x00, 0x01, 0x00, 0x32, 0x00, 0x74, 0x02, 0x09, + 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, 0x25, 0x25, 0x35, 0x05, 0x15, 0x05, 0x32, 0x01, 0x79, 0xfe, 0x87, 0x01, 0xd7, + 0xfe, 0x29, 0xc2, 0x9d, 0xb3, 0x4e, 0xeb, 0x32, 0xcf, 0x00, 0x00, 0x02, 0x00, 0x0c, 0xff, 0xf2, 0x01, 0x98, 0x02, 0xd4, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x32, + 0x40, 0x2f, 0x0f, 0x01, 0x00, 0x01, 0x0e, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x04, 0x4e, 0x24, 0x23, 0x1b, 0x25, 0x2a, 0x05, 0x0d, 0x1b, 0x2b, 0x37, 0x34, + 0x36, 0x36, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x0e, 0x02, 0x15, + 0x15, 0x23, 0x07, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x8c, 0x0f, 0x25, 0x20, 0x27, 0x2b, 0x12, 0x3e, 0x3b, 0x31, 0x4c, 0x23, + 0x1f, 0x28, 0x61, 0x3c, 0x5f, 0x68, 0x1d, 0x35, 0x24, 0x21, 0x23, 0x0c, 0x46, 0x17, 0x23, 0x1b, 0x19, 0x24, 0x24, 0x19, 0x1b, 0x23, 0xe4, 0x26, 0x37, 0x32, + 0x1b, 0x21, 0x2c, 0x2a, 0x1e, 0x30, 0x34, 0x19, 0x11, 0x46, 0x15, 0x1c, 0x5e, 0x51, 0x2d, 0x3f, 0x35, 0x1e, 0x1c, 0x2a, 0x29, 0x1d, 0x11, 0x93, 0x25, 0x1e, + 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x00, 0x02, 0x00, 0x3a, 0xff, 0xa7, 0x03, 0x49, 0x02, 0xca, 0x00, 0x3f, 0x00, 0x4d, 0x00, 0x7b, 0x40, 0x13, 0x16, 0x01, + 0x09, 0x02, 0x47, 0x08, 0x02, 0x03, 0x09, 0x2f, 0x01, 0x05, 0x00, 0x30, 0x01, 0x06, 0x05, 0x04, 0x4c, 0x4b, 0xb0, 0x1e, 0x50, 0x58, 0x40, 0x26, 0x08, 0x01, + 0x03, 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, 0x00, 0x07, 0x07, 0x6a, 0x4d, 0x00, + 0x09, 0x09, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x24, 0x00, 0x02, 0x00, 0x09, 0x03, 0x02, 0x09, 0x69, 0x08, 0x01, 0x03, 0x01, 0x01, + 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, 0x00, 0x07, 0x07, 0x6a, 0x04, 0x4e, 0x59, 0x40, 0x0e, + 0x4b, 0x49, 0x25, 0x27, 0x25, 0x25, 0x26, 0x28, 0x25, 0x25, 0x24, 0x0a, 0x0d, 0x1f, 0x2b, 0x01, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, + 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x06, 0x14, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x26, 0x23, + 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x16, 0x05, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x03, 0x49, 0x15, 0x2c, 0x40, 0x2c, 0x2e, 0x35, 0x06, 0x05, 0x12, 0x46, 0x35, + 0x4c, 0x53, 0x34, 0x5f, 0x41, 0x2c, 0x55, 0x18, 0x0a, 0x01, 0x25, 0x19, 0x1f, 0x2b, 0x17, 0x4b, 0x83, 0x53, 0x72, 0x9d, 0x51, 0x9c, 0x93, 0x3d, 0x6f, 0x2b, + 0x2b, 0x6b, 0x41, 0x76, 0xa8, 0x59, 0x3a, 0x6e, 0x9d, 0x63, 0x68, 0xa2, 0x5d, 0xfe, 0x07, 0x33, 0x2b, 0x38, 0x31, 0x04, 0x06, 0x0d, 0x28, 0x15, 0x31, 0x3c, + 0x1a, 0x01, 0x65, 0x2e, 0x58, 0x47, 0x2b, 0x35, 0x22, 0x25, 0x32, 0x66, 0x54, 0x42, 0x65, 0x3a, 0x0f, 0x09, 0xcb, 0x12, 0x0f, 0x03, 0x34, 0x22, 0x33, 0x55, + 0x33, 0x5d, 0x81, 0x44, 0x5e, 0xa5, 0x6a, 0x94, 0x9e, 0x1b, 0x10, 0x44, 0x12, 0x17, 0x58, 0xa5, 0x74, 0x5d, 0x9f, 0x75, 0x41, 0x56, 0xa0, 0xaf, 0x40, 0x3a, + 0x54, 0x43, 0x7d, 0x04, 0x06, 0x30, 0x4b, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7e, 0x02, 0xcd, 0x00, 0x07, 0x00, 0x11, 0x00, 0x2c, 0x40, 0x29, + 0x0c, 0x01, 0x04, 0x02, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x68, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, + 0x4e, 0x00, 0x00, 0x11, 0x10, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x21, 0x27, 0x21, 0x07, 0x23, 0x01, 0x33, 0x01, 0x01, 0x2e, + 0x02, 0x27, 0x06, 0x06, 0x07, 0x07, 0x33, 0x02, 0x21, 0x56, 0xfe, 0xe5, 0x55, 0x5b, 0x01, 0x17, 0x51, 0x01, 0x16, 0xfe, 0xe2, 0x03, 0x0e, 0x0d, 0x04, 0x07, + 0x12, 0x06, 0x51, 0xe2, 0xdd, 0xdd, 0x02, 0xcd, 0xfd, 0x33, 0x02, 0x05, 0x08, 0x2a, 0x2d, 0x0c, 0x1f, 0x3b, 0x11, 0xd8, 0x00, 0x03, 0x00, 0x61, 0x00, 0x00, + 0x02, 0x54, 0x02, 0xca, 0x00, 0x10, 0x00, 0x19, 0x00, 0x22, 0x00, 0x44, 0x40, 0x41, 0x06, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x08, 0x01, 0x05, + 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x04, 0x04, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, + 0x1a, 0x1a, 0x12, 0x11, 0x01, 0x00, 0x1a, 0x22, 0x1a, 0x21, 0x1d, 0x1b, 0x18, 0x16, 0x11, 0x19, 0x12, 0x19, 0x0f, 0x0d, 0x00, 0x10, 0x01, 0x10, 0x09, 0x0d, + 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x23, 0x23, 0x11, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, + 0x15, 0x15, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x2d, 0x86, 0x89, 0x46, 0x42, 0x2d, 0x49, 0x2a, 0x85, 0x73, 0xfb, 0xde, 0x5c, 0x44, 0x53, + 0x5b, 0x76, 0x90, 0x5f, 0x4a, 0x4d, 0x63, 0x02, 0xca, 0x4f, 0x62, 0x3f, 0x53, 0x0c, 0x05, 0x07, 0x26, 0x46, 0x38, 0x61, 0x6a, 0x02, 0xca, 0xfe, 0xd0, 0x3b, + 0x3a, 0x3b, 0x33, 0xe3, 0x4b, 0xfe, 0xfd, 0x4a, 0x3c, 0x38, 0x45, 0x00, 0x00, 0x01, 0x00, 0x3d, 0xff, 0xf6, 0x02, 0x59, 0x02, 0xd4, 0x00, 0x1a, 0x00, 0x37, + 0x40, 0x34, 0x17, 0x01, 0x00, 0x03, 0x18, 0x09, 0x02, 0x01, 0x00, 0x0a, 0x01, 0x02, 0x01, 0x03, 0x4c, 0x04, 0x01, 0x00, 0x00, 0x03, 0x61, 0x00, 0x03, 0x03, + 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x01, 0x00, 0x16, 0x14, 0x0e, 0x0c, 0x07, 0x05, 0x00, 0x1a, 0x01, 0x1a, 0x05, + 0x0d, 0x16, 0x2b, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, + 0x17, 0x07, 0x26, 0x26, 0x01, 0x93, 0x73, 0x84, 0x7b, 0x7b, 0x2f, 0x54, 0x28, 0x28, 0x55, 0x3b, 0x6d, 0x92, 0x49, 0x4f, 0x9a, 0x6e, 0x71, 0x54, 0x24, 0x21, + 0x51, 0x02, 0x85, 0x9a, 0x86, 0x85, 0x9b, 0x10, 0x0c, 0x4e, 0x0f, 0x0e, 0x5a, 0xa6, 0x70, 0x6c, 0xa5, 0x5d, 0x2a, 0x4c, 0x0f, 0x18, 0x00, 0x02, 0x00, 0x61, + 0x00, 0x00, 0x02, 0x9d, 0x02, 0xca, 0x00, 0x09, 0x00, 0x11, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x03, + 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x21, 0x25, 0x21, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x23, 0x23, 0x11, 0x33, 0x32, 0x16, + 0x16, 0x07, 0x34, 0x26, 0x23, 0x23, 0x11, 0x33, 0x20, 0x02, 0x9d, 0xc5, 0xb0, 0xc7, 0xdc, 0x6c, 0x9e, 0x56, 0x5f, 0x8d, 0x81, 0x75, 0x61, 0x01, 0x22, 0x01, + 0x6c, 0xb5, 0xb7, 0x02, 0xca, 0x50, 0x9b, 0x76, 0x8f, 0x85, 0xfd, 0xd0, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, 0xf0, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x29, + 0x40, 0x26, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x5f, 0x00, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x21, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, + 0x21, 0x01, 0xf0, 0xfe, 0x71, 0x01, 0x8f, 0xfe, 0xcb, 0x01, 0x23, 0xfe, 0xdd, 0x01, 0x35, 0x02, 0xca, 0x4f, 0xdf, 0x4e, 0xff, 0x00, 0x00, 0x01, 0x00, 0x61, + 0x00, 0x00, 0x01, 0xf0, 0x02, 0xca, 0x00, 0x09, 0x00, 0x23, 0x40, 0x20, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, + 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x10, 0x05, 0x0d, 0x1b, 0x2b, 0x33, 0x23, 0x11, 0x21, 0x15, 0x21, 0x15, + 0x21, 0x15, 0x21, 0xbb, 0x5a, 0x01, 0x8f, 0xfe, 0xcb, 0x01, 0x22, 0xfe, 0xde, 0x02, 0xca, 0x4f, 0xfd, 0x4f, 0x00, 0x01, 0x00, 0x3d, 0xff, 0xf6, 0x02, 0x8e, + 0x02, 0xd4, 0x00, 0x20, 0x00, 0x3b, 0x40, 0x38, 0x10, 0x01, 0x03, 0x02, 0x11, 0x01, 0x00, 0x03, 0x1e, 0x01, 0x04, 0x05, 0x02, 0x01, 0x01, 0x04, 0x04, 0x4c, + 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x67, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, + 0x71, 0x01, 0x4e, 0x13, 0x25, 0x25, 0x26, 0x23, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x11, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x35, 0x23, 0x01, 0x97, 0xf7, 0x3a, 0x76, 0x4b, + 0x6f, 0x98, 0x4f, 0x58, 0xa5, 0x75, 0x3c, 0x6b, 0x2e, 0x22, 0x26, 0x5f, 0x33, 0x80, 0x8f, 0x37, 0x76, 0x60, 0x2f, 0x42, 0x1b, 0x9d, 0x01, 0x79, 0xfe, 0xa2, + 0x13, 0x12, 0x59, 0xa5, 0x71, 0x70, 0xa4, 0x5b, 0x16, 0x14, 0x4e, 0x11, 0x18, 0x9a, 0x86, 0x55, 0x83, 0x49, 0x0a, 0x07, 0xd4, 0x00, 0x00, 0x01, 0x00, 0x61, + 0x00, 0x00, 0x02, 0x83, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x21, 0x40, 0x1e, 0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x01, 0x67, 0x05, 0x01, 0x03, 0x03, 0x6a, 0x4d, + 0x02, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, + 0x21, 0x11, 0x33, 0x02, 0x83, 0x5a, 0xfe, 0x92, 0x5a, 0x5a, 0x01, 0x6e, 0x5a, 0x01, 0x4d, 0xfe, 0xb3, 0x02, 0xca, 0xfe, 0xd2, 0x01, 0x2e, 0x00, 0x00, 0x01, + 0x00, 0x28, 0x00, 0x00, 0x01, 0x2a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x0a, 0x09, 0x08, 0x05, 0x04, 0x03, 0x02, 0x08, 0x00, 0x01, 0x01, + 0x4c, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x11, 0x27, 0x35, 0x21, + 0x15, 0x07, 0x11, 0x17, 0x01, 0x2a, 0xfe, 0xfe, 0x54, 0x54, 0x01, 0x02, 0x54, 0x54, 0x34, 0x13, 0x02, 0x3b, 0x14, 0x34, 0x34, 0x14, 0xfd, 0xc5, 0x13, 0x00, + 0x00, 0x01, 0xff, 0xb2, 0xff, 0x42, 0x00, 0xb6, 0x02, 0xca, 0x00, 0x10, 0x00, 0x28, 0x40, 0x25, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, + 0x00, 0x01, 0x03, 0x01, 0x00, 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, 0x01, 0x00, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x10, 0x01, 0x10, 0x04, 0x0d, + 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x04, 0x18, 0x24, 0x0e, 0x10, 0x24, 0x14, + 0x19, 0x2d, 0x1c, 0x5a, 0x66, 0xbe, 0x07, 0x06, 0x4c, 0x04, 0x06, 0x14, 0x32, 0x2d, 0x02, 0xc6, 0xfd, 0x41, 0x67, 0x62, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, + 0x02, 0x6b, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x20, 0x40, 0x1d, 0x0e, 0x08, 0x03, 0x02, 0x04, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, + 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x11, 0x13, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x07, 0x11, 0x23, 0x11, 0x33, 0x11, 0x36, 0x36, 0x37, + 0x37, 0x33, 0x01, 0x02, 0x6b, 0x6a, 0xfd, 0x49, 0x5a, 0x5a, 0x1e, 0x3e, 0x1f, 0xc1, 0x69, 0xfe, 0xe5, 0x01, 0x55, 0x40, 0xfe, 0xeb, 0x02, 0xca, 0xfe, 0xa0, + 0x22, 0x44, 0x22, 0xd8, 0xfe, 0xc9, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, 0xf3, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x6a, + 0x4d, 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, + 0x11, 0x33, 0x11, 0x21, 0x15, 0x61, 0x5a, 0x01, 0x38, 0x02, 0xca, 0xfd, 0x86, 0x50, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x03, 0x2a, 0x02, 0xca, 0x00, 0x15, + 0x00, 0x27, 0x40, 0x24, 0x13, 0x0a, 0x01, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x05, 0x04, 0x03, 0x03, 0x00, 0x00, 0x6b, 0x00, + 0x4e, 0x00, 0x00, 0x00, 0x15, 0x00, 0x15, 0x11, 0x13, 0x11, 0x16, 0x06, 0x0d, 0x1a, 0x2b, 0x21, 0x03, 0x23, 0x16, 0x16, 0x15, 0x11, 0x23, 0x11, 0x33, 0x13, + 0x33, 0x13, 0x33, 0x11, 0x23, 0x11, 0x34, 0x36, 0x37, 0x23, 0x03, 0x01, 0x9c, 0xeb, 0x04, 0x03, 0x04, 0x53, 0x85, 0xdc, 0x04, 0xe0, 0x84, 0x59, 0x05, 0x02, + 0x04, 0xee, 0x02, 0x72, 0x1f, 0x69, 0x39, 0xfe, 0x4f, 0x02, 0xca, 0xfd, 0xb7, 0x02, 0x49, 0xfd, 0x36, 0x01, 0xb7, 0x34, 0x66, 0x20, 0xfd, 0x8f, 0x00, 0x01, + 0x00, 0x61, 0x00, 0x00, 0x02, 0x97, 0x02, 0xca, 0x00, 0x12, 0x00, 0x1d, 0x40, 0x1a, 0x02, 0x01, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, + 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x17, 0x11, 0x16, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x01, 0x23, 0x16, 0x16, 0x15, 0x11, 0x23, 0x11, 0x33, + 0x01, 0x33, 0x2e, 0x02, 0x35, 0x11, 0x33, 0x02, 0x97, 0x69, 0xfe, 0x82, 0x04, 0x02, 0x06, 0x53, 0x68, 0x01, 0x7d, 0x04, 0x01, 0x03, 0x03, 0x54, 0x02, 0x51, + 0x23, 0x68, 0x37, 0xfe, 0x71, 0x02, 0xca, 0xfd, 0xb1, 0x10, 0x40, 0x4c, 0x20, 0x01, 0x93, 0x00, 0x00, 0x02, 0x00, 0x3d, 0xff, 0xf6, 0x02, 0xd0, 0x02, 0xd5, + 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x24, 0x25, 0x26, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xd0, 0x4b, 0x92, 0x6c, 0x6f, 0x93, 0x48, 0x48, 0x93, 0x70, 0x6b, 0x92, + 0x4b, 0xfd, 0xcc, 0x72, 0x79, 0x7a, 0x70, 0x70, 0x79, 0x79, 0x73, 0x01, 0x66, 0x6f, 0xa5, 0x5c, 0x5c, 0xa6, 0x6f, 0x6e, 0xa4, 0x5c, 0x5b, 0xa5, 0x6f, 0x87, + 0x9b, 0x9b, 0x87, 0x87, 0x99, 0x99, 0x00, 0x02, 0x00, 0x61, 0x00, 0x00, 0x02, 0x2a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x32, 0x40, 0x2f, 0x00, 0x04, + 0x00, 0x01, 0x02, 0x04, 0x01, 0x67, 0x06, 0x01, 0x03, 0x03, 0x00, 0x5f, 0x05, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0d, 0x0c, + 0x01, 0x00, 0x10, 0x0e, 0x0c, 0x14, 0x0d, 0x14, 0x0a, 0x09, 0x08, 0x06, 0x00, 0x0b, 0x01, 0x0b, 0x07, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x06, 0x23, 0x23, 0x11, 0x23, 0x11, 0x17, 0x23, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x1e, 0x8c, 0x80, 0x35, 0x7d, 0x6b, 0x52, 0x5a, 0xb5, 0x5b, + 0x48, 0x66, 0x64, 0x58, 0x02, 0xca, 0x6e, 0x64, 0x3b, 0x67, 0x40, 0xfe, 0xea, 0x02, 0xca, 0x4d, 0xfe, 0xe6, 0x42, 0x4f, 0x45, 0x44, 0x00, 0x02, 0x00, 0x3d, + 0xff, 0x56, 0x02, 0xd0, 0x02, 0xd5, 0x00, 0x14, 0x00, 0x20, 0x00, 0x2b, 0x40, 0x28, 0x03, 0x01, 0x01, 0x03, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x86, 0x00, + 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x25, 0x26, 0x41, 0x14, 0x05, + 0x0d, 0x1b, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x17, 0x23, 0x27, 0x22, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, + 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xd0, 0x69, 0x67, 0xab, 0x81, 0x8a, 0x06, 0x0d, 0x06, 0x6f, 0x93, 0x48, 0x48, 0x93, 0x70, + 0x6b, 0x92, 0x4b, 0xfd, 0xcc, 0x72, 0x79, 0x7a, 0x70, 0x70, 0x79, 0x79, 0x73, 0x01, 0x66, 0x83, 0xb8, 0x23, 0xb2, 0xa1, 0x01, 0x5c, 0xa6, 0x6f, 0x6e, 0xa4, + 0x5c, 0x5b, 0xa5, 0x6f, 0x87, 0x9b, 0x9b, 0x87, 0x87, 0x99, 0x99, 0x00, 0x00, 0x02, 0x00, 0x61, 0x00, 0x00, 0x02, 0x5f, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x17, + 0x00, 0x3b, 0x40, 0x38, 0x07, 0x01, 0x02, 0x05, 0x01, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x5f, 0x06, 0x01, + 0x00, 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x10, 0x0f, 0x01, 0x00, 0x13, 0x11, 0x0f, 0x17, 0x10, 0x17, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, + 0x08, 0x00, 0x0e, 0x01, 0x0e, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x11, 0x23, 0x11, 0x17, 0x23, + 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x26, 0x85, 0x7f, 0x2a, 0x41, 0x24, 0xc4, 0x69, 0xad, 0x8e, 0x5a, 0xc0, 0x66, 0x6b, 0x57, 0x50, 0x54, 0x02, + 0xca, 0x65, 0x66, 0x39, 0x4c, 0x2d, 0x0d, 0xfe, 0xc0, 0x01, 0x27, 0xfe, 0xd9, 0x02, 0xca, 0x4e, 0xfe, 0xf7, 0x45, 0x43, 0x46, 0x3b, 0x00, 0x01, 0x00, 0x33, + 0xff, 0xf6, 0x01, 0xf6, 0x02, 0xd4, 0x00, 0x29, 0x00, 0x2e, 0x40, 0x2b, 0x1b, 0x01, 0x03, 0x02, 0x1c, 0x07, 0x02, 0x01, 0x03, 0x06, 0x01, 0x00, 0x01, 0x03, + 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, 0x2c, 0x25, 0x22, + 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x26, 0x26, 0x35, 0x34, + 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xf6, 0x8a, 0x75, 0x3c, 0x66, 0x22, + 0x24, 0x6b, 0x39, 0x50, 0x51, 0x1e, 0x49, 0x41, 0x5b, 0x5d, 0x3a, 0x67, 0x43, 0x3b, 0x62, 0x28, 0x1c, 0x25, 0x57, 0x2f, 0x43, 0x44, 0x1e, 0x44, 0x3a, 0x3f, + 0x57, 0x2d, 0xbf, 0x5f, 0x6a, 0x12, 0x10, 0x56, 0x10, 0x1a, 0x3e, 0x35, 0x23, 0x30, 0x29, 0x17, 0x21, 0x60, 0x53, 0x39, 0x51, 0x2c, 0x16, 0x12, 0x4d, 0x10, + 0x16, 0x39, 0x2f, 0x24, 0x30, 0x26, 0x16, 0x17, 0x35, 0x4a, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x02, 0x21, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1b, 0x40, 0x18, + 0x03, 0x01, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, + 0x23, 0x11, 0x23, 0x35, 0x21, 0x15, 0x23, 0x01, 0x43, 0x5a, 0xdf, 0x02, 0x17, 0xde, 0x02, 0x7b, 0x4f, 0x4f, 0x00, 0x01, 0x00, 0x5a, 0xff, 0xf6, 0x02, 0x80, + 0x02, 0xca, 0x00, 0x12, 0x00, 0x1b, 0x40, 0x18, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x13, + 0x23, 0x13, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, + 0x02, 0x80, 0x3c, 0x7b, 0x5f, 0x85, 0x8b, 0x5a, 0x5d, 0x5e, 0x61, 0x57, 0x59, 0xfc, 0x4a, 0x77, 0x45, 0x91, 0x77, 0x01, 0xcc, 0xfe, 0x31, 0x57, 0x60, 0x67, + 0x51, 0x01, 0xce, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x58, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x21, 0x40, 0x1e, 0x08, 0x01, 0x00, 0x01, 0x01, 0x4c, + 0x03, 0x02, 0x02, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x01, + 0x03, 0x23, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x36, 0x36, 0x37, 0x13, 0x02, 0x58, 0xff, 0x5a, 0xff, 0x5e, 0xa1, 0x10, 0x16, 0x07, 0x07, 0x16, 0x10, 0xa0, + 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0xfe, 0x36, 0x2c, 0x4d, 0x23, 0x23, 0x4e, 0x2d, 0x01, 0xc8, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x03, 0x95, 0x02, 0xca, + 0x00, 0x1f, 0x00, 0x27, 0x40, 0x24, 0x1b, 0x12, 0x07, 0x03, 0x00, 0x02, 0x01, 0x4c, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, + 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x18, 0x11, 0x19, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x01, 0x03, 0x23, 0x03, 0x2e, 0x02, 0x27, 0x06, 0x06, + 0x07, 0x03, 0x23, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x36, 0x36, 0x37, 0x13, 0x33, 0x13, 0x16, 0x16, 0x17, 0x36, 0x36, 0x37, 0x13, 0x03, 0x95, 0xbe, 0x5b, + 0x8b, 0x08, 0x10, 0x0a, 0x02, 0x01, 0x13, 0x0e, 0x87, 0x5b, 0xbd, 0x5e, 0x6f, 0x0c, 0x11, 0x05, 0x05, 0x14, 0x0d, 0x7e, 0x5d, 0x83, 0x0e, 0x14, 0x05, 0x05, + 0x12, 0x0c, 0x6e, 0x02, 0xca, 0xfd, 0x36, 0x01, 0xd4, 0x1d, 0x3a, 0x2d, 0x09, 0x0d, 0x55, 0x2e, 0xfe, 0x2f, 0x02, 0xca, 0xfe, 0x4c, 0x2e, 0x56, 0x26, 0x27, + 0x5c, 0x2c, 0x01, 0xaf, 0xfe, 0x4e, 0x2e, 0x5b, 0x23, 0x25, 0x57, 0x2f, 0x01, 0xb3, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x02, 0x46, 0x02, 0xca, 0x00, 0x0b, + 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x08, 0x05, 0x02, 0x04, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, + 0x12, 0x12, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x03, 0x23, 0x13, 0x03, 0x33, 0x13, 0x13, 0x33, 0x03, 0x02, 0x46, 0x66, 0xbd, 0xc0, 0x5f, + 0xed, 0xde, 0x64, 0xaf, 0xb0, 0x5f, 0xdd, 0x01, 0x36, 0xfe, 0xca, 0x01, 0x74, 0x01, 0x56, 0xfe, 0xe8, 0x01, 0x18, 0xfe, 0xac, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x36, 0x02, 0xca, 0x00, 0x08, 0x00, 0x1c, 0x40, 0x19, 0x06, 0x03, 0x02, 0x01, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, + 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x12, 0x12, 0x11, 0x03, 0x0d, 0x19, 0x2b, 0x01, 0x13, 0x33, 0x03, 0x11, 0x23, 0x11, 0x03, 0x33, 0x01, 0x1b, 0xba, 0x61, 0xee, + 0x5a, 0xee, 0x62, 0x01, 0x6b, 0x01, 0x5f, 0xfe, 0x4b, 0xfe, 0xeb, 0x01, 0x11, 0x01, 0xb9, 0x00, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x02, 0x15, 0x02, 0xca, + 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x4d, + 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, + 0x15, 0x01, 0x21, 0x02, 0x15, 0xfe, 0x11, 0x01, 0x78, 0xfe, 0x94, 0x01, 0xd9, 0xfe, 0x88, 0x01, 0x82, 0x44, 0x02, 0x36, 0x50, 0x44, 0xfd, 0xca, 0x00, 0x01, + 0x00, 0x50, 0xff, 0x62, 0x01, 0x30, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x63, 0x00, 0x02, 0x02, 0x01, 0x5f, + 0x00, 0x01, 0x01, 0x6a, 0x02, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x05, 0x23, 0x11, 0x33, 0x15, 0x23, 0x11, 0x33, 0x01, 0x30, 0xe0, 0xe0, + 0x8a, 0x8a, 0x9e, 0x03, 0x68, 0x48, 0xfd, 0x28, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x6b, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, + 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x01, 0x23, 0x01, 0x60, + 0x01, 0x0b, 0x57, 0xfe, 0xf6, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0x00, 0x00, 0x01, 0x00, 0x19, 0xff, 0x62, 0x00, 0xf9, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, + 0x40, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x63, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, + 0x1a, 0x2b, 0x17, 0x33, 0x11, 0x23, 0x35, 0x33, 0x11, 0x23, 0x19, 0x8a, 0x8a, 0xe0, 0xe0, 0x56, 0x02, 0xd8, 0x48, 0xfc, 0x98, 0x00, 0x00, 0x01, 0x00, 0x26, + 0x01, 0x0b, 0x02, 0x16, 0x02, 0xcf, 0x00, 0x06, 0x00, 0x27, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, + 0x85, 0x03, 0x02, 0x02, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x13, 0x13, 0x33, + 0x13, 0x23, 0x03, 0x03, 0x26, 0xd4, 0x32, 0xea, 0x4e, 0xb4, 0xa0, 0x01, 0x0b, 0x01, 0xc4, 0xfe, 0x3c, 0x01, 0x67, 0xfe, 0x99, 0x00, 0x00, 0x01, 0xff, 0xfe, + 0xff, 0x66, 0x01, 0xbe, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x20, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, + 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x05, 0x21, 0x35, 0x21, 0x01, 0xbe, 0xfe, 0x40, 0x01, 0xc0, + 0x9a, 0x40, 0x00, 0x01, 0x00, 0x28, 0x02, 0x5e, 0x00, 0xf1, 0x02, 0xfe, 0x00, 0x0b, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x0a, 0x04, 0x02, 0x00, + 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x00, 0x01, 0x85, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, + 0x00, 0x44, 0x13, 0x1e, 0x02, 0x17, 0x15, 0x23, 0x2e, 0x02, 0x27, 0x35, 0x91, 0x0b, 0x21, 0x25, 0x0f, 0x3b, 0x17, 0x3a, 0x31, 0x0c, 0x02, 0xfe, 0x16, 0x37, + 0x34, 0x13, 0x0c, 0x12, 0x39, 0x39, 0x12, 0x0a, 0x00, 0x02, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xe0, 0x02, 0x21, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x7b, 0x40, 0x0e, + 0x19, 0x01, 0x04, 0x00, 0x18, 0x01, 0x03, 0x04, 0x06, 0x01, 0x06, 0x05, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x20, 0x00, 0x03, 0x08, 0x01, 0x05, + 0x06, 0x03, 0x05, 0x67, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, + 0x4e, 0x1b, 0x40, 0x24, 0x00, 0x03, 0x08, 0x01, 0x05, 0x06, 0x03, 0x05, 0x67, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x01, + 0x01, 0x6b, 0x4d, 0x00, 0x06, 0x06, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, 0x26, 0x1d, + 0x26, 0x16, 0x14, 0x11, 0x0f, 0x0b, 0x09, 0x05, 0x04, 0x00, 0x1b, 0x01, 0x1b, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x27, 0x23, 0x06, + 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x13, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, + 0x32, 0x36, 0x35, 0x35, 0x01, 0x20, 0x62, 0x5e, 0x40, 0x11, 0x04, 0x23, 0x4d, 0x44, 0x49, 0x60, 0x7e, 0x83, 0x5b, 0x3a, 0x35, 0x2a, 0x4c, 0x21, 0x1b, 0x23, + 0x60, 0x4e, 0x64, 0x4d, 0x37, 0x2b, 0x44, 0x5a, 0x02, 0x21, 0x56, 0x5e, 0xfe, 0x93, 0x4c, 0x2c, 0x2a, 0x4d, 0x52, 0x50, 0x57, 0x04, 0x03, 0x20, 0x43, 0x34, + 0x19, 0x10, 0x42, 0x13, 0x1b, 0xfe, 0xe2, 0x04, 0x38, 0x33, 0x2d, 0x2a, 0x4b, 0x4e, 0x30, 0x00, 0x00, 0x02, 0x00, 0x55, 0xff, 0xf6, 0x02, 0x30, 0x02, 0xf8, + 0x00, 0x15, 0x00, 0x21, 0x00, 0x8a, 0xb6, 0x10, 0x03, 0x02, 0x05, 0x04, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x6c, 0x4d, + 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1b, 0x4b, 0xb0, + 0x29, 0x50, 0x58, 0x40, 0x20, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x4d, + 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1b, 0x40, 0x20, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, + 0x03, 0x03, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x59, 0x59, 0x40, 0x0f, 0x17, 0x16, + 0x1e, 0x1c, 0x16, 0x21, 0x17, 0x21, 0x11, 0x14, 0x24, 0x26, 0x07, 0x0d, 0x1a, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, + 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x07, 0x23, 0x11, 0x33, 0x13, 0x22, 0x06, 0x15, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0xad, 0x03, 0x02, 0x05, + 0x17, 0x50, 0x3f, 0x64, 0x79, 0x7a, 0x63, 0x3f, 0x50, 0x17, 0x07, 0x12, 0x3f, 0x58, 0x97, 0x55, 0x42, 0x41, 0x58, 0x48, 0x47, 0x02, 0x3f, 0x22, 0x3b, 0x11, + 0x22, 0x2e, 0x8b, 0x8a, 0x8a, 0x8c, 0x2e, 0x20, 0x44, 0x02, 0xf8, 0xfe, 0xe0, 0x62, 0x67, 0x04, 0x63, 0x69, 0x6a, 0x64, 0xcb, 0x00, 0x00, 0x01, 0x00, 0x37, + 0xff, 0xf6, 0x01, 0xbf, 0x02, 0x22, 0x00, 0x1a, 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, 0x02, 0x01, 0x17, 0x0c, 0x02, 0x03, 0x02, 0x18, 0x01, 0x00, 0x03, 0x03, + 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x15, + 0x13, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1a, 0x01, 0x1a, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, + 0x26, 0x26, 0x23, 0x22, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x01, 0x2c, 0x47, 0x6f, 0x3f, 0x42, 0x71, 0x48, 0x29, 0x4c, 0x18, 0x1b, + 0x18, 0x40, 0x1c, 0x9e, 0x4d, 0x4c, 0x2c, 0x43, 0x1c, 0x1b, 0x41, 0x0a, 0x3a, 0x7a, 0x5f, 0x63, 0x7c, 0x3a, 0x11, 0x0c, 0x49, 0x09, 0x10, 0xcb, 0x61, 0x67, + 0x12, 0x0d, 0x4e, 0x0e, 0x0f, 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x12, 0x02, 0xf8, 0x00, 0x15, 0x00, 0x22, 0x00, 0x95, 0xb6, 0x12, 0x09, 0x02, + 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, + 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, + 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6b, 0x4d, + 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x22, 0x17, + 0x22, 0x11, 0x10, 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, + 0x26, 0x26, 0x35, 0x35, 0x33, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x27, 0x32, 0x36, 0x35, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x01, 0x13, + 0x64, 0x78, 0x79, 0x64, 0x3e, 0x4f, 0x19, 0x06, 0x01, 0x05, 0x58, 0x47, 0x0d, 0x04, 0x18, 0x50, 0x31, 0x55, 0x45, 0x42, 0x59, 0x47, 0x47, 0x47, 0x0a, 0x8b, + 0x8a, 0x8a, 0x8d, 0x2e, 0x21, 0x0d, 0x33, 0x0f, 0xd6, 0xfd, 0x08, 0x48, 0x22, 0x30, 0x49, 0x5d, 0x5e, 0x10, 0x64, 0x6b, 0x71, 0x5f, 0x60, 0x6a, 0x00, 0x02, + 0x00, 0x37, 0xff, 0xf6, 0x02, 0x01, 0x02, 0x22, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x43, 0x40, 0x40, 0x0c, 0x01, 0x02, 0x01, 0x0d, 0x01, 0x03, 0x02, 0x02, 0x4c, + 0x00, 0x05, 0x00, 0x01, 0x02, 0x05, 0x01, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, + 0x03, 0x03, 0x71, 0x03, 0x4e, 0x19, 0x18, 0x01, 0x00, 0x1c, 0x1b, 0x18, 0x1e, 0x19, 0x1e, 0x11, 0x0f, 0x0a, 0x08, 0x06, 0x05, 0x00, 0x17, 0x01, 0x17, 0x08, + 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x15, 0x21, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, + 0x36, 0x17, 0x22, 0x06, 0x07, 0x21, 0x26, 0x26, 0x01, 0x24, 0x45, 0x63, 0x35, 0xfe, 0x91, 0x02, 0x59, 0x50, 0x33, 0x4f, 0x2a, 0x29, 0x50, 0x37, 0x4c, 0x75, + 0x41, 0x3b, 0x6b, 0x46, 0x3f, 0x49, 0x07, 0x01, 0x11, 0x01, 0x3e, 0x02, 0x22, 0x3c, 0x6d, 0x49, 0x35, 0x5b, 0x5f, 0x13, 0x12, 0x4d, 0x12, 0x11, 0x3e, 0x7b, + 0x59, 0x58, 0x7e, 0x44, 0x48, 0x51, 0x48, 0x44, 0x55, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x83, 0x02, 0xfd, 0x00, 0x17, 0x00, 0x5c, 0x40, 0x0f, + 0x0e, 0x01, 0x04, 0x03, 0x0f, 0x07, 0x02, 0x05, 0x04, 0x06, 0x01, 0x00, 0x05, 0x03, 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, + 0x61, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x19, + 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x69, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, + 0x40, 0x09, 0x13, 0x25, 0x25, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x37, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, + 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x15, 0x33, 0x01, 0x4c, 0x87, 0x58, 0x5e, 0x5e, 0x5c, 0x52, 0x20, 0x35, 0x13, 0x17, 0x10, 0x2a, 0x16, 0x2c, + 0x2b, 0x87, 0x01, 0xd4, 0xfe, 0x2c, 0x01, 0xd4, 0x29, 0x1e, 0x1f, 0x68, 0x5b, 0x0b, 0x07, 0x45, 0x05, 0x0a, 0x3b, 0x3f, 0x23, 0x00, 0x00, 0x02, 0x00, 0x37, + 0xff, 0x10, 0x02, 0x12, 0x02, 0x22, 0x00, 0x1e, 0x00, 0x2b, 0x00, 0x80, 0x40, 0x0f, 0x16, 0x03, 0x02, 0x06, 0x05, 0x0d, 0x01, 0x03, 0x04, 0x0c, 0x01, 0x02, + 0x03, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x08, 0x01, 0x05, 0x05, 0x00, 0x61, 0x01, 0x07, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, + 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x01, 0x01, 0x6d, 0x4d, + 0x08, 0x01, 0x05, 0x05, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, + 0x61, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x20, 0x1f, 0x01, 0x00, 0x26, 0x24, 0x1f, 0x2b, 0x20, 0x2b, 0x1a, 0x18, 0x10, 0x0e, 0x0b, 0x09, + 0x06, 0x05, 0x00, 0x1e, 0x01, 0x1e, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x14, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, + 0x32, 0x36, 0x35, 0x35, 0x34, 0x36, 0x37, 0x23, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x35, + 0x34, 0x26, 0x01, 0x13, 0x35, 0x55, 0x1e, 0x05, 0x0c, 0x46, 0x75, 0x7b, 0x76, 0x4b, 0x4f, 0x77, 0x45, 0x4f, 0x02, 0x01, 0x04, 0x36, 0x70, 0x68, 0x75, 0x75, + 0x73, 0x43, 0x4a, 0x49, 0x46, 0x51, 0x4a, 0x4c, 0x02, 0x22, 0x28, 0x29, 0x47, 0xfd, 0xdf, 0x73, 0x74, 0x22, 0x51, 0x2a, 0x51, 0x46, 0x15, 0x0c, 0x2d, 0x09, + 0x51, 0x92, 0x83, 0x80, 0x97, 0x4a, 0x6b, 0x63, 0x63, 0x69, 0x57, 0x61, 0x15, 0x6e, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x02, 0x19, 0x02, 0xf8, + 0x00, 0x15, 0x00, 0x48, 0xb5, 0x02, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x16, 0x00, 0x04, 0x04, 0x6c, 0x4d, 0x00, 0x02, 0x02, + 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, + 0x4d, 0x00, 0x04, 0x04, 0x01, 0x5f, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0xb7, 0x11, 0x13, 0x22, 0x13, 0x25, 0x05, 0x0d, 0x1b, 0x2b, 0x13, 0x14, + 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0xad, 0x05, 0x06, 0x1a, 0x59, 0x34, + 0x62, 0x62, 0x57, 0x78, 0x5a, 0x43, 0x58, 0x58, 0x02, 0x19, 0x28, 0x23, 0x29, 0x2a, 0x5d, 0x67, 0xfe, 0xa3, 0x01, 0x57, 0x81, 0x65, 0x5e, 0xfe, 0xeb, 0x02, + 0xf8, 0x00, 0x00, 0x02, 0x00, 0x4e, 0x00, 0x00, 0x00, 0xb5, 0x02, 0xe1, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x8d, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x17, 0x00, + 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x6c, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, + 0x50, 0x58, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, + 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x6c, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, + 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x15, 0x04, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x01, 0x69, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, + 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x13, 0x0c, 0x0c, 0x01, 0x00, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, + 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x11, 0x23, 0x11, 0x82, 0x14, 0x1f, 0x1f, 0x14, 0x16, 0x1e, + 0x1e, 0x41, 0x58, 0x02, 0xe1, 0x1b, 0x1d, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1b, 0xc9, 0xfd, 0xe8, 0x02, 0x18, 0x00, 0x02, 0xff, 0xc9, 0xff, 0x10, 0x00, 0xb5, + 0x02, 0xe1, 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xa5, 0x40, 0x0a, 0x10, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, + 0x1b, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, + 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, + 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x6c, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x19, 0x00, 0x00, 0x00, + 0x01, 0x04, 0x00, 0x01, 0x69, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x59, 0x59, 0x40, + 0x0f, 0x0d, 0x0c, 0x18, 0x17, 0x14, 0x12, 0x0c, 0x1b, 0x0d, 0x1b, 0x24, 0x22, 0x06, 0x0d, 0x18, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x23, 0x22, 0x26, 0x03, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x4e, 0x1e, 0x16, 0x14, 0x1f, 0x1f, 0x14, + 0x16, 0x1e, 0x38, 0x19, 0x26, 0x0e, 0x0f, 0x20, 0x13, 0x20, 0x2a, 0x58, 0x48, 0x02, 0xa9, 0x1d, 0x1b, 0x1b, 0x1d, 0x1c, 0x1c, 0x1c, 0xfc, 0x83, 0x07, 0x05, + 0x47, 0x04, 0x06, 0x23, 0x31, 0x02, 0x6b, 0xfd, 0x98, 0x4b, 0x55, 0x00, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x02, 0x0d, 0x02, 0xf8, 0x00, 0x13, 0x00, 0x47, + 0x40, 0x09, 0x0f, 0x0e, 0x0b, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x11, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x00, 0x00, 0x00, + 0x6d, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x03, 0x03, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x4d, 0x00, 0x00, 0x00, + 0x6d, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0xb6, 0x11, 0x13, 0x12, 0x19, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x3e, 0x02, + 0x37, 0x37, 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x15, 0x23, 0x11, 0x33, 0xac, 0x03, 0x01, 0x04, 0x06, 0x18, 0x19, 0x09, 0xab, 0x67, 0xd9, 0xe8, 0x6a, 0xba, + 0x3d, 0x57, 0x57, 0x01, 0x6b, 0x10, 0x34, 0x13, 0x08, 0x1e, 0x1f, 0x0a, 0xb5, 0xe5, 0xfe, 0xcd, 0xfa, 0x35, 0xc5, 0x02, 0xf8, 0x00, 0x00, 0x01, 0x00, 0x55, + 0x00, 0x00, 0x00, 0xad, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x28, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0b, 0x00, 0x01, 0x01, 0x6c, 0x4d, 0x00, 0x00, 0x00, 0x6b, + 0x00, 0x4e, 0x1b, 0x40, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x59, 0xb4, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x33, 0x23, + 0x11, 0x33, 0xad, 0x58, 0x58, 0x02, 0xf8, 0x00, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x03, 0x56, 0x02, 0x22, 0x00, 0x21, 0x00, 0x5d, 0xb6, 0x1e, 0x18, 0x02, + 0x01, 0x02, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x04, 0x01, 0x02, 0x02, 0x00, 0x61, 0x07, 0x06, 0x08, 0x03, 0x00, 0x00, 0x73, 0x4d, 0x05, + 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x1a, 0x00, 0x06, 0x06, 0x6d, 0x4d, 0x04, 0x01, 0x02, 0x02, 0x00, 0x61, 0x07, 0x08, 0x02, 0x00, 0x00, + 0x73, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x17, 0x01, 0x00, 0x1d, 0x1b, 0x17, 0x16, 0x15, 0x14, 0x11, 0x0f, 0x0d, 0x0c, 0x09, + 0x07, 0x05, 0x04, 0x00, 0x21, 0x01, 0x21, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, + 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x33, 0x32, 0x17, 0x33, 0x36, 0x36, 0x02, 0xa1, 0x5b, 0x5a, 0x57, 0x6d, 0x4e, + 0x43, 0x57, 0x6e, 0x51, 0x3e, 0x58, 0x47, 0x0d, 0x05, 0x19, 0x55, 0x30, 0x7e, 0x26, 0x05, 0x1b, 0x5d, 0x02, 0x22, 0x5d, 0x68, 0xfe, 0xa3, 0x01, 0x59, 0x7f, + 0x5a, 0x56, 0xfe, 0xd8, 0x01, 0x59, 0x7f, 0x64, 0x5e, 0xfe, 0xea, 0x02, 0x18, 0x49, 0x2a, 0x29, 0x5a, 0x2e, 0x2c, 0x00, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, + 0x02, 0x19, 0x02, 0x22, 0x00, 0x13, 0x00, 0x50, 0xb5, 0x10, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x00, 0x02, 0x02, 0x00, + 0x61, 0x04, 0x05, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x02, 0x02, + 0x00, 0x61, 0x05, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x09, 0x07, + 0x05, 0x04, 0x00, 0x13, 0x01, 0x13, 0x06, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, + 0x17, 0x33, 0x36, 0x36, 0x01, 0x57, 0x60, 0x62, 0x57, 0x78, 0x59, 0x44, 0x58, 0x47, 0x0d, 0x05, 0x1a, 0x5c, 0x02, 0x22, 0x5d, 0x68, 0xfe, 0xa3, 0x01, 0x57, + 0x81, 0x64, 0x5e, 0xfe, 0xea, 0x02, 0x18, 0x49, 0x2a, 0x29, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x27, 0x02, 0x22, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x1f, + 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x25, 0x25, + 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x27, 0x87, 0x73, 0x47, 0x6f, 0x40, 0x86, 0x73, 0x49, 0x6f, 0x3f, 0xfe, 0x6b, 0x4b, 0x52, 0x51, 0x4c, 0x4c, 0x52, 0x52, + 0x4a, 0x01, 0x0d, 0x85, 0x92, 0x41, 0x7d, 0x59, 0x85, 0x90, 0x41, 0x7b, 0x59, 0x5f, 0x6f, 0x6f, 0x5f, 0x5f, 0x6c, 0x6c, 0x00, 0x02, 0x00, 0x55, 0xff, 0x10, + 0x02, 0x30, 0x02, 0x22, 0x00, 0x15, 0x00, 0x23, 0x00, 0x6b, 0xb6, 0x12, 0x09, 0x02, 0x05, 0x04, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x07, + 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, + 0x02, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, + 0x61, 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x23, 0x17, 0x23, 0x11, + 0x10, 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x16, 0x16, + 0x15, 0x15, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x17, 0x22, 0x06, 0x07, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x01, 0x54, 0x63, + 0x79, 0x79, 0x64, 0x3e, 0x51, 0x17, 0x06, 0x02, 0x04, 0x58, 0x48, 0x0c, 0x04, 0x18, 0x4e, 0x31, 0x52, 0x43, 0x02, 0x41, 0x58, 0x31, 0x3f, 0x1f, 0x47, 0x02, + 0x22, 0x8a, 0x8b, 0x89, 0x8e, 0x2f, 0x1f, 0x11, 0x34, 0x13, 0xdc, 0x03, 0x08, 0x49, 0x23, 0x30, 0x4a, 0x5c, 0x5e, 0x11, 0x63, 0x6b, 0x36, 0x5d, 0x3c, 0x5c, + 0x6e, 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0x10, 0x02, 0x12, 0x02, 0x22, 0x00, 0x15, 0x00, 0x22, 0x00, 0x61, 0xb6, 0x10, 0x03, 0x02, 0x04, 0x05, 0x01, 0x4c, + 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, + 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x17, 0x16, 0x1e, 0x1c, 0x16, + 0x22, 0x17, 0x22, 0x11, 0x14, 0x24, 0x26, 0x07, 0x0d, 0x1a, 0x2b, 0x05, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, + 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x23, 0x03, 0x32, 0x36, 0x37, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x01, 0xba, 0x02, 0x03, 0x06, 0x17, + 0x51, 0x40, 0x61, 0x79, 0x7b, 0x62, 0x3f, 0x50, 0x18, 0x04, 0x0d, 0x46, 0x58, 0x98, 0x53, 0x45, 0x01, 0x44, 0x57, 0x48, 0x46, 0x47, 0x0b, 0x12, 0x30, 0x11, + 0x22, 0x30, 0x8b, 0x8a, 0x8a, 0x8d, 0x30, 0x23, 0x49, 0xfc, 0xf8, 0x01, 0x2f, 0x5b, 0x5e, 0x12, 0x66, 0x69, 0x71, 0x5f, 0x5f, 0x6b, 0x00, 0x01, 0x00, 0x55, + 0x00, 0x00, 0x01, 0x8e, 0x02, 0x22, 0x00, 0x13, 0x00, 0x66, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0b, 0x03, 0x01, 0x01, 0x00, 0x10, 0x04, 0x02, 0x02, 0x01, + 0x02, 0x4c, 0x1b, 0x40, 0x0b, 0x03, 0x01, 0x03, 0x00, 0x10, 0x04, 0x02, 0x02, 0x01, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x03, 0x04, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0f, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x08, 0x06, + 0x00, 0x13, 0x01, 0x13, 0x05, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, + 0x36, 0x36, 0x01, 0x4f, 0x0f, 0x23, 0x0d, 0x0b, 0x0d, 0x1f, 0x0e, 0x29, 0x48, 0x2b, 0x58, 0x48, 0x0a, 0x04, 0x1a, 0x52, 0x02, 0x22, 0x03, 0x03, 0x51, 0x03, + 0x04, 0x2d, 0x51, 0x36, 0xfe, 0xe2, 0x02, 0x18, 0x62, 0x2c, 0x40, 0x00, 0x00, 0x01, 0x00, 0x33, 0xff, 0xf6, 0x01, 0xb2, 0x02, 0x22, 0x00, 0x29, 0x00, 0x2e, + 0x40, 0x2b, 0x1b, 0x01, 0x03, 0x02, 0x1c, 0x07, 0x02, 0x01, 0x03, 0x06, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, + 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, 0x2c, 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, 0x22, 0x26, + 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, + 0x06, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xb2, 0x74, 0x62, 0x38, 0x51, 0x1f, 0x20, 0x5b, 0x2f, 0x43, 0x3c, 0x16, 0x39, 0x35, 0x34, 0x4a, 0x28, + 0x6f, 0x5a, 0x31, 0x55, 0x25, 0x1e, 0x22, 0x4a, 0x27, 0x36, 0x39, 0x1a, 0x3d, 0x33, 0x33, 0x48, 0x26, 0x94, 0x4e, 0x50, 0x12, 0x10, 0x50, 0x10, 0x1b, 0x2b, + 0x24, 0x14, 0x20, 0x20, 0x14, 0x14, 0x28, 0x38, 0x2c, 0x44, 0x4a, 0x13, 0x11, 0x46, 0x0e, 0x14, 0x23, 0x1e, 0x16, 0x1f, 0x1d, 0x14, 0x13, 0x28, 0x39, 0x00, + 0x00, 0x01, 0x00, 0x10, 0xff, 0xf6, 0x01, 0x53, 0x02, 0x93, 0x00, 0x18, 0x00, 0x40, 0x40, 0x3d, 0x0e, 0x01, 0x02, 0x04, 0x03, 0x01, 0x00, 0x02, 0x04, 0x01, + 0x01, 0x00, 0x03, 0x4c, 0x00, 0x03, 0x04, 0x03, 0x85, 0x05, 0x01, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x06, 0x01, 0x00, 0x00, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x01, 0x00, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x18, 0x01, 0x18, 0x07, 0x0d, 0x16, 0x2b, + 0x25, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x11, 0x23, 0x35, 0x37, 0x37, 0x33, 0x15, 0x33, 0x15, 0x23, 0x11, 0x14, 0x16, 0x01, + 0x08, 0x14, 0x2a, 0x0d, 0x0e, 0x34, 0x18, 0x2a, 0x47, 0x2c, 0x4c, 0x4d, 0x23, 0x34, 0x9b, 0x9b, 0x2f, 0x3e, 0x07, 0x04, 0x43, 0x07, 0x09, 0x1d, 0x48, 0x41, + 0x01, 0x38, 0x2a, 0x23, 0x72, 0x7b, 0x44, 0xfe, 0xca, 0x31, 0x2f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0xff, 0xf6, 0x02, 0x15, 0x02, 0x18, 0x00, 0x13, 0x00, 0x4c, + 0xb5, 0x03, 0x01, 0x03, 0x02, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, + 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1b, 0x40, 0x17, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0x00, 0x03, 0x03, 0x01, + 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x13, 0x22, 0x13, 0x24, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x01, 0x11, + 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x33, 0x32, 0x36, 0x35, 0x11, 0x02, 0x15, 0x48, 0x0d, 0x04, 0x1a, 0x5c, 0x34, + 0x61, 0x62, 0x59, 0x77, 0x59, 0x45, 0x02, 0x18, 0xfd, 0xe8, 0x47, 0x2a, 0x27, 0x5d, 0x66, 0x01, 0x5f, 0xfe, 0xa7, 0x80, 0x64, 0x5e, 0x01, 0x17, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x02, 0x18, 0x00, 0x0f, 0x00, 0x21, 0x40, 0x1e, 0x07, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, + 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x1b, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x17, + 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x03, 0xcb, 0xcb, 0x5e, 0x72, 0x08, 0x12, 0x0e, 0x03, 0x04, 0x04, 0x0f, 0x13, 0x07, 0x72, 0x5e, 0xcc, 0x02, 0x18, 0xfe, + 0xc4, 0x16, 0x36, 0x31, 0x11, 0x11, 0x32, 0x36, 0x15, 0x01, 0x3c, 0xfd, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x01, 0x03, 0x07, 0x02, 0x19, 0x00, 0x22, + 0x00, 0x21, 0x40, 0x1e, 0x1a, 0x0f, 0x03, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x02, 0x02, 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, + 0x11, 0x19, 0x1a, 0x11, 0x18, 0x05, 0x0d, 0x1b, 0x2b, 0x01, 0x26, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x03, 0x23, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, + 0x3e, 0x02, 0x37, 0x13, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0x23, 0x01, 0xaf, 0x0d, 0x13, 0x05, 0x04, 0x04, 0x12, 0x0e, + 0x60, 0x64, 0x93, 0x5b, 0x4a, 0x0b, 0x14, 0x04, 0x04, 0x04, 0x0b, 0x0e, 0x07, 0x5f, 0x60, 0x5c, 0x0b, 0x15, 0x04, 0x04, 0x03, 0x15, 0x0c, 0x4b, 0x5a, 0x95, + 0x67, 0x01, 0x2f, 0x29, 0x4f, 0x16, 0x16, 0x4f, 0x2a, 0xfe, 0xd3, 0x02, 0x18, 0xfe, 0xe2, 0x2b, 0x58, 0x1d, 0x11, 0x32, 0x37, 0x16, 0x01, 0x2e, 0xfe, 0xd2, + 0x22, 0x50, 0x1d, 0x19, 0x58, 0x2e, 0x01, 0x1e, 0xfd, 0xe8, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x01, 0xff, 0x02, 0x18, 0x00, 0x0b, 0x00, 0x1f, 0x40, 0x1c, + 0x09, 0x06, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x12, 0x12, 0x12, 0x11, 0x04, + 0x0d, 0x1a, 0x2b, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x23, 0xd4, 0xb9, 0x64, 0x8a, 0x89, 0x63, 0xb9, 0xc3, 0x64, 0x92, 0x94, + 0x63, 0x01, 0x12, 0x01, 0x06, 0xca, 0xca, 0xfe, 0xfa, 0xfe, 0xee, 0xd6, 0xd6, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0x10, 0x01, 0xfe, 0x02, 0x18, 0x00, 0x1a, + 0x00, 0x27, 0x40, 0x24, 0x1a, 0x13, 0x05, 0x03, 0x03, 0x00, 0x12, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, + 0x61, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x25, 0x23, 0x19, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, + 0x33, 0x03, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x01, 0x5e, 0x74, 0x0f, 0x18, 0x06, 0x04, 0x06, 0x1a, 0x0e, + 0x6d, 0x5f, 0xe7, 0x1c, 0x59, 0x4e, 0x18, 0x24, 0x0d, 0x0b, 0x1f, 0x11, 0x2e, 0x39, 0x10, 0x1c, 0x02, 0x18, 0xfe, 0xcf, 0x28, 0x49, 0x21, 0x19, 0x51, 0x29, + 0x01, 0x30, 0xfd, 0x9e, 0x4c, 0x5a, 0x05, 0x03, 0x46, 0x02, 0x04, 0x34, 0x2b, 0x47, 0x00, 0x01, 0x00, 0x27, 0x00, 0x00, 0x01, 0xaf, 0x02, 0x18, 0x00, 0x09, + 0x00, 0x29, 0x40, 0x26, 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x03, + 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, + 0x21, 0x01, 0xaf, 0xfe, 0x78, 0x01, 0x20, 0xfe, 0xf1, 0x01, 0x70, 0xfe, 0xe4, 0x01, 0x23, 0x3a, 0x01, 0x9a, 0x44, 0x42, 0xfe, 0x6e, 0x00, 0x01, 0x00, 0x1c, + 0xff, 0x62, 0x01, 0x5c, 0x02, 0xca, 0x00, 0x1d, 0x00, 0x2c, 0x40, 0x29, 0x16, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, + 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, 0x4e, 0x1b, 0x11, 0x15, 0x11, 0x15, 0x10, 0x06, 0x0d, + 0x1c, 0x2b, 0x05, 0x26, 0x26, 0x35, 0x35, 0x34, 0x26, 0x23, 0x35, 0x36, 0x36, 0x35, 0x35, 0x34, 0x36, 0x33, 0x15, 0x06, 0x06, 0x15, 0x15, 0x14, 0x07, 0x15, + 0x16, 0x15, 0x15, 0x14, 0x16, 0x17, 0x01, 0x5c, 0x5c, 0x6a, 0x3f, 0x3b, 0x3b, 0x3f, 0x6e, 0x58, 0x34, 0x3b, 0x6d, 0x6d, 0x3a, 0x35, 0x9e, 0x01, 0x4e, 0x50, + 0x93, 0x33, 0x2b, 0x49, 0x01, 0x2a, 0x32, 0x94, 0x50, 0x4e, 0x48, 0x01, 0x2c, 0x31, 0x90, 0x67, 0x13, 0x06, 0x13, 0x67, 0x93, 0x31, 0x2b, 0x01, 0x00, 0x01, + 0x00, 0xef, 0xff, 0x0f, 0x01, 0x38, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x28, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x01, + 0x01, 0x6f, 0x01, 0x4e, 0x1b, 0x40, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x85, 0x00, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x59, 0xb4, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, + 0x13, 0x33, 0x11, 0x23, 0xef, 0x49, 0x49, 0x02, 0xf8, 0xfc, 0x17, 0x00, 0x00, 0x01, 0x00, 0x20, 0xff, 0x62, 0x01, 0x60, 0x02, 0xca, 0x00, 0x1d, 0x00, 0x2c, + 0x40, 0x29, 0x06, 0x01, 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, 0x00, 0x01, 0x01, + 0x02, 0x61, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x15, 0x11, 0x15, 0x11, 0x1b, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x17, 0x36, 0x36, 0x35, 0x35, 0x34, 0x37, 0x35, + 0x26, 0x35, 0x35, 0x34, 0x26, 0x27, 0x35, 0x16, 0x16, 0x15, 0x15, 0x14, 0x16, 0x33, 0x15, 0x06, 0x06, 0x15, 0x15, 0x14, 0x06, 0x23, 0x20, 0x34, 0x3b, 0x6d, + 0x6d, 0x3a, 0x35, 0x5c, 0x6a, 0x3f, 0x3b, 0x3b, 0x3f, 0x6e, 0x58, 0x56, 0x02, 0x2b, 0x31, 0x91, 0x67, 0x13, 0x06, 0x13, 0x67, 0x92, 0x31, 0x2b, 0x01, 0x48, + 0x01, 0x4e, 0x50, 0x92, 0x33, 0x2b, 0x49, 0x01, 0x2a, 0x32, 0x95, 0x4f, 0x4f, 0x00, 0x00, 0x01, 0x00, 0x32, 0x01, 0x1f, 0x02, 0x09, 0x01, 0xa2, 0x00, 0x17, + 0x00, 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, 0x02, 0x01, 0x13, 0x01, 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, + 0x00, 0x02, 0x00, 0x03, 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, 0x03, 0x51, 0x24, 0x24, + 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, 0x33, + 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x01, 0x0d, 0x24, 0x2f, 0x16, 0x1c, 0x3e, 0x18, 0x30, 0x48, 0x1d, 0x39, 0x2e, 0x24, 0x2f, 0x15, 0x1d, 0x3e, + 0x18, 0x31, 0x47, 0x1c, 0x3b, 0x01, 0x3f, 0x10, 0x0b, 0x22, 0x19, 0x4e, 0x35, 0x0c, 0x14, 0x10, 0x0b, 0x22, 0x19, 0x4d, 0x36, 0x0d, 0x00, 0x01, 0x00, 0x18, + 0x01, 0xa0, 0x01, 0x33, 0x03, 0x55, 0x00, 0x19, 0x00, 0x30, 0x40, 0x2d, 0x0e, 0x01, 0x01, 0x02, 0x0d, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, 0x03, 0x4c, + 0x00, 0x02, 0x00, 0x01, 0x03, 0x02, 0x01, 0x69, 0x00, 0x03, 0x00, 0x00, 0x03, 0x57, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x00, 0x4f, 0x16, 0x25, + 0x28, 0x10, 0x04, 0x0c, 0x1a, 0x2b, 0x01, 0x21, 0x35, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x07, 0x07, 0x33, 0x01, 0x32, 0xfe, 0xe6, 0x73, 0x29, 0x29, 0x0f, 0x25, 0x1e, 0x1e, 0x31, 0x1a, 0x23, 0x1d, 0x45, 0x2b, 0x40, 0x49, 0x3b, 0x38, + 0x51, 0xc3, 0x01, 0xa0, 0x36, 0x70, 0x27, 0x31, 0x27, 0x16, 0x20, 0x20, 0x17, 0x14, 0x2e, 0x19, 0x1e, 0x3f, 0x37, 0x31, 0x4e, 0x35, 0x4d, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x01, 0x98, 0x01, 0x41, 0x03, 0x55, 0x00, 0x28, 0x00, 0x4d, 0x40, 0x4a, 0x26, 0x01, 0x05, 0x00, 0x25, 0x01, 0x04, 0x05, 0x06, 0x01, 0x03, 0x04, + 0x11, 0x01, 0x02, 0x03, 0x10, 0x01, 0x01, 0x02, 0x05, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x69, 0x00, 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, + 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x01, 0x00, 0x23, 0x21, 0x1d, 0x1b, 0x1a, 0x18, 0x14, + 0x12, 0x0e, 0x0c, 0x00, 0x28, 0x01, 0x28, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, + 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, + 0xa5, 0x47, 0x48, 0x2b, 0x1e, 0x27, 0x2f, 0x54, 0x59, 0x25, 0x40, 0x1e, 0x46, 0x3e, 0x34, 0x30, 0x3a, 0x34, 0x39, 0x39, 0x32, 0x2f, 0x29, 0x1d, 0x1f, 0x35, + 0x1b, 0x24, 0x1f, 0x45, 0x03, 0x55, 0x3e, 0x30, 0x28, 0x34, 0x0a, 0x03, 0x07, 0x33, 0x29, 0x3a, 0x49, 0x0d, 0x0f, 0x3f, 0x22, 0x29, 0x23, 0x24, 0x21, 0x37, + 0x27, 0x1f, 0x20, 0x1d, 0x15, 0x11, 0x2e, 0x17, 0x1a, 0x00, 0x00, 0x01, 0x00, 0x25, 0x01, 0xa0, 0x00, 0xf0, 0x03, 0x4c, 0x00, 0x0c, 0x00, 0x27, 0x40, 0x24, + 0x0b, 0x0a, 0x06, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x00, 0x00, 0x01, 0x57, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x11, 0x03, 0x0c, 0x17, 0x2b, 0x13, 0x11, 0x23, 0x11, 0x34, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0xf0, 0x47, + 0x03, 0x01, 0x0a, 0x18, 0x0d, 0x36, 0x23, 0x82, 0x03, 0x4c, 0xfe, 0x54, 0x01, 0x14, 0x1a, 0x2a, 0x15, 0x09, 0x15, 0x09, 0x27, 0x31, 0x5c, 0x00, 0x00, 0x01, + 0xff, 0x41, 0x00, 0x00, 0x01, 0x40, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x01, 0x01, 0x23, 0x01, 0x01, 0x40, 0xfe, 0x4c, 0x4b, 0x01, 0xb4, 0x02, 0xca, 0xfd, 0x36, + 0x02, 0xca, 0x00, 0x02, 0x00, 0x0a, 0x01, 0xa0, 0x01, 0x55, 0x03, 0x4f, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x30, 0x40, 0x2d, 0x0e, 0x01, 0x04, 0x03, 0x06, 0x01, + 0x00, 0x04, 0x02, 0x4c, 0x00, 0x03, 0x04, 0x01, 0x03, 0x57, 0x05, 0x01, 0x04, 0x02, 0x01, 0x00, 0x01, 0x04, 0x00, 0x67, 0x00, 0x03, 0x03, 0x01, 0x5f, 0x00, + 0x01, 0x03, 0x01, 0x4f, 0x18, 0x11, 0x12, 0x11, 0x11, 0x10, 0x06, 0x0c, 0x1c, 0x2b, 0x01, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x13, 0x33, 0x11, 0x33, 0x27, + 0x34, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x33, 0x01, 0x55, 0x3d, 0x4b, 0xc3, 0xc5, 0x49, 0x3d, 0x88, 0x02, 0x01, 0x05, 0x20, 0x0b, 0x50, 0x7d, 0x02, 0x00, + 0x60, 0x60, 0x34, 0x01, 0x1b, 0xfe, 0xed, 0x5d, 0x15, 0x38, 0x18, 0x0b, 0x31, 0x11, 0x75, 0x00, 0x00, 0x01, 0x00, 0x1e, 0x01, 0x97, 0x01, 0x40, 0x03, 0x4c, + 0x00, 0x1e, 0x00, 0x42, 0x40, 0x3f, 0x1d, 0x03, 0x02, 0x04, 0x01, 0x1c, 0x10, 0x02, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x03, 0x4c, 0x06, 0x01, 0x05, 0x00, + 0x00, 0x01, 0x05, 0x00, 0x67, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x69, 0x00, 0x03, 0x02, 0x02, 0x03, 0x59, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, + 0x03, 0x02, 0x51, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1e, 0x24, 0x25, 0x24, 0x23, 0x11, 0x07, 0x0c, 0x1b, 0x2b, 0x01, 0x15, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x37, 0x01, 0x2b, 0xb9, + 0x09, 0x0c, 0x1d, 0x11, 0x43, 0x5a, 0x54, 0x52, 0x20, 0x46, 0x16, 0x1b, 0x45, 0x1a, 0x2d, 0x35, 0x35, 0x30, 0x1a, 0x25, 0x0f, 0x1f, 0x10, 0x03, 0x4c, 0x37, + 0x6d, 0x02, 0x04, 0x44, 0x40, 0x46, 0x4d, 0x0d, 0x0d, 0x43, 0x10, 0x13, 0x28, 0x2b, 0x26, 0x2a, 0x08, 0x04, 0x14, 0xd0, 0x00, 0x01, 0x00, 0x1c, 0x01, 0xa0, + 0x01, 0x43, 0x03, 0x4c, 0x00, 0x06, 0x00, 0x2a, 0x40, 0x27, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, + 0x23, 0x35, 0x21, 0x15, 0x03, 0x4f, 0xaa, 0xdd, 0x01, 0x27, 0xaa, 0x01, 0xa0, 0x01, 0x70, 0x3c, 0x31, 0xfe, 0x85, 0x00, 0x00, 0x03, 0x00, 0x19, 0x01, 0x98, + 0x01, 0x45, 0x03, 0x54, 0x00, 0x18, 0x00, 0x24, 0x00, 0x31, 0x00, 0x38, 0x40, 0x35, 0x1f, 0x12, 0x06, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x04, 0x01, 0x00, 0x05, + 0x01, 0x02, 0x03, 0x00, 0x02, 0x69, 0x00, 0x03, 0x01, 0x01, 0x03, 0x59, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x03, 0x01, 0x51, 0x1a, 0x19, 0x01, 0x00, + 0x2c, 0x2a, 0x19, 0x24, 0x1a, 0x24, 0x0d, 0x0b, 0x00, 0x18, 0x01, 0x18, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, + 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, + 0x26, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0xb0, 0x37, 0x50, 0x2a, 0x1e, 0x27, 0x2f, 0x53, 0x42, 0x49, 0x4e, 0x2d, + 0x20, 0x1f, 0x21, 0x26, 0x3f, 0x24, 0x20, 0x24, 0x28, 0x1e, 0x1d, 0x25, 0x24, 0x2f, 0x21, 0x22, 0x28, 0x29, 0x2a, 0x28, 0x2d, 0x26, 0x03, 0x54, 0x35, 0x37, + 0x25, 0x30, 0x10, 0x10, 0x37, 0x29, 0x38, 0x43, 0x40, 0x38, 0x29, 0x36, 0x11, 0x14, 0x2b, 0x26, 0x24, 0x31, 0x1a, 0x37, 0x1d, 0x1a, 0x1a, 0x22, 0x0c, 0x0b, + 0x21, 0x1c, 0x1a, 0x1d, 0xb8, 0x10, 0x28, 0x1d, 0x1c, 0x24, 0x24, 0x1c, 0x1d, 0x26, 0x0d, 0x00, 0x00, 0x02, 0x00, 0x13, 0x01, 0x98, 0x01, 0x4a, 0x03, 0x54, + 0x00, 0x0b, 0x00, 0x15, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, + 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x0d, 0x0c, 0x01, 0x00, 0x11, 0x0f, 0x0c, 0x15, 0x0d, 0x15, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, + 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x27, 0x32, 0x35, 0x34, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0xae, + 0x4d, 0x4e, 0x4a, 0x51, 0x4d, 0x4f, 0x49, 0x53, 0x54, 0x54, 0x2b, 0x27, 0x27, 0x01, 0x98, 0x73, 0x6c, 0x6a, 0x73, 0x72, 0x6b, 0x6a, 0x75, 0x3f, 0xa0, 0x9f, + 0x4f, 0x51, 0x4f, 0x50, 0x00, 0x02, 0x00, 0x14, 0x01, 0x98, 0x01, 0x4c, 0x03, 0x54, 0x00, 0x1c, 0x00, 0x29, 0x00, 0x4a, 0x40, 0x47, 0x03, 0x01, 0x01, 0x00, + 0x04, 0x01, 0x02, 0x01, 0x0b, 0x01, 0x04, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 0x69, 0x00, 0x02, 0x07, 0x01, 0x04, 0x05, 0x02, + 0x04, 0x69, 0x00, 0x05, 0x03, 0x03, 0x05, 0x59, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x05, 0x03, 0x51, 0x1e, 0x1d, 0x01, 0x00, 0x25, 0x23, 0x1d, 0x29, + 0x1e, 0x29, 0x16, 0x14, 0x10, 0x0e, 0x08, 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x17, 0x15, 0x26, 0x26, 0x23, 0x22, 0x06, + 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, + 0x32, 0x36, 0x35, 0x34, 0x26, 0xec, 0x0e, 0x23, 0x0b, 0x0b, 0x22, 0x13, 0x36, 0x3e, 0x1b, 0x03, 0x04, 0x0e, 0x36, 0x29, 0x3b, 0x4a, 0x52, 0x45, 0x44, 0x5d, + 0x12, 0x2f, 0x54, 0x0d, 0x2b, 0x32, 0x14, 0x28, 0x1e, 0x26, 0x2f, 0x29, 0x03, 0x54, 0x04, 0x03, 0x3b, 0x04, 0x05, 0x29, 0x46, 0x2a, 0x15, 0x1d, 0x46, 0x40, + 0x46, 0x50, 0x5f, 0x61, 0x2f, 0x5a, 0x48, 0x2b, 0xd7, 0x2d, 0x1a, 0x18, 0x2f, 0x1e, 0x2d, 0x2e, 0x26, 0x2b, 0x00, 0x02, 0x00, 0x11, 0x01, 0x98, 0x01, 0x49, + 0x03, 0x56, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x4a, 0x40, 0x47, 0x12, 0x01, 0x03, 0x05, 0x0b, 0x01, 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, + 0x00, 0x07, 0x01, 0x04, 0x05, 0x00, 0x04, 0x69, 0x00, 0x05, 0x00, 0x03, 0x02, 0x05, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, + 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, 0x27, 0x1d, 0x27, 0x17, 0x15, 0x0f, 0x0d, 0x09, 0x07, 0x00, 0x1b, 0x01, 0x1b, + 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xa8, 0x44, 0x5d, 0x12, 0x2d, 0x54, 0x42, 0x25, 0x1a, + 0x0b, 0x20, 0x18, 0x37, 0x3c, 0x1b, 0x02, 0x05, 0x0d, 0x33, 0x28, 0x40, 0x4a, 0x52, 0x45, 0x24, 0x2f, 0x27, 0x2a, 0x2b, 0x33, 0x2d, 0x03, 0x56, 0x5c, 0x63, + 0x2f, 0x5b, 0x49, 0x2c, 0x07, 0x3c, 0x04, 0x06, 0x2c, 0x47, 0x28, 0x13, 0x1f, 0x48, 0x40, 0x41, 0x53, 0x39, 0x2c, 0x2c, 0x26, 0x2e, 0x2d, 0x1a, 0x2a, 0x3b, + 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x02, 0xdb, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x47, 0x01, 0x58, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x0f, 0x00, 0x00, 0x02, 0x0d, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, + 0x00, 0x00, 0x02, 0x05, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, + 0x03, 0x65, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x58, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x02, 0xb0, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x5d, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x58, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x4d, 0x02, 0xb0, 0x00, 0x00, 0xff, 0xff, 0x00, 0x13, 0xff, 0xf8, 0x01, 0x4a, 0x01, 0xb4, 0x03, 0x07, 0x00, 0x68, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, + 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x25, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xac, 0x03, 0x07, 0x00, 0x62, 0x00, 0x00, + 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x18, 0x00, 0x00, 0x01, 0x33, 0x01, 0xb5, 0x03, 0x07, + 0x00, 0x60, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0xff, 0xf8, 0x01, 0x41, + 0x01, 0xb5, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0a, + 0x00, 0x00, 0x01, 0x55, 0x01, 0xaf, 0x03, 0x07, 0x00, 0x64, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0x00, 0x1e, 0xff, 0xf7, 0x01, 0x40, 0x01, 0xac, 0x03, 0x07, 0x00, 0x65, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x14, 0xff, 0xf8, 0x01, 0x4c, 0x01, 0xb4, 0x03, 0x07, 0x00, 0x69, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, + 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x43, 0x01, 0xac, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xfe, 0x60, + 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x19, 0xff, 0xf8, 0x01, 0x45, 0x01, 0xb4, 0x03, 0x07, 0x00, 0x67, + 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0xff, 0xf8, 0x01, 0x49, 0x01, 0xb6, + 0x03, 0x07, 0x00, 0x6a, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x13, 0x01, 0x16, + 0x01, 0x4a, 0x02, 0xd2, 0x03, 0x07, 0x00, 0x68, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x25, 0x01, 0x1e, 0x00, 0xf0, 0x02, 0xca, 0x03, 0x07, 0x00, 0x62, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0x00, 0x18, 0x01, 0x1e, 0x01, 0x33, 0x02, 0xd3, 0x03, 0x07, 0x00, 0x60, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, + 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0x01, 0x16, 0x01, 0x41, 0x02, 0xd3, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, + 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x01, 0x1e, 0x01, 0x55, 0x02, 0xcd, 0x03, 0x07, 0x00, 0x64, 0x00, 0x00, + 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x01, 0x15, 0x01, 0x40, 0x02, 0xca, 0x03, 0x07, + 0x00, 0x65, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x14, 0x01, 0x16, 0x01, 0x4c, + 0x02, 0xd2, 0x03, 0x07, 0x00, 0x69, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1c, + 0x01, 0x1e, 0x01, 0x43, 0x02, 0xca, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0x00, 0x19, 0x01, 0x16, 0x01, 0x45, 0x02, 0xd2, 0x03, 0x07, 0x00, 0x67, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xff, 0x7e, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0x01, 0x16, 0x01, 0x49, 0x02, 0xd4, 0x03, 0x07, 0x00, 0x6a, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, + 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, 0x01, 0x04, 0x00, 0x18, 0x00, 0x66, 0x00, 0x06, 0x00, 0x02, + 0x00, 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x89, 0x0e, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x54, + 0x00, 0xa8, 0x01, 0x27, 0x01, 0xbc, 0x02, 0x4b, 0x02, 0x66, 0x02, 0x8a, 0x02, 0xae, 0x02, 0xe6, 0x03, 0x0e, 0x03, 0x2e, 0x03, 0x49, 0x03, 0x68, 0x03, 0x84, + 0x03, 0xbd, 0x03, 0xe4, 0x04, 0x25, 0x04, 0x83, 0x04, 0xbe, 0x05, 0x11, 0x05, 0x71, 0x05, 0x96, 0x06, 0x02, 0x06, 0x63, 0x06, 0x98, 0x06, 0xcb, 0x06, 0xe1, + 0x07, 0x0c, 0x07, 0x22, 0x07, 0x7b, 0x08, 0x25, 0x08, 0x5f, 0x08, 0xb6, 0x08, 0xfc, 0x09, 0x2b, 0x09, 0x57, 0x09, 0x7c, 0x09, 0xcc, 0x09, 0xf4, 0x0a, 0x1c, + 0x0a, 0x4d, 0x0a, 0x7a, 0x0a, 0x98, 0x0a, 0xd1, 0x0b, 0x01, 0x0b, 0x3d, 0x0b, 0x79, 0x0b, 0xc2, 0x0c, 0x08, 0x0c, 0x5d, 0x0c, 0x7b, 0x0c, 0xa8, 0x0c, 0xd5, + 0x0d, 0x22, 0x0d, 0x4d, 0x0d, 0x71, 0x0d, 0x9c, 0x0d, 0xbb, 0x0d, 0xd7, 0x0d, 0xf6, 0x0e, 0x1d, 0x0e, 0x3a, 0x0e, 0x64, 0x0e, 0xdd, 0x0f, 0x55, 0x0f, 0x9b, + 0x10, 0x19, 0x10, 0x6d, 0x10, 0xc1, 0x11, 0x40, 0x11, 0x87, 0x11, 0xea, 0x12, 0x69, 0x12, 0xaf, 0x12, 0xcf, 0x13, 0x30, 0x13, 0x79, 0x13, 0xb2, 0x14, 0x1e, + 0x14, 0x83, 0x14, 0xd9, 0x15, 0x2e, 0x15, 0x75, 0x15, 0xbc, 0x15, 0xeb, 0x16, 0x37, 0x16, 0x60, 0x16, 0xa1, 0x16, 0xcc, 0x17, 0x0e, 0x17, 0x2f, 0x17, 0x71, + 0x17, 0xb6, 0x17, 0xf8, 0x18, 0x59, 0x18, 0x87, 0x18, 0xa3, 0x18, 0xde, 0x19, 0x2e, 0x19, 0x55, 0x19, 0xbb, 0x19, 0xf6, 0x1a, 0x58, 0x1a, 0xb7, 0x1a, 0xc3, + 0x1a, 0xcf, 0x1a, 0xdb, 0x1a, 0xeb, 0x1a, 0xfb, 0x1b, 0x0a, 0x1b, 0x19, 0x1b, 0x28, 0x1b, 0x37, 0x1b, 0x46, 0x1b, 0x55, 0x1b, 0x64, 0x1b, 0x73, 0x1b, 0x82, + 0x1b, 0x91, 0x1b, 0xa0, 0x1b, 0xaf, 0x1b, 0xbe, 0x1b, 0xcd, 0x1b, 0xdc, 0x1b, 0xeb, 0x1b, 0xfa, 0x1c, 0x09, 0x1c, 0x18, 0x1c, 0x27, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, 0xb1, 0xf9, 0xad, 0x18, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xd3, 0xe7, + 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc0, 0xb7, 0xfd, 0x93, 0xfe, 0x7b, 0x0a, 0xf0, 0x04, 0x2b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x58, 0x00, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x48, 0x01, 0x98, 0x00, 0x41, 0x02, 0x86, 0x00, 0x19, 0x02, 0x3c, 0x00, 0x3e, + 0x03, 0x3f, 0x00, 0x31, 0x02, 0xdc, 0x00, 0x35, 0x00, 0xe1, 0x00, 0x41, 0x01, 0x2c, 0x00, 0x28, 0x01, 0x2c, 0x00, 0x1e, 0x02, 0x27, 0x00, 0x29, 0x02, 0x3c, + 0x00, 0x32, 0x01, 0x0c, 0x00, 0x29, 0x01, 0x42, 0x00, 0x28, 0x01, 0x0c, 0x00, 0x48, 0x01, 0x74, 0x00, 0x0a, 0x02, 0x3c, 0x00, 0x31, 0x02, 0x3c, 0x00, 0x59, + 0x02, 0x3c, 0x00, 0x30, 0x02, 0x3c, 0x00, 0x2d, 0x02, 0x3c, 0x00, 0x15, 0x02, 0x3c, 0x00, 0x3f, 0x02, 0x3c, 0x00, 0x37, 0x02, 0x3c, 0x00, 0x2c, 0x02, 0x3c, + 0x00, 0x31, 0x02, 0x3c, 0x00, 0x32, 0x01, 0x0c, 0x00, 0x48, 0x01, 0x0c, 0x00, 0x1f, 0x02, 0x3c, 0x00, 0x32, 0x02, 0x3c, 0x00, 0x38, 0x02, 0x3c, 0x00, 0x32, + 0x01, 0xb2, 0x00, 0x0c, 0x03, 0x83, 0x00, 0x3a, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x8a, 0x00, 0x61, 0x02, 0x78, 0x00, 0x3d, 0x02, 0xda, 0x00, 0x61, 0x02, 0x2c, + 0x00, 0x61, 0x02, 0x07, 0x00, 0x61, 0x02, 0xd8, 0x00, 0x3d, 0x02, 0xe5, 0x00, 0x61, 0x01, 0x53, 0x00, 0x28, 0x01, 0x11, 0xff, 0xb2, 0x02, 0x6b, 0x00, 0x61, + 0x02, 0x0c, 0x00, 0x61, 0x03, 0x8b, 0x00, 0x61, 0x02, 0xf8, 0x00, 0x61, 0x03, 0x0d, 0x00, 0x3d, 0x02, 0x5d, 0x00, 0x61, 0x03, 0x0d, 0x00, 0x3d, 0x02, 0x6e, + 0x00, 0x61, 0x02, 0x25, 0x00, 0x33, 0x02, 0x2c, 0x00, 0x0a, 0x02, 0xdb, 0x00, 0x5a, 0x02, 0x58, 0x00, 0x00, 0x03, 0xa2, 0x00, 0x0c, 0x02, 0x4a, 0x00, 0x04, + 0x02, 0x36, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x26, 0x01, 0x49, 0x00, 0x50, 0x01, 0x74, 0x00, 0x0a, 0x01, 0x49, 0x00, 0x19, 0x02, 0x3c, 0x00, 0x26, 0x01, 0xbc, + 0xff, 0xfe, 0x01, 0x19, 0x00, 0x28, 0x02, 0x31, 0x00, 0x2e, 0x02, 0x67, 0x00, 0x55, 0x01, 0xe0, 0x00, 0x37, 0x02, 0x67, 0x00, 0x37, 0x02, 0x34, 0x00, 0x37, + 0x01, 0x58, 0x00, 0x0f, 0x02, 0x67, 0x00, 0x37, 0x02, 0x6a, 0x00, 0x55, 0x01, 0x02, 0x00, 0x4e, 0x01, 0x02, 0xff, 0xc9, 0x02, 0x16, 0x00, 0x55, 0x01, 0x02, + 0x00, 0x55, 0x03, 0xa7, 0x00, 0x55, 0x02, 0x6a, 0x00, 0x55, 0x02, 0x5d, 0x00, 0x37, 0x02, 0x67, 0x00, 0x55, 0x02, 0x67, 0x00, 0x37, 0x01, 0x9d, 0x00, 0x55, + 0x01, 0xdf, 0x00, 0x33, 0x01, 0x69, 0x00, 0x10, 0x02, 0x6a, 0x00, 0x4f, 0x01, 0xfc, 0x00, 0x00, 0x03, 0x12, 0x00, 0x0b, 0x02, 0x11, 0x00, 0x12, 0x01, 0xfe, + 0x00, 0x01, 0x01, 0xd6, 0x00, 0x27, 0x01, 0x7c, 0x00, 0x1c, 0x02, 0x27, 0x00, 0xef, 0x01, 0x7c, 0x00, 0x20, 0x02, 0x3c, 0x00, 0x32, 0x01, 0x5e, 0x00, 0x18, + 0x01, 0x5e, 0x00, 0x11, 0x01, 0x5e, 0x00, 0x25, 0x00, 0x82, 0xff, 0x41, 0x01, 0x5e, 0x00, 0x0a, 0x01, 0x5e, 0x00, 0x1e, 0x01, 0x5e, 0x00, 0x1c, 0x01, 0x5e, + 0x00, 0x19, 0x01, 0x5e, 0x00, 0x13, 0x01, 0x5e, 0x00, 0x14, 0x01, 0x5e, 0x00, 0x11, 0x02, 0xb0, 0x00, 0x0f, 0x02, 0x5a, 0x00, 0x0f, 0x02, 0x5a, 0x00, 0x0f, + 0x03, 0xb2, 0x00, 0x0f, 0x03, 0xb2, 0x00, 0x0f, 0x01, 0x5e, 0x00, 0x13, 0x00, 0x25, 0x00, 0x18, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x1c, + 0x00, 0x19, 0x00, 0x11, 0x00, 0x13, 0x00, 0x25, 0x00, 0x18, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x19, 0x00, 0x11, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x0b, 0x18, 0xfd, 0x93, 0xfd, 0x94, 0x0a, 0xf0, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x04, 0x02, 0x41, 0x01, 0x90, 0x00, 0x05, 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x00, + 0x00, 0x4b, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x32, 0x01, 0x42, 0x00, 0x00, 0x02, 0x0b, 0x05, 0x02, 0x04, 0x05, 0x04, 0x02, 0x02, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0xc0, 0x00, 0x20, 0x00, 0x7e, + 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x02, 0xca, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, + 0x34, 0x1b, 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, + 0x21, 0xb0, 0x00, 0x59, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, + 0x02, 0x2c, 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, + 0xb1, 0x02, 0x14, 0x43, 0x42, 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, 0x04, + 0x50, 0x78, 0xb2, 0x02, 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, 0x20, 0xb0, + 0x02, 0x43, 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, + 0xb0, 0x04, 0x2c, 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x1b, + 0x20, 0x64, 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, 0x21, 0xb0, 0x03, 0x25, + 0x59, 0x52, 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, + 0xb0, 0x38, 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, + 0x20, 0xb0, 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, + 0x60, 0x1b, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, + 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, 0xb0, + 0x1e, 0x50, 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, + 0x01, 0x2b, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, 0x20, 0x45, + 0x20, 0xb0, 0x04, 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, 0x59, 0xb0, 0x01, + 0x60, 0x2d, 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, + 0x58, 0x1b, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, 0xb0, 0x08, 0x43, 0x20, + 0x8a, 0x20, 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, + 0x20, 0xb0, 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, + 0x43, 0x2b, 0xb2, 0x00, 0x02, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, + 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, 0x0e, + 0x00, 0x43, 0x45, 0x42, 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, + 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, + 0x61, 0x20, 0x64, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, 0x23, 0xb0, 0x00, + 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, + 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, + 0x00, 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, + 0x0c, 0x00, 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, + 0xb0, 0x10, 0x2c, 0xb0, 0x01, 0x60, 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, + 0xb0, 0x00, 0x52, 0x58, 0x20, 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, 0x00, + 0x63, 0x8a, 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, + 0x64, 0x44, 0x59, 0x24, 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x1b, 0x21, + 0x59, 0x24, 0xb0, 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, 0x61, 0x42, 0xb0, + 0x11, 0x2b, 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, + 0x03, 0x25, 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x23, 0xb0, 0x01, + 0x61, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, + 0x21, 0x59, 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, + 0x63, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, + 0x00, 0x13, 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, + 0x54, 0x58, 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, 0x00, + 0x11, 0x00, 0x13, 0x00, 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, + 0x59, 0x2d, 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, + 0xb0, 0x19, 0x2c, 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, 0x2d, 0xb0, 0x1c, + 0x2c, 0xb1, 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, + 0x09, 0x15, 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, + 0x01, 0x5d, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, + 0x20, 0x2e, 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, + 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, + 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, 0x01, + 0x00, 0x11, 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, + 0xb0, 0x22, 0x2c, 0xb1, 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, 0xb0, 0x25, + 0x2c, 0xb1, 0x04, 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, 0x28, 0x2c, 0xb1, + 0x07, 0x20, 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, + 0x01, 0x60, 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x01, 0x60, 0xb0, + 0x2e, 0x2a, 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, + 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, + 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, + 0x23, 0x61, 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, + 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, + 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x34, + 0x2c, 0x20, 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, + 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3e, 0x23, 0x38, 0xb1, + 0x34, 0x01, 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, + 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, + 0x60, 0xb0, 0x00, 0x43, 0x61, 0xb0, 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, + 0x42, 0xb0, 0x02, 0x25, 0x49, 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, 0x01, + 0x15, 0x14, 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, + 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, + 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, + 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, + 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, + 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, + 0x02, 0x25, 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, + 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, 0x25, + 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, 0x60, 0x64, + 0x23, 0xb0, 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, + 0x3c, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x3c, 0x38, 0x2d, + 0xb0, 0x3d, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, + 0x38, 0x2d, 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, + 0x58, 0x2e, 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, + 0x23, 0x47, 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, + 0x1b, 0x21, 0x59, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, + 0x20, 0x3c, 0x8a, 0x38, 0x23, 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, 0x23, + 0x47, 0x23, 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, + 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, + 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, + 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, + 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, + 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, + 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, + 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, + 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, + 0xb0, 0x04, 0x26, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, 0x20, + 0x3c, 0x20, 0x2e, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, + 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, + 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, 0xb0, 0x06, 0x43, + 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, + 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, + 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, + 0x23, 0x38, 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, + 0xb1, 0x00, 0x3a, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, + 0x42, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, + 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, + 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, 0xb0, 0x4c, + 0x2c, 0xb0, 0x39, 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, + 0x2d, 0xb0, 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, + 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x53, 0x2c, 0xb2, + 0x00, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, + 0xb2, 0x01, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, + 0xb0, 0x59, 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, + 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, + 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, 0x2d, + 0xb0, 0x61, 0x2c, 0xb2, 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, 0x48, 0x2b, + 0x2d, 0xb0, 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, + 0x2b, 0x2d, 0xb0, 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x69, 0x2c, 0xb3, + 0x01, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x44, 0x2b, 0x2d, + 0xb0, 0x6c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, + 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, + 0x40, 0x2b, 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, + 0x2b, 0x2d, 0xb0, 0x73, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, + 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, + 0xb0, 0x77, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, + 0x00, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, + 0x41, 0x2b, 0x2d, 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, + 0x2b, 0x2d, 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, + 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, 0x2c, 0xb1, 0x01, 0x3e, + 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, + 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, + 0xb0, 0x87, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, + 0x01, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, + 0x50, 0x58, 0xb0, 0x06, 0x1b, 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, 0x50, + 0x78, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, 0xb9, 0x08, + 0x00, 0x08, 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, 0x51, 0x41, 0x00, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, + 0x42, 0x40, 0x14, 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, 0x02, 0x56, 0x06, 0x46, 0x08, 0x3a, 0x06, 0x32, 0x04, 0x24, 0x07, 0x09, 0x0a, 0x2a, 0xb1, 0x00, + 0x07, 0x42, 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x4e, 0x06, 0x40, 0x04, 0x36, 0x02, 0x2b, 0x05, 0x09, 0x0a, 0x2a, 0xb1, + 0x00, 0x10, 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, 0x11, 0xc0, 0x0e, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, + 0x0b, 0x2a, 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, + 0x00, 0x09, 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, + 0x44, 0xb1, 0x28, 0x01, 0x88, 0x51, 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, + 0xba, 0x08, 0x80, 0x00, 0x01, 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, 0x06, + 0x7a, 0x06, 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x48, 0x06, 0x3c, 0x04, 0x34, 0x02, 0x26, 0x05, 0x09, 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, + 0xb1, 0x02, 0x00, 0x44, 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x5d, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, + 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4b, 0x00, 0x4b, 0x02, 0x3c, 0x00, 0x00, 0x02, 0x45, 0xff, 0xf8, 0x00, 0x5c, 0x00, 0x5c, + 0x00, 0x4b, 0x00, 0x4b, 0x02, 0x3c, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x45, 0x02, 0x45, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x49, + 0x00, 0x49, 0x02, 0xca, 0xff, 0xf6, 0x02, 0xf8, 0x02, 0x18, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xfd, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, + 0x00, 0x48, 0x00, 0x48, 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x48, + 0x00, 0x48, 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0x00, 0x00, 0x02, 0xec, 0x02, 0x18, + 0x00, 0x00, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xec, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x2c, 0x00, 0x2c, 0x01, 0x2a, + 0xff, 0x7e, 0x01, 0x61, 0x00, 0xe2, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x32, 0xff, 0x76, 0x01, 0x61, 0x00, 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x3b, 0x00, 0x3b, + 0x00, 0x2c, 0x00, 0x2c, 0x02, 0xcb, 0x01, 0xa0, 0x02, 0xe0, 0x02, 0x61, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe0, 0x01, 0x98, 0x02, 0xe0, 0x02, 0x67, 0x01, 0x19, + 0x00, 0x8f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, + 0x00, 0x01, 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x0e, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, + 0x00, 0x36, 0x00, 0xd6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x22, 0x01, 0x0c, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, + 0x01, 0x2e, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x20, 0x01, 0x82, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, + 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, + 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, + 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, + 0x00, 0x73, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, + 0x00, 0x6d, 0x00, 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, + 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, + 0x00, 0x72, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, + 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, + 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, + 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x4e, 0x00, 0x6f, + 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, + 0x00, 0x61, 0x00, 0x72, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, + 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x68, 0x00, 0x69, + 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, + 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, + 0x00, 0x2d, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9c, + 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, + 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x1f, 0x00, 0x01, + 0x00, 0x22, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x42, 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x05, 0x00, 0x18, 0x00, 0x18, + 0x00, 0x18, 0x00, 0x20, 0x00, 0x20, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x2d, 0x00, 0x02, + 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x3b, 0x00, 0x01, 0x02, 0x77, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, + 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0x65, 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x06, 0x07, 0x2c, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0xf6, 0x00, 0x01, 0x00, 0x34, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, + 0x00, 0x62, 0x00, 0xe2, 0x00, 0x74, 0x00, 0x7a, 0x00, 0xb2, 0x00, 0x84, 0x00, 0x8a, 0x00, 0xb2, 0x00, 0xa8, 0x00, 0xb2, 0x00, 0xb8, 0x00, 0xdc, 0x00, 0xdc, + 0x00, 0xc2, 0x00, 0xe2, 0x00, 0xcc, 0x00, 0xd2, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xe2, 0x00, 0x01, 0x00, 0x15, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, + 0x00, 0x23, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3c, 0x00, 0x40, + 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, 0x37, 0xff, 0xec, 0x00, 0x38, 0xff, 0xec, 0x00, 0x3a, + 0xff, 0xe2, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x32, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xf6, 0x00, 0x0f, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x07, + 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, 0xec, 0x00, 0x3e, 0x00, 0x14, 0x00, 0x5e, + 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x39, 0xff, 0xec, 0x00, 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, + 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x5f, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, + 0x00, 0x14, 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, 0x04, 0x32, 0x00, 0x04, 0x00, 0x00, + 0x04, 0x86, 0x05, 0x50, 0x00, 0x17, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, 0xff, 0xe2, + 0xff, 0xce, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xce, 0xff, 0xd8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, + 0xff, 0xec, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xec, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xce, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x00, + 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xe2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xba, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xff, 0xc4, 0xff, 0xba, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, + 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x60, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x28, 0x00, 0x03, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x2c, + 0x00, 0x2d, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x42, + 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, + 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6b, 0x00, 0x02, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x09, + 0x00, 0x13, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x22, 0x00, 0x02, + 0x00, 0x24, 0x00, 0x24, 0x00, 0x08, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x26, 0x00, 0x26, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x12, 0x00, 0x2d, + 0x00, 0x2d, 0x00, 0x09, 0x00, 0x30, 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, + 0x00, 0x0c, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x0a, 0x00, 0x39, 0x00, 0x39, 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x07, + 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0e, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x49, + 0x00, 0x49, 0x00, 0x01, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0d, 0x00, 0x57, 0x00, 0x58, + 0x00, 0x05, 0x00, 0x59, 0x00, 0x59, 0x00, 0x16, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x15, + 0x00, 0x01, 0x00, 0x03, 0x00, 0x6d, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0d, 0x00, 0x12, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, + 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, + 0x00, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, + 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0d, + 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x36, 0x00, 0x6c, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, + 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x1a, 0x66, 0x72, 0x61, 0x63, 0x00, 0x20, + 0x6c, 0x69, 0x67, 0x61, 0x00, 0x2a, 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x32, 0x00, 0x10, 0x00, 0x1e, 0x00, 0x32, 0x00, 0x4a, + 0x00, 0x88, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x5f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, + 0x00, 0x01, 0x00, 0x06, 0x00, 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x69, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, + 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, + 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x70, 0x00, 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, 0x7a, 0x00, 0x83, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, + 0x00, 0x01, 0x00, 0x36, 0x00, 0x01, 0x00, 0x08, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6f, 0x00, 0x03, 0x00, 0x47, + 0x00, 0x4d, 0x00, 0x6e, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x6d, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6b, 0x00, 0x02, + 0x00, 0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x47}; + +const inline uint8_t FONT_ITALICS_DATA[] = { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x09, 0x76, 0x04, 0x22, 0x00, 0x00, 0x59, 0xdc, 0x00, 0x00, + 0x00, 0x7a, 0x47, 0x50, 0x4f, 0x53, 0x33, 0x4f, 0x0e, 0xa7, 0x00, 0x00, 0x5a, 0x58, 0x00, 0x00, 0x07, 0x4e, 0x47, 0x53, 0x55, 0x42, 0xfc, 0xd3, 0xd8, 0xce, + 0x00, 0x00, 0x61, 0xa8, 0x00, 0x00, 0x01, 0xd4, 0x4f, 0x53, 0x2f, 0x32, 0x69, 0x50, 0x5f, 0x5f, 0x00, 0x00, 0x46, 0xec, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, + 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x47, 0x4c, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, 0x20, 0x3d, 0xa5, 0x1a, 0xce, 0x00, 0x00, 0x56, 0x94, + 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, 0x0b, 0x83, 0x00, 0x00, 0x47, 0x80, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x59, 0xd4, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0x07, 0xce, 0x9d, 0x67, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x42, 0x36, + 0x68, 0x65, 0x61, 0x64, 0x28, 0x38, 0xd8, 0x22, 0x00, 0x00, 0x44, 0x8c, 0x00, 0x00, 0x00, 0x36, 0x68, 0x68, 0x65, 0x61, 0x0d, 0x3b, 0x0b, 0x91, 0x00, 0x00, + 0x46, 0xc8, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0xec, 0x2d, 0x0f, 0x0b, 0x00, 0x00, 0x44, 0xc4, 0x00, 0x00, 0x02, 0x02, 0x6c, 0x6f, 0x63, 0x61, + 0xd3, 0x44, 0xc2, 0xf3, 0x00, 0x00, 0x43, 0x74, 0x00, 0x00, 0x01, 0x16, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x5b, 0x10, 0x84, 0x00, 0x00, 0x43, 0x54, 0x00, 0x00, + 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x5c, 0x42, 0x2a, 0x00, 0x00, 0x57, 0xc0, 0x00, 0x00, 0x01, 0xf4, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x93, 0x00, 0x32, + 0x00, 0x00, 0x59, 0xb4, 0x00, 0x00, 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0xff, 0x8d, 0x0b, 0xc2, 0x00, 0x00, 0x55, 0x8c, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, + 0x00, 0x14, 0xff, 0xf2, 0x01, 0x13, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x2f, 0x40, 0x2c, 0x04, 0x01, 0x01, 0x00, 0x03, 0x00, 0x01, 0x03, 0x80, 0x00, + 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x05, 0x04, 0x00, 0x00, 0x0a, 0x08, 0x04, 0x0e, 0x05, 0x0e, + 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x37, 0x13, 0x33, 0x03, 0x07, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x4d, 0x5b, + 0x6b, 0x7f, 0x4b, 0x35, 0x24, 0x27, 0x17, 0x1c, 0x23, 0xc9, 0x02, 0x01, 0xfd, 0xff, 0xd7, 0x36, 0x20, 0x31, 0x1c, 0x1a, 0x1d, 0x34, 0x00, 0x02, 0x00, 0x6d, + 0x01, 0xc8, 0x01, 0x9c, 0x02, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x40, 0x21, 0x05, 0x03, 0x04, 0x03, 0x01, 0x01, 0x00, 0x5f, 0x02, 0x01, 0x00, 0x00, + 0x6a, 0x01, 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x01, 0x13, 0x33, 0x03, + 0x23, 0x13, 0x33, 0x03, 0x01, 0x19, 0x23, 0x60, 0x4b, 0xe4, 0x23, 0x60, 0x4b, 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x02, + 0x00, 0x1e, 0x00, 0x00, 0x02, 0x8e, 0x02, 0xca, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, 0x40, 0x44, 0x07, 0x05, 0x02, 0x03, 0x0f, 0x08, 0x02, 0x02, 0x01, 0x03, + 0x02, 0x68, 0x0e, 0x09, 0x02, 0x01, 0x0c, 0x0a, 0x02, 0x00, 0x0b, 0x01, 0x00, 0x67, 0x06, 0x01, 0x04, 0x04, 0x6a, 0x4d, 0x10, 0x0d, 0x02, 0x0b, 0x0b, 0x6b, + 0x0b, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, 0x1c, 0x00, 0x1b, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x0d, 0x1f, 0x2b, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, 0x07, 0x23, + 0x07, 0x33, 0x07, 0x23, 0x07, 0x23, 0x37, 0x23, 0x07, 0x13, 0x33, 0x37, 0x23, 0x61, 0x3b, 0x7e, 0x06, 0x8b, 0x30, 0x86, 0x06, 0x92, 0x3c, 0x48, 0x3d, 0x90, + 0x3e, 0x44, 0x3c, 0x80, 0x07, 0x8d, 0x2f, 0x8a, 0x06, 0x97, 0x3c, 0x48, 0x3f, 0x90, 0x3d, 0x50, 0x90, 0x2d, 0x8f, 0xd1, 0x42, 0xa2, 0x41, 0xd4, 0xd4, 0xd4, + 0xd4, 0x41, 0xa2, 0x42, 0xd1, 0xd1, 0xd1, 0x01, 0x13, 0xa2, 0x00, 0x03, 0x00, 0x22, 0xff, 0xc6, 0x02, 0x0d, 0x02, 0xf6, 0x00, 0x23, 0x00, 0x2a, 0x00, 0x31, + 0x00, 0x82, 0x40, 0x14, 0x15, 0x12, 0x02, 0x03, 0x02, 0x31, 0x2a, 0x1a, 0x16, 0x08, 0x04, 0x06, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x4b, 0xb0, + 0x0c, 0x50, 0x58, 0x40, 0x19, 0x00, 0x04, 0x00, 0x00, 0x04, 0x71, 0x00, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x03, 0x03, 0x02, 0x5f, 0x00, 0x02, + 0x02, 0x6c, 0x03, 0x4e, 0x1b, 0x4b, 0xb0, 0x31, 0x50, 0x58, 0x40, 0x18, 0x00, 0x04, 0x00, 0x04, 0x86, 0x00, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, + 0x03, 0x03, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6c, 0x03, 0x4e, 0x1b, 0x40, 0x1d, 0x00, 0x04, 0x00, 0x04, 0x86, 0x00, 0x02, 0x00, 0x03, 0x01, 0x02, 0x03, 0x69, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, 0x00, 0x51, 0x59, 0x59, 0xb7, 0x19, 0x17, 0x19, 0x15, 0x10, 0x05, 0x0d, + 0x1b, 0x2b, 0x37, 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x37, 0x37, 0x33, 0x07, 0x16, 0x16, 0x17, 0x07, 0x26, + 0x26, 0x27, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x23, 0x13, 0x06, 0x06, 0x15, 0x14, 0x16, 0x17, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, + 0xbe, 0x29, 0x54, 0x1f, 0x27, 0x5c, 0x27, 0x2f, 0x3d, 0x47, 0x35, 0x5c, 0x39, 0x13, 0x41, 0x12, 0x26, 0x46, 0x1e, 0x21, 0x17, 0x3e, 0x23, 0x2d, 0x44, 0x45, + 0x38, 0x5e, 0x3b, 0x18, 0x41, 0x8c, 0x2f, 0x3b, 0x21, 0x22, 0x03, 0x2e, 0x40, 0x1f, 0x26, 0x32, 0x02, 0x13, 0x0f, 0x50, 0x14, 0x17, 0x01, 0xd7, 0x17, 0x45, + 0x3f, 0x39, 0x4c, 0x2b, 0x05, 0x55, 0x56, 0x03, 0x12, 0x10, 0x47, 0x0d, 0x15, 0x02, 0xd1, 0x19, 0x43, 0x3b, 0x3a, 0x4f, 0x2d, 0x07, 0x6d, 0x02, 0x92, 0x05, + 0x34, 0x31, 0x19, 0x2a, 0x0d, 0xfe, 0xdf, 0x06, 0x37, 0x2f, 0x1a, 0x28, 0x0f, 0x00, 0x00, 0x05, 0x00, 0x50, 0xff, 0xf6, 0x02, 0xf3, 0x02, 0xd4, 0x00, 0x11, + 0x00, 0x15, 0x00, 0x26, 0x00, 0x38, 0x00, 0x49, 0x00, 0x99, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x2c, 0x00, 0x07, 0x00, 0x09, 0x04, 0x07, 0x09, 0x6a, 0x0c, + 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x70, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x03, 0x61, + 0x0d, 0x06, 0x0b, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x34, 0x00, 0x07, 0x00, 0x09, 0x04, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, + 0x08, 0x04, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x0b, 0x01, 0x03, 0x03, 0x6b, 0x4d, 0x0e, + 0x01, 0x08, 0x08, 0x06, 0x61, 0x0d, 0x01, 0x06, 0x06, 0x71, 0x06, 0x4e, 0x59, 0x40, 0x2b, 0x3a, 0x39, 0x28, 0x27, 0x17, 0x16, 0x12, 0x12, 0x01, 0x00, 0x43, + 0x41, 0x39, 0x49, 0x3a, 0x49, 0x31, 0x2f, 0x27, 0x38, 0x28, 0x38, 0x20, 0x1e, 0x16, 0x26, 0x17, 0x26, 0x12, 0x15, 0x12, 0x15, 0x14, 0x13, 0x0a, 0x08, 0x00, + 0x11, 0x01, 0x11, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x03, 0x03, 0x01, 0x33, 0x01, 0x13, + 0x32, 0x3e, 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x14, 0x01, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x03, + 0x27, 0x32, 0x3e, 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x14, 0xc3, 0x37, 0x3c, 0x0a, 0x19, 0x2b, 0x42, 0x2e, 0x39, 0x3c, 0x0b, 0x1a, 0x2d, + 0x41, 0x7f, 0x02, 0x12, 0x4e, 0xfd, 0xee, 0x0b, 0x1a, 0x27, 0x1a, 0x0f, 0x07, 0x1a, 0x19, 0x1a, 0x26, 0x1a, 0x0f, 0x07, 0x01, 0x9a, 0x37, 0x3c, 0x0a, 0x19, + 0x2c, 0x41, 0x2e, 0x3a, 0x3c, 0x0c, 0x1a, 0x2c, 0x42, 0x26, 0x1a, 0x27, 0x1a, 0x0f, 0x07, 0x1a, 0x19, 0x1a, 0x26, 0x19, 0x0f, 0x07, 0x01, 0x14, 0x4b, 0x46, + 0x1d, 0x4e, 0x52, 0x47, 0x2b, 0x47, 0x42, 0x1b, 0x4f, 0x55, 0x4a, 0x2e, 0xfe, 0xec, 0x02, 0xca, 0xfd, 0x36, 0x01, 0x56, 0x27, 0x3d, 0x42, 0x3a, 0x0f, 0x29, + 0x25, 0x24, 0x38, 0x41, 0x3c, 0x14, 0x50, 0xfe, 0xa0, 0x4a, 0x46, 0x1e, 0x4f, 0x52, 0x46, 0x2b, 0x47, 0x41, 0x1b, 0x4f, 0x55, 0x4b, 0x2e, 0x42, 0x27, 0x3d, + 0x43, 0x39, 0x0f, 0x29, 0x25, 0x24, 0x38, 0x41, 0x3c, 0x14, 0x50, 0x00, 0x00, 0x03, 0x00, 0x20, 0xff, 0xf6, 0x02, 0x85, 0x02, 0xd5, 0x00, 0x21, 0x00, 0x2d, + 0x00, 0x38, 0x00, 0x7b, 0x40, 0x0f, 0x32, 0x14, 0x06, 0x03, 0x02, 0x04, 0x31, 0x1f, 0x1c, 0x15, 0x04, 0x05, 0x02, 0x02, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x24, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x4d, 0x07, 0x01, + 0x05, 0x05, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, + 0x02, 0x02, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x2f, + 0x2e, 0x01, 0x00, 0x2e, 0x38, 0x2f, 0x38, 0x2a, 0x28, 0x1e, 0x1d, 0x19, 0x18, 0x0e, 0x0c, 0x00, 0x21, 0x01, 0x21, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, + 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, 0x07, + 0x17, 0x23, 0x27, 0x06, 0x06, 0x13, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x03, 0x32, 0x36, 0x37, 0x27, 0x0e, 0x02, 0x15, 0x14, 0x16, + 0xd8, 0x51, 0x67, 0x63, 0x5b, 0x13, 0x1e, 0x2d, 0x56, 0x3d, 0x49, 0x56, 0x35, 0x58, 0x35, 0x84, 0x21, 0x2e, 0x10, 0x58, 0x19, 0x46, 0x2c, 0x63, 0x68, 0x37, + 0x2f, 0x6a, 0x02, 0x20, 0x42, 0x2e, 0x28, 0x26, 0x31, 0x37, 0x18, 0x35, 0x51, 0x25, 0x91, 0x24, 0x40, 0x28, 0x40, 0x0a, 0x5b, 0x57, 0x50, 0x69, 0x2b, 0x20, + 0x4b, 0x2a, 0x33, 0x51, 0x30, 0x4d, 0x42, 0x32, 0x48, 0x37, 0x1b, 0xb8, 0x1d, 0x4b, 0x28, 0x3d, 0x66, 0x2a, 0x85, 0x4e, 0x26, 0x32, 0x01, 0xbb, 0x10, 0x27, + 0x34, 0x23, 0x23, 0x2c, 0x3a, 0x33, 0x3b, 0xfe, 0x59, 0x2b, 0x1e, 0xce, 0x13, 0x2c, 0x3d, 0x2c, 0x33, 0x3c, 0x00, 0x01, 0x00, 0x6d, 0x01, 0xc8, 0x00, 0xf0, + 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, + 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x13, 0x33, 0x03, 0x6d, 0x23, 0x60, 0x4b, 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, 0x62, + 0x01, 0x6f, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x0e, 0x16, 0x03, 0x0d, 0x17, 0x2b, 0x17, 0x26, 0x26, 0x35, 0x34, 0x12, 0x37, 0x33, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x17, 0x70, 0x22, 0x26, 0x80, 0x76, + 0x51, 0x47, 0x6e, 0x3e, 0x1d, 0x1b, 0x9e, 0x3d, 0x94, 0x52, 0xb3, 0x01, 0x19, 0x79, 0x4e, 0xb5, 0xcd, 0x74, 0x57, 0x8f, 0x3e, 0x00, 0x00, 0x01, 0xff, 0xb3, + 0xff, 0x62, 0x00, 0xf9, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x00, + 0x00, 0x0e, 0x00, 0x0e, 0x17, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x15, 0x14, 0x02, 0x07, 0x4d, 0x47, 0x6d, + 0x3e, 0x1c, 0x1b, 0x44, 0x22, 0x25, 0x7f, 0x77, 0x9e, 0x4f, 0xb4, 0xce, 0x73, 0x56, 0x91, 0x3d, 0x3d, 0x94, 0x53, 0xb2, 0xfe, 0xe7, 0x79, 0x00, 0x00, 0x01, + 0x00, 0x67, 0x01, 0x2c, 0x02, 0x33, 0x02, 0xfb, 0x00, 0x0e, 0x00, 0x1d, 0x40, 0x1a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x05, 0x00, 0x4a, 0x0e, 0x0d, 0x0c, 0x04, + 0x03, 0x02, 0x01, 0x07, 0x00, 0x49, 0x00, 0x00, 0x00, 0x76, 0x1a, 0x01, 0x0d, 0x17, 0x2b, 0x01, 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x37, 0x17, 0x07, + 0x37, 0x07, 0x27, 0x17, 0x01, 0x74, 0x36, 0x7b, 0x3d, 0x95, 0xb4, 0x1c, 0xb4, 0x14, 0x57, 0x3b, 0xcc, 0x04, 0xbe, 0x57, 0x01, 0x2c, 0xc3, 0xa5, 0x3d, 0x89, + 0x35, 0x4e, 0x59, 0xc1, 0x11, 0xba, 0x0a, 0x52, 0x17, 0xb9, 0x00, 0x01, 0x00, 0x46, 0x00, 0x6f, 0x02, 0x1c, 0x02, 0x53, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, + 0x00, 0x05, 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, 0x05, 0x02, 0x5f, 0x00, 0x02, 0x05, 0x02, 0x4f, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, 0x01, 0x55, 0xc7, 0xc7, + 0x48, 0xc7, 0xc7, 0x48, 0x01, 0x84, 0x47, 0xce, 0xce, 0x47, 0xcf, 0x00, 0x00, 0x01, 0xff, 0xd5, 0xff, 0x7f, 0x00, 0x9c, 0x00, 0x74, 0x00, 0x08, 0x00, 0x17, + 0x40, 0x14, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x13, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x36, 0x36, + 0x37, 0x33, 0x17, 0x06, 0x06, 0x07, 0x2b, 0x1a, 0x36, 0x13, 0x60, 0x04, 0x19, 0x48, 0x23, 0x81, 0x3b, 0x86, 0x34, 0x0b, 0x35, 0x7e, 0x37, 0x00, 0x00, 0x01, + 0x00, 0x1a, 0x00, 0xe3, 0x01, 0x18, 0x01, 0x34, 0x00, 0x03, 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, + 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, 0x37, 0x33, 0x07, 0x1a, 0x12, 0xec, 0x12, 0xe3, 0x51, + 0x51, 0x00, 0x00, 0x01, 0x00, 0x14, 0xff, 0xf2, 0x00, 0x92, 0x00, 0x79, 0x00, 0x0a, 0x00, 0x1a, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x02, 0x01, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x06, 0x04, 0x00, 0x0a, 0x01, 0x0a, 0x03, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, + 0x06, 0x48, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0x0e, 0x34, 0x21, 0x32, 0x1b, 0x1a, 0x1f, 0x33, 0x00, 0x01, 0xff, 0xd2, 0x00, 0x00, 0x01, 0xb9, 0x02, 0xca, + 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, + 0x0d, 0x17, 0x2b, 0x23, 0x01, 0x33, 0x01, 0x2e, 0x01, 0x8d, 0x5a, 0xfe, 0x74, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x00, 0x02, 0x00, 0x39, 0xff, 0xf6, 0x02, 0x16, + 0x02, 0xd5, 0x00, 0x11, 0x00, 0x23, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, + 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x13, 0x12, 0x01, 0x00, 0x1c, 0x1a, 0x12, 0x23, 0x13, 0x23, 0x0a, 0x08, 0x00, 0x11, 0x01, 0x11, 0x06, 0x0d, 0x16, + 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x03, 0x27, 0x32, 0x3e, 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, + 0x15, 0x14, 0x16, 0xec, 0x58, 0x5b, 0x14, 0x2b, 0x46, 0x63, 0x41, 0x5c, 0x58, 0x16, 0x2d, 0x46, 0x62, 0x35, 0x28, 0x3f, 0x2f, 0x20, 0x10, 0x2f, 0x30, 0x26, + 0x40, 0x31, 0x22, 0x12, 0x30, 0x0a, 0x7e, 0x75, 0x3b, 0x86, 0x81, 0x6a, 0x40, 0x77, 0x6f, 0x48, 0x90, 0x82, 0x65, 0x3a, 0x4b, 0x34, 0x59, 0x70, 0x79, 0x3a, + 0x4a, 0x4f, 0x33, 0x57, 0x6c, 0x75, 0x36, 0x51, 0x57, 0x00, 0x00, 0x01, 0x00, 0x8f, 0x00, 0x00, 0x01, 0xbc, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x1b, 0x40, 0x18, + 0x08, 0x07, 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x11, 0x19, 0x02, 0x0d, 0x18, 0x2b, 0x01, + 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, 0x03, 0x23, 0x01, 0x29, 0x0a, 0x17, 0x09, 0x0f, 0x20, 0x14, 0x58, 0x29, 0xe0, 0x4d, 0x99, 0x59, + 0x01, 0xba, 0x2f, 0x60, 0x1d, 0x10, 0x18, 0x0d, 0x37, 0x42, 0x8e, 0xfd, 0x36, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x10, 0x02, 0xd4, 0x00, 0x1b, + 0x00, 0x2c, 0x40, 0x29, 0x0d, 0x0c, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, + 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x1b, 0x27, 0x25, 0x28, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x37, 0x37, 0x3e, 0x02, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x15, 0x21, 0x07, 0x03, 0x10, 0xe3, 0x42, 0x54, + 0x28, 0x37, 0x33, 0x2c, 0x4a, 0x23, 0x2a, 0x29, 0x64, 0x40, 0x5b, 0x61, 0x2c, 0x63, 0x53, 0xa8, 0x01, 0x46, 0x0f, 0x4b, 0xcd, 0x3c, 0x54, 0x4c, 0x2f, 0x2d, + 0x39, 0x24, 0x1a, 0x3c, 0x21, 0x2c, 0x5b, 0x48, 0x3a, 0x5f, 0x6a, 0x48, 0x92, 0x04, 0x50, 0x00, 0x00, 0x01, 0x00, 0x16, 0xff, 0xf6, 0x02, 0x0d, 0x02, 0xd4, + 0x00, 0x2b, 0x00, 0x4a, 0x40, 0x47, 0x1b, 0x01, 0x04, 0x05, 0x1a, 0x01, 0x03, 0x04, 0x24, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, + 0x05, 0x4c, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1f, 0x1d, 0x18, 0x16, 0x11, 0x0f, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x2b, 0x01, 0x2b, 0x07, 0x0d, 0x16, 0x2b, + 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, + 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xd2, 0x3a, 0x5b, 0x27, 0x23, 0x66, 0x34, 0x50, + 0x56, 0x4b, 0x45, 0x40, 0x0f, 0x41, 0x32, 0x55, 0x33, 0x39, 0x2d, 0x2e, 0x4c, 0x26, 0x29, 0x29, 0x65, 0x43, 0x5a, 0x5e, 0x62, 0x57, 0x39, 0x49, 0x36, 0x72, + 0x0a, 0x15, 0x12, 0x55, 0x13, 0x1f, 0x4d, 0x41, 0x3e, 0x40, 0x49, 0x23, 0x44, 0x2f, 0x2e, 0x31, 0x20, 0x1a, 0x3e, 0x1e, 0x28, 0x57, 0x47, 0x4c, 0x6a, 0x10, + 0x04, 0x0a, 0x4f, 0x41, 0x38, 0x65, 0x3f, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x02, 0x18, 0x02, 0xca, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x2e, 0x40, 0x2b, + 0x11, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x05, 0x01, 0x02, 0x03, 0x01, 0x00, 0x04, 0x02, 0x00, 0x68, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x6b, + 0x04, 0x4e, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0d, 0x1a, 0x2b, 0x21, 0x37, 0x21, 0x37, 0x01, 0x33, 0x03, 0x33, + 0x07, 0x23, 0x07, 0x25, 0x33, 0x37, 0x3e, 0x02, 0x37, 0x23, 0x0e, 0x02, 0x07, 0x01, 0x20, 0x23, 0xfe, 0xc3, 0x0f, 0x01, 0x93, 0x65, 0x63, 0x6e, 0x11, 0x6f, + 0x23, 0xfe, 0xfa, 0xe5, 0x24, 0x08, 0x15, 0x15, 0x06, 0x04, 0x08, 0x1a, 0x19, 0x09, 0xa2, 0x50, 0x01, 0xd8, 0xfe, 0x26, 0x4e, 0xa2, 0xf0, 0xab, 0x25, 0x51, + 0x48, 0x17, 0x0d, 0x24, 0x22, 0x0a, 0x00, 0x01, 0x00, 0x25, 0xff, 0xf6, 0x02, 0x18, 0x02, 0xca, 0x00, 0x20, 0x00, 0x44, 0x40, 0x41, 0x16, 0x11, 0x02, 0x02, + 0x05, 0x10, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, + 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1a, 0x18, 0x15, 0x14, 0x13, 0x12, 0x0e, 0x0c, + 0x07, 0x05, 0x00, 0x20, 0x01, 0x20, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, + 0x07, 0x27, 0x13, 0x21, 0x07, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0xc8, 0x61, 0x42, 0x24, 0x53, 0x2c, 0x46, 0x56, 0x27, 0x48, + 0x3e, 0x1e, 0x34, 0x20, 0x25, 0x61, 0x01, 0x49, 0x11, 0xfd, 0x3c, 0x12, 0x2a, 0x1b, 0x59, 0x69, 0x1d, 0x41, 0x6f, 0x0a, 0x27, 0x55, 0x16, 0x1c, 0x30, 0x4f, + 0x2e, 0x3e, 0x44, 0x0a, 0x08, 0x1d, 0x01, 0x50, 0x50, 0xcf, 0x04, 0x06, 0x65, 0x58, 0x2d, 0x5b, 0x4c, 0x2e, 0x00, 0x02, 0x00, 0x3f, 0xff, 0xf6, 0x02, 0x22, + 0x02, 0xd4, 0x00, 0x1e, 0x00, 0x30, 0x00, 0x47, 0x40, 0x44, 0x0c, 0x01, 0x02, 0x01, 0x0d, 0x01, 0x03, 0x02, 0x13, 0x01, 0x04, 0x05, 0x03, 0x4c, 0x00, 0x03, + 0x00, 0x05, 0x04, 0x03, 0x05, 0x69, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x20, 0x1f, 0x01, 0x00, 0x27, 0x25, 0x1f, 0x30, 0x20, 0x30, 0x18, 0x16, 0x11, 0x0f, 0x0b, 0x09, 0x00, 0x1e, 0x01, 0x1e, 0x08, 0x0d, 0x16, + 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x37, 0x36, 0x36, 0x33, 0x32, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, + 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0xfb, 0x54, 0x68, + 0x20, 0x44, 0x35, 0x2b, 0x76, 0x4d, 0x36, 0x26, 0x12, 0x10, 0x29, 0x1b, 0x5f, 0x91, 0x23, 0x04, 0x1d, 0x54, 0x34, 0x4a, 0x58, 0x1e, 0x3d, 0x5e, 0x37, 0x31, + 0x44, 0x24, 0x34, 0x35, 0x24, 0x3c, 0x29, 0x09, 0x07, 0x05, 0x16, 0x30, 0x0a, 0x6b, 0x70, 0x46, 0x9d, 0x91, 0x33, 0x2c, 0x30, 0x0b, 0x4c, 0x05, 0x07, 0x84, + 0x97, 0x26, 0x2d, 0x5e, 0x56, 0x32, 0x63, 0x51, 0x31, 0x4a, 0x38, 0x5b, 0x32, 0x38, 0x3d, 0x20, 0x2e, 0x15, 0x10, 0x28, 0x14, 0x24, 0x3f, 0x28, 0x00, 0x01, + 0x00, 0x51, 0x00, 0x00, 0x02, 0x32, 0x02, 0xca, 0x00, 0x06, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, + 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x37, 0x21, 0x07, 0x01, 0x51, 0x01, + 0x75, 0xfe, 0xa5, 0x10, 0x01, 0xb7, 0x0d, 0xfe, 0x8b, 0x02, 0x7c, 0x4e, 0x46, 0xfd, 0x7c, 0x00, 0x00, 0x03, 0x00, 0x2d, 0xff, 0xf6, 0x02, 0x1f, 0x02, 0xd5, + 0x00, 0x1c, 0x00, 0x28, 0x00, 0x36, 0x00, 0x35, 0x40, 0x32, 0x30, 0x16, 0x07, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, + 0x70, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x2a, 0x29, 0x01, 0x00, 0x29, 0x36, 0x2a, 0x36, 0x24, 0x22, 0x0f, + 0x0d, 0x00, 0x1c, 0x01, 0x1c, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x03, 0x32, + 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x0e, 0x02, 0x15, 0x14, 0x16, 0xf6, 0x45, 0x59, 0x2b, 0x64, 0x59, 0x26, 0x2f, 0x38, 0x61, 0x3b, 0x42, 0x50, 0x24, 0x2f, + 0x4c, 0x2c, 0x34, 0x3d, 0x33, 0x6c, 0x0f, 0x44, 0x47, 0x36, 0x2e, 0x35, 0x41, 0x2c, 0x19, 0x32, 0x40, 0x1e, 0x32, 0x35, 0x2d, 0x49, 0x2a, 0x43, 0x0a, 0x31, + 0x51, 0x31, 0x4d, 0x68, 0x22, 0x1c, 0x46, 0x37, 0x3b, 0x54, 0x2d, 0x2d, 0x48, 0x29, 0x35, 0x49, 0x32, 0x13, 0x1f, 0x53, 0x41, 0x35, 0x5d, 0x39, 0x01, 0xa6, + 0x1a, 0x43, 0x35, 0x2b, 0x32, 0x3d, 0x35, 0x2d, 0x3a, 0xfe, 0x8d, 0x25, 0x3b, 0x20, 0x30, 0x48, 0x1c, 0x0e, 0x29, 0x3f, 0x2f, 0x34, 0x3b, 0x00, 0x00, 0x02, + 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x0a, 0x02, 0xd4, 0x00, 0x1f, 0x00, 0x2e, 0x00, 0x47, 0x40, 0x44, 0x0a, 0x01, 0x04, 0x05, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, + 0x00, 0x01, 0x03, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, + 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x21, 0x20, 0x01, 0x00, 0x29, 0x27, 0x20, 0x2e, 0x21, 0x2e, 0x16, 0x14, 0x0f, 0x0d, 0x08, 0x06, 0x00, + 0x1f, 0x01, 0x1f, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, + 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x07, 0x06, 0x06, 0x13, 0x32, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, + 0x16, 0xa5, 0x1e, 0x3e, 0x1a, 0x1b, 0x3b, 0x22, 0x64, 0x77, 0x1e, 0x05, 0x19, 0x4f, 0x30, 0x52, 0x5a, 0x3c, 0x70, 0x4d, 0x58, 0x62, 0x12, 0x22, 0x31, 0x20, + 0x2e, 0x71, 0x2f, 0x2f, 0x4c, 0x15, 0x0e, 0x36, 0x32, 0x32, 0x46, 0x25, 0x34, 0x0a, 0x09, 0x08, 0x51, 0x09, 0x0d, 0x8a, 0x8b, 0x23, 0x2b, 0x62, 0x5b, 0x48, + 0x7b, 0x4b, 0x6f, 0x6d, 0x34, 0x75, 0x73, 0x64, 0x23, 0x33, 0x2c, 0x01, 0x5a, 0x32, 0x2e, 0x22, 0x32, 0x3b, 0x4b, 0x34, 0x57, 0x35, 0x3a, 0x40, 0x00, 0x02, + 0x00, 0x14, 0xff, 0xf2, 0x00, 0xe1, 0x02, 0x26, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x2d, 0x40, 0x2a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, + 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x0c, 0x0b, 0x01, 0x00, 0x11, 0x0f, 0x0b, 0x15, 0x0c, 0x15, 0x06, 0x04, 0x00, + 0x0a, 0x01, 0x0a, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x03, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, + 0x15, 0x14, 0x06, 0x97, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0x75, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0x01, 0x9f, 0x33, 0x22, 0x32, 0x1a, 0x1b, 0x1f, 0x33, + 0xfe, 0x53, 0x34, 0x21, 0x32, 0x1b, 0x1a, 0x1f, 0x33, 0x00, 0x00, 0x02, 0xff, 0xcf, 0xff, 0x7f, 0x00, 0xe1, 0x02, 0x26, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x2f, + 0x40, 0x2c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, 0x03, 0x80, 0x05, 0x01, 0x03, 0x03, 0x84, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x00, + 0x4e, 0x0b, 0x0b, 0x01, 0x00, 0x0b, 0x13, 0x0b, 0x13, 0x0f, 0x0e, 0x06, 0x04, 0x00, 0x0a, 0x01, 0x0a, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x35, 0x34, 0x36, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x03, 0x36, 0x36, 0x37, 0x33, 0x17, 0x06, 0x06, 0x07, 0x97, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0xee, 0x1a, 0x36, 0x13, + 0x60, 0x04, 0x19, 0x48, 0x23, 0x01, 0x9f, 0x33, 0x22, 0x32, 0x1a, 0x1b, 0x1f, 0x33, 0xfd, 0xe0, 0x3b, 0x86, 0x34, 0x0b, 0x35, 0x7e, 0x37, 0x00, 0x00, 0x01, + 0x00, 0x46, 0x00, 0x74, 0x02, 0x1d, 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, 0x32, 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, 0x05, 0x02, + 0x1d, 0xfe, 0x29, 0x01, 0xd7, 0xfe, 0x87, 0x01, 0x79, 0x74, 0xcf, 0x32, 0xeb, 0x4e, 0xb2, 0x9e, 0x00, 0x02, 0x00, 0x4c, 0x00, 0xd9, 0x02, 0x16, 0x01, 0xe7, + 0x00, 0x03, 0x00, 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, + 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, + 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, 0x35, 0x21, 0x15, 0x4c, 0x01, 0xca, 0xfe, 0x36, 0x01, 0xca, 0x01, 0xa0, 0x47, 0x47, 0xc7, 0x47, 0x47, 0x00, 0x00, 0x01, + 0x00, 0x46, 0x00, 0x74, 0x02, 0x1d, 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, 0x25, 0x25, 0x35, 0x05, 0x15, 0x05, 0x46, + 0x01, 0x79, 0xfe, 0x87, 0x01, 0xd7, 0xfe, 0x29, 0xc2, 0x9d, 0xb3, 0x4e, 0xeb, 0x32, 0xcf, 0x00, 0x00, 0x02, 0x00, 0x4d, 0xff, 0xf2, 0x01, 0xc6, 0x02, 0xd4, + 0x00, 0x1c, 0x00, 0x27, 0x00, 0x3f, 0x40, 0x3c, 0x0f, 0x01, 0x00, 0x01, 0x0e, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x05, 0x01, 0x02, 0x00, 0x04, 0x00, 0x02, 0x04, + 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x1e, 0x1d, 0x00, + 0x00, 0x23, 0x21, 0x1d, 0x27, 0x1e, 0x27, 0x00, 0x1c, 0x00, 0x1c, 0x25, 0x2a, 0x07, 0x0d, 0x18, 0x2b, 0x37, 0x3e, 0x02, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, + 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x0e, 0x02, 0x07, 0x07, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x7f, 0x07, 0x1b, 0x2f, 0x24, 0x20, 0x37, 0x22, 0x30, 0x2e, 0x26, 0x49, 0x21, 0x20, 0x29, 0x62, 0x2f, 0x4f, 0x5e, 0x49, 0x46, 0x27, 0x2b, 0x17, + 0x08, 0x45, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0xc9, 0x2b, 0x40, 0x37, 0x1c, 0x19, 0x2e, 0x38, 0x26, 0x2c, 0x30, 0x19, 0x10, 0x43, 0x16, 0x1c, 0x4e, 0x4f, + 0x43, 0x64, 0x34, 0x1c, 0x28, 0x2c, 0x23, 0xd7, 0x34, 0x21, 0x32, 0x1b, 0x1a, 0x1f, 0x33, 0x00, 0x00, 0x02, 0x00, 0x35, 0xff, 0xa5, 0x03, 0x36, 0x02, 0xc9, + 0x00, 0x40, 0x00, 0x4e, 0x00, 0x90, 0x40, 0x13, 0x22, 0x01, 0x09, 0x04, 0x45, 0x14, 0x02, 0x05, 0x09, 0x3d, 0x01, 0x07, 0x02, 0x3e, 0x01, 0x00, 0x07, 0x04, + 0x4c, 0x4b, 0xb0, 0x1b, 0x50, 0x58, 0x40, 0x28, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, 0x07, 0x05, 0x02, 0x69, 0x00, 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, + 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x09, 0x09, 0x04, 0x61, 0x00, 0x04, 0x04, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x26, 0x00, + 0x04, 0x00, 0x09, 0x05, 0x04, 0x09, 0x69, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, 0x07, 0x05, 0x02, 0x69, 0x00, 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, 0x65, + 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x06, 0x4e, 0x59, 0x40, 0x1f, 0x42, 0x41, 0x01, 0x00, 0x49, 0x47, 0x41, 0x4e, 0x42, 0x4e, 0x3b, 0x39, + 0x33, 0x31, 0x2a, 0x28, 0x20, 0x1e, 0x19, 0x17, 0x12, 0x10, 0x0a, 0x08, 0x00, 0x40, 0x01, 0x40, 0x0c, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, 0x34, + 0x3e, 0x02, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, + 0x16, 0x17, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x15, 0x06, 0x06, 0x03, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x01, 0x81, 0x65, 0x95, 0x52, 0x40, 0x7a, 0xad, + 0x6c, 0x6a, 0x85, 0x3f, 0x37, 0x60, 0x3e, 0x38, 0x2d, 0x04, 0x04, 0x16, 0x44, 0x32, 0x37, 0x42, 0x45, 0x73, 0x44, 0x30, 0x40, 0x1a, 0x2f, 0x08, 0x08, 0x1c, + 0x14, 0x1f, 0x32, 0x23, 0x13, 0x2f, 0x6a, 0x59, 0x56, 0x8b, 0x64, 0x36, 0x88, 0x84, 0x36, 0x6c, 0x2c, 0x34, 0x70, 0x3c, 0x30, 0x3f, 0x13, 0x21, 0x0a, 0x1e, + 0x14, 0x2e, 0x4c, 0x2c, 0x20, 0x5b, 0x50, 0x97, 0x6a, 0x5b, 0xa8, 0x83, 0x4d, 0x53, 0x87, 0x50, 0x59, 0x8c, 0x50, 0x36, 0x23, 0x25, 0x34, 0x49, 0x43, 0x51, + 0x7b, 0x44, 0x12, 0x0b, 0xb3, 0x1e, 0x27, 0x11, 0x1f, 0x18, 0x2a, 0x45, 0x55, 0x2b, 0x42, 0x6c, 0x41, 0x3d, 0x6d, 0x90, 0x53, 0x7f, 0x93, 0x19, 0x11, 0x41, + 0x15, 0x17, 0x01, 0x04, 0x55, 0x43, 0x7c, 0x04, 0x07, 0x36, 0x5c, 0x39, 0x2c, 0x28, 0x00, 0x02, 0xff, 0xc7, 0x00, 0x00, 0x02, 0x01, 0x02, 0xca, 0x00, 0x07, + 0x00, 0x11, 0x00, 0x2c, 0x40, 0x29, 0x0d, 0x01, 0x04, 0x00, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, 0x68, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, + 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x09, 0x08, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x33, 0x13, + 0x23, 0x27, 0x23, 0x07, 0x13, 0x33, 0x27, 0x26, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x39, 0x01, 0x84, 0x5e, 0x58, 0x58, 0x1b, 0xf1, 0x74, 0x9f, 0xbd, 0x10, + 0x04, 0x07, 0x01, 0x03, 0x10, 0x2a, 0x17, 0x02, 0xca, 0xfd, 0x36, 0xde, 0xde, 0x01, 0x2e, 0x96, 0x26, 0x5c, 0x23, 0x26, 0x57, 0x2c, 0x00, 0x03, 0x00, 0x29, + 0x00, 0x00, 0x02, 0x4d, 0x02, 0xca, 0x00, 0x10, 0x00, 0x1a, 0x00, 0x23, 0x00, 0x43, 0x40, 0x40, 0x08, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x00, + 0x05, 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x08, 0x01, 0x04, 0x04, 0x01, 0x5f, 0x06, 0x01, 0x01, 0x01, 0x6b, + 0x01, 0x4e, 0x1c, 0x1b, 0x12, 0x11, 0x00, 0x00, 0x22, 0x20, 0x1b, 0x23, 0x1c, 0x23, 0x19, 0x17, 0x11, 0x1a, 0x12, 0x1a, 0x00, 0x10, 0x00, 0x0f, 0x21, 0x09, + 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x13, 0x32, 0x36, 0x36, 0x35, 0x34, + 0x26, 0x23, 0x23, 0x07, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0xb9, 0x63, 0x71, 0x58, 0x49, 0x31, 0x42, 0x47, 0x7b, 0x50, 0x41, + 0x2d, 0x49, 0x2c, 0x3c, 0x46, 0x65, 0x30, 0x37, 0x55, 0x5c, 0x3e, 0x4a, 0x70, 0x37, 0x02, 0xca, 0x4e, 0x56, 0x49, 0x5b, 0x0e, 0x05, 0x0d, 0x48, 0x3c, 0x49, + 0x63, 0x32, 0x01, 0x9a, 0x1c, 0x39, 0x2c, 0x2f, 0x33, 0xe3, 0xfe, 0xb2, 0x4c, 0x46, 0x30, 0x42, 0xfe, 0xfc, 0x00, 0x01, 0x00, 0x48, 0xff, 0xf6, 0x02, 0x78, + 0x02, 0xd4, 0x00, 0x1d, 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, 0x02, 0x01, 0x1a, 0x0c, 0x02, 0x03, 0x02, 0x1b, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x18, 0x16, 0x10, 0x0e, 0x0a, + 0x08, 0x00, 0x1d, 0x01, 0x1d, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, + 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x01, 0x46, 0x77, 0x87, 0x1e, 0x3d, 0x5d, 0x7c, 0x4e, 0x64, 0x4a, 0x24, 0x1b, 0x43, 0x2c, 0x4b, + 0x6d, 0x48, 0x23, 0x5d, 0x52, 0x29, 0x4f, 0x26, 0x27, 0x4f, 0x0a, 0x92, 0x7f, 0x40, 0x84, 0x76, 0x5d, 0x36, 0x28, 0x4a, 0x0e, 0x15, 0x43, 0x6f, 0x86, 0x44, + 0x5b, 0x69, 0x10, 0x0d, 0x4e, 0x0e, 0x10, 0x00, 0x00, 0x02, 0x00, 0x29, 0x00, 0x00, 0x02, 0x7c, 0x02, 0xca, 0x00, 0x09, 0x00, 0x13, 0x00, 0x2c, 0x40, 0x29, + 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x01, 0x5f, 0x04, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x0b, 0x0a, 0x00, + 0x00, 0x12, 0x10, 0x0a, 0x13, 0x0b, 0x13, 0x00, 0x09, 0x00, 0x08, 0x21, 0x06, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, + 0x37, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0xa9, 0x81, 0x92, 0x61, 0xbb, 0x87, 0x05, 0x68, 0x8e, 0x4a, 0x69, 0x57, 0x55, 0x77, + 0x02, 0xca, 0x8c, 0x91, 0x7c, 0xc2, 0x6f, 0x4d, 0x5e, 0xa0, 0x63, 0x6e, 0x61, 0xfd, 0xd0, 0x00, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x02, 0x2a, 0x02, 0xca, + 0x00, 0x0b, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x04, + 0x04, 0x05, 0x5f, 0x06, 0x01, 0x05, 0x05, 0x6b, 0x05, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x33, + 0x13, 0x21, 0x07, 0x21, 0x07, 0x33, 0x07, 0x21, 0x07, 0x21, 0x07, 0x29, 0x97, 0x01, 0x6a, 0x11, 0xfe, 0xef, 0x2f, 0xff, 0x0f, 0xff, 0x00, 0x37, 0x01, 0x12, + 0x11, 0x02, 0xca, 0x4f, 0xdf, 0x4e, 0xff, 0x4f, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x02, 0x2a, 0x02, 0xca, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x00, 0x02, + 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x04, 0x04, 0x6b, 0x04, 0x4e, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x09, 0x11, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x21, 0x07, 0x21, 0x07, 0x21, 0x07, 0x21, 0x03, 0x29, 0x97, 0x01, 0x6a, 0x10, + 0xfe, 0xee, 0x35, 0x01, 0x00, 0x11, 0xff, 0x00, 0x40, 0x02, 0xca, 0x4f, 0xfe, 0x4f, 0xfe, 0xd2, 0x00, 0x01, 0x00, 0x48, 0xff, 0xf6, 0x02, 0x98, 0x02, 0xd4, + 0x00, 0x21, 0x00, 0x3e, 0x40, 0x3b, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, 0x05, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x67, 0x00, 0x02, + 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1e, 0x1d, 0x1c, 0x1b, + 0x18, 0x16, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x21, 0x01, 0x21, 0x07, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, + 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x23, 0x37, 0x33, 0x03, 0x06, 0x06, 0x01, 0x57, 0x7f, 0x90, 0x37, + 0x67, 0x8d, 0x56, 0x41, 0x62, 0x2c, 0x22, 0x25, 0x56, 0x33, 0x52, 0x83, 0x4c, 0x27, 0x52, 0x40, 0x26, 0x3f, 0x16, 0x2e, 0x8c, 0x11, 0xe5, 0x4c, 0x2d, 0x64, + 0x0a, 0x8e, 0x7f, 0x62, 0xa9, 0x7f, 0x47, 0x16, 0x14, 0x4e, 0x11, 0x18, 0x62, 0xab, 0x6f, 0x37, 0x59, 0x34, 0x0b, 0x07, 0xd3, 0x4e, 0xfe, 0xa3, 0x10, 0x15, + 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x02, 0xac, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x27, 0x40, 0x24, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x68, 0x02, 0x01, + 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x05, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x07, 0x0d, 0x1b, + 0x2b, 0x33, 0x13, 0x33, 0x03, 0x21, 0x13, 0x33, 0x03, 0x23, 0x13, 0x21, 0x03, 0x2a, 0x97, 0x59, 0x40, 0x01, 0x3a, 0x40, 0x58, 0x97, 0x58, 0x46, 0xfe, 0xc6, + 0x46, 0x02, 0xca, 0xfe, 0xd2, 0x01, 0x2e, 0xfd, 0x36, 0x01, 0x4d, 0xfe, 0xb3, 0x00, 0x00, 0x01, 0xff, 0xec, 0x00, 0x00, 0x01, 0x7d, 0x02, 0xca, 0x00, 0x0b, + 0x00, 0x22, 0x40, 0x1f, 0x0a, 0x09, 0x04, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, + 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0x23, 0x37, 0x37, 0x13, 0x27, 0x37, 0x33, 0x07, 0x07, 0x03, 0x17, 0x07, 0x14, 0x0a, 0x55, 0x7a, + 0x4c, 0x0a, 0xfa, 0x0a, 0x56, 0x7a, 0x4d, 0x0a, 0x31, 0x14, 0x02, 0x40, 0x13, 0x32, 0x32, 0x13, 0xfd, 0xc0, 0x14, 0x31, 0x00, 0x01, 0xff, 0x64, 0xff, 0x42, + 0x01, 0x1a, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x28, 0x40, 0x25, 0x03, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, 0x00, 0x01, + 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, 0x01, 0x00, 0x0b, 0x0a, 0x07, 0x05, 0x00, 0x0e, 0x01, 0x0e, 0x04, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x27, 0x37, + 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x50, 0x32, 0x1a, 0x03, 0x0f, 0x24, 0x14, 0x2c, 0x44, 0x0d, 0x96, 0x59, 0x97, 0x16, 0x6d, + 0xbe, 0x0c, 0x4d, 0x04, 0x06, 0x38, 0x40, 0x02, 0xc1, 0xfd, 0x35, 0x65, 0x58, 0x00, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x02, 0x8b, 0x02, 0xca, 0x00, 0x0c, + 0x00, 0x25, 0x40, 0x22, 0x0a, 0x07, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x12, 0x13, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x37, 0x01, 0x33, 0x01, 0x13, 0x23, 0x03, 0x07, 0x03, + 0x29, 0x97, 0x59, 0x4a, 0x3e, 0x01, 0x12, 0x6c, 0xfe, 0xca, 0xa9, 0x62, 0x8b, 0x53, 0x3c, 0x02, 0xca, 0xfe, 0xa5, 0x42, 0x01, 0x19, 0xfe, 0xc6, 0xfe, 0x70, + 0x01, 0x5a, 0x3d, 0xfe, 0xe3, 0x00, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x01, 0xa4, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x6a, + 0x4d, 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, + 0x13, 0x33, 0x03, 0x21, 0x07, 0x29, 0x97, 0x59, 0x87, 0x01, 0x12, 0x11, 0x02, 0xca, 0xfd, 0x86, 0x50, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x03, 0x4c, + 0x02, 0xca, 0x00, 0x16, 0x00, 0x27, 0x40, 0x24, 0x10, 0x0c, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x04, 0x03, 0x03, + 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x16, 0x00, 0x16, 0x16, 0x11, 0x13, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x01, 0x33, + 0x03, 0x23, 0x13, 0x36, 0x36, 0x37, 0x23, 0x01, 0x23, 0x03, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x28, 0x97, 0x7e, 0x45, 0x04, 0x01, 0x3d, 0x89, 0x94, 0x5a, 0x5a, + 0x0e, 0x19, 0x09, 0x02, 0xfe, 0xa8, 0x47, 0x4c, 0x04, 0x02, 0x0a, 0x0d, 0x07, 0x5b, 0x02, 0xca, 0xfd, 0xb9, 0x02, 0x47, 0xfd, 0x36, 0x01, 0xa8, 0x41, 0x6a, + 0x20, 0xfd, 0x8d, 0x02, 0x72, 0x14, 0x43, 0x4b, 0x23, 0xfe, 0x53, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x02, 0xc8, 0x02, 0xca, 0x00, 0x12, 0x00, 0x24, + 0x40, 0x21, 0x0c, 0x03, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x12, 0x11, 0x16, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0x23, 0x03, 0x23, 0x0e, 0x02, + 0x07, 0x03, 0x28, 0x97, 0x5f, 0xdb, 0x03, 0x05, 0x13, 0x0b, 0x54, 0x55, 0x97, 0x5f, 0xdd, 0x03, 0x02, 0x0b, 0x0f, 0x08, 0x52, 0x02, 0xca, 0xfd, 0xb2, 0x24, + 0x6f, 0x32, 0x01, 0x89, 0xfd, 0x36, 0x02, 0x50, 0x15, 0x44, 0x4e, 0x25, 0xfe, 0x7c, 0x00, 0x02, 0x00, 0x48, 0xff, 0xf6, 0x02, 0xb2, 0x02, 0xd5, 0x00, 0x0f, + 0x00, 0x1f, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x11, 0x10, 0x01, 0x00, 0x19, 0x17, 0x10, 0x1f, 0x11, 0x1f, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, + 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, + 0x51, 0x80, 0x89, 0x31, 0x5e, 0x86, 0x54, 0x7a, 0x87, 0x2d, 0x59, 0x84, 0x54, 0x3c, 0x5e, 0x42, 0x23, 0x5a, 0x4e, 0x3c, 0x60, 0x44, 0x24, 0x5c, 0x0a, 0x95, + 0x80, 0x5c, 0xa6, 0x7f, 0x49, 0x96, 0x83, 0x5d, 0xa4, 0x7d, 0x48, 0x4f, 0x3c, 0x69, 0x88, 0x4c, 0x5f, 0x69, 0x3b, 0x67, 0x89, 0x4e, 0x5e, 0x6a, 0x00, 0x02, + 0x00, 0x29, 0x00, 0x00, 0x02, 0x37, 0x02, 0xca, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x30, 0x40, 0x2d, 0x06, 0x01, 0x03, 0x00, 0x01, 0x02, 0x03, 0x01, 0x69, 0x00, + 0x04, 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0c, 0x0b, 0x00, 0x00, 0x12, 0x10, 0x0b, 0x13, 0x0c, 0x13, + 0x00, 0x0a, 0x00, 0x0a, 0x24, 0x21, 0x07, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x23, 0x03, 0x13, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0xa1, 0x74, 0x62, 0xa0, 0x9a, 0x40, 0x3b, 0x89, 0x60, 0x71, 0x43, 0x44, 0x4c, 0x3c, 0x02, 0xca, 0x67, 0x53, 0x79, 0x80, + 0xfe, 0xe9, 0x01, 0x62, 0x53, 0x58, 0x3b, 0x35, 0xfe, 0xe5, 0x00, 0x02, 0x00, 0x48, 0xff, 0x56, 0x02, 0xb2, 0x02, 0xd5, 0x00, 0x14, 0x00, 0x24, 0x00, 0x32, + 0x40, 0x2f, 0x12, 0x01, 0x00, 0x03, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x02, 0x86, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x03, + 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x16, 0x15, 0x1e, 0x1c, 0x15, 0x24, 0x16, 0x24, 0x17, 0x26, 0x22, 0x06, 0x0d, 0x19, 0x2b, 0x05, 0x06, + 0x22, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x17, 0x23, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, + 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x61, 0x04, 0x08, 0x04, 0x80, 0x89, 0x31, 0x5e, 0x86, 0x54, 0x7a, 0x87, 0x3a, 0x6f, 0x50, 0x86, 0x72, 0x79, 0x3d, + 0x5f, 0x41, 0x22, 0x5a, 0x4e, 0x3c, 0x60, 0x44, 0x24, 0x5c, 0x09, 0x01, 0x95, 0x80, 0x5c, 0xa6, 0x7f, 0x49, 0x96, 0x83, 0x67, 0xb3, 0x80, 0x1b, 0xb1, 0xef, + 0x3c, 0x69, 0x88, 0x4c, 0x5f, 0x69, 0x3b, 0x67, 0x89, 0x4e, 0x5e, 0x6a, 0x00, 0x02, 0x00, 0x29, 0x00, 0x00, 0x02, 0x39, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x15, + 0x00, 0x38, 0x40, 0x35, 0x07, 0x01, 0x02, 0x04, 0x01, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, 0x67, 0x00, 0x05, 0x05, 0x00, 0x5f, 0x00, 0x00, + 0x00, 0x6a, 0x4d, 0x06, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x0e, 0x0d, 0x00, 0x00, 0x14, 0x12, 0x0d, 0x15, 0x0e, 0x15, 0x00, 0x0c, 0x00, 0x0c, 0x11, + 0x15, 0x21, 0x08, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x15, 0x14, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x03, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, + 0x23, 0x03, 0x29, 0x97, 0x9d, 0xdc, 0x51, 0x61, 0x76, 0x62, 0x66, 0x75, 0x3e, 0x9c, 0x64, 0x5b, 0x44, 0x44, 0x4c, 0x39, 0x02, 0xca, 0xb5, 0x4d, 0x72, 0x1b, + 0xfe, 0xc5, 0x01, 0x27, 0xfe, 0xd9, 0x01, 0x73, 0x57, 0x45, 0x3d, 0x30, 0xfe, 0xf7, 0x00, 0x01, 0x00, 0x13, 0xff, 0xf6, 0x02, 0x07, 0x02, 0xd4, 0x00, 0x2a, + 0x00, 0x37, 0x40, 0x34, 0x19, 0x01, 0x03, 0x02, 0x1a, 0x04, 0x02, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, + 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1e, 0x1c, 0x17, 0x15, 0x08, 0x06, 0x00, 0x2a, 0x01, + 0x2a, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x15, 0x14, 0x06, 0xb9, 0x34, 0x4f, 0x23, 0x1e, 0x53, + 0x36, 0x2d, 0x4c, 0x2e, 0x35, 0x41, 0x26, 0x3b, 0x21, 0x40, 0x6b, 0x40, 0x38, 0x55, 0x26, 0x22, 0x1a, 0x4e, 0x29, 0x3d, 0x4f, 0x16, 0x2e, 0x22, 0x2b, 0x41, + 0x25, 0x8f, 0x0a, 0x10, 0x10, 0x58, 0x10, 0x1a, 0x1c, 0x3a, 0x2e, 0x28, 0x39, 0x25, 0x17, 0x31, 0x41, 0x2e, 0x42, 0x5d, 0x30, 0x16, 0x14, 0x4c, 0x0e, 0x19, + 0x40, 0x3a, 0x1e, 0x29, 0x21, 0x15, 0x1a, 0x32, 0x42, 0x31, 0x6b, 0x6e, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0x4d, 0x02, 0xca, 0x00, 0x07, 0x00, 0x21, + 0x40, 0x1e, 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, + 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x23, 0x37, 0x21, 0x07, 0x23, 0x03, 0x98, 0x86, 0xc4, 0x11, 0x01, 0xe2, 0x10, 0xc4, 0x87, 0x02, 0x7b, + 0x4f, 0x4f, 0xfd, 0x85, 0x00, 0x01, 0x00, 0x4f, 0xff, 0xf6, 0x02, 0xb0, 0x02, 0xca, 0x00, 0x18, 0x00, 0x24, 0x40, 0x21, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, + 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x14, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x00, 0x18, 0x01, 0x18, 0x05, 0x0d, + 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x0e, 0x02, + 0x01, 0x2c, 0x70, 0x6d, 0x06, 0x06, 0x5c, 0x59, 0x5d, 0x05, 0x06, 0x45, 0x44, 0x59, 0x57, 0x13, 0x63, 0x59, 0x64, 0x10, 0x45, 0x74, 0x0a, 0x67, 0x5f, 0x11, + 0x32, 0x1c, 0x01, 0xaf, 0xfe, 0x4c, 0x17, 0x32, 0x10, 0x38, 0x40, 0x5c, 0x59, 0x01, 0xd0, 0xfe, 0x29, 0x4e, 0x72, 0x3d, 0x00, 0x01, 0x00, 0x5c, 0x00, 0x00, + 0x02, 0x84, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, + 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x16, 0x07, 0x33, 0x36, 0x36, 0x37, + 0x13, 0x33, 0x01, 0xa9, 0x4d, 0x58, 0x2d, 0x05, 0x05, 0x01, 0x02, 0x0f, 0x26, 0x18, 0xe8, 0x63, 0xfe, 0x84, 0x02, 0xca, 0xfe, 0x3c, 0x29, 0x54, 0x24, 0x24, + 0x4f, 0x2f, 0x01, 0xc3, 0xfd, 0x36, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x00, 0x03, 0xaf, 0x02, 0xca, 0x00, 0x21, 0x00, 0x27, 0x40, 0x24, 0x1c, 0x10, 0x06, 0x03, + 0x03, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x02, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x21, 0x11, + 0x19, 0x19, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x13, 0x16, 0x16, 0x07, 0x33, 0x36, + 0x36, 0x37, 0x13, 0x33, 0x01, 0x23, 0x03, 0x26, 0x26, 0x35, 0x23, 0x06, 0x06, 0x07, 0x03, 0x89, 0x1e, 0x58, 0x0e, 0x02, 0x04, 0x02, 0x03, 0x0e, 0x28, 0x15, + 0xc4, 0x5b, 0x14, 0x03, 0x02, 0x01, 0x03, 0x0e, 0x1f, 0x13, 0xbb, 0x5f, 0xfe, 0xbc, 0x5b, 0x16, 0x02, 0x02, 0x03, 0x0a, 0x1a, 0x17, 0xd3, 0x02, 0xca, 0xfe, + 0x4d, 0x29, 0x58, 0x28, 0x27, 0x65, 0x2c, 0x01, 0xa4, 0xfe, 0x5e, 0x2f, 0x66, 0x25, 0x26, 0x5a, 0x2c, 0x01, 0xb0, 0xfd, 0x36, 0x01, 0xcc, 0x21, 0x4b, 0x1f, + 0x1e, 0x3e, 0x32, 0xfe, 0x37, 0x00, 0x00, 0x01, 0xff, 0xcc, 0x00, 0x00, 0x02, 0x61, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, + 0x04, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x12, + 0x12, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x03, 0x33, 0x13, 0x13, 0x33, 0x01, 0x13, 0x23, 0x03, 0x03, 0x34, 0x01, 0x23, 0x7f, 0x5a, 0x61, 0xd4, 0x62, + 0xfe, 0xf2, 0x87, 0x5e, 0x66, 0xe8, 0x01, 0x7a, 0x01, 0x50, 0xfe, 0xef, 0x01, 0x11, 0xfe, 0xac, 0xfe, 0x8a, 0x01, 0x35, 0xfe, 0xcb, 0x00, 0x01, 0x00, 0x5c, + 0x00, 0x00, 0x02, 0x59, 0x02, 0xca, 0x00, 0x08, 0x00, 0x22, 0x40, 0x1f, 0x04, 0x01, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x03, + 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x12, 0x12, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x03, 0x33, 0x13, 0x13, 0x33, 0x01, + 0x03, 0x96, 0x3a, 0x74, 0x59, 0x55, 0xea, 0x65, 0xfe, 0xce, 0x37, 0x01, 0x0c, 0x01, 0xbe, 0xfe, 0x9a, 0x01, 0x66, 0xfe, 0x3f, 0xfe, 0xf7, 0x00, 0x00, 0x01, + 0xff, 0xf6, 0x00, 0x00, 0x02, 0x3d, 0x02, 0xca, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, + 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x01, + 0x21, 0x37, 0x21, 0x07, 0x01, 0x21, 0x07, 0x0a, 0x0e, 0x01, 0xbd, 0xfe, 0xc5, 0x11, 0x01, 0xa6, 0x0d, 0xfe, 0x43, 0x01, 0x4f, 0x10, 0x46, 0x02, 0x34, 0x50, + 0x47, 0xfd, 0xcd, 0x50, 0x00, 0x01, 0xff, 0xf7, 0xff, 0x62, 0x01, 0x72, 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x02, 0x04, 0x01, 0x03, 0x02, + 0x03, 0x63, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, + 0x07, 0x13, 0x33, 0x07, 0x23, 0x03, 0x33, 0x07, 0x09, 0xba, 0xc1, 0x10, 0x6e, 0x9a, 0x6e, 0x10, 0x9e, 0x03, 0x68, 0x48, 0xfd, 0x28, 0x48, 0x00, 0x00, 0x01, + 0x00, 0x6c, 0x00, 0x00, 0x01, 0x26, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x33, 0x03, 0x33, 0x13, 0xd6, 0x6a, 0x50, 0x6a, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x00, 0x01, + 0xff, 0xb8, 0xff, 0x62, 0x01, 0x32, 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x00, 0x04, 0x01, 0x03, 0x00, 0x03, 0x63, 0x00, 0x01, 0x01, 0x02, + 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x07, 0x37, 0x33, 0x13, 0x23, 0x37, + 0x33, 0x03, 0x48, 0x0f, 0x6e, 0x9a, 0x6e, 0x10, 0xc1, 0xba, 0x9e, 0x48, 0x02, 0xd8, 0x48, 0xfc, 0x98, 0x00, 0x00, 0x01, 0x00, 0x26, 0x01, 0x0b, 0x02, 0x16, + 0x02, 0xcf, 0x00, 0x06, 0x00, 0x27, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x03, 0x02, 0x02, + 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x13, 0x13, 0x33, 0x13, 0x23, 0x03, 0x03, + 0x26, 0xd4, 0x32, 0xea, 0x4e, 0xb4, 0xa0, 0x01, 0x0b, 0x01, 0xc4, 0xfe, 0x3c, 0x01, 0x67, 0xfe, 0x99, 0x00, 0x00, 0x01, 0xff, 0xa4, 0xff, 0x62, 0x01, 0x40, + 0xff, 0xa6, 0x00, 0x03, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, + 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x07, 0x37, 0x21, 0x07, 0x5c, 0x0f, 0x01, 0x8d, + 0x0f, 0x9e, 0x44, 0x44, 0x00, 0x01, 0x00, 0x92, 0x02, 0x5e, 0x01, 0x36, 0x02, 0xfe, 0x00, 0x0a, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x09, 0x04, + 0x02, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x15, 0x03, 0x0d, 0x17, 0x2b, + 0xb1, 0x06, 0x00, 0x44, 0x01, 0x2e, 0x02, 0x27, 0x35, 0x33, 0x16, 0x16, 0x17, 0x15, 0x01, 0x00, 0x13, 0x2b, 0x26, 0x0a, 0x5e, 0x0b, 0x27, 0x14, 0x02, 0x5e, + 0x13, 0x36, 0x38, 0x15, 0x0a, 0x25, 0x4d, 0x22, 0x0c, 0x00, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf6, 0x02, 0x26, 0x02, 0x22, 0x00, 0x14, 0x00, 0x26, 0x00, 0x67, + 0xb6, 0x11, 0x0b, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x19, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, + 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, + 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, + 0x17, 0x16, 0x15, 0x01, 0x00, 0x20, 0x1e, 0x15, 0x26, 0x16, 0x26, 0x10, 0x0f, 0x0e, 0x0d, 0x09, 0x07, 0x00, 0x14, 0x01, 0x14, 0x08, 0x0d, 0x16, 0x2b, 0x17, + 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0x27, 0x32, 0x36, 0x36, 0x37, 0x36, 0x36, + 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0xc1, 0x40, 0x51, 0x27, 0x46, 0x60, 0x3a, 0x35, 0x42, 0x10, 0x05, 0x20, 0x43, 0x72, 0x46, 0x0d, + 0x04, 0x22, 0x5c, 0x1b, 0x25, 0x47, 0x3a, 0x0f, 0x08, 0x05, 0x34, 0x2c, 0x27, 0x42, 0x32, 0x1b, 0x2c, 0x0a, 0x5d, 0x5a, 0x4b, 0x87, 0x67, 0x3c, 0x38, 0x25, + 0x53, 0xfd, 0xe8, 0x63, 0x2c, 0x41, 0x49, 0x36, 0x5c, 0x39, 0x1d, 0x31, 0x15, 0x2f, 0x3c, 0x31, 0x55, 0x6c, 0x3b, 0x36, 0x36, 0x00, 0x00, 0x02, 0x00, 0x1c, + 0xff, 0xf6, 0x02, 0x12, 0x02, 0xf8, 0x00, 0x18, 0x00, 0x27, 0x00, 0x94, 0xb5, 0x03, 0x01, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, + 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x62, 0x01, 0x06, 0x02, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, + 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x62, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x03, 0x02, 0x85, + 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x62, 0x06, 0x01, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x59, 0x59, 0x40, 0x17, 0x1a, 0x19, 0x01, 0x00, 0x21, 0x1f, 0x19, 0x27, 0x1a, 0x27, 0x12, 0x10, 0x08, 0x07, 0x06, 0x05, 0x00, 0x18, 0x01, 0x18, + 0x08, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x27, 0x23, 0x07, 0x23, 0x13, 0x33, 0x07, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, + 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x0d, 0x36, 0x43, 0x10, 0x05, 0x21, 0x42, 0xa1, 0x58, 0x26, 0x07, + 0x11, 0x0c, 0x01, 0x04, 0x24, 0x55, 0x38, 0x42, 0x51, 0x24, 0x44, 0x60, 0x44, 0x28, 0x42, 0x2f, 0x19, 0x55, 0x21, 0x45, 0x3a, 0x23, 0x32, 0x0a, 0x37, 0x25, + 0x52, 0x02, 0xf8, 0xb4, 0x22, 0x41, 0x2b, 0x02, 0x2c, 0x41, 0x5c, 0x5a, 0x49, 0x86, 0x69, 0x3d, 0x49, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x31, 0x55, 0x6c, 0x3b, + 0x30, 0x3c, 0x00, 0x01, 0x00, 0x30, 0xff, 0xf6, 0x01, 0xcd, 0x02, 0x22, 0x00, 0x1c, 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, 0x02, 0x01, 0x19, 0x0c, 0x02, 0x03, + 0x02, 0x1a, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x01, 0x00, 0x17, 0x15, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1c, 0x01, 0x1c, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0xf7, 0x59, 0x6e, 0x27, 0x49, + 0x68, 0x40, 0x23, 0x46, 0x1c, 0x19, 0x14, 0x37, 0x20, 0x39, 0x56, 0x30, 0x3f, 0x37, 0x23, 0x3f, 0x1f, 0x1c, 0x45, 0x0a, 0x64, 0x64, 0x48, 0x81, 0x62, 0x39, + 0x0e, 0x0c, 0x49, 0x09, 0x10, 0x4d, 0x80, 0x4c, 0x3d, 0x43, 0x14, 0x0d, 0x4a, 0x0e, 0x12, 0x00, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf6, 0x02, 0x55, 0x02, 0xf8, + 0x00, 0x17, 0x00, 0x26, 0x00, 0x95, 0xb6, 0x14, 0x0b, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, + 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x4b, + 0xb0, 0x29, 0x50, 0x58, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, + 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x01, 0x02, 0x85, 0x00, 0x05, 0x05, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x59, 0x40, + 0x17, 0x19, 0x18, 0x01, 0x00, 0x21, 0x1f, 0x18, 0x26, 0x19, 0x26, 0x13, 0x12, 0x11, 0x10, 0x09, 0x07, 0x00, 0x17, 0x01, 0x17, 0x08, 0x0d, 0x16, 0x2b, 0x17, + 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0x27, 0x32, 0x3e, 0x02, + 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xc1, 0x40, 0x51, 0x24, 0x45, 0x61, 0x3d, 0x36, 0x41, 0x10, 0x05, 0x05, 0x09, 0x08, 0x25, 0x57, 0xa1, + 0x48, 0x0b, 0x04, 0x24, 0x56, 0x1a, 0x21, 0x44, 0x3a, 0x23, 0x2f, 0x35, 0x28, 0x41, 0x30, 0x1a, 0x0a, 0x5c, 0x5b, 0x4a, 0x85, 0x69, 0x3c, 0x37, 0x25, 0x22, + 0x3e, 0x24, 0xaf, 0xfd, 0x08, 0x63, 0x2d, 0x40, 0x49, 0x31, 0x54, 0x6c, 0x3c, 0x30, 0x3c, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf6, + 0x01, 0xd5, 0x02, 0x22, 0x00, 0x1c, 0x00, 0x27, 0x00, 0x43, 0x40, 0x40, 0x19, 0x01, 0x03, 0x02, 0x1a, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x07, 0x01, 0x04, 0x00, + 0x02, 0x03, 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, + 0x4e, 0x1e, 0x1d, 0x01, 0x00, 0x25, 0x23, 0x1d, 0x27, 0x1e, 0x27, 0x17, 0x15, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1c, 0x01, 0x1c, 0x08, 0x0d, 0x16, 0x2b, 0x17, + 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x23, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, + 0x06, 0x03, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0xf2, 0x5d, 0x65, 0x25, 0x46, 0x63, 0x3e, 0x4c, 0x4d, 0x41, 0x8a, 0x6e, 0x11, 0x01, + 0x01, 0x3c, 0x3d, 0x26, 0x44, 0x28, 0x26, 0x49, 0x86, 0x3c, 0x66, 0x3e, 0x23, 0x25, 0x30, 0x59, 0x16, 0x0a, 0x6d, 0x5d, 0x40, 0x7d, 0x67, 0x3e, 0x42, 0x3b, + 0x34, 0x56, 0x33, 0x09, 0x14, 0x08, 0x3d, 0x47, 0x16, 0x13, 0x4b, 0x11, 0x16, 0x01, 0x39, 0x15, 0x31, 0x29, 0x1a, 0x21, 0x59, 0x51, 0x00, 0x01, 0xff, 0x90, + 0xff, 0x10, 0x01, 0xbb, 0x02, 0xfd, 0x00, 0x24, 0x00, 0x77, 0x40, 0x12, 0x16, 0x01, 0x04, 0x03, 0x17, 0x01, 0x05, 0x04, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, + 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x21, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, 0x02, 0x02, 0x05, + 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x1f, 0x00, 0x03, 0x00, 0x04, 0x05, + 0x03, 0x04, 0x69, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, + 0x59, 0x40, 0x15, 0x01, 0x00, 0x21, 0x20, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x24, 0x01, 0x24, 0x08, 0x0d, 0x16, 0x2b, 0x07, + 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, + 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x24, 0x28, 0x0c, 0x6e, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, + 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0x73, 0x0d, 0x73, 0x70, 0x12, 0x4c, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x3b, 0x37, + 0x02, 0x0a, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, 0x5e, 0x00, 0x00, 0x02, 0x00, 0x19, + 0xff, 0x10, 0x02, 0x27, 0x02, 0x22, 0x00, 0x23, 0x00, 0x32, 0x00, 0x80, 0x40, 0x0f, 0x1d, 0x0e, 0x02, 0x05, 0x06, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x00, 0x06, 0x06, 0x03, 0x61, 0x04, 0x01, 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, + 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x04, 0x04, 0x6d, 0x4d, + 0x00, 0x06, 0x06, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, + 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, 0x19, 0x25, 0x24, 0x01, 0x00, 0x2d, 0x2b, 0x24, 0x32, 0x25, 0x32, 0x20, 0x1f, 0x1b, 0x19, 0x13, 0x11, + 0x08, 0x06, 0x00, 0x23, 0x01, 0x23, 0x09, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, 0x37, 0x23, + 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x06, 0x06, 0x03, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, + 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xba, 0x31, 0x53, 0x1d, 0x1a, 0x59, 0x2b, 0x3e, 0x50, 0x10, 0x09, 0x05, 0x0f, 0x05, 0x04, 0x22, 0x57, 0x38, 0x41, 0x51, + 0x24, 0x45, 0x61, 0x3d, 0x36, 0x42, 0x10, 0x04, 0x21, 0x43, 0x7a, 0x18, 0x7b, 0x3b, 0x22, 0x44, 0x39, 0x22, 0x2d, 0x35, 0x28, 0x42, 0x30, 0x1a, 0xf0, 0x13, + 0x0f, 0x51, 0x10, 0x1a, 0x3c, 0x46, 0x26, 0x17, 0x38, 0x13, 0x2c, 0x41, 0x5d, 0x5a, 0x49, 0x86, 0x69, 0x3d, 0x38, 0x25, 0x53, 0xfd, 0xc9, 0x71, 0x60, 0x01, + 0x2f, 0x32, 0x55, 0x6c, 0x3a, 0x30, 0x3c, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x02, 0x0b, 0x02, 0xf8, 0x00, 0x1e, 0x00, 0x50, + 0xb5, 0x06, 0x01, 0x02, 0x03, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x17, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x00, 0x01, 0x00, 0x85, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1e, 0x25, 0x16, 0x28, 0x11, 0x06, 0x0d, + 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x06, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x03, 0x23, 0x13, 0x36, 0x35, 0x34, 0x26, + 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x1c, 0xa1, 0x58, 0x2b, 0x06, 0x12, 0x08, 0x05, 0x13, 0x34, 0x43, 0x2b, 0x3e, 0x49, 0x06, 0x05, 0x46, 0x58, 0x47, 0x09, + 0x21, 0x25, 0x22, 0x4f, 0x43, 0x13, 0x31, 0x02, 0xf8, 0xc5, 0x1e, 0x41, 0x20, 0x19, 0x32, 0x22, 0x45, 0x44, 0x13, 0x28, 0x17, 0xfe, 0xba, 0x01, 0x50, 0x2d, + 0x15, 0x21, 0x25, 0x2f, 0x6a, 0x58, 0xe7, 0x00, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x0e, 0x02, 0xe0, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x4d, 0x4b, 0xb0, + 0x2d, 0x50, 0x58, 0x40, 0x17, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6b, + 0x03, 0x4e, 0x1b, 0x40, 0x15, 0x00, 0x01, 0x04, 0x01, 0x00, 0x02, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, + 0x59, 0x40, 0x13, 0x0b, 0x0b, 0x01, 0x00, 0x0b, 0x0e, 0x0b, 0x0e, 0x0d, 0x0c, 0x07, 0x05, 0x00, 0x0a, 0x01, 0x0a, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, + 0x35, 0x34, 0x36, 0x33, 0x32, 0x15, 0x14, 0x06, 0x03, 0x13, 0x33, 0x03, 0xd5, 0x15, 0x1b, 0x1f, 0x1c, 0x2e, 0x24, 0xce, 0x72, 0x58, 0x72, 0x02, 0x71, 0x19, + 0x16, 0x1a, 0x26, 0x2d, 0x1f, 0x23, 0xfd, 0x8f, 0x02, 0x18, 0xfd, 0xe8, 0x00, 0x02, 0xff, 0x82, 0xff, 0x10, 0x01, 0x0d, 0x02, 0xe0, 0x00, 0x0a, 0x00, 0x18, + 0x00, 0x65, 0x40, 0x0a, 0x0e, 0x01, 0x03, 0x04, 0x0d, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x1c, 0x05, 0x01, 0x00, 0x00, 0x01, + 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x06, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x1a, + 0x00, 0x01, 0x05, 0x01, 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x06, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, + 0x59, 0x40, 0x15, 0x0c, 0x0b, 0x01, 0x00, 0x15, 0x14, 0x12, 0x10, 0x0b, 0x18, 0x0c, 0x18, 0x07, 0x05, 0x00, 0x0a, 0x01, 0x0a, 0x07, 0x0d, 0x16, 0x2b, 0x13, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x15, 0x14, 0x06, 0x01, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0xd4, 0x14, + 0x1b, 0x1f, 0x1c, 0x2d, 0x24, 0xfe, 0xd7, 0x25, 0x19, 0x0c, 0x1e, 0x10, 0x3d, 0x15, 0x80, 0x57, 0x82, 0x10, 0x49, 0x02, 0x71, 0x19, 0x16, 0x1a, 0x26, 0x2d, + 0x1f, 0x23, 0xfc, 0x9f, 0x0a, 0x4a, 0x04, 0x07, 0x62, 0x02, 0x5d, 0xfd, 0x9b, 0x4b, 0x58, 0x00, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x02, 0x0d, 0x02, 0xf8, + 0x00, 0x0f, 0x00, 0x47, 0xb7, 0x0d, 0x0a, 0x06, 0x03, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x12, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, + 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x12, 0x00, 0x00, 0x01, 0x00, 0x85, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x04, + 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x12, 0x16, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, + 0x03, 0x06, 0x06, 0x07, 0x33, 0x13, 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x07, 0x1b, 0xa1, 0x59, 0x41, 0x11, 0x19, 0x05, 0x02, 0xfe, 0x68, 0xe6, 0x8f, 0x61, + 0x71, 0x48, 0x28, 0x02, 0xf8, 0xfe, 0xd2, 0x50, 0x57, 0x0e, 0x01, 0x03, 0xe6, 0xfe, 0xce, 0xfb, 0x39, 0xc2, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x15, + 0x02, 0xf8, 0x00, 0x03, 0x00, 0x30, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, + 0x40, 0x0c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, + 0x17, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x1b, 0xa2, 0x58, 0xa2, 0x02, 0xf8, 0xfd, 0x08, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x03, 0x33, 0x02, 0x22, 0x00, 0x30, + 0x00, 0x56, 0xb6, 0x0b, 0x03, 0x02, 0x03, 0x04, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x02, 0x01, 0x02, + 0x00, 0x00, 0x6d, 0x4d, 0x08, 0x07, 0x05, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x1a, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x01, + 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x08, 0x07, 0x05, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x59, 0x40, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x25, + 0x14, 0x26, 0x16, 0x26, 0x25, 0x11, 0x09, 0x0d, 0x1d, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x3e, 0x02, 0x33, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x07, 0x03, 0x23, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x23, 0x13, 0x36, 0x35, 0x34, 0x26, 0x23, + 0x22, 0x06, 0x06, 0x07, 0x07, 0x1c, 0x72, 0x48, 0x0b, 0x05, 0x12, 0x31, 0x41, 0x29, 0x37, 0x3b, 0x06, 0x04, 0x14, 0x37, 0x44, 0x29, 0x3e, 0x44, 0x06, 0x05, + 0x45, 0x59, 0x48, 0x05, 0x04, 0x21, 0x23, 0x20, 0x49, 0x3f, 0x11, 0x33, 0x58, 0x47, 0x09, 0x1e, 0x23, 0x20, 0x4a, 0x40, 0x13, 0x31, 0x02, 0x18, 0x63, 0x19, + 0x32, 0x22, 0x3f, 0x38, 0x1e, 0x36, 0x23, 0x44, 0x40, 0x18, 0x29, 0x17, 0xfe, 0xba, 0x01, 0x50, 0x17, 0x20, 0x0f, 0x1e, 0x24, 0x30, 0x65, 0x51, 0xf2, 0x01, + 0x50, 0x2d, 0x15, 0x21, 0x25, 0x2f, 0x6a, 0x58, 0xe7, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x02, 0x0e, 0x02, 0x25, 0x00, 0x1b, 0x00, 0x4c, 0xb5, 0x03, + 0x01, 0x02, 0x03, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x00, 0x03, 0x03, 0x00, 0x61, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, + 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, + 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x1b, 0x25, 0x16, 0x25, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x07, + 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x03, 0x23, 0x13, 0x36, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x18, 0x73, 0x4e, + 0x0b, 0x01, 0x13, 0x33, 0x44, 0x2b, 0x41, 0x49, 0x07, 0x04, 0x47, 0x5e, 0x48, 0x05, 0x05, 0x44, 0x21, 0x4d, 0x43, 0x13, 0x32, 0x02, 0x1b, 0x63, 0x19, 0x32, + 0x22, 0x47, 0x40, 0x17, 0x30, 0x12, 0xfe, 0xbb, 0x01, 0x51, 0x17, 0x1f, 0x0e, 0x40, 0x2e, 0x68, 0x58, 0xe7, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf8, 0x02, 0x04, + 0x02, 0x1f, 0x00, 0x0f, 0x00, 0x1e, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, + 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x11, 0x10, 0x01, 0x00, 0x19, 0x17, 0x10, 0x1e, 0x11, 0x1e, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, + 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x26, 0x23, 0x22, 0x06, + 0x06, 0x15, 0x14, 0x16, 0xf8, 0x5d, 0x6b, 0x22, 0x43, 0x65, 0x42, 0x5e, 0x6a, 0x22, 0x43, 0x64, 0x3e, 0x30, 0x4e, 0x2f, 0x15, 0x30, 0x28, 0x37, 0x51, 0x2c, + 0x3d, 0x08, 0x6f, 0x5f, 0x3e, 0x7a, 0x64, 0x3d, 0x6f, 0x60, 0x3d, 0x7a, 0x64, 0x3d, 0x49, 0x43, 0x7e, 0x58, 0x1e, 0x39, 0x25, 0x4b, 0x7d, 0x4b, 0x3e, 0x44, + 0x00, 0x02, 0xff, 0xea, 0xff, 0x10, 0x02, 0x12, 0x02, 0x21, 0x00, 0x17, 0x00, 0x26, 0x00, 0x68, 0xb6, 0x12, 0x03, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, + 0x1b, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, + 0x4d, 0x06, 0x01, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, + 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x14, 0x19, 0x18, 0x00, 0x00, 0x20, + 0x1e, 0x18, 0x26, 0x19, 0x26, 0x00, 0x17, 0x00, 0x17, 0x26, 0x24, 0x11, 0x08, 0x0d, 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x15, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x07, 0x13, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, + 0x16, 0xa4, 0x48, 0x0c, 0x04, 0x23, 0x58, 0x38, 0x41, 0x50, 0x24, 0x44, 0x61, 0x3c, 0x36, 0x42, 0x11, 0x05, 0x01, 0x08, 0x04, 0x31, 0xc5, 0x28, 0x42, 0x2f, + 0x19, 0x55, 0x21, 0x45, 0x3a, 0x23, 0x32, 0xf0, 0x03, 0x08, 0x64, 0x2c, 0x41, 0x5c, 0x5b, 0x49, 0x86, 0x69, 0x3c, 0x37, 0x25, 0x10, 0x39, 0x12, 0xe7, 0x01, + 0x2f, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x31, 0x54, 0x6c, 0x3c, 0x30, 0x3c, 0x00, 0x02, 0x00, 0x30, 0xff, 0x10, 0x02, 0x26, 0x02, 0x22, 0x00, 0x17, 0x00, 0x26, + 0x00, 0x61, 0xb6, 0x12, 0x03, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, + 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x02, 0x02, 0x6d, + 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, + 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x19, 0x18, 0x21, 0x1f, 0x18, 0x26, 0x19, 0x26, 0x11, 0x14, 0x26, 0x26, 0x07, 0x0d, 0x1a, 0x2b, 0x05, 0x36, 0x36, 0x37, 0x23, + 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x03, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, + 0x22, 0x0e, 0x02, 0x15, 0x14, 0x01, 0x5a, 0x05, 0x11, 0x07, 0x04, 0x22, 0x57, 0x38, 0x41, 0x51, 0x24, 0x45, 0x62, 0x3d, 0x35, 0x41, 0x10, 0x05, 0x21, 0x42, + 0xa5, 0x57, 0x4b, 0x21, 0x44, 0x39, 0x23, 0x2e, 0x34, 0x28, 0x42, 0x30, 0x1a, 0x0c, 0x13, 0x43, 0x19, 0x2c, 0x41, 0x5c, 0x5b, 0x49, 0x86, 0x69, 0x3d, 0x38, + 0x25, 0x53, 0xfc, 0xf8, 0x01, 0x2f, 0x32, 0x55, 0x6c, 0x3a, 0x2c, 0x40, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x01, 0xad, + 0x02, 0x22, 0x00, 0x13, 0x00, 0x63, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0b, 0x0c, 0x03, 0x02, 0x03, 0x02, 0x01, 0x4c, 0x0b, 0x01, 0x00, 0x4a, 0x1b, 0x40, + 0x0b, 0x0b, 0x01, 0x00, 0x01, 0x0c, 0x03, 0x02, 0x03, 0x02, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x02, 0x02, 0x00, 0x61, 0x01, + 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x73, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x59, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x13, 0x00, 0x13, 0x24, 0x25, 0x11, 0x05, 0x0d, 0x19, + 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x1c, 0x72, 0x48, 0x0b, 0x05, 0x15, + 0x2e, 0x3a, 0x26, 0x0e, 0x1f, 0x0d, 0x13, 0x1b, 0x18, 0x32, 0x4e, 0x34, 0x0b, 0x34, 0x02, 0x18, 0x63, 0x1c, 0x31, 0x20, 0x03, 0x04, 0x4f, 0x06, 0x42, 0x66, + 0x35, 0xf5, 0x00, 0x01, 0x00, 0x05, 0xff, 0xf6, 0x01, 0x9c, 0x02, 0x22, 0x00, 0x26, 0x00, 0x37, 0x40, 0x34, 0x16, 0x01, 0x03, 0x02, 0x17, 0x04, 0x02, 0x01, + 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1b, 0x19, 0x14, 0x12, 0x08, 0x06, 0x00, 0x26, 0x01, 0x26, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, + 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, + 0x1e, 0x02, 0x15, 0x14, 0x06, 0x9b, 0x31, 0x49, 0x1c, 0x1a, 0x4f, 0x2a, 0x3b, 0x3e, 0x26, 0x34, 0x39, 0x3a, 0x63, 0x53, 0x31, 0x53, 0x1e, 0x1c, 0x1a, 0x40, + 0x2c, 0x2b, 0x33, 0x23, 0x35, 0x22, 0x36, 0x1f, 0x71, 0x0a, 0x13, 0x0f, 0x51, 0x10, 0x1b, 0x2f, 0x25, 0x1d, 0x27, 0x1d, 0x20, 0x44, 0x33, 0x44, 0x54, 0x17, + 0x0e, 0x46, 0x0c, 0x15, 0x29, 0x20, 0x1a, 0x27, 0x1d, 0x14, 0x28, 0x34, 0x26, 0x51, 0x54, 0x00, 0x00, 0x01, 0x00, 0x2c, 0xff, 0xf6, 0x01, 0x6c, 0x02, 0x92, + 0x00, 0x1c, 0x00, 0x66, 0x40, 0x0a, 0x19, 0x01, 0x05, 0x01, 0x1a, 0x01, 0x00, 0x05, 0x02, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x03, + 0x03, 0x02, 0x70, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x1b, 0x40, 0x1c, 0x00, 0x02, 0x03, 0x02, 0x85, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x13, 0x01, 0x00, 0x17, 0x15, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x07, 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x07, 0x0d, + 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x33, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x15, 0x06, 0x06, 0xb9, 0x36, 0x4a, 0x09, 0x3d, 0x53, 0x08, 0x5a, 0x3e, 0x34, 0x1b, 0x87, 0x0e, 0x86, 0x3e, 0x03, 0x06, 0x19, 0x1c, 0x12, 0x22, 0x13, + 0x0c, 0x32, 0x0a, 0x34, 0x41, 0x20, 0x27, 0x01, 0x23, 0x28, 0x26, 0x6f, 0x7a, 0x43, 0xfe, 0xdc, 0x0d, 0x21, 0x0e, 0x17, 0x20, 0x07, 0x06, 0x43, 0x06, 0x0c, + 0x00, 0x01, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x26, 0x02, 0x18, 0x00, 0x1b, 0x00, 0x50, 0xb5, 0x17, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x13, 0x03, 0x01, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x05, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x17, 0x03, 0x01, + 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x04, 0x04, 0x6b, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x05, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, + 0x16, 0x15, 0x14, 0x13, 0x0f, 0x0d, 0x08, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, + 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x0e, 0x02, 0xbd, 0x3d, 0x49, 0x07, 0x04, 0x46, 0x59, 0x48, 0x09, + 0x21, 0x25, 0x22, 0x4f, 0x44, 0x13, 0x31, 0x57, 0x72, 0x48, 0x0b, 0x05, 0x13, 0x33, 0x43, 0x0a, 0x44, 0x41, 0x17, 0x29, 0x16, 0x01, 0x47, 0xfe, 0xaf, 0x2b, + 0x18, 0x20, 0x25, 0x30, 0x6a, 0x58, 0xe7, 0xfd, 0xe8, 0x63, 0x18, 0x33, 0x22, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x00, 0x02, 0x03, 0x02, 0x18, 0x00, 0x0f, + 0x00, 0x21, 0x40, 0x1e, 0x07, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x0f, 0x1b, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x15, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x01, 0x6e, 0x3e, 0x58, + 0x1e, 0x03, 0x05, 0x03, 0x03, 0x0b, 0x1e, 0x1f, 0x0b, 0x9e, 0x5e, 0xfe, 0xde, 0x02, 0x18, 0xfe, 0xd6, 0x1a, 0x46, 0x3d, 0x0e, 0x19, 0x40, 0x40, 0x15, 0x01, + 0x27, 0xfd, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x39, 0x00, 0x00, 0x02, 0xf9, 0x02, 0x18, 0x00, 0x22, 0x00, 0x27, 0x40, 0x24, 0x1d, 0x11, 0x06, 0x03, 0x03, 0x00, + 0x01, 0x4c, 0x02, 0x01, 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x22, 0x11, 0x19, 0x1a, + 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x13, 0x16, 0x16, 0x07, 0x33, 0x36, 0x36, 0x37, + 0x13, 0x33, 0x03, 0x23, 0x03, 0x26, 0x36, 0x35, 0x23, 0x06, 0x06, 0x07, 0x03, 0x4f, 0x16, 0x56, 0x08, 0x02, 0x04, 0x02, 0x04, 0x08, 0x16, 0x19, 0x0a, 0x8d, + 0x5f, 0x11, 0x01, 0x02, 0x02, 0x04, 0x0d, 0x28, 0x18, 0x75, 0x5d, 0xf8, 0x6a, 0x0f, 0x02, 0x01, 0x04, 0x0d, 0x1b, 0x18, 0x8c, 0x02, 0x18, 0xfe, 0xe2, 0x37, + 0x59, 0x1d, 0x15, 0x39, 0x39, 0x15, 0x01, 0x2f, 0xfe, 0xe1, 0x25, 0x61, 0x26, 0x26, 0x67, 0x37, 0x01, 0x07, 0xfd, 0xe8, 0x01, 0x22, 0x28, 0x4a, 0x2f, 0x25, + 0x3f, 0x33, 0xfe, 0xd4, 0x00, 0x01, 0xff, 0xdb, 0x00, 0x00, 0x01, 0xfe, 0x02, 0x18, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, 0x04, 0x02, + 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x12, 0x12, 0x12, + 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x25, 0xe8, 0x74, 0x59, 0x53, 0x9d, 0x66, 0xdf, 0x7b, 0x59, + 0x5b, 0xa5, 0x01, 0x14, 0x01, 0x04, 0xc6, 0xc6, 0xfe, 0xf8, 0xfe, 0xf0, 0xd0, 0xd0, 0x00, 0x01, 0xff, 0xa2, 0xff, 0x10, 0x02, 0x03, 0x02, 0x18, 0x00, 0x1c, + 0x00, 0x30, 0x40, 0x2d, 0x12, 0x0b, 0x04, 0x03, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, + 0x61, 0x04, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x01, 0x00, 0x19, 0x18, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x05, 0x0d, 0x16, 0x2b, 0x07, 0x22, + 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x15, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x01, 0x06, 0x06, 0x19, + 0x18, 0x1f, 0x0e, 0x0e, 0x20, 0x12, 0x29, 0x39, 0x1a, 0x23, 0x51, 0x58, 0x23, 0x05, 0x05, 0x03, 0x03, 0x07, 0x1b, 0x20, 0x0c, 0x9c, 0x5e, 0xfe, 0xac, 0x28, + 0x59, 0xf0, 0x06, 0x04, 0x47, 0x04, 0x05, 0x32, 0x30, 0x3e, 0x02, 0x20, 0xfe, 0xf7, 0x20, 0x4d, 0x45, 0x15, 0x10, 0x40, 0x44, 0x16, 0x01, 0x26, 0xfd, 0x8e, + 0x4b, 0x4b, 0x00, 0x01, 0xff, 0xf1, 0x00, 0x00, 0x01, 0xb7, 0x02, 0x18, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, + 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, + 0x2b, 0x23, 0x37, 0x01, 0x23, 0x37, 0x21, 0x07, 0x01, 0x33, 0x07, 0x0f, 0x0c, 0x01, 0x4d, 0xe6, 0x0e, 0x01, 0x45, 0x0e, 0xfe, 0xb9, 0xff, 0x0d, 0x3c, 0x01, + 0x9a, 0x42, 0x47, 0xfe, 0x71, 0x42, 0x00, 0x01, 0x00, 0x0b, 0xff, 0x62, 0x01, 0x90, 0x02, 0xca, 0x00, 0x2c, 0x00, 0x37, 0x40, 0x34, 0x1d, 0x01, 0x01, 0x02, + 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, 0x05, 0x06, 0x01, 0x00, 0x05, 0x00, 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, + 0x6a, 0x04, 0x4e, 0x01, 0x00, 0x2b, 0x2a, 0x17, 0x16, 0x15, 0x13, 0x0e, 0x0d, 0x0c, 0x0b, 0x00, 0x2c, 0x01, 0x2c, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, + 0x35, 0x34, 0x36, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x23, 0x37, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, 0x33, 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x06, 0x06, + 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x15, 0xd9, 0x46, 0x4b, 0x06, 0x04, 0x18, 0x03, 0x04, 0x66, 0x11, + 0x3a, 0x46, 0x0a, 0x21, 0x11, 0x53, 0x53, 0x12, 0x0f, 0x2c, 0x32, 0x0b, 0x23, 0x0b, 0x39, 0x3b, 0x27, 0x24, 0x05, 0x04, 0x16, 0x03, 0x04, 0x29, 0x22, 0x9e, + 0x35, 0x39, 0x10, 0x21, 0x13, 0x69, 0x10, 0x1a, 0x0c, 0x46, 0x49, 0x2a, 0x33, 0x9d, 0x4f, 0x3f, 0x49, 0x1e, 0x2f, 0x9c, 0x33, 0x42, 0x0a, 0x02, 0x0a, 0x37, + 0x27, 0x0d, 0x22, 0x10, 0x66, 0x0d, 0x17, 0x0a, 0x1d, 0x14, 0x49, 0x00, 0x00, 0x01, 0x01, 0x04, 0xff, 0x0f, 0x01, 0x4c, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x30, + 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x1b, 0x40, 0x0c, 0x00, 0x00, 0x01, 0x00, + 0x85, 0x02, 0x01, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x59, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x05, 0x11, 0x33, 0x11, + 0x01, 0x04, 0x48, 0xf1, 0x03, 0xe9, 0xfc, 0x17, 0x00, 0x01, 0xff, 0xdb, 0xff, 0x62, 0x01, 0x59, 0x02, 0xca, 0x00, 0x2d, 0x00, 0x31, 0x40, 0x2e, 0x07, 0x01, + 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, + 0x02, 0x6a, 0x01, 0x4e, 0x2c, 0x2b, 0x25, 0x24, 0x23, 0x22, 0x18, 0x16, 0x15, 0x14, 0x10, 0x06, 0x0d, 0x17, 0x2b, 0x07, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, + 0x37, 0x35, 0x26, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x37, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, 0x06, 0x06, + 0x15, 0x14, 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x0e, 0x02, 0x23, 0x23, 0x25, 0x30, 0x38, 0x0a, 0x23, 0x0b, 0x3a, 0x3a, 0x27, 0x23, 0x05, 0x04, 0x17, 0x03, + 0x04, 0x2e, 0x29, 0x0f, 0x06, 0x48, 0x4b, 0x05, 0x05, 0x18, 0x03, 0x05, 0x66, 0x10, 0x3a, 0x45, 0x0b, 0x21, 0x0c, 0x2e, 0x4a, 0x38, 0x07, 0x55, 0x1e, 0x2f, + 0x9c, 0x33, 0x41, 0x0a, 0x03, 0x0b, 0x35, 0x27, 0x0e, 0x21, 0x10, 0x67, 0x0d, 0x17, 0x0a, 0x1d, 0x14, 0x49, 0x35, 0x39, 0x10, 0x21, 0x13, 0x6a, 0x10, 0x19, + 0x0c, 0x46, 0x49, 0x2a, 0x33, 0x9d, 0x38, 0x3e, 0x18, 0x00, 0x00, 0x01, 0x00, 0x46, 0x01, 0x1f, 0x02, 0x1d, 0x01, 0xa2, 0x00, 0x17, 0x00, 0x3c, 0xb1, 0x06, + 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, 0x02, 0x01, 0x13, 0x01, 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, 0x00, 0x02, 0x00, 0x03, + 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, 0x03, 0x51, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, + 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, + 0x06, 0x23, 0x22, 0x26, 0x01, 0x21, 0x24, 0x2f, 0x16, 0x1c, 0x3e, 0x18, 0x30, 0x48, 0x1d, 0x39, 0x2e, 0x24, 0x2f, 0x15, 0x1d, 0x3e, 0x18, 0x31, 0x47, 0x1c, + 0x3b, 0x01, 0x3f, 0x10, 0x0b, 0x22, 0x19, 0x4e, 0x35, 0x0c, 0x14, 0x10, 0x0b, 0x22, 0x19, 0x4d, 0x36, 0x0d, 0x00, 0x01, 0x00, 0x47, 0x01, 0xa0, 0x01, 0x8e, + 0x03, 0x55, 0x00, 0x19, 0x00, 0x32, 0x40, 0x2f, 0x0b, 0x01, 0x00, 0x01, 0x0a, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x69, + 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x19, 0x18, 0x24, 0x27, + 0x05, 0x0c, 0x19, 0x2b, 0x13, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, + 0x07, 0x07, 0x33, 0x07, 0x47, 0x0c, 0x81, 0x3c, 0x38, 0x1d, 0x1c, 0x2f, 0x30, 0x1f, 0x1f, 0x43, 0x28, 0x2a, 0x32, 0x17, 0x17, 0x36, 0x2e, 0x68, 0xbf, 0x0d, + 0x01, 0xa0, 0x37, 0x6e, 0x34, 0x44, 0x27, 0x19, 0x1e, 0x27, 0x2f, 0x19, 0x19, 0x1e, 0x2f, 0x19, 0x21, 0x38, 0x3c, 0x26, 0x57, 0x3d, 0x00, 0x01, 0x00, 0x51, + 0x01, 0x99, 0x01, 0x8c, 0x03, 0x56, 0x00, 0x27, 0x00, 0x4d, 0x40, 0x4a, 0x18, 0x01, 0x04, 0x05, 0x17, 0x01, 0x03, 0x04, 0x21, 0x01, 0x02, 0x03, 0x04, 0x01, + 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x69, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x01, 0x00, 0x51, 0x01, 0x00, 0x1c, 0x1a, 0x15, 0x13, 0x10, 0x0e, 0x0d, 0x0b, 0x08, + 0x06, 0x00, 0x27, 0x01, 0x27, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, 0x23, 0x37, 0x33, 0x32, + 0x36, 0x35, 0x34, 0x07, 0x06, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0xc4, 0x21, 0x3b, + 0x17, 0x1a, 0x3e, 0x1d, 0x32, 0x31, 0x54, 0x2e, 0x0c, 0x2e, 0x2e, 0x38, 0x40, 0x1a, 0x2d, 0x15, 0x1c, 0x17, 0x44, 0x2a, 0x3c, 0x3c, 0x36, 0x30, 0x23, 0x25, + 0x53, 0x01, 0x99, 0x0f, 0x0c, 0x41, 0x0f, 0x14, 0x2c, 0x25, 0x40, 0x37, 0x27, 0x22, 0x3b, 0x02, 0x01, 0x11, 0x0f, 0x30, 0x12, 0x19, 0x39, 0x2c, 0x2d, 0x37, + 0x0d, 0x04, 0x08, 0x31, 0x22, 0x3a, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x94, 0x01, 0x9f, 0x01, 0x60, 0x03, 0x4b, 0x00, 0x0c, 0x00, 0x19, 0x40, 0x16, 0x08, 0x07, + 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x00, 0x01, 0x01, 0x76, 0x11, 0x19, 0x02, 0x0c, 0x18, 0x2b, 0x13, 0x36, 0x36, 0x37, 0x06, + 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, 0x03, 0x23, 0xf3, 0x05, 0x11, 0x06, 0x08, 0x17, 0x0c, 0x34, 0x1c, 0x8e, 0x3e, 0x5b, 0x47, 0x02, 0x9a, 0x19, 0x3f, 0x15, + 0x07, 0x15, 0x09, 0x22, 0x2f, 0x5c, 0xfe, 0x54, 0x00, 0x01, 0xff, 0x10, 0x00, 0x00, 0x01, 0x71, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, + 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x23, 0x01, 0x33, 0x01, 0xf0, + 0x02, 0x12, 0x4f, 0xfd, 0xee, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x00, 0x02, 0x00, 0x4b, 0x01, 0xa0, 0x01, 0x8a, 0x03, 0x4f, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x61, + 0xb5, 0x10, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x0d, 0x50, 0x58, 0x40, 0x1f, 0x00, 0x01, 0x02, 0x01, 0x85, 0x06, 0x01, 0x04, 0x00, 0x00, 0x04, 0x71, + 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, 0x02, 0x02, 0x00, 0x60, 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, 0x1b, 0x40, 0x1e, 0x00, 0x01, 0x02, 0x01, + 0x85, 0x06, 0x01, 0x04, 0x00, 0x04, 0x86, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, 0x02, 0x02, 0x00, 0x60, 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, + 0x59, 0x40, 0x0f, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0c, 0x1a, 0x2b, 0x13, 0x37, 0x23, 0x37, 0x13, 0x33, 0x03, + 0x33, 0x07, 0x23, 0x07, 0x27, 0x33, 0x37, 0x36, 0x36, 0x37, 0x0e, 0x02, 0x07, 0xe9, 0x14, 0xb2, 0x0b, 0xeb, 0x47, 0x3b, 0x3d, 0x0b, 0x3f, 0x14, 0x8e, 0x6c, + 0x14, 0x06, 0x0a, 0x07, 0x04, 0x13, 0x16, 0x08, 0x01, 0xa0, 0x61, 0x34, 0x01, 0x1a, 0xfe, 0xed, 0x3b, 0x61, 0x9c, 0x5c, 0x1a, 0x2f, 0x18, 0x07, 0x1b, 0x1c, + 0x09, 0x00, 0x00, 0x01, 0x00, 0x5f, 0x01, 0x99, 0x01, 0x98, 0x03, 0x4d, 0x00, 0x1e, 0x00, 0x47, 0x40, 0x44, 0x15, 0x10, 0x02, 0x02, 0x05, 0x0f, 0x03, 0x02, + 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x01, 0x00, 0x51, 0x01, 0x00, 0x19, 0x17, 0x14, 0x13, 0x12, 0x11, 0x0d, 0x0b, 0x07, + 0x05, 0x00, 0x1e, 0x01, 0x1e, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, + 0x37, 0x33, 0x07, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc6, 0x3b, 0x2c, 0x1a, 0x36, 0x1c, 0x32, 0x36, 0x2e, 0x21, 0x10, 0x20, + 0x11, 0x1b, 0x3c, 0xd4, 0x0c, 0x9b, 0x1f, 0x09, 0x17, 0x0d, 0x38, 0x3f, 0x22, 0x4d, 0x01, 0x99, 0x19, 0x43, 0x10, 0x12, 0x33, 0x2a, 0x22, 0x22, 0x05, 0x06, + 0x17, 0xcd, 0x3e, 0x69, 0x02, 0x04, 0x3e, 0x37, 0x25, 0x49, 0x30, 0x00, 0x00, 0x01, 0x00, 0x71, 0x01, 0xa1, 0x01, 0xae, 0x03, 0x4d, 0x00, 0x06, 0x00, 0x24, + 0x40, 0x21, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, 0x23, 0x37, 0x21, 0x07, 0x03, 0x71, 0xe4, 0xc0, 0x0d, 0x01, 0x0c, 0x0a, 0xe4, 0x01, + 0xa1, 0x01, 0x71, 0x3b, 0x30, 0xfe, 0x84, 0x00, 0x00, 0x03, 0x00, 0x58, 0x01, 0x99, 0x01, 0x94, 0x03, 0x55, 0x00, 0x16, 0x00, 0x22, 0x00, 0x2e, 0x00, 0x39, + 0x40, 0x36, 0x29, 0x11, 0x05, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x05, 0x01, 0x03, 0x00, 0x00, 0x03, 0x59, 0x05, + 0x01, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x03, 0x00, 0x51, 0x24, 0x23, 0x01, 0x00, 0x23, 0x2e, 0x24, 0x2e, 0x1e, 0x1c, 0x0c, 0x0a, 0x00, 0x16, 0x01, + 0x16, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, + 0x14, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x07, 0x16, 0x36, 0x35, 0x34, 0x26, 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, + 0xd7, 0x38, 0x47, 0x6e, 0x18, 0x1d, 0x4c, 0x43, 0x3a, 0x3a, 0x35, 0x2e, 0x1e, 0x24, 0x55, 0x1b, 0x1b, 0x32, 0x1f, 0x18, 0x21, 0x24, 0x1c, 0x13, 0x26, 0x2a, + 0x23, 0x17, 0x25, 0x33, 0x25, 0x01, 0x99, 0x39, 0x32, 0x58, 0x29, 0x12, 0x29, 0x23, 0x32, 0x40, 0x3a, 0x28, 0x28, 0x3a, 0x10, 0x13, 0x30, 0x25, 0x37, 0x49, + 0x01, 0x04, 0x0a, 0x22, 0x24, 0x17, 0x1a, 0x22, 0x1a, 0x1a, 0x1f, 0xd9, 0x01, 0x29, 0x1f, 0x1a, 0x28, 0x0c, 0x0d, 0x2a, 0x23, 0x1b, 0x1f, 0x00, 0x00, 0x02, + 0x00, 0x65, 0x01, 0x98, 0x01, 0x96, 0x03, 0x59, 0x00, 0x0e, 0x00, 0x1d, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, + 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x10, 0x0f, 0x01, 0x00, 0x17, 0x15, 0x0f, 0x1d, 0x10, + 0x1d, 0x09, 0x07, 0x00, 0x0e, 0x01, 0x0e, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, + 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0xdc, 0x39, 0x3e, 0x13, 0x2b, 0x47, 0x33, 0x79, 0x15, 0x2d, 0x47, 0x2c, 0x1d, 0x2a, 0x1b, + 0x0e, 0x38, 0x1a, 0x29, 0x1d, 0x0f, 0x1a, 0x01, 0x98, 0x4d, 0x4c, 0x2d, 0x67, 0x5a, 0x3a, 0x90, 0x37, 0x6c, 0x59, 0x35, 0x3e, 0x2c, 0x49, 0x56, 0x29, 0x51, + 0x2a, 0x45, 0x52, 0x29, 0x2c, 0x2f, 0x00, 0x02, 0x00, 0x6a, 0x01, 0x99, 0x01, 0x9d, 0x03, 0x53, 0x00, 0x1a, 0x00, 0x27, 0x00, 0x4b, 0x40, 0x48, 0x09, 0x01, + 0x02, 0x01, 0x0a, 0x01, 0x03, 0x02, 0x10, 0x01, 0x05, 0x03, 0x03, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x00, 0x03, 0x00, 0x05, 0x04, 0x03, + 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x00, 0x04, 0x59, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x04, 0x00, 0x51, 0x1c, 0x1b, 0x01, 0x00, 0x22, + 0x20, 0x1b, 0x27, 0x1c, 0x27, 0x15, 0x13, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x1a, 0x01, 0x1a, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, + 0x33, 0x32, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x27, 0x32, 0x36, 0x35, 0x34, 0x26, + 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0xe2, 0x35, 0x43, 0x33, 0x6c, 0x53, 0x23, 0x1e, 0x0f, 0x0c, 0x21, 0x13, 0x3c, 0x4d, 0x0f, 0x04, 0x0b, 0x2f, 0x25, + 0x2f, 0x38, 0x22, 0x46, 0x30, 0x29, 0x2c, 0x1c, 0x1d, 0x23, 0x27, 0x0e, 0x1c, 0x01, 0x99, 0x44, 0x44, 0x52, 0x8b, 0x55, 0x08, 0x3b, 0x04, 0x05, 0x4e, 0x45, + 0x0e, 0x20, 0x3c, 0x35, 0x2a, 0x4e, 0x32, 0x3a, 0x41, 0x2a, 0x1d, 0x21, 0x24, 0x2d, 0x0d, 0x1d, 0x2e, 0x00, 0x00, 0x02, 0x00, 0x5f, 0x01, 0x99, 0x01, 0x91, + 0x03, 0x53, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x4a, 0x40, 0x47, 0x11, 0x01, 0x03, 0x04, 0x0a, 0x01, 0x02, 0x03, 0x09, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, + 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, + 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, 0x26, 0x1d, 0x26, 0x16, 0x14, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x1b, 0x01, 0x1b, + 0x08, 0x0c, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x01, 0x18, 0x36, 0x43, 0x37, 0x6c, 0x50, 0x22, 0x1d, + 0x0c, 0x27, 0x13, 0x2f, 0x42, 0x28, 0x06, 0x02, 0x11, 0x34, 0x1c, 0x2e, 0x38, 0x22, 0x46, 0x14, 0x26, 0x32, 0x1b, 0x21, 0x29, 0x2c, 0x03, 0x53, 0x43, 0x45, + 0x52, 0x8b, 0x55, 0x08, 0x3f, 0x05, 0x08, 0x2e, 0x46, 0x25, 0x1a, 0x19, 0x3c, 0x34, 0x2a, 0x4e, 0x32, 0xe2, 0x37, 0x27, 0x1d, 0x2d, 0x41, 0x2a, 0x3d, 0x00, + 0x00, 0x01, 0x00, 0x2b, 0x00, 0x00, 0x01, 0xbb, 0x02, 0xfd, 0x00, 0x18, 0x00, 0x35, 0x40, 0x32, 0x0c, 0x01, 0x02, 0x01, 0x0d, 0x01, 0x03, 0x02, 0x02, 0x4c, + 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x04, 0x01, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x28, 0x4d, 0x06, 0x01, 0x05, 0x05, 0x27, 0x05, 0x4e, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x11, 0x13, 0x25, 0x26, 0x11, 0x07, 0x07, 0x1b, 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x2b, 0x63, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, + 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0x73, 0x0d, 0x73, 0x63, 0x01, 0xd5, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, + 0x33, 0x43, 0xfe, 0x2b, 0x00, 0x01, 0xff, 0x90, 0xff, 0x10, 0x02, 0xfb, 0x02, 0xfd, 0x00, 0x44, 0x00, 0x93, 0x40, 0x16, 0x27, 0x16, 0x02, 0x04, 0x03, 0x28, + 0x17, 0x02, 0x05, 0x04, 0x39, 0x04, 0x02, 0x01, 0x02, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x27, 0x07, 0x01, 0x04, + 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, + 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x25, 0x06, 0x01, 0x03, 0x07, 0x01, 0x04, 0x05, 0x03, 0x04, 0x69, 0x0c, 0x09, 0x02, + 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, + 0x21, 0x01, 0x00, 0x41, 0x40, 0x3d, 0x3b, 0x37, 0x35, 0x32, 0x31, 0x30, 0x2f, 0x2c, 0x2a, 0x25, 0x23, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, 0x08, + 0x06, 0x00, 0x44, 0x01, 0x44, 0x0e, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, + 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x06, 0x06, 0x30, 0x13, 0x20, + 0x0d, 0x0e, 0x1a, 0x10, 0x1e, 0x2d, 0x0d, 0x6e, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, + 0x0c, 0xe7, 0x0c, 0x10, 0x2f, 0x46, 0x31, 0x1a, 0x35, 0x10, 0x18, 0x0e, 0x21, 0x13, 0x28, 0x2d, 0x0e, 0x0c, 0x74, 0x0e, 0x73, 0x70, 0x12, 0x4b, 0x49, 0x26, + 0x19, 0x0c, 0x1c, 0x10, 0x1e, 0x2c, 0x0d, 0x6e, 0xe7, 0x70, 0x12, 0x4c, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x32, 0x40, 0x02, 0x0a, 0x25, 0x21, 0x30, 0x45, + 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x34, 0x44, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, + 0x5e, 0x0a, 0x4a, 0x04, 0x07, 0x33, 0x3f, 0x02, 0x0a, 0xfd, 0xec, 0x53, 0x5e, 0x00, 0x00, 0x03, 0xff, 0x90, 0xff, 0x10, 0x03, 0x8c, 0x02, 0xfd, 0x00, 0x44, + 0x00, 0x4f, 0x00, 0x53, 0x01, 0x05, 0x40, 0x16, 0x27, 0x16, 0x02, 0x0e, 0x03, 0x28, 0x17, 0x02, 0x0d, 0x04, 0x39, 0x04, 0x02, 0x01, 0x10, 0x38, 0x03, 0x02, + 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x39, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x6c, 0x4d, 0x12, 0x01, 0x0d, + 0x0d, 0x0e, 0x61, 0x00, 0x0e, 0x0e, 0x70, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, + 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x37, 0x06, 0x01, + 0x03, 0x07, 0x01, 0x04, 0x0d, 0x03, 0x04, 0x69, 0x12, 0x01, 0x0d, 0x0d, 0x0e, 0x61, 0x00, 0x0e, 0x0e, 0x70, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, + 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, + 0x4e, 0x1b, 0x40, 0x35, 0x06, 0x01, 0x03, 0x07, 0x01, 0x04, 0x0d, 0x03, 0x04, 0x69, 0x00, 0x0e, 0x12, 0x01, 0x0d, 0x05, 0x0e, 0x0d, 0x69, 0x0c, 0x09, 0x02, + 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, + 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x31, 0x50, 0x50, 0x46, 0x45, 0x01, 0x00, 0x50, 0x53, 0x50, 0x53, 0x52, 0x51, 0x4c, 0x4a, 0x45, 0x4f, 0x46, + 0x4f, 0x41, 0x40, 0x3d, 0x3b, 0x37, 0x35, 0x32, 0x31, 0x30, 0x2f, 0x2c, 0x2a, 0x25, 0x23, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, 0x08, 0x06, 0x00, + 0x44, 0x01, 0x44, 0x14, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, + 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, + 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x06, 0x06, 0x01, 0x22, 0x26, 0x35, 0x34, + 0x36, 0x33, 0x32, 0x15, 0x14, 0x06, 0x03, 0x13, 0x33, 0x03, 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x1e, 0x2d, 0x0d, 0x6e, 0x5d, 0x07, 0x64, 0x0b, 0x10, + 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0c, 0x10, 0x2f, 0x46, 0x31, 0x1a, 0x35, 0x10, 0x18, 0x0e, 0x21, + 0x13, 0x28, 0x2d, 0x0e, 0x0c, 0x74, 0x0e, 0x73, 0x70, 0x12, 0x4b, 0x49, 0x26, 0x19, 0x0c, 0x1c, 0x10, 0x1e, 0x2c, 0x0d, 0x6e, 0xe7, 0x70, 0x12, 0x4c, 0x03, + 0x3b, 0x13, 0x1c, 0x1f, 0x1c, 0x2d, 0x24, 0xce, 0x73, 0x58, 0x73, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x32, 0x40, 0x02, 0x0a, 0x25, 0x21, 0x30, 0x45, 0x4d, + 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x34, 0x44, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, 0x5e, + 0x0a, 0x4a, 0x04, 0x07, 0x33, 0x3f, 0x02, 0x0a, 0xfd, 0xec, 0x53, 0x5e, 0x03, 0x61, 0x19, 0x16, 0x1a, 0x26, 0x2d, 0x1f, 0x23, 0xfd, 0x8f, 0x02, 0x18, 0xfd, + 0xe8, 0x00, 0x00, 0x02, 0xff, 0x90, 0xff, 0x10, 0x03, 0x93, 0x02, 0xfd, 0x00, 0x44, 0x00, 0x48, 0x01, 0x04, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x16, 0x27, + 0x16, 0x02, 0x04, 0x03, 0x28, 0x17, 0x02, 0x05, 0x04, 0x39, 0x04, 0x02, 0x01, 0x0e, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x1b, 0x40, 0x16, 0x27, 0x16, + 0x02, 0x04, 0x0d, 0x28, 0x17, 0x02, 0x05, 0x04, 0x39, 0x04, 0x02, 0x01, 0x0e, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x1d, 0x50, 0x58, + 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, + 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, + 0x50, 0x58, 0x40, 0x2c, 0x0d, 0x06, 0x02, 0x03, 0x07, 0x01, 0x04, 0x05, 0x03, 0x04, 0x69, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, + 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x33, 0x00, + 0x0d, 0x03, 0x04, 0x03, 0x0d, 0x04, 0x80, 0x06, 0x01, 0x03, 0x07, 0x01, 0x04, 0x05, 0x03, 0x04, 0x69, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, + 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, + 0x40, 0x29, 0x45, 0x45, 0x01, 0x00, 0x45, 0x48, 0x45, 0x48, 0x47, 0x46, 0x41, 0x40, 0x3d, 0x3b, 0x37, 0x35, 0x32, 0x31, 0x30, 0x2f, 0x2c, 0x2a, 0x25, 0x23, + 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x44, 0x01, 0x44, 0x11, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, + 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, + 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x13, 0x23, 0x03, 0x06, 0x06, 0x25, 0x13, 0x33, 0x03, 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x1e, 0x2d, 0x0d, 0x6e, 0x5d, 0x07, 0x64, 0x0b, 0x10, + 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0c, 0x10, 0x2f, 0x46, 0x31, 0x1a, 0x35, 0x10, 0x18, 0x0e, 0x21, + 0x13, 0x28, 0x2d, 0x0e, 0x0c, 0x74, 0x0e, 0x73, 0x70, 0x12, 0x4b, 0x49, 0x26, 0x19, 0x0c, 0x1c, 0x10, 0x1e, 0x2c, 0x0d, 0x6e, 0xe7, 0x70, 0x12, 0x4c, 0x02, + 0x82, 0xa1, 0x58, 0xa2, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x32, 0x40, 0x02, 0x0a, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, + 0x3e, 0x33, 0x34, 0x44, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, 0x5e, 0x0a, 0x4a, 0x04, 0x07, 0x33, 0x3f, 0x02, + 0x0a, 0xfd, 0xec, 0x53, 0x5e, 0xf0, 0x02, 0xf8, 0xfd, 0x08, 0xff, 0xff, 0xff, 0x90, 0xff, 0x10, 0x02, 0x4c, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x4a, 0x01, 0x3e, 0x00, 0x00, 0xff, 0xff, 0xff, 0x90, 0xff, 0x10, 0x02, 0x53, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x4d, 0x01, 0x3e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x00, 0x02, 0xf9, 0x02, 0xfd, 0x00, 0x2d, 0x00, 0x42, 0x40, 0x3f, 0x1d, 0x0c, 0x02, 0x02, + 0x01, 0x1e, 0x0d, 0x02, 0x03, 0x02, 0x02, 0x4c, 0x04, 0x01, 0x01, 0x05, 0x01, 0x02, 0x03, 0x01, 0x02, 0x69, 0x09, 0x07, 0x02, 0x00, 0x00, 0x03, 0x5f, 0x06, + 0x01, 0x03, 0x03, 0x28, 0x4d, 0x0b, 0x0a, 0x02, 0x08, 0x08, 0x27, 0x08, 0x4e, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x2d, 0x2c, 0x2b, 0x11, 0x11, 0x13, 0x25, 0x24, + 0x13, 0x25, 0x26, 0x11, 0x0c, 0x07, 0x1f, 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, + 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x23, 0x13, 0x23, 0x03, 0x2b, + 0x63, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0b, 0x0f, 0x2f, 0x47, 0x31, + 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0x73, 0x0d, 0x73, 0x63, 0x58, 0x63, 0xe6, 0x63, 0x01, 0xd5, 0x25, 0x21, 0x30, 0x45, 0x4d, + 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x33, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfe, 0x2b, 0x01, 0xd5, + 0xfe, 0x2b, 0xff, 0xff, 0x00, 0x2b, 0x00, 0x00, 0x03, 0x8a, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x02, 0x7c, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x2b, 0x00, 0x00, 0x03, 0x91, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x02, 0x7c, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x2b, 0x00, 0x00, 0x02, 0x4c, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, 0x3e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2b, + 0x00, 0x00, 0x02, 0x53, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x3e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0d, 0xff, 0xf8, + 0x01, 0x3e, 0x01, 0xb9, 0x01, 0x07, 0x00, 0x68, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x40, 0x00, 0x00, 0x01, 0x0c, 0x01, 0xac, 0x01, 0x07, 0x00, 0x62, 0xff, 0xac, 0xfe, 0x61, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x61, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0xff, 0xef, 0x00, 0x00, 0x01, 0x36, 0x01, 0xb5, 0x01, 0x07, 0x00, 0x60, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, + 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x04, 0xff, 0xf9, 0x01, 0x3f, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x61, 0xff, 0xb3, 0xfe, 0x60, 0x00, 0x09, + 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x3e, 0x01, 0xaf, 0x01, 0x07, 0x00, 0x64, 0xff, 0xb4, + 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0d, 0xff, 0xf9, 0x01, 0x46, 0x01, 0xad, 0x01, 0x07, + 0x00, 0x65, 0xff, 0xae, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0xff, 0xf9, 0x01, 0x44, + 0x01, 0xb3, 0x01, 0x07, 0x00, 0x69, 0xff, 0xa7, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1f, + 0x00, 0x00, 0x01, 0x5c, 0x01, 0xac, 0x01, 0x07, 0x00, 0x66, 0xff, 0xae, 0xfe, 0x5f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x5f, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x01, 0x3b, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x67, 0xff, 0xa7, 0xfe, 0x61, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x61, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x07, 0xff, 0xf9, 0x01, 0x39, 0x01, 0xb3, 0x01, 0x07, 0x00, 0x6a, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, + 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x4a, 0x01, 0x17, 0x01, 0x7b, 0x02, 0xd8, 0x01, 0x07, 0x00, 0x68, 0xff, 0xe5, 0xff, 0x7f, + 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x75, 0x01, 0x1e, 0x01, 0x41, 0x02, 0xca, 0x01, 0x07, 0x00, 0x62, + 0xff, 0xe1, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x2b, 0x01, 0x1f, 0x01, 0x72, 0x02, 0xd4, + 0x01, 0x07, 0x00, 0x60, 0xff, 0xe4, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x37, 0x01, 0x18, + 0x01, 0x72, 0x02, 0xd5, 0x01, 0x07, 0x00, 0x61, 0xff, 0xe6, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x31, 0x01, 0x1f, 0x01, 0x70, 0x02, 0xce, 0x01, 0x07, 0x00, 0x64, 0xff, 0xe6, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0x00, 0x45, 0x01, 0x18, 0x01, 0x7e, 0x02, 0xcc, 0x01, 0x07, 0x00, 0x65, 0xff, 0xe6, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, + 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x53, 0x01, 0x18, 0x01, 0x86, 0x02, 0xd2, 0x01, 0x07, 0x00, 0x69, 0xff, 0xe9, 0xff, 0x7f, 0x00, 0x09, + 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x5b, 0x01, 0x20, 0x01, 0x98, 0x02, 0xcc, 0x01, 0x07, 0x00, 0x66, 0xff, 0xea, + 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x3b, 0x01, 0x18, 0x01, 0x77, 0x02, 0xd4, 0x01, 0x07, + 0x00, 0x67, 0xff, 0xe3, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x49, 0x01, 0x18, 0x01, 0x7b, + 0x02, 0xd2, 0x01, 0x07, 0x00, 0x6a, 0xff, 0xea, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x8a, 0x01, 0x08, 0x00, 0x18, 0x00, 0x71, 0x00, 0x06, 0x00, 0x02, 0x00, 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x89, 0x0e, 0x0c, + 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x5b, 0x00, 0xaf, 0x01, 0x40, 0x01, 0xf5, 0x02, 0x87, 0x02, 0xa2, 0x02, 0xca, + 0x02, 0xf2, 0x03, 0x1f, 0x03, 0x47, 0x03, 0x67, 0x03, 0x83, 0x03, 0xa4, 0x03, 0xbf, 0x04, 0x09, 0x04, 0x32, 0x04, 0x74, 0x04, 0xd8, 0x05, 0x18, 0x05, 0x6c, + 0x05, 0xd7, 0x05, 0xfa, 0x06, 0x66, 0x06, 0xce, 0x07, 0x08, 0x07, 0x43, 0x07, 0x59, 0x07, 0x84, 0x07, 0x9a, 0x07, 0xf5, 0x08, 0xaa, 0x08, 0xe2, 0x09, 0x3b, + 0x09, 0x84, 0x09, 0xbc, 0x09, 0xec, 0x0a, 0x17, 0x0a, 0x6a, 0x0a, 0x98, 0x0a, 0xc2, 0x0a, 0xf3, 0x0b, 0x23, 0x0b, 0x43, 0x0b, 0x81, 0x0b, 0xb6, 0x0b, 0xfc, + 0x0c, 0x36, 0x0c, 0x85, 0x0c, 0xc7, 0x0d, 0x21, 0x0d, 0x44, 0x0d, 0x80, 0x0d, 0xad, 0x0d, 0xfb, 0x0e, 0x2a, 0x0e, 0x52, 0x0e, 0x7c, 0x0e, 0xa0, 0x0e, 0xba, + 0x0e, 0xde, 0x0f, 0x05, 0x0f, 0x25, 0x0f, 0x4f, 0x0f, 0xbd, 0x10, 0x42, 0x10, 0x8a, 0x11, 0x0e, 0x11, 0x6a, 0x11, 0xdf, 0x12, 0x69, 0x12, 0xc2, 0x13, 0x05, + 0x13, 0x62, 0x13, 0xa4, 0x13, 0xc9, 0x14, 0x3c, 0x14, 0x8e, 0x14, 0xd3, 0x15, 0x41, 0x15, 0xac, 0x15, 0xff, 0x16, 0x54, 0x16, 0xb4, 0x17, 0x09, 0x17, 0x38, + 0x17, 0x86, 0x17, 0xb2, 0x17, 0xfa, 0x18, 0x23, 0x18, 0x81, 0x18, 0xa6, 0x19, 0x02, 0x19, 0x47, 0x19, 0x8a, 0x19, 0xeb, 0x1a, 0x12, 0x1a, 0x2d, 0x1a, 0x84, + 0x1a, 0xd7, 0x1a, 0xfc, 0x1b, 0x5f, 0x1b, 0xa4, 0x1c, 0x05, 0x1c, 0x64, 0x1c, 0xa7, 0x1d, 0x55, 0x1e, 0x53, 0x1f, 0x41, 0x1f, 0x4d, 0x1f, 0x59, 0x1f, 0xbf, + 0x1f, 0xcb, 0x1f, 0xd7, 0x1f, 0xe3, 0x1f, 0xef, 0x1f, 0xfe, 0x20, 0x0d, 0x20, 0x1c, 0x20, 0x2b, 0x20, 0x3a, 0x20, 0x49, 0x20, 0x58, 0x20, 0x67, 0x20, 0x76, + 0x20, 0x85, 0x20, 0x94, 0x20, 0xa3, 0x20, 0xb2, 0x20, 0xc1, 0x20, 0xd0, 0x20, 0xdf, 0x20, 0xee, 0x20, 0xfd, 0x21, 0x0c, 0x21, 0x1b, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, 0x57, 0x3e, 0x69, 0x66, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xcc, 0xa2, + 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc4, 0x0f, 0xfd, 0x67, 0xfe, 0x7b, 0x0a, 0xcf, 0x04, 0x3c, 0x00, 0x02, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x58, 0x00, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x01, 0x05, 0x00, 0x14, 0x01, 0x88, 0x00, 0x6d, 0x02, 0x86, 0x00, 0x1e, 0x02, 0x27, 0x00, 0x22, + 0x03, 0x1f, 0x00, 0x50, 0x02, 0xa1, 0x00, 0x20, 0x00, 0xdc, 0x00, 0x6d, 0x01, 0x22, 0x00, 0x28, 0x01, 0x22, 0xff, 0xb3, 0x02, 0x27, 0x00, 0x67, 0x02, 0x3c, + 0x00, 0x46, 0x01, 0x00, 0xff, 0xd5, 0x01, 0x39, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x14, 0x01, 0x64, 0xff, 0xd2, 0x02, 0x27, 0x00, 0x39, 0x02, 0x27, 0x00, 0x8f, + 0x02, 0x27, 0x00, 0x03, 0x02, 0x27, 0x00, 0x16, 0x02, 0x27, 0x00, 0x06, 0x02, 0x27, 0x00, 0x25, 0x02, 0x27, 0x00, 0x3f, 0x02, 0x27, 0x00, 0x51, 0x02, 0x27, + 0x00, 0x2d, 0x02, 0x27, 0x00, 0x2f, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0xff, 0xcf, 0x02, 0x3c, 0x00, 0x46, 0x02, 0x3c, 0x00, 0x4c, 0x02, 0x3c, 0x00, 0x46, + 0x01, 0xae, 0x00, 0x4d, 0x03, 0x50, 0x00, 0x35, 0x02, 0x32, 0xff, 0xc7, 0x02, 0x58, 0x00, 0x29, 0x02, 0x4b, 0x00, 0x48, 0x02, 0x9b, 0x00, 0x29, 0x02, 0x02, + 0x00, 0x29, 0x01, 0xdd, 0x00, 0x29, 0x02, 0xa6, 0x00, 0x48, 0x02, 0xa8, 0x00, 0x2a, 0x01, 0x44, 0xff, 0xec, 0x01, 0x11, 0xff, 0x64, 0x02, 0x32, 0x00, 0x29, + 0x01, 0xde, 0x00, 0x29, 0x03, 0x49, 0x00, 0x28, 0x02, 0xc3, 0x00, 0x28, 0x02, 0xd1, 0x00, 0x48, 0x02, 0x37, 0x00, 0x29, 0x02, 0xd1, 0x00, 0x48, 0x02, 0x3d, + 0x00, 0x29, 0x01, 0xf9, 0x00, 0x13, 0x01, 0xf5, 0x00, 0x5a, 0x02, 0xa5, 0x00, 0x4f, 0x02, 0x28, 0x00, 0x5c, 0x03, 0x58, 0x00, 0x6b, 0x02, 0x0f, 0xff, 0xcc, + 0x01, 0xfd, 0x00, 0x5c, 0x02, 0x13, 0xff, 0xf6, 0x01, 0x22, 0xff, 0xf7, 0x01, 0x64, 0x00, 0x6c, 0x01, 0x22, 0xff, 0xb8, 0x02, 0x3c, 0x00, 0x26, 0x01, 0x8b, + 0xff, 0xa4, 0x01, 0x16, 0x00, 0x92, 0x02, 0x38, 0x00, 0x30, 0x02, 0x43, 0x00, 0x1c, 0x01, 0xc5, 0x00, 0x30, 0x02, 0x43, 0x00, 0x30, 0x01, 0xf3, 0x00, 0x30, + 0x01, 0x3e, 0xff, 0x90, 0x02, 0x43, 0x00, 0x19, 0x02, 0x43, 0x00, 0x1c, 0x01, 0x02, 0x00, 0x1c, 0x01, 0x02, 0xff, 0x82, 0x01, 0xef, 0x00, 0x1b, 0x01, 0x02, + 0x00, 0x1b, 0x03, 0x6b, 0x00, 0x1c, 0x02, 0x43, 0x00, 0x18, 0x02, 0x33, 0x00, 0x30, 0x02, 0x43, 0xff, 0xea, 0x02, 0x43, 0x00, 0x30, 0x01, 0x8e, 0x00, 0x1c, + 0x01, 0xb0, 0x00, 0x05, 0x01, 0x4c, 0x00, 0x2c, 0x02, 0x43, 0x00, 0x37, 0x01, 0xd3, 0x00, 0x30, 0x02, 0xd3, 0x00, 0x39, 0x01, 0xe3, 0xff, 0xdb, 0x01, 0xd3, + 0xff, 0xa2, 0x01, 0xbd, 0xff, 0xf1, 0x01, 0x5e, 0x00, 0x0b, 0x02, 0x27, 0x01, 0x04, 0x01, 0x5e, 0xff, 0xdb, 0x02, 0x3c, 0x00, 0x46, 0x01, 0x61, 0x00, 0x47, + 0x01, 0x61, 0x00, 0x51, 0x01, 0x61, 0x00, 0x94, 0x00, 0x82, 0xff, 0x10, 0x01, 0x61, 0x00, 0x4b, 0x01, 0x61, 0x00, 0x5f, 0x01, 0x61, 0x00, 0x71, 0x01, 0x61, + 0x00, 0x58, 0x01, 0x61, 0x00, 0x65, 0x01, 0x61, 0x00, 0x6a, 0x01, 0x61, 0x00, 0x5f, 0x01, 0x3e, 0x00, 0x2b, 0x02, 0x7e, 0xff, 0x90, 0x03, 0x80, 0xff, 0x90, + 0x03, 0x80, 0xff, 0x90, 0x02, 0x40, 0xff, 0x90, 0x02, 0x40, 0xff, 0x90, 0x02, 0x7c, 0x00, 0x2b, 0x03, 0x7e, 0x00, 0x2b, 0x03, 0x7e, 0x00, 0x2b, 0x02, 0x40, + 0x00, 0x2b, 0x02, 0x40, 0x00, 0x2b, 0x01, 0x61, 0x00, 0x0d, 0x00, 0x40, 0xff, 0xef, 0x00, 0x04, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x1f, 0xff, 0xff, + 0x00, 0x07, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x2b, 0x00, 0x37, 0x00, 0x31, 0x00, 0x45, 0x00, 0x53, 0x00, 0x5b, 0x00, 0x3b, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x0a, 0xf0, 0xfd, 0x67, 0xfd, 0x67, 0x0a, 0xcf, 0x03, 0xe8, 0x00, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, 0x02, 0x26, 0x01, 0x90, 0x00, 0x05, 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, 0xff, 0xf0, 0x00, 0x4b, + 0x02, 0x8a, 0x02, 0x58, 0x00, 0x4a, 0x01, 0x5e, 0x00, 0x32, 0x01, 0x42, 0x00, 0x00, 0x02, 0x0b, 0x05, 0x02, 0x04, 0x05, 0x04, 0x09, 0x02, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x01, 0x81, 0x00, 0x20, 0x00, 0x7e, 0x04, 0x2d, + 0xfe, 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x02, 0xca, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, + 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, 0x21, 0xb0, + 0x00, 0x59, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, 0x02, 0x2c, + 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, + 0x14, 0x43, 0x42, 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, 0x04, 0x50, 0x78, + 0xb2, 0x02, 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, 0x20, 0xb0, 0x02, 0x43, + 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, + 0x2c, 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x1b, 0x20, 0x64, + 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, + 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, 0x38, + 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x20, 0xb0, + 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, + 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, 0x1b, 0xb0, + 0x02, 0x25, 0xb0, 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, 0xb0, 0x1e, 0x50, + 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, + 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, 0x20, 0x45, 0x20, 0xb0, + 0x04, 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, 0x59, 0xb0, 0x01, 0x60, 0x2d, + 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, + 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, 0xb0, 0x08, 0x43, 0x20, 0x8a, 0x20, + 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, + 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, 0x43, 0x2b, + 0xb2, 0x00, 0x02, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, 0x62, 0x66, + 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, 0x0e, 0x00, 0x43, + 0x45, 0x42, 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, + 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, + 0x64, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, + 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, + 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, + 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, 0x0c, 0x00, + 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, + 0x2c, 0xb0, 0x01, 0x60, 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, 0xb0, 0x00, + 0x52, 0x58, 0x20, 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, 0x00, 0x63, 0x8a, + 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, + 0x59, 0x24, 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x1b, 0x21, 0x59, 0x24, + 0xb0, 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, 0x61, 0x42, 0xb0, 0x11, 0x2b, + 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, + 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x23, 0xb0, 0x01, 0x61, 0x20, + 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, + 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x20, + 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, 0x00, 0x13, + 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, + 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, + 0x13, 0x00, 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, + 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, + 0x2c, 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, + 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, + 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x5d, + 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, + 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, + 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, + 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, 0x01, 0x00, 0x11, + 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, + 0x2c, 0xb1, 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, 0xb0, 0x25, 0x2c, 0xb1, + 0x04, 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, 0x28, 0x2c, 0xb1, 0x07, 0x20, + 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, + 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x01, 0x60, 0xb0, 0x2e, 0x2a, + 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, + 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, 0x20, 0x47, + 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, + 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, + 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, + 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x34, 0x2c, 0x20, + 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, + 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, 0x20, 0x3c, + 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, + 0x00, 0x43, 0x61, 0xb0, 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb0, + 0x02, 0x25, 0x49, 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, 0x01, 0x15, 0x14, + 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, + 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, + 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, + 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, + 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, + 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, 0x02, 0x25, + 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, + 0xb0, 0x01, 0x63, 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, 0x25, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, 0x60, 0x64, 0x23, 0xb0, + 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, + 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x3c, 0x38, 0x2d, 0xb0, 0x3d, + 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, + 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, 0x2e, + 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, + 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, + 0x59, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, 0x20, 0x3c, + 0x8a, 0x38, 0x23, 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, + 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, + 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, + 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, + 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, + 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, + 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, + 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, 0x20, 0x20, + 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, + 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, + 0x26, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, 0x20, 0x3c, 0x20, + 0x2e, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, + 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, + 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, 0xb0, 0x06, 0x43, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, + 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, 0x23, 0x38, + 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, + 0x3a, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x23, + 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, + 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, + 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, 0xb0, 0x4c, 0x2c, 0xb0, + 0x39, 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, + 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, + 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x53, 0x2c, 0xb2, 0x00, 0x00, + 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, + 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x59, + 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x43, + 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, + 0x01, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x61, + 0x2c, 0xb2, 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, 0x48, 0x2b, 0x2d, 0xb0, + 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, + 0xb0, 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x69, 0x2c, 0xb3, 0x01, 0x00, + 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, + 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x44, + 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, + 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, + 0xb0, 0x73, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, 0x2c, 0xb0, + 0x00, 0x16, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x77, + 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, + 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, + 0x2d, 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, + 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, + 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, + 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, + 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x87, + 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, 0x01, 0x3f, + 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, + 0xb0, 0x06, 0x1b, 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, 0x50, 0x78, 0xb1, + 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, 0xb9, 0x08, 0x00, 0x08, + 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, 0x00, 0x49, 0x39, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, + 0x14, 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, 0x02, 0x56, 0x06, 0x4e, 0x04, 0x3e, 0x08, 0x32, 0x06, 0x24, 0x07, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x07, 0x42, + 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x52, 0x02, 0x46, 0x06, 0x38, 0x04, 0x2b, 0x05, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, + 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, 0x13, 0xc0, 0x0f, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, + 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x09, + 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, + 0x28, 0x01, 0x88, 0x51, 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, 0xba, 0x08, + 0x80, 0x00, 0x01, 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, 0x06, 0x7a, 0x06, + 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x50, 0x02, 0x40, 0x06, 0x34, 0x04, 0x26, 0x05, 0x09, 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, + 0x00, 0x44, 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x48, 0x02, 0xca, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd6, 0xff, 0xf6, 0x02, 0x20, + 0xff, 0xf6, 0xff, 0x10, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4c, 0x00, 0x4c, 0x02, 0x3b, 0x02, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x44, 0x02, 0x47, 0xff, 0xf8, + 0x00, 0x00, 0x00, 0x59, 0x00, 0x59, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0xff, 0xf6, 0x02, 0xf8, 0x02, 0x18, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, + 0x02, 0xfd, 0x02, 0x21, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4c, 0x00, 0x4c, 0x02, 0x3b, 0x00, 0x00, 0x02, 0x44, 0xff, 0xf8, 0x00, 0x45, + 0x00, 0x45, 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x45, 0x00, 0x45, + 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x59, 0x00, 0x59, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0x00, 0x00, 0x02, 0xec, 0x02, 0x18, 0x00, 0x00, + 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xec, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x2c, 0x00, 0x2c, 0x01, 0x2b, 0xff, 0x7e, + 0x01, 0x61, 0x00, 0xe2, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x34, 0xff, 0x77, 0x01, 0x61, 0x00, 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x2c, + 0x00, 0x2c, 0x02, 0xcb, 0x01, 0x9f, 0x02, 0xe0, 0x02, 0x61, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe0, 0x01, 0x98, 0x02, 0xe0, 0x02, 0x67, 0x01, 0x19, 0x00, 0x8f, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, + 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x0c, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x34, + 0x00, 0xd4, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x20, 0x01, 0x08, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, 0x01, 0x28, + 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x1e, 0x01, 0x7c, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, + 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x4e, + 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x41, + 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, + 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, + 0x00, 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, + 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, + 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, + 0x00, 0x6e, 0x00, 0x73, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, + 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, + 0x00, 0x73, 0x00, 0x2d, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, + 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x56, 0x00, 0x65, + 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x20, + 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, + 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, + 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, + 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x03, 0x00, 0x00, 0xff, 0xf4, 0x00, 0x00, 0xff, 0x9c, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x22, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x42, 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6b, + 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x02, 0x00, 0x18, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x32, 0x00, 0x3c, 0x00, 0x4a, 0x00, 0x4a, 0x00, 0x2a, 0x00, 0x32, + 0x00, 0x3c, 0x00, 0x4a, 0x00, 0x4a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0xfa, 0x00, 0x01, + 0x00, 0x04, 0x00, 0x01, 0x00, 0xff, 0x00, 0x02, 0x00, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0xf7, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x00, 0xf9, + 0x00, 0x01, 0x02, 0x2d, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, + 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0x65, 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x06, 0x06, 0xc8, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x01, 0x08, 0x00, 0x01, 0x00, 0x38, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x6a, 0x00, 0xf4, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x8c, 0x00, 0xb4, 0x00, 0x92, 0x00, 0x98, 0x00, 0xb4, 0x00, 0xaa, 0x00, 0xb4, 0x00, 0xba, 0x00, 0xc4, + 0x00, 0xc4, 0x00, 0xce, 0x00, 0xd8, 0x00, 0xf4, 0x00, 0xde, 0x00, 0xe4, 0x00, 0xee, 0x00, 0xee, 0x00, 0xee, 0x00, 0xf4, 0x00, 0x01, 0x00, 0x17, 0x00, 0x07, + 0x00, 0x09, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, 0x00, 0x38, + 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, 0x37, + 0xff, 0xd8, 0x00, 0x38, 0xff, 0xd8, 0x00, 0x3a, 0xff, 0xc4, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x4b, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xec, 0x00, 0x0f, 0xff, 0xec, + 0x00, 0x01, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x04, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, 0x00, 0x20, 0x00, 0x14, + 0x00, 0x22, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x39, 0xff, 0xec, 0x00, 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, + 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, + 0x00, 0x07, 0xff, 0xec, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, + 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, 0x03, 0xd8, 0x00, 0x04, 0x00, 0x00, 0x04, 0x26, 0x04, 0xe4, 0x00, 0x16, 0x00, 0x16, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, + 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, 0xff, 0xe2, 0xff, 0xce, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, + 0x00, 0x00, 0xff, 0xc4, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xf6, 0x00, 0x00, 0xff, 0xd8, 0xff, 0xec, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xec, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xf6, 0x00, 0x00, 0xff, 0xce, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0xff, 0xe2, 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, + 0xff, 0xce, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x0a, 0xff, 0xc4, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, + 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x88, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x25, 0x00, 0x03, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, + 0x00, 0x25, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, + 0x00, 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x4c, 0x00, 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, + 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x09, + 0x00, 0x13, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x22, 0x00, 0x22, 0x00, 0x01, + 0x00, 0x24, 0x00, 0x24, 0x00, 0x07, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x08, 0x00, 0x30, + 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, + 0x00, 0x05, 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x39, 0x00, 0x39, 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x06, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0d, + 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x02, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x10, 0x00, 0x53, + 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0c, 0x00, 0x57, 0x00, 0x58, 0x00, 0x04, 0x00, 0x59, 0x00, 0x59, 0x00, 0x10, 0x00, 0x5a, 0x00, 0x5a, + 0x00, 0x04, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x15, 0x00, 0x02, 0x00, 0x23, 0x00, 0x03, 0x00, 0x03, 0x00, 0x11, 0x00, 0x08, + 0x00, 0x08, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, + 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x05, 0x00, 0x24, 0x00, 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x28, 0x00, 0x02, + 0x00, 0x30, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x32, 0x00, 0x02, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, + 0x00, 0x38, 0x00, 0x09, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x08, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, + 0x00, 0x04, 0x00, 0x44, 0x00, 0x46, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x48, 0x00, 0x48, 0x00, 0x0d, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x03, + 0x00, 0x50, 0x00, 0x50, 0x00, 0x01, 0x00, 0x51, 0x00, 0x51, 0x00, 0x03, 0x00, 0x52, 0x00, 0x52, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x03, 0x00, 0x54, + 0x00, 0x54, 0x00, 0x0a, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0e, 0x00, 0x56, 0x00, 0x56, 0x00, 0x03, 0x00, 0x57, 0x00, 0x58, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x5a, + 0x00, 0x07, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x5e, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x15, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, + 0x00, 0x08, 0x00, 0x02, 0x00, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x02, 0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, + 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x50, 0x00, 0x92, 0x00, 0x04, + 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1e, 0x00, 0x0e, + 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x45, 0x57, 0x45, 0x20, 0x00, 0x18, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x20, 0x66, 0x72, + 0x61, 0x63, 0x00, 0x26, 0x6c, 0x69, 0x67, 0x61, 0x00, 0x30, 0x6c, 0x6f, 0x63, 0x6c, 0x00, 0x36, 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x3c, 0x00, 0x4a, 0x00, 0x5e, 0x00, 0x76, 0x00, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x12, 0x00, 0x06, 0x00, 0x6b, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x01, 0x00, 0x06, + 0x00, 0x47, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x65, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0a, + 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, + 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x01, 0x00, 0x76, 0x00, 0x7f, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x00, 0x89, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x66, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x38, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, + 0x00, 0x22, 0x00, 0x28, 0x00, 0x6e, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x4a, + 0x00, 0x70, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x47, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x73, + 0x00, 0x03, 0x00, 0x6b, 0x00, 0x4d, 0x00, 0x72, 0x00, 0x03, 0x00, 0x6b, 0x00, 0x4a, 0x00, 0x74, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x02, 0x00, 0x4d, + 0x00, 0x71, 0x00, 0x02, 0x00, 0x6b, 0x00, 0x01, 0x00, 0x02, 0x00, 0x47, 0x00, 0x6b}; + +const inline uint8_t FONT_BOLD_DATA[] = { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x06, 0x75, 0x08, 0xc3, 0x00, 0x00, 0x4f, 0x3c, 0x00, 0x00, + 0x00, 0x6c, 0x47, 0x50, 0x4f, 0x53, 0x28, 0x98, 0x0a, 0xef, 0x00, 0x00, 0x4f, 0xa8, 0x00, 0x00, 0x07, 0xb2, 0x47, 0x53, 0x55, 0x42, 0x39, 0x7a, 0x34, 0x30, + 0x00, 0x00, 0x57, 0x5c, 0x00, 0x00, 0x01, 0x50, 0x4f, 0x53, 0x2f, 0x32, 0x6a, 0x81, 0x61, 0x8b, 0x00, 0x00, 0x3c, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, + 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x3c, 0xbc, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, 0x20, 0x41, 0xb6, 0x1e, 0xcf, 0x00, 0x00, 0x4c, 0x04, + 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, 0x0b, 0x83, 0x00, 0x00, 0x3c, 0xf0, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x4f, 0x34, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0xea, 0xe8, 0x66, 0x13, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x37, 0xca, + 0x68, 0x65, 0x61, 0x64, 0x28, 0x6e, 0xdc, 0x4a, 0x00, 0x00, 0x3a, 0x14, 0x00, 0x00, 0x00, 0x36, 0x68, 0x68, 0x65, 0x61, 0x0c, 0x9d, 0x0b, 0xd8, 0x00, 0x00, + 0x3c, 0x38, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0xf4, 0x22, 0x11, 0xe6, 0x00, 0x00, 0x3a, 0x4c, 0x00, 0x00, 0x01, 0xea, 0x6c, 0x6f, 0x63, 0x61, + 0x08, 0xbe, 0xfb, 0x1b, 0x00, 0x00, 0x39, 0x08, 0x00, 0x00, 0x01, 0x0a, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x55, 0x10, 0x44, 0x00, 0x00, 0x38, 0xe8, 0x00, 0x00, + 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x27, 0x83, 0x40, 0x7b, 0x00, 0x00, 0x4d, 0x30, 0x00, 0x00, 0x01, 0xe4, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x9f, 0x00, 0x32, + 0x00, 0x00, 0x4f, 0x14, 0x00, 0x00, 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0x44, 0x7e, 0xc6, 0xb9, 0x00, 0x00, 0x4a, 0xfc, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, + 0x00, 0x36, 0xff, 0xf3, 0x00, 0xe3, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, + 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x24, 0x23, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x37, 0x23, 0x03, 0x33, 0x03, 0x34, 0x36, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0xc9, 0x78, 0x19, 0xaa, 0xac, 0x33, 0x24, 0x23, 0x33, 0x33, 0x23, 0x24, 0x33, 0xe8, 0x01, 0xe2, 0xfd, + 0x7c, 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x02, 0x00, 0x3d, 0x01, 0xc8, 0x01, 0xa1, 0x02, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x40, 0x21, + 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x05, 0x03, 0x04, 0x03, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, + 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0x21, 0x03, 0x23, 0x03, 0xcd, 0x14, 0x68, 0x14, 0x01, 0x64, 0x14, 0x67, 0x14, 0x02, + 0xca, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x00, 0x16, 0x00, 0x00, 0x02, 0x70, 0x02, 0xc9, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, + 0x40, 0x44, 0x0c, 0x0a, 0x02, 0x08, 0x0f, 0x10, 0x0d, 0x03, 0x07, 0x00, 0x08, 0x07, 0x68, 0x0e, 0x06, 0x02, 0x00, 0x05, 0x03, 0x02, 0x01, 0x02, 0x00, 0x01, + 0x67, 0x0b, 0x01, 0x09, 0x09, 0x6a, 0x4d, 0x04, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, 0x1c, 0x00, 0x1b, 0x00, 0x1b, 0x1a, 0x19, + 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0d, 0x1f, 0x2b, 0x01, 0x07, 0x33, 0x15, 0x23, 0x07, 0x23, + 0x37, 0x23, 0x07, 0x23, 0x37, 0x23, 0x35, 0x33, 0x37, 0x23, 0x35, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, 0x15, 0x05, 0x33, 0x37, 0x23, 0x01, + 0xe8, 0x17, 0x7e, 0x91, 0x26, 0x6b, 0x26, 0x5f, 0x25, 0x69, 0x24, 0x74, 0x87, 0x17, 0x7b, 0x8d, 0x26, 0x6b, 0x26, 0x61, 0x26, 0x69, 0x26, 0x75, 0xfe, 0x97, + 0x60, 0x17, 0x60, 0x01, 0x9c, 0x71, 0x65, 0xc6, 0xc6, 0xc6, 0xc6, 0x65, 0x71, 0x66, 0xc7, 0xc7, 0xc7, 0xc7, 0x66, 0x71, 0x71, 0x00, 0x00, 0x03, 0x00, 0x2b, + 0xff, 0xc6, 0x02, 0x15, 0x02, 0xf7, 0x00, 0x22, 0x00, 0x28, 0x00, 0x2e, 0x00, 0x3f, 0x40, 0x3c, 0x2e, 0x29, 0x28, 0x23, 0x19, 0x18, 0x15, 0x14, 0x08, 0x04, + 0x0a, 0x01, 0x03, 0x20, 0x03, 0x02, 0x00, 0x01, 0x02, 0x4c, 0x0f, 0x01, 0x03, 0x01, 0x4b, 0x00, 0x03, 0x02, 0x01, 0x02, 0x03, 0x01, 0x80, 0x00, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x04, 0x04, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6c, 0x04, 0x4e, 0x1e, 0x11, 0x19, 0x15, 0x10, 0x05, 0x0d, 0x1b, 0x2b, 0x37, + 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x35, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x37, 0x35, 0x33, 0x15, 0x16, 0x17, 0x07, 0x26, 0x26, 0x27, 0x15, 0x1e, 0x02, + 0x15, 0x14, 0x06, 0x07, 0x15, 0x23, 0x11, 0x06, 0x15, 0x14, 0x16, 0x17, 0x13, 0x36, 0x35, 0x34, 0x26, 0x27, 0xfd, 0x41, 0x66, 0x2a, 0x29, 0x74, 0x34, 0x4d, + 0x5d, 0x28, 0x75, 0x5d, 0x43, 0x6f, 0x5b, 0x2e, 0x28, 0x51, 0x23, 0x36, 0x62, 0x3d, 0x6a, 0x6b, 0x43, 0x3f, 0x1e, 0x21, 0x43, 0x42, 0x21, 0x21, 0x28, 0x02, + 0x15, 0x13, 0x81, 0x14, 0x21, 0x03, 0x97, 0x1e, 0x39, 0x46, 0x31, 0x4b, 0x59, 0x08, 0x4b, 0x49, 0x04, 0x29, 0x72, 0x11, 0x12, 0x03, 0x90, 0x14, 0x2f, 0x48, + 0x3b, 0x49, 0x62, 0x0a, 0x64, 0x02, 0x6d, 0x09, 0x2a, 0x15, 0x1c, 0x0f, 0xfe, 0xde, 0x0c, 0x2e, 0x14, 0x1d, 0x0f, 0x00, 0x00, 0x05, 0x00, 0x1e, 0xff, 0xf7, + 0x03, 0x68, 0x02, 0xd4, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x33, 0x00, 0xd2, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x2c, 0x0d, 0x01, 0x06, + 0x0e, 0x01, 0x08, 0x01, 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, 0x0b, 0x03, 0x0a, 0x03, 0x00, + 0x00, 0x70, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x07, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x1a, 0x50, 0x58, 0x40, 0x30, 0x0d, 0x01, 0x06, + 0x0e, 0x01, 0x08, 0x01, 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0b, 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x0c, 0x01, 0x04, 0x04, 0x00, + 0x61, 0x0a, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x07, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x34, 0x0d, 0x01, 0x06, 0x0e, + 0x01, 0x08, 0x01, 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0b, 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x0a, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x09, 0x09, 0x07, 0x61, 0x00, 0x07, 0x07, 0x71, 0x07, 0x4e, 0x59, 0x59, 0x40, 0x2b, + 0x29, 0x28, 0x1d, 0x1c, 0x11, 0x10, 0x0c, 0x0c, 0x01, 0x00, 0x2f, 0x2d, 0x28, 0x33, 0x29, 0x33, 0x23, 0x21, 0x1c, 0x27, 0x1d, 0x27, 0x17, 0x15, 0x10, 0x1b, + 0x11, 0x1b, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, + 0x26, 0x35, 0x34, 0x36, 0x05, 0x01, 0x23, 0x01, 0x05, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x05, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xc6, 0x50, 0x5c, 0x56, 0x56, 0x4e, 0x5a, 0x55, + 0x02, 0x50, 0xfe, 0x74, 0x77, 0x01, 0x8c, 0xfe, 0x7b, 0x1b, 0x18, 0x18, 0x1b, 0x1c, 0x19, 0x19, 0x01, 0xd9, 0x4f, 0x5d, 0x57, 0x55, 0x4e, 0x5a, 0x55, 0x54, + 0x1c, 0x17, 0x17, 0x1c, 0x1c, 0x19, 0x19, 0x02, 0xd4, 0x75, 0x6a, 0x6a, 0x77, 0x77, 0x6a, 0x6a, 0x75, 0x0a, 0xfd, 0x36, 0x02, 0xca, 0x57, 0x42, 0x3d, 0x3d, + 0x43, 0x42, 0x3e, 0x3d, 0x42, 0xbc, 0x75, 0x6a, 0x6a, 0x77, 0x77, 0x6a, 0x6a, 0x75, 0x61, 0x42, 0x3d, 0x3d, 0x43, 0x42, 0x3e, 0x3e, 0x41, 0x00, 0x00, 0x03, + 0x00, 0x28, 0xff, 0xf6, 0x02, 0xee, 0x02, 0xd4, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x37, 0x00, 0x7d, 0x40, 0x12, 0x28, 0x1b, 0x02, 0x01, 0x04, 0x37, 0x0f, 0x08, + 0x07, 0x04, 0x05, 0x01, 0x12, 0x01, 0x02, 0x05, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x23, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, + 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, + 0x1b, 0x40, 0x21, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6b, 0x4d, 0x00, + 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x59, 0x40, 0x17, 0x23, 0x22, 0x01, 0x00, 0x35, 0x33, 0x22, 0x2d, 0x23, 0x2d, 0x16, 0x14, 0x11, + 0x10, 0x0c, 0x0b, 0x00, 0x21, 0x01, 0x21, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, + 0x07, 0x17, 0x23, 0x27, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, + 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x01, 0x36, 0x3a, 0x5a, 0x34, 0x52, 0x3d, 0x8b, 0x14, 0x1e, 0x0a, + 0x9b, 0x0f, 0x3a, 0x2d, 0x93, 0xb8, 0x38, 0x2b, 0x6a, 0x3e, 0x7a, 0x89, 0x46, 0x3d, 0x27, 0x1f, 0x35, 0x5f, 0x3c, 0x19, 0x2d, 0x19, 0x15, 0x2a, 0x2d, 0x28, + 0x4a, 0x1c, 0x21, 0x40, 0x30, 0x20, 0x38, 0x17, 0x02, 0xd4, 0x24, 0x45, 0x32, 0x45, 0x5e, 0x23, 0x87, 0x22, 0x4b, 0x26, 0x38, 0x80, 0x38, 0x8f, 0x37, 0x1e, + 0x23, 0x70, 0x5b, 0x4c, 0x5b, 0x23, 0x2d, 0x4c, 0x2b, 0x33, 0x4a, 0x28, 0x73, 0x19, 0x23, 0x19, 0x2e, 0x18, 0x17, 0x2e, 0x1e, 0x1e, 0x1a, 0xfe, 0xd1, 0x15, + 0x2f, 0x1f, 0x2b, 0x31, 0x10, 0x0e, 0x00, 0x01, 0x00, 0x3d, 0x01, 0xc8, 0x00, 0xcd, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x01, + 0x5f, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0xcd, 0x14, 0x68, + 0x14, 0x02, 0xca, 0xfe, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, 0x62, 0x01, 0x35, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, 0x00, 0x01, + 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x16, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x13, 0x34, 0x36, 0x37, 0x33, 0x06, 0x06, 0x15, 0x14, 0x16, 0x17, + 0x23, 0x26, 0x26, 0x28, 0x47, 0x4c, 0x7a, 0x44, 0x47, 0x47, 0x43, 0x79, 0x4c, 0x47, 0x01, 0x12, 0x7a, 0xe3, 0x5b, 0x5e, 0xe2, 0x77, 0x74, 0xe1, 0x5c, 0x58, + 0xdf, 0x00, 0x00, 0x01, 0x00, 0x1e, 0xff, 0x62, 0x01, 0x2b, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, + 0x6a, 0x00, 0x4e, 0x16, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x23, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x01, 0x2b, 0x47, + 0x4c, 0x79, 0x44, 0x46, 0x47, 0x44, 0x7a, 0x4c, 0x47, 0x01, 0x12, 0x79, 0xdf, 0x58, 0x5c, 0xe1, 0x74, 0x77, 0xe2, 0x5e, 0x5b, 0xe3, 0x00, 0x01, 0x00, 0x1d, + 0x01, 0x24, 0x02, 0x01, 0x02, 0xf8, 0x00, 0x0e, 0x00, 0x23, 0x40, 0x20, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x0d, + 0x00, 0x49, 0x01, 0x01, 0x00, 0x00, 0x6c, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x02, 0x0d, 0x16, 0x2b, 0x01, 0x07, 0x37, 0x17, 0x07, 0x17, 0x07, + 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x27, 0x01, 0x4f, 0x14, 0xb5, 0x11, 0xa5, 0x6c, 0x6f, 0x4c, 0x43, 0x74, 0x6c, 0xa5, 0x13, 0xb2, 0x14, 0x02, 0xf8, + 0xb4, 0x33, 0x7c, 0x0c, 0x90, 0x3b, 0x98, 0x98, 0x3b, 0x90, 0x0e, 0x7a, 0x33, 0xb4, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x6f, 0x02, 0x10, 0x02, 0x54, 0x00, 0x0b, + 0x00, 0x26, 0x40, 0x23, 0x00, 0x05, 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, 0x05, 0x02, 0x5f, 0x00, + 0x02, 0x05, 0x02, 0x4f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, + 0x01, 0x53, 0xbd, 0xbd, 0x6b, 0xbd, 0xbd, 0x6b, 0x01, 0x96, 0x6b, 0xbc, 0xbc, 0x6b, 0xbe, 0x00, 0x00, 0x01, 0x00, 0x1f, 0xff, 0x7f, 0x00, 0xe0, 0x00, 0x74, + 0x00, 0x08, 0x00, 0x18, 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x13, 0x13, 0x02, 0x0d, + 0x18, 0x2b, 0x37, 0x06, 0x06, 0x07, 0x23, 0x36, 0x36, 0x37, 0x33, 0xe0, 0x0d, 0x30, 0x19, 0x6b, 0x0e, 0x1c, 0x07, 0x89, 0x69, 0x35, 0x7e, 0x37, 0x3b, 0x86, + 0x34, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0xce, 0x01, 0x23, 0x01, 0x4a, 0x00, 0x03, 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, + 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, 0x35, 0x21, 0x15, 0x1c, 0x01, + 0x07, 0xce, 0x7c, 0x7c, 0x00, 0x01, 0x00, 0x36, 0xff, 0xf3, 0x00, 0xe3, 0x00, 0x9a, 0x00, 0x0b, 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x22, 0x02, 0x0d, 0x18, 0x2b, 0x37, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x36, 0x33, 0x24, + 0x23, 0x33, 0x33, 0x23, 0x24, 0x33, 0x46, 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x01, 0x00, 0x07, 0xff, 0xfa, 0x01, 0x9a, 0x02, 0xd0, 0x00, 0x03, + 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, + 0x2b, 0x01, 0x01, 0x23, 0x01, 0x01, 0x9a, 0xfe, 0xf6, 0x89, 0x01, 0x0a, 0x02, 0xd0, 0xfd, 0x2a, 0x02, 0xd6, 0x00, 0x02, 0x00, 0x24, 0xff, 0xf6, 0x02, 0x17, + 0x02, 0xd5, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x24, 0x25, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, + 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x17, 0x31, 0x6d, 0x5c, 0x81, 0x78, 0x30, 0x6e, 0x5b, 0x80, 0x7a, 0xfe, + 0xa3, 0x2a, 0x39, 0x38, 0x2c, 0x2c, 0x38, 0x39, 0x2a, 0x01, 0x65, 0x73, 0xa4, 0x58, 0xc3, 0xac, 0x74, 0xa4, 0x58, 0xc2, 0xae, 0x7a, 0x7b, 0x7a, 0x7b, 0x7a, + 0x7c, 0x7c, 0x00, 0x01, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x9d, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x1b, 0x40, 0x18, 0x0a, 0x09, 0x05, 0x03, 0x00, 0x01, 0x01, 0x4c, + 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1a, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x21, 0x23, 0x11, 0x34, 0x36, 0x37, 0x06, 0x06, 0x07, + 0x07, 0x27, 0x37, 0x33, 0x01, 0x9d, 0x97, 0x03, 0x01, 0x05, 0x21, 0x0e, 0x52, 0x49, 0xe6, 0x7c, 0x01, 0x9d, 0x1a, 0x54, 0x20, 0x06, 0x1f, 0x0c, 0x42, 0x5b, + 0xb7, 0x00, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x02, 0x1b, 0x02, 0xd4, 0x00, 0x1d, 0x00, 0x2d, 0x40, 0x2a, 0x0e, 0x01, 0x01, 0x02, 0x0d, 0x01, 0x03, 0x01, + 0x02, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, + 0x4e, 0x28, 0x26, 0x28, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x3e, 0x02, 0x33, + 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x15, 0x21, 0x02, 0x1b, 0xfe, 0x0d, 0xb3, 0x36, 0x42, 0x1e, 0x2f, 0x28, 0x29, 0x4e, 0x2b, 0x52, 0x1f, + 0x45, 0x5b, 0x40, 0x46, 0x65, 0x37, 0x2f, 0x59, 0x3f, 0x5c, 0x01, 0x37, 0x69, 0xb5, 0x38, 0x4b, 0x3d, 0x23, 0x2b, 0x2a, 0x26, 0x23, 0x61, 0x1b, 0x2e, 0x1d, + 0x33, 0x57, 0x37, 0x3b, 0x62, 0x60, 0x3a, 0x56, 0x07, 0x00, 0x00, 0x01, 0x00, 0x26, 0xff, 0xf6, 0x02, 0x14, 0x02, 0xd4, 0x00, 0x2b, 0x00, 0x3f, 0x40, 0x3c, + 0x26, 0x01, 0x04, 0x05, 0x25, 0x01, 0x03, 0x04, 0x03, 0x01, 0x02, 0x03, 0x0e, 0x01, 0x01, 0x02, 0x0d, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x03, 0x00, 0x02, + 0x01, 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, + 0x25, 0x21, 0x25, 0x24, 0x2a, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, + 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x23, 0x23, 0x35, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, + 0x16, 0x01, 0xff, 0x59, 0x41, 0x56, 0x59, 0x3d, 0x7f, 0x64, 0x74, 0x5a, 0x2e, 0x65, 0x2b, 0x51, 0x41, 0x1e, 0x4b, 0x43, 0x36, 0x37, 0x42, 0x45, 0x19, 0x2f, + 0x37, 0x33, 0x4b, 0x1a, 0x46, 0x2a, 0x71, 0x4e, 0x6e, 0x81, 0x02, 0x2a, 0x4a, 0x58, 0x10, 0x03, 0x0a, 0x54, 0x47, 0x3e, 0x63, 0x39, 0x27, 0x80, 0x17, 0x18, + 0x38, 0x33, 0x1e, 0x29, 0x15, 0x74, 0x19, 0x2b, 0x1c, 0x26, 0x2b, 0x23, 0x11, 0x68, 0x1e, 0x28, 0x59, 0x00, 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x02, 0x2b, + 0x02, 0xca, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x27, 0x40, 0x24, 0x06, 0x01, 0x00, 0x04, 0x01, 0x4c, 0x05, 0x01, 0x04, 0x02, 0x01, 0x00, 0x01, 0x04, 0x00, 0x67, + 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1a, 0x11, 0x12, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x25, 0x23, 0x15, 0x23, 0x35, + 0x21, 0x35, 0x01, 0x33, 0x11, 0x33, 0x27, 0x34, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x07, 0x07, 0x33, 0x02, 0x2b, 0x56, 0x93, 0xfe, 0xcf, 0x01, 0x39, 0x8b, + 0x56, 0xe9, 0x02, 0x03, 0x01, 0x04, 0x09, 0x14, 0x0e, 0x83, 0xac, 0x94, 0x94, 0x94, 0x69, 0x01, 0xcd, 0xfe, 0x3f, 0x79, 0x17, 0x42, 0x39, 0x09, 0x14, 0x26, + 0x14, 0xc6, 0x00, 0x01, 0x00, 0x31, 0xff, 0xf6, 0x02, 0x0e, 0x02, 0xca, 0x00, 0x1e, 0x00, 0x44, 0x40, 0x41, 0x1c, 0x17, 0x02, 0x03, 0x00, 0x16, 0x0b, 0x02, + 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x03, 0x02, 0x00, 0x03, 0x69, 0x00, 0x05, 0x05, 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6a, + 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x01, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x14, 0x12, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x1e, + 0x01, 0x1e, 0x07, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, + 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x15, 0x23, 0x07, 0x36, 0x36, 0x01, 0x2c, 0x41, 0x66, 0x3b, 0x90, 0x8d, 0x38, 0x63, 0x25, 0x25, 0x68, 0x2e, 0x43, 0x47, + 0x8f, 0x1c, 0x3c, 0x14, 0x3c, 0x1b, 0x01, 0x83, 0xff, 0x0d, 0x11, 0x27, 0x01, 0xc8, 0x32, 0x60, 0x47, 0x74, 0x85, 0x14, 0x13, 0x82, 0x13, 0x1b, 0x37, 0x3a, + 0x6c, 0x0b, 0x05, 0x20, 0x01, 0x6c, 0x80, 0x8c, 0x03, 0x07, 0x00, 0x02, 0x00, 0x23, 0xff, 0xf6, 0x02, 0x1b, 0x02, 0xd2, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x69, + 0x40, 0x0e, 0x09, 0x01, 0x01, 0x00, 0x0a, 0x01, 0x02, 0x01, 0x11, 0x01, 0x05, 0x02, 0x03, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1e, 0x00, 0x02, 0x00, + 0x05, 0x04, 0x02, 0x05, 0x69, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, + 0x4e, 0x1b, 0x40, 0x1e, 0x00, 0x02, 0x00, 0x05, 0x04, 0x02, 0x05, 0x69, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x70, 0x4d, 0x06, 0x01, 0x04, 0x04, + 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x20, 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x24, 0x26, 0x24, 0x35, 0x07, 0x0d, 0x1a, + 0x2b, 0x13, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x17, 0x15, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x23, 0x22, 0x26, 0x26, 0x05, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x23, 0x12, 0x2d, 0x51, 0x7d, 0x59, 0x15, 0x38, + 0x13, 0x13, 0x2d, 0x16, 0x59, 0x61, 0x28, 0x03, 0x06, 0x14, 0x4b, 0x3c, 0x5e, 0x6e, 0x83, 0x70, 0x49, 0x76, 0x46, 0x01, 0x02, 0x2c, 0x38, 0x30, 0x31, 0x21, + 0x32, 0x1c, 0x18, 0x31, 0x01, 0x2f, 0x3e, 0x78, 0x6b, 0x53, 0x2f, 0x03, 0x04, 0x79, 0x05, 0x05, 0x38, 0x65, 0x42, 0x23, 0x30, 0x76, 0x6c, 0x74, 0x84, 0x43, + 0x8b, 0x55, 0x3d, 0x40, 0x34, 0x3c, 0x1d, 0x2e, 0x18, 0x21, 0x3f, 0x2a, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x02, 0x1b, 0x02, 0xca, 0x00, 0x06, 0x00, 0x25, + 0x40, 0x22, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x6f, 0x01, 0x0c, 0xfe, 0xa0, 0x02, 0x00, 0xfe, + 0xf2, 0x02, 0x4b, 0x7f, 0x5f, 0xfd, 0x95, 0x00, 0x00, 0x03, 0x00, 0x23, 0xff, 0xf6, 0x02, 0x18, 0x02, 0xd3, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x35, 0x00, 0x36, + 0x40, 0x33, 0x33, 0x22, 0x15, 0x07, 0x04, 0x03, 0x02, 0x01, 0x4c, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x03, 0x03, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1d, 0x1c, 0x01, 0x00, 0x2c, 0x2a, 0x1c, 0x27, 0x1d, 0x27, 0x10, 0x0e, 0x00, 0x1b, 0x01, 0x1b, 0x06, 0x0d, + 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, + 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, + 0x27, 0x06, 0x06, 0x01, 0x1e, 0x3e, 0x67, 0x3f, 0x49, 0x37, 0x26, 0x45, 0x2b, 0x3f, 0x71, 0x4a, 0x78, 0x83, 0x50, 0x39, 0x30, 0x43, 0x40, 0x69, 0x3b, 0x25, + 0x31, 0x34, 0x23, 0x22, 0x34, 0x31, 0x94, 0x37, 0x36, 0x38, 0x38, 0x20, 0x2f, 0x19, 0x0d, 0x2e, 0x3a, 0x02, 0xd3, 0x26, 0x4c, 0x3a, 0x40, 0x53, 0x1b, 0x14, + 0x35, 0x47, 0x30, 0x3b, 0x58, 0x30, 0x66, 0x59, 0x4a, 0x5a, 0x1c, 0x1e, 0x55, 0x40, 0x39, 0x4c, 0x26, 0x6e, 0x26, 0x23, 0x25, 0x2e, 0x11, 0x10, 0x2d, 0x27, + 0x23, 0x26, 0xfe, 0x59, 0x27, 0x32, 0x30, 0x28, 0x1b, 0x29, 0x21, 0x0e, 0x07, 0x16, 0x3a, 0x00, 0x00, 0x02, 0x00, 0x20, 0xff, 0xf6, 0x02, 0x18, 0x02, 0xd2, + 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x3e, 0x40, 0x3b, 0x11, 0x01, 0x02, 0x05, 0x0a, 0x01, 0x01, 0x02, 0x09, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, + 0x01, 0x05, 0x02, 0x69, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x20, 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x24, 0x26, 0x24, 0x35, 0x07, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x0e, 0x03, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, + 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x16, 0x25, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, + 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x26, 0x02, 0x18, 0x12, 0x2d, 0x51, 0x7d, 0x59, 0x15, 0x38, 0x13, 0x14, 0x2c, 0x16, 0x59, 0x61, 0x28, 0x03, 0x06, 0x15, + 0x45, 0x44, 0x5b, 0x6e, 0x83, 0x70, 0x49, 0x76, 0x46, 0xfe, 0xfe, 0x2c, 0x38, 0x30, 0x31, 0x22, 0x31, 0x1c, 0x18, 0x30, 0x01, 0x99, 0x3d, 0x79, 0x6b, 0x53, + 0x2f, 0x03, 0x04, 0x79, 0x04, 0x06, 0x39, 0x64, 0x42, 0x23, 0x30, 0x76, 0x6c, 0x74, 0x84, 0x43, 0x8b, 0x55, 0x3c, 0x41, 0x34, 0x3c, 0x1e, 0x2d, 0x18, 0x21, + 0x40, 0x29, 0x00, 0x02, 0x00, 0x36, 0xff, 0xf3, 0x00, 0xe3, 0x02, 0x2c, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, + 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x11, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x36, 0x33, 0x24, 0x23, 0x33, + 0x33, 0x23, 0x24, 0x33, 0x33, 0x24, 0x23, 0x33, 0x33, 0x23, 0x24, 0x33, 0x01, 0xd9, 0x2e, 0x25, 0x25, 0x2e, 0x2d, 0x27, 0x27, 0xfe, 0x9a, 0x2e, 0x26, 0x26, + 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x02, 0x00, 0x1f, 0xff, 0x7f, 0x00, 0xe4, 0x02, 0x2c, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x02, + 0x03, 0x02, 0x63, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x01, 0x4e, 0x13, 0x15, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x13, 0x06, 0x06, 0x07, 0x23, 0x36, 0x36, 0x37, 0x33, 0x39, 0x32, 0x24, 0x23, 0x32, 0x32, 0x23, 0x24, 0x32, + 0xa7, 0x0d, 0x30, 0x19, 0x6b, 0x0e, 0x1c, 0x07, 0x89, 0x01, 0xd9, 0x2e, 0x25, 0x25, 0x2e, 0x2c, 0x27, 0x27, 0xfe, 0xbc, 0x35, 0x7e, 0x37, 0x3b, 0x86, 0x34, + 0x00, 0x01, 0x00, 0x2b, 0x00, 0x63, 0x02, 0x10, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, 0x32, 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, + 0x05, 0x02, 0x10, 0xfe, 0x1b, 0x01, 0xe5, 0xfe, 0xb2, 0x01, 0x4e, 0x63, 0xd6, 0x46, 0xf2, 0x75, 0x9b, 0x89, 0x00, 0x02, 0x00, 0x2b, 0x00, 0xcc, 0x02, 0x10, + 0x01, 0xf4, 0x00, 0x03, 0x00, 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, + 0x02, 0x02, 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, + 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, 0x35, 0x21, 0x15, 0x2b, 0x01, 0xe5, 0xfe, 0x1b, 0x01, 0xe5, 0x01, 0x8a, 0x6a, 0x6a, 0xbe, 0x6b, 0x6b, 0x00, + 0x00, 0x01, 0x00, 0x2b, 0x00, 0x63, 0x02, 0x10, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, 0x25, 0x25, 0x35, 0x05, 0x15, + 0x05, 0x2b, 0x01, 0x4e, 0xfe, 0xb2, 0x01, 0xe5, 0xfe, 0x1b, 0xd8, 0x89, 0x9b, 0x75, 0xf2, 0x46, 0xd6, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0xf3, 0x01, 0xc8, + 0x02, 0xd4, 0x00, 0x1d, 0x00, 0x29, 0x00, 0x32, 0x40, 0x2f, 0x0e, 0x01, 0x00, 0x01, 0x0d, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, + 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x04, 0x4e, 0x24, 0x23, 0x1a, + 0x25, 0x29, 0x05, 0x0d, 0x1b, 0x2b, 0x13, 0x34, 0x36, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x07, 0x0e, 0x02, 0x15, 0x15, 0x23, 0x07, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x8e, 0x24, 0x33, 0x24, 0x24, 0x0d, + 0x2f, 0x29, 0x2a, 0x53, 0x2b, 0x35, 0x31, 0x72, 0x44, 0x69, 0x73, 0x3a, 0x3b, 0x1f, 0x22, 0x0d, 0x77, 0x15, 0x32, 0x25, 0x22, 0x33, 0x33, 0x22, 0x25, 0x32, + 0x01, 0x0c, 0x32, 0x45, 0x24, 0x19, 0x24, 0x21, 0x14, 0x1f, 0x22, 0x1a, 0x16, 0x6d, 0x1b, 0x22, 0x60, 0x51, 0x3d, 0x54, 0x2a, 0x16, 0x21, 0x1e, 0x15, 0x16, + 0xa2, 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xb0, 0x03, 0x53, 0x02, 0xcf, 0x00, 0x3e, 0x00, 0x4c, 0x00, 0x7e, 0x40, 0x16, + 0x16, 0x01, 0x09, 0x02, 0x46, 0x01, 0x03, 0x09, 0x08, 0x01, 0x00, 0x03, 0x2e, 0x01, 0x05, 0x00, 0x2f, 0x01, 0x06, 0x05, 0x05, 0x4c, 0x4b, 0xb0, 0x2c, 0x50, + 0x58, 0x40, 0x26, 0x08, 0x01, 0x03, 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, 0x00, + 0x07, 0x07, 0x6a, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x24, 0x00, 0x02, 0x00, 0x09, 0x03, 0x02, 0x09, 0x69, + 0x08, 0x01, 0x03, 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, 0x00, 0x07, 0x07, 0x6a, + 0x04, 0x4e, 0x59, 0x40, 0x0e, 0x4a, 0x48, 0x25, 0x27, 0x25, 0x25, 0x25, 0x28, 0x25, 0x25, 0x24, 0x0a, 0x0d, 0x1f, 0x2b, 0x01, 0x14, 0x0e, 0x02, 0x23, 0x22, + 0x26, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x14, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, + 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, + 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x03, 0x53, 0x17, 0x2e, 0x43, 0x2d, 0x27, 0x3c, 0x0e, + 0x06, 0x15, 0x42, 0x2e, 0x56, 0x59, 0x37, 0x69, 0x4c, 0x2f, 0x5a, 0x1c, 0x0a, 0x01, 0x17, 0x10, 0x17, 0x21, 0x11, 0x8e, 0x7d, 0x69, 0x8f, 0x4a, 0x8e, 0x8b, + 0x39, 0x7e, 0x36, 0x31, 0x76, 0x42, 0x7c, 0xb0, 0x5e, 0x3c, 0x70, 0x9f, 0x63, 0x6f, 0xa8, 0x5f, 0xfe, 0x12, 0x2a, 0x23, 0x2e, 0x28, 0x04, 0x05, 0x0b, 0x18, + 0x0e, 0x2c, 0x36, 0x19, 0x01, 0x6c, 0x2e, 0x5a, 0x49, 0x2b, 0x27, 0x1e, 0x1d, 0x28, 0x6a, 0x57, 0x42, 0x68, 0x3c, 0x12, 0x0a, 0xcd, 0x0a, 0x17, 0x09, 0x23, + 0x18, 0x2d, 0x4b, 0x2c, 0x7b, 0x8b, 0x56, 0x98, 0x62, 0x82, 0x94, 0x1a, 0x13, 0x5e, 0x15, 0x17, 0x59, 0xa6, 0x74, 0x5b, 0x9c, 0x75, 0x40, 0x56, 0x9f, 0xa9, + 0x37, 0x31, 0x48, 0x47, 0x5f, 0x02, 0x04, 0x28, 0x3f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0xb4, 0x02, 0xcd, 0x00, 0x07, 0x00, 0x12, 0x00, 0x2c, + 0x40, 0x29, 0x0c, 0x01, 0x04, 0x02, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x68, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, + 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x12, 0x11, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x21, 0x27, 0x23, 0x07, 0x23, 0x13, 0x33, 0x13, + 0x01, 0x2e, 0x02, 0x27, 0x0e, 0x02, 0x07, 0x07, 0x33, 0x02, 0x0f, 0x37, 0xfc, 0x37, 0xa5, 0xfb, 0xbc, 0xfd, 0xfe, 0xcf, 0x04, 0x11, 0x10, 0x05, 0x04, 0x0f, + 0x0e, 0x05, 0x33, 0xb5, 0xa8, 0xa8, 0x02, 0xcd, 0xfd, 0x33, 0x01, 0xc3, 0x0f, 0x3c, 0x3f, 0x14, 0x17, 0x3b, 0x39, 0x13, 0x9b, 0x00, 0x00, 0x03, 0x00, 0x55, + 0x00, 0x00, 0x02, 0x67, 0x02, 0xca, 0x00, 0x10, 0x00, 0x19, 0x00, 0x22, 0x00, 0x44, 0x40, 0x41, 0x06, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x08, + 0x01, 0x05, 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x04, 0x04, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6b, + 0x01, 0x4e, 0x1a, 0x1a, 0x12, 0x11, 0x01, 0x00, 0x1a, 0x22, 0x1a, 0x21, 0x1d, 0x1b, 0x18, 0x16, 0x11, 0x19, 0x12, 0x19, 0x0f, 0x0d, 0x00, 0x10, 0x01, 0x10, + 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, + 0x23, 0x23, 0x1d, 0x02, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x3c, 0x93, 0x86, 0x47, 0x32, 0x23, 0x40, 0x28, 0x8d, 0x7a, 0xfe, 0xf5, 0xef, 0x41, + 0x33, 0x3c, 0x3f, 0x4f, 0x61, 0x44, 0x35, 0x36, 0x48, 0x02, 0xca, 0x57, 0x5b, 0x43, 0x4f, 0x0b, 0x05, 0x07, 0x24, 0x44, 0x38, 0x62, 0x6d, 0x02, 0xca, 0xfe, + 0xe2, 0x30, 0x27, 0x29, 0x27, 0xa7, 0x73, 0xc0, 0x37, 0x2b, 0x27, 0x37, 0x00, 0x01, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x63, 0x02, 0xd4, 0x00, 0x1a, 0x00, 0x37, + 0x40, 0x34, 0x17, 0x01, 0x00, 0x03, 0x18, 0x09, 0x02, 0x01, 0x00, 0x0a, 0x01, 0x02, 0x01, 0x03, 0x4c, 0x04, 0x01, 0x00, 0x00, 0x03, 0x61, 0x00, 0x03, 0x03, + 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x01, 0x00, 0x15, 0x13, 0x0d, 0x0b, 0x07, 0x05, 0x00, 0x1a, 0x01, 0x1a, 0x05, + 0x0d, 0x16, 0x2b, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x17, 0x07, 0x26, 0x26, 0x01, 0x8e, 0x56, 0x63, 0x5f, 0x60, 0x2f, 0x57, 0x2c, 0x55, 0x6e, 0x72, 0x93, 0x47, 0x50, 0x9a, 0x6f, 0x35, 0x6d, 0x31, 0x32, 0x24, + 0x51, 0x02, 0x55, 0x81, 0x71, 0x71, 0x7d, 0x16, 0x11, 0x82, 0x24, 0x5b, 0xa5, 0x6e, 0x6c, 0xa6, 0x5e, 0x17, 0x18, 0x7a, 0x11, 0x19, 0x00, 0x02, 0x00, 0x55, + 0x00, 0x00, 0x02, 0xa6, 0x02, 0xca, 0x00, 0x09, 0x00, 0x11, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x03, + 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x21, 0x24, 0x21, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, 0x23, 0x23, 0x11, 0x33, 0x32, + 0x16, 0x07, 0x34, 0x26, 0x23, 0x23, 0x11, 0x33, 0x32, 0x02, 0xa6, 0x5c, 0xa8, 0x73, 0xda, 0xec, 0xa8, 0xbd, 0xa0, 0x66, 0x63, 0x4f, 0x40, 0xd8, 0x01, 0x71, + 0x7b, 0xa4, 0x52, 0x02, 0xca, 0xb1, 0xae, 0x73, 0x6f, 0xfe, 0x31, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x01, 0xf5, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x29, + 0x40, 0x26, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x5f, 0x00, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x21, 0x11, 0x21, 0x15, 0x21, 0x15, 0x33, 0x15, 0x23, 0x15, + 0x21, 0x01, 0xf5, 0xfe, 0x65, 0x01, 0x9b, 0xfe, 0xfc, 0xf2, 0xf2, 0x01, 0x04, 0x02, 0xca, 0x7c, 0x9d, 0x7c, 0xb8, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, + 0x01, 0xf3, 0x02, 0xca, 0x00, 0x09, 0x00, 0x23, 0x40, 0x20, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, + 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x10, 0x05, 0x0d, 0x1b, 0x2b, 0x33, 0x23, 0x11, 0x21, 0x15, 0x21, 0x15, 0x33, 0x15, + 0x23, 0xef, 0x95, 0x01, 0x99, 0xfe, 0xfc, 0xf2, 0xf2, 0x02, 0xca, 0x7c, 0xb8, 0x7c, 0x00, 0x01, 0x00, 0x3a, 0xff, 0xf6, 0x02, 0x84, 0x02, 0xd4, 0x00, 0x20, + 0x00, 0x3b, 0x40, 0x38, 0x0f, 0x01, 0x03, 0x02, 0x10, 0x01, 0x00, 0x03, 0x1e, 0x01, 0x04, 0x05, 0x02, 0x01, 0x01, 0x04, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x05, + 0x04, 0x00, 0x05, 0x67, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x13, + 0x26, 0x25, 0x25, 0x23, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x21, 0x11, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, + 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x35, 0x23, 0x01, 0x69, 0x01, 0x1b, 0x38, 0x79, 0x4d, 0xa0, 0xac, 0x57, + 0xa6, 0x78, 0x39, 0x6e, 0x2d, 0x32, 0x21, 0x54, 0x2e, 0x42, 0x61, 0x35, 0x26, 0x52, 0x42, 0x20, 0x2d, 0x13, 0x87, 0x01, 0x91, 0xfe, 0x8e, 0x13, 0x16, 0xbc, + 0xb4, 0x70, 0xa4, 0x5a, 0x18, 0x14, 0x79, 0x11, 0x16, 0x3c, 0x6d, 0x4a, 0x46, 0x6c, 0x3d, 0x06, 0x04, 0x95, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0xa3, + 0x02, 0xca, 0x00, 0x0b, 0x00, 0x21, 0x40, 0x1e, 0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x01, 0x67, 0x05, 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x02, 0x01, 0x00, 0x00, + 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x02, + 0xa3, 0x97, 0xfe, 0xe5, 0x97, 0x97, 0x01, 0x1b, 0x97, 0x01, 0x34, 0xfe, 0xcc, 0x02, 0xca, 0xfe, 0xe8, 0x01, 0x18, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, + 0x01, 0x65, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x0a, 0x09, 0x08, 0x05, 0x04, 0x03, 0x02, 0x08, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x01, 0x01, + 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x11, 0x27, 0x35, 0x21, 0x15, 0x07, 0x11, 0x17, + 0x01, 0x65, 0xfe, 0xbb, 0x57, 0x57, 0x01, 0x45, 0x57, 0x57, 0x56, 0x28, 0x01, 0xce, 0x28, 0x56, 0x56, 0x28, 0xfe, 0x32, 0x28, 0x00, 0x00, 0x01, 0xff, 0xb6, + 0xff, 0x2e, 0x00, 0xf1, 0x02, 0xca, 0x00, 0x11, 0x00, 0x28, 0x40, 0x25, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, + 0x00, 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, 0x01, 0x00, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x11, 0x01, 0x11, 0x04, 0x0d, 0x16, 0x2b, 0x17, 0x22, + 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x06, 0x0f, 0x1d, 0x2c, 0x10, 0x10, 0x23, 0x14, 0x1a, 0x2b, 0x18, + 0x97, 0x39, 0x66, 0xd2, 0x07, 0x04, 0x7e, 0x04, 0x06, 0x14, 0x38, 0x34, 0x02, 0x9d, 0xfd, 0x64, 0x5c, 0x71, 0x33, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, + 0x02, 0x98, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x20, 0x40, 0x1d, 0x0e, 0x08, 0x03, 0x02, 0x04, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, + 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x11, 0x13, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x07, 0x15, 0x23, 0x11, 0x33, 0x11, 0x36, 0x36, 0x37, + 0x37, 0x33, 0x03, 0x02, 0x98, 0xac, 0xbb, 0x40, 0x97, 0x97, 0x0f, 0x1e, 0x0f, 0xc1, 0xa8, 0xf9, 0x01, 0x2d, 0x2e, 0xff, 0x02, 0xca, 0xfe, 0xb9, 0x15, 0x2a, + 0x15, 0xf3, 0xfe, 0xc4, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x02, 0x0f, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, + 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x11, 0x33, + 0x11, 0x21, 0x15, 0x55, 0x99, 0x01, 0x21, 0x02, 0xca, 0xfd, 0xb4, 0x7e, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x03, 0x55, 0x02, 0xca, 0x00, 0x17, 0x00, 0x26, + 0x40, 0x23, 0x15, 0x0b, 0x02, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x05, 0x04, 0x03, 0x03, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, + 0x00, 0x17, 0x00, 0x17, 0x11, 0x13, 0x11, 0x17, 0x06, 0x0d, 0x1a, 0x2b, 0x21, 0x03, 0x23, 0x1e, 0x02, 0x15, 0x11, 0x23, 0x11, 0x33, 0x13, 0x33, 0x13, 0x33, + 0x11, 0x23, 0x11, 0x34, 0x36, 0x36, 0x37, 0x23, 0x03, 0x01, 0x88, 0xac, 0x04, 0x01, 0x04, 0x04, 0x87, 0xce, 0xa9, 0x03, 0xb3, 0xce, 0x8d, 0x03, 0x03, 0x01, + 0x04, 0xb8, 0x02, 0x30, 0x14, 0x50, 0x5b, 0x25, 0xfe, 0xb4, 0x02, 0xca, 0xfd, 0xde, 0x02, 0x22, 0xfd, 0x36, 0x01, 0x52, 0x22, 0x58, 0x4f, 0x14, 0xfd, 0xd1, + 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0xd3, 0x02, 0xca, 0x00, 0x11, 0x00, 0x1e, 0x40, 0x1b, 0x0b, 0x02, 0x02, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, + 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x16, 0x11, 0x16, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x01, 0x23, 0x16, 0x16, 0x17, 0x11, + 0x23, 0x11, 0x33, 0x01, 0x33, 0x26, 0x26, 0x27, 0x11, 0x33, 0x02, 0xd3, 0xc0, 0xfe, 0xc9, 0x04, 0x02, 0x05, 0x02, 0x87, 0xbf, 0x01, 0x36, 0x03, 0x01, 0x04, + 0x02, 0x88, 0x02, 0x1c, 0x33, 0x66, 0x33, 0xfe, 0xb0, 0x02, 0xca, 0xfd, 0xe9, 0x32, 0x62, 0x31, 0x01, 0x52, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0xdf, + 0x02, 0xd5, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x25, 0x26, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, + 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xdf, 0x49, 0x96, 0x75, 0x74, 0x97, 0x49, 0x49, 0x97, 0x75, + 0x74, 0x97, 0x48, 0xfd, 0xf9, 0x55, 0x5e, 0x60, 0x53, 0x53, 0x5f, 0x5f, 0x55, 0x01, 0x66, 0x6f, 0xa5, 0x5c, 0x5c, 0xa6, 0x6f, 0x6e, 0xa5, 0x5b, 0x5b, 0xa5, + 0x6f, 0x70, 0x7f, 0x7f, 0x70, 0x70, 0x80, 0x80, 0x00, 0x02, 0x00, 0x55, 0x00, 0x00, 0x02, 0x43, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x32, 0x40, 0x2f, + 0x00, 0x04, 0x00, 0x01, 0x02, 0x04, 0x01, 0x69, 0x06, 0x01, 0x03, 0x03, 0x00, 0x5f, 0x05, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, + 0x0d, 0x0c, 0x01, 0x00, 0x10, 0x0e, 0x0c, 0x14, 0x0d, 0x14, 0x0a, 0x09, 0x08, 0x06, 0x00, 0x0b, 0x01, 0x0b, 0x07, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x06, 0x23, 0x23, 0x15, 0x23, 0x11, 0x17, 0x23, 0x15, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x35, 0x8a, 0x84, 0x34, 0x79, 0x67, 0x41, 0x99, + 0xdb, 0x42, 0x33, 0x3f, 0x49, 0x3b, 0x02, 0xca, 0x73, 0x69, 0x3f, 0x6e, 0x44, 0xfd, 0x02, 0xca, 0x7d, 0xd2, 0x32, 0x3c, 0x30, 0x34, 0x00, 0x02, 0x00, 0x37, + 0xff, 0x56, 0x02, 0xdf, 0x02, 0xd5, 0x00, 0x14, 0x00, 0x20, 0x00, 0x2b, 0x40, 0x28, 0x03, 0x01, 0x01, 0x03, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x86, 0x00, + 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x25, 0x26, 0x41, 0x14, 0x05, + 0x0d, 0x1b, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x17, 0x23, 0x27, 0x22, 0x22, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, + 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xdf, 0x55, 0x5a, 0xad, 0xc5, 0x7f, 0x03, 0x08, 0x03, 0x74, 0x97, 0x49, 0x49, 0x97, 0x75, + 0x74, 0x97, 0x48, 0xfd, 0xf9, 0x55, 0x5e, 0x60, 0x53, 0x53, 0x5f, 0x5f, 0x55, 0x01, 0x66, 0x77, 0xb0, 0x29, 0xc0, 0xa0, 0x5c, 0xa6, 0x6f, 0x6e, 0xa5, 0x5b, + 0x5b, 0xa5, 0x6f, 0x70, 0x7f, 0x7f, 0x70, 0x70, 0x80, 0x80, 0x00, 0x02, 0x00, 0x55, 0x00, 0x00, 0x02, 0x91, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x15, 0x00, 0x3b, + 0x40, 0x38, 0x05, 0x01, 0x02, 0x05, 0x01, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, + 0x6a, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x0e, 0x0d, 0x01, 0x00, 0x11, 0x0f, 0x0d, 0x15, 0x0e, 0x15, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x00, + 0x0c, 0x01, 0x0c, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x20, 0x15, 0x14, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x11, 0x23, 0x11, 0x17, 0x23, 0x15, 0x33, 0x32, 0x36, + 0x35, 0x34, 0x26, 0x01, 0x30, 0x01, 0x17, 0x4a, 0x37, 0xcb, 0xaf, 0x9f, 0x55, 0x99, 0xd8, 0x3f, 0x3f, 0x3d, 0x42, 0x3d, 0x02, 0xca, 0xd0, 0x49, 0x5c, 0x1a, + 0xfe, 0xc5, 0x01, 0x12, 0xfe, 0xee, 0x02, 0xca, 0x77, 0xcb, 0x32, 0x39, 0x30, 0x30, 0x00, 0x01, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xff, 0x02, 0xd4, 0x00, 0x28, + 0x00, 0x2e, 0x40, 0x2b, 0x1b, 0x01, 0x03, 0x02, 0x1c, 0x06, 0x02, 0x01, 0x03, 0x05, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, + 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, 0x2d, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, + 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x2e, 0x03, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, + 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xff, 0x89, 0x7e, 0x71, 0x59, 0x33, 0x6d, 0x36, 0x38, 0x2f, 0x25, 0x3e, 0x28, 0x19, 0x3a, 0x35, 0x22, + 0x82, 0x70, 0x38, 0x65, 0x37, 0x31, 0x31, 0x4e, 0x29, 0x2b, 0x2e, 0x44, 0x43, 0x37, 0x4d, 0x2a, 0xc6, 0x5f, 0x71, 0x2b, 0x8d, 0x16, 0x25, 0x2b, 0x21, 0x1b, + 0x26, 0x21, 0x13, 0x0c, 0x21, 0x31, 0x46, 0x31, 0x60, 0x6b, 0x1a, 0x18, 0x76, 0x14, 0x16, 0x28, 0x20, 0x26, 0x2c, 0x20, 0x1a, 0x38, 0x4c, 0x00, 0x00, 0x01, + 0x00, 0x13, 0x00, 0x00, 0x02, 0x2e, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1b, 0x40, 0x18, 0x03, 0x01, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x11, 0x23, 0x35, 0x21, 0x15, 0x23, 0x01, 0x6d, 0x99, 0xc1, 0x02, + 0x1b, 0xc1, 0x02, 0x4b, 0x7f, 0x7f, 0x00, 0x01, 0x00, 0x55, 0xff, 0xf6, 0x02, 0x9f, 0x02, 0xca, 0x00, 0x12, 0x00, 0x1b, 0x40, 0x18, 0x03, 0x01, 0x01, 0x01, + 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x13, 0x23, 0x13, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x06, 0x23, + 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x02, 0x9f, 0x41, 0x83, 0x64, 0x8e, 0x94, 0x97, 0x48, 0x47, 0x4a, 0x43, + 0x97, 0xfc, 0x4a, 0x77, 0x45, 0x91, 0x77, 0x01, 0xcc, 0xfe, 0x4b, 0x58, 0x48, 0x4e, 0x53, 0x01, 0xb4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x8a, + 0x02, 0xca, 0x00, 0x0e, 0x00, 0x21, 0x40, 0x1e, 0x09, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x02, 0x02, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, + 0x4e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x01, 0x03, 0x23, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x17, 0x3e, 0x02, 0x37, 0x13, + 0x02, 0x8a, 0xf3, 0xa5, 0xf2, 0x99, 0x86, 0x04, 0x0f, 0x10, 0x03, 0x03, 0x0f, 0x10, 0x03, 0x87, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0xfe, 0x57, 0x0b, 0x3b, + 0x41, 0x16, 0x16, 0x41, 0x3b, 0x0b, 0x01, 0xa9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc7, 0x02, 0xca, 0x00, 0x26, 0x00, 0x27, 0x40, 0x24, 0x21, 0x16, + 0x08, 0x03, 0x00, 0x02, 0x01, 0x4c, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x26, 0x00, + 0x26, 0x1a, 0x11, 0x1c, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x01, 0x03, 0x23, 0x03, 0x2e, 0x03, 0x27, 0x0e, 0x03, 0x07, 0x03, 0x23, 0x03, 0x33, 0x13, 0x1e, 0x02, + 0x17, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x13, 0x1e, 0x02, 0x17, 0x3e, 0x02, 0x37, 0x13, 0x03, 0xc7, 0xb6, 0xac, 0x61, 0x03, 0x09, 0x0b, 0x08, 0x02, 0x01, 0x09, + 0x0a, 0x0a, 0x03, 0x60, 0xac, 0xb6, 0x95, 0x5b, 0x06, 0x0e, 0x0c, 0x03, 0x03, 0x0c, 0x0d, 0x05, 0x68, 0x8f, 0x68, 0x05, 0x0d, 0x0c, 0x03, 0x03, 0x0c, 0x0f, + 0x05, 0x5b, 0x02, 0xca, 0xfd, 0x36, 0x01, 0x77, 0x0b, 0x2c, 0x34, 0x2f, 0x0d, 0x0d, 0x2f, 0x33, 0x2d, 0x0c, 0xfe, 0x8a, 0x02, 0xca, 0xfe, 0x7a, 0x17, 0x46, + 0x46, 0x18, 0x19, 0x45, 0x41, 0x12, 0x01, 0x90, 0xfe, 0x70, 0x11, 0x42, 0x46, 0x18, 0x19, 0x45, 0x46, 0x17, 0x01, 0x86, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, + 0x02, 0x9a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x08, 0x05, 0x02, 0x04, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, + 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x12, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x03, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, + 0x02, 0x9a, 0xb0, 0x9e, 0x9f, 0xaa, 0xed, 0xdf, 0xaa, 0x93, 0x90, 0xab, 0xe0, 0x01, 0x01, 0xfe, 0xff, 0x01, 0x70, 0x01, 0x5a, 0xf4, 0xf4, 0xfe, 0x9d, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x72, 0x02, 0xca, 0x00, 0x08, 0x00, 0x1c, 0x40, 0x19, 0x06, 0x03, 0x02, 0x01, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x00, + 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x12, 0x12, 0x11, 0x03, 0x0d, 0x19, 0x2b, 0x01, 0x13, 0x33, 0x03, 0x11, 0x23, 0x11, 0x03, 0x33, 0x01, + 0x39, 0x93, 0xa6, 0xec, 0x9a, 0xec, 0xa6, 0x01, 0x9f, 0x01, 0x2b, 0xfe, 0x4c, 0xfe, 0xea, 0x01, 0x11, 0x01, 0xb9, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, + 0x02, 0x2b, 0x02, 0xca, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, + 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, + 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x21, 0x02, 0x2b, 0xfd, 0xed, 0x01, 0x56, 0xfe, 0xb3, 0x02, 0x01, 0xfe, 0xaa, 0x01, 0x5f, 0x62, 0x01, 0xeb, 0x7d, 0x62, + 0xfe, 0x15, 0x00, 0x01, 0x00, 0x46, 0xff, 0x62, 0x01, 0x32, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x63, 0x00, + 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x02, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x05, 0x23, 0x11, 0x33, 0x15, 0x23, 0x11, 0x33, + 0x01, 0x32, 0xec, 0xec, 0x6d, 0x6d, 0x9e, 0x03, 0x68, 0x67, 0xfd, 0x66, 0x00, 0x01, 0x00, 0x06, 0xff, 0xfa, 0x01, 0x99, 0x02, 0xd0, 0x00, 0x03, 0x00, 0x19, + 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, + 0x01, 0x23, 0x01, 0x8e, 0x01, 0x0b, 0x89, 0xfe, 0xf6, 0x02, 0xd0, 0xfd, 0x2a, 0x02, 0xd6, 0x00, 0x00, 0x01, 0x00, 0x19, 0xff, 0x62, 0x01, 0x05, 0x02, 0xca, + 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x63, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x11, 0x11, + 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x17, 0x33, 0x11, 0x23, 0x35, 0x33, 0x11, 0x23, 0x19, 0x6d, 0x6d, 0xec, 0xec, 0x37, 0x02, 0x9a, 0x67, 0xfc, 0x98, 0x00, + 0x00, 0x01, 0x00, 0x17, 0x00, 0xfe, 0x02, 0x25, 0x02, 0xce, 0x00, 0x06, 0x00, 0x27, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, + 0x00, 0x00, 0x01, 0x00, 0x85, 0x03, 0x02, 0x02, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, + 0x44, 0x37, 0x13, 0x33, 0x13, 0x23, 0x03, 0x03, 0x17, 0xd6, 0x46, 0xf2, 0x75, 0x9d, 0x89, 0xfe, 0x01, 0xd0, 0xfe, 0x30, 0x01, 0x3a, 0xfe, 0xc6, 0x00, 0x01, + 0xff, 0xfe, 0xff, 0x62, 0x01, 0x9d, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x20, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, + 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x05, 0x21, 0x35, 0x21, 0x01, 0x9d, 0xfe, 0x61, + 0x01, 0x9f, 0x9e, 0x44, 0x00, 0x01, 0x00, 0x28, 0x02, 0x5e, 0x01, 0x45, 0x02, 0xfe, 0x00, 0x0c, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x0b, 0x04, + 0x02, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x00, 0x01, 0x85, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x15, 0x03, 0x0d, 0x17, 0x2b, + 0xb1, 0x06, 0x00, 0x44, 0x13, 0x1e, 0x02, 0x17, 0x15, 0x23, 0x2e, 0x03, 0x27, 0x35, 0xd1, 0x0f, 0x2a, 0x2a, 0x11, 0x65, 0x13, 0x33, 0x35, 0x2f, 0x0e, 0x02, + 0xfe, 0x16, 0x37, 0x33, 0x13, 0x0d, 0x0d, 0x27, 0x2c, 0x28, 0x0e, 0x0a, 0x00, 0x02, 0x00, 0x28, 0xff, 0xf6, 0x02, 0x10, 0x02, 0x2c, 0x00, 0x1b, 0x00, 0x26, + 0x00, 0x7b, 0x40, 0x0e, 0x19, 0x01, 0x04, 0x00, 0x18, 0x01, 0x03, 0x04, 0x06, 0x01, 0x01, 0x06, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x20, 0x00, + 0x03, 0x08, 0x01, 0x05, 0x06, 0x03, 0x05, 0x69, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x01, 0x61, 0x02, 0x01, + 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x24, 0x00, 0x03, 0x08, 0x01, 0x05, 0x06, 0x03, 0x05, 0x69, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, + 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x00, 0x06, 0x06, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x1d, 0x1c, 0x01, 0x00, 0x23, + 0x21, 0x1c, 0x26, 0x1d, 0x26, 0x16, 0x14, 0x11, 0x0f, 0x0b, 0x09, 0x05, 0x04, 0x00, 0x1b, 0x01, 0x1b, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, + 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x13, 0x06, 0x06, + 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x35, 0x01, 0x3d, 0x66, 0x6d, 0x69, 0x1d, 0x04, 0x24, 0x4d, 0x45, 0x48, 0x60, 0x7c, 0x7b, 0x5b, 0x2d, 0x27, 0x25, + 0x4e, 0x26, 0x2c, 0x2b, 0x6f, 0x46, 0x48, 0x37, 0x27, 0x21, 0x2f, 0x41, 0x02, 0x2c, 0x61, 0x5f, 0xfe, 0x94, 0x4a, 0x2c, 0x28, 0x54, 0x57, 0x55, 0x57, 0x05, + 0x03, 0x11, 0x31, 0x27, 0x18, 0x11, 0x67, 0x16, 0x1a, 0xfe, 0xce, 0x02, 0x2a, 0x26, 0x23, 0x21, 0x38, 0x34, 0x2d, 0x00, 0x00, 0x02, 0x00, 0x49, 0xff, 0xf6, + 0x02, 0x48, 0x02, 0xf8, 0x00, 0x15, 0x00, 0x21, 0x00, 0x6b, 0xb5, 0x03, 0x01, 0x05, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x21, 0x07, 0x01, + 0x05, 0x05, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6c, 0x4d, 0x00, 0x06, 0x06, 0x01, 0x61, 0x03, 0x01, + 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1b, 0x40, 0x25, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, + 0x04, 0x6c, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x59, 0x40, 0x10, 0x17, 0x16, 0x1e, 0x1c, + 0x16, 0x21, 0x17, 0x21, 0x11, 0x11, 0x12, 0x24, 0x26, 0x08, 0x0d, 0x1b, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x23, 0x22, 0x26, 0x27, 0x23, 0x07, 0x23, 0x11, 0x33, 0x13, 0x22, 0x06, 0x15, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0xe0, 0x04, 0x02, 0x06, 0x16, + 0x4a, 0x3b, 0x5b, 0x72, 0x73, 0x5e, 0x3c, 0x45, 0x16, 0x0a, 0x19, 0x74, 0x97, 0x6a, 0x39, 0x31, 0x2f, 0x3d, 0x31, 0x32, 0x02, 0x47, 0x1f, 0x38, 0x15, 0x22, + 0x2f, 0x8f, 0x8b, 0x8c, 0x90, 0x2b, 0x1a, 0x3b, 0x02, 0xf8, 0xfe, 0xbc, 0x48, 0x4d, 0x12, 0x4e, 0x4f, 0x54, 0x50, 0xa0, 0x00, 0x01, 0x00, 0x2f, 0xff, 0xf6, + 0x01, 0xe8, 0x02, 0x2c, 0x00, 0x1b, 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, 0x02, 0x01, 0x18, 0x0c, 0x02, 0x03, 0x02, 0x19, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, + 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x16, 0x14, 0x10, + 0x0e, 0x09, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, + 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x01, 0x37, 0x4f, 0x77, 0x42, 0x48, 0x7c, 0x4f, 0x2f, 0x56, 0x21, 0x2d, 0x1e, + 0x3d, 0x1e, 0x3a, 0x3f, 0x3f, 0x38, 0x2a, 0x4e, 0x21, 0x20, 0x4d, 0x0a, 0x3b, 0x7c, 0x61, 0x64, 0x7f, 0x3b, 0x14, 0x11, 0x72, 0x0d, 0x11, 0x52, 0x52, 0x51, + 0x4e, 0x17, 0x13, 0x7b, 0x13, 0x16, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x2f, 0x02, 0xf8, 0x00, 0x15, 0x00, 0x22, 0x00, 0x82, 0x4b, 0xb0, 0x19, 0x50, + 0x58, 0x40, 0x0a, 0x09, 0x01, 0x05, 0x01, 0x12, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x09, 0x01, 0x05, 0x01, 0x12, 0x01, 0x03, 0x04, 0x02, 0x4c, + 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, + 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, + 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x22, 0x17, 0x22, 0x11, 0x10, 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, + 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x26, 0x26, 0x35, 0x35, 0x33, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x27, 0x32, 0x36, 0x37, 0x35, 0x34, 0x26, 0x23, + 0x22, 0x06, 0x15, 0x14, 0x16, 0xfc, 0x5b, 0x72, 0x74, 0x5e, 0x3a, 0x48, 0x17, 0x05, 0x03, 0x05, 0x98, 0x74, 0x1e, 0x06, 0x15, 0x4a, 0x07, 0x3d, 0x32, 0x01, + 0x30, 0x41, 0x31, 0x37, 0x37, 0x0a, 0x8f, 0x8b, 0x8d, 0x8f, 0x2e, 0x22, 0x12, 0x41, 0x1b, 0xae, 0xfd, 0x08, 0x47, 0x22, 0x2f, 0x79, 0x47, 0x49, 0x10, 0x4f, + 0x54, 0x54, 0x50, 0x50, 0x4f, 0x00, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x27, 0x02, 0x2c, 0x00, 0x15, 0x00, 0x1c, 0x00, 0x43, 0x40, 0x40, 0x0b, 0x01, + 0x02, 0x01, 0x0c, 0x01, 0x03, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x01, 0x02, 0x05, 0x01, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, + 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x17, 0x16, 0x01, 0x00, 0x1a, 0x19, 0x16, 0x1c, 0x17, 0x1c, 0x10, 0x0e, 0x09, + 0x07, 0x05, 0x04, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x15, 0x21, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, + 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x07, 0x33, 0x26, 0x26, 0x01, 0x32, 0x72, 0x83, 0xfe, 0xa1, 0x03, 0x47, 0x43, 0x33, 0x54, 0x2c, + 0x28, 0x5a, 0x41, 0x51, 0x7d, 0x48, 0x8f, 0x78, 0x2d, 0x39, 0x04, 0xce, 0x01, 0x31, 0x02, 0x2c, 0x80, 0x78, 0x49, 0x3e, 0x47, 0x14, 0x14, 0x71, 0x14, 0x13, + 0x3d, 0x7c, 0x5e, 0x8f, 0x90, 0x6b, 0x39, 0x38, 0x31, 0x40, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x01, 0xb0, 0x02, 0xfd, 0x00, 0x18, 0x00, 0x86, 0x40, 0x13, + 0x0f, 0x01, 0x04, 0x03, 0x10, 0x01, 0x05, 0x04, 0x06, 0x01, 0x00, 0x05, 0x03, 0x4c, 0x07, 0x01, 0x05, 0x01, 0x4b, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1b, + 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, + 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, + 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x02, 0x01, 0x00, + 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x59, 0x40, 0x09, 0x13, 0x25, 0x26, 0x11, 0x11, 0x10, 0x06, 0x0d, + 0x1c, 0x2b, 0x01, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x37, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x15, + 0x33, 0x01, 0x7c, 0x81, 0x95, 0x52, 0x52, 0x2f, 0x57, 0x3b, 0x2c, 0x47, 0x16, 0x26, 0x11, 0x28, 0x1a, 0x1f, 0x1d, 0x81, 0x01, 0xb2, 0xfe, 0x4e, 0x01, 0xb2, + 0x48, 0x28, 0x28, 0x46, 0x4d, 0x20, 0x0e, 0x09, 0x6d, 0x05, 0x09, 0x26, 0x1d, 0x22, 0x00, 0x02, 0x00, 0x2f, 0xff, 0x10, 0x02, 0x2f, 0x02, 0x2c, 0x00, 0x21, + 0x00, 0x2d, 0x00, 0x9e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x03, 0x01, 0x05, 0x00, 0x18, 0x01, 0x04, 0x06, 0x0e, 0x01, 0x03, 0x04, 0x0d, 0x01, 0x02, + 0x03, 0x04, 0x4c, 0x1b, 0x40, 0x12, 0x03, 0x01, 0x05, 0x01, 0x18, 0x01, 0x04, 0x06, 0x0e, 0x01, 0x03, 0x04, 0x0d, 0x01, 0x02, 0x03, 0x04, 0x4c, 0x59, 0x4b, + 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x08, 0x01, 0x05, 0x05, 0x00, 0x61, 0x01, 0x07, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, + 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x08, 0x01, 0x05, 0x05, + 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, + 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x23, 0x22, 0x01, 0x00, 0x28, 0x26, 0x22, 0x2d, 0x23, 0x2d, 0x1d, 0x1b, 0x12, 0x10, 0x0b, 0x09, 0x06, 0x05, 0x00, 0x21, + 0x01, 0x21, 0x09, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, + 0x35, 0x35, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x33, 0x32, 0x36, 0x35, 0x35, 0x34, 0x26, + 0xff, 0x38, 0x4d, 0x19, 0x05, 0x0d, 0x80, 0x86, 0x8c, 0x3f, 0x64, 0x2c, 0x2e, 0x5e, 0x3e, 0x3e, 0x42, 0x03, 0x02, 0x05, 0x17, 0x4b, 0x38, 0x5f, 0x70, 0x72, + 0x8f, 0x32, 0x35, 0x6a, 0x3c, 0x33, 0x33, 0x02, 0x2c, 0x2b, 0x24, 0x45, 0xfd, 0xda, 0x74, 0x78, 0x0f, 0x12, 0x80, 0x14, 0x16, 0x3a, 0x33, 0x0f, 0x0c, 0x28, + 0x0f, 0x24, 0x2c, 0x92, 0x88, 0x88, 0x94, 0x77, 0x56, 0x51, 0xa2, 0x46, 0x4a, 0x16, 0x52, 0x51, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x02, 0x43, 0x02, 0xf8, + 0x00, 0x16, 0x00, 0x27, 0x40, 0x24, 0x03, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x00, 0x04, 0x04, 0x6c, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, + 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x11, 0x13, 0x22, 0x13, 0x26, 0x05, 0x0d, 0x1b, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, + 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0xe0, 0x04, 0x03, 0x08, 0x1b, 0x51, 0x32, 0x58, 0x6c, 0x97, 0x57, 0x43, + 0x32, 0x97, 0x97, 0x02, 0x5f, 0x2d, 0x43, 0x13, 0x2a, 0x26, 0x5f, 0x69, 0xfe, 0x9c, 0x01, 0x3e, 0x76, 0x5d, 0x57, 0xff, 0x00, 0x02, 0xf8, 0x00, 0x00, 0x02, + 0x00, 0x44, 0x00, 0x00, 0x00, 0xe8, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x72, + 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0c, 0x0c, 0x01, 0x00, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, + 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x11, 0x23, 0x11, 0x96, 0x21, 0x31, + 0x31, 0x21, 0x22, 0x30, 0x30, 0x6d, 0x97, 0x02, 0xf9, 0x1f, 0x2b, 0x29, 0x20, 0x20, 0x29, 0x2b, 0x1f, 0xd7, 0xfd, 0xde, 0x02, 0x22, 0x00, 0x02, 0xff, 0xcb, + 0xff, 0x10, 0x00, 0xe8, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x1c, 0x00, 0x37, 0x40, 0x34, 0x10, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x72, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x62, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x0d, + 0x0c, 0x18, 0x17, 0x14, 0x12, 0x0c, 0x1c, 0x0d, 0x1c, 0x24, 0x22, 0x06, 0x0d, 0x18, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, + 0x26, 0x03, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x06, 0x44, 0x2f, 0x23, 0x21, 0x31, 0x31, 0x21, 0x23, + 0x2f, 0x1c, 0x18, 0x33, 0x12, 0x10, 0x1c, 0x12, 0x1b, 0x25, 0x97, 0x24, 0x51, 0x02, 0xaf, 0x2b, 0x1f, 0x1f, 0x2b, 0x29, 0x20, 0x20, 0xfc, 0x8a, 0x07, 0x05, + 0x77, 0x05, 0x05, 0x22, 0x32, 0x02, 0x45, 0xfd, 0xa3, 0x32, 0x52, 0x31, 0x00, 0x01, 0x00, 0x4e, 0x00, 0x00, 0x02, 0x6c, 0x02, 0xf8, 0x00, 0x12, 0x00, 0x24, + 0x40, 0x21, 0x0e, 0x0d, 0x0a, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, + 0x01, 0x4e, 0x11, 0x13, 0x12, 0x18, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x37, 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x15, + 0x23, 0x11, 0x33, 0xe3, 0x05, 0x03, 0x02, 0x0f, 0x20, 0x12, 0x99, 0xa8, 0xd9, 0xe6, 0xac, 0x9d, 0x40, 0x95, 0x95, 0x01, 0xa4, 0x1f, 0x3d, 0x1f, 0x15, 0x2b, + 0x13, 0xa6, 0xed, 0xfe, 0xcb, 0xdd, 0x33, 0xaa, 0x02, 0xf8, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x00, 0xe0, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x13, 0x40, 0x10, + 0x00, 0x01, 0x01, 0x6c, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x33, 0x23, 0x11, 0x33, 0xe0, 0x97, 0x97, 0x02, 0xf8, + 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x03, 0x88, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x6c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0xb6, 0x21, 0x1a, 0x02, 0x02, 0x00, 0x01, + 0x4c, 0x1b, 0xb6, 0x21, 0x1a, 0x02, 0x02, 0x06, 0x01, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x04, 0x01, 0x02, 0x02, 0x00, 0x61, 0x07, 0x06, + 0x08, 0x03, 0x00, 0x00, 0x73, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x1a, 0x00, 0x06, 0x06, 0x6d, 0x4d, 0x04, 0x01, 0x02, 0x02, + 0x00, 0x61, 0x07, 0x08, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x17, 0x01, 0x00, 0x1f, 0x1d, 0x19, 0x18, + 0x17, 0x16, 0x13, 0x11, 0x0e, 0x0d, 0x0a, 0x08, 0x05, 0x04, 0x00, 0x24, 0x01, 0x24, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, + 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, + 0x33, 0x36, 0x36, 0x02, 0xca, 0x5e, 0x60, 0x96, 0x2a, 0x2a, 0x3b, 0x2f, 0x97, 0x28, 0x2a, 0x3e, 0x2d, 0x97, 0x74, 0x16, 0x05, 0x17, 0x54, 0x38, 0x3d, 0x51, + 0x17, 0x05, 0x1b, 0x56, 0x02, 0x2c, 0x5f, 0x69, 0xfe, 0x9c, 0x01, 0x3e, 0x3f, 0x37, 0x55, 0x4e, 0xfe, 0xef, 0x01, 0x3e, 0x3d, 0x39, 0x5d, 0x57, 0xff, 0x00, + 0x02, 0x22, 0x46, 0x25, 0x2b, 0x2a, 0x28, 0x29, 0x29, 0x00, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x02, 0x43, 0x02, 0x2c, 0x00, 0x12, 0x00, 0x5e, 0x4b, 0xb0, + 0x19, 0x50, 0x58, 0xb5, 0x10, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x1b, 0xb5, 0x10, 0x01, 0x02, 0x04, 0x01, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, + 0x00, 0x02, 0x02, 0x00, 0x61, 0x04, 0x05, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x04, 0x04, 0x6d, + 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x05, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, 0x0f, 0x0e, + 0x0d, 0x0c, 0x09, 0x07, 0x05, 0x04, 0x00, 0x12, 0x01, 0x12, 0x06, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, + 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x01, 0x81, 0x5a, 0x68, 0x96, 0x58, 0x44, 0x31, 0x97, 0x74, 0x15, 0x06, 0x36, 0x02, 0x2c, 0x5f, 0x69, 0xfe, 0x9c, + 0x01, 0x3e, 0x76, 0x5d, 0x57, 0xff, 0x00, 0x02, 0x22, 0x49, 0x53, 0x00, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x41, 0x02, 0x2c, 0x00, 0x0d, 0x00, 0x19, + 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, + 0x25, 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, + 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x41, 0x8f, 0x7b, 0x4d, 0x77, 0x44, 0x8f, 0x7c, 0x4d, 0x76, 0x44, 0xfe, 0x88, 0x34, 0x3c, 0x3a, 0x34, 0x34, + 0x3b, 0x3b, 0x34, 0x01, 0x12, 0x88, 0x94, 0x42, 0x7f, 0x5b, 0x88, 0x92, 0x41, 0x7e, 0x5b, 0x50, 0x59, 0x59, 0x50, 0x51, 0x56, 0x56, 0x00, 0x02, 0x00, 0x49, + 0xff, 0x10, 0x02, 0x48, 0x02, 0x2c, 0x00, 0x15, 0x00, 0x21, 0x00, 0x82, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x12, 0x01, 0x04, 0x00, 0x09, 0x01, 0x01, + 0x05, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x12, 0x01, 0x04, 0x03, 0x09, 0x01, 0x01, 0x05, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x07, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, + 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x21, 0x17, 0x21, 0x11, 0x10, + 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x16, 0x16, 0x15, + 0x15, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x17, 0x22, 0x06, 0x07, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x01, 0x7b, 0x5e, 0x6f, 0x75, 0x5c, + 0x3c, 0x47, 0x14, 0x06, 0x02, 0x04, 0x97, 0x7b, 0x15, 0x07, 0x16, 0x48, 0x0b, 0x3a, 0x2d, 0x02, 0x2d, 0x3d, 0x33, 0x32, 0x02, 0x2c, 0x8f, 0x8b, 0x8c, 0x90, + 0x2b, 0x1a, 0x12, 0x2f, 0x19, 0xd1, 0x03, 0x12, 0x47, 0x21, 0x30, 0x78, 0x48, 0x49, 0x10, 0x4f, 0x54, 0x54, 0x50, 0xa0, 0x00, 0x02, 0x00, 0x2f, 0xff, 0x10, + 0x02, 0x2f, 0x02, 0x2c, 0x00, 0x15, 0x00, 0x21, 0x00, 0x78, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x10, 0x01, 0x05, 0x01, 0x03, 0x01, 0x00, 0x04, 0x02, + 0x4c, 0x1b, 0x40, 0x0a, 0x10, 0x01, 0x05, 0x02, 0x03, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, + 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, + 0x20, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, + 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x17, 0x16, 0x1e, 0x1c, 0x16, 0x21, 0x17, 0x21, 0x11, 0x14, 0x24, 0x26, 0x07, 0x0d, 0x1a, 0x2b, + 0x05, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x23, 0x03, 0x32, 0x36, 0x35, + 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x01, 0x98, 0x02, 0x03, 0x06, 0x15, 0x49, 0x3c, 0x5c, 0x72, 0x74, 0x5d, 0x3c, 0x4a, 0x17, 0x04, 0x0e, 0x80, + 0x97, 0x65, 0x3d, 0x31, 0x2f, 0x42, 0x34, 0x33, 0x0b, 0x13, 0x2c, 0x13, 0x22, 0x2f, 0x8f, 0x8b, 0x8c, 0x90, 0x2e, 0x22, 0x46, 0xfc, 0xee, 0x01, 0x5d, 0x47, + 0x49, 0x15, 0x4f, 0x55, 0x58, 0x50, 0xa1, 0x00, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x01, 0xb3, 0x02, 0x2c, 0x00, 0x13, 0x00, 0x69, 0x4b, 0xb0, 0x19, 0x50, + 0x58, 0x40, 0x0b, 0x10, 0x03, 0x02, 0x01, 0x00, 0x04, 0x01, 0x02, 0x01, 0x02, 0x4c, 0x1b, 0x40, 0x0e, 0x03, 0x01, 0x03, 0x00, 0x10, 0x01, 0x01, 0x03, 0x04, + 0x01, 0x02, 0x01, 0x03, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x01, 0x01, 0x00, 0x61, 0x03, 0x04, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, + 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, + 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0f, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x13, 0x01, 0x13, 0x05, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, + 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x01, 0x77, 0x0f, 0x22, 0x0b, 0x0f, 0x0b, 0x1e, 0x15, + 0x1f, 0x3e, 0x29, 0x97, 0x73, 0x16, 0x07, 0x18, 0x53, 0x02, 0x2c, 0x04, 0x02, 0x8d, 0x03, 0x03, 0x1a, 0x3c, 0x34, 0xfe, 0xeb, 0x02, 0x22, 0x5c, 0x2a, 0x3c, + 0x00, 0x01, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xcc, 0x02, 0x2c, 0x00, 0x27, 0x00, 0x2e, 0x40, 0x2b, 0x1a, 0x01, 0x03, 0x02, 0x1b, 0x07, 0x02, 0x01, 0x03, 0x06, + 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x25, 0x2b, 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, + 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xcc, 0x6f, 0x73, 0x3a, + 0x58, 0x29, 0x2c, 0x65, 0x26, 0x2e, 0x29, 0x15, 0x35, 0x31, 0x49, 0x4b, 0x77, 0x62, 0x34, 0x5c, 0x2f, 0x2c, 0x26, 0x50, 0x1f, 0x48, 0x15, 0x35, 0x30, 0x31, + 0x43, 0x21, 0xa1, 0x4e, 0x5d, 0x0f, 0x11, 0x7d, 0x15, 0x18, 0x1a, 0x16, 0x0f, 0x18, 0x1a, 0x13, 0x1d, 0x47, 0x44, 0x4c, 0x4e, 0x16, 0x14, 0x67, 0x11, 0x16, + 0x28, 0x0f, 0x15, 0x18, 0x13, 0x14, 0x2a, 0x3d, 0x00, 0x01, 0x00, 0x17, 0xff, 0xf6, 0x01, 0x92, 0x02, 0x96, 0x00, 0x18, 0x00, 0x40, 0x40, 0x3d, 0x0e, 0x01, + 0x02, 0x04, 0x03, 0x01, 0x00, 0x02, 0x04, 0x01, 0x01, 0x00, 0x03, 0x4c, 0x00, 0x03, 0x04, 0x03, 0x85, 0x05, 0x01, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, 0x04, + 0x6d, 0x4d, 0x06, 0x01, 0x00, 0x00, 0x01, 0x62, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x01, 0x00, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0d, 0x0c, 0x08, 0x06, + 0x00, 0x18, 0x01, 0x18, 0x07, 0x0d, 0x16, 0x2b, 0x25, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x11, 0x23, 0x35, 0x37, 0x37, 0x33, + 0x15, 0x33, 0x15, 0x23, 0x11, 0x14, 0x16, 0x01, 0x34, 0x19, 0x2e, 0x17, 0x18, 0x47, 0x2a, 0x31, 0x4d, 0x2d, 0x47, 0x52, 0x2b, 0x5f, 0x99, 0x99, 0x24, 0x6d, + 0x0a, 0x07, 0x6f, 0x0a, 0x0f, 0x20, 0x4f, 0x46, 0x01, 0x07, 0x3f, 0x32, 0x73, 0x74, 0x70, 0xfe, 0xf9, 0x1f, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x46, 0xff, 0xf6, + 0x02, 0x40, 0x02, 0x22, 0x00, 0x14, 0x00, 0x50, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x18, 0x00, 0x01, 0x01, 0x03, 0x5f, 0x06, 0x05, 0x02, 0x03, 0x03, 0x6d, + 0x4d, 0x00, 0x04, 0x04, 0x00, 0x62, 0x02, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1b, 0x40, 0x1c, 0x00, 0x01, 0x01, 0x03, 0x5f, 0x06, 0x05, 0x02, 0x03, 0x03, + 0x6d, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0x00, 0x04, 0x04, 0x02, 0x62, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x59, 0x40, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x14, 0x23, 0x13, 0x22, 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x01, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, + 0x33, 0x32, 0x36, 0x35, 0x11, 0x02, 0x40, 0x74, 0x13, 0x09, 0x1a, 0x5a, 0x34, 0x57, 0x6b, 0x98, 0x29, 0x2d, 0x44, 0x31, 0x02, 0x22, 0xfd, 0xde, 0x46, 0x2a, + 0x26, 0x5f, 0x69, 0x01, 0x64, 0xfe, 0xc2, 0x3a, 0x3b, 0x5c, 0x57, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3b, 0x02, 0x22, 0x00, 0x0d, + 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0xd0, 0xd0, 0x9e, + 0x66, 0x05, 0x0f, 0x02, 0x04, 0x02, 0x0f, 0x06, 0x68, 0x9e, 0xd0, 0x02, 0x22, 0xfe, 0xbe, 0x10, 0x37, 0x13, 0x14, 0x33, 0x12, 0x01, 0x43, 0xfd, 0xde, 0x00, + 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x03, 0x4e, 0x02, 0x22, 0x00, 0x2a, 0x00, 0x21, 0x40, 0x1e, 0x21, 0x14, 0x05, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x02, + 0x02, 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x1b, 0x1c, 0x11, 0x1c, 0x05, 0x0d, 0x1b, 0x2b, 0x25, 0x2e, 0x03, 0x27, 0x23, + 0x0e, 0x03, 0x07, 0x07, 0x23, 0x03, 0x33, 0x17, 0x1e, 0x02, 0x17, 0x33, 0x3e, 0x03, 0x37, 0x13, 0x33, 0x13, 0x1e, 0x02, 0x15, 0x33, 0x3e, 0x02, 0x37, 0x37, + 0x33, 0x03, 0x23, 0x01, 0xe5, 0x04, 0x0f, 0x12, 0x10, 0x03, 0x04, 0x03, 0x0f, 0x12, 0x10, 0x04, 0x2c, 0xa0, 0x9b, 0x94, 0x3f, 0x07, 0x0b, 0x0a, 0x02, 0x04, + 0x01, 0x06, 0x09, 0x07, 0x02, 0x43, 0xa4, 0x40, 0x04, 0x0b, 0x09, 0x04, 0x02, 0x0a, 0x0d, 0x07, 0x41, 0x92, 0x9d, 0xa2, 0xbf, 0x11, 0x43, 0x4d, 0x41, 0x0f, + 0x0f, 0x41, 0x4d, 0x44, 0x12, 0xbd, 0x02, 0x22, 0xf2, 0x19, 0x46, 0x41, 0x13, 0x0e, 0x2f, 0x32, 0x29, 0x07, 0x01, 0x06, 0xfe, 0xfa, 0x0e, 0x3e, 0x40, 0x13, + 0x11, 0x41, 0x48, 0x19, 0xf2, 0xfd, 0xde, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x02, 0x3d, 0x02, 0x22, 0x00, 0x0b, 0x00, 0x1f, 0x40, 0x1c, 0x09, 0x06, + 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x12, 0x12, 0x12, 0x11, 0x04, 0x0d, 0x1a, + 0x2b, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x23, 0xbe, 0xb0, 0xa9, 0x6a, 0x6b, 0xa9, 0xb2, 0xba, 0xa9, 0x73, 0x73, 0xa9, 0x01, + 0x17, 0x01, 0x0b, 0xae, 0xae, 0xfe, 0xf5, 0xfe, 0xe9, 0xbb, 0xbb, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0x10, 0x02, 0x3b, 0x02, 0x22, 0x00, 0x1a, 0x00, 0x27, + 0x40, 0x24, 0x1a, 0x13, 0x05, 0x03, 0x03, 0x00, 0x12, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x62, 0x00, + 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x25, 0x23, 0x19, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x11, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, + 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x9f, 0x67, 0x07, 0x0d, 0x03, 0x04, 0x03, 0x0f, 0x07, 0x65, 0x9c, 0xe0, + 0x22, 0x69, 0x61, 0x1a, 0x25, 0x0d, 0x0a, 0x20, 0x11, 0x2e, 0x32, 0x0f, 0x0c, 0x02, 0x22, 0xfe, 0xc8, 0x16, 0x31, 0x16, 0x15, 0x32, 0x16, 0x01, 0x38, 0xfd, + 0xac, 0x5c, 0x62, 0x05, 0x03, 0x77, 0x02, 0x04, 0x35, 0x27, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xce, 0x02, 0x22, 0x00, 0x09, 0x00, 0x29, + 0x40, 0x26, 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x00, + 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x13, 0x23, 0x35, 0x21, 0x15, 0x03, 0x33, 0x01, + 0xce, 0xfe, 0x50, 0xfc, 0xee, 0x01, 0x99, 0xf5, 0xfe, 0x59, 0x01, 0x56, 0x73, 0x61, 0xfe, 0xb3, 0x00, 0x01, 0x00, 0x0f, 0xff, 0x62, 0x01, 0x62, 0x02, 0xca, + 0x00, 0x1f, 0x00, 0x2c, 0x40, 0x29, 0x18, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, + 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, 0x4e, 0x1b, 0x11, 0x16, 0x11, 0x16, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x05, 0x22, 0x26, 0x26, + 0x35, 0x35, 0x34, 0x26, 0x23, 0x35, 0x32, 0x36, 0x35, 0x35, 0x34, 0x36, 0x36, 0x33, 0x15, 0x06, 0x06, 0x15, 0x15, 0x14, 0x07, 0x15, 0x16, 0x15, 0x15, 0x14, + 0x16, 0x17, 0x01, 0x62, 0x55, 0x5d, 0x24, 0x40, 0x3d, 0x3d, 0x40, 0x24, 0x5d, 0x55, 0x27, 0x2e, 0x72, 0x72, 0x2e, 0x27, 0x9e, 0x1c, 0x3c, 0x30, 0x9a, 0x2f, + 0x28, 0x75, 0x28, 0x2f, 0x9b, 0x30, 0x3c, 0x1c, 0x6e, 0x01, 0x1a, 0x2a, 0x92, 0x5b, 0x11, 0x06, 0x11, 0x5b, 0x92, 0x2a, 0x1a, 0x01, 0x00, 0x01, 0x00, 0xde, + 0xff, 0x1d, 0x01, 0x49, 0x02, 0xf5, 0x00, 0x03, 0x00, 0x28, 0x4b, 0xb0, 0x27, 0x50, 0x58, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x01, 0x01, 0x6f, + 0x01, 0x4e, 0x1b, 0x40, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x4e, 0x59, 0xb4, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x13, 0x33, + 0x11, 0x23, 0xde, 0x6b, 0x6b, 0x02, 0xf5, 0xfc, 0x28, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, 0x62, 0x01, 0x7b, 0x02, 0xca, 0x00, 0x1f, 0x00, 0x2c, 0x40, 0x29, + 0x06, 0x01, 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, 0x00, 0x01, 0x01, 0x02, 0x61, + 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x16, 0x11, 0x16, 0x11, 0x1b, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x17, 0x36, 0x36, 0x35, 0x35, 0x34, 0x37, 0x35, 0x26, 0x35, + 0x35, 0x34, 0x26, 0x27, 0x35, 0x32, 0x16, 0x16, 0x15, 0x15, 0x14, 0x16, 0x33, 0x15, 0x22, 0x06, 0x15, 0x15, 0x14, 0x06, 0x06, 0x23, 0x28, 0x27, 0x2e, 0x72, + 0x72, 0x2e, 0x27, 0x56, 0x5c, 0x24, 0x40, 0x3d, 0x3d, 0x40, 0x24, 0x5c, 0x56, 0x30, 0x01, 0x1a, 0x2a, 0x92, 0x5b, 0x11, 0x06, 0x11, 0x5b, 0x92, 0x2a, 0x1a, + 0x01, 0x6e, 0x1c, 0x3c, 0x30, 0x9b, 0x2f, 0x28, 0x75, 0x28, 0x2f, 0x9a, 0x30, 0x3c, 0x1c, 0x00, 0x00, 0x01, 0x00, 0x2b, 0x01, 0x0d, 0x02, 0x10, 0x01, 0xb4, + 0x00, 0x17, 0x00, 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, 0x02, 0x01, 0x13, 0x01, 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, + 0x03, 0x49, 0x00, 0x02, 0x00, 0x03, 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, 0x03, 0x51, + 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, + 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x01, 0x0c, 0x25, 0x33, 0x17, 0x1c, 0x3d, 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x2f, 0x25, 0x34, 0x16, + 0x1d, 0x3c, 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x01, 0x2d, 0x10, 0x0b, 0x22, 0x19, 0x71, 0x35, 0x0b, 0x14, 0x10, 0x0b, 0x22, 0x19, 0x71, 0x35, 0x0c, 0x00, 0x01, + 0x00, 0x17, 0x01, 0xa0, 0x01, 0x57, 0x03, 0x56, 0x00, 0x17, 0x00, 0x30, 0x40, 0x2d, 0x0c, 0x01, 0x01, 0x02, 0x0b, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, + 0x03, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x03, 0x02, 0x01, 0x69, 0x00, 0x03, 0x00, 0x00, 0x03, 0x57, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x00, 0x4f, + 0x16, 0x24, 0x27, 0x10, 0x04, 0x0c, 0x1a, 0x2b, 0x01, 0x21, 0x35, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x15, 0x14, 0x06, 0x07, 0x07, 0x33, 0x01, 0x57, 0xfe, 0xc4, 0x6d, 0x2d, 0x21, 0x17, 0x14, 0x27, 0x31, 0x3c, 0x20, 0x4f, 0x35, 0x41, 0x4f, 0x32, 0x3b, 0x33, + 0xac, 0x01, 0xa0, 0x52, 0x6b, 0x2c, 0x2f, 0x1a, 0x12, 0x14, 0x2b, 0x4a, 0x1c, 0x23, 0x3f, 0x3b, 0x2d, 0x4a, 0x35, 0x2e, 0x00, 0x01, 0x00, 0x1a, 0x01, 0x98, + 0x01, 0x5e, 0x03, 0x55, 0x00, 0x26, 0x00, 0x4d, 0x40, 0x4a, 0x24, 0x01, 0x05, 0x00, 0x23, 0x01, 0x04, 0x05, 0x05, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, + 0x0e, 0x01, 0x01, 0x02, 0x05, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x69, 0x00, 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, + 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x01, 0x00, 0x21, 0x1f, 0x1b, 0x19, 0x18, 0x16, 0x13, 0x11, 0x0c, 0x0a, 0x00, + 0x26, 0x01, 0x26, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x07, 0x15, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, + 0x32, 0x35, 0x34, 0x26, 0x23, 0x23, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0xb9, 0x49, 0x4e, 0x4d, 0x5b, 0x5d, + 0x56, 0x29, 0x49, 0x1e, 0x21, 0x48, 0x23, 0x4a, 0x24, 0x2f, 0x35, 0x2e, 0x2c, 0x23, 0x1c, 0x1b, 0x1a, 0x30, 0x1a, 0x31, 0x1f, 0x4e, 0x03, 0x55, 0x3b, 0x30, + 0x4e, 0x1b, 0x04, 0x15, 0x51, 0x3b, 0x44, 0x0f, 0x11, 0x5e, 0x14, 0x12, 0x32, 0x16, 0x1a, 0x50, 0x1c, 0x16, 0x14, 0x18, 0x12, 0x13, 0x45, 0x17, 0x1e, 0x00, + 0x00, 0x01, 0x00, 0x20, 0x01, 0xa0, 0x01, 0x15, 0x03, 0x4c, 0x00, 0x0d, 0x00, 0x27, 0x40, 0x24, 0x0c, 0x0b, 0x07, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, + 0x01, 0x00, 0x00, 0x01, 0x57, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0d, 0x11, 0x03, 0x0c, 0x17, + 0x2b, 0x01, 0x11, 0x23, 0x35, 0x34, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x01, 0x15, 0x70, 0x02, 0x02, 0x01, 0x07, 0x14, 0x0a, 0x2d, 0x38, + 0x97, 0x03, 0x4c, 0xfe, 0x54, 0xd6, 0x0d, 0x27, 0x25, 0x0a, 0x09, 0x14, 0x07, 0x24, 0x45, 0x76, 0x00, 0x01, 0xff, 0x40, 0x00, 0x00, 0x01, 0x41, 0x02, 0xca, + 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, + 0x0d, 0x17, 0x2b, 0x01, 0x01, 0x23, 0x01, 0x01, 0x41, 0xfe, 0x74, 0x75, 0x01, 0x8c, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0x00, 0x02, 0x00, 0x0c, 0x01, 0xa0, + 0x01, 0x73, 0x03, 0x4f, 0x00, 0x0a, 0x00, 0x12, 0x00, 0x5e, 0x40, 0x0a, 0x0d, 0x01, 0x04, 0x03, 0x06, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x4b, 0xb0, 0x10, 0x50, + 0x58, 0x40, 0x1e, 0x00, 0x03, 0x04, 0x03, 0x85, 0x00, 0x01, 0x00, 0x00, 0x01, 0x71, 0x05, 0x01, 0x04, 0x00, 0x00, 0x04, 0x57, 0x05, 0x01, 0x04, 0x04, 0x00, + 0x60, 0x02, 0x01, 0x00, 0x04, 0x00, 0x50, 0x1b, 0x40, 0x1d, 0x00, 0x03, 0x04, 0x03, 0x85, 0x00, 0x01, 0x00, 0x01, 0x86, 0x05, 0x01, 0x04, 0x00, 0x00, 0x04, + 0x57, 0x05, 0x01, 0x04, 0x04, 0x00, 0x60, 0x02, 0x01, 0x00, 0x04, 0x00, 0x50, 0x59, 0x40, 0x09, 0x17, 0x11, 0x12, 0x11, 0x11, 0x10, 0x06, 0x0c, 0x1c, 0x2b, + 0x01, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x13, 0x33, 0x11, 0x33, 0x27, 0x34, 0x37, 0x06, 0x06, 0x07, 0x07, 0x33, 0x01, 0x73, 0x3d, 0x6f, 0xbb, 0xb6, 0x74, + 0x3d, 0xac, 0x03, 0x05, 0x17, 0x09, 0x3e, 0x60, 0x01, 0xef, 0x4f, 0x4f, 0x4c, 0x01, 0x14, 0xfe, 0xf3, 0x56, 0x26, 0x29, 0x0d, 0x2a, 0x0e, 0x60, 0x00, 0x01, + 0x00, 0x28, 0x01, 0x98, 0x01, 0x5d, 0x03, 0x4e, 0x00, 0x1d, 0x00, 0x42, 0x40, 0x3f, 0x1c, 0x03, 0x02, 0x04, 0x01, 0x1b, 0x10, 0x02, 0x03, 0x04, 0x0f, 0x01, + 0x02, 0x03, 0x03, 0x4c, 0x06, 0x01, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x67, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x69, 0x00, 0x03, 0x02, 0x02, 0x03, + 0x59, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x03, 0x02, 0x51, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x1d, 0x23, 0x25, 0x24, 0x23, 0x11, 0x07, 0x0c, 0x1b, 0x2b, + 0x01, 0x15, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, 0x22, + 0x06, 0x07, 0x27, 0x37, 0x01, 0x40, 0xae, 0x07, 0x0a, 0x1c, 0x11, 0x41, 0x5a, 0x5e, 0x58, 0x23, 0x44, 0x18, 0x19, 0x42, 0x1a, 0x26, 0x2d, 0x51, 0x0c, 0x22, + 0x0b, 0x36, 0x12, 0x03, 0x4e, 0x55, 0x48, 0x01, 0x04, 0x46, 0x42, 0x47, 0x4f, 0x0c, 0x0d, 0x5f, 0x10, 0x14, 0x1d, 0x23, 0x3e, 0x05, 0x04, 0x14, 0xd9, 0x00, + 0x00, 0x01, 0x00, 0x1d, 0x01, 0xa0, 0x01, 0x64, 0x03, 0x4c, 0x00, 0x06, 0x00, 0x2a, 0x40, 0x27, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x00, + 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, + 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, 0x23, 0x35, 0x21, 0x15, 0x03, 0x4b, 0xa9, 0xd7, 0x01, 0x47, 0x9d, 0x01, 0xa0, 0x01, 0x55, 0x57, 0x4a, 0xfe, 0x9e, 0x00, + 0x00, 0x03, 0x00, 0x16, 0x01, 0x96, 0x01, 0x66, 0x03, 0x56, 0x00, 0x17, 0x00, 0x22, 0x00, 0x2d, 0x00, 0x39, 0x40, 0x36, 0x23, 0x1d, 0x12, 0x06, 0x04, 0x03, + 0x02, 0x01, 0x4c, 0x04, 0x01, 0x00, 0x05, 0x01, 0x02, 0x03, 0x00, 0x02, 0x69, 0x00, 0x03, 0x01, 0x01, 0x03, 0x59, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, + 0x03, 0x01, 0x51, 0x19, 0x18, 0x01, 0x00, 0x29, 0x27, 0x18, 0x22, 0x19, 0x22, 0x0d, 0x0b, 0x00, 0x17, 0x01, 0x17, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, + 0x15, 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x15, 0x14, 0x16, + 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x35, 0x34, 0x26, 0x27, 0xbf, 0x3f, 0x58, 0x29, 0x1d, 0x25, 0x31, 0x58, 0x4f, + 0x58, 0x51, 0x2e, 0x1f, 0x1d, 0x21, 0x5a, 0x3f, 0x33, 0x1c, 0x18, 0x16, 0x1b, 0x17, 0x24, 0x37, 0x1f, 0x20, 0x40, 0x20, 0x1f, 0x03, 0x56, 0x37, 0x37, 0x25, + 0x2f, 0x11, 0x0f, 0x33, 0x2b, 0x36, 0x4a, 0x49, 0x36, 0x2e, 0x2c, 0x10, 0x13, 0x32, 0x24, 0x36, 0x38, 0x4f, 0x27, 0x13, 0x1a, 0x0b, 0x0a, 0x19, 0x15, 0x0f, + 0x18, 0xb2, 0x17, 0x26, 0x18, 0x1b, 0x30, 0x16, 0x1c, 0x0a, 0x00, 0x02, 0x00, 0x14, 0x01, 0x96, 0x01, 0x67, 0x03, 0x56, 0x00, 0x0b, 0x00, 0x13, 0x00, 0x31, + 0x40, 0x2e, 0x00, 0x01, 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, + 0x02, 0x00, 0x51, 0x0d, 0x0c, 0x01, 0x00, 0x11, 0x0f, 0x0c, 0x13, 0x0d, 0x13, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, + 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x27, 0x32, 0x35, 0x34, 0x23, 0x22, 0x15, 0x14, 0xbc, 0x52, 0x56, 0x50, 0x58, 0x54, 0x57, 0x52, 0x58, + 0x2f, 0x2f, 0x2e, 0x01, 0x96, 0x77, 0x6a, 0x6a, 0x75, 0x75, 0x6a, 0x6a, 0x77, 0x65, 0x7b, 0x7a, 0x7a, 0x7b, 0x00, 0x02, 0x00, 0x16, 0x01, 0x96, 0x01, 0x66, + 0x03, 0x55, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x4a, 0x40, 0x47, 0x03, 0x01, 0x01, 0x00, 0x04, 0x01, 0x02, 0x01, 0x0a, 0x01, 0x04, 0x02, 0x03, 0x4c, 0x06, 0x01, + 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 0x69, 0x00, 0x02, 0x07, 0x01, 0x04, 0x05, 0x02, 0x04, 0x69, 0x00, 0x05, 0x03, 0x03, 0x05, 0x59, 0x00, 0x05, 0x05, 0x03, + 0x61, 0x00, 0x03, 0x05, 0x03, 0x51, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, 0x26, 0x1d, 0x26, 0x15, 0x13, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x1b, 0x01, 0x1b, + 0x08, 0x0c, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x17, 0x15, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, + 0x26, 0x35, 0x34, 0x3e, 0x02, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x35, 0x34, 0x26, 0x01, 0x03, 0x0e, 0x27, 0x0d, 0x0c, 0x1f, 0x14, 0x46, 0x39, + 0x03, 0x05, 0x0e, 0x2f, 0x26, 0x38, 0x42, 0x56, 0x4b, 0x4c, 0x63, 0x13, 0x33, 0x5d, 0x08, 0x1f, 0x21, 0x1d, 0x1f, 0x3b, 0x1d, 0x03, 0x55, 0x03, 0x03, 0x57, + 0x02, 0x04, 0x42, 0x35, 0x14, 0x19, 0x44, 0x41, 0x47, 0x52, 0x60, 0x60, 0x2f, 0x5b, 0x49, 0x2c, 0xea, 0x22, 0x14, 0x1a, 0x30, 0x43, 0x1d, 0x20, 0x00, 0x02, + 0x00, 0x15, 0x01, 0x96, 0x01, 0x64, 0x03, 0x56, 0x00, 0x19, 0x00, 0x24, 0x00, 0x4a, 0x40, 0x47, 0x10, 0x01, 0x03, 0x05, 0x0b, 0x01, 0x02, 0x03, 0x0a, 0x01, + 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x07, 0x01, 0x04, 0x05, 0x00, 0x04, 0x69, 0x00, 0x05, 0x00, 0x03, 0x02, 0x05, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, + 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1b, 0x1a, 0x01, 0x00, 0x20, 0x1e, 0x1a, 0x24, 0x1b, 0x24, 0x15, 0x13, 0x0e, 0x0c, + 0x08, 0x06, 0x00, 0x19, 0x01, 0x19, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xb8, 0x4a, 0x62, 0x28, 0x62, + 0x58, 0x16, 0x2a, 0x0c, 0x19, 0x30, 0x3f, 0x35, 0x03, 0x05, 0x0e, 0x2d, 0x25, 0x3a, 0x42, 0x57, 0x51, 0x3a, 0x1b, 0x1b, 0x1f, 0x22, 0x1e, 0x03, 0x56, 0x5f, + 0x60, 0x46, 0x75, 0x46, 0x04, 0x04, 0x58, 0x08, 0x43, 0x34, 0x14, 0x19, 0x45, 0x41, 0x46, 0x52, 0x54, 0x43, 0x1d, 0x21, 0x22, 0x14, 0x1d, 0x2e, 0xff, 0xff, + 0x00, 0x14, 0x00, 0x00, 0x03, 0x32, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x47, 0x01, 0x82, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, + 0x00, 0x00, 0x02, 0x6a, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, 0x82, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0x00, 0x00, + 0x02, 0x63, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x83, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0x00, 0x00, 0x03, 0xec, + 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x82, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x03, 0x04, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x14, 0x00, 0x00, 0x03, 0xe6, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x83, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, + 0x03, 0x06, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0xff, 0xf6, 0x01, 0x67, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x68, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, + 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x20, 0x00, 0x00, 0x01, 0x15, 0x01, 0xac, 0x03, 0x07, 0x00, 0x62, 0x00, 0x00, 0xfe, 0x60, + 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0x00, 0x01, 0x57, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x60, + 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1a, 0xff, 0xf8, 0x01, 0x5e, 0x01, 0xb5, + 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x00, + 0x01, 0x73, 0x01, 0xaf, 0x03, 0x07, 0x00, 0x64, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x28, 0xff, 0xf8, 0x01, 0x5d, 0x01, 0xae, 0x03, 0x07, 0x00, 0x65, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0xff, 0xf6, 0x01, 0x66, 0x01, 0xb5, 0x03, 0x07, 0x00, 0x69, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, + 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x64, 0x01, 0xac, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, + 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0xff, 0xf6, 0x01, 0x66, 0x01, 0xb6, 0x03, 0x07, 0x00, 0x67, 0x00, 0x00, + 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x15, 0xff, 0xf6, 0x01, 0x64, 0x01, 0xb6, 0x03, 0x07, + 0x00, 0x6a, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x14, 0x01, 0x14, 0x01, 0x67, + 0x02, 0xd4, 0x01, 0x07, 0x00, 0x68, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x20, + 0x01, 0x1e, 0x01, 0x15, 0x02, 0xca, 0x03, 0x07, 0x00, 0x62, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0x00, 0x17, 0x01, 0x1e, 0x01, 0x57, 0x02, 0xd4, 0x01, 0x07, 0x00, 0x60, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1a, 0x01, 0x16, 0x01, 0x5e, 0x02, 0xd3, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, + 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x01, 0x1e, 0x01, 0x73, 0x02, 0xcd, 0x03, 0x07, 0x00, 0x64, 0x00, 0x00, 0xff, 0x7e, + 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x28, 0x01, 0x16, 0x01, 0x5d, 0x02, 0xcc, 0x03, 0x07, 0x00, 0x65, + 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0x01, 0x14, 0x01, 0x66, 0x02, 0xd3, + 0x03, 0x07, 0x00, 0x69, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x1e, + 0x01, 0x64, 0x02, 0xca, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x16, 0x01, 0x14, 0x01, 0x66, 0x02, 0xd4, 0x03, 0x07, 0x00, 0x67, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xff, 0x7e, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0x00, 0x15, 0x01, 0x14, 0x01, 0x64, 0x02, 0xd4, 0x03, 0x07, 0x00, 0x6a, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, + 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, 0x00, 0xd4, 0x00, 0x18, 0x00, 0x65, 0x00, 0x06, 0x00, 0x02, 0x00, 0x98, + 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x89, 0x0e, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x54, 0x00, 0xa8, + 0x01, 0x0f, 0x01, 0xc7, 0x02, 0x5a, 0x02, 0x75, 0x02, 0x99, 0x02, 0xbd, 0x02, 0xed, 0x03, 0x15, 0x03, 0x35, 0x03, 0x50, 0x03, 0x6f, 0x03, 0x8b, 0x03, 0xc4, + 0x03, 0xeb, 0x04, 0x30, 0x04, 0x8f, 0x04, 0xc8, 0x05, 0x1a, 0x05, 0x90, 0x05, 0xb5, 0x06, 0x21, 0x06, 0x82, 0x06, 0xb7, 0x06, 0xe9, 0x06, 0xff, 0x07, 0x2a, + 0x07, 0x40, 0x07, 0x96, 0x08, 0x40, 0x08, 0x7a, 0x08, 0xd0, 0x09, 0x16, 0x09, 0x45, 0x09, 0x70, 0x09, 0x94, 0x09, 0xe4, 0x0a, 0x0c, 0x0a, 0x34, 0x0a, 0x67, + 0x0a, 0x93, 0x0a, 0xb1, 0x0a, 0xec, 0x0b, 0x1c, 0x0b, 0x58, 0x0b, 0x93, 0x0b, 0xdb, 0x0c, 0x1e, 0x0c, 0x71, 0x0c, 0x8f, 0x0c, 0xbc, 0x0c, 0xeb, 0x0d, 0x3f, + 0x0d, 0x69, 0x0d, 0x8d, 0x0d, 0xb8, 0x0d, 0xd7, 0x0d, 0xf3, 0x0e, 0x12, 0x0e, 0x38, 0x0e, 0x55, 0x0e, 0x80, 0x0e, 0xf9, 0x0f, 0x61, 0x0f, 0xa8, 0x10, 0x1d, + 0x10, 0x6d, 0x10, 0xd7, 0x11, 0x67, 0x11, 0x9f, 0x11, 0xd2, 0x12, 0x1b, 0x12, 0x4e, 0x12, 0x63, 0x12, 0xd0, 0x13, 0x1f, 0x13, 0x58, 0x13, 0xcc, 0x14, 0x3b, + 0x14, 0x92, 0x14, 0xe4, 0x15, 0x2b, 0x15, 0x76, 0x15, 0xa3, 0x15, 0xf5, 0x16, 0x1e, 0x16, 0x5f, 0x16, 0x88, 0x16, 0xcc, 0x16, 0xed, 0x17, 0x31, 0x17, 0x76, + 0x17, 0xb5, 0x18, 0x13, 0x18, 0x42, 0x18, 0x5e, 0x18, 0xae, 0x18, 0xfd, 0x19, 0x24, 0x19, 0x84, 0x19, 0xbc, 0x1a, 0x1a, 0x1a, 0x75, 0x1a, 0x81, 0x1a, 0x8d, + 0x1a, 0x99, 0x1a, 0xa9, 0x1a, 0xb9, 0x1a, 0xc8, 0x1a, 0xd7, 0x1a, 0xe6, 0x1a, 0xf5, 0x1b, 0x04, 0x1b, 0x13, 0x1b, 0x22, 0x1b, 0x31, 0x1b, 0x40, 0x1b, 0x4f, + 0x1b, 0x5e, 0x1b, 0x6d, 0x1b, 0x7c, 0x1b, 0x8b, 0x1b, 0x9a, 0x1b, 0xa9, 0x1b, 0xb8, 0x1b, 0xc7, 0x1b, 0xd6, 0x1b, 0xe5, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x02, 0x03, 0xd7, 0x28, 0x5e, 0xd5, 0x8c, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xd3, 0xe7, 0x00, 0x00, + 0x00, 0x00, 0xe3, 0x63, 0xc1, 0x01, 0xfd, 0x7c, 0xfe, 0x7b, 0x0a, 0xf1, 0x04, 0x2d, 0x00, 0x01, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x4d, 0x00, 0x59, 0x01, 0x04, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x36, 0x01, 0xdf, 0x00, 0x3d, 0x02, 0x86, 0x00, 0x16, 0x02, 0x3c, 0x00, 0x2b, 0x03, 0x86, + 0x00, 0x1e, 0x02, 0xee, 0x00, 0x28, 0x01, 0x0a, 0x00, 0x3d, 0x01, 0x53, 0x00, 0x28, 0x01, 0x53, 0x00, 0x1e, 0x02, 0x1e, 0x00, 0x1d, 0x02, 0x3c, 0x00, 0x2b, + 0x01, 0x1d, 0x00, 0x1f, 0x01, 0x40, 0x00, 0x1c, 0x01, 0x19, 0x00, 0x36, 0x01, 0x9f, 0x00, 0x07, 0x02, 0x3c, 0x00, 0x24, 0x02, 0x3c, 0x00, 0x3b, 0x02, 0x3c, + 0x00, 0x26, 0x02, 0x3c, 0x00, 0x26, 0x02, 0x3c, 0x00, 0x11, 0x02, 0x3c, 0x00, 0x31, 0x02, 0x3c, 0x00, 0x23, 0x02, 0x3c, 0x00, 0x1b, 0x02, 0x3c, 0x00, 0x23, + 0x02, 0x3c, 0x00, 0x20, 0x01, 0x19, 0x00, 0x36, 0x01, 0x1d, 0x00, 0x1f, 0x02, 0x3c, 0x00, 0x2b, 0x02, 0x3c, 0x00, 0x2b, 0x02, 0x3c, 0x00, 0x2b, 0x01, 0xdd, + 0x00, 0x05, 0x03, 0x82, 0x00, 0x2f, 0x02, 0xb4, 0x00, 0x00, 0x02, 0x99, 0x00, 0x55, 0x02, 0x82, 0x00, 0x37, 0x02, 0xdc, 0x00, 0x55, 0x02, 0x30, 0x00, 0x5a, + 0x02, 0x25, 0x00, 0x5a, 0x02, 0xd4, 0x00, 0x3a, 0x02, 0xfd, 0x00, 0x5a, 0x01, 0x85, 0x00, 0x20, 0x01, 0x4b, 0xff, 0xb6, 0x02, 0x98, 0x00, 0x5a, 0x02, 0x2f, + 0x00, 0x55, 0x03, 0xaf, 0x00, 0x5a, 0x03, 0x2d, 0x00, 0x5a, 0x03, 0x17, 0x00, 0x37, 0x02, 0x6d, 0x00, 0x55, 0x03, 0x17, 0x00, 0x37, 0x02, 0x90, 0x00, 0x55, + 0x02, 0x27, 0x00, 0x2e, 0x02, 0x41, 0x00, 0x13, 0x02, 0xf4, 0x00, 0x55, 0x02, 0x8a, 0x00, 0x00, 0x03, 0xc7, 0x00, 0x00, 0x02, 0x9e, 0x00, 0x03, 0x02, 0x72, + 0x00, 0x00, 0x02, 0x43, 0x00, 0x18, 0x01, 0x4b, 0x00, 0x46, 0x01, 0x9f, 0x00, 0x06, 0x01, 0x4b, 0x00, 0x19, 0x02, 0x3c, 0x00, 0x17, 0x01, 0x9b, 0xff, 0xfe, + 0x01, 0x6d, 0x00, 0x28, 0x02, 0x57, 0x00, 0x28, 0x02, 0x78, 0x00, 0x49, 0x02, 0x04, 0x00, 0x2f, 0x02, 0x78, 0x00, 0x2f, 0x02, 0x55, 0x00, 0x2f, 0x01, 0x83, + 0x00, 0x14, 0x02, 0x78, 0x00, 0x2f, 0x02, 0x8a, 0x00, 0x49, 0x01, 0x2b, 0x00, 0x44, 0x01, 0x2a, 0xff, 0xcb, 0x02, 0x6c, 0x00, 0x4e, 0x01, 0x2a, 0x00, 0x49, + 0x03, 0xcf, 0x00, 0x49, 0x02, 0x8a, 0x00, 0x49, 0x02, 0x71, 0x00, 0x2f, 0x02, 0x78, 0x00, 0x49, 0x02, 0x78, 0x00, 0x2f, 0x01, 0xbf, 0x00, 0x49, 0x01, 0xf6, + 0x00, 0x2e, 0x01, 0xb2, 0x00, 0x17, 0x02, 0x8a, 0x00, 0x46, 0x02, 0x3b, 0x00, 0x00, 0x03, 0x58, 0x00, 0x0a, 0x02, 0x42, 0x00, 0x05, 0x02, 0x3b, 0x00, 0x00, + 0x01, 0xed, 0x00, 0x1e, 0x01, 0x8a, 0x00, 0x0f, 0x02, 0x27, 0x00, 0xde, 0x01, 0x8a, 0x00, 0x28, 0x02, 0x3c, 0x00, 0x2b, 0x01, 0x7b, 0x00, 0x17, 0x01, 0x7c, + 0x00, 0x1a, 0x01, 0x7c, 0x00, 0x20, 0x00, 0x82, 0xff, 0x40, 0x01, 0x7c, 0x00, 0x0c, 0x01, 0x7c, 0x00, 0x28, 0x01, 0x7c, 0x00, 0x1d, 0x01, 0x7c, 0x00, 0x16, + 0x01, 0x7b, 0x00, 0x14, 0x01, 0x7c, 0x00, 0x16, 0x01, 0x7c, 0x00, 0x15, 0x03, 0x04, 0x00, 0x14, 0x02, 0xad, 0x00, 0x14, 0x02, 0xb4, 0x00, 0x14, 0x04, 0x2f, + 0x00, 0x14, 0x04, 0x37, 0x00, 0x14, 0x01, 0x7c, 0x00, 0x14, 0x00, 0x20, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x0c, 0x00, 0x28, 0x00, 0x16, 0x00, 0x1d, 0x00, 0x16, + 0x00, 0x15, 0x00, 0x14, 0x00, 0x20, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x0c, 0x00, 0x28, 0x00, 0x16, 0x00, 0x1d, 0x00, 0x16, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x0b, 0x17, 0xfd, 0x7c, 0xfd, 0x8d, 0x0a, 0xf1, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x04, 0x02, 0x6a, 0x02, 0xbc, 0x00, 0x05, 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x00, 0x00, 0x4b, + 0x02, 0x8a, 0x02, 0x58, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x32, 0x01, 0x48, 0x00, 0x00, 0x02, 0x0b, 0x08, 0x02, 0x04, 0x05, 0x04, 0x02, 0x02, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0xa0, 0x00, 0x20, 0x00, 0x7e, 0x04, 0x2d, + 0xfe, 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x22, 0x02, 0xca, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, + 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, 0x21, 0xb0, + 0x00, 0x59, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, 0x02, 0x2c, + 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, + 0x14, 0x43, 0x42, 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, 0x04, 0x50, 0x78, + 0xb2, 0x02, 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, 0x20, 0xb0, 0x02, 0x43, + 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, + 0x2c, 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x1b, 0x20, 0x64, + 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, + 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, 0x38, + 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x20, 0xb0, + 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, + 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, 0x1b, 0xb0, + 0x02, 0x25, 0xb0, 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, 0xb0, 0x1e, 0x50, + 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, + 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, 0x20, 0x45, 0x20, 0xb0, + 0x04, 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, 0x59, 0xb0, 0x01, 0x60, 0x2d, + 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, + 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, 0xb0, 0x08, 0x43, 0x20, 0x8a, 0x20, + 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, + 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, 0x43, 0x2b, + 0xb2, 0x00, 0x02, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, 0x62, 0x66, + 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, 0x0e, 0x00, 0x43, + 0x45, 0x42, 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, + 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, + 0x64, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, + 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, + 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, + 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, 0x0c, 0x00, + 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, + 0x2c, 0xb0, 0x01, 0x60, 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, 0xb0, 0x00, + 0x52, 0x58, 0x20, 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, 0x00, 0x63, 0x8a, + 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, + 0x59, 0x24, 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x1b, 0x21, 0x59, 0x24, + 0xb0, 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, 0x61, 0x42, 0xb0, 0x11, 0x2b, + 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, + 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x23, 0xb0, 0x01, 0x61, 0x20, + 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, + 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x20, + 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, 0x00, 0x13, + 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, + 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, + 0x13, 0x00, 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, + 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, + 0x2c, 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, + 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, + 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x5d, + 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, + 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, + 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, + 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, 0x01, 0x00, 0x11, + 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, + 0x2c, 0xb1, 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, 0xb0, 0x25, 0x2c, 0xb1, + 0x04, 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, 0x28, 0x2c, 0xb1, 0x07, 0x20, + 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, + 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x01, 0x60, 0xb0, 0x2e, 0x2a, + 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, + 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, 0x20, 0x47, + 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, + 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, + 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, + 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x34, 0x2c, 0x20, + 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, + 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, 0x20, 0x3c, + 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, + 0x00, 0x43, 0x61, 0xb0, 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb0, + 0x02, 0x25, 0x49, 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, 0x01, 0x15, 0x14, + 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, + 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, + 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, + 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, + 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, + 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, 0x02, 0x25, + 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, + 0xb0, 0x01, 0x63, 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, 0x25, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, 0x60, 0x64, 0x23, 0xb0, + 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, + 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x3c, 0x38, 0x2d, 0xb0, 0x3d, + 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, + 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, 0x2e, + 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, + 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, + 0x59, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, 0x20, 0x3c, + 0x8a, 0x38, 0x23, 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, + 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, + 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, + 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, + 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, + 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, + 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, + 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, 0x20, 0x20, + 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, + 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, + 0x26, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, 0x20, 0x3c, 0x20, + 0x2e, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, + 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, + 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, 0xb0, 0x06, 0x43, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, + 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, 0x23, 0x38, + 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, + 0x3a, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x23, + 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, + 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, + 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, 0xb0, 0x4c, 0x2c, 0xb0, + 0x39, 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, + 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, + 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x53, 0x2c, 0xb2, 0x00, 0x00, + 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, + 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x59, + 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x43, + 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, + 0x01, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x61, + 0x2c, 0xb2, 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, 0x48, 0x2b, 0x2d, 0xb0, + 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, + 0xb0, 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x69, 0x2c, 0xb3, 0x01, 0x00, + 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, + 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x44, + 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, + 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, + 0xb0, 0x73, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, 0x2c, 0xb0, + 0x00, 0x16, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x77, + 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, + 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, + 0x2d, 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, + 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, + 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, + 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, + 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x87, + 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, 0x01, 0x3f, + 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, + 0xb0, 0x06, 0x1b, 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, 0x50, 0x78, 0xb1, + 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, 0xb9, 0x08, 0x00, 0x08, + 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, 0x51, 0x41, 0x00, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, + 0x14, 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, 0x02, 0x56, 0x06, 0x46, 0x08, 0x3a, 0x06, 0x32, 0x04, 0x24, 0x07, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x07, 0x42, + 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x4e, 0x06, 0x40, 0x04, 0x36, 0x02, 0x2b, 0x05, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, + 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, 0x11, 0xc0, 0x0e, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, + 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x09, + 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, + 0x28, 0x01, 0x88, 0x51, 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, 0xba, 0x08, + 0x80, 0x00, 0x01, 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, 0x06, 0x7a, 0x06, + 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x48, 0x06, 0x3c, 0x04, 0x34, 0x02, 0x26, 0x05, 0x09, 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, + 0x00, 0x44, 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x98, 0x00, 0x98, 0x00, 0x72, 0x00, 0x72, 0x02, 0xca, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd4, 0xff, 0xf6, 0x02, 0x2c, + 0xff, 0xf6, 0xff, 0x10, 0x00, 0x95, 0x00, 0x95, 0x00, 0x73, 0x00, 0x73, 0x02, 0x48, 0x00, 0x00, 0x02, 0x50, 0xff, 0xf8, 0x00, 0x95, 0x00, 0x95, 0x00, 0x73, + 0x00, 0x73, 0x02, 0x48, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x50, 0x02, 0x50, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x73, 0x00, 0x73, + 0x02, 0xca, 0xff, 0xf6, 0x02, 0xf8, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xfd, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x7b, + 0x00, 0x7b, 0x00, 0x65, 0x00, 0x65, 0x01, 0x68, 0x00, 0xee, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x7b, 0x00, 0x7b, + 0x00, 0x65, 0x00, 0x65, 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x73, 0x00, 0x73, 0x02, 0xca, 0x00, 0x00, 0x02, 0xf8, 0x02, 0x22, 0x00, 0x00, + 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xf9, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x64, 0x00, 0x64, 0x00, 0x45, 0x00, 0x45, 0x01, 0x2c, 0xff, 0x7e, + 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x34, 0xff, 0x74, 0x01, 0x68, 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x64, 0x00, 0x64, 0x00, 0x45, + 0x00, 0x45, 0x02, 0xcb, 0x01, 0xa0, 0x02, 0xe7, 0x02, 0x67, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe7, 0x01, 0x96, 0x02, 0xe7, 0x02, 0x6d, 0x01, 0x19, 0x00, 0x8f, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, + 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x08, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x30, + 0x00, 0xd0, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, 0x01, 0x1c, + 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x1a, 0x01, 0x70, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, + 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x4e, + 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x41, + 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, + 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, + 0x00, 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, + 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, + 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, + 0x00, 0x6e, 0x00, 0x73, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, + 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, + 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, + 0x00, 0x20, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, + 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, + 0x00, 0x6f, 0x00, 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x34, + 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, + 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9c, + 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, + 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x1f, 0x00, 0x01, + 0x00, 0x22, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x42, 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x05, 0x00, 0x18, 0x00, 0x18, + 0x00, 0x20, 0x00, 0x28, 0x00, 0x36, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x56, 0x00, 0x01, + 0x00, 0x04, 0x00, 0x01, 0x01, 0x5a, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x65, 0x00, 0x01, 0x02, 0xca, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, + 0x00, 0x01, 0x01, 0x68, 0x00, 0x01, 0x02, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, + 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0x65, 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x07, 0x2c, + 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0xf6, 0x00, 0x01, 0x00, 0x34, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x62, 0x00, 0xe2, 0x00, 0x74, + 0x00, 0x7a, 0x00, 0xb2, 0x00, 0x84, 0x00, 0x8a, 0x00, 0xb2, 0x00, 0xa8, 0x00, 0xb2, 0x00, 0xb8, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xc2, 0x00, 0xe2, 0x00, 0xcc, + 0x00, 0xd2, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xe2, 0x00, 0x01, 0x00, 0x15, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, 0x00, 0x23, 0x00, 0x25, 0x00, 0x26, + 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, + 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, 0x37, 0xff, 0xec, 0x00, 0x38, 0xff, 0xec, 0x00, 0x3a, 0xff, 0xe2, 0x00, 0x01, 0x00, 0x2b, + 0x00, 0x32, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xf6, 0x00, 0x0f, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x07, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0d, + 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, 0xec, 0x00, 0x3e, 0x00, 0x14, 0x00, 0x5e, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, + 0xff, 0xf6, 0x00, 0x39, 0xff, 0xec, 0x00, 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, + 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x5f, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x00, 0x20, + 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, 0x04, 0x32, 0x00, 0x04, 0x00, 0x00, 0x04, 0x86, 0x05, 0x50, 0x00, 0x17, + 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, 0xff, 0xe2, 0xff, 0xce, 0xff, 0xc4, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xce, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xec, 0x00, 0x00, 0xff, 0xec, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, + 0xff, 0xf6, 0xff, 0xec, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xf6, 0xff, 0xf6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xba, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xff, 0xc4, 0xff, 0xba, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x60, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x03, + 0x00, 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x31, + 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, + 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6b, + 0x00, 0x02, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x09, 0x00, 0x13, 0x00, 0x0d, 0x00, 0x0d, + 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x22, 0x00, 0x02, 0x00, 0x24, 0x00, 0x24, 0x00, 0x08, + 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x26, 0x00, 0x26, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x09, 0x00, 0x30, + 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0c, 0x00, 0x36, 0x00, 0x36, + 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x0a, 0x00, 0x39, 0x00, 0x39, 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x07, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0e, + 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x49, 0x00, 0x49, 0x00, 0x01, 0x00, 0x4e, + 0x00, 0x4f, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0d, 0x00, 0x57, 0x00, 0x58, 0x00, 0x05, 0x00, 0x59, 0x00, 0x59, + 0x00, 0x16, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x15, 0x00, 0x01, 0x00, 0x03, 0x00, 0x6d, + 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x12, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x16, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, + 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, + 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x16, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x36, 0x00, 0x6c, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, + 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x1a, 0x66, 0x72, 0x61, 0x63, 0x00, 0x20, 0x6c, 0x69, 0x67, 0x61, 0x00, 0x2a, + 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x32, 0x00, 0x10, 0x00, 0x1e, 0x00, 0x32, 0x00, 0x4a, 0x00, 0x88, 0x00, 0xa0, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x5f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x53, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x69, 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, + 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x70, 0x00, 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, + 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, 0x7a, 0x00, 0x83, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x36, 0x00, 0x01, + 0x00, 0x08, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6f, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4d, 0x00, 0x6e, 0x00, 0x03, + 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x6d, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6b, 0x00, 0x02, 0x00, 0x47, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x47}; + +const inline uint8_t FONT_BOLD_ITALICS_DATA[] = { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x0a, 0x6b, 0x06, 0xbf, 0x00, 0x00, 0x5a, 0xd0, 0x00, 0x00, + 0x00, 0x7e, 0x47, 0x50, 0x4f, 0x53, 0x33, 0x4f, 0x0e, 0xbf, 0x00, 0x00, 0x5b, 0x50, 0x00, 0x00, 0x07, 0x4e, 0x47, 0x53, 0x55, 0x42, 0xfc, 0xd3, 0xd8, 0xce, + 0x00, 0x00, 0x62, 0xa0, 0x00, 0x00, 0x01, 0xd4, 0x4f, 0x53, 0x2f, 0x32, 0x6a, 0x82, 0x62, 0xb3, 0x00, 0x00, 0x47, 0xbc, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, + 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, 0x20, 0x41, 0x2b, 0x1e, 0x46, 0x00, 0x00, 0x57, 0x64, + 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, 0x0b, 0x83, 0x00, 0x00, 0x48, 0x50, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x5a, 0xc8, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0xb2, 0xab, 0x07, 0x57, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x43, 0x06, + 0x68, 0x65, 0x61, 0x64, 0x28, 0x3b, 0xd8, 0x55, 0x00, 0x00, 0x45, 0x5c, 0x00, 0x00, 0x00, 0x36, 0x68, 0x68, 0x65, 0x61, 0x0d, 0x3d, 0x0b, 0xc5, 0x00, 0x00, + 0x47, 0x98, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0xfa, 0xcf, 0x0a, 0x08, 0x00, 0x00, 0x45, 0x94, 0x00, 0x00, 0x02, 0x02, 0x6c, 0x6f, 0x63, 0x61, + 0xde, 0x29, 0xcd, 0xbc, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x01, 0x16, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x5b, 0x10, 0x44, 0x00, 0x00, 0x44, 0x24, 0x00, 0x00, + 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x7e, 0x45, 0xc4, 0x00, 0x00, 0x58, 0x90, 0x00, 0x00, 0x02, 0x18, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x93, 0x00, 0x32, + 0x00, 0x00, 0x5a, 0xa8, 0x00, 0x00, 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0xff, 0x8d, 0x0b, 0xc2, 0x00, 0x00, 0x56, 0x5c, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, + 0x00, 0x0b, 0xff, 0xf3, 0x01, 0x3e, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x2c, 0x40, 0x29, 0x04, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, + 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x05, 0x04, 0x00, 0x00, 0x0b, 0x09, 0x04, 0x0f, 0x05, 0x0f, 0x00, 0x03, 0x00, + 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x37, 0x13, 0x33, 0x03, 0x07, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x43, 0x52, 0xa9, 0x7d, + 0x69, 0x2a, 0x23, 0x32, 0x34, 0x23, 0x27, 0x36, 0xe8, 0x01, 0xe2, 0xfe, 0x1e, 0xf5, 0x27, 0x1b, 0x2a, 0x3c, 0x24, 0x20, 0x2e, 0x36, 0x00, 0x02, 0x00, 0x62, + 0x01, 0xc8, 0x01, 0xd2, 0x02, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x40, 0x21, 0x05, 0x03, 0x04, 0x03, 0x01, 0x01, 0x00, 0x5f, 0x02, 0x01, 0x00, 0x00, + 0x6a, 0x01, 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x01, 0x13, 0x33, 0x03, + 0x21, 0x13, 0x33, 0x03, 0x01, 0x27, 0x24, 0x87, 0x4a, 0xfe, 0xda, 0x23, 0x87, 0x4a, 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x02, + 0x00, 0x14, 0x00, 0x00, 0x02, 0x8b, 0x02, 0xca, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, 0x40, 0x44, 0x07, 0x05, 0x02, 0x03, 0x0f, 0x08, 0x02, 0x02, 0x01, 0x03, + 0x02, 0x68, 0x0e, 0x09, 0x02, 0x01, 0x0c, 0x0a, 0x02, 0x00, 0x0b, 0x01, 0x00, 0x67, 0x06, 0x01, 0x04, 0x04, 0x6a, 0x4d, 0x10, 0x0d, 0x02, 0x0b, 0x0b, 0x6b, + 0x0b, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, 0x1c, 0x00, 0x1b, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x0d, 0x1f, 0x2b, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, 0x07, 0x23, + 0x07, 0x33, 0x07, 0x23, 0x07, 0x23, 0x37, 0x23, 0x07, 0x13, 0x33, 0x37, 0x23, 0x51, 0x37, 0x74, 0x09, 0x87, 0x22, 0x7b, 0x09, 0x8d, 0x3a, 0x6a, 0x39, 0x61, + 0x39, 0x69, 0x39, 0x75, 0x09, 0x88, 0x22, 0x7e, 0x09, 0x91, 0x39, 0x6b, 0x39, 0x5f, 0x38, 0x54, 0x60, 0x22, 0x60, 0xc7, 0x65, 0x71, 0x66, 0xc7, 0xc7, 0xc7, + 0xc7, 0x66, 0x71, 0x65, 0xc7, 0xc7, 0xc7, 0x01, 0x2c, 0x71, 0x00, 0x03, 0x00, 0x19, 0xff, 0xc6, 0x02, 0x23, 0x02, 0xf8, 0x00, 0x24, 0x00, 0x2a, 0x00, 0x31, + 0x00, 0x70, 0x40, 0x17, 0x13, 0x01, 0x02, 0x03, 0x16, 0x01, 0x04, 0x02, 0x31, 0x2a, 0x1b, 0x17, 0x08, 0x04, 0x06, 0x01, 0x04, 0x03, 0x01, 0x00, 0x01, 0x04, + 0x4c, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x20, 0x00, 0x06, 0x00, 0x00, 0x06, 0x71, 0x00, 0x02, 0x04, 0x00, 0x02, 0x59, 0x00, 0x01, 0x05, 0x01, 0x00, 0x06, + 0x01, 0x00, 0x69, 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6c, 0x04, 0x4e, 0x1b, 0x40, 0x1f, 0x00, 0x06, 0x00, 0x06, 0x86, 0x00, 0x02, 0x04, 0x00, + 0x02, 0x59, 0x00, 0x01, 0x05, 0x01, 0x00, 0x06, 0x01, 0x00, 0x69, 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6c, 0x04, 0x4e, 0x59, 0x40, 0x0a, 0x11, + 0x17, 0x17, 0x11, 0x18, 0x15, 0x10, 0x07, 0x0d, 0x1d, 0x2b, 0x37, 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x37, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x36, 0x37, + 0x37, 0x33, 0x07, 0x16, 0x16, 0x17, 0x07, 0x26, 0x26, 0x27, 0x07, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x07, 0x23, 0x13, 0x06, 0x06, 0x15, 0x14, 0x17, 0x13, + 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0xc6, 0x33, 0x56, 0x24, 0x26, 0x65, 0x3a, 0x23, 0x2b, 0x47, 0x2a, 0x3c, 0x69, 0x44, 0x11, 0x44, 0x10, 0x29, 0x44, 0x23, + 0x34, 0x1c, 0x3d, 0x1d, 0x1f, 0x2d, 0x48, 0x2a, 0x71, 0x80, 0x13, 0x44, 0x84, 0x19, 0x27, 0x27, 0x06, 0x1f, 0x26, 0x18, 0x11, 0x28, 0x03, 0x14, 0x13, 0x82, + 0x15, 0x22, 0x02, 0x9d, 0x11, 0x2e, 0x43, 0x30, 0x3c, 0x54, 0x30, 0x04, 0x4a, 0x4a, 0x05, 0x14, 0x13, 0x71, 0x0e, 0x14, 0x02, 0x92, 0x11, 0x2c, 0x41, 0x33, + 0x52, 0x70, 0x09, 0x61, 0x02, 0x6f, 0x03, 0x1e, 0x21, 0x26, 0x10, 0xfe, 0xe0, 0x05, 0x23, 0x1e, 0x17, 0x1c, 0x07, 0x00, 0x00, 0x05, 0x00, 0x38, 0xff, 0xf7, + 0x03, 0x34, 0x02, 0xd4, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x21, 0x00, 0x31, 0x00, 0x3f, 0x00, 0xd2, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x2c, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x70, 0x4d, + 0x0e, 0x01, 0x08, 0x08, 0x03, 0x61, 0x0d, 0x06, 0x0b, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x4b, 0xb0, 0x1a, 0x50, 0x58, 0x40, 0x30, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x70, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x03, 0x61, 0x0d, 0x06, 0x0b, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x34, 0x00, 0x07, 0x00, 0x09, + 0x00, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x70, 0x4d, 0x0b, 0x01, 0x03, 0x03, 0x6b, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x06, 0x61, 0x0d, 0x01, 0x06, 0x06, 0x71, 0x06, 0x4e, 0x59, 0x59, 0x40, 0x2b, + 0x33, 0x32, 0x23, 0x22, 0x15, 0x14, 0x10, 0x10, 0x01, 0x00, 0x3a, 0x38, 0x32, 0x3f, 0x33, 0x3f, 0x2b, 0x29, 0x22, 0x31, 0x23, 0x31, 0x1c, 0x1a, 0x14, 0x21, + 0x15, 0x21, 0x10, 0x13, 0x10, 0x13, 0x12, 0x11, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x03, 0x01, 0x33, 0x01, 0x03, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x01, 0x22, 0x26, 0x35, + 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xc2, 0x43, 0x47, 0x15, + 0x2f, 0x4f, 0x3a, 0x43, 0x49, 0x15, 0x30, 0x4f, 0x8c, 0x02, 0x13, 0x73, 0xfd, 0xef, 0x1b, 0x12, 0x1d, 0x14, 0x0b, 0x1c, 0x10, 0x1d, 0x14, 0x0c, 0x01, 0xb8, + 0x46, 0x47, 0x16, 0x31, 0x4e, 0x38, 0x43, 0x49, 0x15, 0x30, 0x4e, 0x33, 0x12, 0x1d, 0x14, 0x0b, 0x1c, 0x10, 0x1d, 0x14, 0x0c, 0x01, 0x14, 0x52, 0x4a, 0x2c, + 0x65, 0x5a, 0x39, 0x4e, 0x4d, 0x2b, 0x65, 0x5b, 0x3a, 0xfe, 0xec, 0x02, 0xca, 0xfd, 0x36, 0x01, 0x79, 0x27, 0x3c, 0x45, 0x1e, 0x2f, 0x24, 0x3c, 0x45, 0x21, + 0x2f, 0xfe, 0x7e, 0x4d, 0x46, 0x35, 0x6a, 0x58, 0x36, 0x4d, 0x4a, 0x2d, 0x67, 0x5b, 0x3a, 0x65, 0x27, 0x3c, 0x45, 0x1e, 0x2f, 0x24, 0x3c, 0x45, 0x21, 0x2f, + 0x00, 0x03, 0x00, 0x21, 0xff, 0xf6, 0x02, 0xba, 0x02, 0xd5, 0x00, 0x20, 0x00, 0x2c, 0x00, 0x36, 0x00, 0x99, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x06, + 0x01, 0x02, 0x04, 0x31, 0x30, 0x1b, 0x14, 0x13, 0x05, 0x05, 0x02, 0x1e, 0x01, 0x00, 0x05, 0x03, 0x4c, 0x1b, 0x40, 0x12, 0x06, 0x01, 0x02, 0x04, 0x31, 0x30, + 0x1b, 0x14, 0x13, 0x05, 0x05, 0x02, 0x1e, 0x01, 0x03, 0x05, 0x03, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x24, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x4d, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6b, + 0x4d, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x2e, 0x2d, 0x01, 0x00, 0x2d, 0x36, 0x2e, 0x36, 0x28, + 0x26, 0x1d, 0x1c, 0x18, 0x17, 0x0d, 0x0b, 0x00, 0x20, 0x01, 0x20, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x35, 0x34, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, 0x07, 0x17, 0x23, 0x27, 0x06, 0x06, 0x13, 0x36, 0x36, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x03, 0x32, 0x36, 0x37, 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, 0xf4, 0x65, 0x6e, 0x54, 0x58, 0x25, 0x38, 0x60, + 0x3c, 0x3f, 0x4e, 0x24, 0x5f, 0x53, 0x5f, 0x1c, 0x22, 0x10, 0x92, 0x1e, 0x49, 0x30, 0x64, 0xab, 0x23, 0x27, 0x5f, 0x10, 0x28, 0x39, 0x1d, 0x14, 0x22, 0x22, + 0x0c, 0x31, 0x20, 0x36, 0x16, 0x6e, 0x23, 0x2a, 0x2a, 0x0a, 0x60, 0x59, 0x4b, 0x65, 0x2b, 0x3e, 0x40, 0x44, 0x5b, 0x2e, 0x2a, 0x44, 0x28, 0x4a, 0x64, 0x22, + 0x80, 0x23, 0x45, 0x28, 0x47, 0x7a, 0x32, 0x8c, 0x30, 0x1a, 0x20, 0x01, 0xcb, 0x14, 0x33, 0x26, 0x1c, 0x19, 0x30, 0x21, 0x16, 0x2d, 0xfe, 0xa4, 0x11, 0x0c, + 0xa0, 0x14, 0x33, 0x2c, 0x1d, 0x2d, 0x00, 0x01, 0x00, 0x62, 0x01, 0xc8, 0x01, 0x0c, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, + 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x13, 0x33, 0x03, 0x62, 0x23, 0x87, + 0x4a, 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x24, 0xff, 0x62, 0x01, 0x9a, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, + 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x16, 0x03, 0x0d, 0x17, 0x2b, 0x17, 0x26, 0x26, 0x35, 0x34, + 0x12, 0x37, 0x33, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x17, 0x6d, 0x25, 0x24, 0x7e, 0x78, 0x80, 0x47, 0x6e, 0x3f, 0x1e, 0x1b, 0x9e, 0x41, 0x96, 0x50, 0xad, 0x01, + 0x18, 0x7c, 0x4d, 0xb3, 0xcf, 0x77, 0x4c, 0x94, 0x42, 0x00, 0x00, 0x01, 0xff, 0xba, 0xff, 0x62, 0x01, 0x30, 0x02, 0xd6, 0x00, 0x0e, 0x00, 0x2e, 0x4b, 0xb0, + 0x29, 0x50, 0x58, 0x40, 0x0c, 0x02, 0x01, 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x1b, 0x40, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, + 0x01, 0x01, 0x01, 0x76, 0x59, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x17, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x27, 0x33, + 0x16, 0x16, 0x15, 0x14, 0x02, 0x07, 0x46, 0x47, 0x6e, 0x3f, 0x1e, 0x1b, 0x72, 0x25, 0x24, 0x7d, 0x78, 0x9e, 0x4e, 0xb2, 0xcf, 0x77, 0x4c, 0xa0, 0x42, 0x41, + 0xa2, 0x50, 0xae, 0xfe, 0xe8, 0x7b, 0x00, 0x01, 0x00, 0x55, 0x01, 0x19, 0x02, 0x35, 0x02, 0xfd, 0x00, 0x0e, 0x00, 0x1d, 0x40, 0x1a, 0x09, 0x08, 0x07, 0x06, + 0x04, 0x00, 0x4a, 0x0e, 0x0d, 0x0c, 0x05, 0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0x49, 0x00, 0x00, 0x00, 0x76, 0x1a, 0x01, 0x0d, 0x17, 0x2b, 0x01, 0x27, 0x07, + 0x27, 0x37, 0x27, 0x37, 0x17, 0x37, 0x17, 0x07, 0x37, 0x07, 0x27, 0x17, 0x01, 0x5f, 0x2d, 0x61, 0x62, 0x86, 0xa0, 0x29, 0xa5, 0x11, 0x7e, 0x3a, 0xbd, 0x08, + 0xa6, 0x4e, 0x01, 0x19, 0xa6, 0x89, 0x4f, 0x7a, 0x2e, 0x71, 0x54, 0xb3, 0x18, 0xac, 0x0d, 0x79, 0x15, 0xa5, 0x00, 0x01, 0x00, 0x35, 0x00, 0x6f, 0x02, 0x1a, + 0x02, 0x54, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x00, 0x05, 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, + 0x05, 0x02, 0x5f, 0x00, 0x02, 0x05, 0x02, 0x4f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, + 0x35, 0x33, 0x35, 0x33, 0x01, 0x5d, 0xbd, 0xbd, 0x6b, 0xbd, 0xbd, 0x6b, 0x01, 0x96, 0x6b, 0xbc, 0xbc, 0x6b, 0xbe, 0x00, 0x00, 0x01, 0xff, 0xd0, 0xff, 0x7f, + 0x00, 0xc0, 0x00, 0x74, 0x00, 0x08, 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, + 0x4f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x13, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x36, 0x36, 0x37, 0x33, 0x17, 0x06, 0x06, 0x07, 0x30, 0x1a, 0x32, 0x13, 0x8d, + 0x04, 0x18, 0x44, 0x24, 0x81, 0x3b, 0x86, 0x34, 0x0b, 0x35, 0x7e, 0x37, 0x00, 0x01, 0x00, 0x11, 0x00, 0xce, 0x01, 0x2c, 0x01, 0x4a, 0x00, 0x03, 0x00, 0x1e, + 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, + 0x03, 0x0d, 0x17, 0x2b, 0x37, 0x37, 0x21, 0x07, 0x11, 0x1a, 0x01, 0x01, 0x1a, 0xce, 0x7c, 0x7c, 0x00, 0x01, 0x00, 0x08, 0xff, 0xf3, 0x00, 0xb7, 0x00, 0x9b, + 0x00, 0x0b, 0x00, 0x1a, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x02, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, + 0x03, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x50, 0x21, 0x27, 0x3a, 0x2c, 0x21, 0x28, 0x37, 0x0d, 0x21, + 0x21, 0x31, 0x35, 0x21, 0x22, 0x34, 0x31, 0x00, 0x00, 0x01, 0xff, 0xd3, 0xff, 0xfa, 0x01, 0xf1, 0x02, 0xd0, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, + 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x01, 0x33, 0x01, 0x2d, + 0x01, 0x95, 0x89, 0xfe, 0x6c, 0x06, 0x02, 0xd6, 0xfd, 0x2a, 0x00, 0x02, 0x00, 0x20, 0xff, 0xf6, 0x02, 0x1e, 0x02, 0xd5, 0x00, 0x0f, 0x00, 0x21, 0x00, 0x2d, + 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x11, + 0x10, 0x01, 0x00, 0x1a, 0x18, 0x10, 0x21, 0x11, 0x21, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x14, 0x16, 0xe5, 0x65, 0x60, 0x28, 0x50, + 0x76, 0x4d, 0x5c, 0x67, 0x24, 0x4b, 0x77, 0x47, 0x1c, 0x30, 0x26, 0x19, 0x0e, 0x1e, 0x1e, 0x1e, 0x31, 0x25, 0x19, 0x0d, 0x1b, 0x0a, 0x7c, 0x72, 0x62, 0xb3, + 0x8b, 0x51, 0x6e, 0x79, 0x5f, 0xb4, 0x90, 0x55, 0x7a, 0x31, 0x53, 0x65, 0x6b, 0x2f, 0x36, 0x32, 0x36, 0x57, 0x65, 0x63, 0x25, 0x37, 0x3a, 0x00, 0x00, 0x01, + 0x00, 0x59, 0x00, 0x00, 0x01, 0xe7, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x1b, 0x40, 0x18, 0x08, 0x07, 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6a, + 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x11, 0x19, 0x02, 0x0d, 0x18, 0x2b, 0x01, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x25, 0x33, 0x03, 0x23, + 0x01, 0x13, 0x05, 0x16, 0x0a, 0x09, 0x26, 0x10, 0x5f, 0x41, 0x01, 0x14, 0x7a, 0x97, 0x95, 0x01, 0x95, 0x1a, 0x52, 0x20, 0x07, 0x1d, 0x0a, 0x3c, 0x69, 0xaa, + 0xfd, 0x36, 0x00, 0x01, 0xff, 0xe8, 0x00, 0x00, 0x02, 0x18, 0x02, 0xd4, 0x00, 0x1c, 0x00, 0x2f, 0x40, 0x2c, 0x0d, 0x01, 0x00, 0x01, 0x0c, 0x01, 0x02, 0x00, + 0x02, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, + 0x00, 0x1c, 0x00, 0x1c, 0x28, 0x25, 0x28, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x15, 0x21, 0x07, 0x18, 0x15, 0xe9, 0x3a, 0x44, 0x1d, 0x28, 0x22, 0x24, 0x44, 0x2e, 0x47, 0x32, + 0x77, 0x4c, 0x46, 0x59, 0x2a, 0x37, 0x5e, 0x3d, 0x83, 0x01, 0x15, 0x1a, 0x68, 0xcf, 0x34, 0x4a, 0x3b, 0x1b, 0x25, 0x26, 0x24, 0x26, 0x63, 0x2b, 0x3a, 0x32, + 0x4f, 0x2d, 0x3f, 0x68, 0x5d, 0x32, 0x6c, 0x05, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x07, 0xff, 0xf6, 0x02, 0x1b, 0x02, 0xd4, 0x00, 0x2b, 0x00, 0x4a, 0x40, 0x47, + 0x1b, 0x01, 0x04, 0x05, 0x1a, 0x01, 0x03, 0x04, 0x24, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x03, 0x00, 0x02, + 0x01, 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x01, 0x00, 0x1f, 0x1d, 0x18, 0x16, 0x11, 0x0f, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x2b, 0x01, 0x2b, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, + 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc4, 0x37, 0x62, 0x24, 0x29, 0x60, 0x2d, 0x47, 0x59, 0x35, 0x49, 0x43, 0x16, 0x24, + 0x2b, 0x50, 0x34, 0x26, 0x2a, 0x2c, 0x46, 0x1a, 0x3e, 0x30, 0x6b, 0x4f, 0x63, 0x63, 0x5a, 0x54, 0x36, 0x4c, 0x3e, 0x84, 0x0a, 0x14, 0x13, 0x82, 0x18, 0x19, + 0x3a, 0x3b, 0x24, 0x30, 0x6c, 0x16, 0x32, 0x2a, 0x1d, 0x28, 0x20, 0x11, 0x64, 0x20, 0x27, 0x5d, 0x46, 0x4a, 0x67, 0x0f, 0x04, 0x0a, 0x48, 0x44, 0x38, 0x68, + 0x41, 0x00, 0x00, 0x02, 0xff, 0xf4, 0x00, 0x00, 0x02, 0x1b, 0x02, 0xca, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x2e, 0x40, 0x2b, 0x11, 0x01, 0x02, 0x01, 0x01, 0x4c, + 0x05, 0x01, 0x02, 0x03, 0x01, 0x00, 0x04, 0x02, 0x00, 0x68, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x6b, 0x04, 0x4e, 0x00, 0x00, 0x0c, 0x0b, + 0x00, 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0d, 0x1a, 0x2b, 0x33, 0x37, 0x21, 0x37, 0x01, 0x33, 0x03, 0x33, 0x07, 0x23, 0x07, 0x03, 0x33, 0x37, + 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x07, 0xf5, 0x1f, 0xfe, 0xe0, 0x17, 0x01, 0x78, 0x98, 0x5f, 0x53, 0x19, 0x53, 0x1f, 0xef, 0x98, 0x1c, 0x06, 0x0f, 0x0f, + 0x04, 0x05, 0x0b, 0x22, 0x11, 0x94, 0x72, 0x01, 0xc4, 0xfe, 0x3f, 0x75, 0x94, 0x01, 0x09, 0x79, 0x1a, 0x3c, 0x33, 0x0c, 0x13, 0x30, 0x15, 0x00, 0x00, 0x01, + 0x00, 0x0d, 0xff, 0xf6, 0x02, 0x27, 0x02, 0xca, 0x00, 0x21, 0x00, 0x44, 0x40, 0x41, 0x17, 0x12, 0x02, 0x02, 0x05, 0x11, 0x04, 0x02, 0x01, 0x02, 0x03, 0x01, + 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x00, + 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1b, 0x19, 0x16, 0x15, 0x14, 0x13, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x21, 0x01, 0x21, 0x07, 0x0d, + 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x07, 0x23, 0x07, + 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc7, 0x3a, 0x61, 0x1f, 0x24, 0x58, 0x30, 0x3c, 0x46, 0x1e, 0x2f, 0x3e, 0x1e, 0x38, 0x12, 0x33, + 0x65, 0x01, 0x71, 0x1b, 0xef, 0x2b, 0x0c, 0x1f, 0x13, 0x36, 0x58, 0x33, 0x3f, 0x83, 0x0a, 0x17, 0x11, 0x83, 0x14, 0x1c, 0x27, 0x3b, 0x1f, 0x26, 0x36, 0x0b, + 0x05, 0x26, 0x01, 0x66, 0x80, 0x8f, 0x02, 0x05, 0x29, 0x54, 0x41, 0x4a, 0x7b, 0x49, 0x00, 0x02, 0x00, 0x2b, 0xff, 0xf6, 0x02, 0x33, 0x02, 0xd5, 0x00, 0x1f, + 0x00, 0x30, 0x00, 0x47, 0x40, 0x44, 0x0d, 0x01, 0x02, 0x01, 0x0e, 0x01, 0x03, 0x02, 0x14, 0x01, 0x05, 0x03, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x05, 0x04, 0x03, + 0x05, 0x69, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x21, + 0x20, 0x01, 0x00, 0x28, 0x26, 0x20, 0x30, 0x21, 0x30, 0x19, 0x17, 0x12, 0x10, 0x0b, 0x09, 0x00, 0x1f, 0x01, 0x1f, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, + 0x35, 0x34, 0x36, 0x36, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, + 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0xfc, 0x67, 0x6a, 0x26, 0x47, 0x31, 0x31, + 0x7a, 0x52, 0x1f, 0x3b, 0x13, 0x19, 0x12, 0x33, 0x18, 0x64, 0x74, 0x1e, 0x04, 0x19, 0x4a, 0x35, 0x4a, 0x56, 0x19, 0x3c, 0x65, 0x46, 0x25, 0x30, 0x18, 0x21, + 0x21, 0x1c, 0x30, 0x1f, 0x04, 0x02, 0x02, 0x26, 0x0a, 0x7c, 0x73, 0x4e, 0x99, 0x84, 0x2d, 0x2c, 0x2c, 0x08, 0x05, 0x78, 0x05, 0x07, 0x6f, 0x6e, 0x23, 0x2e, + 0x5c, 0x59, 0x2a, 0x65, 0x5b, 0x3b, 0x79, 0x30, 0x4a, 0x27, 0x23, 0x29, 0x1e, 0x2c, 0x17, 0x0b, 0x17, 0x0b, 0x29, 0x36, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, + 0x02, 0x52, 0x02, 0xca, 0x00, 0x06, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, + 0x4e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x37, 0x21, 0x07, 0x01, 0x26, 0x01, 0x68, 0xfe, 0xcd, 0x1b, + 0x01, 0xdc, 0x14, 0xfe, 0x91, 0x02, 0x4b, 0x7f, 0x5f, 0xfd, 0x95, 0x00, 0x00, 0x03, 0x00, 0x1b, 0xff, 0xf6, 0x02, 0x26, 0x02, 0xd5, 0x00, 0x1c, 0x00, 0x28, + 0x00, 0x34, 0x00, 0x35, 0x40, 0x32, 0x2f, 0x15, 0x06, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, + 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x2a, 0x29, 0x01, 0x00, 0x29, 0x34, 0x2a, 0x34, 0x24, 0x22, 0x0e, 0x0c, 0x00, 0x1c, 0x01, + 0x1c, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, + 0x07, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x03, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, + 0x06, 0x06, 0x15, 0x14, 0x16, 0xfb, 0x70, 0x70, 0x58, 0x52, 0x1e, 0x33, 0x36, 0x69, 0x4d, 0x43, 0x57, 0x2c, 0x2b, 0x45, 0x28, 0x1a, 0x31, 0x1f, 0x36, 0x70, + 0x14, 0x2a, 0x30, 0x26, 0x1f, 0x27, 0x2a, 0x21, 0x1d, 0x33, 0x30, 0x2b, 0x22, 0x38, 0x38, 0x31, 0x0a, 0x68, 0x4d, 0x4d, 0x65, 0x1e, 0x17, 0x49, 0x32, 0x37, + 0x5b, 0x36, 0x2d, 0x4a, 0x2c, 0x34, 0x49, 0x31, 0x0e, 0x11, 0x30, 0x43, 0x2e, 0x34, 0x5f, 0x3b, 0x01, 0xbe, 0x11, 0x34, 0x27, 0x21, 0x26, 0x2f, 0x22, 0x23, + 0x30, 0xfe, 0xa2, 0x3a, 0x24, 0x29, 0x38, 0x16, 0x16, 0x3d, 0x2c, 0x27, 0x2f, 0x00, 0x00, 0x02, 0x00, 0x2a, 0xff, 0xf6, 0x02, 0x15, 0x02, 0xd5, 0x00, 0x21, + 0x00, 0x32, 0x00, 0x47, 0x40, 0x44, 0x0c, 0x01, 0x02, 0x04, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, + 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x23, + 0x22, 0x01, 0x00, 0x2d, 0x2b, 0x22, 0x32, 0x23, 0x32, 0x19, 0x17, 0x11, 0x0f, 0x08, 0x06, 0x00, 0x21, 0x01, 0x21, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, + 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, + 0x07, 0x06, 0x06, 0x13, 0x32, 0x36, 0x36, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x9f, 0x21, 0x40, 0x14, 0x13, 0x3b, + 0x21, 0x36, 0x4c, 0x32, 0x20, 0x0a, 0x04, 0x18, 0x46, 0x32, 0x55, 0x52, 0x19, 0x3c, 0x6a, 0x50, 0x5c, 0x6e, 0x1e, 0x3c, 0x2e, 0x2a, 0x74, 0x26, 0x1d, 0x2c, + 0x1c, 0x04, 0x02, 0x02, 0x22, 0x25, 0x24, 0x30, 0x18, 0x25, 0x0a, 0x0a, 0x06, 0x7d, 0x07, 0x0d, 0x25, 0x3e, 0x4e, 0x28, 0x22, 0x2b, 0x6c, 0x52, 0x28, 0x61, + 0x59, 0x3a, 0x6f, 0x7d, 0x46, 0x98, 0x88, 0x30, 0x2b, 0x32, 0x01, 0x79, 0x1f, 0x2e, 0x16, 0x0b, 0x17, 0x0b, 0x29, 0x34, 0x2f, 0x45, 0x23, 0x2a, 0x2c, 0x00, + 0x00, 0x02, 0x00, 0x08, 0xff, 0xf3, 0x01, 0x10, 0x02, 0x2c, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x2d, 0x40, 0x2a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x0d, 0x0c, 0x01, 0x00, 0x13, 0x11, 0x0c, 0x17, 0x0d, 0x17, 0x07, + 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x03, 0x22, 0x26, 0x35, 0x34, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0xa9, 0x21, 0x27, 0x39, 0x2d, 0x20, 0x29, 0x37, 0x89, 0x21, 0x27, 0x3a, 0x2c, 0x21, 0x28, 0x37, 0x01, 0x85, 0x21, + 0x20, 0x32, 0x34, 0x20, 0x22, 0x34, 0x31, 0xfe, 0x6e, 0x21, 0x21, 0x31, 0x35, 0x21, 0x22, 0x34, 0x31, 0x00, 0x00, 0x02, 0xff, 0xca, 0xff, 0x7f, 0x01, 0x10, + 0x02, 0x2c, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x2a, 0x40, 0x27, 0x00, 0x02, 0x05, 0x01, 0x03, 0x02, 0x03, 0x63, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x73, 0x00, 0x4e, 0x0c, 0x0c, 0x01, 0x00, 0x0c, 0x14, 0x0c, 0x14, 0x10, 0x0f, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, + 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x36, 0x36, 0x37, 0x33, 0x17, 0x06, 0x06, 0x07, 0xa9, 0x21, 0x27, 0x39, 0x2d, 0x20, 0x29, + 0x37, 0xfe, 0xf1, 0x1a, 0x32, 0x13, 0x8d, 0x04, 0x18, 0x44, 0x24, 0x01, 0x85, 0x21, 0x20, 0x32, 0x34, 0x20, 0x22, 0x34, 0x31, 0xfd, 0xfa, 0x3b, 0x86, 0x34, + 0x0b, 0x35, 0x7e, 0x37, 0x00, 0x01, 0x00, 0x35, 0x00, 0x63, 0x02, 0x1a, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, 0x32, 0x2b, 0x25, 0x25, + 0x35, 0x25, 0x15, 0x05, 0x05, 0x02, 0x1a, 0xfe, 0x1b, 0x01, 0xe5, 0xfe, 0xb2, 0x01, 0x4e, 0x63, 0xd6, 0x46, 0xf2, 0x75, 0x9b, 0x89, 0x00, 0x02, 0x00, 0x35, + 0x00, 0xcc, 0x02, 0x1a, 0x01, 0xf4, 0x00, 0x03, 0x00, 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, + 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, + 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, 0x35, 0x21, 0x15, 0x35, 0x01, 0xe5, 0xfe, 0x1b, 0x01, 0xe5, 0x01, 0x8a, 0x6a, 0x6a, + 0xbe, 0x6b, 0x6b, 0x00, 0x00, 0x01, 0x00, 0x35, 0x00, 0x63, 0x02, 0x1a, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, 0x25, + 0x25, 0x35, 0x05, 0x15, 0x05, 0x35, 0x01, 0x4e, 0xfe, 0xb2, 0x01, 0xe5, 0xfe, 0x1b, 0xd8, 0x89, 0x9b, 0x75, 0xf2, 0x46, 0xd6, 0x00, 0x00, 0x02, 0x00, 0x4d, + 0xff, 0xf3, 0x01, 0xeb, 0x02, 0xd4, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x3f, 0x40, 0x3c, 0x0d, 0x01, 0x00, 0x01, 0x0c, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x05, 0x01, + 0x02, 0x00, 0x04, 0x00, 0x02, 0x04, 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, + 0x71, 0x03, 0x4e, 0x1d, 0x1c, 0x00, 0x00, 0x23, 0x21, 0x1c, 0x27, 0x1d, 0x27, 0x00, 0x1b, 0x00, 0x1b, 0x25, 0x28, 0x07, 0x0d, 0x18, 0x2b, 0x37, 0x36, 0x36, + 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x0e, 0x02, 0x07, 0x07, 0x22, + 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x7f, 0x0d, 0x36, 0x3c, 0x31, 0x2c, 0x1e, 0x23, 0x23, 0x47, 0x2c, 0x2d, 0x2d, 0x6d, 0x3f, 0x58, + 0x63, 0x26, 0x43, 0x2a, 0x1d, 0x23, 0x14, 0x07, 0x64, 0x2a, 0x22, 0x2d, 0x37, 0x21, 0x28, 0x35, 0xed, 0x45, 0x5b, 0x28, 0x21, 0x2d, 0x1f, 0x1b, 0x1f, 0x1c, + 0x15, 0x6c, 0x19, 0x24, 0x56, 0x4c, 0x32, 0x47, 0x38, 0x1c, 0x13, 0x21, 0x27, 0x1d, 0xfa, 0x2b, 0x1a, 0x24, 0x3d, 0x25, 0x22, 0x29, 0x36, 0x00, 0x00, 0x02, + 0x00, 0x2d, 0xff, 0xa5, 0x03, 0x4e, 0x02, 0xca, 0x00, 0x40, 0x00, 0x4f, 0x00, 0x93, 0x40, 0x16, 0x23, 0x01, 0x09, 0x04, 0x45, 0x01, 0x05, 0x09, 0x14, 0x01, + 0x02, 0x05, 0x3d, 0x01, 0x07, 0x02, 0x3e, 0x01, 0x00, 0x07, 0x05, 0x4c, 0x4b, 0xb0, 0x15, 0x50, 0x58, 0x40, 0x28, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, + 0x07, 0x05, 0x02, 0x69, 0x00, 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x09, 0x09, 0x04, + 0x61, 0x00, 0x04, 0x04, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x04, 0x00, 0x09, 0x05, 0x04, 0x09, 0x69, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, 0x07, + 0x05, 0x02, 0x69, 0x00, 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x06, 0x4e, 0x59, 0x40, 0x1f, 0x42, + 0x41, 0x01, 0x00, 0x49, 0x47, 0x41, 0x4f, 0x42, 0x4f, 0x3b, 0x39, 0x33, 0x31, 0x2b, 0x29, 0x21, 0x1f, 0x19, 0x17, 0x12, 0x10, 0x0a, 0x08, 0x00, 0x40, 0x01, + 0x40, 0x0c, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, + 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, + 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x03, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, + 0x14, 0x16, 0x01, 0x87, 0x72, 0x9a, 0x4e, 0x4c, 0x83, 0xa9, 0x5d, 0x9b, 0xb1, 0x20, 0x3f, 0x5a, 0x39, 0x27, 0x3a, 0x09, 0x05, 0x15, 0x39, 0x2f, 0x37, 0x4c, + 0x23, 0x42, 0x5f, 0x3b, 0x36, 0x4c, 0x1e, 0x34, 0x05, 0x08, 0x10, 0x0c, 0x1b, 0x2d, 0x21, 0x12, 0x73, 0x79, 0x63, 0x9d, 0x5c, 0x32, 0x6e, 0x59, 0x3e, 0x65, + 0x34, 0x2f, 0x71, 0x40, 0x27, 0x31, 0x10, 0x1c, 0x09, 0x12, 0x0d, 0x23, 0x34, 0x22, 0x11, 0x1c, 0x5b, 0x59, 0x98, 0x5e, 0x72, 0xaf, 0x78, 0x3d, 0xa0, 0x90, + 0x3b, 0x6f, 0x58, 0x34, 0x23, 0x25, 0x21, 0x27, 0x47, 0x50, 0x33, 0x61, 0x4e, 0x2e, 0x10, 0x0b, 0xcd, 0x16, 0x1f, 0x10, 0x12, 0x0f, 0x27, 0x40, 0x4d, 0x27, + 0x63, 0x73, 0x5a, 0xa5, 0x70, 0x44, 0x74, 0x45, 0x16, 0x14, 0x5b, 0x13, 0x19, 0x01, 0x18, 0x49, 0x3b, 0x6c, 0x02, 0x03, 0x23, 0x37, 0x3d, 0x1a, 0x26, 0x1e, + 0x00, 0x02, 0xff, 0xc4, 0x00, 0x00, 0x02, 0x38, 0x02, 0xca, 0x00, 0x07, 0x00, 0x11, 0x00, 0x2c, 0x40, 0x29, 0x0d, 0x01, 0x04, 0x00, 0x01, 0x4c, 0x00, 0x04, + 0x00, 0x02, 0x01, 0x04, 0x02, 0x68, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x09, 0x08, 0x00, 0x07, 0x00, + 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x33, 0x13, 0x23, 0x27, 0x23, 0x07, 0x13, 0x33, 0x27, 0x26, 0x26, 0x37, 0x23, 0x06, 0x06, 0x07, + 0x3c, 0x01, 0x76, 0xb6, 0x48, 0x91, 0x0c, 0xe7, 0x54, 0x91, 0xa3, 0x0d, 0x02, 0x04, 0x01, 0x02, 0x0a, 0x18, 0x0f, 0x02, 0xca, 0xfd, 0x36, 0xaa, 0xaa, 0x01, + 0x29, 0xb8, 0x1d, 0x3c, 0x1f, 0x1b, 0x35, 0x1f, 0x00, 0x03, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x63, 0x02, 0xca, 0x00, 0x10, 0x00, 0x18, 0x00, 0x21, 0x00, 0x43, + 0x40, 0x40, 0x08, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x00, 0x05, 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, + 0x4d, 0x08, 0x01, 0x04, 0x04, 0x01, 0x5f, 0x06, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1a, 0x19, 0x12, 0x11, 0x00, 0x00, 0x20, 0x1e, 0x19, 0x21, 0x1a, 0x21, + 0x17, 0x15, 0x11, 0x18, 0x12, 0x18, 0x00, 0x10, 0x00, 0x0f, 0x21, 0x09, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, + 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x13, 0x32, 0x36, 0x35, 0x34, 0x23, 0x23, 0x07, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x07, 0x1a, 0x97, 0xd0, + 0x66, 0x7c, 0x52, 0x4a, 0x31, 0x3a, 0x4a, 0x7f, 0x50, 0x3a, 0x35, 0x41, 0x53, 0x4a, 0x22, 0x17, 0x37, 0x43, 0x2c, 0x2d, 0x51, 0x28, 0x02, 0xca, 0x49, 0x56, + 0x49, 0x5e, 0x10, 0x04, 0x0d, 0x45, 0x35, 0x51, 0x67, 0x31, 0x01, 0xaf, 0x2b, 0x31, 0x43, 0x9f, 0xfe, 0xce, 0x37, 0x34, 0x26, 0x29, 0xba, 0x00, 0x00, 0x01, + 0x00, 0x3b, 0xff, 0xf6, 0x02, 0x8c, 0x02, 0xd5, 0x00, 0x1d, 0x00, 0x37, 0x40, 0x34, 0x0c, 0x01, 0x02, 0x01, 0x1b, 0x0d, 0x02, 0x03, 0x02, 0x1c, 0x01, 0x00, + 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, + 0x00, 0x19, 0x17, 0x11, 0x0f, 0x0a, 0x08, 0x00, 0x1d, 0x01, 0x1d, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x01, 0x3f, 0x80, 0x84, 0x1d, 0x3b, 0x5a, 0x7c, 0x50, 0x3f, + 0x67, 0x2d, 0x3a, 0x26, 0x49, 0x2a, 0x38, 0x55, 0x39, 0x1d, 0x46, 0x3f, 0x2b, 0x51, 0x2f, 0x5c, 0x0a, 0x97, 0x7d, 0x40, 0x83, 0x76, 0x5c, 0x36, 0x1d, 0x1a, + 0x78, 0x16, 0x19, 0x38, 0x5d, 0x73, 0x3c, 0x4b, 0x51, 0x14, 0x12, 0x7e, 0x27, 0x00, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x86, 0x02, 0xca, 0x00, 0x09, + 0x00, 0x13, 0x00, 0x2c, 0x40, 0x29, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x01, 0x5f, 0x04, 0x01, 0x01, 0x01, + 0x6b, 0x01, 0x4e, 0x0b, 0x0a, 0x00, 0x00, 0x12, 0x10, 0x0a, 0x13, 0x0b, 0x13, 0x00, 0x09, 0x00, 0x08, 0x21, 0x06, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x37, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, 0x1a, 0x97, 0xbd, 0x83, 0x95, 0x61, 0xb8, 0x82, 0x13, 0x4a, + 0x6b, 0x39, 0x49, 0x3f, 0x36, 0x62, 0x02, 0xca, 0x8b, 0x89, 0x85, 0xc5, 0x6c, 0x7e, 0x4f, 0x8a, 0x59, 0x50, 0x4d, 0xfe, 0x31, 0x00, 0x00, 0x01, 0x00, 0x1a, + 0x00, 0x00, 0x02, 0x41, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, + 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x04, 0x04, 0x05, 0x5f, 0x06, 0x01, 0x05, 0x05, 0x6b, 0x05, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x33, 0x13, 0x21, 0x07, 0x23, 0x07, 0x33, 0x07, 0x23, 0x07, 0x33, 0x07, 0x1a, 0x97, 0x01, 0x90, 0x1b, 0xf8, 0x21, 0xe8, 0x1b, + 0xe8, 0x27, 0xf9, 0x1a, 0x02, 0xca, 0x7d, 0x9c, 0x7d, 0xb5, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x3f, 0x02, 0xca, 0x00, 0x09, 0x00, 0x29, + 0x40, 0x26, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x04, 0x04, 0x6b, 0x04, + 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x11, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x21, 0x07, 0x23, 0x07, 0x33, 0x07, 0x23, 0x03, 0x1a, + 0x97, 0x01, 0x8e, 0x1b, 0xf7, 0x26, 0xe6, 0x1b, 0xe7, 0x3a, 0x02, 0xca, 0x7d, 0xb6, 0x7e, 0xfe, 0xe7, 0x00, 0x00, 0x01, 0x00, 0x3b, 0xff, 0xf6, 0x02, 0xa7, + 0x02, 0xd5, 0x00, 0x21, 0x00, 0x3e, 0x40, 0x3b, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, 0x05, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x67, + 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1e, 0x1d, + 0x1c, 0x1b, 0x18, 0x16, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x21, 0x01, 0x21, 0x07, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, + 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x23, 0x37, 0x21, 0x03, 0x06, 0x06, 0x01, 0x48, 0x7b, 0x92, + 0x35, 0x67, 0x97, 0x62, 0x40, 0x6b, 0x2c, 0x3a, 0x21, 0x4f, 0x2e, 0x3f, 0x5d, 0x3e, 0x1f, 0x43, 0x43, 0x1b, 0x29, 0x14, 0x21, 0x7b, 0x1b, 0x01, 0x0f, 0x50, + 0x30, 0x72, 0x0a, 0x8f, 0x88, 0x5a, 0xa4, 0x80, 0x4a, 0x19, 0x17, 0x7b, 0x11, 0x1a, 0x39, 0x5e, 0x73, 0x3a, 0x4a, 0x51, 0x06, 0x05, 0x97, 0x7a, 0xfe, 0x8b, + 0x10, 0x17, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x02, 0xc1, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x27, 0x40, 0x24, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x68, + 0x02, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x05, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x07, + 0x0d, 0x1b, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x33, 0x13, 0x33, 0x03, 0x23, 0x13, 0x23, 0x03, 0x1a, 0x97, 0x97, 0x3a, 0xe2, 0x3b, 0x96, 0x97, 0x96, 0x40, 0xe2, + 0x41, 0x02, 0xca, 0xfe, 0xe9, 0x01, 0x17, 0xfd, 0x36, 0x01, 0x33, 0xfe, 0xcd, 0x00, 0x00, 0x01, 0xff, 0xe3, 0x00, 0x00, 0x01, 0xb6, 0x02, 0xca, 0x00, 0x0b, + 0x00, 0x22, 0x40, 0x1f, 0x0a, 0x09, 0x04, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, + 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0x23, 0x37, 0x37, 0x13, 0x27, 0x37, 0x21, 0x07, 0x07, 0x03, 0x17, 0x07, 0x1d, 0x12, 0x5b, 0x62, + 0x4a, 0x12, 0x01, 0x3c, 0x12, 0x5d, 0x62, 0x4c, 0x12, 0x56, 0x28, 0x01, 0xce, 0x28, 0x56, 0x56, 0x28, 0xfe, 0x32, 0x28, 0x56, 0x00, 0x00, 0x01, 0xff, 0x62, + 0xff, 0x2d, 0x01, 0x54, 0x02, 0xca, 0x00, 0x0f, 0x00, 0x28, 0x40, 0x25, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, + 0x00, 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, 0x01, 0x00, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x0f, 0x01, 0x0f, 0x04, 0x0d, 0x16, 0x2b, 0x07, 0x22, + 0x26, 0x27, 0x37, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x41, 0x19, 0x32, 0x12, 0x01, 0x11, 0x26, 0x18, 0x2d, 0x3e, 0x0f, 0x91, + 0x97, 0x94, 0x1b, 0x78, 0xd3, 0x07, 0x06, 0x7d, 0x04, 0x07, 0x34, 0x46, 0x02, 0xa4, 0xfd, 0x4a, 0x7e, 0x69, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x02, 0xc1, + 0x02, 0xca, 0x00, 0x0c, 0x00, 0x25, 0x40, 0x22, 0x0a, 0x07, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, + 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x12, 0x13, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x37, 0x37, 0x33, 0x01, 0x13, + 0x23, 0x03, 0x07, 0x07, 0x1a, 0x97, 0x95, 0x4b, 0x4c, 0xca, 0xb0, 0xfe, 0xde, 0x8e, 0xa5, 0x67, 0x3d, 0x35, 0x02, 0xca, 0xfe, 0xa7, 0x66, 0xf3, 0xfe, 0xaa, + 0xfe, 0x8c, 0x01, 0x21, 0x22, 0xff, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x01, 0xc3, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x6a, + 0x4d, 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, + 0x13, 0x33, 0x03, 0x33, 0x07, 0x1a, 0x97, 0x95, 0x7d, 0xfa, 0x1a, 0x02, 0xca, 0xfd, 0xb3, 0x7d, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x03, 0x75, 0x02, 0xca, + 0x00, 0x17, 0x00, 0x27, 0x40, 0x24, 0x11, 0x0d, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, + 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x17, 0x17, 0x11, 0x13, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x01, 0x33, 0x03, 0x23, + 0x13, 0x3e, 0x02, 0x37, 0x23, 0x01, 0x23, 0x03, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x1a, 0x97, 0xc5, 0x20, 0x04, 0x01, 0x0c, 0xcf, 0x97, 0x89, 0x47, 0x07, 0x13, + 0x13, 0x08, 0x04, 0xfe, 0xea, 0x89, 0x1e, 0x04, 0x02, 0x0c, 0x0f, 0x09, 0x46, 0x02, 0xca, 0xfd, 0xea, 0x02, 0x16, 0xfd, 0x36, 0x01, 0x52, 0x22, 0x4d, 0x4b, + 0x1d, 0xfd, 0xd7, 0x02, 0x29, 0x15, 0x49, 0x56, 0x29, 0xfe, 0xb4, 0x00, 0x00, 0x01, 0x00, 0x19, 0x00, 0x00, 0x02, 0xfb, 0x02, 0xca, 0x00, 0x13, 0x00, 0x24, + 0x40, 0x21, 0x0d, 0x03, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x13, 0x11, 0x17, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x03, 0x23, 0x03, 0x23, 0x0e, 0x02, + 0x07, 0x03, 0x19, 0x97, 0xad, 0xab, 0x03, 0x03, 0x0a, 0x0c, 0x06, 0x48, 0x89, 0x97, 0xad, 0xac, 0x04, 0x01, 0x09, 0x0d, 0x08, 0x46, 0x02, 0xca, 0xfd, 0xf5, + 0x17, 0x42, 0x46, 0x1c, 0x01, 0x50, 0xfd, 0x36, 0x02, 0x19, 0x10, 0x47, 0x53, 0x22, 0xfe, 0xb3, 0x00, 0x02, 0x00, 0x3b, 0xff, 0xf6, 0x02, 0xbc, 0x02, 0xd5, + 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x11, 0x10, 0x01, 0x00, 0x19, 0x17, 0x10, 0x1f, 0x11, 0x1f, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, 0x2b, 0x05, + 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, + 0x16, 0x01, 0x4a, 0x86, 0x89, 0x30, 0x5e, 0x8e, 0x5d, 0x80, 0x88, 0x2d, 0x5c, 0x8b, 0x53, 0x2d, 0x4b, 0x36, 0x1e, 0x40, 0x39, 0x30, 0x4d, 0x38, 0x1d, 0x42, + 0x0a, 0x96, 0x7e, 0x57, 0xa4, 0x83, 0x4d, 0x96, 0x7f, 0x57, 0xa4, 0x82, 0x4d, 0x7f, 0x34, 0x5c, 0x77, 0x43, 0x47, 0x50, 0x37, 0x5e, 0x76, 0x40, 0x48, 0x4e, + 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x67, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x30, 0x40, 0x2d, 0x06, 0x01, 0x03, 0x00, 0x01, 0x02, 0x03, 0x01, + 0x67, 0x00, 0x04, 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0e, 0x0d, 0x00, 0x00, 0x13, 0x11, 0x0d, 0x14, + 0x0e, 0x14, 0x00, 0x0c, 0x00, 0x0c, 0x26, 0x21, 0x07, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x23, 0x07, 0x13, + 0x32, 0x36, 0x35, 0x34, 0x23, 0x23, 0x07, 0x1a, 0x97, 0xc7, 0x57, 0x69, 0x2f, 0x52, 0x8c, 0x59, 0x4c, 0x35, 0x8d, 0x43, 0x52, 0x5f, 0x46, 0x2d, 0x02, 0xca, + 0x34, 0x5e, 0x3e, 0x55, 0x70, 0x37, 0xfe, 0x01, 0x7a, 0x42, 0x3a, 0x58, 0xd4, 0x00, 0x00, 0x02, 0x00, 0x3b, 0xff, 0x56, 0x02, 0xbc, 0x02, 0xd5, 0x00, 0x14, + 0x00, 0x23, 0x00, 0x32, 0x40, 0x2f, 0x12, 0x01, 0x00, 0x03, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x02, 0x86, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, + 0x4d, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x16, 0x15, 0x1e, 0x1c, 0x15, 0x23, 0x16, 0x23, 0x17, 0x26, 0x40, 0x06, 0x0d, + 0x19, 0x2b, 0x05, 0x22, 0x22, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x17, 0x23, 0x03, 0x32, 0x3e, 0x02, + 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x01, 0x4e, 0x03, 0x07, 0x03, 0x7f, 0x87, 0x30, 0x5f, 0x8e, 0x5e, 0x7e, 0x88, 0x32, 0x64, 0x4a, + 0x7b, 0xaf, 0x58, 0x30, 0x4d, 0x37, 0x1d, 0x3f, 0x38, 0x3f, 0x60, 0x35, 0x41, 0x0a, 0x96, 0x7e, 0x57, 0xa4, 0x83, 0x4d, 0x96, 0x7f, 0x5a, 0xa8, 0x83, 0x22, + 0xc3, 0x01, 0x21, 0x34, 0x5c, 0x76, 0x43, 0x48, 0x4d, 0x5b, 0x96, 0x5b, 0x46, 0x4c, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x52, 0x02, 0xca, 0x00, 0x0d, + 0x00, 0x16, 0x00, 0x38, 0x40, 0x35, 0x08, 0x01, 0x02, 0x04, 0x01, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, 0x67, 0x00, 0x05, 0x05, 0x00, 0x5f, + 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x0f, 0x0e, 0x00, 0x00, 0x15, 0x13, 0x0e, 0x16, 0x0f, 0x16, 0x00, 0x0d, 0x00, + 0x0d, 0x11, 0x16, 0x21, 0x08, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x03, 0x13, 0x32, 0x36, 0x35, + 0x34, 0x26, 0x23, 0x23, 0x07, 0x1a, 0x97, 0xb0, 0x76, 0x7b, 0x57, 0x43, 0x7d, 0xa5, 0x62, 0x43, 0x3a, 0x81, 0x3e, 0x4a, 0x2d, 0x31, 0x2d, 0x2b, 0x02, 0xca, + 0x5f, 0x5f, 0x5a, 0x6a, 0x17, 0xfe, 0xcf, 0x01, 0x12, 0xfe, 0xee, 0x01, 0x88, 0x3e, 0x3c, 0x27, 0x2a, 0xcb, 0x00, 0x01, 0x00, 0x14, 0xff, 0xf6, 0x02, 0x1e, + 0x02, 0xd4, 0x00, 0x27, 0x00, 0x37, 0x40, 0x34, 0x18, 0x01, 0x03, 0x02, 0x19, 0x04, 0x02, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, + 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1c, 0x1a, 0x16, 0x14, 0x08, + 0x06, 0x00, 0x27, 0x01, 0x27, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x2e, 0x02, 0x35, + 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc2, 0x36, 0x59, 0x1f, + 0x2c, 0x56, 0x2d, 0x32, 0x42, 0x30, 0x26, 0x1e, 0x38, 0x24, 0x3c, 0x6f, 0x4a, 0x38, 0x5e, 0x2c, 0x35, 0x4c, 0x41, 0x28, 0x34, 0x2e, 0x2a, 0x3b, 0x3b, 0x49, + 0x79, 0x0a, 0x18, 0x14, 0x86, 0x19, 0x1c, 0x26, 0x28, 0x29, 0x2f, 0x1c, 0x16, 0x36, 0x49, 0x31, 0x40, 0x61, 0x38, 0x18, 0x18, 0x72, 0x24, 0x2b, 0x25, 0x26, + 0x2d, 0x1c, 0x27, 0x5e, 0x3f, 0x4b, 0x62, 0x30, 0x00, 0x01, 0x00, 0x51, 0x00, 0x00, 0x02, 0x5b, 0x02, 0xca, 0x00, 0x07, 0x00, 0x21, 0x40, 0x1e, 0x02, 0x01, + 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, + 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x23, 0x37, 0x21, 0x07, 0x23, 0x03, 0x81, 0x7b, 0xab, 0x1c, 0x01, 0xee, 0x1c, 0xab, 0x7b, 0x02, 0x4b, 0x7f, 0x7f, 0xfd, 0xb5, + 0x00, 0x01, 0x00, 0x44, 0xff, 0xf6, 0x02, 0xbc, 0x02, 0xca, 0x00, 0x17, 0x00, 0x24, 0x40, 0x21, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, + 0x62, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x13, 0x12, 0x0f, 0x0d, 0x08, 0x07, 0x00, 0x17, 0x01, 0x17, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, + 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x0e, 0x02, 0x01, 0x2b, 0x70, 0x77, 0x04, + 0x04, 0x5f, 0x98, 0x5f, 0x08, 0x2e, 0x2e, 0x3c, 0x41, 0x11, 0x5f, 0x97, 0x62, 0x12, 0x48, 0x79, 0x0a, 0x6f, 0x5c, 0x10, 0x29, 0x15, 0x01, 0xbb, 0xfe, 0x46, + 0x27, 0x1e, 0x28, 0x2d, 0x48, 0x4d, 0x01, 0xbf, 0xfe, 0x33, 0x54, 0x75, 0x3e, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0xa8, 0x02, 0xca, 0x00, 0x0d, + 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, 0x98, 0x3e, 0x90, + 0x19, 0x02, 0x01, 0x02, 0x04, 0x0b, 0x1b, 0x10, 0xd2, 0x9a, 0xfe, 0x93, 0x02, 0xca, 0xfe, 0x52, 0x1f, 0x4e, 0x1d, 0x21, 0x47, 0x22, 0x01, 0xae, 0xfd, 0x36, + 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x03, 0xdc, 0x02, 0xca, 0x00, 0x22, 0x00, 0x27, 0x40, 0x24, 0x1e, 0x11, 0x06, 0x03, 0x03, 0x00, 0x01, 0x4c, 0x02, 0x01, + 0x02, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x22, 0x11, 0x1a, 0x19, 0x11, 0x06, 0x0d, 0x1a, + 0x2b, 0x33, 0x03, 0x33, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x13, 0x16, 0x06, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, + 0x23, 0x03, 0x26, 0x26, 0x34, 0x37, 0x23, 0x06, 0x07, 0x03, 0x70, 0x16, 0x8c, 0x03, 0x03, 0x04, 0x04, 0x0e, 0x22, 0x0d, 0xb4, 0x84, 0x0a, 0x01, 0x01, 0x02, + 0x02, 0x04, 0x0e, 0x23, 0x0e, 0xa1, 0x97, 0xfe, 0xc4, 0xa9, 0x08, 0x01, 0x01, 0x01, 0x04, 0x1a, 0x1d, 0x9e, 0x02, 0xca, 0xfe, 0x7a, 0x25, 0x5d, 0x27, 0x27, + 0x59, 0x1f, 0x01, 0x90, 0xfe, 0x70, 0x11, 0x36, 0x3d, 0x1b, 0x29, 0x5f, 0x22, 0x01, 0x85, 0xfd, 0x36, 0x01, 0x45, 0x2c, 0x39, 0x2e, 0x19, 0x50, 0x42, 0xfe, + 0xa1, 0x00, 0x00, 0x01, 0xff, 0xc7, 0x00, 0x00, 0x02, 0xb0, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, 0x04, 0x02, 0x00, 0x01, + 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x12, 0x12, 0x12, 0x05, 0x0d, + 0x19, 0x2b, 0x23, 0x01, 0x03, 0x33, 0x17, 0x37, 0x33, 0x01, 0x13, 0x23, 0x03, 0x03, 0x39, 0x01, 0x19, 0x74, 0x9f, 0x4a, 0xaf, 0xac, 0xfe, 0xf6, 0x83, 0xa6, + 0x53, 0xbf, 0x01, 0x7b, 0x01, 0x4f, 0xf6, 0xf6, 0xfe, 0xa3, 0xfe, 0x93, 0x01, 0x0d, 0xfe, 0xf3, 0x00, 0x01, 0x00, 0x5b, 0x00, 0x00, 0x02, 0x90, 0x02, 0xca, + 0x00, 0x08, 0x00, 0x22, 0x40, 0x1f, 0x04, 0x01, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x12, 0x12, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x03, 0x33, 0x13, 0x13, 0x33, 0x01, 0x03, 0x94, 0x3a, 0x73, 0x98, 0x3f, + 0xb7, 0xa7, 0xfe, 0xd2, 0x3a, 0x01, 0x11, 0x01, 0xb9, 0xfe, 0xdf, 0x01, 0x21, 0xfe, 0x47, 0xfe, 0xef, 0x00, 0x00, 0x01, 0xff, 0xe2, 0x00, 0x00, 0x02, 0x4a, + 0x02, 0xca, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, + 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x01, 0x21, 0x37, 0x21, 0x07, 0x01, 0x21, + 0x07, 0x1e, 0x13, 0x01, 0x7b, 0xfe, 0xf7, 0x1a, 0x01, 0xc9, 0x14, 0xfe, 0x82, 0x01, 0x23, 0x1a, 0x62, 0x01, 0xeb, 0x7d, 0x63, 0xfe, 0x16, 0x7d, 0x00, 0x01, + 0xff, 0xee, 0xff, 0x62, 0x01, 0x8f, 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x02, 0x04, 0x01, 0x03, 0x02, 0x03, 0x63, 0x00, 0x01, 0x01, 0x00, + 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, 0x23, 0x03, + 0x33, 0x07, 0x12, 0xba, 0xe7, 0x16, 0x69, 0x8e, 0x69, 0x16, 0x9e, 0x03, 0x68, 0x67, 0xfd, 0x66, 0x67, 0x00, 0x00, 0x01, 0x00, 0x6c, 0xff, 0xfa, 0x01, 0x5a, + 0x02, 0xd0, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, + 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x17, 0x03, 0x33, 0x13, 0xdc, 0x70, 0x7b, 0x73, 0x06, 0x02, 0xd6, 0xfd, 0x2a, 0x00, 0x01, 0xff, 0xbd, 0xff, 0x62, 0x01, 0x5d, + 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x00, 0x04, 0x01, 0x03, 0x00, 0x03, 0x63, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, + 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x07, 0x37, 0x33, 0x13, 0x23, 0x37, 0x33, 0x03, 0x43, 0x16, 0x68, 0x8e, + 0x69, 0x16, 0xe7, 0xba, 0x9e, 0x67, 0x02, 0x9a, 0x67, 0xfc, 0x98, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0xfe, 0x02, 0x0e, 0x02, 0xce, 0x00, 0x06, 0x00, 0x27, + 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x03, 0x02, 0x02, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x37, 0x01, 0x33, 0x13, 0x23, 0x03, 0x03, 0x11, 0x01, 0x2e, 0x48, 0x87, 0x6d, + 0x55, 0xc4, 0xfe, 0x01, 0xd0, 0xfe, 0x30, 0x01, 0x35, 0xfe, 0xcb, 0x00, 0x00, 0x01, 0xff, 0xa5, 0xff, 0x62, 0x01, 0x45, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x26, + 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x07, 0x37, 0x21, 0x07, 0x5b, 0x0f, 0x01, 0x91, 0x0f, 0x9e, 0x44, 0x44, 0x00, 0x01, + 0x00, 0x91, 0x02, 0x5e, 0x01, 0x63, 0x02, 0xfe, 0x00, 0x09, 0x00, 0x2d, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x22, 0x08, 0x04, 0x02, 0x01, 0x00, 0x01, 0x4c, 0x00, + 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x15, 0x03, 0x0d, 0x17, + 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x2e, 0x02, 0x27, 0x35, 0x33, 0x16, 0x17, 0x15, 0x01, 0x07, 0x15, 0x2e, 0x28, 0x0b, 0x9a, 0x11, 0x27, 0x02, 0x5e, 0x14, + 0x34, 0x37, 0x17, 0x0a, 0x48, 0x4c, 0x0c, 0x00, 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x42, 0x02, 0x2c, 0x00, 0x15, 0x00, 0x24, 0x00, 0x7e, 0x4b, 0xb0, + 0x19, 0x50, 0x58, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x01, 0x12, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x02, 0x12, 0x01, 0x03, 0x04, + 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x19, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, + 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, + 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, + 0x20, 0x1e, 0x16, 0x24, 0x17, 0x24, 0x11, 0x10, 0x0f, 0x0e, 0x0a, 0x08, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, 0x34, + 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0x37, 0x32, 0x36, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x06, 0x06, 0x15, 0x14, 0xc4, 0x2b, 0x45, 0x28, 0x21, 0x40, 0x5e, 0x3d, 0x32, 0x3e, 0x13, 0x04, 0x1d, 0x76, 0x74, 0x77, 0x08, 0x04, 0x1b, 0x48, 0x07, 0x1b, + 0x32, 0x26, 0x0a, 0x09, 0x21, 0x1d, 0x24, 0x3b, 0x23, 0x0a, 0x29, 0x58, 0x47, 0x3c, 0x80, 0x6e, 0x44, 0x30, 0x23, 0x49, 0xfd, 0xde, 0x4b, 0x24, 0x31, 0x79, + 0x2d, 0x4a, 0x2d, 0x29, 0x22, 0x26, 0x2f, 0x46, 0x6d, 0x3c, 0x55, 0x00, 0x00, 0x02, 0x00, 0x12, 0xff, 0xf6, 0x02, 0x27, 0x02, 0xf8, 0x00, 0x19, 0x00, 0x28, + 0x00, 0x82, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x0d, 0x01, 0x05, 0x03, 0x03, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x0d, 0x01, 0x05, 0x03, + 0x03, 0x01, 0x01, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, + 0x03, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x01, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, + 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, + 0x4e, 0x59, 0x40, 0x17, 0x1b, 0x1a, 0x01, 0x00, 0x22, 0x20, 0x1a, 0x28, 0x1b, 0x28, 0x12, 0x10, 0x08, 0x07, 0x06, 0x05, 0x00, 0x19, 0x01, 0x19, 0x08, 0x0d, + 0x16, 0x2b, 0x05, 0x22, 0x26, 0x27, 0x23, 0x07, 0x23, 0x13, 0x33, 0x07, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x0e, 0x02, + 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x2a, 0x34, 0x41, 0x12, 0x04, 0x1c, 0x71, 0xa1, 0x93, 0x1e, 0x04, 0x0e, + 0x10, 0x07, 0x04, 0x1a, 0x3e, 0x32, 0x28, 0x46, 0x2c, 0x24, 0x42, 0x5d, 0x53, 0x1b, 0x2f, 0x23, 0x14, 0x40, 0x24, 0x32, 0x20, 0x0f, 0x25, 0x0a, 0x2c, 0x24, + 0x46, 0x02, 0xf8, 0x8d, 0x14, 0x35, 0x35, 0x14, 0x21, 0x32, 0x27, 0x57, 0x48, 0x43, 0x82, 0x6b, 0x40, 0x77, 0x2b, 0x46, 0x56, 0x2b, 0x56, 0x34, 0x4f, 0x52, + 0x1d, 0x27, 0x2f, 0x00, 0x00, 0x01, 0x00, 0x2c, 0xff, 0xf6, 0x01, 0xef, 0x02, 0x2c, 0x00, 0x1e, 0x00, 0x37, 0x40, 0x34, 0x0c, 0x01, 0x02, 0x01, 0x1b, 0x0d, + 0x02, 0x03, 0x02, 0x1c, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x19, 0x17, 0x11, 0x0f, 0x0a, 0x08, 0x00, 0x1e, 0x01, 0x1e, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, + 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0xf7, 0x39, + 0x5c, 0x36, 0x28, 0x4c, 0x6b, 0x42, 0x2e, 0x4f, 0x25, 0x2f, 0x17, 0x39, 0x1d, 0x22, 0x36, 0x25, 0x13, 0x2c, 0x27, 0x23, 0x41, 0x22, 0x22, 0x50, 0x0a, 0x2d, + 0x60, 0x4b, 0x49, 0x7f, 0x60, 0x36, 0x11, 0x11, 0x71, 0x0a, 0x11, 0x28, 0x41, 0x4f, 0x26, 0x36, 0x31, 0x16, 0x11, 0x79, 0x12, 0x15, 0x00, 0x02, 0x00, 0x2c, + 0xff, 0xf6, 0x02, 0x6e, 0x02, 0xf8, 0x00, 0x19, 0x00, 0x28, 0x00, 0x82, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x01, 0x16, 0x01, 0x00, + 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x01, 0x16, 0x01, 0x03, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, + 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, + 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x1b, 0x1a, 0x01, 0x00, 0x23, 0x21, 0x1a, 0x28, 0x1b, 0x28, 0x15, 0x14, + 0x13, 0x12, 0x0a, 0x08, 0x00, 0x19, 0x01, 0x19, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x34, + 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0x37, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xc6, 0x27, + 0x47, 0x2c, 0x24, 0x42, 0x5d, 0x3a, 0x31, 0x38, 0x13, 0x04, 0x03, 0x06, 0x04, 0x25, 0x93, 0xa1, 0x70, 0x09, 0x04, 0x1d, 0x4a, 0x09, 0x23, 0x31, 0x1f, 0x0f, + 0x24, 0x20, 0x1b, 0x2f, 0x23, 0x14, 0x0a, 0x27, 0x57, 0x49, 0x42, 0x83, 0x6a, 0x40, 0x2e, 0x22, 0x03, 0x25, 0x31, 0x14, 0xaf, 0xfd, 0x08, 0x47, 0x24, 0x2d, + 0x77, 0x35, 0x4f, 0x51, 0x1d, 0x27, 0x2f, 0x2b, 0x46, 0x56, 0x2b, 0x56, 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x14, 0x02, 0x2c, 0x00, 0x1b, 0x00, 0x25, + 0x00, 0x43, 0x40, 0x40, 0x18, 0x01, 0x03, 0x02, 0x19, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x03, 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1d, 0x1c, 0x01, 0x00, 0x22, 0x20, 0x1c, + 0x25, 0x1d, 0x25, 0x16, 0x14, 0x0f, 0x0d, 0x09, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x08, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x23, 0x23, 0x06, 0x14, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x03, 0x32, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, + 0x06, 0x07, 0x01, 0x04, 0x60, 0x78, 0x27, 0x4d, 0x72, 0x4b, 0x5c, 0x5b, 0x9b, 0x9f, 0x19, 0x01, 0x33, 0x2e, 0x2b, 0x46, 0x30, 0x2b, 0x58, 0x58, 0x55, 0x4b, + 0x33, 0x1b, 0x36, 0x29, 0x09, 0x0a, 0x69, 0x6a, 0x45, 0x7f, 0x64, 0x3b, 0x54, 0x41, 0x56, 0x68, 0x06, 0x09, 0x05, 0x2c, 0x34, 0x14, 0x16, 0x6f, 0x15, 0x15, + 0x01, 0x46, 0x35, 0x23, 0x2e, 0x22, 0x3c, 0x28, 0x00, 0x01, 0xff, 0x96, 0xff, 0x10, 0x01, 0xe5, 0x02, 0xfd, 0x00, 0x23, 0x00, 0xa3, 0x40, 0x12, 0x15, 0x01, + 0x04, 0x03, 0x16, 0x01, 0x05, 0x04, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x21, 0x00, 0x04, 0x04, + 0x03, 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, + 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x21, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, 0x02, 0x02, + 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x04, 0x04, 0x03, + 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, + 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x15, 0x01, 0x00, 0x20, 0x1f, 0x1e, 0x1d, 0x1a, 0x18, 0x13, 0x11, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x23, 0x01, 0x23, 0x08, + 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, + 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x13, 0x18, 0x2f, 0x10, 0x0e, 0x1c, 0x0f, 0x24, 0x26, 0x09, 0x63, 0x55, 0x0f, 0x5f, + 0x0a, 0x15, 0x5f, 0x50, 0x22, 0x41, 0x16, 0x26, 0x0e, 0x22, 0x11, 0x19, 0x21, 0x07, 0x0a, 0x6c, 0x19, 0x6b, 0x69, 0x11, 0x5a, 0xf0, 0x07, 0x05, 0x77, 0x04, + 0x06, 0x29, 0x29, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x61, 0x51, 0x0e, 0x0a, 0x69, 0x06, 0x08, 0x1c, 0x22, 0x2a, 0x70, 0xfe, 0x13, 0x51, 0x64, 0x00, 0x00, 0x02, + 0x00, 0x12, 0xff, 0x10, 0x02, 0x42, 0x02, 0x2c, 0x00, 0x23, 0x00, 0x32, 0x00, 0x9e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x1c, 0x01, 0x06, 0x03, 0x0d, + 0x01, 0x02, 0x05, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x1b, 0x40, 0x12, 0x1c, 0x01, 0x06, 0x04, 0x0d, 0x01, 0x02, 0x05, 0x04, 0x01, + 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x00, 0x06, 0x06, 0x03, 0x61, 0x04, 0x01, 0x03, 0x03, 0x73, + 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, + 0x26, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x06, 0x06, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, + 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, 0x19, 0x25, 0x24, 0x01, 0x00, 0x2d, 0x2b, 0x24, 0x32, 0x25, 0x32, + 0x1f, 0x1e, 0x1a, 0x18, 0x12, 0x10, 0x08, 0x06, 0x00, 0x23, 0x01, 0x23, 0x09, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x37, + 0x37, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x0e, 0x02, 0x11, 0x32, + 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xbd, 0x38, 0x53, 0x20, 0x21, 0x58, 0x2e, 0x67, 0x18, 0x07, 0x03, 0x0a, 0x05, 0x04, 0x1a, + 0x43, 0x32, 0x40, 0x52, 0x20, 0x3f, 0x5e, 0x3f, 0x32, 0x3b, 0x16, 0x04, 0x1d, 0x76, 0x78, 0x12, 0x4c, 0x6d, 0x1b, 0x30, 0x25, 0x16, 0x1d, 0x21, 0x1c, 0x2f, + 0x24, 0x13, 0xf0, 0x13, 0x0d, 0x7e, 0x12, 0x18, 0x63, 0x1c, 0x0f, 0x27, 0x0f, 0x21, 0x2e, 0x5c, 0x68, 0x3c, 0x80, 0x6f, 0x44, 0x2c, 0x27, 0x49, 0xfd, 0xca, + 0x52, 0x60, 0x2a, 0x01, 0x5f, 0x2b, 0x47, 0x54, 0x29, 0x26, 0x2f, 0x29, 0x45, 0x55, 0x2c, 0x55, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x02, 0x29, 0x02, 0xf8, + 0x00, 0x1c, 0x00, 0x2d, 0x40, 0x2a, 0x07, 0x01, 0x03, 0x01, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, + 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1c, 0x24, 0x15, 0x28, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, + 0x07, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x03, 0x23, 0x13, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x12, + 0xa1, 0x93, 0x1c, 0x04, 0x10, 0x10, 0x07, 0x04, 0x1e, 0x4a, 0x31, 0x47, 0x46, 0x0b, 0x41, 0x93, 0x43, 0x08, 0x35, 0x21, 0x36, 0x27, 0x0d, 0x30, 0x02, 0xf8, + 0x84, 0x16, 0x3a, 0x37, 0x14, 0x26, 0x2d, 0x55, 0x48, 0x24, 0x34, 0xfe, 0xc9, 0x01, 0x3f, 0x23, 0x17, 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0x00, 0x02, 0x00, 0x12, + 0x00, 0x00, 0x01, 0x41, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x2d, 0x40, 0x2a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x72, 0x4d, 0x00, + 0x02, 0x02, 0x6d, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x0c, 0x0c, 0x01, 0x00, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, 0x0b, 0x01, + 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x13, 0x33, 0x03, 0xe8, 0x21, 0x2b, 0x30, 0x2b, + 0x20, 0x2a, 0x2f, 0xff, 0x00, 0x73, 0x97, 0x75, 0x02, 0x65, 0x1d, 0x20, 0x28, 0x2f, 0x1c, 0x20, 0x28, 0x30, 0xfd, 0x9b, 0x02, 0x22, 0xfd, 0xde, 0x00, 0x02, + 0xff, 0x80, 0xff, 0x10, 0x01, 0x43, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x1b, 0x00, 0x3e, 0x40, 0x3b, 0x10, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x02, 0x4c, + 0x05, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x72, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x06, 0x01, 0x02, 0x02, 0x6f, + 0x02, 0x4e, 0x0d, 0x0c, 0x01, 0x00, 0x17, 0x16, 0x13, 0x11, 0x0c, 0x1b, 0x0d, 0x1b, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x07, 0x0d, 0x16, 0x2b, 0x13, 0x22, + 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x0e, 0x02, 0xea, + 0x20, 0x2b, 0x2f, 0x2b, 0x20, 0x2a, 0x2f, 0xfe, 0xc2, 0x17, 0x30, 0x0f, 0x1c, 0x1c, 0x1e, 0x2d, 0x09, 0x7c, 0x95, 0x80, 0x0b, 0x2e, 0x50, 0x02, 0x65, 0x1d, + 0x20, 0x28, 0x2f, 0x1c, 0x20, 0x28, 0x30, 0xfc, 0xab, 0x07, 0x05, 0x77, 0x0a, 0x27, 0x2b, 0x02, 0x47, 0xfd, 0xa4, 0x32, 0x53, 0x31, 0x00, 0x01, 0x00, 0x12, + 0x00, 0x00, 0x02, 0x69, 0x02, 0xf8, 0x00, 0x0f, 0x00, 0x29, 0x40, 0x26, 0x0d, 0x0a, 0x06, 0x03, 0x02, 0x01, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, + 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x12, 0x16, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, + 0x13, 0x33, 0x03, 0x06, 0x06, 0x07, 0x33, 0x37, 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x07, 0x12, 0xa1, 0x93, 0x48, 0x05, 0x14, 0x05, 0x04, 0xdd, 0xa8, 0xf3, + 0x8b, 0xa4, 0x59, 0x3b, 0x24, 0x02, 0xf8, 0xfe, 0xad, 0x19, 0x41, 0x11, 0xe8, 0xf6, 0xfe, 0xd4, 0xcd, 0x23, 0xaa, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, + 0x01, 0x48, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x11, 0xa2, 0x95, 0xa1, 0x02, 0xf8, 0xfd, 0x08, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, + 0x03, 0x56, 0x02, 0x2c, 0x00, 0x2a, 0x00, 0x56, 0xb6, 0x0a, 0x03, 0x02, 0x04, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x06, 0x01, 0x04, + 0x04, 0x00, 0x61, 0x02, 0x01, 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x08, 0x07, 0x05, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x1a, 0x00, 0x00, 0x00, 0x6d, + 0x4d, 0x06, 0x01, 0x04, 0x04, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x08, 0x07, 0x05, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x59, 0x40, 0x10, 0x00, + 0x00, 0x00, 0x2a, 0x00, 0x2a, 0x24, 0x14, 0x24, 0x15, 0x25, 0x24, 0x11, 0x09, 0x0d, 0x1d, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x17, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x03, 0x23, 0x13, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x23, 0x13, 0x36, 0x35, + 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x12, 0x74, 0x70, 0x0a, 0x04, 0x20, 0x53, 0x39, 0x38, 0x3e, 0x0a, 0x04, 0x1f, 0x56, 0x39, 0x44, 0x44, 0x0b, 0x41, + 0x93, 0x43, 0x08, 0x30, 0x21, 0x36, 0x28, 0x0c, 0x2f, 0x93, 0x43, 0x08, 0x30, 0x21, 0x36, 0x27, 0x0d, 0x30, 0x02, 0x22, 0x65, 0x31, 0x3e, 0x3b, 0x34, 0x31, + 0x3e, 0x55, 0x48, 0x24, 0x34, 0xfe, 0xc9, 0x01, 0x3f, 0x23, 0x17, 0x3c, 0x38, 0x5f, 0x3b, 0xe3, 0x01, 0x3f, 0x23, 0x17, 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0x00, + 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x02, 0x29, 0x02, 0x2c, 0x00, 0x18, 0x00, 0x4c, 0xb5, 0x03, 0x01, 0x03, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x13, 0x00, 0x03, 0x03, 0x00, 0x61, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x00, + 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x18, 0x24, 0x15, 0x24, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x03, + 0x23, 0x13, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x12, 0x74, 0x70, 0x0a, 0x04, 0x20, 0x53, 0x39, 0x47, 0x46, 0x0b, 0x41, 0x93, 0x43, 0x08, + 0x35, 0x21, 0x36, 0x27, 0x0d, 0x30, 0x02, 0x22, 0x65, 0x31, 0x3e, 0x55, 0x48, 0x24, 0x34, 0xfe, 0xc9, 0x01, 0x3f, 0x23, 0x17, 0x3c, 0x39, 0x60, 0x3a, 0xe2, + 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x1d, 0x02, 0x2c, 0x00, 0x10, 0x00, 0x1e, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, + 0x73, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x12, 0x11, 0x01, 0x00, 0x19, 0x17, 0x11, 0x1e, 0x12, 0x1e, 0x0a, + 0x08, 0x00, 0x10, 0x01, 0x10, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, + 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xfd, 0x3d, 0x5f, 0x35, 0x24, 0x48, 0x6d, 0x49, 0x5f, 0x70, 0x22, 0x47, 0x6d, 0x3e, 0x29, + 0x39, 0x1e, 0x1f, 0x27, 0x21, 0x32, 0x20, 0x10, 0x0a, 0x33, 0x5e, 0x41, 0x48, 0x81, 0x63, 0x38, 0x72, 0x66, 0x45, 0x7e, 0x62, 0x39, 0x78, 0x42, 0x69, 0x3b, + 0x29, 0x37, 0x2d, 0x48, 0x52, 0x25, 0x5a, 0x00, 0x00, 0x02, 0xff, 0xdf, 0xff, 0x10, 0x02, 0x27, 0x02, 0x2c, 0x00, 0x18, 0x00, 0x27, 0x00, 0x6c, 0x40, 0x0a, + 0x03, 0x01, 0x05, 0x00, 0x13, 0x01, 0x02, 0x04, 0x02, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x01, 0x01, 0x00, 0x00, + 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x00, 0x00, + 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, 0x03, + 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x14, 0x1a, 0x19, 0x00, 0x00, 0x21, 0x1f, 0x19, 0x27, 0x1a, 0x27, 0x00, 0x18, 0x00, 0x18, 0x27, 0x24, 0x11, 0x08, 0x0d, + 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x07, + 0x13, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x21, 0xa7, 0x70, 0x08, 0x04, 0x1a, 0x4c, 0x35, 0x28, 0x46, 0x2c, 0x24, 0x42, + 0x5d, 0x3a, 0x32, 0x36, 0x14, 0x04, 0x03, 0x0a, 0x08, 0x23, 0x9f, 0x1b, 0x2f, 0x23, 0x14, 0x40, 0x24, 0x32, 0x20, 0x0f, 0x25, 0xf0, 0x03, 0x12, 0x53, 0x23, + 0x3a, 0x27, 0x57, 0x49, 0x42, 0x83, 0x6a, 0x40, 0x2e, 0x22, 0x28, 0x42, 0x26, 0xa6, 0x01, 0x5d, 0x2b, 0x46, 0x56, 0x2b, 0x56, 0x34, 0x4e, 0x52, 0x1e, 0x27, + 0x2f, 0x00, 0x00, 0x02, 0x00, 0x2c, 0xff, 0x10, 0x02, 0x41, 0x02, 0x2c, 0x00, 0x19, 0x00, 0x29, 0x00, 0x78, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x14, + 0x01, 0x05, 0x01, 0x04, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x14, 0x01, 0x05, 0x02, 0x04, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, + 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, + 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x1b, 0x1a, 0x23, 0x21, 0x1a, 0x29, 0x1b, 0x29, + 0x11, 0x14, 0x27, 0x27, 0x07, 0x0d, 0x1a, 0x2b, 0x05, 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, + 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x03, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x2b, 0x04, 0x0e, 0x11, 0x06, + 0x04, 0x1a, 0x44, 0x33, 0x24, 0x43, 0x2c, 0x24, 0x42, 0x5d, 0x3a, 0x31, 0x3e, 0x18, 0x04, 0x1c, 0x71, 0xa7, 0x93, 0x02, 0x23, 0x31, 0x1e, 0x0f, 0x24, 0x20, + 0x1b, 0x2f, 0x23, 0x14, 0x24, 0x4b, 0x12, 0x35, 0x38, 0x15, 0x22, 0x31, 0x27, 0x57, 0x48, 0x43, 0x82, 0x6b, 0x40, 0x2a, 0x26, 0x46, 0xfc, 0xee, 0x01, 0x5d, + 0x35, 0x4f, 0x51, 0x1d, 0x27, 0x2f, 0x2b, 0x46, 0x56, 0x2b, 0x2b, 0x2b, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x01, 0xcc, 0x02, 0x2c, 0x00, 0x12, 0x00, 0x69, + 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0e, 0x03, 0x01, 0x02, 0x00, 0x0b, 0x01, 0x03, 0x02, 0x02, 0x4c, 0x0a, 0x01, 0x00, 0x4a, 0x1b, 0x40, 0x0e, 0x0a, 0x01, + 0x00, 0x01, 0x03, 0x01, 0x02, 0x00, 0x0b, 0x01, 0x03, 0x02, 0x03, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x02, 0x02, 0x00, 0x61, 0x01, + 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x73, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x59, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x12, 0x25, 0x24, 0x11, 0x05, 0x0d, 0x19, + 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x12, 0x73, 0x79, 0x0a, 0x04, 0x22, + 0x4b, 0x38, 0x0c, 0x1a, 0x09, 0x21, 0x0c, 0x1c, 0x10, 0x39, 0x4e, 0x11, 0x34, 0x02, 0x22, 0x5e, 0x33, 0x35, 0x02, 0x03, 0x91, 0x04, 0x05, 0x5c, 0x4f, 0xf4, + 0x00, 0x01, 0x00, 0x0b, 0xff, 0xf6, 0x01, 0xc7, 0x02, 0x2c, 0x00, 0x26, 0x00, 0x37, 0x40, 0x34, 0x17, 0x01, 0x03, 0x02, 0x18, 0x04, 0x02, 0x01, 0x03, 0x03, + 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, + 0x4e, 0x01, 0x00, 0x1c, 0x1a, 0x15, 0x13, 0x08, 0x06, 0x00, 0x26, 0x01, 0x26, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, + 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, + 0x16, 0x15, 0x14, 0x06, 0xb0, 0x35, 0x51, 0x1f, 0x25, 0x4f, 0x28, 0x22, 0x36, 0x0d, 0x23, 0x22, 0x36, 0x33, 0x6a, 0x67, 0x34, 0x58, 0x26, 0x2f, 0x1b, 0x44, + 0x22, 0x1c, 0x20, 0x21, 0x29, 0x37, 0x3b, 0x7e, 0x0a, 0x11, 0x0f, 0x7c, 0x15, 0x16, 0x19, 0x1c, 0x0f, 0x16, 0x1a, 0x13, 0x1d, 0x47, 0x34, 0x4b, 0x5b, 0x18, + 0x16, 0x66, 0x10, 0x19, 0x1a, 0x17, 0x13, 0x1c, 0x16, 0x1c, 0x48, 0x35, 0x5f, 0x5d, 0x00, 0x01, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xad, 0x02, 0x96, 0x00, 0x1b, + 0x00, 0x66, 0x40, 0x0a, 0x18, 0x01, 0x05, 0x01, 0x19, 0x01, 0x00, 0x05, 0x02, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x03, 0x03, 0x02, + 0x70, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, + 0x1c, 0x00, 0x02, 0x03, 0x02, 0x85, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x59, 0x40, 0x13, 0x01, 0x00, 0x16, 0x14, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x07, 0x06, 0x00, 0x1b, 0x01, 0x1b, 0x07, 0x0d, 0x16, 0x2b, + 0x17, 0x22, 0x26, 0x35, 0x34, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x33, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, + 0x06, 0xc8, 0x40, 0x4e, 0x06, 0x38, 0x4a, 0x0e, 0x60, 0x40, 0x5f, 0x18, 0x8a, 0x18, 0x8a, 0x38, 0x03, 0x18, 0x13, 0x14, 0x25, 0x16, 0x17, 0x42, 0x0a, 0x37, + 0x47, 0x19, 0x1e, 0x01, 0x07, 0x48, 0x29, 0x73, 0x74, 0x70, 0xfe, 0xf9, 0x0f, 0x0b, 0x13, 0x11, 0x09, 0x08, 0x6e, 0x0b, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x36, + 0xff, 0xf6, 0x02, 0x4b, 0x02, 0x22, 0x00, 0x19, 0x00, 0x5e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0xb5, 0x16, 0x01, 0x00, 0x02, 0x01, 0x4c, 0x1b, 0xb5, 0x16, 0x01, + 0x04, 0x02, 0x01, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x03, 0x01, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x05, 0x02, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x17, 0x03, 0x01, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x04, 0x04, 0x6b, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x05, 0x01, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, 0x15, 0x14, 0x13, 0x12, 0x0e, 0x0c, 0x08, 0x07, 0x00, 0x19, 0x01, 0x19, 0x06, 0x0d, 0x16, 0x2b, + 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x15, 0x14, 0x33, 0x32, 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, + 0xc1, 0x46, 0x45, 0x06, 0x06, 0x3e, 0x93, 0x43, 0x08, 0x35, 0x22, 0x35, 0x28, 0x0c, 0x30, 0x93, 0x74, 0x70, 0x0a, 0x05, 0x1f, 0x53, 0x0a, 0x55, 0x48, 0x12, + 0x39, 0x1d, 0x01, 0x27, 0xfe, 0xc1, 0x23, 0x17, 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0xfd, 0xde, 0x65, 0x31, 0x3e, 0x00, 0x01, 0x00, 0x32, 0x00, 0x00, 0x02, 0x3a, + 0x02, 0x22, 0x00, 0x0d, 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, + 0x4e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x16, 0x15, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, + 0x01, 0x75, 0x43, 0x90, 0x16, 0x02, 0x01, 0x05, 0x09, 0x18, 0x0a, 0x91, 0x9e, 0xfe, 0xd9, 0x02, 0x22, 0xfe, 0xe2, 0x13, 0x43, 0x1b, 0x19, 0x41, 0x13, 0x01, + 0x22, 0xfd, 0xde, 0x00, 0x00, 0x01, 0x00, 0x3d, 0x00, 0x00, 0x03, 0x47, 0x02, 0x22, 0x00, 0x25, 0x00, 0x27, 0x40, 0x24, 0x1f, 0x11, 0x06, 0x03, 0x03, 0x00, + 0x01, 0x4c, 0x02, 0x01, 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x25, 0x00, 0x25, 0x11, 0x1a, 0x1a, + 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x03, 0x33, 0x17, 0x14, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x11, 0x14, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, + 0x37, 0x33, 0x01, 0x23, 0x27, 0x34, 0x36, 0x36, 0x37, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x56, 0x19, 0x89, 0x02, 0x01, 0x04, 0x04, 0x07, 0x16, 0x13, 0x04, 0x71, + 0xa0, 0x01, 0x04, 0x05, 0x07, 0x15, 0x16, 0x08, 0x6b, 0x96, 0xfe, 0xfd, 0xa1, 0x03, 0x01, 0x03, 0x01, 0x06, 0x08, 0x15, 0x14, 0x08, 0x72, 0x02, 0x22, 0xf2, + 0x28, 0x4f, 0x2e, 0x19, 0x3d, 0x32, 0x09, 0x01, 0x06, 0xfe, 0xfa, 0x22, 0x46, 0x29, 0x17, 0x3e, 0x3d, 0x13, 0xf2, 0xfd, 0xde, 0xfe, 0x15, 0x3b, 0x3e, 0x18, + 0x18, 0x3b, 0x36, 0x13, 0xfe, 0xf8, 0x00, 0x01, 0xff, 0xce, 0x00, 0x00, 0x02, 0x47, 0x02, 0x22, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, + 0x04, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x12, + 0x12, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x32, 0xe8, 0x6b, 0xa0, 0x37, 0x75, 0xb0, 0xe1, + 0x73, 0xa2, 0x3b, 0x7f, 0x01, 0x18, 0x01, 0x0a, 0xaa, 0xaa, 0xfe, 0xee, 0xfe, 0xf0, 0xb3, 0xb3, 0x00, 0x01, 0xff, 0xbb, 0xff, 0x10, 0x02, 0x3b, 0x02, 0x22, + 0x00, 0x1a, 0x00, 0x30, 0x40, 0x2d, 0x11, 0x0b, 0x04, 0x03, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x01, + 0x01, 0x00, 0x62, 0x04, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x01, 0x00, 0x17, 0x16, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x1a, 0x01, 0x1a, 0x05, 0x0d, 0x16, 0x2b, + 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x03, 0x33, 0x17, 0x16, 0x16, 0x15, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, 0x06, + 0x06, 0x03, 0x1a, 0x22, 0x0c, 0x0d, 0x1b, 0x11, 0x2f, 0x3c, 0x16, 0x0d, 0x50, 0x90, 0x1b, 0x04, 0x02, 0x04, 0x0a, 0x18, 0x13, 0x7f, 0xa0, 0xfe, 0xb4, 0x2c, + 0x77, 0xf0, 0x05, 0x04, 0x75, 0x02, 0x04, 0x36, 0x2a, 0x18, 0x02, 0x22, 0xfd, 0x22, 0x50, 0x1d, 0x19, 0x43, 0x29, 0x01, 0x07, 0xfd, 0x90, 0x53, 0x4f, 0x00, + 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x01, 0xdf, 0x02, 0x22, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6d, 0x4d, + 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, + 0x37, 0x01, 0x23, 0x37, 0x21, 0x07, 0x01, 0x33, 0x07, 0x12, 0x11, 0x01, 0x18, 0xc2, 0x1a, 0x01, 0x70, 0x15, 0xfe, 0xed, 0xd5, 0x18, 0x59, 0x01, 0x57, 0x72, + 0x63, 0xfe, 0xb4, 0x73, 0x00, 0x01, 0xff, 0xff, 0xff, 0x62, 0x01, 0xa3, 0x02, 0xca, 0x00, 0x2c, 0x00, 0x37, 0x40, 0x34, 0x1d, 0x01, 0x01, 0x02, 0x01, 0x4c, + 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, 0x05, 0x06, 0x01, 0x00, 0x05, 0x00, 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, + 0x4e, 0x01, 0x00, 0x2b, 0x2a, 0x17, 0x16, 0x15, 0x13, 0x0e, 0x0d, 0x0c, 0x0b, 0x00, 0x2c, 0x01, 0x2c, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, + 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x37, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, 0x33, 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x15, + 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x15, 0xde, 0x56, 0x4d, 0x08, 0x14, 0x02, 0x03, 0x2a, 0x33, 0x17, 0x3b, 0x3c, + 0x0a, 0x1d, 0x11, 0x53, 0x5d, 0x2e, 0x18, 0x27, 0x2e, 0x09, 0x1d, 0x0c, 0x43, 0x36, 0x2a, 0x26, 0x04, 0x02, 0x13, 0x02, 0x03, 0x21, 0x1e, 0x9e, 0x41, 0x3c, + 0x1d, 0x24, 0x5c, 0x0a, 0x11, 0x07, 0x22, 0x22, 0x72, 0x28, 0x30, 0x86, 0x4c, 0x4c, 0x70, 0x1b, 0x29, 0x8a, 0x36, 0x37, 0x07, 0x03, 0x0d, 0x38, 0x29, 0x0b, + 0x18, 0x0b, 0x59, 0x0a, 0x10, 0x07, 0x19, 0x14, 0x70, 0x00, 0x00, 0x01, 0x00, 0xde, 0xff, 0x1d, 0x01, 0x49, 0x02, 0xf5, 0x00, 0x03, 0x00, 0x30, 0x4b, 0xb0, + 0x27, 0x50, 0x58, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x1b, 0x40, 0x0c, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, + 0x00, 0x00, 0x00, 0x6c, 0x01, 0x4e, 0x59, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x17, 0x11, 0x33, 0x11, 0xde, 0x6b, + 0xe3, 0x03, 0xd8, 0xfc, 0x28, 0x00, 0x00, 0x01, 0xff, 0xcd, 0xff, 0x62, 0x01, 0x65, 0x02, 0xca, 0x00, 0x2a, 0x00, 0x31, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x03, + 0x01, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6a, + 0x01, 0x4e, 0x2a, 0x28, 0x23, 0x22, 0x21, 0x20, 0x17, 0x15, 0x14, 0x13, 0x10, 0x06, 0x0d, 0x17, 0x2b, 0x07, 0x36, 0x36, 0x37, 0x37, 0x36, 0x36, 0x37, 0x35, + 0x26, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x23, 0x37, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x07, 0x06, 0x06, 0x15, 0x14, 0x33, 0x07, + 0x22, 0x06, 0x07, 0x07, 0x06, 0x06, 0x23, 0x23, 0x33, 0x33, 0x2a, 0x09, 0x1d, 0x0c, 0x43, 0x36, 0x2a, 0x26, 0x04, 0x03, 0x13, 0x02, 0x03, 0x4a, 0x15, 0x15, + 0x56, 0x4c, 0x09, 0x14, 0x02, 0x03, 0x61, 0x17, 0x3b, 0x40, 0x0a, 0x1d, 0x11, 0x58, 0x5d, 0x19, 0x2e, 0x01, 0x1b, 0x29, 0x89, 0x36, 0x36, 0x07, 0x04, 0x0d, + 0x37, 0x2a, 0x0a, 0x19, 0x0b, 0x59, 0x0a, 0x10, 0x07, 0x2d, 0x70, 0x45, 0x38, 0x1d, 0x24, 0x5d, 0x0a, 0x10, 0x07, 0x44, 0x72, 0x28, 0x30, 0x86, 0x4e, 0x4a, + 0x00, 0x01, 0x00, 0x35, 0x01, 0x0d, 0x02, 0x1a, 0x01, 0xb4, 0x00, 0x17, 0x00, 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, 0x02, 0x01, 0x13, 0x01, + 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, 0x00, 0x02, 0x00, 0x03, 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, + 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, 0x03, 0x51, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, + 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x01, 0x16, 0x25, 0x33, 0x17, 0x1c, + 0x3d, 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x2f, 0x25, 0x34, 0x16, 0x1d, 0x3c, 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x01, 0x2d, 0x10, 0x0b, 0x22, 0x19, 0x71, 0x35, 0x0b, + 0x14, 0x10, 0x0b, 0x22, 0x19, 0x71, 0x35, 0x0c, 0x00, 0x01, 0x00, 0x38, 0x01, 0x9f, 0x01, 0xa7, 0x03, 0x55, 0x00, 0x18, 0x00, 0x32, 0x40, 0x2f, 0x0b, 0x01, + 0x00, 0x01, 0x0a, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x69, 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, + 0x5f, 0x04, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x17, 0x24, 0x27, 0x05, 0x0c, 0x19, 0x2b, 0x13, 0x37, 0x37, 0x36, 0x36, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x33, 0x07, 0x38, 0x11, 0x85, 0x30, 0x32, 0x19, 0x11, + 0x2a, 0x32, 0x31, 0x24, 0x51, 0x35, 0x3d, 0x47, 0x1f, 0x3d, 0x2d, 0x3f, 0xa9, 0x14, 0x01, 0x9f, 0x51, 0x6b, 0x27, 0x31, 0x1c, 0x14, 0x14, 0x28, 0x4d, 0x1c, + 0x1d, 0x3e, 0x2f, 0x29, 0x3b, 0x34, 0x21, 0x2e, 0x62, 0x00, 0x00, 0x01, 0x00, 0x48, 0x01, 0x97, 0x01, 0xa8, 0x03, 0x54, 0x00, 0x2b, 0x00, 0x4d, 0x40, 0x4a, + 0x1a, 0x01, 0x04, 0x05, 0x19, 0x01, 0x03, 0x04, 0x24, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x05, 0x00, 0x04, + 0x03, 0x05, 0x04, 0x69, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, + 0x01, 0x00, 0x51, 0x01, 0x00, 0x1e, 0x1c, 0x17, 0x15, 0x11, 0x0f, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x2b, 0x01, 0x2b, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, + 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xca, 0x25, 0x45, 0x18, 0x1d, 0x3d, 0x22, 0x23, 0x32, 0x19, 0x1f, + 0x3e, 0x11, 0x2c, 0x29, 0x2f, 0x19, 0x16, 0x16, 0x2f, 0x17, 0x28, 0x23, 0x4a, 0x2c, 0x33, 0x3c, 0x1b, 0x3e, 0x2c, 0x29, 0x22, 0x37, 0x58, 0x01, 0x97, 0x0f, + 0x0c, 0x5e, 0x10, 0x13, 0x1d, 0x1d, 0x12, 0x19, 0x4e, 0x1b, 0x1c, 0x14, 0x13, 0x11, 0x0f, 0x49, 0x17, 0x16, 0x1d, 0x2f, 0x1b, 0x33, 0x33, 0x0b, 0x04, 0x09, + 0x2c, 0x20, 0x31, 0x3e, 0x1d, 0x00, 0x00, 0x01, 0x00, 0x5b, 0x01, 0x9f, 0x01, 0x83, 0x03, 0x4b, 0x00, 0x0c, 0x00, 0x20, 0x40, 0x1d, 0x08, 0x07, 0x03, 0x03, + 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x00, 0x01, 0x4f, 0x11, 0x19, 0x02, 0x0c, 0x18, 0x2b, + 0x13, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, 0x03, 0x23, 0xd9, 0x07, 0x0f, 0x05, 0x09, 0x17, 0x07, 0x40, 0x32, 0xc3, 0x65, 0x5b, 0x78, + 0x02, 0x61, 0x1f, 0x35, 0x11, 0x07, 0x11, 0x05, 0x28, 0x51, 0x79, 0xfe, 0x54, 0x00, 0x00, 0x01, 0xfe, 0xfb, 0x00, 0x00, 0x01, 0x83, 0x02, 0xca, 0x00, 0x03, + 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, + 0x2b, 0x21, 0x01, 0x33, 0x01, 0xfe, 0xfb, 0x02, 0x13, 0x75, 0xfd, 0xef, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x02, 0x00, 0x32, 0x01, 0x9f, 0x01, 0xa8, 0x03, 0x4e, + 0x00, 0x0a, 0x00, 0x13, 0x00, 0x61, 0xb5, 0x10, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x11, 0x50, 0x58, 0x40, 0x1f, 0x00, 0x01, 0x02, 0x01, 0x85, 0x06, + 0x01, 0x04, 0x00, 0x00, 0x04, 0x71, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, 0x02, 0x02, 0x00, 0x60, 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, 0x1b, + 0x40, 0x1e, 0x00, 0x01, 0x02, 0x01, 0x85, 0x06, 0x01, 0x04, 0x00, 0x04, 0x86, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, 0x02, 0x02, 0x00, 0x60, + 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, 0x59, 0x40, 0x0f, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0c, 0x1a, 0x2b, 0x13, + 0x37, 0x23, 0x37, 0x13, 0x33, 0x03, 0x33, 0x07, 0x23, 0x07, 0x27, 0x33, 0x37, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0xd8, 0x10, 0xb6, 0x0f, 0xe8, 0x7f, 0x3b, + 0x3a, 0x11, 0x3a, 0x10, 0xa8, 0x55, 0x14, 0x05, 0x07, 0x07, 0x09, 0x19, 0x08, 0x01, 0x9f, 0x4a, 0x55, 0x01, 0x10, 0xfe, 0xed, 0x52, 0x4a, 0x9c, 0x50, 0x14, + 0x19, 0x18, 0x0d, 0x1f, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x49, 0x01, 0x97, 0x01, 0xac, 0x03, 0x4b, 0x00, 0x1e, 0x00, 0x47, 0x40, 0x44, 0x15, 0x10, 0x02, 0x02, + 0x05, 0x0f, 0x04, 0x02, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, + 0x02, 0x69, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x01, 0x00, 0x51, 0x01, 0x00, 0x19, 0x17, 0x14, 0x13, 0x12, + 0x11, 0x0d, 0x0b, 0x08, 0x06, 0x00, 0x1e, 0x01, 0x1e, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, + 0x22, 0x06, 0x07, 0x27, 0x37, 0x21, 0x07, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc5, 0x22, 0x43, 0x17, 0x19, 0x3c, 0x1c, 0x32, + 0x2a, 0x40, 0x10, 0x23, 0x0e, 0x25, 0x3a, 0x01, 0x02, 0x14, 0xad, 0x15, 0x08, 0x19, 0x13, 0x38, 0x45, 0x33, 0x58, 0x01, 0x97, 0x0d, 0x0d, 0x59, 0x0f, 0x11, + 0x2b, 0x1d, 0x36, 0x06, 0x04, 0x21, 0xcc, 0x5a, 0x44, 0x02, 0x04, 0x40, 0x35, 0x35, 0x4b, 0x27, 0x00, 0x01, 0x00, 0x62, 0x01, 0x9f, 0x01, 0xd2, 0x03, 0x4b, + 0x00, 0x06, 0x00, 0x24, 0x40, 0x21, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, + 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, 0x23, 0x37, 0x21, 0x07, 0x03, 0x62, 0xe2, 0xc6, 0x13, 0x01, + 0x41, 0x0f, 0xe3, 0x01, 0x9f, 0x01, 0x52, 0x5a, 0x49, 0xfe, 0x9d, 0x00, 0x00, 0x03, 0x00, 0x4c, 0x01, 0x95, 0x01, 0xae, 0x03, 0x55, 0x00, 0x18, 0x00, 0x24, + 0x00, 0x30, 0x00, 0x39, 0x40, 0x36, 0x2b, 0x13, 0x06, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x05, 0x01, 0x03, 0x00, + 0x00, 0x03, 0x59, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x03, 0x00, 0x51, 0x26, 0x25, 0x01, 0x00, 0x25, 0x30, 0x26, 0x30, 0x20, 0x1e, 0x0e, + 0x0c, 0x00, 0x18, 0x01, 0x18, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x07, 0x32, 0x36, 0x35, 0x34, 0x26, + 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, 0xe4, 0x49, 0x4f, 0x3b, 0x35, 0x19, 0x1c, 0x2b, 0x46, 0x28, 0x48, 0x46, 0x30, 0x2c, 0x20, 0x26, 0x66, 0x1d, 0x14, 0x1a, + 0x10, 0x14, 0x11, 0x18, 0x12, 0x1c, 0x1a, 0x1d, 0x15, 0x13, 0x16, 0x28, 0x1a, 0x01, 0x95, 0x42, 0x30, 0x2e, 0x3b, 0x12, 0x11, 0x2b, 0x1e, 0x27, 0x36, 0x1c, + 0x3a, 0x2c, 0x2b, 0x33, 0x10, 0x11, 0x30, 0x24, 0x43, 0x44, 0x01, 0x17, 0x09, 0x1a, 0x16, 0x0d, 0x16, 0x18, 0x14, 0x10, 0x18, 0xd2, 0x1f, 0x15, 0x15, 0x1c, + 0x0b, 0x07, 0x21, 0x1b, 0x14, 0x19, 0x00, 0x02, 0x00, 0x5d, 0x01, 0x95, 0x01, 0xb6, 0x03, 0x55, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, + 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x10, + 0x0f, 0x01, 0x00, 0x17, 0x15, 0x0f, 0x1c, 0x10, 0x1c, 0x09, 0x07, 0x00, 0x0e, 0x01, 0x0e, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xe7, 0x40, 0x4a, 0x13, 0x2f, 0x4f, 0x3c, + 0x43, 0x49, 0x30, 0x5c, 0x3a, 0x12, 0x1d, 0x14, 0x0b, 0x1c, 0x10, 0x1d, 0x14, 0x0c, 0x01, 0x95, 0x4d, 0x46, 0x30, 0x68, 0x5c, 0x39, 0x4d, 0x4a, 0x52, 0x87, + 0x50, 0x65, 0x27, 0x3c, 0x45, 0x1e, 0x2f, 0x24, 0x3c, 0x45, 0x21, 0x2f, 0x00, 0x02, 0x00, 0x5b, 0x01, 0x97, 0x01, 0xb7, 0x03, 0x54, 0x00, 0x1d, 0x00, 0x2a, + 0x00, 0x4b, 0x40, 0x48, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, 0x03, 0x02, 0x13, 0x01, 0x05, 0x03, 0x03, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, + 0x00, 0x03, 0x00, 0x05, 0x04, 0x03, 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x00, 0x04, 0x59, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x04, 0x00, + 0x51, 0x1f, 0x1e, 0x01, 0x00, 0x25, 0x23, 0x1e, 0x2a, 0x1f, 0x2a, 0x18, 0x16, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1d, 0x01, 0x1d, 0x08, 0x0c, 0x16, 0x2b, 0x13, + 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, + 0x06, 0x06, 0x27, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0xf0, 0x43, 0x52, 0x16, 0x39, 0x66, 0x4f, 0x14, 0x39, 0x0b, 0x15, + 0x0a, 0x29, 0x1c, 0x2d, 0x36, 0x1b, 0x07, 0x04, 0x0e, 0x30, 0x21, 0x37, 0x37, 0x2b, 0x4e, 0x34, 0x20, 0x22, 0x19, 0x14, 0x19, 0x1c, 0x0c, 0x16, 0x01, 0x97, + 0x57, 0x55, 0x26, 0x5e, 0x56, 0x37, 0x06, 0x04, 0x5c, 0x05, 0x09, 0x23, 0x34, 0x1a, 0x11, 0x1a, 0x40, 0x32, 0x31, 0x4f, 0x2d, 0x55, 0x2f, 0x1f, 0x17, 0x1b, + 0x1b, 0x23, 0x0d, 0x17, 0x1e, 0x00, 0x00, 0x02, 0x00, 0x5b, 0x01, 0x97, 0x01, 0xb1, 0x03, 0x54, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x4a, 0x40, 0x47, 0x12, 0x01, + 0x03, 0x04, 0x0b, 0x01, 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x03, + 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1e, 0x1d, 0x01, 0x00, 0x24, 0x22, + 0x1d, 0x28, 0x1e, 0x28, 0x17, 0x15, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x08, 0x0c, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, + 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x01, 0x1c, 0x4b, 0x4a, 0x40, 0x79, 0x56, 0x13, 0x29, 0x0b, 0x0d, 0x2d, 0x10, 0x31, 0x3c, 0x23, 0x09, 0x03, 0x10, + 0x2f, 0x21, 0x37, 0x37, 0x2b, 0x4f, 0x1f, 0x1f, 0x22, 0x16, 0x17, 0x1e, 0x23, 0x19, 0x03, 0x54, 0x52, 0x46, 0x58, 0x84, 0x49, 0x05, 0x04, 0x5b, 0x05, 0x07, + 0x1e, 0x33, 0x1d, 0x10, 0x18, 0x41, 0x31, 0x32, 0x4e, 0x2d, 0xd3, 0x2b, 0x1f, 0x17, 0x1e, 0x2d, 0x20, 0x17, 0x1b, 0x00, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, + 0x01, 0xe5, 0x02, 0xfd, 0x00, 0x17, 0x00, 0x35, 0x40, 0x32, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, 0x03, 0x02, 0x02, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, + 0x02, 0x69, 0x04, 0x01, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x28, 0x4d, 0x06, 0x01, 0x05, 0x05, 0x27, 0x05, 0x4e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x17, + 0x11, 0x13, 0x25, 0x25, 0x11, 0x07, 0x07, 0x1b, 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, + 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x2a, 0x5b, 0x55, 0x0f, 0x5f, 0x0a, 0x15, 0x5f, 0x50, 0x22, 0x41, 0x16, 0x26, 0x0e, 0x22, 0x11, 0x19, 0x21, 0x07, 0x0a, + 0x6c, 0x19, 0x6b, 0x5c, 0x01, 0xb2, 0x47, 0x29, 0x29, 0x61, 0x51, 0x0e, 0x0a, 0x69, 0x06, 0x08, 0x1c, 0x22, 0x2a, 0x70, 0xfe, 0x4e, 0x00, 0x01, 0xff, 0x95, + 0xff, 0x10, 0x03, 0x36, 0x02, 0xfd, 0x00, 0x41, 0x00, 0xc5, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x03, 0x24, 0x14, 0x02, 0x05, 0x04, 0x36, 0x03, 0x02, 0x01, + 0x02, 0x35, 0x02, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x27, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, + 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, + 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x27, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, + 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x27, + 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, + 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x21, 0x01, 0x00, 0x3d, 0x3c, 0x39, 0x37, 0x34, 0x32, 0x2e, + 0x2d, 0x2c, 0x2b, 0x28, 0x26, 0x21, 0x1f, 0x1c, 0x1b, 0x18, 0x16, 0x11, 0x0f, 0x0a, 0x09, 0x06, 0x04, 0x00, 0x41, 0x01, 0x41, 0x0e, 0x0d, 0x16, 0x2b, 0x07, + 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, + 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x35, + 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x0e, 0x02, 0x16, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, + 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, + 0x06, 0x6b, 0x18, 0x6b, 0x69, 0x0a, 0x2e, 0x4f, 0x3e, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0xc1, 0x69, 0x0a, 0x2e, 0x4f, 0xf0, 0x0c, 0x76, 0x0a, + 0x28, 0x2b, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, + 0x20, 0x1e, 0x70, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x00, 0x03, 0xff, 0x95, 0xff, 0x10, + 0x03, 0xfe, 0x02, 0xfd, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x51, 0x01, 0x75, 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x03, 0x24, 0x14, + 0x02, 0x0d, 0x04, 0x36, 0x03, 0x02, 0x01, 0x10, 0x35, 0x02, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x1b, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x0e, 0x24, 0x14, 0x02, + 0x0d, 0x04, 0x36, 0x03, 0x02, 0x01, 0x10, 0x35, 0x02, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x3c, 0x07, 0x01, 0x04, 0x04, + 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x12, 0x01, 0x0d, 0x0d, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, + 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, + 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x3c, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x12, + 0x01, 0x0d, 0x0d, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, + 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2e, 0x50, 0x58, + 0x40, 0x3c, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x12, 0x01, 0x0d, 0x0d, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, + 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, + 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x39, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, 0x4d, 0x12, + 0x01, 0x0d, 0x0d, 0x0e, 0x61, 0x00, 0x0e, 0x0e, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, + 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x31, 0x4e, 0x4e, 0x43, + 0x42, 0x01, 0x00, 0x4e, 0x51, 0x4e, 0x51, 0x50, 0x4f, 0x49, 0x47, 0x42, 0x4d, 0x43, 0x4d, 0x3d, 0x3c, 0x39, 0x37, 0x34, 0x32, 0x2e, 0x2d, 0x2c, 0x2b, 0x28, + 0x26, 0x21, 0x1f, 0x1c, 0x1b, 0x18, 0x16, 0x11, 0x0f, 0x0a, 0x09, 0x06, 0x04, 0x00, 0x41, 0x01, 0x41, 0x14, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x27, 0x35, 0x16, + 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x13, 0x23, 0x03, 0x0e, 0x02, 0x01, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x13, 0x33, 0x03, 0x16, 0x33, 0x22, 0x1e, + 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, + 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0x6b, 0x18, 0x6b, 0x69, 0x0a, 0x2e, 0x4f, 0x3e, 0x33, 0x22, 0x1e, 0x1a, 0x1e, + 0x2d, 0x09, 0x64, 0xc1, 0x69, 0x0a, 0x2e, 0x4f, 0x03, 0x7e, 0x1f, 0x2b, 0x2f, 0x2a, 0x1d, 0x2c, 0x2b, 0xfe, 0xfe, 0x74, 0x93, 0x74, 0xf0, 0x0c, 0x76, 0x0a, + 0x28, 0x2b, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, + 0x20, 0x1e, 0x70, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x03, 0x56, 0x1b, 0x21, 0x2a, 0x2c, + 0x1a, 0x21, 0x27, 0x30, 0xfd, 0x9a, 0x02, 0x22, 0xfd, 0xde, 0x00, 0x02, 0xff, 0x95, 0xff, 0x10, 0x04, 0x05, 0x02, 0xfd, 0x00, 0x41, 0x00, 0x45, 0x01, 0x3c, + 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x03, 0x24, 0x14, 0x02, 0x05, 0x04, 0x36, 0x03, 0x02, 0x01, 0x0e, 0x35, 0x02, 0x02, 0x00, + 0x01, 0x04, 0x4c, 0x1b, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x0d, 0x24, 0x14, 0x02, 0x05, 0x04, 0x36, 0x03, 0x02, 0x01, 0x0e, 0x35, 0x02, 0x02, 0x00, 0x01, + 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, + 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, + 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x0c, + 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, + 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, 0x03, 0x03, 0x72, + 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, + 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x32, 0x00, 0x0d, 0x0d, 0x6c, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, + 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, + 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x29, 0x42, 0x42, 0x01, 0x00, 0x42, 0x45, 0x42, 0x45, 0x44, 0x43, 0x3d, 0x3c, + 0x39, 0x37, 0x34, 0x32, 0x2e, 0x2d, 0x2c, 0x2b, 0x28, 0x26, 0x21, 0x1f, 0x1c, 0x1b, 0x18, 0x16, 0x11, 0x0f, 0x0a, 0x09, 0x06, 0x04, 0x00, 0x41, 0x01, 0x41, + 0x11, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, + 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x0e, + 0x02, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x0e, 0x02, 0x25, 0x13, 0x33, 0x03, 0x16, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, + 0x09, 0x64, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, 0x63, 0x50, 0x22, + 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0x6b, 0x18, 0x6b, 0x69, 0x0a, 0x2e, 0x4f, 0x3e, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, + 0xc1, 0x69, 0x0a, 0x2e, 0x4f, 0x02, 0xa9, 0xa1, 0x93, 0xa1, 0xf0, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, + 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x70, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x0c, 0x76, 0x0a, 0x28, + 0x2b, 0x01, 0xd7, 0xfe, 0x13, 0x32, 0x52, 0x31, 0xf0, 0x02, 0xf8, 0xfd, 0x08, 0x00, 0xff, 0xff, 0xff, 0x96, 0xff, 0x10, 0x02, 0xb6, 0x02, 0xfd, 0x00, 0x26, + 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0xff, 0x96, 0xff, 0x10, 0x02, 0xbd, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x03, 0x36, 0x02, 0xfd, 0x00, 0x2b, 0x00, 0x42, 0x40, 0x3f, + 0x1b, 0x0b, 0x02, 0x02, 0x01, 0x1c, 0x0c, 0x02, 0x03, 0x02, 0x02, 0x4c, 0x04, 0x01, 0x01, 0x05, 0x01, 0x02, 0x03, 0x01, 0x02, 0x69, 0x09, 0x07, 0x02, 0x00, + 0x00, 0x03, 0x5f, 0x06, 0x01, 0x03, 0x03, 0x28, 0x4d, 0x0b, 0x0a, 0x02, 0x08, 0x08, 0x27, 0x08, 0x4e, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2b, 0x2a, 0x29, 0x11, + 0x11, 0x13, 0x25, 0x23, 0x13, 0x25, 0x25, 0x11, 0x0c, 0x07, 0x1f, 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, + 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x23, + 0x13, 0x23, 0x03, 0x29, 0x5c, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, + 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0x6b, 0x18, 0x6b, 0x5c, 0x93, 0x5c, 0xc1, 0x5c, 0x01, 0xb2, 0x47, 0x29, 0x29, + 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x70, 0xfe, 0x4e, 0x01, 0xb2, + 0xfe, 0x4e, 0xff, 0xff, 0x00, 0x29, 0x00, 0x00, 0x04, 0x0a, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x02, 0xc9, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x29, 0x00, 0x00, 0x04, 0x11, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x02, 0xc9, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x2a, 0x00, 0x00, 0x02, 0xb6, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2a, + 0x00, 0x00, 0x02, 0xbd, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0xff, 0xf5, + 0x01, 0x5c, 0x01, 0xb5, 0x01, 0x07, 0x00, 0x68, 0xff, 0xa6, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x0e, 0xff, 0xff, 0x01, 0x36, 0x01, 0xab, 0x01, 0x07, 0x00, 0x62, 0xff, 0xb3, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0xff, 0xe2, 0xff, 0xff, 0x01, 0x51, 0x01, 0xb5, 0x01, 0x07, 0x00, 0x60, 0xff, 0xaa, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, + 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xf7, 0x01, 0x58, 0x01, 0xb4, 0x01, 0x07, 0x00, 0x61, 0xff, 0xb0, 0xfe, 0x60, 0x00, 0x09, + 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xff, 0x01, 0x57, 0x01, 0xae, 0x01, 0x07, 0x00, 0x64, 0xff, 0xaf, + 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xf7, 0x01, 0x5e, 0x01, 0xab, 0x01, 0x07, + 0x00, 0x65, 0xff, 0xb2, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x04, 0xff, 0xf7, 0x01, 0x60, + 0x01, 0xb4, 0x01, 0x07, 0x00, 0x69, 0xff, 0xa9, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0b, + 0xff, 0xff, 0x01, 0x7b, 0x01, 0xab, 0x01, 0x07, 0x00, 0x66, 0xff, 0xa9, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0xff, 0xf6, 0xff, 0xf5, 0x01, 0x58, 0x01, 0xb5, 0x01, 0x07, 0x00, 0x67, 0xff, 0xaa, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x60, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x03, 0xff, 0xf7, 0x01, 0x59, 0x01, 0xb4, 0x01, 0x07, 0x00, 0x6a, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, + 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x3f, 0x01, 0x13, 0x01, 0x98, 0x02, 0xd3, 0x01, 0x07, 0x00, 0x68, 0xff, 0xe2, 0xff, 0x7e, + 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x47, 0x01, 0x1d, 0x01, 0x6f, 0x02, 0xc9, 0x01, 0x07, 0x00, 0x62, + 0xff, 0xec, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1b, 0x01, 0x1d, 0x01, 0x8a, 0x02, 0xd3, + 0x01, 0x07, 0x00, 0x60, 0xff, 0xe3, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x2f, 0x01, 0x15, + 0x01, 0x8f, 0x02, 0xd2, 0x01, 0x07, 0x00, 0x61, 0xff, 0xe7, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x1c, 0x01, 0x1d, 0x01, 0x92, 0x02, 0xcc, 0x01, 0x07, 0x00, 0x64, 0xff, 0xea, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0x00, 0x37, 0x01, 0x15, 0x01, 0x9a, 0x02, 0xc9, 0x01, 0x07, 0x00, 0x65, 0xff, 0xee, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, + 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x44, 0x01, 0x15, 0x01, 0xa0, 0x02, 0xd2, 0x01, 0x07, 0x00, 0x69, 0xff, 0xe9, 0xff, 0x7e, 0x00, 0x09, + 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x01, 0x1d, 0x01, 0xbd, 0x02, 0xc9, 0x01, 0x07, 0x00, 0x66, 0xff, 0xeb, + 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x33, 0x01, 0x13, 0x01, 0x95, 0x02, 0xd3, 0x01, 0x07, + 0x00, 0x67, 0xff, 0xe7, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x41, 0x01, 0x15, 0x01, 0x97, + 0x02, 0xd2, 0x01, 0x07, 0x00, 0x6a, 0xff, 0xe6, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x8a, 0x00, 0xd3, 0x00, 0x18, 0x00, 0x66, 0x00, 0x06, 0x00, 0x02, 0x00, 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x89, 0x0e, 0x0c, + 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x5b, 0x00, 0xaf, 0x01, 0x36, 0x01, 0xfc, 0x02, 0x9b, 0x02, 0xb6, 0x02, 0xde, + 0x03, 0x10, 0x03, 0x3d, 0x03, 0x65, 0x03, 0x88, 0x03, 0xa4, 0x03, 0xc7, 0x03, 0xe2, 0x04, 0x2a, 0x04, 0x53, 0x04, 0x98, 0x04, 0xfc, 0x05, 0x3b, 0x05, 0x91, + 0x05, 0xfc, 0x06, 0x1f, 0x06, 0x88, 0x06, 0xf6, 0x07, 0x33, 0x07, 0x6d, 0x07, 0x83, 0x07, 0xae, 0x07, 0xc4, 0x08, 0x20, 0x08, 0xd7, 0x09, 0x0f, 0x09, 0x65, + 0x09, 0xae, 0x09, 0xe6, 0x0a, 0x15, 0x0a, 0x3f, 0x0a, 0x92, 0x0a, 0xbf, 0x0a, 0xea, 0x0b, 0x1c, 0x0b, 0x4a, 0x0b, 0x69, 0x0b, 0xa8, 0x0b, 0xde, 0x0c, 0x24, + 0x0c, 0x5f, 0x0c, 0xad, 0x0c, 0xf0, 0x0d, 0x46, 0x0d, 0x69, 0x0d, 0xa4, 0x0d, 0xd1, 0x0e, 0x20, 0x0e, 0x4e, 0x0e, 0x76, 0x0e, 0xa0, 0x0e, 0xc4, 0x0e, 0xde, + 0x0f, 0x02, 0x0f, 0x29, 0x0f, 0x49, 0x0f, 0x75, 0x0f, 0xec, 0x10, 0x6a, 0x10, 0xb4, 0x11, 0x31, 0x11, 0x8a, 0x12, 0x14, 0x12, 0xac, 0x12, 0xf0, 0x13, 0x25, + 0x13, 0x72, 0x13, 0xa5, 0x13, 0xbf, 0x14, 0x2a, 0x14, 0x78, 0x14, 0xbd, 0x15, 0x2f, 0x15, 0xa9, 0x15, 0xfe, 0x16, 0x53, 0x16, 0xb2, 0x17, 0x0b, 0x17, 0x38, + 0x17, 0x87, 0x17, 0xb3, 0x17, 0xf9, 0x18, 0x22, 0x18, 0x80, 0x18, 0xa5, 0x18, 0xfd, 0x19, 0x42, 0x19, 0x84, 0x19, 0xea, 0x1a, 0x15, 0x1a, 0x30, 0x1a, 0x86, + 0x1a, 0xd9, 0x1a, 0xfe, 0x1b, 0x63, 0x1b, 0xa7, 0x1c, 0x0c, 0x1c, 0x6e, 0x1c, 0xb0, 0x1d, 0x72, 0x1e, 0xa5, 0x1f, 0xab, 0x1f, 0xb7, 0x1f, 0xc3, 0x20, 0x27, + 0x20, 0x33, 0x20, 0x3f, 0x20, 0x4b, 0x20, 0x57, 0x20, 0x66, 0x20, 0x75, 0x20, 0x84, 0x20, 0x93, 0x20, 0xa2, 0x20, 0xb1, 0x20, 0xc0, 0x20, 0xcf, 0x20, 0xde, + 0x20, 0xed, 0x20, 0xfc, 0x21, 0x0b, 0x21, 0x1a, 0x21, 0x29, 0x21, 0x38, 0x21, 0x47, 0x21, 0x56, 0x21, 0x65, 0x21, 0x74, 0x21, 0x83, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, 0xbc, 0xcf, 0x60, 0xc2, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xcc, 0xa2, + 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc4, 0x58, 0xfd, 0x5c, 0xfe, 0x7b, 0x0a, 0xdc, 0x04, 0x26, 0x00, 0x03, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x58, 0x00, 0x5f, 0x01, 0x04, 0x00, 0x00, 0x01, 0x1f, 0x00, 0x0b, 0x01, 0xc5, 0x00, 0x62, 0x02, 0x86, 0x00, 0x14, 0x02, 0x27, 0x00, 0x19, + 0x03, 0x58, 0x00, 0x38, 0x02, 0xc4, 0x00, 0x21, 0x00, 0xff, 0x00, 0x62, 0x01, 0x53, 0x00, 0x24, 0x01, 0x55, 0xff, 0xba, 0x02, 0x22, 0x00, 0x55, 0x02, 0x3c, + 0x00, 0x35, 0x01, 0x1f, 0xff, 0xd0, 0x01, 0x43, 0x00, 0x11, 0x01, 0x1f, 0x00, 0x08, 0x01, 0xa8, 0xff, 0xd3, 0x02, 0x27, 0x00, 0x20, 0x02, 0x27, 0x00, 0x59, + 0x02, 0x27, 0xff, 0xe8, 0x02, 0x27, 0x00, 0x07, 0x02, 0x27, 0xff, 0xf4, 0x02, 0x27, 0x00, 0x0d, 0x02, 0x27, 0x00, 0x2b, 0x02, 0x27, 0x00, 0x26, 0x02, 0x27, + 0x00, 0x1b, 0x02, 0x27, 0x00, 0x2a, 0x01, 0x1f, 0x00, 0x08, 0x01, 0x1f, 0xff, 0xca, 0x02, 0x3c, 0x00, 0x35, 0x02, 0x3c, 0x00, 0x35, 0x02, 0x3c, 0x00, 0x35, + 0x01, 0xcb, 0x00, 0x4d, 0x03, 0x58, 0x00, 0x2d, 0x02, 0x74, 0xff, 0xc4, 0x02, 0x6c, 0x00, 0x1a, 0x02, 0x65, 0x00, 0x3b, 0x02, 0xa5, 0x00, 0x1a, 0x02, 0x1f, + 0x00, 0x1a, 0x02, 0x15, 0x00, 0x1a, 0x02, 0xb2, 0x00, 0x3b, 0x02, 0xbd, 0x00, 0x1a, 0x01, 0x7f, 0xff, 0xe3, 0x01, 0x4e, 0xff, 0x62, 0x02, 0x65, 0x00, 0x1a, + 0x02, 0x06, 0x00, 0x1a, 0x03, 0x70, 0x00, 0x1a, 0x02, 0xf6, 0x00, 0x19, 0x02, 0xdb, 0x00, 0x3b, 0x02, 0x62, 0x00, 0x1a, 0x02, 0xdb, 0x00, 0x3b, 0x02, 0x6c, + 0x00, 0x1a, 0x02, 0x12, 0x00, 0x14, 0x02, 0x14, 0x00, 0x51, 0x02, 0xb4, 0x00, 0x44, 0x02, 0x4e, 0x00, 0x5a, 0x03, 0x7e, 0x00, 0x5a, 0x02, 0x62, 0xff, 0xc7, + 0x02, 0x34, 0x00, 0x5b, 0x02, 0x18, 0xff, 0xe2, 0x01, 0x4b, 0xff, 0xee, 0x01, 0xa8, 0x00, 0x6c, 0x01, 0x4b, 0xff, 0xbd, 0x02, 0x27, 0x00, 0x11, 0x01, 0x90, + 0xff, 0xa5, 0x01, 0x44, 0x00, 0x91, 0x02, 0x50, 0x00, 0x2c, 0x02, 0x53, 0x00, 0x12, 0x01, 0xe4, 0x00, 0x2c, 0x02, 0x52, 0x00, 0x2c, 0x02, 0x2d, 0x00, 0x2c, + 0x01, 0x76, 0xff, 0x96, 0x02, 0x54, 0x00, 0x12, 0x02, 0x5c, 0x00, 0x12, 0x01, 0x2b, 0x00, 0x12, 0x01, 0x2b, 0xff, 0x80, 0x02, 0x38, 0x00, 0x12, 0x01, 0x2b, + 0x00, 0x11, 0x03, 0x89, 0x00, 0x12, 0x02, 0x5c, 0x00, 0x12, 0x02, 0x49, 0x00, 0x2c, 0x02, 0x53, 0xff, 0xdf, 0x02, 0x52, 0x00, 0x2c, 0x01, 0xa6, 0x00, 0x12, + 0x01, 0xdb, 0x00, 0x0b, 0x01, 0x9a, 0x00, 0x2e, 0x02, 0x5c, 0x00, 0x36, 0x02, 0x00, 0x00, 0x32, 0x03, 0x14, 0x00, 0x3d, 0x02, 0x16, 0xff, 0xce, 0x02, 0x07, + 0xff, 0xbb, 0x01, 0xd5, 0xff, 0xee, 0x01, 0x63, 0xff, 0xff, 0x02, 0x27, 0x00, 0xde, 0x01, 0x63, 0xff, 0xcd, 0x02, 0x3c, 0x00, 0x35, 0x01, 0x7b, 0x00, 0x38, + 0x01, 0x7b, 0x00, 0x48, 0x01, 0x7b, 0x00, 0x5b, 0x00, 0x7d, 0xfe, 0xfb, 0x01, 0x7b, 0x00, 0x32, 0x01, 0x7b, 0x00, 0x49, 0x01, 0x7b, 0x00, 0x62, 0x01, 0x7b, + 0x00, 0x4c, 0x01, 0x7b, 0x00, 0x5d, 0x01, 0x7b, 0x00, 0x5b, 0x01, 0x7b, 0x00, 0x5b, 0x01, 0x76, 0x00, 0x2a, 0x02, 0xc9, 0xff, 0x95, 0x03, 0xe8, 0xff, 0x95, + 0x03, 0xe8, 0xff, 0x95, 0x02, 0x9e, 0xff, 0x96, 0x02, 0x9e, 0xff, 0x96, 0x02, 0xc9, 0x00, 0x29, 0x03, 0xf2, 0x00, 0x29, 0x03, 0xf2, 0x00, 0x29, 0x02, 0x9e, + 0x00, 0x2a, 0x02, 0x9e, 0x00, 0x2a, 0x01, 0x7b, 0x00, 0x03, 0x00, 0x0e, 0xff, 0xe2, 0xff, 0xf8, 0xff, 0xe1, 0xff, 0xfb, 0x00, 0x04, 0x00, 0x0b, 0xff, 0xf6, + 0x00, 0x03, 0x00, 0x3f, 0x00, 0x47, 0x00, 0x1b, 0x00, 0x2f, 0x00, 0x1c, 0x00, 0x37, 0x00, 0x44, 0x00, 0x4d, 0x00, 0x33, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x0a, 0xf0, 0xfd, 0x5c, 0xfd, 0x9b, 0x0a, 0xdc, 0x03, 0xe8, 0x00, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, 0x02, 0x50, 0x02, 0xbc, 0x00, 0x05, 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, 0xff, 0xf0, 0x00, 0x4b, + 0x02, 0x8a, 0x02, 0x58, 0x00, 0x4a, 0x01, 0x5e, 0x00, 0x32, 0x01, 0x48, 0x00, 0x00, 0x02, 0x0b, 0x08, 0x02, 0x04, 0x05, 0x04, 0x09, 0x02, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x01, 0xa1, 0x00, 0x20, 0x00, 0x7e, 0x04, 0x2d, + 0xfe, 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x22, 0x02, 0xca, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, + 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, 0x21, 0xb0, + 0x00, 0x59, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, 0x02, 0x2c, + 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, + 0x14, 0x43, 0x42, 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, 0x04, 0x50, 0x78, + 0xb2, 0x02, 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, 0x20, 0xb0, 0x02, 0x43, + 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, + 0x2c, 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x1b, 0x20, 0x64, + 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, + 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, 0x38, + 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x20, 0xb0, + 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, + 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, 0x1b, 0xb0, + 0x02, 0x25, 0xb0, 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, 0xb0, 0x1e, 0x50, + 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, + 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, 0x20, 0x45, 0x20, 0xb0, + 0x04, 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, 0x59, 0xb0, 0x01, 0x60, 0x2d, + 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, + 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, 0xb0, 0x08, 0x43, 0x20, 0x8a, 0x20, + 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, + 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, 0x43, 0x2b, + 0xb2, 0x00, 0x02, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, 0x62, 0x66, + 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, 0x0e, 0x00, 0x43, + 0x45, 0x42, 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, + 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, + 0x64, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, + 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, + 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, + 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, 0x0c, 0x00, + 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, + 0x2c, 0xb0, 0x01, 0x60, 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, 0xb0, 0x00, + 0x52, 0x58, 0x20, 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, 0x00, 0x63, 0x8a, + 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, + 0x59, 0x24, 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x1b, 0x21, 0x59, 0x24, + 0xb0, 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, 0x61, 0x42, 0xb0, 0x11, 0x2b, + 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, + 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x23, 0xb0, 0x01, 0x61, 0x20, + 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, + 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x20, + 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, 0x00, 0x13, + 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, + 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, + 0x13, 0x00, 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, + 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, + 0x2c, 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, + 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, + 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x5d, + 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, + 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, + 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, + 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, 0x01, 0x00, 0x11, + 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, + 0x2c, 0xb1, 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, 0xb0, 0x25, 0x2c, 0xb1, + 0x04, 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, 0x28, 0x2c, 0xb1, 0x07, 0x20, + 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, + 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x01, 0x60, 0xb0, 0x2e, 0x2a, + 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, + 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, 0x20, 0x47, + 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, + 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, + 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, + 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x34, 0x2c, 0x20, + 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, + 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, 0x20, 0x3c, + 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, + 0x00, 0x43, 0x61, 0xb0, 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb0, + 0x02, 0x25, 0x49, 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, 0x01, 0x15, 0x14, + 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, + 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, + 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, + 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, + 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, + 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, 0x02, 0x25, + 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, + 0xb0, 0x01, 0x63, 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, 0x25, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, 0x60, 0x64, 0x23, 0xb0, + 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, + 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x3c, 0x38, 0x2d, 0xb0, 0x3d, + 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, + 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, 0x2e, + 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, + 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, + 0x59, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, 0x20, 0x3c, + 0x8a, 0x38, 0x23, 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, + 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, + 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, + 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, + 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, + 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, + 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, + 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, 0x20, 0x20, + 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, + 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, + 0x26, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, 0x20, 0x3c, 0x20, + 0x2e, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, + 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, + 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, 0xb0, 0x06, 0x43, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, + 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, 0x23, 0x38, + 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, + 0x3a, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x23, + 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, + 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, + 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, 0xb0, 0x4c, 0x2c, 0xb0, + 0x39, 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, + 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, + 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x53, 0x2c, 0xb2, 0x00, 0x00, + 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, + 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x59, + 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x43, + 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, + 0x01, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x61, + 0x2c, 0xb2, 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, 0x48, 0x2b, 0x2d, 0xb0, + 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, + 0xb0, 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x69, 0x2c, 0xb3, 0x01, 0x00, + 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, + 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x44, + 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, + 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, + 0xb0, 0x73, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, 0x2c, 0xb0, + 0x00, 0x16, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x77, + 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, + 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, + 0x2d, 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, + 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, + 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, + 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, + 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x87, + 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, 0x01, 0x3f, + 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, + 0xb0, 0x06, 0x1b, 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, 0x50, 0x78, 0xb1, + 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, 0xb9, 0x08, 0x00, 0x08, + 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, 0x00, 0x49, 0x39, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, + 0x14, 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, 0x02, 0x56, 0x06, 0x4e, 0x04, 0x3e, 0x08, 0x32, 0x06, 0x24, 0x07, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x07, 0x42, + 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x52, 0x02, 0x46, 0x06, 0x38, 0x04, 0x2b, 0x05, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, + 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, 0x13, 0xc0, 0x0f, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, + 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x09, + 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, + 0x28, 0x01, 0x88, 0x51, 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, 0xba, 0x08, + 0x80, 0x00, 0x01, 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, 0x06, 0x7a, 0x06, + 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x50, 0x02, 0x40, 0x06, 0x34, 0x04, 0x26, 0x05, 0x09, 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, + 0x00, 0x44, 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x73, 0x02, 0xca, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd6, 0xff, 0xf6, 0x02, 0x2c, + 0xff, 0xf6, 0xff, 0x10, 0x00, 0x99, 0x00, 0x99, 0x00, 0x7d, 0x00, 0x7d, 0x02, 0x46, 0x02, 0x46, 0x00, 0x00, 0x00, 0x00, 0x02, 0x4f, 0x02, 0x50, 0xff, 0xf8, + 0x00, 0x00, 0x00, 0x94, 0x00, 0x94, 0x00, 0x78, 0x00, 0x78, 0x02, 0xca, 0xff, 0xf6, 0x02, 0xf8, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, + 0x02, 0xfd, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x99, 0x00, 0x99, 0x00, 0x7d, 0x00, 0x7d, 0x02, 0x46, 0x00, 0x00, 0x02, 0x50, 0xff, 0xf8, 0x00, 0x78, + 0x00, 0x78, 0x00, 0x65, 0x00, 0x65, 0x01, 0x68, 0x00, 0xee, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x78, 0x00, 0x78, + 0x00, 0x65, 0x00, 0x65, 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x94, 0x00, 0x94, 0x00, 0x78, 0x00, 0x78, 0x02, 0xca, 0x00, 0x00, 0x02, 0xf8, 0x02, 0x22, 0x00, 0x00, + 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xf9, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x60, 0x00, 0x60, 0x00, 0x48, 0x00, 0x48, 0x01, 0x29, 0xff, 0x7d, + 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x33, 0xff, 0x73, 0x01, 0x69, 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x60, 0x00, 0x60, 0x00, 0x48, + 0x00, 0x48, 0x02, 0xcb, 0x01, 0x9f, 0x02, 0xe7, 0x02, 0x67, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe8, 0x01, 0x95, 0x02, 0xe8, 0x02, 0x6d, 0x01, 0x19, 0x00, 0x8f, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, + 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x16, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x3c, + 0x00, 0xde, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x2a, 0x01, 0x1a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, 0x01, 0x44, + 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x26, 0x01, 0x98, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, + 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x4e, + 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x41, + 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, + 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, + 0x00, 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, + 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, + 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, + 0x00, 0x6e, 0x00, 0x73, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x20, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, + 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x6f, + 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x49, 0x00, 0x74, + 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, + 0x00, 0x20, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x20, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x56, + 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, + 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, + 0x00, 0x28, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, + 0x00, 0x62, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6f, + 0x00, 0x6c, 0x00, 0x64, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x03, 0x00, 0x00, 0xff, 0xf4, 0x00, 0x00, 0xff, 0x9c, + 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, + 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x22, 0x00, 0x3b, 0x00, 0x01, + 0x00, 0x42, 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x02, 0x00, 0x18, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x32, + 0x00, 0x40, 0x00, 0x4e, 0x00, 0x4e, 0x00, 0x2a, 0x00, 0x32, 0x00, 0x40, 0x00, 0x4e, 0x00, 0x4e, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x21, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x15, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x1f, + 0x00, 0x01, 0x02, 0x73, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x25, 0x00, 0x01, 0x02, 0x7d, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x27, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, + 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x6b, 0x65, 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x06, 0xc8, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, + 0x00, 0x0a, 0x01, 0x08, 0x00, 0x01, 0x00, 0x38, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x6a, 0x00, 0xf4, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x8c, 0x00, 0xb4, + 0x00, 0x92, 0x00, 0x98, 0x00, 0xb4, 0x00, 0xaa, 0x00, 0xb4, 0x00, 0xba, 0x00, 0xc4, 0x00, 0xc4, 0x00, 0xce, 0x00, 0xd8, 0x00, 0xf4, 0x00, 0xde, 0x00, 0xe4, + 0x00, 0xee, 0x00, 0xee, 0x00, 0xee, 0x00, 0xf4, 0x00, 0x01, 0x00, 0x17, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, + 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, + 0x00, 0x58, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, 0x37, 0xff, 0xd8, 0x00, 0x38, 0xff, 0xd8, 0x00, 0x3a, 0xff, 0xc4, 0x00, 0x01, + 0x00, 0x2b, 0x00, 0x4b, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xec, 0x00, 0x0f, 0xff, 0xec, 0x00, 0x01, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, + 0x00, 0x04, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x39, + 0xff, 0xec, 0x00, 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x20, + 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, 0x00, 0x07, 0xff, 0xec, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x6c, 0x00, 0x02, + 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, + 0x03, 0xd8, 0x00, 0x04, 0x00, 0x00, 0x04, 0x26, 0x04, 0xe4, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xf6, + 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, 0xff, 0xe2, + 0xff, 0xce, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xd8, 0xff, 0xec, 0x00, 0x00, 0xff, 0xd8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, + 0xff, 0xf6, 0xff, 0xec, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xce, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0xff, 0xe2, 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xce, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, + 0x00, 0x0a, 0xff, 0xc4, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xc4, + 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x8e, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x25, 0x00, 0x03, + 0x00, 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, + 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x4c, + 0x00, 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x1f, 0x00, 0x03, + 0x00, 0x03, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x09, 0x00, 0x13, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, + 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x22, 0x00, 0x22, 0x00, 0x01, 0x00, 0x24, 0x00, 0x24, 0x00, 0x07, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, + 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x08, 0x00, 0x30, 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, 0x14, 0x00, 0x32, + 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, 0x05, 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x39, 0x00, 0x39, + 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x06, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0d, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x02, + 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x10, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0c, 0x00, 0x57, + 0x00, 0x58, 0x00, 0x04, 0x00, 0x59, 0x00, 0x59, 0x00, 0x10, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, + 0x00, 0x15, 0x00, 0x02, 0x00, 0x23, 0x00, 0x03, 0x00, 0x03, 0x00, 0x11, 0x00, 0x08, 0x00, 0x08, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x0d, + 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, + 0x00, 0x05, 0x00, 0x24, 0x00, 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x28, 0x00, 0x02, 0x00, 0x30, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x32, 0x00, 0x02, + 0x00, 0x35, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x08, 0x00, 0x3b, + 0x00, 0x3b, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x04, 0x00, 0x44, 0x00, 0x46, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, + 0x00, 0x15, 0x00, 0x48, 0x00, 0x48, 0x00, 0x0d, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x03, 0x00, 0x50, 0x00, 0x50, 0x00, 0x01, 0x00, 0x51, 0x00, 0x51, 0x00, 0x03, + 0x00, 0x52, 0x00, 0x52, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x03, 0x00, 0x54, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0e, 0x00, 0x56, + 0x00, 0x56, 0x00, 0x03, 0x00, 0x57, 0x00, 0x58, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x07, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x5e, + 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x15, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x50, 0x00, 0x92, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, + 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x45, 0x57, 0x45, 0x20, 0x00, 0x18, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, + 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x20, 0x66, 0x72, 0x61, 0x63, 0x00, 0x26, 0x6c, 0x69, 0x67, 0x61, 0x00, 0x30, 0x6c, 0x6f, + 0x63, 0x6c, 0x00, 0x36, 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x3c, + 0x00, 0x4a, 0x00, 0x5e, 0x00, 0x76, 0x00, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x12, 0x00, 0x06, 0x00, 0x6b, + 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x01, 0x00, 0x06, 0x00, 0x47, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x70, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, + 0x00, 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x01, + 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x01, 0x00, 0x76, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, + 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x00, 0x89, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x66, + 0x00, 0x02, 0x00, 0x0a, 0x00, 0x38, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6e, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4d, + 0x00, 0x6d, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x70, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x47, + 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x73, 0x00, 0x03, 0x00, 0x6b, 0x00, 0x4d, 0x00, 0x72, 0x00, 0x03, 0x00, 0x6b, + 0x00, 0x4a, 0x00, 0x74, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x71, 0x00, 0x02, 0x00, 0x6b, 0x00, 0x01, 0x00, 0x02, 0x00, 0x47, + 0x00, 0x6b}; + +const inline Font FONTS[FONT_COUNT] = {{.data = FONT_REGULAR_DATA, .length = std::size(FONT_REGULAR_DATA)}, + {.data = FONT_ITALICS_DATA, .length = std::size(FONT_ITALICS_DATA)}, + {.data = FONT_BOLD_DATA, .length = std::size(FONT_BOLD_DATA)}, + {.data = FONT_BOLD_ITALICS_DATA, .length = std::size(FONT_BOLD_ITALICS_DATA)}}; diff --git a/src/anm2.cpp b/src/anm2.cpp index 5ef807e..5808bce 100644 --- a/src/anm2.cpp +++ b/src/anm2.cpp @@ -17,7 +17,8 @@ static void _anm2_frame_serialize(Anm2Frame* frame, Anm2Type type, XMLDocument* XMLDocument localDocument; XMLDocument* useDocument = document ? document : &localDocument; - XMLElement* element = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]); + XMLElement* element = type == ANM2_TRIGGER ? useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]) + : useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]); if (type == ANM2_TRIGGER) { element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_EVENT_ID], frame->eventID); // EventID @@ -118,8 +119,8 @@ static void _anm2_animation_serialize(Anm2Animation* animation, XMLDocument* doc // Triggers XMLElement* triggersElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS]); - for (auto& frame : animation->triggers.frames) - _anm2_frame_serialize(&frame, ANM2_TRIGGER, useDocument, triggersElement); + for (auto& trigger : animation->triggers.frames) + _anm2_frame_serialize(&trigger, ANM2_TRIGGER, useDocument, triggersElement); element->InsertEndChild(triggersElement); @@ -220,11 +221,9 @@ bool anm2_serialize(Anm2* self, const std::string& path) { // Animations XMLElement* animationsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATIONS]); - if (self->defaultAnimationID != ID_NONE) - animationsElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DEFAULT_ANIMATION], - self->animations[self->defaultAnimationID].name.c_str()); // DefaultAnimation + animationsElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DEFAULT_ANIMATION], self->defaultAnimation.c_str()); // DefaultAnimation - for (auto& [id, animation] : self->animations) + for (auto& animation : self->animations) _anm2_animation_serialize(&animation, &document, animationsElement); animatedActorElement->InsertEndChild(animationsElement); @@ -426,13 +425,9 @@ bool anm2_deserialize(Anm2* self, const std::string& path, bool isTextures) { anm2_new(self); self->path = path; - std::string defaultAnimation{}; int id{}; - // Save old working directory and then use anm2's path as directory - // (used for loading textures from anm2 correctly which are relative) - std::filesystem::path workingPath = std::filesystem::current_path(); - working_directory_from_file_set(path); + WorkingDirectory workingDirectory(path); const XMLElement* root = document.RootElement(); @@ -506,13 +501,13 @@ bool anm2_deserialize(Anm2* self, const std::string& path, bool isTextures) { switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { case ANM2_ATTRIBUTE_NAME: addLayer.name = std::string(attribute->Value()); - break; // Name + break; case ANM2_ATTRIBUTE_ID: id = std::atoi(attribute->Value()); - break; // ID + break; case ANM2_ATTRIBUTE_SPRITESHEET_ID: addLayer.spritesheetID = std::atoi(attribute->Value()); - break; // ID + break; default: break; } @@ -575,7 +570,7 @@ bool anm2_deserialize(Anm2* self, const std::string& path, bool isTextures) { for (const XMLAttribute* attribute = animations->FirstAttribute(); attribute; attribute = attribute->Next()) { switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { case ANM2_ATTRIBUTE_DEFAULT_ANIMATION: - defaultAnimation = std::string(attribute->Value()); + self->defaultAnimation = std::string(attribute->Value()); break; // DefaultAnimation default: break; @@ -585,18 +580,12 @@ bool anm2_deserialize(Anm2* self, const std::string& path, bool isTextures) { // Animation for (const XMLElement* animation = animations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION]); animation; animation = animation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION])) - _anm2_animation_deserialize(&self->animations[map_next_id_get(self->animations)], animation); + _anm2_animation_deserialize(&self->animations.emplace_back(Anm2Animation()), animation); } - for (auto& [id, animation] : self->animations) - if (animation.name == defaultAnimation) - self->defaultAnimationID = id; - if (isTextures) anm2_spritesheet_texture_pixels_download(self); - std::filesystem::current_path(workingPath); - log_info(std::format(ANM2_READ_INFO, path)); return true; @@ -625,7 +614,7 @@ int anm2_layer_add(Anm2* self) { void anm2_layer_remove(Anm2* self, int id) { self->layers.erase(id); - for (auto& [_, animation] : self->animations) + for (auto& animation : self->animations) anm2_animation_layer_animation_remove(&animation, id); } @@ -641,36 +630,32 @@ void anm2_null_remove(Anm2* self, int id) { self->nulls.erase(id); - for (auto& [_, animation] : self->animations) + for (auto& animation : self->animations) anm2_animation_null_animation_remove(&animation, id); } -int anm2_animation_add(Anm2* self, Anm2Animation* animation, int id) { - int addID = map_next_id_get(self->animations); +int anm2_animation_add(Anm2* self, Anm2Animation* animation, int index) { - Anm2Animation localAnimation; - Anm2Animation* addAnimation = animation ? animation : &localAnimation; + Anm2Animation addAnimation = animation ? *animation : Anm2Animation(); if (!animation) - addAnimation->rootAnimation.frames.push_back(Anm2Frame{}); + addAnimation.rootAnimation.frames.push_back(Anm2Frame{}); - if (id != ID_NONE) { - map_insert_shift(self->animations, id, *addAnimation); - return id + 1; - } else - self->animations[addID] = *addAnimation; + int addIndex = index != INDEX_NONE ? index : (int)self->animations.size() - 1; - return addID; + self->animations.insert(self->animations.begin() + addIndex, addAnimation); + + return addIndex; } -void anm2_animation_remove(Anm2* self, int id) { self->animations.erase(id); } +void anm2_animations_remove(Anm2* self, const std::set indices) { vector_erase_indices(self->animations, indices); }; void anm2_new(Anm2* self) { *self = Anm2{}; _anm2_created_on_set(self); } -Anm2Animation* anm2_animation_from_reference(Anm2* self, Anm2Reference reference) { return map_find(self->animations, reference.animationID); } +Anm2Animation* anm2_animation_from_reference(Anm2* self, Anm2Reference reference) { return vector_get(self->animations, reference.animationIndex); } Anm2Item* anm2_item_from_reference(Anm2* self, Anm2Reference reference) { if (reference.itemType == ANM2_NONE) @@ -928,8 +913,8 @@ void anm2_item_frame_set(Anm2* self, Anm2Reference reference, const Anm2FrameCha } } -void anm2_animation_merge(Anm2* self, int animationID, const std::vector& mergeIDs, Anm2MergeType type) { - Anm2Animation newAnimation = self->animations[animationID]; +void anm2_animation_merge(Anm2* self, int animationIndex, std::set mergeIndices, Anm2MergeType type) { + Anm2Animation newAnimation = self->animations[animationIndex]; auto merge_item = [&](Anm2Item& destinationItem, const Anm2Item& sourceItem) { switch (type) { @@ -950,11 +935,11 @@ void anm2_animation_merge(Anm2* self, int animationID, const std::vector& m } }; - for (auto mergeID : mergeIDs) { - if (animationID == mergeID) + for (auto mergeIndices : mergeIndices) { + if (animationIndex == mergeIndices) continue; - const Anm2Animation& mergeAnimation = self->animations[mergeID]; + const Anm2Animation& mergeAnimation = self->animations[mergeIndices]; merge_item(newAnimation.rootAnimation, mergeAnimation.rootAnimation); @@ -967,9 +952,9 @@ void anm2_animation_merge(Anm2* self, int animationID, const std::vector& m merge_item(newAnimation.triggers, mergeAnimation.triggers); } - self->animations[animationID] = newAnimation; + self->animations[animationIndex] = newAnimation; - anm2_animation_length_set(&self->animations[animationID]); + anm2_animation_length_set(&self->animations[animationIndex]); } void anm2_frame_bake(Anm2* self, Anm2Reference reference, int interval, bool isRoundScale, bool isRoundRotation) { @@ -981,7 +966,7 @@ void anm2_frame_bake(Anm2* self, Anm2Reference reference, int interval, bool isR if (!frame) return; - Anm2Reference referenceNext = {reference.animationID, reference.itemType, reference.itemID, reference.frameIndex + 1}; + Anm2Reference referenceNext = {reference.animationIndex, reference.itemType, reference.itemID, reference.frameIndex + 1}; Anm2Frame* frameNext = anm2_frame_from_reference(self, referenceNext); if (!frameNext) frameNext = frame; @@ -1028,7 +1013,7 @@ void anm2_scale(Anm2* self, float scale) { frame.pivot = vec2((int)(frame.pivot.x * scale), (int)(frame.pivot.y * scale)); }; - for (auto& [_, animation] : self->animations) { + for (auto& animation : self->animations) { for (auto& frame : animation.rootAnimation.frames) frame_scale(frame); @@ -1112,7 +1097,7 @@ vec4 anm2_animation_rect_get(Anm2* self, Anm2Reference reference, bool isRootTra for (float t = 0.0f; t <= animation->frameNum; t += 1.0f) { for (const auto& [id, _] : animation->layerAnimations) { - anm2_frame_from_time(self, &frame, {reference.animationID, ANM2_LAYER, id}, t); + anm2_frame_from_time(self, &frame, {reference.animationIndex, ANM2_LAYER, id}, t); if (!frame.isVisible) continue; if (frame.size.x <= 0 || frame.size.y <= 0) @@ -1120,7 +1105,7 @@ vec4 anm2_animation_rect_get(Anm2* self, Anm2Reference reference, bool isRootTra mat4 rootModel(1.0f); if (isRootTransform) { - anm2_frame_from_time(self, &root, {reference.animationID, ANM2_ROOT}, t); + anm2_frame_from_time(self, &root, {reference.animationIndex, ANM2_ROOT}, t); rootModel = quad_model_parent_get(root.position, root.pivot, PERCENT_TO_UNIT(root.scale), root.rotation); } @@ -1149,7 +1134,7 @@ void anm2_animation_serialize_to_string(Anm2Animation* animation, std::string* s void anm2_frame_serialize_to_string(Anm2Frame* frame, Anm2Type type, std::string* string) { _anm2_frame_serialize(frame, type, nullptr, nullptr, string); } -bool anm2_animation_deserialize_from_xml(Anm2Animation* animation, const std::string& xml) { +bool anm2_animations_deserialize_from_xml(std::vector& animations, const std::string& xml) { XMLDocument document; auto animation_deserialize_error = [&]() { @@ -1160,13 +1145,12 @@ bool anm2_animation_deserialize_from_xml(Anm2Animation* animation, const std::st if (document.Parse(xml.c_str()) != XML_SUCCESS) return animation_deserialize_error(); - const XMLElement* element = document.RootElement(); - if (!element) - return animation_deserialize_error(); - if (std::string(element->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION])) - return animation_deserialize_error(); + for (const XMLElement* element = document.RootElement(); element; element = element->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION])) { + if (std::string(document.RootElement()->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION])) + return animation_deserialize_error(); + _anm2_animation_deserialize(&animations.emplace_back(Anm2Animation()), element); + } - _anm2_animation_deserialize(animation, element); return true; } diff --git a/src/anm2.h b/src/anm2.h index b0affcb..4f56dc9 100644 --- a/src/anm2.h +++ b/src/anm2.h @@ -23,6 +23,7 @@ #define ANM2_WRITE_INFO "Wrote anm2 to file: {}" #define ANM2_CREATED_ON_FORMAT "%d-%B-%Y %I:%M:%S %p" +#define ANM2_ANIMATION_DEFAULT "New Animation" #define ANM2_EXTENSION "anm2" #define ANM2_SPRITESHEET_EXTENSION "png" @@ -185,7 +186,7 @@ struct Anm2Item { struct Anm2Animation { int frameNum = ANM2_FRAME_NUM_MIN; - std::string name = "New Animation"; + std::string name = ANM2_ANIMATION_DEFAULT; bool isLoop = true; Anm2Item rootAnimation; std::unordered_map layerAnimations; @@ -200,12 +201,12 @@ struct Anm2 { std::string path{}; std::string createdBy = "robot"; std::string createdOn{}; + std::string defaultAnimation = ANM2_ANIMATION_DEFAULT; std::map spritesheets; std::map layers; std::map nulls; std::map events; - std::map animations; - int defaultAnimationID = ID_NONE; + std::vector animations; int fps = ANM2_FPS_DEFAULT; int version{}; @@ -213,7 +214,7 @@ struct Anm2 { }; struct Anm2Reference { - int animationID = ID_NONE; + int animationIndex = ID_NONE; Anm2Type itemType = ANM2_NONE; int itemID = ID_NONE; int frameIndex = INDEX_NONE; @@ -231,11 +232,11 @@ Anm2Animation* anm2_animation_from_reference(Anm2* self, Anm2Reference reference Anm2Frame* anm2_frame_add(Anm2* self, Anm2Frame* frame, Anm2Reference reference); Anm2Frame* anm2_frame_from_reference(Anm2* self, Anm2Reference reference); Anm2Item* anm2_item_from_reference(Anm2* self, Anm2Reference reference); -bool anm2_animation_deserialize_from_xml(Anm2Animation* animation, const std::string& xml); +bool anm2_animations_deserialize_from_xml(std::vector& animations, const std::string& xml); bool anm2_deserialize(Anm2* self, const std::string& path, bool isTextures = true); bool anm2_frame_deserialize_from_xml(Anm2Frame* frame, const std::string& xml); bool anm2_serialize(Anm2* self, const std::string& path); -int anm2_animation_add(Anm2* self, Anm2Animation* animation = nullptr, int id = ID_NONE); +int anm2_animation_add(Anm2* self, Anm2Animation* animation = nullptr, int index = INDEX_NONE); int anm2_animation_length_get(Anm2Animation* self); int anm2_frame_index_from_time(Anm2* self, Anm2Reference reference, float time); int anm2_layer_add(Anm2* self); @@ -244,10 +245,10 @@ vec4 anm2_animation_rect_get(Anm2* anm2, Anm2Reference reference, bool isRootTra void anm2_animation_layer_animation_add(Anm2Animation* animation, int id); void anm2_animation_layer_animation_remove(Anm2Animation* animation, int id); void anm2_animation_length_set(Anm2Animation* self); -void anm2_animation_merge(Anm2* self, int animationID, const std::vector& mergeIDs, Anm2MergeType type); +void anm2_animation_merge(Anm2* self, int animationID, std::set mergeIndices, Anm2MergeType type); void anm2_animation_null_animation_add(Anm2Animation* animation, int id); void anm2_animation_null_animation_remove(Anm2Animation* animation, int id); -void anm2_animation_remove(Anm2* self, int id); +void anm2_animations_remove(Anm2* self, const std::set indices); void anm2_animation_serialize_to_string(Anm2Animation* animation, std::string* string); void anm2_frame_bake(Anm2* self, Anm2Reference reference, int interval, bool isRoundScale, bool isRoundRotation); void anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, float time); diff --git a/src/clipboard.cpp b/src/clipboard.cpp index 3e5d09d..abe61fd 100644 --- a/src/clipboard.cpp +++ b/src/clipboard.cpp @@ -10,27 +10,27 @@ void clipboard_copy(Clipboard* self) { switch (self->type) { case CLIPBOARD_FRAME: { - Anm2Reference* reference = std::get_if(&self->location); - if (!reference) - break; - Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *reference); - if (!frame) - break; - anm2_frame_serialize_to_string(frame, reference->itemType, &clipboardText); - clipboard_text_set(); + if (Anm2Reference* reference = std::get_if(&self->destination)) { + if (Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *reference)) { + anm2_frame_serialize_to_string(frame, reference->itemType, &clipboardText); + clipboard_text_set(); + } + } break; } case CLIPBOARD_ANIMATION: { - int* id = std::get_if(&self->location); - if (!id) - break; - Anm2Animation* animation = map_find(self->anm2->animations, *id); - if (!animation) - break; - anm2_animation_serialize_to_string(animation, &clipboardText); - clipboard_text_set(); + if (std::set* set = std::get_if>(&self->source)) { + for (auto& i : *set) { + if (Anm2Animation* animation = anm2_animation_from_reference(self->anm2, {i})) { + std::string animationText{}; + anm2_animation_serialize_to_string(animation, &animationText); + clipboardText += animationText; + } + } + clipboard_text_set(); + } break; - } break; + } default: break; } @@ -41,17 +41,13 @@ void clipboard_cut(Clipboard* self) { switch (self->type) { case CLIPBOARD_FRAME: { - Anm2Reference* reference = std::get_if(&self->location); - if (!reference) - break; - anm2_frame_remove(self->anm2, *reference); + if (Anm2Reference* reference = std::get_if(&self->destination)) + anm2_frame_remove(self->anm2, *reference); break; } case CLIPBOARD_ANIMATION: { - int* id = std::get_if(&self->location); - if (!id) - break; - anm2_animation_remove(self->anm2, *id); + if (std::set* set = std::get_if>(&self->source)) + anm2_animations_remove(self->anm2, *set); break; } default: @@ -69,25 +65,25 @@ bool clipboard_paste(Clipboard* self) { switch (self->type) { case CLIPBOARD_FRAME: { - Anm2Reference* reference = std::get_if(&self->location); - if (!reference) - break; - Anm2Frame frame; - if (anm2_frame_deserialize_from_xml(&frame, clipboard_string())) + if (Anm2Reference* reference = std::get_if(&self->destination)) { + Anm2Frame frame; + if (!anm2_frame_deserialize_from_xml(&frame, clipboard_string())) + return false; anm2_frame_add(self->anm2, &frame, *reference); - else - return false; + } break; } case CLIPBOARD_ANIMATION: { - int* id = std::get_if(&self->location); - if (!id) - break; - Anm2Animation animation; - if (anm2_animation_deserialize_from_xml(&animation, clipboard_string())) - anm2_animation_add(self->anm2, &animation, *id); - else - return false; + if (int* index = std::get_if(&self->destination)) { + std::vector clipboardAnimations; + if (!anm2_animations_deserialize_from_xml(clipboardAnimations, clipboard_string())) + return false; + + int useIndex = std::clamp(*index + 1, 0, (int)self->anm2->animations.size()); + + for (auto& animation : clipboardAnimations) + anm2_animation_add(self->anm2, &animation, useIndex++); + } break; } default: @@ -98,5 +94,4 @@ bool clipboard_paste(Clipboard* self) { } void clipboard_init(Clipboard* self, Anm2* anm2) { self->anm2 = anm2; } - bool clipboard_is_value(void) { return SDL_HasClipboardText(); } \ No newline at end of file diff --git a/src/clipboard.h b/src/clipboard.h index 98621e1..2ee4f7c 100644 --- a/src/clipboard.h +++ b/src/clipboard.h @@ -1,17 +1,19 @@ #pragma once #include "anm2.h" +#include #define CLIPBOARD_TEXT_SET_WARNING "Unable to set clipboard text! ({})" enum ClipboardType { CLIPBOARD_NONE, CLIPBOARD_FRAME, CLIPBOARD_ANIMATION }; -using ClipboardLocation = std::variant; +using ClipboardValue = std::variant, int>; struct Clipboard { Anm2* anm2 = nullptr; ClipboardType type; - ClipboardLocation location; + ClipboardValue source; + ClipboardValue destination; }; bool clipboard_is_value(void); diff --git a/src/imgui.cpp b/src/imgui.cpp index 37fc548..ae2ab3d 100644 --- a/src/imgui.cpp +++ b/src/imgui.cpp @@ -1,4 +1,6 @@ #include "imgui.h" +#include "COMMON.h" +#include "anm2.h" static void _imgui_anm2_open(Imgui* self, const std::string& path) { imgui_anm2_new(self); @@ -22,13 +24,14 @@ static void _imgui_spritesheet_add(Imgui* self, const std::string& path) { self->anm2->spritesheets[id] = Anm2Spritesheet{}; self->anm2->spritesheets[id].path = spritesheetPath; self->anm2->spritesheets[id].texture = texture; + imgui_log_push(self, std::format(IMGUI_LOG_ADD_SPRITESHEET, id, path)); } else imgui_log_push(self, std::format(IMGUI_LOG_ADD_SPRITESHEET_ERROR, path)); } static bool _imgui_is_window_hovered(void) { return ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } static bool _imgui_is_window_hovered_and_click(void) { return _imgui_is_window_hovered() && ImGui::IsMouseClicked(0); } -static bool _imgui_is_no_click_on_item(void) { return ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered(); } +static bool _imgui_is_no_click_on_item(void) { return ImGui::IsMouseClicked(0) && !ImGui::IsItemHovered(); } static bool _imgui_is_input_begin(void) { return ImGui::IsItemHovered() && (ImGui::IsKeyPressed(IMGUI_INPUT_RENAME) || ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)); @@ -67,6 +70,10 @@ static vec2 _imgui_item_spacing_get(const ImguiItem& self) { return self.itemSpa static vec2 _imgui_window_padding_get(const ImguiItem& self) { return self.windowPadding.has_value() ? *self.windowPadding : vec2(ImGui::GetStyle().WindowPadding); } +static vec2 _imgui_frame_padding_get(const ImguiItem& self) { + return self.framePadding.has_value() ? *self.framePadding : vec2(ImGui::GetStyle().WindowPadding); +} + static vec2 _imgui_cursor_position_get(const ImguiItem& self) { return self.cursorPosition.has_value() ? *self.cursorPosition : vec2(ImGui::GetCursorPos()); } static vec2 _imgui_item_size_get(const ImguiItem& self, ImguiItemType type) { @@ -80,20 +87,24 @@ static vec2 _imgui_item_size_get(const ImguiItem& self, ImguiItemType type) { default: if (self.rowCount.has_value()) size.x = (ImGui::GetWindowSize().x - (_imgui_item_spacing_get(self).x * (*self.rowCount + 1))) / *self.rowCount; - else if (self.isSizeToText) + else if (self.isWidthToText) size.x = (ImGui::CalcTextSize(self.label_get().c_str()).x + ImGui::GetStyle().FramePadding.x); - else if (self.isSizeToRegion) + else if (self.isWidthToRegion) size.x = ImGui::GetContentRegionAvail().x; else size.x = ImGui::CalcItemWidth(); - if (type != IMGUI_BUTTON) - size.y = ImGui::GetTextLineHeight() + IMGUI_TEXT_HEIGHT_PADDING; + if (self.isHeightToRegion) + size.y = ImGui::GetContentRegionAvail().y; + else if (type != IMGUI_BUTTON) + size.y = ImGui::GetTextLineHeight() + ImGui::GetStyle().FramePadding.y; break; } } else size = *self.size; + size *= self.scale; + return size; } @@ -102,6 +113,8 @@ static void _imgui_item_style_push(const ImguiItem& self) { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, *self.windowPadding); if (self.itemSpacing.has_value()) ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, *self.itemSpacing); + if (self.font.has_value()) + ImGui::PushFont(*self.font, FONT_SIZE); } static void _imgui_item_style_pop(const ImguiItem& self) { @@ -109,6 +122,8 @@ static void _imgui_item_style_pop(const ImguiItem& self) { ImGui::PopStyleVar(); if (self.itemSpacing.has_value()) ImGui::PopStyleVar(); + if (self.font.has_value()) + ImGui::PopFont(); } static const char* _imgui_float_format_get(const ImguiItem& item, float& value) { @@ -127,7 +142,8 @@ static void _imgui_item_pre(const ImguiItem& self, ImguiItemType type) { switch (type) { case IMGUI_ITEM: case IMGUI_TEXT: - case IMGUI_WINDOW: + case IMGUI_BEGIN_WINDOW: + case IMGUI_END_WINDOW: case IMGUI_DOCKSPACE: case IMGUI_BEGIN_CHILD: case IMGUI_END_CHILD: @@ -195,6 +211,9 @@ static void _imgui_item_pre(const ImguiItem& self, ImguiItemType type) { } switch (type) { + case IMGUI_END_WINDOW: + _imgui_item_style_pop(self); + break; case IMGUI_END_CHILD: break; default: @@ -203,12 +222,26 @@ static void _imgui_item_pre(const ImguiItem& self, ImguiItemType type) { } switch (type) { - case IMGUI_WINDOW: + case IMGUI_BEGIN_WINDOW: + case IMGUI_END_WINDOW: + case IMGUI_BEGIN_CHILD: + case IMGUI_END_CHILD: break; default: ImGui::SetCursorPos(self.cursorPosition.value_or(vec2(ImGui::GetCursorPos())) + self.cursorOffset); break; } + + switch (type) { + case IMGUI_BEGIN_WINDOW: + if (self.position.has_value()) + ImGui::SetNextWindowPos(*self.position); + if (self.size.has_value()) + ImGui::SetNextWindowSize(*self.size); + break; + default: + break; + } } static void _imgui_item_post(const ImguiItem& self, Imgui* imgui, ImguiItemType type, bool& isActivated) { @@ -304,7 +337,8 @@ static void _imgui_item_post(const ImguiItem& self, Imgui* imgui, ImguiItemType switch (type) { case IMGUI_ITEM: case IMGUI_TEXT: - case IMGUI_WINDOW: + case IMGUI_BEGIN_WINDOW: + case IMGUI_END_WINDOW: case IMGUI_DOCKSPACE: case IMGUI_BEGIN_CHILD: case IMGUI_END_CHILD: @@ -323,6 +357,9 @@ static void _imgui_item_post(const ImguiItem& self, Imgui* imgui, ImguiItemType switch (type) { case IMGUI_BEGIN_CHILD: break; + case IMGUI_BEGIN_WINDOW: + _imgui_item_style_push(self); + break; default: _imgui_item_style_pop(self); break; @@ -348,10 +385,7 @@ static void _imgui_item_post(const ImguiItem& self, Imgui* imgui, ImguiItemType bool isActivated = false; \ do { \ VALUE_TYPE value = inValue; \ - BODY if (_imgui_is_input_default()) { \ - value = VALUE_TYPE(self.value); \ - isActivated = true; \ - } \ + BODY {} \ inValue = value; \ } while (0); \ _imgui_item_post(self, imgui, type, isActivated); \ @@ -384,6 +418,9 @@ static void _imgui_item_post(const ImguiItem& self, Imgui* imgui, ImguiItemType return isActivated; \ } +#define IMGUI_ITEM_CUSTOM_FUNCTION(NAME, TYPE, BODY) IMGUI_ITEM_BASE(NAME, TYPE, BODY) +#define IMGUI_ITEM_CUSTOM_VALUE_FUNCTION(NAME, TYPE, VALUE_TYPE, BODY) IMGUI_ITEM_VALUE_BASE(NAME, TYPE, VALUE_TYPE, {BODY}) + IMGUI_ITEM_VOID_FUNCTION(_imgui_dockspace, IMGUI_DOCKSPACE, ImGui::DockSpace(ImGui::GetID(self.label_get().c_str()), *self.size, self.flags)); IMGUI_ITEM_VOID_FUNCTION(_imgui_begin_child, IMGUI_BEGIN_CHILD, ImGui::BeginChild(self.label_get().c_str(), *self.size, self.flags, self.windowFlags)); IMGUI_ITEM_VOID_FUNCTION(_imgui_end_child, IMGUI_END_CHILD, ImGui::EndChild()); @@ -407,26 +444,17 @@ IMGUI_ITEM_VALUE_FUNCTION(_imgui_slider_float, IMGUI_SLIDER_FLOAT, float, IMGUI_ITEM_STRING_FUNCTION(_imgui_input_text, IMGUI_INPUT_TEXT, (value.resize(*self.max), ImGui::InputText(self.label_get().c_str(), value.data(), *self.max, self.flags))); -static bool _imgui_begin(const ImguiItem& self) { return ImGui::Begin(self.label_get().c_str(), nullptr, self.flags); } -static void _imgui_end(void) { ImGui::End(); } +IMGUI_ITEM_BOOL_FUNCTION(_imgui_begin, IMGUI_BEGIN_WINDOW, ImGui::Begin(self.label_get().c_str(), nullptr, self.flags)); +IMGUI_ITEM_VOID_FUNCTION(_imgui_end, IMGUI_END_WINDOW, ImGui::End()); -#define IMGUI_BEGIN_OR_RETURN(item) \ - if (!_imgui_begin(item)) { \ - _imgui_end(); \ - return; \ - } - -/* IMGUI_ITEM_VALUE_FUNCTION(_imgui_radio_button, IMGUI_RADIO_BUTTON, int, ImGui::RadioButton(self.label_get().c_str(), &value, self.value)); IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_button, IMGUI_COLOR_BUTTON, vec4, ImGui::ColorButton(self.label_get().c_str(), ImVec4(value), self.flags)); - IMGUI_ITEM_VALUE_FUNCTION(_imgui_drag_float, IMGUI_DRAG_FLOAT, float, - ImGui::DragFloat(self.label_get().c_str(), &value, self.speed, *self.min, *self.max, _imgui_float_format_get(self, value))); + ImGui::DragFloat(self.label_get().c_str(), &value, self.speed, *self.min, *self.max, _imgui_float_format_get(self, value))); IMGUI_ITEM_VALUE_FUNCTION(_imgui_drag_float2, IMGUI_DRAG_FLOAT, vec2, - ImGui::DragFloat2(self.label_get().c_str(), value_ptr(value), self.speed, *self.min, *self.max, _imgui_vec2_format_get(self, value))); + ImGui::DragFloat2(self.label_get().c_str(), value_ptr(value), self.speed, *self.min, *self.max, _imgui_vec2_format_get(self, value))); IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_edit3, IMGUI_COLOR_EDIT, vec3, ImGui::ColorEdit3(self.label_get().c_str(), value_ptr(value), self.flags)); IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_edit4, IMGUI_COLOR_EDIT, vec4, ImGui::ColorEdit4(self.label_get().c_str(), value_ptr(value), self.flags)); -*/ /* IMGUI_ITEM_CHECKBOX_FUNCTION(_imgui_checkbox_selectable, _imgui_selectable(self, imgui)); @@ -438,58 +466,126 @@ IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_color_edit3, vec3, _imgui_col IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_color_edit4, vec4, _imgui_color_edit4(self, imgui, value)); */ +IMGUI_ITEM_CUSTOM_VALUE_FUNCTION(_imgui_combo, IMGUI_COMBO, int, { + std::vector cStrings; + cStrings.reserve(self.items.size()); + for (auto& [id, string] : self.items) + cStrings.emplace_back(string.c_str()); + + isActivated = ImGui::Combo(self.label_get().c_str(), &value, cStrings.data(), (int)self.items.size()); +}); + +IMGUI_ITEM_CUSTOM_VALUE_FUNCTION(_imgui_selectable_input_text, IMGUI_SELECTABLE, std::string, { + static std::string buffer{}; + static int id = ID_NONE; + ImguiItem selectable = self; + ImVec2 size = _imgui_item_size_get(selectable, IMGUI_SELECTABLE); + + if (id == self.id) { + isActivated = _imgui_input_text(IMGUI_CHANGE_INPUT_TEXT.copy({.size = size}), imgui, buffer); + imgui_contextual_actions_disable(imgui); + + if (isActivated || _imgui_is_no_click_on_item()) { + value = buffer; + buffer.clear(); + id = ID_NONE; + imgui_contextual_actions_enable(imgui); + } + } else { + isActivated = _imgui_selectable(selectable, imgui); + + if (_imgui_is_input_begin()) { + buffer = value; + buffer.resize(*IMGUI_CHANGE_INPUT_TEXT.max); + id = self.id; + ImGui::SetKeyboardFocusHere(-1); + } + } +}); + +#define IMGUI_ATLAS_VOID_FUNCTION(NAME, FUNCTION) \ + static void NAME(const ImguiItem& self, Imgui* imgui) { \ + vec2 cursorPosition = _imgui_cursor_position_get(self); \ + _imgui_image(self.copy({.textureID = imgui->resources->atlas.id, \ + .size = ATLAS_SIZE(self.atlas) * imgui->settings->displayScale, \ + .uvMin = ATLAS_UV_MIN(self.atlas), \ + .uvMax = ATLAS_UV_MAX(self.atlas), \ + .cursorPosition = cursorPosition}), \ + imgui); \ + \ + FUNCTION(self.copy({.cursorPosition = \ + cursorPosition + vec2(ATLAS_SIZE(self.atlas).x + (((_imgui_item_spacing_get(self).x + _imgui_frame_padding_get(self).x * 0.5f) * \ + imgui->settings->displayScale)), \ + 0.0f)}), \ + imgui); \ + } + +#define IMGUI_ATLAS_BOOL_FUNCTION(NAME, FUNCTION) \ + static bool NAME(const ImguiItem& self, Imgui* imgui) { \ + vec2 cursorPosition = _imgui_cursor_position_get(self); \ + _imgui_image(self.copy({.textureID = imgui->resources->atlas.id, \ + .size = ATLAS_SIZE(self.atlas) * imgui->settings->displayScale, \ + .uvMin = ATLAS_UV_MIN(self.atlas), \ + .uvMax = ATLAS_UV_MAX(self.atlas), \ + .cursorPosition = cursorPosition}), \ + imgui); \ + \ + return FUNCTION(self.copy({.cursorPosition = cursorPosition + vec2(ATLAS_SIZE(self.atlas).x + \ + (((_imgui_item_spacing_get(self).x + _imgui_frame_padding_get(self).x * 0.5f) * \ + imgui->settings->displayScale)), \ + 0.0f)}), \ + imgui); \ + } + +#define IMGUI_ATLAS_VALUE_BOOL_FUNCTION(NAME, FUNCTION, TYPE) \ + static bool NAME(const ImguiItem& self, Imgui* imgui, TYPE& value) { \ + vec2 cursorPosition = _imgui_cursor_position_get(self); \ + _imgui_image(self.copy({.textureID = imgui->resources->atlas.id, \ + .size = ATLAS_SIZE(self.atlas) * imgui->settings->displayScale, \ + .uvMin = ATLAS_UV_MIN(self.atlas), \ + .uvMax = ATLAS_UV_MAX(self.atlas), \ + .cursorPosition = cursorPosition}), \ + imgui); \ + \ + return FUNCTION(self.copy({.cursorPosition = cursorPosition + vec2(ATLAS_SIZE(self.atlas).x + \ + (((_imgui_item_spacing_get(self).x + _imgui_frame_padding_get(self).x * 0.5f) * \ + imgui->settings->displayScale)), \ + 0.0f)}), \ + imgui, value); \ + } + +IMGUI_ATLAS_VOID_FUNCTION(_imgui_atlas_text, _imgui_text); +IMGUI_ATLAS_BOOL_FUNCTION(_imgui_atlas_selectable, _imgui_selectable); +IMGUI_ATLAS_VALUE_BOOL_FUNCTION(_imgui_atlas_selectable_input_text, _imgui_selectable_input_text, std::string); + +#define IMGUI_BEGIN_OR_RETURN(item, imgui) \ + if (!_imgui_begin(item, imgui)) { \ + _imgui_end(item, imgui); \ + return; \ + } + static void _imgui_end_table(void) { ImGui::EndTable(); } static void _imgui_table_setup_column(const char* text) { ImGui::TableSetupColumn(text); } static void _imgui_table_headers_row(void) { ImGui::TableHeadersRow(); } static void _imgui_table_next_row(void) { ImGui::TableNextRow(); } static void _imgui_table_set_column_index(int index) { ImGui::TableSetColumnIndex(index); } -static bool _imgui_combo(ImguiItem self, Imgui* imgui, int* value) { - std::vector cStrings; - cStrings.reserve(self.items.size()); - for (auto& string : self.items) - cStrings.emplace_back(string.c_str()); - - _imgui_item_pre(self, IMGUI_COMBO); - - bool isActivated = ImGui::Combo(self.label_get().c_str(), value, cStrings.data(), (int)self.items.size()); - if (_imgui_is_input_default()) { - *value = self.value; - isActivated = true; - } - - _imgui_item_post(self, imgui, IMGUI_COMBO, isActivated); - - return isActivated; -}; - -static void _imgui_atlas_text(const ImguiItem& self, Imgui* imgui) { - _imgui_image(self.copy({.textureID = imgui->resources->atlas.id, - .size = ATLAS_SIZE(self.atlas) * imgui->settings->displayScale, - .uvMin = ATLAS_UV_MIN(self.atlas), - .uvMax = ATLAS_UV_MAX(self.atlas)}), - imgui); - - _imgui_text(self.copy({.cursorPosition = _imgui_cursor_position_get(self) + - vec2(ATLAS_SIZE(self.atlas).x + (_imgui_item_spacing_get(self).x * imgui->settings->displayScale), 0.0f)}), - imgui); -} - -/* IMGUI_ITEM_CUSTOM_FUNCTION(_imgui_atlas_button, IMGUI_ATLAS_BUTTON, { ImVec2 size = _imgui_item_size_get(self, type); if (self.size.has_value()) { isActivated = ImGui::Button(self.label_get().c_str(), size); + vec2 framePadding = _imgui_frame_padding_get(self) * self.scale; - ImVec2 start = ImGui::GetItemRectMin() + self.atlasOffset; - ImVec2 end = start + ImVec2(ATLAS_SIZE(self.atlas)); + vec2 atlasOffset = self.atlasOffset.has_value() ? *self.atlasOffset * self.scale : framePadding; + vec2 start = ImGui::GetItemRectMin() + atlasOffset; + vec2 atlasSize = self.isAtlasStretch ? *self.size - framePadding : ATLAS_SIZE(self.atlas); + vec2 end = start + atlasSize; ImGui::GetWindowDrawList()->AddImage(imgui->resources->atlas.id, start, end, ATLAS_UV_ARGS(self.atlas)); } else isActivated = ImGui::ImageButton(self.label_get().c_str(), imgui->resources->atlas.id, size, ATLAS_UV_ARGS(self.atlas)); }); -*/ /* static bool _imgui_selectable_input_int(const ImguiItem& self, Imgui* imgui, int& value) { @@ -520,37 +616,6 @@ static bool _imgui_selectable_input_int(const ImguiItem& self, Imgui* imgui, int return isActivated; }; - -static bool _imgui_selectable_input_text(const ImguiItem& self, Imgui* imgui, std::string& value) { - static std::string buffer{}; - static int id = ID_NONE; - ImguiItem selectable = self.copy({}); - ImVec2 size = _imgui_item_size_get(selectable, IMGUI_SELECTABLE); - bool isActivated = false; - - if (id == self.id) { - isActivated = _imgui_input_text(IMGUI_CHANGE_INPUT_TEXT.copy({.size = size}), imgui, buffer); - imgui_contextual_actions_disable(imgui); - - if (isActivated || _imgui_is_no_click_on_item()) { - value = buffer; - buffer.clear(); - id = ID_NONE; - imgui_contextual_actions_enable(imgui); - } - } else { - isActivated = _imgui_selectable(selectable, imgui); - - if (_imgui_is_input_begin()) { - buffer = value; - buffer.resize(IMGUI_CHANGE_INPUT_TEXT.max); - id = self.id; - ImGui::SetKeyboardFocusHere(-1); - } - } - - return isActivated; -}; */ static bool _imgui_confirm_popup(ImguiItem self, Imgui* imgui, ImguiPopupState* state = nullptr, bool isOnlyConfirm = false) { @@ -598,6 +663,7 @@ static void _imgui_no_anm2_path_check(Imgui* self) { static void _imgui_no_anm2_path_click_check(Imgui* self) { if (_imgui_is_window_hovered_and_click() && self->anm2->path.empty() && !imgui_is_any_popup_open()) imgui_open_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION.label); + _imgui_confirm_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION, self, nullptr, true); } static void _imgui_context_menu(Imgui* self) { @@ -608,7 +674,10 @@ static void _imgui_context_menu(Imgui* self) { imgui_open_popup(IMGUI_CONTEXT_MENU.label_get()); if (imgui_begin_popup(IMGUI_CONTEXT_MENU.label_get(), self)) { - _imgui_selectable(IMGUI_CUT, self); + if (_imgui_selectable(IMGUI_CUT, self)) { + if (self->clipboard->type == CLIPBOARD_ANIMATION) + self->selectedAnimationIndices = {}; + } _imgui_selectable(IMGUI_COPY, self); _imgui_selectable(IMGUI_PASTE.copy({.isDisabled = !clipboard_is_value()}), self); @@ -1002,7 +1071,7 @@ static void _imgui_timeline(Imgui* self) { if (_imgui_is_window_hovered()) { hoverReference = reference; hoverReference.frameIndex = anm2_frame_index_from_time(self->anm2, reference, frameTime); - self->clipboard->location = hoverReference; + self->clipboard->destination = hoverReference; self->clipboard->type = CLIPBOARD_FRAME; if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) { @@ -1387,16 +1456,13 @@ static void _imgui_timeline(Imgui* self) { _imgui_end(); // IMGUI_TIMELINE } + */ static void _imgui_onionskin(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_ONIONSKIN); + IMGUI_BEGIN_OR_RETURN(IMGUI_ONIONSKIN, self); - static auto& isEnabled = self->settings->onionskinIsEnabled; - static auto& beforeCount = self->settings->onionskinBeforeCount; - static auto& afterCount = self->settings->onionskinAfterCount; - static auto& beforeColorOffset = self->settings->onionskinBeforeColorOffset; - static auto& afterColorOffset = self->settings->onionskinAfterColorOffset; - static auto& drawOrder = self->settings->onionskinDrawOrder; + bool isEnabled = self->settings->onionskinIsEnabled; + int drawOrder = self->settings->onionskinDrawOrder; _imgui_checkbox(IMGUI_ONIONSKIN_ENABLED, self, isEnabled); @@ -1408,8 +1474,8 @@ static void _imgui_onionskin(Imgui* self) { ImGui::PopID(); }; - onionskin_section(IMGUI_ONIONSKIN_BEFORE, beforeCount, beforeColorOffset); - onionskin_section(IMGUI_ONIONSKIN_AFTER, afterCount, afterColorOffset); + onionskin_section(IMGUI_ONIONSKIN_BEFORE, self->settings->onionskinBeforeCount, self->settings->onionskinBeforeColorOffset); + onionskin_section(IMGUI_ONIONSKIN_AFTER, self->settings->onionskinAfterCount, self->settings->onionskinAfterColorOffset); ImGui::Separator(); @@ -1417,24 +1483,21 @@ static void _imgui_onionskin(Imgui* self) { _imgui_radio_button(IMGUI_ONIONSKIN_BELOW.copy({.isDisabled = !isEnabled}), self, drawOrder); _imgui_radio_button(IMGUI_ONIONSKIN_ABOVE.copy({.isDisabled = !isEnabled}), self, drawOrder); - _imgui_end(); // IMGUI_ONIONSKIN + _imgui_end(IMGUI_ONIONSKIN, self); } -*/ static void _imgui_taskbar(Imgui* self) { static ImguiPopupState exitConfirmState = IMGUI_POPUP_STATE_CLOSED; - static float& displayScale = self->settings->displayScale; - + static float displayScale = self->settings->displayScale; ImGuiViewport* viewport = ImGui::GetMainViewport(); - ImguiItem taskbar = IMGUI_TASKBAR; - ImGui::SetNextWindowSize({viewport->Size.x, IMGUI_TASKBAR.size->y * displayScale}); - ImGui::SetNextWindowPos(viewport->Pos); - _imgui_begin(taskbar); + + ImguiItem taskbar = IMGUI_TASKBAR.copy({.position = viewport->Pos, .size = vec2(viewport->Size.x, IMGUI_TASKBAR.size->y * displayScale)}); + _imgui_begin(taskbar, self); Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); Anm2Item* item = anm2_item_from_reference(self->anm2, *self->reference); - _imgui_selectable(IMGUI_FILE, self); + _imgui_selectable(IMGUI_FILE.copy({.isSelected = imgui_is_popup_open(IMGUI_FILE.popup)}), self); if (imgui_begin_popup(IMGUI_FILE.popup, self)) { _imgui_selectable(IMGUI_NEW, self); @@ -1474,7 +1537,7 @@ static void _imgui_taskbar(Imgui* self) { break; } - _imgui_selectable(IMGUI_WIZARD.copy({}), self); + _imgui_selectable(IMGUI_WIZARD.copy({.isSelected = imgui_is_popup_open(IMGUI_WIZARD.popup)}), self); if (imgui_begin_popup(IMGUI_WIZARD.popup, self)) { _imgui_selectable(IMGUI_GENERATE_ANIMATION_FROM_GRID.copy({.isDisabled = !item || (self->reference->itemType != ANM2_LAYER)}), self); @@ -1666,7 +1729,7 @@ static void _imgui_taskbar(Imgui* self) { } _imgui_input_text(IMGUI_RENDER_ANIMATION_FFMPEG_PATH, self, ffmpegPath); - _imgui_combo(IMGUI_RENDER_ANIMATION_OUTPUT, self, &type); + _imgui_combo(IMGUI_RENDER_ANIMATION_OUTPUT, self, type); _imgui_input_text(IMGUI_RENDER_ANIMATION_FORMAT.copy({.isDisabled = type != RENDER_PNG}), self, format); _imgui_checkbox(IMGUI_RENDER_ANIMATION_IS_USE_ANIMATION_BOUNDS, self, isUseAnimationBounds); _imgui_input_float(IMGUI_RENDER_ANIMATION_SCALE.copy({.isDisabled = !isUseAnimationBounds}), self, scale); @@ -1797,7 +1860,7 @@ static void _imgui_taskbar(Imgui* self) { imgui_end_popup(self); } - _imgui_selectable(IMGUI_PLAYBACK.copy({}), self); + _imgui_selectable(IMGUI_PLAYBACK.copy({.isSelected = imgui_is_popup_open(IMGUI_PLAYBACK.popup)}), self); if (imgui_begin_popup(IMGUI_PLAYBACK.popup, self, IMGUI_PLAYBACK.popupSize)) { /* @@ -1807,7 +1870,7 @@ static void _imgui_taskbar(Imgui* self) { imgui_end_popup(self); } - _imgui_selectable(IMGUI_SETTINGS.copy({}), self); + _imgui_selectable(IMGUI_SETTINGS.copy({.isSelected = imgui_is_popup_open(IMGUI_SETTINGS.popup)}), self); /* if (imgui_begin_popup(IMGUI_SETTINGS.popup, self, IMGUI_SETTINGS.popupSize)) { @@ -1887,170 +1950,170 @@ static void _imgui_taskbar(Imgui* self) { imgui_end_popup(self); } - _imgui_end(); + _imgui_end(taskbar, self); } -/* static void _imgui_tools(Imgui* self) { - ImGuiStyle style = ImGui::GetStyle(); - - IMGUI_BEGIN_OR_RETURN(IMGUI_TOOLS); + IMGUI_BEGIN_OR_RETURN(IMGUI_TOOLS, self); + float displayScale = self->settings->displayScale; float availableWidth = ImGui::GetContentRegionAvail().x; - float usedWidth = style.FramePadding.x; + float usedWidth = ImGui::GetStyle().FramePadding.x; for (int i = 0; i < TOOL_COUNT; i++) { - ImguiItem item = *IMGUI_TOOL_ITEMS[i]; + + ImguiItem item = IMGUI_TOOL_ITEMS[i]->copy( + {.scale = displayScale, + .isDisabled = (i == TOOL_UNDO && self->snapshots->undoStack.empty()) || (i == TOOL_REDO && self->snapshots->redoStack.empty()), + .isSelected = self->settings->tool == (ToolType)i}); if (i > 0 && usedWidth + ImGui::GetItemRectSize().x < availableWidth) ImGui::SameLine(); else usedWidth = 0; - item.isSelected = self->settings->tool == (ToolType)i; - - switch ((ToolType)i) { - case TOOL_UNDO: - item.isDisabled = self->snapshots->undoStack.is_empty(); - break; - case TOOL_REDO: - item.isDisabled = self->snapshots->redoStack.is_empty(); - break; - default: - break; - } - - if (i != TOOL_COLOR) - _imgui_atlas_button(item, self); - else + if (i == TOOL_COLOR) _imgui_color_edit4(item, self, self->settings->toolColor); + else + _imgui_atlas_button(item, self); - usedWidth += ImGui::GetItemRectSize().x + style.ItemSpacing.x; + usedWidth += ImGui::GetItemRectSize().x + ImGui::GetStyle().ItemSpacing.x; } - _imgui_end(); // IMGUI_TOOLS + _imgui_end(IMGUI_TOOLS, self); } static void _imgui_layers(Imgui* self) { - static int selectedLayerID = ID_NONE; - - IMGUI_BEGIN_OR_RETURN(IMGUI_LAYERS); + IMGUI_BEGIN_OR_RETURN(IMGUI_LAYERS, self); _imgui_no_anm2_path_click_check(self); - ImVec2 size = ImGui::GetContentRegionAvail(); + vec2 footerSize = {0, (ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f)}; + vec2 childSize = ImGui::GetContentRegionAvail() - footerSize; - _imgui_begin_child(IMGUI_LAYERS_CHILD.copy({.size = vec2(size.x, size.y - IMGUI_FOOTER_CHILD.size->y)}), self); + ImguiItem layersChild = IMGUI_LAYERS_CHILD.copy({.size = childSize}); + _imgui_begin_child(layersChild, self); for (auto& [id, layer] : self->anm2->layers) { ImGui::PushID(id); - ImguiItem layerItem = IMGUI_LAYER.copy({.label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), - .size = vec2(ImGui::GetContentRegionAvail().x - (IMGUI_LAYER_SPRITESHEET_ID.size->x * 2.0f), 0), - .isSelected = selectedLayerID == id, - .id = id}); + ImguiItem layerItem = IMGUI_LAYER.copy({.label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), .isSelected = self->selectedLayerID == id, .id = id}); if (_imgui_atlas_selectable_input_text(layerItem, self, layer.name)) - selectedLayerID = id; - - ImGui::SameLine(); + self->selectedLayerID = id; + /* ImguiItem spritesheetItem = - IMGUI_LAYER_SPRITESHEET_ID.copy({.label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), .isSelected = selectedLayerID == id, .id = id}); + IMGUI_LAYER_SPRITESHEET_ID.copy({.label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), .isSelected = self->selectedLayerID == id, .id = id}); _imgui_atlas_selectable_input_int(spritesheetItem, self, layer.spritesheetID); + */ ImGui::PopID(); }; - _imgui_end_child(); // layersChild + _imgui_end_child(layersChild, self); - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); + ImguiItem footerChild = IMGUI_FOOTER_CHILD.copy({.size = footerSize}); + _imgui_begin_child(footerChild, self); if (_imgui_button(IMGUI_LAYER_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) - selectedLayerID = anm2_layer_add(self->anm2); + self->selectedLayerID = anm2_layer_add(self->anm2); - if (_imgui_button(IMGUI_LAYER_REMOVE.copy({.isDisabled = selectedLayerID == ID_NONE}), self)) { - anm2_layer_remove(self->anm2, selectedLayerID); - selectedLayerID = ID_NONE; + if (_imgui_button(IMGUI_LAYER_REMOVE.copy({.isDisabled = self->selectedLayerID == ID_NONE}), self)) { + anm2_layer_remove(self->anm2, self->selectedLayerID); + self->selectedLayerID = ID_NONE; } - _imgui_end_child(); // IMGUI_FOOTER_CHILD - _imgui_end(); // IMGUI_LAYERS + _imgui_end_child(footerChild, self); + _imgui_end(IMGUI_LAYERS, self); } static void _imgui_nulls(Imgui* self) { - static int selectedNullID = ID_NONE; - - IMGUI_BEGIN_OR_RETURN(IMGUI_NULLS); + IMGUI_BEGIN_OR_RETURN(IMGUI_NULLS, self); _imgui_no_anm2_path_click_check(self); - ImVec2 size = ImGui::GetContentRegionAvail(); + vec2 footerSize = {0, (ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f)}; + vec2 childSize = ImGui::GetContentRegionAvail() - footerSize; - _imgui_begin_child(IMGUI_NULLS_CHILD.copy({.size = vec2(size.x, size.y - IMGUI_FOOTER_CHILD.size->y)}), self); + ImguiItem nullsChild = IMGUI_NULLS_CHILD.copy({.size = childSize}); + _imgui_begin_child(nullsChild, self); for (auto& [id, null] : self->anm2->nulls) { ImGui::PushID(id); - ImguiItem nullItem = IMGUI_NULL.copy({.label = std::format(IMGUI_NULL_FORMAT, id, null.name), .isSelected = selectedNullID == id, .id = id}); + ImguiItem nullItem = IMGUI_NULL.copy({.label = std::format(IMGUI_NULL_FORMAT, id, null.name), .isSelected = self->selectedNullID == id, .id = id}); if (_imgui_atlas_selectable_input_text(nullItem, self, null.name)) - selectedNullID = id; + self->selectedNullID = id; ImGui::PopID(); }; - _imgui_end_child(); // nullsChild + _imgui_end_child(nullsChild, self); // nullsChild - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); + ImguiItem footerChild = IMGUI_FOOTER_CHILD.copy({.size = footerSize}); + _imgui_begin_child(footerChild, self); if (_imgui_button(IMGUI_NULL_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) - selectedNullID = anm2_null_add(self->anm2); + self->selectedNullID = anm2_null_add(self->anm2); - if (_imgui_button(IMGUI_NULL_REMOVE.copy({.isDisabled = selectedNullID == ID_NONE}), self)) { - anm2_null_remove(self->anm2, selectedNullID); - selectedNullID = ID_NONE; + if (_imgui_button(IMGUI_NULL_REMOVE.copy({.isDisabled = self->selectedNullID == ID_NONE}), self)) { + anm2_null_remove(self->anm2, self->selectedNullID); + self->selectedNullID = ID_NONE; } - _imgui_end_child(); // IMGUI_FOOTER_CHILD - _imgui_end(); // IMGUI_NULLS + _imgui_end_child(footerChild, self); + _imgui_end(IMGUI_NULLS, self); } static void _imgui_animations(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATIONS); + IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATIONS, self); _imgui_no_anm2_path_click_check(self); - ImVec2 size = ImGui::GetContentRegionAvail(); + vec2 footerSize = {0, (ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f)}; + vec2 childSize = ImGui::GetContentRegionAvail() - footerSize; + ImguiItem animationsChild = IMGUI_ANIMATIONS_CHILD.copy({.size = childSize}); - _imgui_begin_child(IMGUI_ANIMATIONS_CHILD.copy({.size = vec2(size.x, size.y - IMGUI_FOOTER_CHILD.size->y)}), self); + _imgui_begin_child(animationsChild, self); - for (auto& [id, animation] : self->anm2->animations) { - ImGui::PushID(id); + for (auto [i, animation] : std::views::enumerate(self->anm2->animations)) { + ImGui::PushID(i); - ImguiItem animationItem = - IMGUI_ANIMATION.copy({.label = self->anm2->defaultAnimationID == id ? std::format(IMGUI_ANIMATION_DEFAULT_FORMAT, animation.name) : animation.name, - .isSelected = self->reference->animationID == id, - .id = id}); + bool isDefaultAnimation = self->anm2->defaultAnimation == animation.name; + bool isReferenceAnimation = self->reference->animationIndex == i; - if (_imgui_atlas_selectable_input_text(animationItem, self, animation.name)) - *self->reference = {id}; + ImguiItem animationItem = IMGUI_ANIMATION.copy({.label = animation.name, + .tooltip = animation.name, + .size = vec2(childSize.x, 0), + .isSelected = self->selectedAnimationIndices.contains(i), + .id = i, + .font = isDefaultAnimation && isReferenceAnimation ? self->fonts[FONT_BOLD_ITALICS] + : isDefaultAnimation ? self->fonts[FONT_BOLD] + : isReferenceAnimation ? self->fonts[FONT_ITALICS] + : self->fonts[FONT_REGULAR]}); + + if (_imgui_atlas_selectable_input_text(animationItem, self, animation.name)) { + set_list(self->selectedAnimationIndices, (int)i, ImGui::IsKeyDown(ImGuiMod_Ctrl), ImGui::IsKeyDown(ImGuiMod_Shift), &self->lastAnimationIndex); + if (!ImGui::IsKeyDown(ImGuiMod_Ctrl) && !ImGui::IsKeyDown(ImGuiMod_Shift)) + *self->reference = {(int)i}; + } if (ImGui::IsItemHovered()) { self->clipboard->type = CLIPBOARD_ANIMATION; - self->clipboard->location = (int)id; + self->clipboard->destination = (int)i; + self->clipboard->source = self->selectedAnimationIndices; } if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - if (ImGui::IsDragDropActive()) - ImGui::SetNextItemWidth(_imgui_item_size_get(animationItem, IMGUI_SELECTABLE).x); - ImGui::SetDragDropPayload(animationItem.drag_drop_get(), &id, sizeof(int)); - _imgui_atlas_selectable(animationItem, self); + ImGui::SetDragDropPayload(animationItem.drag_drop_get(), &i, sizeof(int)); + _imgui_atlas_selectable(animationItem.copy({.size = vec2(childSize.x, 0)}), self); ImGui::EndDragDropSource(); } if (ImGui::BeginDragDropTarget()) { if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(animationItem.drag_drop_get())) { - int sourceID = *(int*)payload->Data; - if (sourceID != id) { - imgui_snapshot(self, IMGUI_ACTION_ANIMATION_SWAP); - map_swap(self->anm2->animations, sourceID, id); + int sourceIndex = *(int*)payload->Data; + if (sourceIndex != i) { + imgui_snapshot(self, IMGUI_ACTION_ANIMATION_MOVE); + vector_move(self->anm2->animations, sourceIndex, i); } } @@ -2058,83 +2121,44 @@ static void _imgui_animations(Imgui* self) { } ImGui::PopID(); - }; + } _imgui_context_menu(self); - _imgui_end_child(); // animationsChild + _imgui_end_child(animationsChild, self); Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); + ImguiItem footerChild = IMGUI_FOOTER_CHILD.copy({.size = footerSize}); + _imgui_begin_child(footerChild, self); - if (_imgui_button(IMGUI_ANIMATION_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) { - int id = anm2_animation_add(self->anm2); - self->reference->animationID = id; - - if (self->anm2->animations.size() == 1) - self->anm2->defaultAnimationID = id; - } + if (_imgui_button(IMGUI_ANIMATION_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) + self->reference->animationIndex = anm2_animation_add(self->anm2); if (_imgui_button(IMGUI_ANIMATION_DUPLICATE.copy({.isDisabled = !animation}), self)) - self->reference->animationID = anm2_animation_add(self->anm2, animation, self->reference->animationID); + self->reference->animationIndex = anm2_animation_add(self->anm2, animation, self->reference->animationIndex); - _imgui_button(IMGUI_ANIMATION_MERGE.copy({.isDisabled = !animation}), self); + _imgui_button(IMGUI_ANIMATION_MERGE.copy({.isDisabled = !animation || self->reference->animationIndex == INDEX_NONE}), self); if (imgui_begin_popup_modal(IMGUI_ANIMATION_MERGE.popup, self, IMGUI_ANIMATION_MERGE.popupSize)) { - const bool isModCtrl = ImGui::IsKeyDown(IMGUI_INPUT_CTRL); - const bool isModShift = ImGui::IsKeyDown(IMGUI_INPUT_SHIFT); static bool& isDeleteAnimationsAfter = self->settings->mergeIsDeleteAnimationsAfter; - static int lastClickedID = ID_NONE; static int& mergeType = self->settings->mergeType; - static size_t lastAnimationCount = 0; - static std::vector animationIDs; - static std::vector sortedIDs; - - if (self->anm2->animations.size() != lastAnimationCount) { - sortedIDs.clear(); - for (const auto& [id, _] : self->anm2->animations) - sortedIDs.push_back(id); - std::sort(sortedIDs.begin(), sortedIDs.end()); - lastAnimationCount = self->anm2->animations.size(); - } + static std::set selectedMergeIndices; + static int lastMergeAnimationIndex = INDEX_NONE; _imgui_begin_child(IMGUI_MERGE_ANIMATIONS_CHILD, self); - for (const auto& [id, animation] : self->anm2->animations) { - ImGui::PushID(id); + for (auto [i, animation] : std::views::enumerate(self->anm2->animations)) { + ImGui::PushID(i); - if (_imgui_atlas_selectable(IMGUI_ANIMATION.copy({.label = animation.name, .isSelected = vector_find(animationIDs, id)}), self)) { - if (isModCtrl) { - auto it = std::find(animationIDs.begin(), animationIDs.end(), id); - if (it != animationIDs.end()) - animationIDs.erase(it); - else - animationIDs.push_back(id); - - lastClickedID = id; - } else if (isModShift) { - auto it1 = std::find(sortedIDs.begin(), sortedIDs.end(), lastClickedID); - auto it2 = std::find(sortedIDs.begin(), sortedIDs.end(), id); - if (it1 != sortedIDs.end() && it2 != sortedIDs.end()) { - auto begin = std::min(it1, it2); - auto end = std::max(it1, it2); - for (auto it = begin; it <= end; ++it) { - if (std::find(animationIDs.begin(), animationIDs.end(), *it) == animationIDs.end()) - animationIDs.push_back(*it); - } - } - } else { - animationIDs.clear(); - animationIDs.push_back(id); - lastClickedID = id; - } + if (_imgui_atlas_selectable(IMGUI_ANIMATION.copy({.label = animation.name, .isSelected = selectedMergeIndices.contains(i)}), self)) { + set_list(selectedMergeIndices, (int)i, ImGui::IsKeyDown(ImGuiMod_Ctrl), ImGui::IsKeyDown(ImGuiMod_Shift), &lastMergeAnimationIndex); } ImGui::PopID(); } - _imgui_end_child(); // IMGUI_MERGE_ANIMATIONS_CHILD + _imgui_end_child(IMGUI_MERGE_ANIMATIONS_CHILD, self); _imgui_begin_child(IMGUI_MERGE_ON_CONFLICT_CHILD, self); _imgui_text(IMGUI_MERGE_ON_CONFLICT, self); @@ -2142,28 +2166,26 @@ static void _imgui_animations(Imgui* self) { _imgui_radio_button(IMGUI_MERGE_REPLACE_FRAMES, self, mergeType); _imgui_radio_button(IMGUI_MERGE_PREPEND_FRAMES, self, mergeType); _imgui_radio_button(IMGUI_MERGE_IGNORE, self, mergeType); - _imgui_end_child(); // IMGUI_MERGE_ON_CONFLICT_CHILD + _imgui_end_child(IMGUI_MERGE_ON_CONFLICT_CHILD, self); _imgui_begin_child(IMGUI_MERGE_OPTIONS_CHILD, self); _imgui_checkbox(IMGUI_MERGE_DELETE_ANIMATIONS_AFTER, self, isDeleteAnimationsAfter); - _imgui_end_child(); // IMGUI_MERGE_OPTIONS_CHILD + _imgui_end_child(IMGUI_MERGE_OPTIONS_CHILD, self); - if (_imgui_button(IMGUI_MERGE_CONFIRM.copy({.isDisabled = animationIDs.empty()}), self)) { - anm2_animation_merge(self->anm2, self->reference->animationID, animationIDs, (Anm2MergeType)mergeType); + if (_imgui_button(IMGUI_MERGE_CONFIRM.copy({.isDisabled = selectedMergeIndices.empty()}), self)) { + anm2_animation_merge(self->anm2, self->reference->animationIndex, self->selectedAnimationIndices, (Anm2MergeType)mergeType); if (isDeleteAnimationsAfter) - for (int id : animationIDs) - if (id != self->reference->animationID) - self->anm2->animations.erase(id); + anm2_animations_remove(self->anm2, selectedMergeIndices); - animationIDs.clear(); + selectedMergeIndices.clear(); imgui_close_current_popup(self); } if (_imgui_button(IMGUI_POPUP_CANCEL, self)) { - animationIDs.clear(); + selectedMergeIndices.clear(); imgui_close_current_popup(self); } @@ -2171,83 +2193,84 @@ static void _imgui_animations(Imgui* self) { } if (_imgui_button(IMGUI_ANIMATION_REMOVE.copy({.isDisabled = !animation}), self)) { - anm2_animation_remove(self->anm2, self->reference->animationID); + anm2_animations_remove(self->anm2, self->selectedAnimationIndices); *self->reference = Anm2Reference(); + self->selectedAnimationIndices = {}; } if (_imgui_button(IMGUI_ANIMATION_DEFAULT.copy({.isDisabled = !animation}), self)) - self->anm2->defaultAnimationID = self->reference->animationID; + self->anm2->defaultAnimation = animation->name; - _imgui_end_child(); // IMGUI_FOOTER_CHILD - _imgui_end(); // IMGUI_ANIMATIONS + _imgui_end_child(footerChild, self); + _imgui_end(IMGUI_ANIMATIONS, self); } static void _imgui_events(Imgui* self) { - static int selectedID = ID_NONE; - - IMGUI_BEGIN_OR_RETURN(IMGUI_EVENTS); + IMGUI_BEGIN_OR_RETURN(IMGUI_EVENTS, self); _imgui_no_anm2_path_click_check(self); - ImVec2 windowSize = ImGui::GetContentRegionAvail(); + vec2 footerSize = {0, (ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f)}; + vec2 childSize = ImGui::GetContentRegionAvail() - footerSize; + ImguiItem eventsChild = IMGUI_EVENTS_CHILD.copy({.size = childSize}); + _imgui_begin_child(eventsChild, self); - _imgui_begin_child(IMGUI_EVENTS_CHILD.copy({.size = vec2(windowSize.x, windowSize.y - IMGUI_FOOTER_CHILD.size->y)}), self); - - std::function event_item = [&](int id, Anm2Event& event) { + for (auto [id, event] : self->anm2->events) { ImGui::PushID(id); - if (_imgui_atlas_selectable_input_text(IMGUI_EVENT.copy({.label = event.name, .isSelected = id == selectedID, .id = id}), self, event.name)) - selectedID = id; + ImguiItem eventItem = IMGUI_EVENT.copy({.label = event.name, .isSelected = id == self->selectedEventID, .id = id}); + + if (_imgui_atlas_selectable_input_text(eventItem, self, event.name)) + self->selectedEventID = id; ImGui::PopID(); - }; + } - for (auto& [id, event] : self->anm2->events) - event_item(id, event); + _imgui_end_child(eventsChild, self); - _imgui_end_child(); // eventsChild - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); + ImguiItem footerChild = IMGUI_FOOTER_CHILD.copy({.size = footerSize}); + _imgui_begin_child(footerChild, self); if (_imgui_button(IMGUI_EVENTS_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) { int id = map_next_id_get(self->anm2->events); self->anm2->events[id] = Anm2Event{}; - selectedID = id; + self->selectedEventID = id; } - if (_imgui_button(IMGUI_EVENTS_REMOVE_UNUSED.copy({.isDisabled = self->anm2->events.empty()}), self)) { - std::unordered_set usedEventIDs; + std::unordered_set eventIDs = map_keys_to_set(self->anm2->events); - for (auto& [id, animation] : self->anm2->animations) - for (auto& trigger : animation.triggers.frames) - if (trigger.eventID != ID_NONE) - usedEventIDs.insert(trigger.eventID); + std::unordered_set usedEventIDs; + for (auto& animation : self->anm2->animations) + for (auto& frame : animation.triggers.frames) + if (frame.eventID != ID_NONE) + usedEventIDs.insert(frame.eventID); - for (auto it = self->anm2->events.begin(); it != self->anm2->events.end();) { - if (!usedEventIDs.count(it->first)) - it = self->anm2->events.erase(it); - else - it++; - } + std::unordered_set unusedEventIDs = set_symmetric_difference(eventIDs, usedEventIDs); + + if (_imgui_button(IMGUI_EVENTS_REMOVE_UNUSED.copy({.isDisabled = unusedEventIDs.empty()}), self)) { + for (auto& id : unusedEventIDs) + self->anm2->events.erase(id); + imgui_log_push(self, IMGUI_LOG_REMOVE_UNUSED_EVENTS); } - _imgui_end_child(); // IMGUI_ANIMATIONS_OPTIONS_CHILD) - _imgui_end(); // IMGUI_EVENTS + _imgui_end_child(footerChild, self); + _imgui_end(IMGUI_EVENTS, self); } -*/ static void _imgui_spritesheets(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEETS); + IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEETS, self); _imgui_no_anm2_path_click_check(self); - static std::unordered_set selectedIDs; float displayScale = self->settings->displayScale; - vec2 childSize = ImGui::GetContentRegionAvail() - *IMGUI_SPRITESHEETS_FOOTER_CHILD.size * displayScale; + vec2 footerSize = {0, ((ImGui::GetTextLineHeightWithSpacing() * 2.0f) + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f + + ImGui::GetStyle().ItemSpacing.y)}; + vec2 childSize = ImGui::GetContentRegionAvail() - footerSize; + vec2 spritesheetSize = *IMGUI_SPRITESHEET_PREVIEW.size * displayScale; _imgui_begin_child(IMGUI_SPRITESHEETS_CHILD.copy({.size = childSize}), self); std::function spritesheet_draw = [&](int id, Anm2Spritesheet& spritesheet) { ImGui::PushID(id); - vec2 itemSize = {childSize.x, IMGUI_SPRITESHEET_PREVIEW.size->y}; + vec2 itemSize = {childSize.x, spritesheetSize.y}; _imgui_begin_child(IMGUI_SPRITESHEET_CHILD.copy({.size = itemSize}), self); Texture& texture = spritesheet.texture; @@ -2255,12 +2278,9 @@ static void _imgui_spritesheets(Imgui* self) { ImVec2 cursorPos = ImGui::GetCursorPos(); - if (_imgui_selectable(IMGUI_SPRITESHEET.copy({.tooltip = spritesheet.path, .size = itemSize, .isSelected = selectedIDs.contains(id)}), self)) { - if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) - unordered_set_id_toggle(selectedIDs, id); - else - selectedIDs = {id}; - } + if (_imgui_selectable(IMGUI_SPRITESHEET.copy({.tooltip = spritesheet.path, .size = itemSize, .isSelected = self->selectedSpritesheetIDs.contains(id)}), + self)) + set_list(self->selectedSpritesheetIDs, id, ImGui::IsKeyDown(ImGuiMod_Ctrl), ImGui::IsKeyDown(ImGuiMod_Shift), &self->lastSpritesheetID); if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { ImGui::SetDragDropPayload(IMGUI_SPRITESHEET.drag_drop_get(), &id, sizeof(int)); @@ -2279,13 +2299,13 @@ static void _imgui_spritesheets(Imgui* self) { ImGui::EndDragDropTarget(); } - ImVec2 spritesheetPreviewSize = *IMGUI_SPRITESHEET_PREVIEW.size; + vec2 spritesheetPreviewSize = spritesheetSize; float spritesheetAspect = (float)texture.size.x / texture.size.y; - if ((IMGUI_SPRITESHEET_PREVIEW.size->x / IMGUI_SPRITESHEET_PREVIEW.size->y) > spritesheetAspect) - spritesheetPreviewSize.x = IMGUI_SPRITESHEET_PREVIEW.size->y * spritesheetAspect; + if ((spritesheetSize.x / spritesheetSize.y) > spritesheetAspect) + spritesheetPreviewSize.x = spritesheetSize.y * spritesheetAspect; else - spritesheetPreviewSize.y = IMGUI_SPRITESHEET_PREVIEW.size->x / spritesheetAspect; + spritesheetPreviewSize.y = spritesheetSize.x / spritesheetAspect; _imgui_image(IMGUI_SPRITESHEET_PREVIEW.copy({.textureID = isInvalid ? self->resources->atlas.id : spritesheet.texture.id, .size = spritesheetPreviewSize, @@ -2294,10 +2314,10 @@ static void _imgui_spritesheets(Imgui* self) { .cursorPosition = cursorPos}), self); - _imgui_atlas_text(IMGUI_SPRITESHEET_TEXT.copy({.label = std::format(IMGUI_SPRITESHEET_FORMAT, id, spritesheet.path), - .cursorPosition = vec2(IMGUI_SPRITESHEET_PREVIEW.size->x, - (IMGUI_SPRITESHEET_PREVIEW.size->y * 0.5f) - (ImGui::GetTextLineHeight() * 0.5f))}), - self); + _imgui_atlas_text( + IMGUI_SPRITESHEET_TEXT.copy({.label = std::format(IMGUI_SPRITESHEET_FORMAT, id, spritesheet.path), + .cursorPosition = vec2(spritesheetSize.x, (spritesheetSize.y * 0.5f) - (ImGui::GetTextLineHeight() * 0.5f))}), + self); _imgui_end_child(IMGUI_SPRITESHEET_CHILD, self); ImGui::PopID(); @@ -2308,7 +2328,7 @@ static void _imgui_spritesheets(Imgui* self) { _imgui_end_child(IMGUI_SPRITESHEETS_CHILD, self); - _imgui_begin_child(IMGUI_SPRITESHEETS_FOOTER_CHILD.copy({.size = *IMGUI_SPRITESHEETS_FOOTER_CHILD.size * displayScale}), self); + _imgui_begin_child(IMGUI_SPRITESHEETS_FOOTER_CHILD.copy({.size = footerSize}), self); if (_imgui_button(IMGUI_SPRITESHEET_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) dialog_spritesheet_add(self->dialog); @@ -2318,8 +2338,8 @@ static void _imgui_spritesheets(Imgui* self) { dialog_reset(self->dialog); } - if (_imgui_button(IMGUI_SPRITESHEETS_RELOAD.copy({.isDisabled = selectedIDs.empty()}), self)) { - for (auto& id : selectedIDs) { + if (_imgui_button(IMGUI_SPRITESHEETS_RELOAD.copy({.isDisabled = self->selectedSpritesheetIDs.empty()}), self)) { + for (auto& id : self->selectedSpritesheetIDs) { WorkingDirectory workingDirectory(self->anm2->path); Texture texture; texture_from_path_init(&texture, self->anm2->spritesheets[id].path); @@ -2328,8 +2348,8 @@ static void _imgui_spritesheets(Imgui* self) { imgui_log_push(self, IMGUI_LOG_RELOAD_SPRITESHEET); } - if (_imgui_button(IMGUI_SPRITESHEETS_REPLACE.copy({.isDisabled = selectedIDs.size() > 1}), self)) - dialog_spritesheet_replace(self->dialog, *selectedIDs.begin()); + if (_imgui_button(IMGUI_SPRITESHEETS_REPLACE.copy({.isDisabled = self->selectedSpritesheetIDs.size() != 1}), self)) + dialog_spritesheet_replace(self->dialog, *self->selectedSpritesheetIDs.begin()); if (self->dialog->isSelected && self->dialog->type == DIALOG_SPRITESHEET_REPLACE) { @@ -2342,34 +2362,35 @@ static void _imgui_spritesheets(Imgui* self) { Texture texture; texture_from_path_init(&texture, spritesheetPath); self->anm2->spritesheets[self->dialog->replaceID].texture = texture; + imgui_log_push(self, std::format(IMGUI_LOG_REPLACE_SPRITESHEET, self->dialog->replaceID, spritesheetPath)); dialog_reset(self->dialog); } - if (_imgui_button(IMGUI_SPRITESHEETS_REMOVE_UNUSED.copy({.isDisabled = self->anm2->spritesheets.empty()}), self)) { - std::unordered_set usedSpritesheetIDs; + std::unordered_set spritesheetIDs = map_keys_to_set(self->anm2->spritesheets); - for (auto& [layerID, layer] : self->anm2->layers) - if (layer.spritesheetID != ID_NONE) - usedSpritesheetIDs.insert(layer.spritesheetID); + std::unordered_set usedSpritesheetIDs; + for (auto& [layerID, layer] : self->anm2->layers) + usedSpritesheetIDs.insert(layer.spritesheetID); - for (auto it = self->anm2->spritesheets.begin(); it != self->anm2->spritesheets.end();) { - if (!usedSpritesheetIDs.count(it->first)) { - texture_free(&self->anm2->spritesheets[it->first].texture); - it = self->anm2->spritesheets.erase(it); - } else - it++; + std::unordered_set unusedSpritesheetIDs = set_symmetric_difference(spritesheetIDs, usedSpritesheetIDs); + + if (_imgui_button(IMGUI_SPRITESHEETS_REMOVE_UNUSED.copy({.isDisabled = unusedSpritesheetIDs.empty()}), self)) { + for (auto& id : unusedSpritesheetIDs) { + texture_free(&self->anm2->spritesheets[id].texture); + self->anm2->spritesheets.erase(id); } + imgui_log_push(self, IMGUI_LOG_REMOVE_UNUSED_SPRITESHEETS); } - if (_imgui_button(IMGUI_SPRITESHEETS_SELECT_ALL.copy({.isDisabled = selectedIDs.size() == self->anm2->spritesheets.size()}), self)) + if (_imgui_button(IMGUI_SPRITESHEETS_SELECT_ALL.copy({.isDisabled = self->selectedSpritesheetIDs.size() == self->anm2->spritesheets.size()}), self)) for (auto [id, _] : self->anm2->spritesheets) - selectedIDs.insert(id); + self->selectedSpritesheetIDs.insert(id); - if (_imgui_button(IMGUI_SPRITESHEETS_SELECT_NONE.copy({.isDisabled = selectedIDs.empty()}), self)) - selectedIDs.clear(); + if (_imgui_button(IMGUI_SPRITESHEETS_SELECT_NONE.copy({.isDisabled = self->selectedSpritesheetIDs.empty()}), self)) + self->selectedSpritesheetIDs.clear(); - if (_imgui_button(IMGUI_SPRITESHEET_SAVE.copy({.isDisabled = selectedIDs.empty()}), self)) { - for (auto& id : selectedIDs) { + if (_imgui_button(IMGUI_SPRITESHEET_SAVE.copy({.isDisabled = self->selectedSpritesheetIDs.empty()}), self)) { + for (auto& id : self->selectedSpritesheetIDs) { WorkingDirectory workingDirectory(self->anm2->path); Anm2Spritesheet& spritesheet = self->anm2->spritesheets[id]; texture_from_gl_write(&spritesheet.texture, spritesheet.path); @@ -2378,7 +2399,7 @@ static void _imgui_spritesheets(Imgui* self) { } _imgui_end_child(IMGUI_SPRITESHEETS_FOOTER_CHILD, self); - _imgui_end(); // IMGUI_SPRITESHEETS + _imgui_end(IMGUI_SPRITESHEETS, self); } /* @@ -2429,24 +2450,24 @@ static void _imgui_animation_preview(Imgui* self) { _imgui_begin_child(IMGUI_CANVAS_VISUAL_CHILD, self); _imgui_color_edit4(IMGUI_CANVAS_BACKGROUND_COLOR, self, self->settings->previewBackgroundColor); - std::vector animationIDs; + std::vector animationIndices; ImguiItem animationOverlayItem = IMGUI_CANVAS_ANIMATION_OVERLAY; - animationIDs.emplace_back(ID_NONE); + animationIndices.emplace_back(ID_NONE); animationOverlayItem.items.emplace_back(IMGUI_NONE); for (auto& [id, animation] : self->anm2->animations) { - animationIDs.emplace_back(id); + animationIndices.emplace_back(id); animationOverlayItem.items.emplace_back(animation.name); } int animationIndex = 0; if (self->preview->animationOverlayID != ID_NONE) - animationIndex = std::find(animationIDs.begin(), animationIDs.end(), self->preview->animationOverlayID) - animationIDs.begin(); + animationIndex = std::find(animationIndices.begin(), animationIndices.end(), self->preview->animationOverlayID) - animationIndices.begin(); if (_imgui_combo(animationOverlayItem, self, &animationIndex)) - self->preview->animationOverlayID = animationIDs[animationIndex]; + self->preview->animationOverlayID = animationIndices[animationIndex]; _imgui_drag_float(IMGUI_CANVAS_ANIMATION_OVERLAY_TRANSPARENCY, self, self->settings->previewOverlayTransparency); _imgui_end_child(); // IMGUI_CANVAS_VISUAL_CHILD @@ -2817,12 +2838,13 @@ static void _imgui_spritesheet_editor(Imgui* self) { zoom = std::clamp(ROUND_NEAREST_MULTIPLE(zoom + delta, CANVAS_ZOOM_STEP), CANVAS_ZOOM_MIN, CANVAS_ZOOM_MAX); } } +*/ static void _imgui_frame_properties(Imgui* self) { - static Anm2Type& type = self->reference->itemType; - - IMGUI_BEGIN_OR_RETURN(IMGUI_FRAME_PROPERTIES); + IMGUI_BEGIN_OR_RETURN(IMGUI_FRAME_PROPERTIES, self); + _imgui_no_anm2_path_click_check(self); + Anm2Type type = self->reference->itemType; Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *self->reference); bool isLayerFrame = frame && type == ANM2_LAYER; @@ -2853,36 +2875,28 @@ static void _imgui_frame_properties(Imgui* self) { frame->rotation = glm::trunc(frame->rotation); } } else { - std::vector eventIDs; ImguiItem eventItem = IMGUI_FRAME_PROPERTIES_EVENT.copy({.isDisabled = !frame}); - eventIDs.emplace_back(ID_NONE); - eventItem.items.emplace_back(IMGUI_NONE); + eventItem.items[ID_NONE] = IMGUI_NONE; - for (auto& [id, event] : self->anm2->events) { - eventIDs.emplace_back(id); - eventItem.items.emplace_back(event.name); - } - - int eventIndex = std::find(eventIDs.begin(), eventIDs.end(), frame->eventID) - eventIDs.begin(); - - if (_imgui_combo(eventItem, self, &eventIndex)) - frame->eventID = eventIDs[eventIndex]; + for (auto& [id, event] : self->anm2->events) + eventItem.items[id] = event.name; + _imgui_combo(eventItem, self, frame->eventID); _imgui_input_int(IMGUI_FRAME_PROPERTIES_AT_FRAME.copy({.isDisabled = !frame}), self, frame->atFrame); } - _imgui_end(); // IMGUI_FRAME_PROPERTIES + _imgui_end(IMGUI_FRAME_PROPERTIES, self); } -*/ static void _imgui_log(Imgui* self) { ImGuiIO& io = ImGui::GetIO(); ImGuiStyle& style = ImGui::GetStyle(); ImVec4 borderColor = style.Colors[ImGuiCol_Border]; ImVec4 textColor = style.Colors[ImGuiCol_Text]; + float itemSpacingHeight = ImGui::GetStyle().ItemSpacing.y; - ImVec2 position = {io.DisplaySize.x - IMGUI_LOG_PADDING, io.DisplaySize.y - IMGUI_LOG_PADDING}; + ImVec2 position = {io.DisplaySize.x - itemSpacingHeight, io.DisplaySize.y - itemSpacingHeight}; for (int i = (int)self->log.size() - 1; i >= 0; --i) { ImguiLogItem& item = self->log[i]; @@ -2902,41 +2916,45 @@ static void _imgui_log(Imgui* self) { ImGui::PushStyleColor(ImGuiCol_Text, textColor); ImGui::SetNextWindowBgAlpha(lifetime); - _imgui_begin(IMGUI_LOG_WINDOW.copy({.label = std::format(IMGUI_LOG_FORMAT, i)})); + ImguiItem logItem = IMGUI_LOG_WINDOW.copy({.label = std::format(IMGUI_LOG_FORMAT, i)}); + _imgui_begin(logItem, self); ImGui::TextUnformatted(item.text.c_str()); ImVec2 windowSize = ImGui::GetWindowSize(); - _imgui_end(); // IMGUI_LOG_WINDOW + _imgui_end(logItem, self); // IMGUI_LOG_WINDOW ImGui::PopStyleColor(2); - position.y -= windowSize.y + IMGUI_LOG_PADDING; + position.y -= windowSize.y + ImGui::GetStyle().ItemSpacing.y; } } static void _imgui_dock(Imgui* self) { - ImguiItem window = IMGUI_WINDOW_MAIN; ImGuiViewport* viewport = ImGui::GetMainViewport(); - ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + IMGUI_TASKBAR.size->y)); - ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, viewport->Size.y - IMGUI_TASKBAR.size->y)); + float windowOffset = IMGUI_TASKBAR.size->y * self->settings->displayScale; + vec2 windowPosition = {viewport->Pos.x, viewport->Pos.y + windowOffset}; + vec2 windowSize = {viewport->Size.x, viewport->Size.y - windowOffset}; + + ImGui::SetNextWindowPos(windowPosition); + ImGui::SetNextWindowSize(windowSize); ImGui::SetNextWindowViewport(viewport->ID); - _imgui_begin(window); + _imgui_begin(IMGUI_WINDOW_MAIN, self); _imgui_dockspace(IMGUI_DOCKSPACE_MAIN, self); - //_imgui_tools(self); - //_imgui_animations(self); - //_imgui_events(self); + _imgui_tools(self); + _imgui_animations(self); + _imgui_events(self); _imgui_spritesheets(self); //_imgui_animation_preview(self); //_imgui_spritesheet_editor(self); - //_imgui_layers(self); - //_imgui_nulls(self); + _imgui_layers(self); + _imgui_nulls(self); //_imgui_timeline(self); - //_imgui_onionskin(self); - //_imgui_frame_properties(self); + _imgui_onionskin(self); + _imgui_frame_properties(self); - _imgui_end(); // IMGUI_WINDOW_MAIN + _imgui_end(IMGUI_WINDOW_MAIN, self); } void imgui_init(Imgui* self, Dialog* dialog, Resources* resources, Anm2* anm2, Anm2Reference* reference, Editor* editor, Preview* preview, @@ -2973,9 +2991,11 @@ void imgui_init(Imgui* self, Dialog* dialog, Resources* resources, Anm2* anm2, A io.ConfigWindowsMoveFromTitleBarOnly = true; ImGui::GetStyle().FontScaleMain = self->settings->displayScale; - io.Fonts->AddFontFromFileTTF(FONT_PATH, FONT_SIZE); + ImFontConfig config; + config.FontDataOwnedByAtlas = false; - self->style = ImGui::GetStyle(); + for (auto [i, font] : std::views::enumerate(FONTS)) + self->fonts[i] = io.Fonts->AddFontFromMemoryTTF((void*)font.data, font.length, FONT_SIZE, &config); imgui_keyboard_nav_enable(); @@ -2986,6 +3006,8 @@ void imgui_init(Imgui* self, Dialog* dialog, Resources* resources, Anm2* anm2, A continue; imgui_hotkey_chord_registry()[i] = imgui_chord_from_string_get(*&(self->settings->*SETTINGS_HOTKEY_MEMBERS[i])); } + + self->style = ImGui::GetStyle(); } void imgui_update(Imgui* self) { @@ -2993,25 +3015,22 @@ void imgui_update(Imgui* self) { ImGui_ImplOpenGL3_NewFrame(); ImGui::NewFrame(); - auto* ctx = ImGui::GetCurrentContext(); - IM_ASSERT(ctx); - IM_ASSERT(ctx->WithinFrameScope); - IM_ASSERT(ctx->CurrentWindowStack.Size >= 1); - IM_ASSERT(ImGui::GetIO().BackendPlatformUserData && "SDL3 backend not initialized?"); - IM_ASSERT(ImGui::GetIO().BackendRendererUserData && "OpenGL3 backend not initialized?"); - _imgui_taskbar(self); _imgui_dock(self); _imgui_log(self); if (self->isContextualActionsEnabled) { for (const auto& item : imgui_item_registry()) { - if (item->is_chord() && _imgui_chord_pressed(item->chord_get()) && !item->focusWindow.has_value()) { - if (item->snapshotAction.has_value()) - imgui_snapshot(self, *item->snapshotAction); - if (item->function) - item->function(self); - } + if (!item->is_chord() || !_imgui_chord_pressed(item->chord_get())) + continue; + if (item->isAllowHotkeyWhenFocusWindow && !_imgui_is_focus_window(*item->focusWindow)) + continue; + if (!item->isAllowHotkeyWhenFocusWindow && item->focusWindow.has_value()) + continue; + if (item->snapshotAction) + imgui_snapshot(self, *item->snapshotAction); + if (item->function) + item->function(self); } } diff --git a/src/imgui.h b/src/imgui.h index 54c8272..fe07d95 100644 --- a/src/imgui.h +++ b/src/imgui.h @@ -12,11 +12,9 @@ #include "snapshots.h" #include "tool.h" #include "window.h" +#include -#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS -#define IMGUI_DEBUG_PARANOID #define IMGUI_IMPL_OPENGL_LOADER_CUSTOM -#define IMGUI_ENABLE_DOCKING #define IM_VEC2_CLASS_EXTRA \ inline bool operator==(const ImVec2& rhs) const { return x == rhs.x && y == rhs.y; } \ inline bool operator!=(const ImVec2& rhs) const { return !(*this == rhs); } \ @@ -83,7 +81,6 @@ #define IMGUI_CHORD_NONE (ImGuiMod_None) #define IMGUI_FRAME_BORDER 2.0f #define IMGUI_LOG_DURATION 3.0f -#define IMGUI_LOG_PADDING 10.0f #define IMGUI_TEXT_HEIGHT_PADDING 4.0f #define IMGUI_PLAYHEAD_LINE_COLOR IM_COL32(UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX) #define IMGUI_TRIGGERS_EVENT_COLOR IM_COL32(UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, 128) @@ -97,7 +94,7 @@ #define IMGUI_ACTION_FRAME_CROP "Frame Crop" #define IMGUI_ACTION_FRAME_MOVE "Frame Move" -#define IMGUI_ACTION_ANIMATION_SWAP "Animation Swap" +#define IMGUI_ACTION_ANIMATION_MOVE "Move Animation" #define IMGUI_ACTION_TRIGGER_MOVE "Trigger At Frame" #define IMGUI_ACTION_ITEM_SWAP "Item Swap" #define IMGUI_ACTION_FRAME_DELAY "Frame Delay" @@ -140,7 +137,11 @@ #define IMGUI_LOG_ANIMATION_PASTE_ERROR "Failed to parse clipboard text as an animation." #define IMGUI_LOG_FRAME_PASTE_ERROR "Failed to parse clipboard text as a frame." #define IMGUI_LOG_RELOAD_SPRITESHEET "Reloaded spritesheet(s)." +#define IMGUI_LOG_REMOVE_UNUSED_SPRITESHEETS "Removed unused spritesheet(s)." +#define IMGUI_LOG_REMOVE_UNUSED_EVENTS "Removed unused event(s)." #define IMGUI_LOG_ADD_SPRITESHEET_ERROR "Failed to add spritesheet: {}. Make sure it's a valid PNG file." +#define IMGUI_LOG_ADD_SPRITESHEET "Added spritesheet #{}: {}" +#define IMGUI_LOG_REPLACE_SPRITESHEET "Replaced spritesheet #{}: {}" #define IMGUI_NONE "None" #define IMGUI_ANIMATION_DEFAULT_FORMAT "(*) {}" @@ -168,6 +169,8 @@ #define IMGUI_TRIGGERS_FONT_SCALE 2.0 +const ImVec2 IMGUI_TOOL_BUTTON_SIZE = {24, 24}; +const ImVec2 IMGUI_TOOL_COLOR_SIZE = {24, 24}; const ImVec2 IMGUI_TIMELINE_FRAME_SIZE = {12, 36}; const ImVec2 IMGUI_TIMELINE_FRAME_ATLAS_OFFSET = {ATLAS_SIZE_SMALL.x * 0.25f, (IMGUI_TIMELINE_FRAME_SIZE.y * 0.5f) - (ATLAS_SIZE_SMALL.y * 0.5f)}; const ImVec2 IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE = {150, 0}; @@ -198,6 +201,8 @@ const ImGuiKey IMGUI_INPUT_ZOOM_OUT = ImGuiKey_2; const ImGuiKey IMGUI_INPUT_ENTER = ImGuiKey_Enter; const ImGuiKey IMGUI_INPUT_RENAME = ImGuiKey_F2; const ImGuiKey IMGUI_INPUT_DEFAULT = ImGuiKey_Home; +const ImGuiKeyChord IMGUI_CHORD_SELECT_ALL = ImGuiMod_Ctrl | ImGuiKey_A; +const ImGuiKeyChord IMGUI_CHORD_SELECT_NONE = ImGuiKey_Escape; const ImGuiMouseButton IMGUI_MOUSE_DEFAULT = ImGuiMouseButton_Middle; enum ImguiPopupType { IMGUI_POPUP_NONE, IMGUI_POPUP_BY_ITEM, IMGUI_POPUP_CENTER_WINDOW }; @@ -228,14 +233,22 @@ struct Imgui { Clipboard* clipboard = nullptr; SDL_Window* window = nullptr; SDL_GLContext* glContext = nullptr; + Anm2 saveAnm2 = Anm2(); + ImFont* fonts[FONT_COUNT] = {}; + ImGuiStyle style; + std::vector log{}; std::string pendingPopup{}; ImguiPopupType pendingPopupType = IMGUI_POPUP_NONE; ImVec2 pendingPopupPosition{}; - std::vector log; - ImGuiStyle style; - Anm2 saveAnm2; - SDL_SystemCursor cursor; - SDL_SystemCursor pendingCursor; + std::set selectedAnimationIndices{}; + int lastAnimationIndex = ID_NONE; + std::set selectedSpritesheetIDs{}; + int lastSpritesheetID = ID_NONE; + int selectedEventID = ID_NONE; + int selectedLayerID = ID_NONE; + int selectedNullID = ID_NONE; + SDL_SystemCursor cursor = SDL_SYSTEM_CURSOR_DEFAULT; + SDL_SystemCursor pendingCursor = SDL_SYSTEM_CURSOR_DEFAULT; bool isCursorSet = false; bool isContextualActionsEnabled = true; bool isQuit = false; @@ -254,9 +267,12 @@ static void imgui_log_push(Imgui* self, const std::string& text) { } static inline void imgui_anm2_new(Imgui* self) { - *self->reference = Anm2Reference(); anm2_free(self->anm2); anm2_new(self->anm2); + + *self->reference = Anm2Reference(); + self->selectedAnimationIndices = {}; + self->selectedSpritesheetIDs = {}; } static inline void imgui_file_open(Imgui* self) { dialog_anm2_open(self->dialog); } @@ -576,7 +592,8 @@ enum ImguiItemType { IMGUI_ITEM, IMGUI_TEXT, IMGUI_IMAGE, - IMGUI_WINDOW, + IMGUI_BEGIN_WINDOW, + IMGUI_END_WINDOW, IMGUI_DOCKSPACE, IMGUI_BEGIN_CHILD, IMGUI_END_CHILD, @@ -611,6 +628,7 @@ static ImGuiKeyChord* imgui_hotkey_chord_registry(void) { } typedef void (*ImguiFunction)(Imgui*); +using IntStringMap = std::map; #define IMGUI_ITEM_MEMBERS \ X(label, std::string, false, {}) \ @@ -619,14 +637,16 @@ typedef void (*ImguiFunction)(Imgui*); X(popup, std::string, false, {}) \ X(dragDrop, std::string, true, {}) \ X(focusWindow, std::string, true, {}) \ - X(items, std::vector, false, {}) \ + X(items, IntStringMap, false, {}) \ X(atlas, AtlasType, false, ATLAS_NONE) \ X(textureID, int, false, ID_NONE) \ X(chord, ImGuiKeyChord, true, {}) \ X(hotkey, HotkeyType, true, {}) \ X(mnemonicKey, ImGuiKey, false, ImGuiKey_None) \ X(mnemonicIndex, int, false, INDEX_NONE) \ + X(position, vec2, true, {}) \ X(size, vec2, true, {}) \ + X(scale, float, false, 1.0f) \ X(uvMin, vec2, false, vec2()) \ X(uvMax, vec2, false, vec2(1.0f)) \ X(popupSize, vec2, false, {}) \ @@ -638,9 +658,12 @@ typedef void (*ImguiFunction)(Imgui*); X(isMnemonicDisabled, bool, false, false) \ X(isEmptyFormat, bool, false, false) \ X(isUseItemActivated, bool, false, false) \ - X(isSizeToText, bool, false, false) \ - X(isSizeToRegion, bool, false, false) \ + X(isWidthToText, bool, false, false) \ + X(isWidthToRegion, bool, false, false) \ + X(isHeightToRegion, bool, false, false) \ X(isHotkeyInLabel, bool, false, false) \ + X(isAllowHotkeyWhenFocusWindow, bool, false, false) \ + X(isAtlasStretch, bool, false, false) \ X(isSameLine, bool, false, false) \ X(isSeparator, bool, false, false) \ X(id, int, false, 0) \ @@ -651,16 +674,19 @@ typedef void (*ImguiFunction)(Imgui*); X(min, int, true, {}) \ X(max, int, true, {}) \ X(value, int, false, {}) \ - X(atlasOffset, vec2, false, {}) \ + X(atlasOffset, vec2, true, {}) \ X(cursorPosition, vec2, true, {}) \ X(cursorOffset, vec2, false, {}) \ + X(textPosition, vec2, true, {}) \ + X(textOffset, vec2, false, {}) \ X(itemSpacing, vec2, true, {}) \ X(windowPadding, vec2, true, {}) \ X(framePadding, vec2, true, {}) \ X(border, int, true, {}) \ X(flags, int, false, {}) \ X(windowFlags, int, false, {}) \ - X(rowCount, int, true, {}) + X(rowCount, int, true, {}) \ + X(font, ImFont*, true, {}) struct ImguiItemOverride { #define X(name, type, isOptional, ...) std::optional name = {}; @@ -714,6 +740,8 @@ struct ImguiItem { IMGUI_ITEM_MEMBERS #undef X + out.id += out.idOffset; + return out; } @@ -761,27 +789,27 @@ IMGUI_ITEM(IMGUI_TASKBAR, self.label = "Taskbar", self.size = {0, 32}, ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoSavedSettings); IMGUI_ITEM(IMGUI_FILE, self.label = "&File", self.tooltip = "Opens the file menu, for reading/writing anm2 files.", self.popup = "## File Popup", - self.popupType = IMGUI_POPUP_BY_ITEM, self.isSizeToText = true, self.isSameLine = true); + self.popupType = IMGUI_POPUP_BY_ITEM, self.isWidthToText = true, self.isHeightToRegion = true, self.isSameLine = true); IMGUI_ITEM(IMGUI_NEW, self.label = "&New", self.tooltip = "Load a blank .anm2 file to edit.", self.function = imgui_file_new, self.hotkey = HOTKEY_NEW, - self.isSizeToText = true, self.isHotkeyInLabel = true); + self.isWidthToRegion = true, self.isHotkeyInLabel = true); IMGUI_ITEM(IMGUI_OPEN, self.label = "&Open", self.tooltip = "Open an existing .anm2 file to edit.", self.function = imgui_file_open, self.hotkey = HOTKEY_OPEN, - self.isSizeToText = true, self.isHotkeyInLabel = true); + self.isWidthToRegion = true, self.isHotkeyInLabel = true); IMGUI_ITEM(IMGUI_SAVE, self.label = "&Save", self.tooltip = "Saves the current .anm2 file to its path.\nIf no " "path exists, one can be chosen.", - self.function = imgui_file_save, self.hotkey = HOTKEY_SAVE, self.isSizeToText = true, self.isHotkeyInLabel = true); + self.function = imgui_file_save, self.hotkey = HOTKEY_SAVE, self.isWidthToText = true, self.isHotkeyInLabel = true); IMGUI_ITEM(IMGUI_SAVE_AS, self.label = "S&ave As", self.tooltip = "Saves the current .anm2 file to a chosen path.", self.function = imgui_file_save_as, - self.hotkey = HOTKEY_SAVE_AS, self.isSizeToText = true, self.isHotkeyInLabel = true); + self.hotkey = HOTKEY_SAVE_AS, self.isWidthToText = true, self.isHotkeyInLabel = true); IMGUI_ITEM(IMGUI_EXPLORE_ANM2_LOCATION, self.label = "E&xplore Anm2 Location", self.tooltip = "Open the system's file explorer in the anm2's path.", - self.function = imgui_explore, self.isSizeToText = true, self.isSeparator = true); + self.function = imgui_explore, self.isWidthToText = true, self.isSeparator = true); IMGUI_ITEM(IMGUI_EXIT, self.label = "&Exit", self.tooltip = "Exits the program.", self.function = imgui_quit, self.hotkey = HOTKEY_EXIT, - self.isSizeToText = true, self.isHotkeyInLabel = true); + self.isWidthToText = true, self.isHotkeyInLabel = true); IMGUI_ITEM(IMGUI_EXIT_CONFIRMATION, self.label = "Exit Confirmation", self.tooltip = "Unsaved changes will be lost!\nAre you sure you want to exit?"); @@ -790,7 +818,8 @@ IMGUI_ITEM(IMGUI_OPEN_CONFIRMATION, self.label = "Open Confirmation", self.toolt IMGUI_ITEM(IMGUI_NO_ANM2_PATH_CONFIRMATION, self.label = "No Anm2 Path", self.tooltip = "You will need to load or make a new .anm2 file first!\n"); IMGUI_ITEM(IMGUI_WIZARD, self.label = "&Wizard", self.tooltip = "Opens the wizard menu, for neat functions related to the .anm2.", - self.popup = "## Wizard Popup", self.popupType = IMGUI_POPUP_BY_ITEM, self.isSizeToText = true, self.isSameLine = true); + self.popup = "## Wizard Popup", self.popupType = IMGUI_POPUP_BY_ITEM, self.isHeightToRegion = true, self.isWidthToText = true, + self.isSameLine = true); #define IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING 40 IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID, self.label = "&Generate Animation from Grid", self.tooltip = "Generate a new animation from grid values.", @@ -875,11 +904,10 @@ IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CANCEL, self.label = "Cancel", self self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT); IMGUI_ITEM(IMGUI_SCALE_ANM2, self.label = "S&cale Anm2", self.tooltip = "Scale up all size and position-related frame properties in the anm2.", - self.popup = "Scale Anm2", self.popupType = IMGUI_POPUP_CENTER_WINDOW, self.popupSize = {260, 75}, self.isSizeToText = true, + self.popup = "Scale Anm2", self.popupType = IMGUI_POPUP_CENTER_WINDOW, self.popupSize = {260, 75}, self.isWidthToText = true, self.isSeparator = true); -IMGUI_ITEM(IMGUI_SCALE_ANM2_OPTIONS_CHILD, self.label = "## Scale Anm2 Options Child", - self.size = {IMGUI_SCALE_ANM2.popupSize.x, IMGUI_SCALE_ANM2.popupSize.y - IMGUI_FOOTER_CHILD.size->y}, self.flags = true); +IMGUI_ITEM(IMGUI_SCALE_ANM2_OPTIONS_CHILD, self.label = "## Scale Anm2 Options Child", self.flags = true); IMGUI_ITEM(IMGUI_SCALE_ANM2_VALUE, self.label = "Value", self.tooltip = "The size and position-related frame properties in " @@ -894,11 +922,9 @@ IMGUI_ITEM(IMGUI_RENDER_ANIMATION, self.label = "&Render Animation", "options can be customized.", self.popup = "Render Animation", self.popupSize = {500, 170}, self.popupType = IMGUI_POPUP_CENTER_WINDOW); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_CHILD, self.label = "## Render Animation Child", - self.size = {IMGUI_RENDER_ANIMATION.popupSize.x, IMGUI_RENDER_ANIMATION.popupSize.y - IMGUI_FOOTER_CHILD.size->y}, self.flags = true); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_CHILD, self.label = "## Render Animation Child", self.flags = true); -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FOOTER_CHILD, self.label = "## Render Animation Footer Child", - self.size = {IMGUI_RENDER_ANIMATION.popupSize.x, IMGUI_FOOTER_CHILD.size->y}, self.flags = true); +IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FOOTER_CHILD, self.label = "## Render Animation Footer Child", self.flags = true); IMGUI_ITEM(IMGUI_RENDER_ANIMATION_LOCATION_BROWSE, self.label = "## Location Browse", self.tooltip = "Open file explorer to pick rendered animation location.", self.atlas = ATLAS_FOLDER, self.isSameLine = true); @@ -920,7 +946,11 @@ IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FFMPEG_PATH, self.label = "FFmpeg Path", IMGUI_ITEM(IMGUI_RENDER_ANIMATION_OUTPUT, self.label = "Output", self.tooltip = "Select the rendered animation output.\nIt can either be " "one animated image or a sequence of frames.", - self.items = {std::begin(RENDER_TYPE_STRINGS), std::end(RENDER_TYPE_STRINGS)}, self.value = RENDER_PNG); + self.items = {{RENDER_PNG, RENDER_TYPE_STRINGS[RENDER_PNG]}, + {RENDER_GIF, RENDER_TYPE_STRINGS[RENDER_GIF]}, + {RENDER_WEBM, RENDER_TYPE_STRINGS[RENDER_WEBM]}, + {RENDER_MP4, RENDER_TYPE_STRINGS[RENDER_MP4]}}, + self.value = RENDER_PNG); IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FORMAT, self.label = "Format", self.tooltip = "(PNG images only).\nSet the format of each output frame; i.e., " @@ -950,28 +980,29 @@ IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_INFO, self.label = "Recording frames. Once IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_CANCEL, self.label = "Cancel", self.tooltip = "Cancel rendering the animation.", self.rowCount = 1); IMGUI_ITEM(IMGUI_PLAYBACK, self.label = "&Playback", self.tooltip = "Opens the playback menu, for configuring playback settings.", - self.popup = "## Playback Popup", self.popupType = IMGUI_POPUP_BY_ITEM, self.isSizeToText = true, self.isSameLine = true); + self.popup = "## Playback Popup", self.popupType = IMGUI_POPUP_BY_ITEM, self.isWidthToText = true, self.isHeightToRegion = true, + self.isSameLine = true); IMGUI_ITEM(IMGUI_ALWAYS_LOOP, self.label = "&Always Loop", self.tooltip = "Sets the animation playback to always loop, " "regardless of the animation's loop setting.", - self.isSizeToText = true); + self.isWidthToText = true); IMGUI_ITEM(IMGUI_CLAMP_PLAYHEAD, self.label = "&Clamp Playhead", self.tooltip = "The playhead (draggable icon on timeline) won't be " "able to exceed the animation length.", - self.isSizeToText = true); + self.isWidthToText = true); IMGUI_ITEM(IMGUI_SETTINGS, self.label = "&Settings", self.tooltip = "Opens the setting menu, for configuring general program settings.", - self.popup = "## Settings Popup", self.popupType = IMGUI_POPUP_BY_ITEM, self.isSizeToText = true); + self.popup = "## Settings Popup", self.popupType = IMGUI_POPUP_BY_ITEM, self.isWidthToText = true, self.isHeightToRegion = true); IMGUI_ITEM(IMGUI_VSYNC, self.label = "&Vsync", self.tooltip = "Toggle vertical sync; synchronizes program " "framerate with your monitor's refresh rate.", - self.isSizeToText = true, self.isSeparator = true); + self.isWidthToText = true, self.isSeparator = true); IMGUI_ITEM(IMGUI_HOTKEYS, self.label = "&Hotkeys", self.tooltip = "Change the program's hotkeys.", self.popup = "Hotkeys", self.popupSize = {500, 405}, - self.isSizeToText = true, self.isSeparator = true); + self.isWidthToText = true, self.isSeparator = true); IMGUI_ITEM(IMGUI_HOTKEYS_CHILD, self.label = "## Hotkeys Child", self.size = {IMGUI_HOTKEYS.popupSize.x, IMGUI_HOTKEYS.popupSize.y - 35}, self.flags = true); @@ -984,12 +1015,18 @@ IMGUI_ITEM(IMGUI_HOTKEYS_OPTIONS_CHILD, self.label = "## Merge Options Child", s IMGUI_ITEM(IMGUI_HOTKEYS_CONFIRM, self.label = "Confirm", self.tooltip = "Use these hotkeys.", self.rowCount = 1); IMGUI_ITEM(IMGUI_DEFAULT_SETTINGS, self.label = "&Reset to Default Settings", self.tooltip = "Reset the program's settings to their default state.", - self.isSizeToText = true); + self.isWidthToText = true); + +IMGUI_ITEM(IMGUI_ANM2S, self.label = "## Anm2s", self.size = {0, 32}, + self.flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoSavedSettings); + +IMGUI_ITEM(IMGUI_ANM2, self.label = "## Anm2"); IMGUI_ITEM(IMGUI_LAYERS, self.label = "Layers", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); IMGUI_ITEM(IMGUI_LAYERS_CHILD, self.label = "## Layers Child", self.flags = true); -IMGUI_ITEM(IMGUI_LAYER, self.label = "## Layer Item", self.dragDrop = "## Layer Drag Drop", self.atlas = ATLAS_LAYER, self.isSizeToRegion = true, +IMGUI_ITEM(IMGUI_LAYER, self.label = "## Layer Item", self.dragDrop = "## Layer Drag Drop", self.atlas = ATLAS_LAYER, self.isWidthToRegion = true, self.idOffset = 3000); IMGUI_ITEM(IMGUI_LAYER_SPRITESHEET_ID, self.label = "## Spritesheet ID", self.tooltip = "Change the spritesheet ID this layer uses.", @@ -1024,7 +1061,7 @@ IMGUI_ITEM(IMGUI_ANIMATIONS, self.label = "Animations", self.flags = ImGuiWindow IMGUI_ITEM(IMGUI_ANIMATIONS_CHILD, self.label = "## Animations Child", self.flags = true); IMGUI_ITEM(IMGUI_ANIMATION, self.label = "## Animation Item", self.dragDrop = "## Animation Drag Drop", self.atlas = ATLAS_ANIMATION, - self.isSizeToRegion = true, self.idOffset = 2000); + self.isWidthToRegion = true, self.idOffset = 2000); #define IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT 5 IMGUI_ITEM(IMGUI_ANIMATION_ADD, self.label = "Add", self.tooltip = "Adds a new animation.", self.snapshotAction = "Add Animation", @@ -1071,12 +1108,28 @@ IMGUI_ITEM(IMGUI_MERGE_DELETE_ANIMATIONS_AFTER, self.label = "Delete Animations IMGUI_ITEM(IMGUI_MERGE_CONFIRM, self.label = "Merge", self.tooltip = "Merge the selected animations with the options set.", self.snapshotAction = "Merge Animations", self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_ANIMATION_REMOVE, self.label = "Remove", self.tooltip = "Remove the selected animation.", self.snapshotAction = "Remove Animation", +IMGUI_ITEM(IMGUI_ANIMATION_REMOVE, self.label = "Remove", self.tooltip = "Remove the selected animation(s).", self.snapshotAction = "Remove Animation(s)", self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, self.chord = ImGuiKey_Delete, self.focusWindow = IMGUI_ANIMATIONS.label, self.isSameLine = true); -IMGUI_ITEM(IMGUI_ANIMATION_DEFAULT, self.label = "Default", self.tooltip = "Set the selected animation as the default one.", +IMGUI_ITEM(IMGUI_ANIMATION_DEFAULT, self.label = "Default", self.tooltip = "Set the referenced animation as the default one.", self.snapshotAction = "Default Animation", self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, self.isSameLine = true); +static inline void imgui_animations_select_all(Imgui* self) { + for (int i = 0; i < (int)self->anm2->animations.size(); i++) + self->selectedAnimationIndices.insert(i); +} + +IMGUI_ITEM(IMGUI_ANIMATION_SELECT_ALL, self.label = "## Select None", self.hotkey = HOTKEY_SELECT_ALL, self.focusWindow = IMGUI_ANIMATIONS.label, + self.function = imgui_animations_select_all, self.isAllowHotkeyWhenFocusWindow = true); + +static inline void imgui_animations_select_none(Imgui* self) { + self->selectedAnimationIndices.clear(); + *self->reference = Anm2Reference(); +} + +IMGUI_ITEM(IMGUI_ANIMATION_SELECT_NONE, self.label = "## Select None", self.hotkey = HOTKEY_SELECT_NONE, self.focusWindow = IMGUI_ANIMATIONS.label, + self.function = imgui_animations_select_none, self.isAllowHotkeyWhenFocusWindow = true); + IMGUI_ITEM(IMGUI_EVENTS, self.label = "Events", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); IMGUI_ITEM(IMGUI_EVENTS_CHILD, self.label = "## Events Child", self.flags = true); @@ -1100,8 +1153,7 @@ IMGUI_ITEM(IMGUI_SPRITESHEET_CHILD, self.label = "## Spritesheet Child", self.fl IMGUI_ITEM(IMGUI_SPRITESHEET, self.label = "## Spritesheet", self.dragDrop = "## Spritesheet Drag Drop"); IMGUI_ITEM(IMGUI_SPRITESHEET_TEXT, self.label = "## Spritesheet Text", self.atlas = ATLAS_SPRITESHEET, self.itemSpacing = vec2(8, 0)); -IMGUI_ITEM(IMGUI_SPRITESHEETS_FOOTER_CHILD, self.label = "## Spritesheets Footer Child", self.size = {0, IMGUI_FOOTER_CHILD.size->y * 1.66f}, - self.flags = true); +IMGUI_ITEM(IMGUI_SPRITESHEETS_FOOTER_CHILD, self.label = "## Spritesheets Footer Child", self.flags = true); #define IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT 4 #define IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT 3 @@ -1117,12 +1169,12 @@ IMGUI_ITEM(IMGUI_SPRITESHEETS_REPLACE, self.label = "Replace", self.tooltip = "R IMGUI_ITEM(IMGUI_SPRITESHEETS_REMOVE_UNUSED, self.label = "Remove Unused", self.tooltip = "Remove all unused spritesheets in the anm2 (i.e., " "the spritesheet isn't used in any layer animations).", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT); + self.snapshotAction = "Remove Unused Spritesheets", self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT); -IMGUI_ITEM(IMGUI_SPRITESHEETS_SELECT_ALL, self.label = "Select All", self.tooltip = "Select all spritesheets.", self.chord = ImGuiMod_Ctrl + ImGuiKey_A, +IMGUI_ITEM(IMGUI_SPRITESHEETS_SELECT_ALL, self.label = "Select All", self.tooltip = "Select all spritesheets.", self.hotkey = HOTKEY_SELECT_ALL, self.focusWindow = IMGUI_SPRITESHEETS.label, self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT, self.isSameLine = true); -IMGUI_ITEM(IMGUI_SPRITESHEETS_SELECT_NONE, self.label = "Select None", self.tooltip = "Unselect all spritesheets.", self.chord = ImGuiKey_Escape, +IMGUI_ITEM(IMGUI_SPRITESHEETS_SELECT_NONE, self.label = "Select None", self.tooltip = "Unselect all spritesheets.", self.hotkey = HOTKEY_SELECT_NONE, self.focusWindow = IMGUI_SPRITESHEETS.label, self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT, self.isSameLine = true); IMGUI_ITEM(IMGUI_SPRITESHEET_SAVE, self.label = "Save", self.tooltip = "Save the selected spritesheets to their original locations.", @@ -1274,7 +1326,7 @@ IMGUI_ITEM(IMGUI_TOOLS, self.label = "Tools"); IMGUI_ITEM(IMGUI_TOOL_PAN, self.label = "## Pan", self.tooltip = "Use the pan tool.\nWill shift the view as the cursor is dragged.\nYou " "can also use the middle mouse button to pan at any time.", - self.function = imgui_tool_pan_set, self.hotkey = HOTKEY_PAN, self.atlas = ATLAS_PAN); + self.function = imgui_tool_pan_set, self.hotkey = HOTKEY_PAN, self.atlas = ATLAS_PAN, self.isAtlasStretch = true); IMGUI_ITEM(IMGUI_TOOL_MOVE, self.label = "## Move", self.tooltip = "Use the move tool.\nAnimation Preview: Will move the position " @@ -1374,12 +1426,12 @@ IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, self.label = "## Item Prop IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER, self.label = "Layer", self.tooltip = "The item will be a layer item.\nA layer item is a " "primary graphical item, using a spritesheet.", - self.isSizeToText = true, self.value = ANM2_LAYER, self.isSameLine = true); + self.isWidthToText = true, self.value = ANM2_LAYER, self.isSameLine = true); IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL, self.label = "Null", self.tooltip = "The item will be a null item.\nA null item is an " "invisible item, often accessed by a game engine.", - self.isSizeToText = true, self.value = ANM2_NULL); + self.isWidthToText = true, self.value = ANM2_NULL); IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, self.label = "## Item Properties Items", self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 250}, self.flags = true); @@ -1598,16 +1650,16 @@ IMGUI_ITEM(IMGUI_CONTEXT_MENU, self.label = "## Context Menu"); IMGUI_ITEM(IMGUI_CUT, self.label = "Cut", self.tooltip = "Cuts the currently selected contextual element; " "removing it and putting it to the clipboard.", - self.snapshotAction = "Cut", self.function = imgui_cut, self.hotkey = HOTKEY_CUT, self.isSizeToText = true); + self.snapshotAction = "Cut", self.function = imgui_cut, self.hotkey = HOTKEY_CUT, self.isWidthToText = true); -IMGUI_ITEM(IMGUI_COPY, self.label = "Copy", self.tooltip = "Copies the currently selected contextual element to the clipboard.", self.snapshotAction = "Copy", - self.function = imgui_copy, self.hotkey = HOTKEY_COPY, self.isSizeToText = true); +IMGUI_ITEM(IMGUI_COPY, self.label = "Copy", self.tooltip = "Copies the currently selected contextual element to the clipboard.", self.function = imgui_copy, + self.hotkey = HOTKEY_COPY, self.isWidthToText = true); IMGUI_ITEM(IMGUI_PASTE, self.label = "Paste", self.tooltip = "Pastes the currently selection contextual element from the clipboard.", - self.snapshotAction = "Paste", self.function = imgui_paste, self.hotkey = HOTKEY_PASTE, self.isSizeToText = true); + self.snapshotAction = "Paste", self.function = imgui_paste, self.hotkey = HOTKEY_PASTE, self.isWidthToText = true); -IMGUI_ITEM(IMGUI_CHANGE_INPUT_TEXT, self.label = "## Input Text", self.tooltip = "Rename the selected item.", self.snapshotAction = "Rename Item", - self.flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue, self.max = UCHAR_MAX); +IMGUI_ITEM(IMGUI_CHANGE_INPUT_TEXT, self.label = "## Input Text", self.tooltip = "Rename the selected item.", self.snapshotAction = "Rename", + self.flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue, self.max = 0xFFFF); IMGUI_ITEM(IMGUI_CHANGE_INPUT_INT, self.label = "## Input Int", self.tooltip = "Change the selected item's value.", self.snapshotAction = "Change Value", self.step = 0); diff --git a/src/preview.cpp b/src/preview.cpp index ef13be7..6d86e06 100644 --- a/src/preview.cpp +++ b/src/preview.cpp @@ -87,8 +87,8 @@ void preview_draw(Preview* self) { if (self->settings->previewIsAxes) canvas_axes_draw(&self->canvas, shaderAxis, transform, self->settings->previewAxesColor); - auto animation_draw = [&](int animationID) { - Anm2Animation* animation = map_find(self->anm2->animations, animationID); + auto animation_draw = [&](int animationIndex) { + Anm2Animation* animation = anm2_animation_from_reference(self->anm2, {animationIndex}); if (!animation) return; @@ -107,7 +107,7 @@ void preview_draw(Preview* self) { return; Anm2Frame frame; - anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_LAYER, id}, time); + anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationIndex, ANM2_LAYER, id}, time); if (!frame.isVisible) return; @@ -151,7 +151,7 @@ void preview_draw(Preview* self) { return; Anm2Frame frame; - anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_NULL, id}, time); + anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationIndex, ANM2_NULL, id}, time); if (!frame.isVisible) return; @@ -180,7 +180,7 @@ void preview_draw(Preview* self) { auto base_draw = [&](float time, vec3 colorOffset = {}, float alphaOffset = {}, bool isOnionskin = {}) { Anm2Frame root; - anm2_frame_from_time(self->anm2, &root, Anm2Reference{animationID, ANM2_ROOT}, time); + anm2_frame_from_time(self->anm2, &root, Anm2Reference{animationIndex, ANM2_ROOT}, time); mat4 rootModel = self->settings->previewIsRootTransform ? quad_model_parent_get(root.position, {}, PERCENT_TO_UNIT(root.scale), root.rotation) : mat4(1.0f); @@ -218,7 +218,7 @@ void preview_draw(Preview* self) { onionskins_draw(); }; - animation_draw(self->reference->animationID); + animation_draw(self->reference->animationIndex); animation_draw(self->animationOverlayID); canvas_unbind(); diff --git a/src/render.h b/src/render.h index 3cb8a87..ac4dc5d 100644 --- a/src/render.h +++ b/src/render.h @@ -2,25 +2,16 @@ #include "COMMON.h" -enum RenderType -{ - RENDER_PNG, - RENDER_GIF, - RENDER_WEBM, - RENDER_MP4, - RENDER_COUNT -}; +enum RenderType { RENDER_PNG, RENDER_GIF, RENDER_WEBM, RENDER_MP4, RENDER_COUNT }; -const inline std::string RENDER_TYPE_STRINGS[] = -{ +const inline std::string RENDER_TYPE_STRINGS[] = { "PNG Images", "GIF image", "WebM video", "MP4 video", }; -const inline std::string RENDER_EXTENSIONS[RENDER_COUNT] = -{ +const inline std::string RENDER_EXTENSIONS[RENDER_COUNT] = { ".png", ".gif", ".webm", diff --git a/src/resources.cpp b/src/resources.cpp index c338e88..2f3280a 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -1,7 +1,8 @@ #include "resources.h" +#include "RESOURCE.h" void resources_init(Resources* self) { - texture_from_path_init(&self->atlas, ATLAS_PATH); + texture_from_memory_init(&self->atlas, TEXTURE_ATLAS_SIZE, TEXTURE_ATLAS, TEXTURE_ATLAS_LENGTH); for (int i = 0; i < SHADER_COUNT; i++) shader_init(&self->shaders[i], SHADER_DATA[i].vertex, SHADER_DATA[i].fragment); diff --git a/src/settings.h b/src/settings.h index 5271063..79fa9fe 100644 --- a/src/settings.h +++ b/src/settings.h @@ -61,6 +61,8 @@ X(HOTKEY_COPY, hotkeyCopy, TYPE_STRING, "Ctrl+C") \ X(HOTKEY_CUT, hotkeyCut, TYPE_STRING, "Ctrl+X") \ X(HOTKEY_PASTE, hotkeyPaste, TYPE_STRING, "Ctrl+V") \ + X(HOTKEY_SELECT_ALL, hotkeySelectAll, TYPE_STRING, "Ctrl+A") \ + X(HOTKEY_SELECT_NONE, hotkeySelectNone, TYPE_STRING, "Ctrl+Shift+A") \ \ X(PLAYBACK_IS_LOOP, playbackIsLoop, TYPE_BOOL, true) \ X(PLAYBACK_IS_CLAMP_PLAYHEAD, playbackIsClampPlayhead, TYPE_BOOL, true) \ @@ -211,7 +213,9 @@ constexpr int SETTINGS_COUNT = (int)std::size(SETTINGS_ENTRIES); X(REDO, "Redo") \ X(COPY, "Copy") \ X(CUT, "Cut") \ - X(PASTE, "Paste") + X(PASTE, "Paste") \ + X(SELECT_ALL, "Select All") \ + X(SELECT_NONE, "Select None") typedef enum { #define X(name, str) HOTKEY_##name, @@ -257,7 +261,9 @@ const inline HotkeyMember SETTINGS_HOTKEY_MEMBERS[HOTKEY_COUNT] = {nullptr, &Settings::hotkeyRedo, &Settings::hotkeyCopy, &Settings::hotkeyCut, - &Settings::hotkeyPaste}; + &Settings::hotkeyPaste, + &Settings::hotkeySelectAll, + &Settings::hotkeySelectNone}; const inline std::string SETTINGS_IMGUI_DEFAULT = R"( # Dear ImGui diff --git a/src/snapshots.h b/src/snapshots.h index b7d2cf9..cc2e56b 100644 --- a/src/snapshots.h +++ b/src/snapshots.h @@ -17,7 +17,7 @@ struct SnapshotStack { Snapshot snapshots[SNAPSHOT_STACK_MAX]; int top = 0; - bool is_empty() const { return top == 0; } + bool empty() const { return top == 0; } }; struct Snapshots { diff --git a/src/texture.cpp b/src/texture.cpp index 1f2d52e..7d1f1f2 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -76,6 +76,22 @@ bool texture_from_rgba_write(const std::string& path, const uint8_t* data, ivec2 return isSuccess; } +bool texture_from_memory_init(Texture* self, ivec2 size, const uint8_t* data, size_t length) { + *self = Texture{}; + self->size = size; + + u8* textureData = stbi_load_from_memory(data, length, &self->size.x, &self->size.y, nullptr, TEXTURE_CHANNELS); + + if (!textureData) + return false; + + self->isInvalid = false; + + _texture_gl_set(self, textureData); + + return true; +} + bool texture_from_gl_write(Texture* self, const std::string& path) { return texture_from_rgba_write(path, texture_download(self).data(), self->size); } void texture_free(Texture* self) { diff --git a/src/texture.h b/src/texture.h index 8c2e3a2..9da64cc 100644 --- a/src/texture.h +++ b/src/texture.h @@ -18,8 +18,9 @@ struct Texture { bool texture_from_gl_write(Texture* self, const std::string& path); bool texture_from_path_init(Texture* self, const std::string& path); -bool texture_from_rgba_init(Texture* self, ivec2 size, const u8* data); -bool texture_from_rgba_write(const std::string& path, const u8* data, ivec2 size); +bool texture_from_rgba_init(Texture* self, ivec2 size, const uint8_t* data); +bool texture_from_rgba_write(const std::string& path, const uint8_t* data, ivec2 size); bool texture_pixel_set(Texture* self, ivec2 position, vec4 color); void texture_free(Texture* self); -std::vector texture_download(const Texture* self); \ No newline at end of file +bool texture_from_memory_init(Texture* self, ivec2 size, const uint8_t* data, size_t length); +std::vector texture_download(const Texture* self); \ No newline at end of file From 5b0f9a39c4ca7319021c85c1b9265cb0128c9b55 Mon Sep 17 00:00:00 2001 From: shweet Date: Tue, 21 Oct 2025 20:23:27 -0400 Subject: [PATCH 05/15] Refactor... --- .clang-format | 13 +- .gitignore | 5 +- .gitmodules | 3 + .vscode/launch.json | 28 + .vscode/tasks.json | 17 + CMakeLists.txt | 129 +- CMakeSettings.json | 26 - assets/Icon.ico | Bin 16958 -> 0 bytes assets/Icon.rc | 1 - assets/atlas.png | Bin 1242 -> 0 bytes assets/atlas_data_write.sh | 66 - external/imgui | 2 +- include/nanosvg.h | 3121 +++++++++++++++++++++ include/nanosvgrast.h | 1461 ++++++++++ src/COMMON.h | 400 --- src/RESOURCE.h | 3992 --------------------------- src/animation_preview.cpp | 316 +++ src/animation_preview.h | 21 + src/animations.cpp | 293 ++ src/animations.h | 20 + src/anm2.cpp | 2128 ++++++--------- src/anm2.h | 426 ++- src/canvas.cpp | 442 +-- src/canvas.h | 104 +- src/clipboard.cpp | 97 - src/clipboard.h | 23 - src/dialog.cpp | 116 +- src/dialog.h | 83 +- src/dockspace.cpp | 54 + src/dockspace.h | 38 + src/document.cpp | 91 + src/document.h | 51 + src/document_manager.cpp | 76 + src/document_manager.h | 27 + src/documents.cpp | 129 + src/documents.h | 20 + src/editor.cpp | 54 - src/editor.h | 41 - src/events.cpp | 83 + src/events.h | 17 + src/ffmpeg.cpp | 56 - src/ffmpeg.h | 26 - src/filesystem.cpp | 47 + src/filesystem.h | 20 + src/font.cpp | 33 + src/font.h | 5238 ++++++++++++++++++++++++++++++++++++ src/frame_properties.cpp | 124 + src/frame_properties.h | 13 + src/generate_preview.cpp | 50 - src/generate_preview.h | 24 - src/icon.h | 200 ++ src/imgui.cpp | 3229 ++-------------------- src/imgui.h | 1816 +------------ src/layers.cpp | 81 + src/layers.h | 17 + src/loader.cpp | 93 + src/loader.h | 24 + src/log.cpp | 104 +- src/log.h | 57 +- src/main.cpp | 56 +- src/main.h | 13 - src/math.cpp | 81 + src/math.h | 46 + src/nulls.cpp | 80 + src/nulls.h | 17 + src/onionskin.cpp | 43 + src/onionskin.h | 18 + src/playback.cpp | 48 + src/playback.h | 18 + src/preview.cpp | 259 -- src/preview.h | 52 - src/render.h | 19 - src/resources.cpp | 25 +- src/resources.h | 24 +- src/settings.cpp | 563 ++-- src/settings.h | 574 ++-- src/shader.cpp | 109 +- src/shader.h | 157 +- src/snapshots.cpp | 67 - src/snapshots.h | 37 - src/spritesheet_editor.cpp | 128 + src/spritesheet_editor.h | 19 + src/spritesheets.cpp | 250 ++ src/spritesheets.h | 16 + src/state.cpp | 293 +- src/state.h | 73 +- src/taskbar.cpp | 266 ++ src/taskbar.h | 22 + src/texture.cpp | 186 +- src/texture.h | 50 +- src/timeline.cpp | 701 +++++ src/timeline.h | 35 + src/toast.cpp | 80 + src/toast.h | 29 + src/tool.h | 100 +- src/tools.cpp | 106 + src/tools.h | 16 + src/types.h | 67 + src/util.cpp | 40 + src/util.h | 55 + src/window.cpp | 11 - src/window.h | 14 - src/xml.cpp | 37 + src/xml.h | 15 + 104 files changed, 17010 insertions(+), 13171 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json delete mode 100644 CMakeSettings.json delete mode 100644 assets/Icon.ico delete mode 100644 assets/Icon.rc delete mode 100644 assets/atlas.png delete mode 100755 assets/atlas_data_write.sh create mode 100644 include/nanosvg.h create mode 100644 include/nanosvgrast.h delete mode 100644 src/COMMON.h delete mode 100644 src/RESOURCE.h create mode 100644 src/animation_preview.cpp create mode 100644 src/animation_preview.h create mode 100644 src/animations.cpp create mode 100644 src/animations.h delete mode 100644 src/clipboard.cpp delete mode 100644 src/clipboard.h create mode 100644 src/dockspace.cpp create mode 100644 src/dockspace.h create mode 100644 src/document.cpp create mode 100644 src/document.h create mode 100644 src/document_manager.cpp create mode 100644 src/document_manager.h create mode 100644 src/documents.cpp create mode 100644 src/documents.h delete mode 100644 src/editor.cpp delete mode 100644 src/editor.h create mode 100644 src/events.cpp create mode 100644 src/events.h delete mode 100644 src/ffmpeg.cpp delete mode 100644 src/ffmpeg.h create mode 100644 src/filesystem.cpp create mode 100644 src/filesystem.h create mode 100644 src/font.cpp create mode 100644 src/font.h create mode 100644 src/frame_properties.cpp create mode 100644 src/frame_properties.h delete mode 100644 src/generate_preview.cpp delete mode 100644 src/generate_preview.h create mode 100644 src/icon.h create mode 100644 src/layers.cpp create mode 100644 src/layers.h create mode 100644 src/loader.cpp create mode 100644 src/loader.h delete mode 100644 src/main.h create mode 100644 src/math.cpp create mode 100644 src/math.h create mode 100644 src/nulls.cpp create mode 100644 src/nulls.h create mode 100644 src/onionskin.cpp create mode 100644 src/onionskin.h create mode 100644 src/playback.cpp create mode 100644 src/playback.h delete mode 100644 src/preview.cpp delete mode 100644 src/preview.h delete mode 100644 src/render.h delete mode 100644 src/snapshots.cpp delete mode 100644 src/snapshots.h create mode 100644 src/spritesheet_editor.cpp create mode 100644 src/spritesheet_editor.h create mode 100644 src/spritesheets.cpp create mode 100644 src/spritesheets.h create mode 100644 src/taskbar.cpp create mode 100644 src/taskbar.h create mode 100644 src/timeline.cpp create mode 100644 src/timeline.h create mode 100644 src/toast.cpp create mode 100644 src/toast.h create mode 100644 src/tools.cpp create mode 100644 src/tools.h create mode 100644 src/types.h create mode 100644 src/util.cpp create mode 100644 src/util.h delete mode 100644 src/window.cpp delete mode 100644 src/window.h create mode 100644 src/xml.cpp create mode 100644 src/xml.h diff --git a/.clang-format b/.clang-format index 01273ba..faa0e23 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,11 @@ -BasedOnStyle: LLVM -ColumnLimit: 160 +ColumnLimit: 120 PointerAlignment: Left -ReferenceAlignment: Left \ No newline at end of file +ReferenceAlignment: Left +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: true +CommentPragmas: '^' +BreakBeforeBraces: Allman +NamespaceIndentation: All +FixNamespaceComments: false +IndentCaseLabels: true +IndentPPDirectives: BeforeHash \ No newline at end of file diff --git a/.gitignore b/.gitignore index 620ce6f..f0a7d48 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,7 @@ packed/ vcpkg_installed/ out/ external/ -external/ -external/ -external/ workshop/resources +cmake-build-debug/ .vs/ +.idea/ diff --git a/.gitmodules b/.gitmodules index 2650de6..b1f95ec 100644 --- a/.gitmodules +++ b/.gitmodules @@ -11,3 +11,6 @@ [submodule "external/SDL"] path = external/SDL url = https://github.com/libsdl-org/SDL.git +[submodule "external/lunasvg"] + path = external/lunasvg + url = https://github.com/sammycage/lunasvg diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..71afeef --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,28 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug ANM2Ed", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/anm2ed", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "/usr/bin/gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing" + }, + { + "description": "Set disassembly flavor to Intel", + "text": "-gdb-set disassembly-flavor intel" + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..dff56b4 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,17 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "command": "cmake --build build --target anm2ed", + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": [ + "$gcc" + ] + } + ] +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index af48cca..2602b5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,90 +1,103 @@ -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.30) project(anm2ed CXX) -# Optional: auto-pick up vcpkg toolchain on Windows -if(WIN32 AND DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE) +if (WIN32 AND DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE) set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" - CACHE STRING "Vcpkg toolchain file") -endif() + CACHE STRING "Vcpkg toolchain file") +endif () -find_package(OpenGL REQUIRED) - -# Export compile_commands.json (for clangd, etc.) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -if(CMAKE_EXPORT_COMPILE_COMMANDS) +if (CMAKE_EXPORT_COMPILE_COMMANDS) execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink - ${CMAKE_BINARY_DIR}/compile_commands.json - ${CMAKE_SOURCE_DIR}/compile_commands.json + ${CMAKE_BINARY_DIR}/compile_commands.json + ${CMAKE_SOURCE_DIR}/compile_commands.json ) -endif() +endif () -set(GLAD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/include/glad/glad.cpp) - -set(IMGUI_SRC - external/imgui/imgui.cpp - external/imgui/imgui_draw.cpp - external/imgui/imgui_widgets.cpp - external/imgui/imgui_tables.cpp - external/imgui/backends/imgui_impl_sdl3.cpp - external/imgui/backends/imgui_impl_opengl3.cpp -) - -set(TINYXML2_SRC external/tinyxml2/tinyxml2.cpp) - -file(GLOB PROJECT_SRC CONFIGURE_DEPENDS - src/*.cpp - src/*.h -) - -add_executable(${PROJECT_NAME} - ${GLAD_SRC} - ${IMGUI_SRC} - ${TINYXML2_SRC} - ${PROJECT_SRC} -) +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) set(SDL_SHARED OFF CACHE BOOL "" FORCE) set(SDL_STATIC ON CACHE BOOL "" FORCE) add_subdirectory(external/SDL EXCLUDE_FROM_ALL) -if(WIN32) +add_subdirectory(external/lunasvg) + +set(GLAD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/include/glad/glad.cpp) + +set(IMGUI_SRC + external/imgui/imgui.cpp + external/imgui/imgui_draw.cpp + external/imgui/imgui_widgets.cpp + external/imgui/imgui_tables.cpp + external/imgui/backends/imgui_impl_sdl3.cpp + external/imgui/backends/imgui_impl_opengl3.cpp +) + +set(TINYXML2_SRC external/tinyxml2/tinyxml2.cpp) + +file(GLOB PROJECT_SRC CONFIGURE_DEPENDS + src/*.cpp + src/*.h +) + +add_executable(${PROJECT_NAME} + ${GLAD_SRC} + ${IMGUI_SRC} + ${TINYXML2_SRC} + ${PROJECT_SRC} +) + + +if (WIN32) enable_language(RC) target_sources(${PROJECT_NAME} PRIVATE Icon.rc) set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE TRUE) set_property(TARGET ${PROJECT_NAME} PROPERTY - MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") target_compile_options(${PROJECT_NAME} PRIVATE /EHsc) target_link_options(${PROJECT_NAME} PRIVATE /STACK:0xffffff) -else() +else () target_compile_options(${PROJECT_NAME} PRIVATE - -O2 -Wall -Wextra -pedantic -fmax-errors=1 + -O2 -Wall -Wextra -pedantic ) - if(CMAKE_BUILD_TYPE STREQUAL "Debug") + if (CMAKE_BUILD_TYPE STREQUAL "Debug") target_compile_definitions(${PROJECT_NAME} PRIVATE DEBUG) - target_compile_options(${PROJECT_NAME} PRIVATE -g) - endif() + target_compile_options(${PROJECT_NAME} PRIVATE -pg) + else () + set(CMAKE_BUILD_TYPE "Release") + endif () + target_link_libraries(${PROJECT_NAME} PRIVATE m) -endif() +endif () -target_compile_definitions(${PROJECT_NAME} PRIVATE IMGUI_DISABLE_OBSOLETE_FUNCTIONS IMGUI_DEBUG_PARANOID IMGUI_ENABLE_DOCKING) - -target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) - -target_include_directories(${PROJECT_NAME} PRIVATE - external - external/imgui - external/glm - external/tinyxml2 - include - include/glad - src +target_compile_definitions(${PROJECT_NAME} PRIVATE + IMGUI_DISABLE_OBSOLETE_FUNCTIONS + IMGUI_DEBUG_PARANOID + IMGUI_ENABLE_DOCKING ) -target_link_libraries(${PROJECT_NAME} PRIVATE OpenGL::GL SDL3::SDL3-static) +target_include_directories(${PROJECT_NAME} PRIVATE + external + external/imgui + external/glm + external/tinyxml2 + external/lunasvg + include + include/glad + src + src/imgui + src/resource + src/util +) + +target_link_libraries(${PROJECT_NAME} PRIVATE GL SDL3-static lunasvg) message(STATUS "System: ${CMAKE_SYSTEM_NAME}") message(STATUS "Project: ${PROJECT_NAME}") -message(STATUS "Build: ${CMAKE_BUILD_TYPE}") \ No newline at end of file +message(STATUS "Compiler: ${CMAKE_CXX_COMPILER}") +message(STATUS "Build: ${CMAKE_BUILD_TYPE}") diff --git a/CMakeSettings.json b/CMakeSettings.json deleted file mode 100644 index 137e083..0000000 --- a/CMakeSettings.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "configurations": [ - { - "name": "x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\build\\${name}", - "installRoot": "${projectDir}\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "" - }, - { - "name": "x64-Release", - "generator": "Ninja", - "configurationType": "Release", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\build\\${name}", - "installRoot": "${projectDir}\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "" - } - ] -} \ No newline at end of file diff --git a/assets/Icon.ico b/assets/Icon.ico deleted file mode 100644 index c9105c049fbb234969c0180bdaec80b6f1a4ef0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16958 zcmeI2QEtLO3`Dml=wHA4$uUq*!cltU-XPsTE5YFS#mcT$E1W7sW^B)l*Fqq*l(+hK zK9~CXSx#T2e3Vj7^{#J~?|QHAU$2Vgl@rJbK`j_#XL zPb==?M!#;}tB|MfTI+j}+tBO!Bhcs<(i73X<{srU>dB&u8~xIMa3>=>aCF{Ay?ed{ z8vXM8^ZdK*z|nm(>S@JYT>H%yyXJO)v-wrMJ1n{>+HbblHMawt&9Ca+VbM)7`gQy4 zt3nRxCVuiqxbkUC{F<+E?|Sk_xa!row|?c*nE1&b;mW5m@oT=uz3a&z z;i^~T-ujhKW8x=&ge#xM#IN}p_pT>@gsWbSd+S#|jftQ95l;P85A~Z3PyhY|^86qF zKVY`~CcXaYFHhgkqxr-?8jt#k=8yJA{82yAeBvLCNBu_g=zo?&R zervt0`$hdk^IPj}-7o4Vn%`RQ=zdZE`hAn?NBbjw(yx9srh4KZjgx-$t1;D&_DB4r zU;S!K^~66Lp8g+yZ|3>?6PRtkN$;!gKg}ocoIp-s{{;L`&mHKEYFYm&q+T!he7_B; hY(3YZ)ayDNa8eBMy=^%t8cqn-c& diff --git a/assets/Icon.rc b/assets/Icon.rc deleted file mode 100644 index 0599d31..0000000 --- a/assets/Icon.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON1 ICON DISCARDABLE "Icon.ico" diff --git a/assets/atlas.png b/assets/atlas.png deleted file mode 100644 index 630a22541669113873b6cdd33179b65569468e14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1242 zcmV<01SR{4P)!00009a7bBm000XT z000XT0n*)m`~Uy|4^T{0MF0Q*c6N6E|NmfMVE_OBKGjEU00003bW%=J0002`cEsKQ z00d%5L_t(o!|hpHZX`DhEP%W~?vMizAP>NRb^kNvgQ8kv&#tF8u>)+Z4|i)?)qE96 zwG8~iAfNxP+1Drl;IWJQ zQSJsv`;K8`0-8!30O9huxVsyGNUgSYSSV0ZM2N&G&PfYNjyKS+3Op*?BTF*K(FeLQ+jq zO-l)kN>`r1+#P^s(4h$^NF;0aGN@Bn2e-z`uiBWY68tjJf8&%J;dx+#l9; zsisLyURMA>SHdZwNA1Rxoqb)!&EBiF*s1-7T@e95&F%EgD!S}y*F|y6N&qMdfDDsT zY?iLVr2wKOZ4H73XciEfnuvm?cKW3*35QC>N`RS~x)PD3c8t0S#i^181J4235|}tu zY5`AGqB6Ca)hcNw&;s5WEljX`c8+&CZ?y6a>Bgu*c z(CRn|Ydw@$i(>bKX#-5KHw+M_S}*jjWKgiMIEZ~SwI@8aE1v}EZLQjLoB<@9PA7y; zc1jz&b!pex-nI1(Mu`C^Nk#$?>Ikrmc@a%ICBBYE|uI_?pHn>1$o@MGWEI9y6Wxe);9iQz^a35 z{R@Ep)WGZt#BJ>m9yU9tO0SXiu?yW8{$|+wS3d`g1s?)}6XLG|;2ZFJ0M_2`Wq_`( z{W5^5eAs?`2i8aF5PD9@0rtcHuf@L&XZmT ztka*D`@@`T+yL~K;tfEbS>6GN;axZVDd2m2kFObbKeqNi6%e1<9X=1R zR{oiH0Ds&C{PpP)ZUH{ut+yk6pG&vddOsh&$NzQw4Lj7;OFRCybpQYW07*qoM6N<$ Ef@Zxm+yDRo diff --git a/assets/atlas_data_write.sh b/assets/atlas_data_write.sh deleted file mode 100755 index 1cf391f..0000000 --- a/assets/atlas_data_write.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -INPUT="atlas.png" -OUTPUT="../src/PACKED.h" -TMP="atlas.bytes" - -# Ensure deps -command -v optipng >/dev/null 2>&1 || { echo "error: optipng not found in PATH" >&2; exit 1; } -command -v xxd >/dev/null 2>&1 || { echo "error: xxd not found in PATH" >&2; exit 1; } - -# 1) Optimize PNG in place -optipng -o7 "$INPUT" >/dev/null - -# 2) Extract ONLY the bytes from xxd -i (between '= {' and '};') -# Using awk avoids the earlier '{' vs '= {' mismatch bug. -xxd -i "$INPUT" \ - | awk ' - /= *\{/ {inside=1; next} - inside && /};/ {inside=0; exit} - inside {print} - ' > "$TMP" - -# Sanity check: make sure we got something -if ! [ -s "$TMP" ]; then - echo "error: failed to extract bytes from xxd output" >&2 - exit 1 -fi - -# 3) Replace ONLY the bytes inside TEXTURE_ATLAS[] initializer -# - Find the exact declaration line for TEXTURE_ATLAS -# - Print that line -# - On the following line with just '{', print it, then insert bytes, -# then skip everything until the matching '};' and print that once. -awk -v tmpfile="$TMP" ' - BEGIN { state=0 } # 0=normal, 1=after decl waiting for {, 2=skipping old bytes until }; - - # Match the TEXTURE_ATLAS declaration line precisely - $0 ~ /^[[:space:]]*const[[:space:]]+u8[[:space:]]+TEXTURE_ATLAS\[\][[:space:]]*=/ { - print; state=1; next - } - - # After the decl, the next line with a lone "{" starts the initializer - state==1 && $0 ~ /^[[:space:]]*{[[:space:]]*$/ { - print # print the opening brace line - while ((getline line < tmpfile) > 0) print line # insert fresh bytes - close(tmpfile) - state=2 # now skip old initializer content until we hit the closing "};" - next - } - - # While skipping, suppress lines until the closing "};", which we reprint once - state==2 { - if ($0 ~ /^[[:space:]]*};[[:space:]]*$/) { - print # print the closing brace+semicolon - state=0 - } - next - } - - # Default: pass through unchanged - { print } -' "$OUTPUT" > "$OUTPUT.tmp" && mv "$OUTPUT.tmp" "$OUTPUT" - -rm -f "$TMP" -echo "Updated $OUTPUT with optimized bytes from $INPUT." diff --git a/external/imgui b/external/imgui index 1ad9de5..0955992 160000 --- a/external/imgui +++ b/external/imgui @@ -1 +1 @@ -Subproject commit 1ad9de5aae5a7508f1bd7eb024b8f045c5844d34 +Subproject commit 0955992dd9dbfdff2b854efcb2a559265afa7923 diff --git a/include/nanosvg.h b/include/nanosvg.h new file mode 100644 index 0000000..a3dba05 --- /dev/null +++ b/include/nanosvg.h @@ -0,0 +1,3121 @@ +/* + * Copyright (c) 2013-14 Mikko Mononen memon@inside.org + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * The SVG parser is based on Anti-Grain Geometry 2.4 SVG example + * Copyright (C) 2002-2004 Maxim Shemanarev (McSeem) (http://www.antigrain.com/) + * + * Arc calculation code based on canvg (https://code.google.com/p/canvg/) + * + * Bounding box calculation based on http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html + * + */ + +#ifndef NANOSVG_H +#define NANOSVG_H + +#ifndef NANOSVG_CPLUSPLUS +#ifdef __cplusplus +extern "C" { +#endif +#endif + +// NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes. +// +// The library suits well for anything from rendering scalable icons in your editor application to prototyping a game. +// +// NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request! +// +// The shapes in the SVG images are transformed by the viewBox and converted to specified units. +// That is, you should get the same looking data as your designed in your favorite app. +// +// NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose +// to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters. +// +// The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'. +// DPI (dots-per-inch) controls how the unit conversion is done. +// +// If you don't know or care about the units stuff, "px" and 96 should get you going. + +/* Example Usage: + // Load SVG + NSVGimage* image; + image = nsvgParseFromFile("test.svg", "px", 96); + printf("size: %f x %f\n", image->width, image->height); + // Use... + for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) { + for (NSVGpath *path = shape->paths; path != NULL; path = path->next) { + for (int i = 0; i < path->npts-1; i += 3) { + float* p = &path->pts[i*2]; + drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]); + } + } + } + // Delete + nsvgDelete(image); +*/ + +enum NSVGpaintType { NSVG_PAINT_UNDEF = -1, NSVG_PAINT_NONE = 0, NSVG_PAINT_COLOR = 1, NSVG_PAINT_LINEAR_GRADIENT = 2, NSVG_PAINT_RADIAL_GRADIENT = 3 }; + +enum NSVGspreadType { NSVG_SPREAD_PAD = 0, NSVG_SPREAD_REFLECT = 1, NSVG_SPREAD_REPEAT = 2 }; + +enum NSVGlineJoin { NSVG_JOIN_MITER = 0, NSVG_JOIN_ROUND = 1, NSVG_JOIN_BEVEL = 2 }; + +enum NSVGlineCap { NSVG_CAP_BUTT = 0, NSVG_CAP_ROUND = 1, NSVG_CAP_SQUARE = 2 }; + +enum NSVGfillRule { NSVG_FILLRULE_NONZERO = 0, NSVG_FILLRULE_EVENODD = 1 }; + +enum NSVGflags { NSVG_FLAGS_VISIBLE = 0x01 }; + +enum NSVGpaintOrder { + NSVG_PAINT_FILL = 0x00, + NSVG_PAINT_MARKERS = 0x01, + NSVG_PAINT_STROKE = 0x02, +}; + +typedef struct NSVGgradientStop { + unsigned int color; + float offset; +} NSVGgradientStop; + +typedef struct NSVGgradient { + float xform[6]; + char spread; + float fx, fy; + int nstops; + NSVGgradientStop stops[1]; +} NSVGgradient; + +typedef struct NSVGpaint { + signed char type; + union { + unsigned int color; + NSVGgradient* gradient; + }; +} NSVGpaint; + +typedef struct NSVGpath { + float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ... + int npts; // Total number of bezier points. + char closed; // Flag indicating if shapes should be treated as closed. + float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. + struct NSVGpath* next; // Pointer to next path, or NULL if last element. +} NSVGpath; + +typedef struct NSVGshape { + char id[64]; // Optional 'id' attr of the shape or its group + NSVGpaint fill; // Fill paint + NSVGpaint stroke; // Stroke paint + float opacity; // Opacity of the shape. + float strokeWidth; // Stroke width (scaled). + float strokeDashOffset; // Stroke dash offset (scaled). + float strokeDashArray[8]; // Stroke dash array (scaled). + char strokeDashCount; // Number of dash values in dash array. + char strokeLineJoin; // Stroke join type. + char strokeLineCap; // Stroke cap type. + float miterLimit; // Miter limit + char fillRule; // Fill rule, see NSVGfillRule. + unsigned char paintOrder; // Encoded paint order (3×2-bit fields) see NSVGpaintOrder + unsigned char flags; // Logical or of NSVG_FLAGS_* flags + float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. + char fillGradient[64]; // Optional 'id' of fill gradient + char strokeGradient[64]; // Optional 'id' of stroke gradient + float xform[6]; // Root transformation for fill/stroke gradient + NSVGpath* paths; // Linked list of paths in the image. + struct NSVGshape* next; // Pointer to next shape, or NULL if last element. +} NSVGshape; + +typedef struct NSVGimage { + float width; // Width of the image. + float height; // Height of the image. + NSVGshape* shapes; // Linked list of shapes in the image. +} NSVGimage; + +// Parses SVG file from a file, returns SVG image as paths. +NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi); + +// Parses SVG file from a null terminated string, returns SVG image as paths. +// Important note: changes the string. +NSVGimage* nsvgParse(char* input, const char* units, float dpi); + +// Duplicates a path. +NSVGpath* nsvgDuplicatePath(NSVGpath* p); + +// Deletes an image. +void nsvgDelete(NSVGimage* image); + +#ifndef NANOSVG_CPLUSPLUS +#ifdef __cplusplus +} +#endif +#endif + +#ifdef NANOSVG_IMPLEMENTATION + +#include +#include +#include +#include + +#define NSVG_PI (3.14159265358979323846264338327f) +#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs. + +#define NSVG_ALIGN_MIN 0 +#define NSVG_ALIGN_MID 1 +#define NSVG_ALIGN_MAX 2 +#define NSVG_ALIGN_NONE 0 +#define NSVG_ALIGN_MEET 1 +#define NSVG_ALIGN_SLICE 2 + +#define NSVG_NOTUSED(v) \ + do { \ + (void)(1 ? (void)0 : ((void)(v))); \ + } while (0) +#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16)) + +#ifdef _MSC_VER +#pragma warning(disable : 4996) // Switch off security warnings +#pragma warning(disable : 4100) // Switch off unreferenced formal parameter warnings +#ifdef __cplusplus +#define NSVG_INLINE inline +#else +#define NSVG_INLINE +#endif +#else +#define NSVG_INLINE inline +#endif + +static int nsvg__isspace(char c) { return strchr(" \t\n\v\f\r", c) != 0; } + +static int nsvg__isdigit(char c) { return c >= '0' && c <= '9'; } + +static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; } +static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; } + +// Simple XML parser + +#define NSVG_XML_TAG 1 +#define NSVG_XML_CONTENT 2 +#define NSVG_XML_MAX_ATTRIBS 256 + +static void nsvg__parseContent(char* s, void (*contentCb)(void* ud, const char* s), void* ud) { + // Trim start white spaces + while (*s && nsvg__isspace(*s)) + s++; + if (!*s) + return; + + if (contentCb) + (*contentCb)(ud, s); +} + +static void nsvg__parseElement(char* s, void (*startelCb)(void* ud, const char* el, const char** attr), void (*endelCb)(void* ud, const char* el), void* ud) { + const char* attr[NSVG_XML_MAX_ATTRIBS]; + int nattr = 0; + char* name; + int start = 0; + int end = 0; + char quote; + + // Skip white space after the '<' + while (*s && nsvg__isspace(*s)) + s++; + + // Check if the tag is end tag + if (*s == '/') { + s++; + end = 1; + } else { + start = 1; + } + + // Skip comments, data and preprocessor stuff. + if (!*s || *s == '?' || *s == '!') + return; + + // Get tag name + name = s; + while (*s && !nsvg__isspace(*s)) + s++; + if (*s) { + *s++ = '\0'; + } + + // Get attribs + while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS - 3) { + char* name = NULL; + char* value = NULL; + + // Skip white space before the attrib name + while (*s && nsvg__isspace(*s)) + s++; + if (!*s) + break; + if (*s == '/') { + end = 1; + break; + } + name = s; + // Find end of the attrib name. + while (*s && !nsvg__isspace(*s) && *s != '=') + s++; + if (*s) { + *s++ = '\0'; + } + // Skip until the beginning of the value. + while (*s && *s != '\"' && *s != '\'') + s++; + if (!*s) + break; + quote = *s; + s++; + // Store value and find the end of it. + value = s; + while (*s && *s != quote) + s++; + if (*s) { + *s++ = '\0'; + } + + // Store only well formed attributes + if (name && value) { + attr[nattr++] = name; + attr[nattr++] = value; + } + } + + // List terminator + attr[nattr++] = 0; + attr[nattr++] = 0; + + // Call callbacks. + if (start && startelCb) + (*startelCb)(ud, name, attr); + if (end && endelCb) + (*endelCb)(ud, name); +} + +int nsvg__parseXML(char* input, void (*startelCb)(void* ud, const char* el, const char** attr), void (*endelCb)(void* ud, const char* el), + void (*contentCb)(void* ud, const char* s), void* ud) { + char* s = input; + char* mark = s; + int state = NSVG_XML_CONTENT; + while (*s) { + if (*s == '<' && state == NSVG_XML_CONTENT) { + // Start of a tag + *s++ = '\0'; + nsvg__parseContent(mark, contentCb, ud); + mark = s; + state = NSVG_XML_TAG; + } else if (*s == '>' && state == NSVG_XML_TAG) { + // Start of a content or new tag. + *s++ = '\0'; + nsvg__parseElement(mark, startelCb, endelCb, ud); + mark = s; + state = NSVG_XML_CONTENT; + } else { + s++; + } + } + + return 1; +} + +/* Simple SVG parser. */ + +#define NSVG_MAX_ATTR 128 + +enum NSVGgradientUnits { NSVG_USER_SPACE = 0, NSVG_OBJECT_SPACE = 1 }; + +#define NSVG_MAX_DASHES 8 + +enum NSVGunits { + NSVG_UNITS_USER, + NSVG_UNITS_PX, + NSVG_UNITS_PT, + NSVG_UNITS_PC, + NSVG_UNITS_MM, + NSVG_UNITS_CM, + NSVG_UNITS_IN, + NSVG_UNITS_PERCENT, + NSVG_UNITS_EM, + NSVG_UNITS_EX +}; + +typedef struct NSVGcoordinate { + float value; + int units; +} NSVGcoordinate; + +typedef struct NSVGlinearData { + NSVGcoordinate x1, y1, x2, y2; +} NSVGlinearData; + +typedef struct NSVGradialData { + NSVGcoordinate cx, cy, r, fx, fy; +} NSVGradialData; + +typedef struct NSVGgradientData { + char id[64]; + char ref[64]; + signed char type; + union { + NSVGlinearData linear; + NSVGradialData radial; + }; + char spread; + char units; + float xform[6]; + int nstops; + NSVGgradientStop* stops; + struct NSVGgradientData* next; +} NSVGgradientData; + +typedef struct NSVGattrib { + char id[64]; + float xform[6]; + unsigned int fillColor; + unsigned int strokeColor; + float opacity; + float fillOpacity; + float strokeOpacity; + char fillGradient[64]; + char strokeGradient[64]; + float strokeWidth; + float strokeDashOffset; + float strokeDashArray[NSVG_MAX_DASHES]; + int strokeDashCount; + char strokeLineJoin; + char strokeLineCap; + float miterLimit; + char fillRule; + float fontSize; + unsigned int stopColor; + float stopOpacity; + float stopOffset; + char hasFill; + char hasStroke; + char visible; + unsigned char paintOrder; +} NSVGattrib; + +typedef struct NSVGparser { + NSVGattrib attr[NSVG_MAX_ATTR]; + int attrHead; + float* pts; + int npts; + int cpts; + NSVGpath* plist; + NSVGimage* image; + NSVGgradientData* gradients; + NSVGshape* shapesTail; + float viewMinx, viewMiny, viewWidth, viewHeight; + int alignX, alignY, alignType; + float dpi; + char pathFlag; + char defsFlag; +} NSVGparser; + +static void nsvg__xformIdentity(float* t) { + t[0] = 1.0f; + t[1] = 0.0f; + t[2] = 0.0f; + t[3] = 1.0f; + t[4] = 0.0f; + t[5] = 0.0f; +} + +static void nsvg__xformSetTranslation(float* t, float tx, float ty) { + t[0] = 1.0f; + t[1] = 0.0f; + t[2] = 0.0f; + t[3] = 1.0f; + t[4] = tx; + t[5] = ty; +} + +static void nsvg__xformSetScale(float* t, float sx, float sy) { + t[0] = sx; + t[1] = 0.0f; + t[2] = 0.0f; + t[3] = sy; + t[4] = 0.0f; + t[5] = 0.0f; +} + +static void nsvg__xformSetSkewX(float* t, float a) { + t[0] = 1.0f; + t[1] = 0.0f; + t[2] = tanf(a); + t[3] = 1.0f; + t[4] = 0.0f; + t[5] = 0.0f; +} + +static void nsvg__xformSetSkewY(float* t, float a) { + t[0] = 1.0f; + t[1] = tanf(a); + t[2] = 0.0f; + t[3] = 1.0f; + t[4] = 0.0f; + t[5] = 0.0f; +} + +static void nsvg__xformSetRotation(float* t, float a) { + float cs = cosf(a), sn = sinf(a); + t[0] = cs; + t[1] = sn; + t[2] = -sn; + t[3] = cs; + t[4] = 0.0f; + t[5] = 0.0f; +} + +static void nsvg__xformMultiply(float* t, float* s) { + float t0 = t[0] * s[0] + t[1] * s[2]; + float t2 = t[2] * s[0] + t[3] * s[2]; + float t4 = t[4] * s[0] + t[5] * s[2] + s[4]; + t[1] = t[0] * s[1] + t[1] * s[3]; + t[3] = t[2] * s[1] + t[3] * s[3]; + t[5] = t[4] * s[1] + t[5] * s[3] + s[5]; + t[0] = t0; + t[2] = t2; + t[4] = t4; +} + +static void nsvg__xformInverse(float* inv, float* t) { + double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1]; + if (det > -1e-6 && det < 1e-6) { + nsvg__xformIdentity(t); + return; + } + invdet = 1.0 / det; + inv[0] = (float)(t[3] * invdet); + inv[2] = (float)(-t[2] * invdet); + inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet); + inv[1] = (float)(-t[1] * invdet); + inv[3] = (float)(t[0] * invdet); + inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet); +} + +static void nsvg__xformPremultiply(float* t, float* s) { + float s2[6]; + memcpy(s2, s, sizeof(float) * 6); + nsvg__xformMultiply(s2, t); + memcpy(t, s2, sizeof(float) * 6); +} + +static void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t) { + *dx = x * t[0] + y * t[2] + t[4]; + *dy = x * t[1] + y * t[3] + t[5]; +} + +static void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t) { + *dx = x * t[0] + y * t[2]; + *dy = x * t[1] + y * t[3]; +} + +#define NSVG_EPSILON (1e-12) + +static int nsvg__ptInBounds(float* pt, float* bounds) { return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3]; } + +static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3) { + double it = 1.0 - t; + return it * it * it * p0 + 3.0 * it * it * t * p1 + 3.0 * it * t * t * p2 + t * t * t * p3; +} + +static void nsvg__curveBounds(float* bounds, float* curve) { + int i, j, count; + double roots[2], a, b, c, b2ac, t, v; + float* v0 = &curve[0]; + float* v1 = &curve[2]; + float* v2 = &curve[4]; + float* v3 = &curve[6]; + + // Start the bounding box by end points + bounds[0] = nsvg__minf(v0[0], v3[0]); + bounds[1] = nsvg__minf(v0[1], v3[1]); + bounds[2] = nsvg__maxf(v0[0], v3[0]); + bounds[3] = nsvg__maxf(v0[1], v3[1]); + + // Bezier curve fits inside the convex hull of it's control points. + // If control points are inside the bounds, we're done. + if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds)) + return; + + // Add bezier curve inflection points in X and Y. + for (i = 0; i < 2; i++) { + a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i]; + b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i]; + c = 3.0 * v1[i] - 3.0 * v0[i]; + count = 0; + if (fabs(a) < NSVG_EPSILON) { + if (fabs(b) > NSVG_EPSILON) { + t = -c / b; + if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON) + roots[count++] = t; + } + } else { + b2ac = b * b - 4.0 * c * a; + if (b2ac > NSVG_EPSILON) { + t = (-b + sqrt(b2ac)) / (2.0 * a); + if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON) + roots[count++] = t; + t = (-b - sqrt(b2ac)) / (2.0 * a); + if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON) + roots[count++] = t; + } + } + for (j = 0; j < count; j++) { + v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]); + bounds[0 + i] = nsvg__minf(bounds[0 + i], (float)v); + bounds[2 + i] = nsvg__maxf(bounds[2 + i], (float)v); + } + } +} + +static unsigned char nsvg__encodePaintOrder(enum NSVGpaintOrder a, enum NSVGpaintOrder b, enum NSVGpaintOrder c) { + return (a & 0x03) | ((b & 0x03) << 2) | ((c & 0x03) << 4); +} + +static NSVGparser* nsvg__createParser(void) { + NSVGparser* p; + p = (NSVGparser*)malloc(sizeof(NSVGparser)); + if (p == NULL) + goto error; + memset(p, 0, sizeof(NSVGparser)); + + p->image = (NSVGimage*)malloc(sizeof(NSVGimage)); + if (p->image == NULL) + goto error; + memset(p->image, 0, sizeof(NSVGimage)); + + // Init style + nsvg__xformIdentity(p->attr[0].xform); + memset(p->attr[0].id, 0, sizeof p->attr[0].id); + p->attr[0].fillColor = NSVG_RGB(0, 0, 0); + p->attr[0].strokeColor = NSVG_RGB(0, 0, 0); + p->attr[0].opacity = 1; + p->attr[0].fillOpacity = 1; + p->attr[0].strokeOpacity = 1; + p->attr[0].stopOpacity = 1; + p->attr[0].strokeWidth = 1; + p->attr[0].strokeLineJoin = NSVG_JOIN_MITER; + p->attr[0].strokeLineCap = NSVG_CAP_BUTT; + p->attr[0].miterLimit = 4; + p->attr[0].fillRule = NSVG_FILLRULE_NONZERO; + p->attr[0].hasFill = 1; + p->attr[0].visible = 1; + p->attr[0].paintOrder = nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS); + + return p; + +error: + if (p) { + if (p->image) + free(p->image); + free(p); + } + return NULL; +} + +static void nsvg__deletePaths(NSVGpath* path) { + while (path) { + NSVGpath* next = path->next; + if (path->pts != NULL) + free(path->pts); + free(path); + path = next; + } +} + +static void nsvg__deletePaint(NSVGpaint* paint) { + if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT) + free(paint->gradient); +} + +static void nsvg__deleteGradientData(NSVGgradientData* grad) { + NSVGgradientData* next; + while (grad != NULL) { + next = grad->next; + free(grad->stops); + free(grad); + grad = next; + } +} + +static void nsvg__deleteParser(NSVGparser* p) { + if (p != NULL) { + nsvg__deletePaths(p->plist); + nsvg__deleteGradientData(p->gradients); + nsvgDelete(p->image); + free(p->pts); + free(p); + } +} + +static void nsvg__resetPath(NSVGparser* p) { p->npts = 0; } + +static void nsvg__addPoint(NSVGparser* p, float x, float y) { + if (p->npts + 1 > p->cpts) { + p->cpts = p->cpts ? p->cpts * 2 : 8; + p->pts = (float*)realloc(p->pts, p->cpts * 2 * sizeof(float)); + if (!p->pts) + return; + } + p->pts[p->npts * 2 + 0] = x; + p->pts[p->npts * 2 + 1] = y; + p->npts++; +} + +static void nsvg__moveTo(NSVGparser* p, float x, float y) { + if (p->npts > 0) { + p->pts[(p->npts - 1) * 2 + 0] = x; + p->pts[(p->npts - 1) * 2 + 1] = y; + } else { + nsvg__addPoint(p, x, y); + } +} + +static void nsvg__lineTo(NSVGparser* p, float x, float y) { + float px, py, dx, dy; + if (p->npts > 0) { + px = p->pts[(p->npts - 1) * 2 + 0]; + py = p->pts[(p->npts - 1) * 2 + 1]; + dx = x - px; + dy = y - py; + nsvg__addPoint(p, px + dx / 3.0f, py + dy / 3.0f); + nsvg__addPoint(p, x - dx / 3.0f, y - dy / 3.0f); + nsvg__addPoint(p, x, y); + } +} + +static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y) { + if (p->npts > 0) { + nsvg__addPoint(p, cpx1, cpy1); + nsvg__addPoint(p, cpx2, cpy2); + nsvg__addPoint(p, x, y); + } +} + +static NSVGattrib* nsvg__getAttr(NSVGparser* p) { return &p->attr[p->attrHead]; } + +static void nsvg__pushAttr(NSVGparser* p) { + if (p->attrHead < NSVG_MAX_ATTR - 1) { + p->attrHead++; + memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead - 1], sizeof(NSVGattrib)); + } +} + +static void nsvg__popAttr(NSVGparser* p) { + if (p->attrHead > 0) + p->attrHead--; +} + +static float nsvg__actualOrigX(NSVGparser* p) { return p->viewMinx; } + +static float nsvg__actualOrigY(NSVGparser* p) { return p->viewMiny; } + +static float nsvg__actualWidth(NSVGparser* p) { return p->viewWidth; } + +static float nsvg__actualHeight(NSVGparser* p) { return p->viewHeight; } + +static float nsvg__actualLength(NSVGparser* p) { + float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p); + return sqrtf(w * w + h * h) / sqrtf(2.0f); +} + +static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig, float length) { + NSVGattrib* attr = nsvg__getAttr(p); + switch (c.units) { + case NSVG_UNITS_USER: + return c.value; + case NSVG_UNITS_PX: + return c.value; + case NSVG_UNITS_PT: + return c.value / 72.0f * p->dpi; + case NSVG_UNITS_PC: + return c.value / 6.0f * p->dpi; + case NSVG_UNITS_MM: + return c.value / 25.4f * p->dpi; + case NSVG_UNITS_CM: + return c.value / 2.54f * p->dpi; + case NSVG_UNITS_IN: + return c.value * p->dpi; + case NSVG_UNITS_EM: + return c.value * attr->fontSize; + case NSVG_UNITS_EX: + return c.value * attr->fontSize * 0.52f; // x-height of Helvetica. + case NSVG_UNITS_PERCENT: + return orig + c.value / 100.0f * length; + default: + return c.value; + } + return c.value; +} + +static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id) { + NSVGgradientData* grad = p->gradients; + if (id == NULL || *id == '\0') + return NULL; + while (grad != NULL) { + if (strcmp(grad->id, id) == 0) + return grad; + grad = grad->next; + } + return NULL; +} + +static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, float* xform, signed char* paintType) { + NSVGgradientData* data = NULL; + NSVGgradientData* ref = NULL; + NSVGgradientStop* stops = NULL; + NSVGgradient* grad; + float ox, oy, sw, sh, sl; + int nstops = 0; + int refIter; + + data = nsvg__findGradientData(p, id); + if (data == NULL) + return NULL; + + // TODO: use ref to fill in all unset values too. + ref = data; + refIter = 0; + while (ref != NULL) { + NSVGgradientData* nextRef = NULL; + if (stops == NULL && ref->stops != NULL) { + stops = ref->stops; + nstops = ref->nstops; + break; + } + nextRef = nsvg__findGradientData(p, ref->ref); + if (nextRef == ref) + break; // prevent infite loops on malformed data + ref = nextRef; + refIter++; + if (refIter > 32) + break; // prevent infite loops on malformed data + } + if (stops == NULL) + return NULL; + + grad = (NSVGgradient*)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop) * (nstops - 1)); + if (grad == NULL) + return NULL; + + // The shape width and height. + if (data->units == NSVG_OBJECT_SPACE) { + ox = localBounds[0]; + oy = localBounds[1]; + sw = localBounds[2] - localBounds[0]; + sh = localBounds[3] - localBounds[1]; + } else { + ox = nsvg__actualOrigX(p); + oy = nsvg__actualOrigY(p); + sw = nsvg__actualWidth(p); + sh = nsvg__actualHeight(p); + } + sl = sqrtf(sw * sw + sh * sh) / sqrtf(2.0f); + + if (data->type == NSVG_PAINT_LINEAR_GRADIENT) { + float x1, y1, x2, y2, dx, dy; + x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw); + y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh); + x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw); + y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh); + // Calculate transform aligned to the line + dx = x2 - x1; + dy = y2 - y1; + grad->xform[0] = dy; + grad->xform[1] = -dx; + grad->xform[2] = dx; + grad->xform[3] = dy; + grad->xform[4] = x1; + grad->xform[5] = y1; + } else { + float cx, cy, fx, fy, r; + cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw); + cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh); + fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw); + fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh); + r = nsvg__convertToPixels(p, data->radial.r, 0, sl); + // Calculate transform aligned to the circle + grad->xform[0] = r; + grad->xform[1] = 0; + grad->xform[2] = 0; + grad->xform[3] = r; + grad->xform[4] = cx; + grad->xform[5] = cy; + grad->fx = fx / r; + grad->fy = fy / r; + } + + nsvg__xformMultiply(grad->xform, data->xform); + nsvg__xformMultiply(grad->xform, xform); + + grad->spread = data->spread; + memcpy(grad->stops, stops, nstops * sizeof(NSVGgradientStop)); + grad->nstops = nstops; + + *paintType = data->type; + + return grad; +} + +static float nsvg__getAverageScale(float* t) { + float sx = sqrtf(t[0] * t[0] + t[2] * t[2]); + float sy = sqrtf(t[1] * t[1] + t[3] * t[3]); + return (sx + sy) * 0.5f; +} + +static void nsvg__getLocalBounds(float* bounds, NSVGshape* shape, float* xform) { + NSVGpath* path; + float curve[4 * 2], curveBounds[4]; + int i, first = 1; + for (path = shape->paths; path != NULL; path = path->next) { + nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform); + for (i = 0; i < path->npts - 1; i += 3) { + nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i + 1) * 2], path->pts[(i + 1) * 2 + 1], xform); + nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i + 2) * 2], path->pts[(i + 2) * 2 + 1], xform); + nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i + 3) * 2], path->pts[(i + 3) * 2 + 1], xform); + nsvg__curveBounds(curveBounds, curve); + if (first) { + bounds[0] = curveBounds[0]; + bounds[1] = curveBounds[1]; + bounds[2] = curveBounds[2]; + bounds[3] = curveBounds[3]; + first = 0; + } else { + bounds[0] = nsvg__minf(bounds[0], curveBounds[0]); + bounds[1] = nsvg__minf(bounds[1], curveBounds[1]); + bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]); + bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]); + } + curve[0] = curve[6]; + curve[1] = curve[7]; + } + } +} + +static void nsvg__addShape(NSVGparser* p) { + NSVGattrib* attr = nsvg__getAttr(p); + float scale = 1.0f; + NSVGshape* shape; + NSVGpath* path; + int i; + + if (p->plist == NULL) + return; + + shape = (NSVGshape*)malloc(sizeof(NSVGshape)); + if (shape == NULL) + goto error; + memset(shape, 0, sizeof(NSVGshape)); + + memcpy(shape->id, attr->id, sizeof shape->id); + memcpy(shape->fillGradient, attr->fillGradient, sizeof shape->fillGradient); + memcpy(shape->strokeGradient, attr->strokeGradient, sizeof shape->strokeGradient); + memcpy(shape->xform, attr->xform, sizeof shape->xform); + scale = nsvg__getAverageScale(attr->xform); + shape->strokeWidth = attr->strokeWidth * scale; + shape->strokeDashOffset = attr->strokeDashOffset * scale; + shape->strokeDashCount = (char)attr->strokeDashCount; + for (i = 0; i < attr->strokeDashCount; i++) + shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale; + shape->strokeLineJoin = attr->strokeLineJoin; + shape->strokeLineCap = attr->strokeLineCap; + shape->miterLimit = attr->miterLimit; + shape->fillRule = attr->fillRule; + shape->opacity = attr->opacity; + shape->paintOrder = attr->paintOrder; + + shape->paths = p->plist; + p->plist = NULL; + + // Calculate shape bounds + shape->bounds[0] = shape->paths->bounds[0]; + shape->bounds[1] = shape->paths->bounds[1]; + shape->bounds[2] = shape->paths->bounds[2]; + shape->bounds[3] = shape->paths->bounds[3]; + for (path = shape->paths->next; path != NULL; path = path->next) { + shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]); + shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]); + shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]); + shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]); + } + + // Set fill + if (attr->hasFill == 0) { + shape->fill.type = NSVG_PAINT_NONE; + } else if (attr->hasFill == 1) { + shape->fill.type = NSVG_PAINT_COLOR; + shape->fill.color = attr->fillColor; + shape->fill.color |= (unsigned int)(attr->fillOpacity * 255) << 24; + } else if (attr->hasFill == 2) { + shape->fill.type = NSVG_PAINT_UNDEF; + } + + // Set stroke + if (attr->hasStroke == 0) { + shape->stroke.type = NSVG_PAINT_NONE; + } else if (attr->hasStroke == 1) { + shape->stroke.type = NSVG_PAINT_COLOR; + shape->stroke.color = attr->strokeColor; + shape->stroke.color |= (unsigned int)(attr->strokeOpacity * 255) << 24; + } else if (attr->hasStroke == 2) { + shape->stroke.type = NSVG_PAINT_UNDEF; + } + + // Set flags + shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00); + + // Add to tail + if (p->image->shapes == NULL) + p->image->shapes = shape; + else + p->shapesTail->next = shape; + p->shapesTail = shape; + + return; + +error: + if (shape) + free(shape); +} + +static void nsvg__addPath(NSVGparser* p, char closed) { + NSVGattrib* attr = nsvg__getAttr(p); + NSVGpath* path = NULL; + float bounds[4]; + float* curve; + int i; + + if (p->npts < 4) + return; + + if (closed) + nsvg__lineTo(p, p->pts[0], p->pts[1]); + + // Expect 1 + N*3 points (N = number of cubic bezier segments). + if ((p->npts % 3) != 1) + return; + + path = (NSVGpath*)malloc(sizeof(NSVGpath)); + if (path == NULL) + goto error; + memset(path, 0, sizeof(NSVGpath)); + + path->pts = (float*)malloc(p->npts * 2 * sizeof(float)); + if (path->pts == NULL) + goto error; + path->closed = closed; + path->npts = p->npts; + + // Transform path. + for (i = 0; i < p->npts; ++i) + nsvg__xformPoint(&path->pts[i * 2], &path->pts[i * 2 + 1], p->pts[i * 2], p->pts[i * 2 + 1], attr->xform); + + // Find bounds + for (i = 0; i < path->npts - 1; i += 3) { + curve = &path->pts[i * 2]; + nsvg__curveBounds(bounds, curve); + if (i == 0) { + path->bounds[0] = bounds[0]; + path->bounds[1] = bounds[1]; + path->bounds[2] = bounds[2]; + path->bounds[3] = bounds[3]; + } else { + path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]); + path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]); + path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]); + path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]); + } + } + + path->next = p->plist; + p->plist = path; + + return; + +error: + if (path != NULL) { + if (path->pts != NULL) + free(path->pts); + free(path); + } +} + +// We roll our own string to float because the std library one uses locale and messes things up. +static double nsvg__atof(const char* s) { + char* cur = (char*)s; + char* end = NULL; + double res = 0.0, sign = 1.0; + long long intPart = 0, fracPart = 0; + char hasIntPart = 0, hasFracPart = 0; + + // Parse optional sign + if (*cur == '+') { + cur++; + } else if (*cur == '-') { + sign = -1; + cur++; + } + + // Parse integer part + if (nsvg__isdigit(*cur)) { + // Parse digit sequence + intPart = strtoll(cur, &end, 10); + if (cur != end) { + res = (double)intPart; + hasIntPart = 1; + cur = end; + } + } + + // Parse fractional part. + if (*cur == '.') { + cur++; // Skip '.' + if (nsvg__isdigit(*cur)) { + // Parse digit sequence + fracPart = strtoll(cur, &end, 10); + if (cur != end) { + res += (double)fracPart / pow(10.0, (double)(end - cur)); + hasFracPart = 1; + cur = end; + } + } + } + + // A valid number should have integer or fractional part. + if (!hasIntPart && !hasFracPart) + return 0.0; + + // Parse optional exponent + if (*cur == 'e' || *cur == 'E') { + long expPart = 0; + cur++; // skip 'E' + expPart = strtol(cur, &end, 10); // Parse digit sequence with sign + if (cur != end) { + res *= pow(10.0, (double)expPart); + } + } + + return res * sign; +} + +static const char* nsvg__parseNumber(const char* s, char* it, const int size) { + const int last = size - 1; + int i = 0; + + // sign + if (*s == '-' || *s == '+') { + if (i < last) + it[i++] = *s; + s++; + } + // integer part + while (*s && nsvg__isdigit(*s)) { + if (i < last) + it[i++] = *s; + s++; + } + if (*s == '.') { + // decimal point + if (i < last) + it[i++] = *s; + s++; + // fraction part + while (*s && nsvg__isdigit(*s)) { + if (i < last) + it[i++] = *s; + s++; + } + } + // exponent + if ((*s == 'e' || *s == 'E') && (s[1] != 'm' && s[1] != 'x')) { + if (i < last) + it[i++] = *s; + s++; + if (*s == '-' || *s == '+') { + if (i < last) + it[i++] = *s; + s++; + } + while (*s && nsvg__isdigit(*s)) { + if (i < last) + it[i++] = *s; + s++; + } + } + it[i] = '\0'; + + return s; +} + +static const char* nsvg__getNextPathItemWhenArcFlag(const char* s, char* it) { + it[0] = '\0'; + while (*s && (nsvg__isspace(*s) || *s == ',')) + s++; + if (!*s) + return s; + if (*s == '0' || *s == '1') { + it[0] = *s++; + it[1] = '\0'; + return s; + } + return s; +} + +static const char* nsvg__getNextPathItem(const char* s, char* it) { + it[0] = '\0'; + // Skip white spaces and commas + while (*s && (nsvg__isspace(*s) || *s == ',')) + s++; + if (!*s) + return s; + if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) { + s = nsvg__parseNumber(s, it, 64); + } else { + // Parse command + it[0] = *s++; + it[1] = '\0'; + return s; + } + + return s; +} + +static unsigned int nsvg__parseColorHex(const char* str) { + unsigned int r = 0, g = 0, b = 0; + if (sscanf(str, "#%2x%2x%2x", &r, &g, &b) == 3) // 2 digit hex + return NSVG_RGB(r, g, b); + if (sscanf(str, "#%1x%1x%1x", &r, &g, &b) == 3) // 1 digit hex, e.g. #abc -> 0xccbbaa + return NSVG_RGB(r * 17, g * 17, b * 17); // same effect as (r<<4|r), (g<<4|g), .. + return NSVG_RGB(128, 128, 128); +} + +// Parse rgb color. The pointer 'str' must point at "rgb(" (4+ characters). +// This function returns gray (rgb(128, 128, 128) == '#808080') on parse errors +// for backwards compatibility. Note: other image viewers return black instead. + +static unsigned int nsvg__parseColorRGB(const char* str) { + int i; + unsigned int rgbi[3]; + float rgbf[3]; + // try decimal integers first + if (sscanf(str, "rgb(%u, %u, %u)", &rgbi[0], &rgbi[1], &rgbi[2]) != 3) { + // integers failed, try percent values (float, locale independent) + const char delimiter[3] = {',', ',', ')'}; + str += 4; // skip "rgb(" + for (i = 0; i < 3; i++) { + while (*str && (nsvg__isspace(*str))) + str++; // skip leading spaces + if (*str == '+') + str++; // skip '+' (don't allow '-') + if (!*str) + break; + rgbf[i] = nsvg__atof(str); + + // Note 1: it would be great if nsvg__atof() returned how many + // bytes it consumed but it doesn't. We need to skip the number, + // the '%' character, spaces, and the delimiter ',' or ')'. + + // Note 2: The following code does not allow values like "33.%", + // i.e. a decimal point w/o fractional part, but this is consistent + // with other image viewers, e.g. firefox, chrome, eog, gimp. + + while (*str && nsvg__isdigit(*str)) + str++; // skip integer part + if (*str == '.') { + str++; + if (!nsvg__isdigit(*str)) + break; // error: no digit after '.' + while (*str && nsvg__isdigit(*str)) + str++; // skip fractional part + } + if (*str == '%') + str++; + else + break; + while (*str && nsvg__isspace(*str)) + str++; + if (*str == delimiter[i]) + str++; + else + break; + } + if (i == 3) { + rgbi[0] = roundf(rgbf[0] * 2.55f); + rgbi[1] = roundf(rgbf[1] * 2.55f); + rgbi[2] = roundf(rgbf[2] * 2.55f); + } else { + rgbi[0] = rgbi[1] = rgbi[2] = 128; + } + } + // clip values as the CSS spec requires + for (i = 0; i < 3; i++) { + if (rgbi[i] > 255) + rgbi[i] = 255; + } + return NSVG_RGB(rgbi[0], rgbi[1], rgbi[2]); +} + +typedef struct NSVGNamedColor { + const char* name; + unsigned int color; +} NSVGNamedColor; + +NSVGNamedColor nsvg__colors[] = { + + {"red", NSVG_RGB(255, 0, 0)}, + {"green", NSVG_RGB(0, 128, 0)}, + {"blue", NSVG_RGB(0, 0, 255)}, + {"yellow", NSVG_RGB(255, 255, 0)}, + {"cyan", NSVG_RGB(0, 255, 255)}, + {"magenta", NSVG_RGB(255, 0, 255)}, + {"black", NSVG_RGB(0, 0, 0)}, + {"grey", NSVG_RGB(128, 128, 128)}, + {"gray", NSVG_RGB(128, 128, 128)}, + {"white", NSVG_RGB(255, 255, 255)}, + +#ifdef NANOSVG_ALL_COLOR_KEYWORDS + {"aliceblue", NSVG_RGB(240, 248, 255)}, + {"antiquewhite", NSVG_RGB(250, 235, 215)}, + {"aqua", NSVG_RGB(0, 255, 255)}, + {"aquamarine", NSVG_RGB(127, 255, 212)}, + {"azure", NSVG_RGB(240, 255, 255)}, + {"beige", NSVG_RGB(245, 245, 220)}, + {"bisque", NSVG_RGB(255, 228, 196)}, + {"blanchedalmond", NSVG_RGB(255, 235, 205)}, + {"blueviolet", NSVG_RGB(138, 43, 226)}, + {"brown", NSVG_RGB(165, 42, 42)}, + {"burlywood", NSVG_RGB(222, 184, 135)}, + {"cadetblue", NSVG_RGB(95, 158, 160)}, + {"chartreuse", NSVG_RGB(127, 255, 0)}, + {"chocolate", NSVG_RGB(210, 105, 30)}, + {"coral", NSVG_RGB(255, 127, 80)}, + {"cornflowerblue", NSVG_RGB(100, 149, 237)}, + {"cornsilk", NSVG_RGB(255, 248, 220)}, + {"crimson", NSVG_RGB(220, 20, 60)}, + {"darkblue", NSVG_RGB(0, 0, 139)}, + {"darkcyan", NSVG_RGB(0, 139, 139)}, + {"darkgoldenrod", NSVG_RGB(184, 134, 11)}, + {"darkgray", NSVG_RGB(169, 169, 169)}, + {"darkgreen", NSVG_RGB(0, 100, 0)}, + {"darkgrey", NSVG_RGB(169, 169, 169)}, + {"darkkhaki", NSVG_RGB(189, 183, 107)}, + {"darkmagenta", NSVG_RGB(139, 0, 139)}, + {"darkolivegreen", NSVG_RGB(85, 107, 47)}, + {"darkorange", NSVG_RGB(255, 140, 0)}, + {"darkorchid", NSVG_RGB(153, 50, 204)}, + {"darkred", NSVG_RGB(139, 0, 0)}, + {"darksalmon", NSVG_RGB(233, 150, 122)}, + {"darkseagreen", NSVG_RGB(143, 188, 143)}, + {"darkslateblue", NSVG_RGB(72, 61, 139)}, + {"darkslategray", NSVG_RGB(47, 79, 79)}, + {"darkslategrey", NSVG_RGB(47, 79, 79)}, + {"darkturquoise", NSVG_RGB(0, 206, 209)}, + {"darkviolet", NSVG_RGB(148, 0, 211)}, + {"deeppink", NSVG_RGB(255, 20, 147)}, + {"deepskyblue", NSVG_RGB(0, 191, 255)}, + {"dimgray", NSVG_RGB(105, 105, 105)}, + {"dimgrey", NSVG_RGB(105, 105, 105)}, + {"dodgerblue", NSVG_RGB(30, 144, 255)}, + {"firebrick", NSVG_RGB(178, 34, 34)}, + {"floralwhite", NSVG_RGB(255, 250, 240)}, + {"forestgreen", NSVG_RGB(34, 139, 34)}, + {"fuchsia", NSVG_RGB(255, 0, 255)}, + {"gainsboro", NSVG_RGB(220, 220, 220)}, + {"ghostwhite", NSVG_RGB(248, 248, 255)}, + {"gold", NSVG_RGB(255, 215, 0)}, + {"goldenrod", NSVG_RGB(218, 165, 32)}, + {"greenyellow", NSVG_RGB(173, 255, 47)}, + {"honeydew", NSVG_RGB(240, 255, 240)}, + {"hotpink", NSVG_RGB(255, 105, 180)}, + {"indianred", NSVG_RGB(205, 92, 92)}, + {"indigo", NSVG_RGB(75, 0, 130)}, + {"ivory", NSVG_RGB(255, 255, 240)}, + {"khaki", NSVG_RGB(240, 230, 140)}, + {"lavender", NSVG_RGB(230, 230, 250)}, + {"lavenderblush", NSVG_RGB(255, 240, 245)}, + {"lawngreen", NSVG_RGB(124, 252, 0)}, + {"lemonchiffon", NSVG_RGB(255, 250, 205)}, + {"lightblue", NSVG_RGB(173, 216, 230)}, + {"lightcoral", NSVG_RGB(240, 128, 128)}, + {"lightcyan", NSVG_RGB(224, 255, 255)}, + {"lightgoldenrodyellow", NSVG_RGB(250, 250, 210)}, + {"lightgray", NSVG_RGB(211, 211, 211)}, + {"lightgreen", NSVG_RGB(144, 238, 144)}, + {"lightgrey", NSVG_RGB(211, 211, 211)}, + {"lightpink", NSVG_RGB(255, 182, 193)}, + {"lightsalmon", NSVG_RGB(255, 160, 122)}, + {"lightseagreen", NSVG_RGB(32, 178, 170)}, + {"lightskyblue", NSVG_RGB(135, 206, 250)}, + {"lightslategray", NSVG_RGB(119, 136, 153)}, + {"lightslategrey", NSVG_RGB(119, 136, 153)}, + {"lightsteelblue", NSVG_RGB(176, 196, 222)}, + {"lightyellow", NSVG_RGB(255, 255, 224)}, + {"lime", NSVG_RGB(0, 255, 0)}, + {"limegreen", NSVG_RGB(50, 205, 50)}, + {"linen", NSVG_RGB(250, 240, 230)}, + {"maroon", NSVG_RGB(128, 0, 0)}, + {"mediumaquamarine", NSVG_RGB(102, 205, 170)}, + {"mediumblue", NSVG_RGB(0, 0, 205)}, + {"mediumorchid", NSVG_RGB(186, 85, 211)}, + {"mediumpurple", NSVG_RGB(147, 112, 219)}, + {"mediumseagreen", NSVG_RGB(60, 179, 113)}, + {"mediumslateblue", NSVG_RGB(123, 104, 238)}, + {"mediumspringgreen", NSVG_RGB(0, 250, 154)}, + {"mediumturquoise", NSVG_RGB(72, 209, 204)}, + {"mediumvioletred", NSVG_RGB(199, 21, 133)}, + {"midnightblue", NSVG_RGB(25, 25, 112)}, + {"mintcream", NSVG_RGB(245, 255, 250)}, + {"mistyrose", NSVG_RGB(255, 228, 225)}, + {"moccasin", NSVG_RGB(255, 228, 181)}, + {"navajowhite", NSVG_RGB(255, 222, 173)}, + {"navy", NSVG_RGB(0, 0, 128)}, + {"oldlace", NSVG_RGB(253, 245, 230)}, + {"olive", NSVG_RGB(128, 128, 0)}, + {"olivedrab", NSVG_RGB(107, 142, 35)}, + {"orange", NSVG_RGB(255, 165, 0)}, + {"orangered", NSVG_RGB(255, 69, 0)}, + {"orchid", NSVG_RGB(218, 112, 214)}, + {"palegoldenrod", NSVG_RGB(238, 232, 170)}, + {"palegreen", NSVG_RGB(152, 251, 152)}, + {"paleturquoise", NSVG_RGB(175, 238, 238)}, + {"palevioletred", NSVG_RGB(219, 112, 147)}, + {"papayawhip", NSVG_RGB(255, 239, 213)}, + {"peachpuff", NSVG_RGB(255, 218, 185)}, + {"peru", NSVG_RGB(205, 133, 63)}, + {"pink", NSVG_RGB(255, 192, 203)}, + {"plum", NSVG_RGB(221, 160, 221)}, + {"powderblue", NSVG_RGB(176, 224, 230)}, + {"purple", NSVG_RGB(128, 0, 128)}, + {"rosybrown", NSVG_RGB(188, 143, 143)}, + {"royalblue", NSVG_RGB(65, 105, 225)}, + {"saddlebrown", NSVG_RGB(139, 69, 19)}, + {"salmon", NSVG_RGB(250, 128, 114)}, + {"sandybrown", NSVG_RGB(244, 164, 96)}, + {"seagreen", NSVG_RGB(46, 139, 87)}, + {"seashell", NSVG_RGB(255, 245, 238)}, + {"sienna", NSVG_RGB(160, 82, 45)}, + {"silver", NSVG_RGB(192, 192, 192)}, + {"skyblue", NSVG_RGB(135, 206, 235)}, + {"slateblue", NSVG_RGB(106, 90, 205)}, + {"slategray", NSVG_RGB(112, 128, 144)}, + {"slategrey", NSVG_RGB(112, 128, 144)}, + {"snow", NSVG_RGB(255, 250, 250)}, + {"springgreen", NSVG_RGB(0, 255, 127)}, + {"steelblue", NSVG_RGB(70, 130, 180)}, + {"tan", NSVG_RGB(210, 180, 140)}, + {"teal", NSVG_RGB(0, 128, 128)}, + {"thistle", NSVG_RGB(216, 191, 216)}, + {"tomato", NSVG_RGB(255, 99, 71)}, + {"turquoise", NSVG_RGB(64, 224, 208)}, + {"violet", NSVG_RGB(238, 130, 238)}, + {"wheat", NSVG_RGB(245, 222, 179)}, + {"whitesmoke", NSVG_RGB(245, 245, 245)}, + {"yellowgreen", NSVG_RGB(154, 205, 50)}, +#endif +}; + +static unsigned int nsvg__parseColorName(const char* str) { + int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor); + + for (i = 0; i < ncolors; i++) { + if (strcmp(nsvg__colors[i].name, str) == 0) { + return nsvg__colors[i].color; + } + } + + return NSVG_RGB(128, 128, 128); +} + +static unsigned int nsvg__parseColor(const char* str) { + size_t len = 0; + while (*str == ' ') + ++str; + len = strlen(str); + if (len >= 1 && *str == '#') + return nsvg__parseColorHex(str); + else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(') + return nsvg__parseColorRGB(str); + return nsvg__parseColorName(str); +} + +static float nsvg__parseOpacity(const char* str) { + float val = nsvg__atof(str); + if (val < 0.0f) + val = 0.0f; + if (val > 1.0f) + val = 1.0f; + return val; +} + +static float nsvg__parseMiterLimit(const char* str) { + float val = nsvg__atof(str); + if (val < 0.0f) + val = 0.0f; + return val; +} + +static int nsvg__parseUnits(const char* units) { + if (units[0] == 'p' && units[1] == 'x') + return NSVG_UNITS_PX; + else if (units[0] == 'p' && units[1] == 't') + return NSVG_UNITS_PT; + else if (units[0] == 'p' && units[1] == 'c') + return NSVG_UNITS_PC; + else if (units[0] == 'm' && units[1] == 'm') + return NSVG_UNITS_MM; + else if (units[0] == 'c' && units[1] == 'm') + return NSVG_UNITS_CM; + else if (units[0] == 'i' && units[1] == 'n') + return NSVG_UNITS_IN; + else if (units[0] == '%') + return NSVG_UNITS_PERCENT; + else if (units[0] == 'e' && units[1] == 'm') + return NSVG_UNITS_EM; + else if (units[0] == 'e' && units[1] == 'x') + return NSVG_UNITS_EX; + return NSVG_UNITS_USER; +} + +static int nsvg__isCoordinate(const char* s) { + // optional sign + if (*s == '-' || *s == '+') + s++; + // must have at least one digit, or start by a dot + return (nsvg__isdigit(*s) || *s == '.'); +} + +static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str) { + NSVGcoordinate coord = {0, NSVG_UNITS_USER}; + char buf[64]; + coord.units = nsvg__parseUnits(nsvg__parseNumber(str, buf, 64)); + coord.value = nsvg__atof(buf); + return coord; +} + +static NSVGcoordinate nsvg__coord(float v, int units) { + NSVGcoordinate coord = {v, units}; + return coord; +} + +static float nsvg__parseCoordinate(NSVGparser* p, const char* str, float orig, float length) { + NSVGcoordinate coord = nsvg__parseCoordinateRaw(str); + return nsvg__convertToPixels(p, coord, orig, length); +} + +static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na) { + const char* end; + const char* ptr; + char it[64]; + + *na = 0; + ptr = str; + while (*ptr && *ptr != '(') + ++ptr; + if (*ptr == 0) + return 1; + end = ptr; + while (*end && *end != ')') + ++end; + if (*end == 0) + return 1; + + while (ptr < end) { + if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) { + if (*na >= maxNa) + return 0; + ptr = nsvg__parseNumber(ptr, it, 64); + args[(*na)++] = (float)nsvg__atof(it); + } else { + ++ptr; + } + } + return (int)(end - str); +} + +static int nsvg__parseMatrix(float* xform, const char* str) { + float t[6]; + int na = 0; + int len = nsvg__parseTransformArgs(str, t, 6, &na); + if (na != 6) + return len; + memcpy(xform, t, sizeof(float) * 6); + return len; +} + +static int nsvg__parseTranslate(float* xform, const char* str) { + float args[2]; + float t[6]; + int na = 0; + int len = nsvg__parseTransformArgs(str, args, 2, &na); + if (na == 1) + args[1] = 0.0; + + nsvg__xformSetTranslation(t, args[0], args[1]); + memcpy(xform, t, sizeof(float) * 6); + return len; +} + +static int nsvg__parseScale(float* xform, const char* str) { + float args[2]; + int na = 0; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 2, &na); + if (na == 1) + args[1] = args[0]; + nsvg__xformSetScale(t, args[0], args[1]); + memcpy(xform, t, sizeof(float) * 6); + return len; +} + +static int nsvg__parseSkewX(float* xform, const char* str) { + float args[1]; + int na = 0; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 1, &na); + nsvg__xformSetSkewX(t, args[0] / 180.0f * NSVG_PI); + memcpy(xform, t, sizeof(float) * 6); + return len; +} + +static int nsvg__parseSkewY(float* xform, const char* str) { + float args[1]; + int na = 0; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 1, &na); + nsvg__xformSetSkewY(t, args[0] / 180.0f * NSVG_PI); + memcpy(xform, t, sizeof(float) * 6); + return len; +} + +static int nsvg__parseRotate(float* xform, const char* str) { + float args[3]; + int na = 0; + float m[6]; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 3, &na); + if (na == 1) + args[1] = args[2] = 0.0f; + nsvg__xformIdentity(m); + + if (na > 1) { + nsvg__xformSetTranslation(t, -args[1], -args[2]); + nsvg__xformMultiply(m, t); + } + + nsvg__xformSetRotation(t, args[0] / 180.0f * NSVG_PI); + nsvg__xformMultiply(m, t); + + if (na > 1) { + nsvg__xformSetTranslation(t, args[1], args[2]); + nsvg__xformMultiply(m, t); + } + + memcpy(xform, m, sizeof(float) * 6); + + return len; +} + +static void nsvg__parseTransform(float* xform, const char* str) { + float t[6]; + int len; + nsvg__xformIdentity(xform); + while (*str) { + if (strncmp(str, "matrix", 6) == 0) + len = nsvg__parseMatrix(t, str); + else if (strncmp(str, "translate", 9) == 0) + len = nsvg__parseTranslate(t, str); + else if (strncmp(str, "scale", 5) == 0) + len = nsvg__parseScale(t, str); + else if (strncmp(str, "rotate", 6) == 0) + len = nsvg__parseRotate(t, str); + else if (strncmp(str, "skewX", 5) == 0) + len = nsvg__parseSkewX(t, str); + else if (strncmp(str, "skewY", 5) == 0) + len = nsvg__parseSkewY(t, str); + else { + ++str; + continue; + } + if (len != 0) { + str += len; + } else { + ++str; + continue; + } + + nsvg__xformPremultiply(xform, t); + } +} + +static void nsvg__parseUrl(char* id, const char* str) { + int i = 0; + str += 4; // "url("; + if (*str && *str == '#') + str++; + while (i < 63 && *str && *str != ')') { + id[i] = *str++; + i++; + } + id[i] = '\0'; +} + +static char nsvg__parseLineCap(const char* str) { + if (strcmp(str, "butt") == 0) + return NSVG_CAP_BUTT; + else if (strcmp(str, "round") == 0) + return NSVG_CAP_ROUND; + else if (strcmp(str, "square") == 0) + return NSVG_CAP_SQUARE; + // TODO: handle inherit. + return NSVG_CAP_BUTT; +} + +static char nsvg__parseLineJoin(const char* str) { + if (strcmp(str, "miter") == 0) + return NSVG_JOIN_MITER; + else if (strcmp(str, "round") == 0) + return NSVG_JOIN_ROUND; + else if (strcmp(str, "bevel") == 0) + return NSVG_JOIN_BEVEL; + // TODO: handle inherit. + return NSVG_JOIN_MITER; +} + +static char nsvg__parseFillRule(const char* str) { + if (strcmp(str, "nonzero") == 0) + return NSVG_FILLRULE_NONZERO; + else if (strcmp(str, "evenodd") == 0) + return NSVG_FILLRULE_EVENODD; + // TODO: handle inherit. + return NSVG_FILLRULE_NONZERO; +} + +static unsigned char nsvg__parsePaintOrder(const char* str) { + if (strcmp(str, "normal") == 0 || strcmp(str, "fill stroke markers") == 0) + return nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS); + else if (strcmp(str, "fill markers stroke") == 0) + return nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_MARKERS, NSVG_PAINT_STROKE); + else if (strcmp(str, "markers fill stroke") == 0) + return nsvg__encodePaintOrder(NSVG_PAINT_MARKERS, NSVG_PAINT_FILL, NSVG_PAINT_STROKE); + else if (strcmp(str, "markers stroke fill") == 0) + return nsvg__encodePaintOrder(NSVG_PAINT_MARKERS, NSVG_PAINT_STROKE, NSVG_PAINT_FILL); + else if (strcmp(str, "stroke fill markers") == 0) + return nsvg__encodePaintOrder(NSVG_PAINT_STROKE, NSVG_PAINT_FILL, NSVG_PAINT_MARKERS); + else if (strcmp(str, "stroke markers fill") == 0) + return nsvg__encodePaintOrder(NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS, NSVG_PAINT_FILL); + // TODO: handle inherit. + return nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS); +} + +static const char* nsvg__getNextDashItem(const char* s, char* it) { + int n = 0; + it[0] = '\0'; + // Skip white spaces and commas + while (*s && (nsvg__isspace(*s) || *s == ',')) + s++; + // Advance until whitespace, comma or end. + while (*s && (!nsvg__isspace(*s) && *s != ',')) { + if (n < 63) + it[n++] = *s; + s++; + } + it[n++] = '\0'; + return s; +} + +static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray) { + char item[64]; + int count = 0, i; + float sum = 0.0f; + + // Handle "none" + if (str[0] == 'n') + return 0; + + // Parse dashes + while (*str) { + str = nsvg__getNextDashItem(str, item); + if (!*item) + break; + if (count < NSVG_MAX_DASHES) + strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p))); + } + + for (i = 0; i < count; i++) + sum += strokeDashArray[i]; + if (sum <= 1e-6f) + count = 0; + + return count; +} + +static void nsvg__parseStyle(NSVGparser* p, const char* str); + +static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value) { + float xform[6]; + NSVGattrib* attr = nsvg__getAttr(p); + if (!attr) + return 0; + + if (strcmp(name, "style") == 0) { + nsvg__parseStyle(p, value); + } else if (strcmp(name, "display") == 0) { + if (strcmp(value, "none") == 0) + attr->visible = 0; + // Don't reset ->visible on display:inline, one display:none hides the whole subtree + + } else if (strcmp(name, "fill") == 0) { + if (strcmp(value, "none") == 0) { + attr->hasFill = 0; + } else if (strncmp(value, "url(", 4) == 0) { + attr->hasFill = 2; + nsvg__parseUrl(attr->fillGradient, value); + } else { + attr->hasFill = 1; + attr->fillColor = nsvg__parseColor(value); + } + } else if (strcmp(name, "opacity") == 0) { + attr->opacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "fill-opacity") == 0) { + attr->fillOpacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "stroke") == 0) { + if (strcmp(value, "none") == 0) { + attr->hasStroke = 0; + } else if (strncmp(value, "url(", 4) == 0) { + attr->hasStroke = 2; + nsvg__parseUrl(attr->strokeGradient, value); + } else { + attr->hasStroke = 1; + attr->strokeColor = nsvg__parseColor(value); + } + } else if (strcmp(name, "stroke-width") == 0) { + attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); + } else if (strcmp(name, "stroke-dasharray") == 0) { + attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray); + } else if (strcmp(name, "stroke-dashoffset") == 0) { + attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); + } else if (strcmp(name, "stroke-opacity") == 0) { + attr->strokeOpacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "stroke-linecap") == 0) { + attr->strokeLineCap = nsvg__parseLineCap(value); + } else if (strcmp(name, "stroke-linejoin") == 0) { + attr->strokeLineJoin = nsvg__parseLineJoin(value); + } else if (strcmp(name, "stroke-miterlimit") == 0) { + attr->miterLimit = nsvg__parseMiterLimit(value); + } else if (strcmp(name, "fill-rule") == 0) { + attr->fillRule = nsvg__parseFillRule(value); + } else if (strcmp(name, "font-size") == 0) { + attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); + } else if (strcmp(name, "transform") == 0) { + nsvg__parseTransform(xform, value); + nsvg__xformPremultiply(attr->xform, xform); + } else if (strcmp(name, "stop-color") == 0) { + attr->stopColor = nsvg__parseColor(value); + } else if (strcmp(name, "stop-opacity") == 0) { + attr->stopOpacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "offset") == 0) { + attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f); + } else if (strcmp(name, "paint-order") == 0) { + attr->paintOrder = nsvg__parsePaintOrder(value); + } else if (strcmp(name, "id") == 0) { + strncpy(attr->id, value, 63); + attr->id[63] = '\0'; + } else { + return 0; + } + return 1; +} + +static int nsvg__parseNameValue(NSVGparser* p, const char* start, const char* end) { + const char* str; + const char* val; + char name[512]; + char value[512]; + int n; + + str = start; + while (str < end && *str != ':') + ++str; + + val = str; + + // Right Trim + while (str > start && (*str == ':' || nsvg__isspace(*str))) + --str; + ++str; + + n = (int)(str - start); + if (n > 511) + n = 511; + if (n) + memcpy(name, start, n); + name[n] = 0; + + while (val < end && (*val == ':' || nsvg__isspace(*val))) + ++val; + + n = (int)(end - val); + if (n > 511) + n = 511; + if (n) + memcpy(value, val, n); + value[n] = 0; + + return nsvg__parseAttr(p, name, value); +} + +static void nsvg__parseStyle(NSVGparser* p, const char* str) { + const char* start; + const char* end; + + while (*str) { + // Left Trim + while (*str && nsvg__isspace(*str)) + ++str; + start = str; + while (*str && *str != ';') + ++str; + end = str; + + // Right Trim + while (end > start && (*end == ';' || nsvg__isspace(*end))) + --end; + ++end; + + nsvg__parseNameValue(p, start, end); + if (*str) + ++str; + } +} + +static void nsvg__parseAttribs(NSVGparser* p, const char** attr) { + int i; + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "style") == 0) + nsvg__parseStyle(p, attr[i + 1]); + else + nsvg__parseAttr(p, attr[i], attr[i + 1]); + } +} + +static int nsvg__getArgsPerElement(char cmd) { + switch (cmd) { + case 'v': + case 'V': + case 'h': + case 'H': + return 1; + case 'm': + case 'M': + case 'l': + case 'L': + case 't': + case 'T': + return 2; + case 'q': + case 'Q': + case 's': + case 'S': + return 4; + case 'c': + case 'C': + return 6; + case 'a': + case 'A': + return 7; + case 'z': + case 'Z': + return 0; + } + return -1; +} + +static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) { + if (rel) { + *cpx += args[0]; + *cpy += args[1]; + } else { + *cpx = args[0]; + *cpy = args[1]; + } + nsvg__moveTo(p, *cpx, *cpy); +} + +static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) { + if (rel) { + *cpx += args[0]; + *cpy += args[1]; + } else { + *cpx = args[0]; + *cpy = args[1]; + } + nsvg__lineTo(p, *cpx, *cpy); +} + +static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) { + if (rel) + *cpx += args[0]; + else + *cpx = args[0]; + nsvg__lineTo(p, *cpx, *cpy); +} + +static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) { + if (rel) + *cpy += args[0]; + else + *cpy = args[0]; + nsvg__lineTo(p, *cpx, *cpy); +} + +static void nsvg__pathCubicBezTo(NSVGparser* p, float* cpx, float* cpy, float* cpx2, float* cpy2, float* args, int rel) { + float x2, y2, cx1, cy1, cx2, cy2; + + if (rel) { + cx1 = *cpx + args[0]; + cy1 = *cpy + args[1]; + cx2 = *cpx + args[2]; + cy2 = *cpy + args[3]; + x2 = *cpx + args[4]; + y2 = *cpy + args[5]; + } else { + cx1 = args[0]; + cy1 = args[1]; + cx2 = args[2]; + cy2 = args[3]; + x2 = args[4]; + y2 = args[5]; + } + + nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2); + + *cpx2 = cx2; + *cpy2 = cy2; + *cpx = x2; + *cpy = y2; +} + +static void nsvg__pathCubicBezShortTo(NSVGparser* p, float* cpx, float* cpy, float* cpx2, float* cpy2, float* args, int rel) { + float x1, y1, x2, y2, cx1, cy1, cx2, cy2; + + x1 = *cpx; + y1 = *cpy; + if (rel) { + cx2 = *cpx + args[0]; + cy2 = *cpy + args[1]; + x2 = *cpx + args[2]; + y2 = *cpy + args[3]; + } else { + cx2 = args[0]; + cy2 = args[1]; + x2 = args[2]; + y2 = args[3]; + } + + cx1 = 2 * x1 - *cpx2; + cy1 = 2 * y1 - *cpy2; + + nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2); + + *cpx2 = cx2; + *cpy2 = cy2; + *cpx = x2; + *cpy = y2; +} + +static void nsvg__pathQuadBezTo(NSVGparser* p, float* cpx, float* cpy, float* cpx2, float* cpy2, float* args, int rel) { + float x1, y1, x2, y2, cx, cy; + float cx1, cy1, cx2, cy2; + + x1 = *cpx; + y1 = *cpy; + if (rel) { + cx = *cpx + args[0]; + cy = *cpy + args[1]; + x2 = *cpx + args[2]; + y2 = *cpy + args[3]; + } else { + cx = args[0]; + cy = args[1]; + x2 = args[2]; + y2 = args[3]; + } + + // Convert to cubic bezier + cx1 = x1 + 2.0f / 3.0f * (cx - x1); + cy1 = y1 + 2.0f / 3.0f * (cy - y1); + cx2 = x2 + 2.0f / 3.0f * (cx - x2); + cy2 = y2 + 2.0f / 3.0f * (cy - y2); + + nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2); + + *cpx2 = cx; + *cpy2 = cy; + *cpx = x2; + *cpy = y2; +} + +static void nsvg__pathQuadBezShortTo(NSVGparser* p, float* cpx, float* cpy, float* cpx2, float* cpy2, float* args, int rel) { + float x1, y1, x2, y2, cx, cy; + float cx1, cy1, cx2, cy2; + + x1 = *cpx; + y1 = *cpy; + if (rel) { + x2 = *cpx + args[0]; + y2 = *cpy + args[1]; + } else { + x2 = args[0]; + y2 = args[1]; + } + + cx = 2 * x1 - *cpx2; + cy = 2 * y1 - *cpy2; + + // Convert to cubix bezier + cx1 = x1 + 2.0f / 3.0f * (cx - x1); + cy1 = y1 + 2.0f / 3.0f * (cy - y1); + cx2 = x2 + 2.0f / 3.0f * (cx - x2); + cy2 = y2 + 2.0f / 3.0f * (cy - y2); + + nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2); + + *cpx2 = cx; + *cpy2 = cy; + *cpx = x2; + *cpy = y2; +} + +static float nsvg__sqr(float x) { return x * x; } +static float nsvg__vmag(float x, float y) { return sqrtf(x * x + y * y); } + +static float nsvg__vecrat(float ux, float uy, float vx, float vy) { return (ux * vx + uy * vy) / (nsvg__vmag(ux, uy) * nsvg__vmag(vx, vy)); } + +static float nsvg__vecang(float ux, float uy, float vx, float vy) { + float r = nsvg__vecrat(ux, uy, vx, vy); + if (r < -1.0f) + r = -1.0f; + if (r > 1.0f) + r = 1.0f; + return ((ux * vy < uy * vx) ? -1.0f : 1.0f) * acosf(r); +} + +static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) { + // Ported from canvg (https://code.google.com/p/canvg/) + float rx, ry, rotx; + float x1, y1, x2, y2, cx, cy, dx, dy, d; + float x1p, y1p, cxp, cyp, s, sa, sb; + float ux, uy, vx, vy, a1, da; + float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6]; + float sinrx, cosrx; + int fa, fs; + int i, ndivs; + float hda, kappa; + + rx = fabsf(args[0]); // y radius + ry = fabsf(args[1]); // x radius + rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle + fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc + fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction + x1 = *cpx; // start point + y1 = *cpy; + if (rel) { // end point + x2 = *cpx + args[5]; + y2 = *cpy + args[6]; + } else { + x2 = args[5]; + y2 = args[6]; + } + + dx = x1 - x2; + dy = y1 - y2; + d = sqrtf(dx * dx + dy * dy); + if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) { + // The arc degenerates to a line + nsvg__lineTo(p, x2, y2); + *cpx = x2; + *cpy = y2; + return; + } + + sinrx = sinf(rotx); + cosrx = cosf(rotx); + + // Convert to center point parameterization. + // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes + // 1) Compute x1', y1' + x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f; + y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f; + d = nsvg__sqr(x1p) / nsvg__sqr(rx) + nsvg__sqr(y1p) / nsvg__sqr(ry); + if (d > 1) { + d = sqrtf(d); + rx *= d; + ry *= d; + } + // 2) Compute cx', cy' + s = 0.0f; + sa = nsvg__sqr(rx) * nsvg__sqr(ry) - nsvg__sqr(rx) * nsvg__sqr(y1p) - nsvg__sqr(ry) * nsvg__sqr(x1p); + sb = nsvg__sqr(rx) * nsvg__sqr(y1p) + nsvg__sqr(ry) * nsvg__sqr(x1p); + if (sa < 0.0f) + sa = 0.0f; + if (sb > 0.0f) + s = sqrtf(sa / sb); + if (fa == fs) + s = -s; + cxp = s * rx * y1p / ry; + cyp = s * -ry * x1p / rx; + + // 3) Compute cx,cy from cx',cy' + cx = (x1 + x2) / 2.0f + cosrx * cxp - sinrx * cyp; + cy = (y1 + y2) / 2.0f + sinrx * cxp + cosrx * cyp; + + // 4) Calculate theta1, and delta theta. + ux = (x1p - cxp) / rx; + uy = (y1p - cyp) / ry; + vx = (-x1p - cxp) / rx; + vy = (-y1p - cyp) / ry; + a1 = nsvg__vecang(1.0f, 0.0f, ux, uy); // Initial angle + da = nsvg__vecang(ux, uy, vx, vy); // Delta angle + + // if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI; + // if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0; + + if (fs == 0 && da > 0) + da -= 2 * NSVG_PI; + else if (fs == 1 && da < 0) + da += 2 * NSVG_PI; + + // Approximate the arc using cubic spline segments. + t[0] = cosrx; + t[1] = sinrx; + t[2] = -sinrx; + t[3] = cosrx; + t[4] = cx; + t[5] = cy; + + // Split arc into max 90 degree segments. + // The loop assumes an iteration per end point (including start and end), this +1. + ndivs = (int)(fabsf(da) / (NSVG_PI * 0.5f) + 1.0f); + hda = (da / (float)ndivs) / 2.0f; + // Fix for ticket #179: division by 0: avoid cotangens around 0 (infinite) + if ((hda < 1e-3f) && (hda > -1e-3f)) + hda *= 0.5f; + else + hda = (1.0f - cosf(hda)) / sinf(hda); + kappa = fabsf(4.0f / 3.0f * hda); + if (da < 0.0f) + kappa = -kappa; + + for (i = 0; i <= ndivs; i++) { + a = a1 + da * ((float)i / (float)ndivs); + dx = cosf(a); + dy = sinf(a); + nsvg__xformPoint(&x, &y, dx * rx, dy * ry, t); // position + nsvg__xformVec(&tanx, &tany, -dy * rx * kappa, dx * ry * kappa, t); // tangent + if (i > 0) + nsvg__cubicBezTo(p, px + ptanx, py + ptany, x - tanx, y - tany, x, y); + px = x; + py = y; + ptanx = tanx; + ptany = tany; + } + + *cpx = x2; + *cpy = y2; +} + +static void nsvg__parsePath(NSVGparser* p, const char** attr) { + const char* s = NULL; + char cmd = '\0'; + float args[10]; + int nargs; + int rargs = 0; + char initPoint; + float cpx, cpy, cpx2, cpy2; + const char* tmp[4]; + char closedFlag; + int i; + char item[64]; + + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "d") == 0) { + s = attr[i + 1]; + } else { + tmp[0] = attr[i]; + tmp[1] = attr[i + 1]; + tmp[2] = 0; + tmp[3] = 0; + nsvg__parseAttribs(p, tmp); + } + } + + if (s) { + nsvg__resetPath(p); + cpx = 0; + cpy = 0; + cpx2 = 0; + cpy2 = 0; + initPoint = 0; + closedFlag = 0; + nargs = 0; + + while (*s) { + item[0] = '\0'; + if ((cmd == 'A' || cmd == 'a') && (nargs == 3 || nargs == 4)) + s = nsvg__getNextPathItemWhenArcFlag(s, item); + if (!*item) + s = nsvg__getNextPathItem(s, item); + if (!*item) + break; + if (cmd != '\0' && nsvg__isCoordinate(item)) { + if (nargs < 10) + args[nargs++] = (float)nsvg__atof(item); + if (nargs >= rargs) { + switch (cmd) { + case 'm': + case 'M': + nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0); + // Moveto can be followed by multiple coordinate pairs, + // which should be treated as linetos. + cmd = (cmd == 'm') ? 'l' : 'L'; + rargs = nsvg__getArgsPerElement(cmd); + cpx2 = cpx; + cpy2 = cpy; + initPoint = 1; + break; + case 'l': + case 'L': + nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0); + cpx2 = cpx; + cpy2 = cpy; + break; + case 'H': + case 'h': + nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0); + cpx2 = cpx; + cpy2 = cpy; + break; + case 'V': + case 'v': + nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0); + cpx2 = cpx; + cpy2 = cpy; + break; + case 'C': + case 'c': + nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0); + break; + case 'S': + case 's': + nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0); + break; + case 'Q': + case 'q': + nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0); + break; + case 'T': + case 't': + nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0); + break; + case 'A': + case 'a': + nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0); + cpx2 = cpx; + cpy2 = cpy; + break; + default: + if (nargs >= 2) { + cpx = args[nargs - 2]; + cpy = args[nargs - 1]; + cpx2 = cpx; + cpy2 = cpy; + } + break; + } + nargs = 0; + } + } else { + cmd = item[0]; + if (cmd == 'M' || cmd == 'm') { + // Commit path. + if (p->npts > 0) + nsvg__addPath(p, closedFlag); + // Start new subpath. + nsvg__resetPath(p); + closedFlag = 0; + nargs = 0; + } else if (initPoint == 0) { + // Do not allow other commands until initial point has been set (moveTo called once). + cmd = '\0'; + } + if (cmd == 'Z' || cmd == 'z') { + closedFlag = 1; + // Commit path. + if (p->npts > 0) { + // Move current point to first point + cpx = p->pts[0]; + cpy = p->pts[1]; + cpx2 = cpx; + cpy2 = cpy; + nsvg__addPath(p, closedFlag); + } + // Start new subpath. + nsvg__resetPath(p); + nsvg__moveTo(p, cpx, cpy); + closedFlag = 0; + nargs = 0; + } + rargs = nsvg__getArgsPerElement(cmd); + if (rargs == -1) { + // Command not recognized + cmd = '\0'; + rargs = 0; + } + } + } + // Commit path. + if (p->npts) + nsvg__addPath(p, closedFlag); + } + + nsvg__addShape(p); +} + +static void nsvg__parseRect(NSVGparser* p, const char** attr) { + float x = 0.0f; + float y = 0.0f; + float w = 0.0f; + float h = 0.0f; + float rx = -1.0f; // marks not set + float ry = -1.0f; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "x") == 0) + x = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "y") == 0) + y = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "width") == 0) + w = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p)); + if (strcmp(attr[i], "height") == 0) + h = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p)); + if (strcmp(attr[i], "rx") == 0) + rx = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p))); + if (strcmp(attr[i], "ry") == 0) + ry = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p))); + } + } + + if (rx < 0.0f && ry > 0.0f) + rx = ry; + if (ry < 0.0f && rx > 0.0f) + ry = rx; + if (rx < 0.0f) + rx = 0.0f; + if (ry < 0.0f) + ry = 0.0f; + if (rx > w / 2.0f) + rx = w / 2.0f; + if (ry > h / 2.0f) + ry = h / 2.0f; + + if (w != 0.0f && h != 0.0f) { + nsvg__resetPath(p); + + if (rx < 0.00001f || ry < 0.0001f) { + nsvg__moveTo(p, x, y); + nsvg__lineTo(p, x + w, y); + nsvg__lineTo(p, x + w, y + h); + nsvg__lineTo(p, x, y + h); + } else { + // Rounded rectangle + nsvg__moveTo(p, x + rx, y); + nsvg__lineTo(p, x + w - rx, y); + nsvg__cubicBezTo(p, x + w - rx * (1 - NSVG_KAPPA90), y, x + w, y + ry * (1 - NSVG_KAPPA90), x + w, y + ry); + nsvg__lineTo(p, x + w, y + h - ry); + nsvg__cubicBezTo(p, x + w, y + h - ry * (1 - NSVG_KAPPA90), x + w - rx * (1 - NSVG_KAPPA90), y + h, x + w - rx, y + h); + nsvg__lineTo(p, x + rx, y + h); + nsvg__cubicBezTo(p, x + rx * (1 - NSVG_KAPPA90), y + h, x, y + h - ry * (1 - NSVG_KAPPA90), x, y + h - ry); + nsvg__lineTo(p, x, y + ry); + nsvg__cubicBezTo(p, x, y + ry * (1 - NSVG_KAPPA90), x + rx * (1 - NSVG_KAPPA90), y, x + rx, y); + } + + nsvg__addPath(p, 1); + + nsvg__addShape(p); + } +} + +static void nsvg__parseCircle(NSVGparser* p, const char** attr) { + float cx = 0.0f; + float cy = 0.0f; + float r = 0.0f; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "cx") == 0) + cx = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "cy") == 0) + cy = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "r") == 0) + r = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualLength(p))); + } + } + + if (r > 0.0f) { + nsvg__resetPath(p); + + nsvg__moveTo(p, cx + r, cy); + nsvg__cubicBezTo(p, cx + r, cy + r * NSVG_KAPPA90, cx + r * NSVG_KAPPA90, cy + r, cx, cy + r); + nsvg__cubicBezTo(p, cx - r * NSVG_KAPPA90, cy + r, cx - r, cy + r * NSVG_KAPPA90, cx - r, cy); + nsvg__cubicBezTo(p, cx - r, cy - r * NSVG_KAPPA90, cx - r * NSVG_KAPPA90, cy - r, cx, cy - r); + nsvg__cubicBezTo(p, cx + r * NSVG_KAPPA90, cy - r, cx + r, cy - r * NSVG_KAPPA90, cx + r, cy); + + nsvg__addPath(p, 1); + + nsvg__addShape(p); + } +} + +static void nsvg__parseEllipse(NSVGparser* p, const char** attr) { + float cx = 0.0f; + float cy = 0.0f; + float rx = 0.0f; + float ry = 0.0f; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "cx") == 0) + cx = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "cy") == 0) + cy = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "rx") == 0) + rx = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p))); + if (strcmp(attr[i], "ry") == 0) + ry = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p))); + } + } + + if (rx > 0.0f && ry > 0.0f) { + + nsvg__resetPath(p); + + nsvg__moveTo(p, cx + rx, cy); + nsvg__cubicBezTo(p, cx + rx, cy + ry * NSVG_KAPPA90, cx + rx * NSVG_KAPPA90, cy + ry, cx, cy + ry); + nsvg__cubicBezTo(p, cx - rx * NSVG_KAPPA90, cy + ry, cx - rx, cy + ry * NSVG_KAPPA90, cx - rx, cy); + nsvg__cubicBezTo(p, cx - rx, cy - ry * NSVG_KAPPA90, cx - rx * NSVG_KAPPA90, cy - ry, cx, cy - ry); + nsvg__cubicBezTo(p, cx + rx * NSVG_KAPPA90, cy - ry, cx + rx, cy - ry * NSVG_KAPPA90, cx + rx, cy); + + nsvg__addPath(p, 1); + + nsvg__addShape(p); + } +} + +static void nsvg__parseLine(NSVGparser* p, const char** attr) { + float x1 = 0.0; + float y1 = 0.0; + float x2 = 0.0; + float y2 = 0.0; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "x1") == 0) + x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "y1") == 0) + y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "x2") == 0) + x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "y2") == 0) + y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + } + } + + nsvg__resetPath(p); + + nsvg__moveTo(p, x1, y1); + nsvg__lineTo(p, x2, y2); + + nsvg__addPath(p, 0); + + nsvg__addShape(p); +} + +static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag) { + int i; + const char* s; + float args[2]; + int nargs, npts = 0; + char item[64]; + + nsvg__resetPath(p); + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "points") == 0) { + s = attr[i + 1]; + nargs = 0; + while (*s) { + s = nsvg__getNextPathItem(s, item); + args[nargs++] = (float)nsvg__atof(item); + if (nargs >= 2) { + if (npts == 0) + nsvg__moveTo(p, args[0], args[1]); + else + nsvg__lineTo(p, args[0], args[1]); + nargs = 0; + npts++; + } + } + } + } + } + + nsvg__addPath(p, (char)closeFlag); + + nsvg__addShape(p); +} + +static void nsvg__parseSVG(NSVGparser* p, const char** attr) { + int i; + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "width") == 0) { + p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); + } else if (strcmp(attr[i], "height") == 0) { + p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); + } else if (strcmp(attr[i], "viewBox") == 0) { + const char* s = attr[i + 1]; + char buf[64]; + s = nsvg__parseNumber(s, buf, 64); + p->viewMinx = nsvg__atof(buf); + while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) + s++; + if (!*s) + return; + s = nsvg__parseNumber(s, buf, 64); + p->viewMiny = nsvg__atof(buf); + while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) + s++; + if (!*s) + return; + s = nsvg__parseNumber(s, buf, 64); + p->viewWidth = nsvg__atof(buf); + while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) + s++; + if (!*s) + return; + s = nsvg__parseNumber(s, buf, 64); + p->viewHeight = nsvg__atof(buf); + } else if (strcmp(attr[i], "preserveAspectRatio") == 0) { + if (strstr(attr[i + 1], "none") != 0) { + // No uniform scaling + p->alignType = NSVG_ALIGN_NONE; + } else { + // Parse X align + if (strstr(attr[i + 1], "xMin") != 0) + p->alignX = NSVG_ALIGN_MIN; + else if (strstr(attr[i + 1], "xMid") != 0) + p->alignX = NSVG_ALIGN_MID; + else if (strstr(attr[i + 1], "xMax") != 0) + p->alignX = NSVG_ALIGN_MAX; + // Parse X align + if (strstr(attr[i + 1], "yMin") != 0) + p->alignY = NSVG_ALIGN_MIN; + else if (strstr(attr[i + 1], "yMid") != 0) + p->alignY = NSVG_ALIGN_MID; + else if (strstr(attr[i + 1], "yMax") != 0) + p->alignY = NSVG_ALIGN_MAX; + // Parse meet/slice + p->alignType = NSVG_ALIGN_MEET; + if (strstr(attr[i + 1], "slice") != 0) + p->alignType = NSVG_ALIGN_SLICE; + } + } + } + } +} + +static void nsvg__parseGradient(NSVGparser* p, const char** attr, signed char type) { + int i; + NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData)); + if (grad == NULL) + return; + memset(grad, 0, sizeof(NSVGgradientData)); + grad->units = NSVG_OBJECT_SPACE; + grad->type = type; + if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) { + grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); + grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); + grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT); + grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); + } else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) { + grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); + grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); + grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); + } + + nsvg__xformIdentity(grad->xform); + + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "id") == 0) { + strncpy(grad->id, attr[i + 1], 63); + grad->id[63] = '\0'; + } else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "gradientUnits") == 0) { + if (strcmp(attr[i + 1], "objectBoundingBox") == 0) + grad->units = NSVG_OBJECT_SPACE; + else + grad->units = NSVG_USER_SPACE; + } else if (strcmp(attr[i], "gradientTransform") == 0) { + nsvg__parseTransform(grad->xform, attr[i + 1]); + } else if (strcmp(attr[i], "cx") == 0) { + grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "cy") == 0) { + grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "r") == 0) { + grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "fx") == 0) { + grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "fy") == 0) { + grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "x1") == 0) { + grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "y1") == 0) { + grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "x2") == 0) { + grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "y2") == 0) { + grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "spreadMethod") == 0) { + if (strcmp(attr[i + 1], "pad") == 0) + grad->spread = NSVG_SPREAD_PAD; + else if (strcmp(attr[i + 1], "reflect") == 0) + grad->spread = NSVG_SPREAD_REFLECT; + else if (strcmp(attr[i + 1], "repeat") == 0) + grad->spread = NSVG_SPREAD_REPEAT; + } else if (strcmp(attr[i], "xlink:href") == 0) { + const char* href = attr[i + 1]; + strncpy(grad->ref, href + 1, 62); + grad->ref[62] = '\0'; + } + } + } + + grad->next = p->gradients; + p->gradients = grad; +} + +static void nsvg__parseGradientStop(NSVGparser* p, const char** attr) { + NSVGattrib* curAttr = nsvg__getAttr(p); + NSVGgradientData* grad; + NSVGgradientStop* stop; + int i, idx; + + curAttr->stopOffset = 0; + curAttr->stopColor = 0; + curAttr->stopOpacity = 1.0f; + + for (i = 0; attr[i]; i += 2) { + nsvg__parseAttr(p, attr[i], attr[i + 1]); + } + + // Add stop to the last gradient. + grad = p->gradients; + if (grad == NULL) + return; + + grad->nstops++; + grad->stops = (NSVGgradientStop*)realloc(grad->stops, sizeof(NSVGgradientStop) * grad->nstops); + if (grad->stops == NULL) + return; + + // Insert + idx = grad->nstops - 1; + for (i = 0; i < grad->nstops - 1; i++) { + if (curAttr->stopOffset < grad->stops[i].offset) { + idx = i; + break; + } + } + if (idx != grad->nstops - 1) { + for (i = grad->nstops - 1; i > idx; i--) + grad->stops[i] = grad->stops[i - 1]; + } + + stop = &grad->stops[idx]; + stop->color = curAttr->stopColor; + stop->color |= (unsigned int)(curAttr->stopOpacity * 255) << 24; + stop->offset = curAttr->stopOffset; +} + +static void nsvg__startElement(void* ud, const char* el, const char** attr) { + NSVGparser* p = (NSVGparser*)ud; + + if (p->defsFlag) { + // Skip everything but gradients in defs + if (strcmp(el, "linearGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT); + } else if (strcmp(el, "radialGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT); + } else if (strcmp(el, "stop") == 0) { + nsvg__parseGradientStop(p, attr); + } + return; + } + + if (strcmp(el, "g") == 0) { + nsvg__pushAttr(p); + nsvg__parseAttribs(p, attr); + } else if (strcmp(el, "path") == 0) { + if (p->pathFlag) // Do not allow nested paths. + return; + nsvg__pushAttr(p); + nsvg__parsePath(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "rect") == 0) { + nsvg__pushAttr(p); + nsvg__parseRect(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "circle") == 0) { + nsvg__pushAttr(p); + nsvg__parseCircle(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "ellipse") == 0) { + nsvg__pushAttr(p); + nsvg__parseEllipse(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "line") == 0) { + nsvg__pushAttr(p); + nsvg__parseLine(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "polyline") == 0) { + nsvg__pushAttr(p); + nsvg__parsePoly(p, attr, 0); + nsvg__popAttr(p); + } else if (strcmp(el, "polygon") == 0) { + nsvg__pushAttr(p); + nsvg__parsePoly(p, attr, 1); + nsvg__popAttr(p); + } else if (strcmp(el, "linearGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT); + } else if (strcmp(el, "radialGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT); + } else if (strcmp(el, "stop") == 0) { + nsvg__parseGradientStop(p, attr); + } else if (strcmp(el, "defs") == 0) { + p->defsFlag = 1; + } else if (strcmp(el, "svg") == 0) { + nsvg__parseSVG(p, attr); + } +} + +static void nsvg__endElement(void* ud, const char* el) { + NSVGparser* p = (NSVGparser*)ud; + + if (strcmp(el, "g") == 0) { + nsvg__popAttr(p); + } else if (strcmp(el, "path") == 0) { + p->pathFlag = 0; + } else if (strcmp(el, "defs") == 0) { + p->defsFlag = 0; + } +} + +static void nsvg__content(void* ud, const char* s) { + NSVG_NOTUSED(ud); + NSVG_NOTUSED(s); + // empty +} + +static void nsvg__imageBounds(NSVGparser* p, float* bounds) { + NSVGshape* shape; + shape = p->image->shapes; + if (shape == NULL) { + bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0; + return; + } + bounds[0] = shape->bounds[0]; + bounds[1] = shape->bounds[1]; + bounds[2] = shape->bounds[2]; + bounds[3] = shape->bounds[3]; + for (shape = shape->next; shape != NULL; shape = shape->next) { + bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]); + bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]); + bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]); + bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]); + } +} + +static float nsvg__viewAlign(float content, float container, int type) { + if (type == NSVG_ALIGN_MIN) + return 0; + else if (type == NSVG_ALIGN_MAX) + return container - content; + // mid + return (container - content) * 0.5f; +} + +static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy) { + float t[6]; + nsvg__xformSetTranslation(t, tx, ty); + nsvg__xformMultiply(grad->xform, t); + + nsvg__xformSetScale(t, sx, sy); + nsvg__xformMultiply(grad->xform, t); +} + +static void nsvg__scaleToViewbox(NSVGparser* p, const char* units) { + NSVGshape* shape; + NSVGpath* path; + float tx, ty, sx, sy, us, bounds[4], t[6], avgs; + int i; + float* pt; + + // Guess image size if not set completely. + nsvg__imageBounds(p, bounds); + + if (p->viewWidth == 0) { + if (p->image->width > 0) { + p->viewWidth = p->image->width; + } else { + p->viewMinx = bounds[0]; + p->viewWidth = bounds[2] - bounds[0]; + } + } + if (p->viewHeight == 0) { + if (p->image->height > 0) { + p->viewHeight = p->image->height; + } else { + p->viewMiny = bounds[1]; + p->viewHeight = bounds[3] - bounds[1]; + } + } + if (p->image->width == 0) + p->image->width = p->viewWidth; + if (p->image->height == 0) + p->image->height = p->viewHeight; + + tx = -p->viewMinx; + ty = -p->viewMiny; + sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0; + sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0; + // Unit scaling + us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f); + + // Fix aspect ratio + if (p->alignType == NSVG_ALIGN_MEET) { + // fit whole image into viewbox + sx = sy = nsvg__minf(sx, sy); + tx += nsvg__viewAlign(p->viewWidth * sx, p->image->width, p->alignX) / sx; + ty += nsvg__viewAlign(p->viewHeight * sy, p->image->height, p->alignY) / sy; + } else if (p->alignType == NSVG_ALIGN_SLICE) { + // fill whole viewbox with image + sx = sy = nsvg__maxf(sx, sy); + tx += nsvg__viewAlign(p->viewWidth * sx, p->image->width, p->alignX) / sx; + ty += nsvg__viewAlign(p->viewHeight * sy, p->image->height, p->alignY) / sy; + } + + // Transform + sx *= us; + sy *= us; + avgs = (sx + sy) / 2.0f; + for (shape = p->image->shapes; shape != NULL; shape = shape->next) { + shape->bounds[0] = (shape->bounds[0] + tx) * sx; + shape->bounds[1] = (shape->bounds[1] + ty) * sy; + shape->bounds[2] = (shape->bounds[2] + tx) * sx; + shape->bounds[3] = (shape->bounds[3] + ty) * sy; + for (path = shape->paths; path != NULL; path = path->next) { + path->bounds[0] = (path->bounds[0] + tx) * sx; + path->bounds[1] = (path->bounds[1] + ty) * sy; + path->bounds[2] = (path->bounds[2] + tx) * sx; + path->bounds[3] = (path->bounds[3] + ty) * sy; + for (i = 0; i < path->npts; i++) { + pt = &path->pts[i * 2]; + pt[0] = (pt[0] + tx) * sx; + pt[1] = (pt[1] + ty) * sy; + } + } + + if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) { + nsvg__scaleGradient(shape->fill.gradient, tx, ty, sx, sy); + memcpy(t, shape->fill.gradient->xform, sizeof(float) * 6); + nsvg__xformInverse(shape->fill.gradient->xform, t); + } + if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) { + nsvg__scaleGradient(shape->stroke.gradient, tx, ty, sx, sy); + memcpy(t, shape->stroke.gradient->xform, sizeof(float) * 6); + nsvg__xformInverse(shape->stroke.gradient->xform, t); + } + + shape->strokeWidth *= avgs; + shape->strokeDashOffset *= avgs; + for (i = 0; i < shape->strokeDashCount; i++) + shape->strokeDashArray[i] *= avgs; + } +} + +static void nsvg__createGradients(NSVGparser* p) { + NSVGshape* shape; + + for (shape = p->image->shapes; shape != NULL; shape = shape->next) { + if (shape->fill.type == NSVG_PAINT_UNDEF) { + if (shape->fillGradient[0] != '\0') { + float inv[6], localBounds[4]; + nsvg__xformInverse(inv, shape->xform); + nsvg__getLocalBounds(localBounds, shape, inv); + shape->fill.gradient = nsvg__createGradient(p, shape->fillGradient, localBounds, shape->xform, &shape->fill.type); + } + if (shape->fill.type == NSVG_PAINT_UNDEF) { + shape->fill.type = NSVG_PAINT_NONE; + } + } + if (shape->stroke.type == NSVG_PAINT_UNDEF) { + if (shape->strokeGradient[0] != '\0') { + float inv[6], localBounds[4]; + nsvg__xformInverse(inv, shape->xform); + nsvg__getLocalBounds(localBounds, shape, inv); + shape->stroke.gradient = nsvg__createGradient(p, shape->strokeGradient, localBounds, shape->xform, &shape->stroke.type); + } + if (shape->stroke.type == NSVG_PAINT_UNDEF) { + shape->stroke.type = NSVG_PAINT_NONE; + } + } + } +} + +NSVGimage* nsvgParse(char* input, const char* units, float dpi) { + NSVGparser* p; + NSVGimage* ret = 0; + + p = nsvg__createParser(); + if (p == NULL) { + return NULL; + } + p->dpi = dpi; + + nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p); + + // Create gradients after all definitions have been parsed + nsvg__createGradients(p); + + // Scale to viewBox + nsvg__scaleToViewbox(p, units); + + ret = p->image; + p->image = NULL; + + nsvg__deleteParser(p); + + return ret; +} + +NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi) { + FILE* fp = NULL; + size_t size; + char* data = NULL; + NSVGimage* image = NULL; + + fp = fopen(filename, "rb"); + if (!fp) + goto error; + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + data = (char*)malloc(size + 1); + if (data == NULL) + goto error; + if (fread(data, 1, size, fp) != size) + goto error; + data[size] = '\0'; // Must be null terminated. + fclose(fp); + image = nsvgParse(data, units, dpi); + free(data); + + return image; + +error: + if (fp) + fclose(fp); + if (data) + free(data); + if (image) + nsvgDelete(image); + return NULL; +} + +NSVGpath* nsvgDuplicatePath(NSVGpath* p) { + NSVGpath* res = NULL; + + if (p == NULL) + return NULL; + + res = (NSVGpath*)malloc(sizeof(NSVGpath)); + if (res == NULL) + goto error; + memset(res, 0, sizeof(NSVGpath)); + + res->pts = (float*)malloc(p->npts * 2 * sizeof(float)); + if (res->pts == NULL) + goto error; + memcpy(res->pts, p->pts, p->npts * sizeof(float) * 2); + res->npts = p->npts; + + memcpy(res->bounds, p->bounds, sizeof(p->bounds)); + + res->closed = p->closed; + + return res; + +error: + if (res != NULL) { + free(res->pts); + free(res); + } + return NULL; +} + +void nsvgDelete(NSVGimage* image) { + NSVGshape *snext, *shape; + if (image == NULL) + return; + shape = image->shapes; + while (shape != NULL) { + snext = shape->next; + nsvg__deletePaths(shape->paths); + nsvg__deletePaint(&shape->fill); + nsvg__deletePaint(&shape->stroke); + free(shape); + shape = snext; + } + free(image); +} + +#endif // NANOSVG_IMPLEMENTATION + +#endif // NANOSVG_H \ No newline at end of file diff --git a/include/nanosvgrast.h b/include/nanosvgrast.h new file mode 100644 index 0000000..d067156 --- /dev/null +++ b/include/nanosvgrast.h @@ -0,0 +1,1461 @@ +/* + * Copyright (c) 2013-14 Mikko Mononen memon@inside.org + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * The polygon rasterization is heavily based on stb_truetype rasterizer + * by Sean Barrett - http://nothings.org/ + * + */ + +#ifndef NANOSVGRAST_H +#define NANOSVGRAST_H + +#include "nanosvg.h" + +#ifndef NANOSVGRAST_CPLUSPLUS +#ifdef __cplusplus +extern "C" { +#endif +#endif + +typedef struct NSVGrasterizer NSVGrasterizer; + +/* Example Usage: + // Load SVG + NSVGimage* image; + image = nsvgParseFromFile("test.svg", "px", 96); + + // Create rasterizer (can be used to render multiple images). + struct NSVGrasterizer* rast = nsvgCreateRasterizer(); + // Allocate memory for image + unsigned char* img = malloc(w*h*4); + // Rasterize + nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4); +*/ + +// Allocated rasterizer context. +NSVGrasterizer* nsvgCreateRasterizer(void); + +// Rasterizes SVG image, returns RGBA image (non-premultiplied alpha) +// r - pointer to rasterizer context +// image - pointer to image to rasterize +// tx,ty - image offset (applied after scaling) +// scale - image scale +// dst - pointer to destination image data, 4 bytes per pixel (RGBA) +// w - width of the image to render +// h - height of the image to render +// stride - number of bytes per scaleline in the destination buffer +void nsvgRasterize(NSVGrasterizer* r, NSVGimage* image, float tx, float ty, float scale, unsigned char* dst, int w, int h, int stride); + +// Deletes rasterizer context. +void nsvgDeleteRasterizer(NSVGrasterizer*); + +#ifndef NANOSVGRAST_CPLUSPLUS +#ifdef __cplusplus +} +#endif +#endif + +#ifdef NANOSVGRAST_IMPLEMENTATION + +#include +#include +#include + +#define NSVG__SUBSAMPLES 5 +#define NSVG__FIXSHIFT 10 +#define NSVG__FIX (1 << NSVG__FIXSHIFT) +#define NSVG__FIXMASK (NSVG__FIX - 1) +#define NSVG__MEMPAGE_SIZE 1024 + +typedef struct NSVGedge { + float x0, y0, x1, y1; + int dir; + struct NSVGedge* next; +} NSVGedge; + +typedef struct NSVGpoint { + float x, y; + float dx, dy; + float len; + float dmx, dmy; + unsigned char flags; +} NSVGpoint; + +typedef struct NSVGactiveEdge { + int x, dx; + float ey; + int dir; + struct NSVGactiveEdge* next; +} NSVGactiveEdge; + +typedef struct NSVGmemPage { + unsigned char mem[NSVG__MEMPAGE_SIZE]; + int size; + struct NSVGmemPage* next; +} NSVGmemPage; + +typedef struct NSVGcachedPaint { + signed char type; + char spread; + float xform[6]; + unsigned int colors[256]; +} NSVGcachedPaint; + +struct NSVGrasterizer { + float px, py; + + float tessTol; + float distTol; + + NSVGedge* edges; + int nedges; + int cedges; + + NSVGpoint* points; + int npoints; + int cpoints; + + NSVGpoint* points2; + int npoints2; + int cpoints2; + + NSVGactiveEdge* freelist; + NSVGmemPage* pages; + NSVGmemPage* curpage; + + unsigned char* scanline; + int cscanline; + + unsigned char* bitmap; + int width, height, stride; +}; + +NSVGrasterizer* nsvgCreateRasterizer(void) { + NSVGrasterizer* r = (NSVGrasterizer*)malloc(sizeof(NSVGrasterizer)); + if (r == NULL) + goto error; + memset(r, 0, sizeof(NSVGrasterizer)); + + r->tessTol = 0.25f; + r->distTol = 0.01f; + + return r; + +error: + nsvgDeleteRasterizer(r); + return NULL; +} + +void nsvgDeleteRasterizer(NSVGrasterizer* r) { + NSVGmemPage* p; + + if (r == NULL) + return; + + p = r->pages; + while (p != NULL) { + NSVGmemPage* next = p->next; + free(p); + p = next; + } + + if (r->edges) + free(r->edges); + if (r->points) + free(r->points); + if (r->points2) + free(r->points2); + if (r->scanline) + free(r->scanline); + + free(r); +} + +static NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur) { + NSVGmemPage* newp; + + // If using existing chain, return the next page in chain + if (cur != NULL && cur->next != NULL) { + return cur->next; + } + + // Alloc new page + newp = (NSVGmemPage*)malloc(sizeof(NSVGmemPage)); + if (newp == NULL) + return NULL; + memset(newp, 0, sizeof(NSVGmemPage)); + + // Add to linked list + if (cur != NULL) + cur->next = newp; + else + r->pages = newp; + + return newp; +} + +static void nsvg__resetPool(NSVGrasterizer* r) { + NSVGmemPage* p = r->pages; + while (p != NULL) { + p->size = 0; + p = p->next; + } + r->curpage = r->pages; +} + +static unsigned char* nsvg__alloc(NSVGrasterizer* r, int size) { + unsigned char* buf; + if (size > NSVG__MEMPAGE_SIZE) + return NULL; + if (r->curpage == NULL || r->curpage->size + size > NSVG__MEMPAGE_SIZE) { + r->curpage = nsvg__nextPage(r, r->curpage); + } + buf = &r->curpage->mem[r->curpage->size]; + r->curpage->size += size; + return buf; +} + +static int nsvg__ptEquals(float x1, float y1, float x2, float y2, float tol) { + float dx = x2 - x1; + float dy = y2 - y1; + return dx * dx + dy * dy < tol * tol; +} + +static void nsvg__addPathPoint(NSVGrasterizer* r, float x, float y, int flags) { + NSVGpoint* pt; + + if (r->npoints > 0) { + pt = &r->points[r->npoints - 1]; + if (nsvg__ptEquals(pt->x, pt->y, x, y, r->distTol)) { + pt->flags = (unsigned char)(pt->flags | flags); + return; + } + } + + if (r->npoints + 1 > r->cpoints) { + r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64; + r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints); + if (r->points == NULL) + return; + } + + pt = &r->points[r->npoints]; + pt->x = x; + pt->y = y; + pt->flags = (unsigned char)flags; + r->npoints++; +} + +static void nsvg__appendPathPoint(NSVGrasterizer* r, NSVGpoint pt) { + if (r->npoints + 1 > r->cpoints) { + r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64; + r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints); + if (r->points == NULL) + return; + } + r->points[r->npoints] = pt; + r->npoints++; +} + +static void nsvg__duplicatePoints(NSVGrasterizer* r) { + if (r->npoints > r->cpoints2) { + r->cpoints2 = r->npoints; + r->points2 = (NSVGpoint*)realloc(r->points2, sizeof(NSVGpoint) * r->cpoints2); + if (r->points2 == NULL) + return; + } + + memcpy(r->points2, r->points, sizeof(NSVGpoint) * r->npoints); + r->npoints2 = r->npoints; +} + +static void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float y1) { + NSVGedge* e; + + // Skip horizontal edges + if (y0 == y1) + return; + + if (r->nedges + 1 > r->cedges) { + r->cedges = r->cedges > 0 ? r->cedges * 2 : 64; + r->edges = (NSVGedge*)realloc(r->edges, sizeof(NSVGedge) * r->cedges); + if (r->edges == NULL) + return; + } + + e = &r->edges[r->nedges]; + r->nedges++; + + if (y0 < y1) { + e->x0 = x0; + e->y0 = y0; + e->x1 = x1; + e->y1 = y1; + e->dir = 1; + } else { + e->x0 = x1; + e->y0 = y1; + e->x1 = x0; + e->y1 = y0; + e->dir = -1; + } +} + +static float nsvg__normalize(float* x, float* y) { + float d = sqrtf((*x) * (*x) + (*y) * (*y)); + if (d > 1e-6f) { + float id = 1.0f / d; + *x *= id; + *y *= id; + } + return d; +} + +static float nsvg__absf(float x) { return x < 0 ? -x : x; } +static float nsvg__roundf(float x) { return (x >= 0) ? floorf(x + 0.5) : ceilf(x - 0.5); } + +static void nsvg__flattenCubicBez(NSVGrasterizer* r, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, int level, int type) { + float x12, y12, x23, y23, x34, y34, x123, y123, x234, y234, x1234, y1234; + float dx, dy, d2, d3; + + if (level > 10) + return; + + x12 = (x1 + x2) * 0.5f; + y12 = (y1 + y2) * 0.5f; + x23 = (x2 + x3) * 0.5f; + y23 = (y2 + y3) * 0.5f; + x34 = (x3 + x4) * 0.5f; + y34 = (y3 + y4) * 0.5f; + x123 = (x12 + x23) * 0.5f; + y123 = (y12 + y23) * 0.5f; + + dx = x4 - x1; + dy = y4 - y1; + d2 = nsvg__absf((x2 - x4) * dy - (y2 - y4) * dx); + d3 = nsvg__absf((x3 - x4) * dy - (y3 - y4) * dx); + + if ((d2 + d3) * (d2 + d3) < r->tessTol * (dx * dx + dy * dy)) { + nsvg__addPathPoint(r, x4, y4, type); + return; + } + + x234 = (x23 + x34) * 0.5f; + y234 = (y23 + y34) * 0.5f; + x1234 = (x123 + x234) * 0.5f; + y1234 = (y123 + y234) * 0.5f; + + nsvg__flattenCubicBez(r, x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1, 0); + nsvg__flattenCubicBez(r, x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1, type); +} + +static void nsvg__flattenShape(NSVGrasterizer* r, NSVGshape* shape, float scale) { + int i, j; + NSVGpath* path; + + for (path = shape->paths; path != NULL; path = path->next) { + r->npoints = 0; + // Flatten path + nsvg__addPathPoint(r, path->pts[0] * scale, path->pts[1] * scale, 0); + for (i = 0; i < path->npts - 1; i += 3) { + float* p = &path->pts[i * 2]; + nsvg__flattenCubicBez(r, p[0] * scale, p[1] * scale, p[2] * scale, p[3] * scale, p[4] * scale, p[5] * scale, p[6] * scale, p[7] * scale, 0, 0); + } + // Close path + nsvg__addPathPoint(r, path->pts[0] * scale, path->pts[1] * scale, 0); + // Build edges + for (i = 0, j = r->npoints - 1; i < r->npoints; j = i++) + nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y); + } +} + +enum NSVGpointFlags { NSVG_PT_CORNER = 0x01, NSVG_PT_BEVEL = 0x02, NSVG_PT_LEFT = 0x04 }; + +static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) { + float w = lineWidth * 0.5f; + float dx = p1->x - p0->x; + float dy = p1->y - p0->y; + float len = nsvg__normalize(&dx, &dy); + float px = p0->x + dx * len * 0.5f, py = p0->y + dy * len * 0.5f; + float dlx = dy, dly = -dx; + float lx = px - dlx * w, ly = py - dly * w; + float rx = px + dlx * w, ry = py + dly * w; + left->x = lx; + left->y = ly; + right->x = rx; + right->y = ry; +} + +static void nsvg__buttCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect) { + float w = lineWidth * 0.5f; + float px = p->x, py = p->y; + float dlx = dy, dly = -dx; + float lx = px - dlx * w, ly = py - dly * w; + float rx = px + dlx * w, ry = py + dly * w; + + nsvg__addEdge(r, lx, ly, rx, ry); + + if (connect) { + nsvg__addEdge(r, left->x, left->y, lx, ly); + nsvg__addEdge(r, rx, ry, right->x, right->y); + } + left->x = lx; + left->y = ly; + right->x = rx; + right->y = ry; +} + +static void nsvg__squareCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect) { + float w = lineWidth * 0.5f; + float px = p->x - dx * w, py = p->y - dy * w; + float dlx = dy, dly = -dx; + float lx = px - dlx * w, ly = py - dly * w; + float rx = px + dlx * w, ry = py + dly * w; + + nsvg__addEdge(r, lx, ly, rx, ry); + + if (connect) { + nsvg__addEdge(r, left->x, left->y, lx, ly); + nsvg__addEdge(r, rx, ry, right->x, right->y); + } + left->x = lx; + left->y = ly; + right->x = rx; + right->y = ry; +} + +#ifndef NSVG_PI +#define NSVG_PI (3.14159265358979323846264338327f) +#endif + +static void nsvg__roundCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int ncap, int connect) { + int i; + float w = lineWidth * 0.5f; + float px = p->x, py = p->y; + float dlx = dy, dly = -dx; + float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0; + + for (i = 0; i < ncap; i++) { + float a = (float)i / (float)(ncap - 1) * NSVG_PI; + float ax = cosf(a) * w, ay = sinf(a) * w; + float x = px - dlx * ax - dx * ay; + float y = py - dly * ax - dy * ay; + + if (i > 0) + nsvg__addEdge(r, prevx, prevy, x, y); + + prevx = x; + prevy = y; + + if (i == 0) { + lx = x; + ly = y; + } else if (i == ncap - 1) { + rx = x; + ry = y; + } + } + + if (connect) { + nsvg__addEdge(r, left->x, left->y, lx, ly); + nsvg__addEdge(r, rx, ry, right->x, right->y); + } + + left->x = lx; + left->y = ly; + right->x = rx; + right->y = ry; +} + +static void nsvg__bevelJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) { + float w = lineWidth * 0.5f; + float dlx0 = p0->dy, dly0 = -p0->dx; + float dlx1 = p1->dy, dly1 = -p1->dx; + float lx0 = p1->x - (dlx0 * w), ly0 = p1->y - (dly0 * w); + float rx0 = p1->x + (dlx0 * w), ry0 = p1->y + (dly0 * w); + float lx1 = p1->x - (dlx1 * w), ly1 = p1->y - (dly1 * w); + float rx1 = p1->x + (dlx1 * w), ry1 = p1->y + (dly1 * w); + + nsvg__addEdge(r, lx0, ly0, left->x, left->y); + nsvg__addEdge(r, lx1, ly1, lx0, ly0); + + nsvg__addEdge(r, right->x, right->y, rx0, ry0); + nsvg__addEdge(r, rx0, ry0, rx1, ry1); + + left->x = lx1; + left->y = ly1; + right->x = rx1; + right->y = ry1; +} + +static void nsvg__miterJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) { + float w = lineWidth * 0.5f; + float dlx0 = p0->dy, dly0 = -p0->dx; + float dlx1 = p1->dy, dly1 = -p1->dx; + float lx0, rx0, lx1, rx1; + float ly0, ry0, ly1, ry1; + + if (p1->flags & NSVG_PT_LEFT) { + lx0 = lx1 = p1->x - p1->dmx * w; + ly0 = ly1 = p1->y - p1->dmy * w; + nsvg__addEdge(r, lx1, ly1, left->x, left->y); + + rx0 = p1->x + (dlx0 * w); + ry0 = p1->y + (dly0 * w); + rx1 = p1->x + (dlx1 * w); + ry1 = p1->y + (dly1 * w); + nsvg__addEdge(r, right->x, right->y, rx0, ry0); + nsvg__addEdge(r, rx0, ry0, rx1, ry1); + } else { + lx0 = p1->x - (dlx0 * w); + ly0 = p1->y - (dly0 * w); + lx1 = p1->x - (dlx1 * w); + ly1 = p1->y - (dly1 * w); + nsvg__addEdge(r, lx0, ly0, left->x, left->y); + nsvg__addEdge(r, lx1, ly1, lx0, ly0); + + rx0 = rx1 = p1->x + p1->dmx * w; + ry0 = ry1 = p1->y + p1->dmy * w; + nsvg__addEdge(r, right->x, right->y, rx1, ry1); + } + + left->x = lx1; + left->y = ly1; + right->x = rx1; + right->y = ry1; +} + +static void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth, int ncap) { + int i, n; + float w = lineWidth * 0.5f; + float dlx0 = p0->dy, dly0 = -p0->dx; + float dlx1 = p1->dy, dly1 = -p1->dx; + float a0 = atan2f(dly0, dlx0); + float a1 = atan2f(dly1, dlx1); + float da = a1 - a0; + float lx, ly, rx, ry; + + if (da < NSVG_PI) + da += NSVG_PI * 2; + if (da > NSVG_PI) + da -= NSVG_PI * 2; + + n = (int)ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap); + if (n < 2) + n = 2; + if (n > ncap) + n = ncap; + + lx = left->x; + ly = left->y; + rx = right->x; + ry = right->y; + + for (i = 0; i < n; i++) { + float u = (float)i / (float)(n - 1); + float a = a0 + u * da; + float ax = cosf(a) * w, ay = sinf(a) * w; + float lx1 = p1->x - ax, ly1 = p1->y - ay; + float rx1 = p1->x + ax, ry1 = p1->y + ay; + + nsvg__addEdge(r, lx1, ly1, lx, ly); + nsvg__addEdge(r, rx, ry, rx1, ry1); + + lx = lx1; + ly = ly1; + rx = rx1; + ry = ry1; + } + + left->x = lx; + left->y = ly; + right->x = rx; + right->y = ry; +} + +static void nsvg__straightJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1, float lineWidth) { + float w = lineWidth * 0.5f; + float lx = p1->x - (p1->dmx * w), ly = p1->y - (p1->dmy * w); + float rx = p1->x + (p1->dmx * w), ry = p1->y + (p1->dmy * w); + + nsvg__addEdge(r, lx, ly, left->x, left->y); + nsvg__addEdge(r, right->x, right->y, rx, ry); + + left->x = lx; + left->y = ly; + right->x = rx; + right->y = ry; +} + +static int nsvg__curveDivs(float r, float arc, float tol) { + float da = acosf(r / (r + tol)) * 2.0f; + int divs = (int)ceilf(arc / da); + if (divs < 2) + divs = 2; + return divs; +} + +static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints, int closed, int lineJoin, int lineCap, float lineWidth) { + int ncap = nsvg__curveDivs(lineWidth * 0.5f, NSVG_PI, r->tessTol); // Calculate divisions per half circle. + NSVGpoint left = {0, 0, 0, 0, 0, 0, 0, 0}, right = {0, 0, 0, 0, 0, 0, 0, 0}, firstLeft = {0, 0, 0, 0, 0, 0, 0, 0}, firstRight = {0, 0, 0, 0, 0, 0, 0, 0}; + NSVGpoint *p0, *p1; + int j, s, e; + + // Build stroke edges + if (closed) { + // Looping + p0 = &points[npoints - 1]; + p1 = &points[0]; + s = 0; + e = npoints; + } else { + // Add cap + p0 = &points[0]; + p1 = &points[1]; + s = 1; + e = npoints - 1; + } + + if (closed) { + nsvg__initClosed(&left, &right, p0, p1, lineWidth); + firstLeft = left; + firstRight = right; + } else { + // Add cap + float dx = p1->x - p0->x; + float dy = p1->y - p0->y; + nsvg__normalize(&dx, &dy); + if (lineCap == NSVG_CAP_BUTT) + nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0); + else if (lineCap == NSVG_CAP_SQUARE) + nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0); + else if (lineCap == NSVG_CAP_ROUND) + nsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0); + } + + for (j = s; j < e; ++j) { + if (p1->flags & NSVG_PT_CORNER) { + if (lineJoin == NSVG_JOIN_ROUND) + nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap); + else if (lineJoin == NSVG_JOIN_BEVEL || (p1->flags & NSVG_PT_BEVEL)) + nsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth); + else + nsvg__miterJoin(r, &left, &right, p0, p1, lineWidth); + } else { + nsvg__straightJoin(r, &left, &right, p1, lineWidth); + } + p0 = p1++; + } + + if (closed) { + // Loop it + nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y); + nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y); + } else { + // Add cap + float dx = p1->x - p0->x; + float dy = p1->y - p0->y; + nsvg__normalize(&dx, &dy); + if (lineCap == NSVG_CAP_BUTT) + nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1); + else if (lineCap == NSVG_CAP_SQUARE) + nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1); + else if (lineCap == NSVG_CAP_ROUND) + nsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1); + } +} + +static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoin) { + int i, j; + NSVGpoint *p0, *p1; + + p0 = &r->points[r->npoints - 1]; + p1 = &r->points[0]; + for (i = 0; i < r->npoints; i++) { + // Calculate segment direction and length + p0->dx = p1->x - p0->x; + p0->dy = p1->y - p0->y; + p0->len = nsvg__normalize(&p0->dx, &p0->dy); + // Advance + p0 = p1++; + } + + // calculate joins + p0 = &r->points[r->npoints - 1]; + p1 = &r->points[0]; + for (j = 0; j < r->npoints; j++) { + float dlx0, dly0, dlx1, dly1, dmr2, cross; + dlx0 = p0->dy; + dly0 = -p0->dx; + dlx1 = p1->dy; + dly1 = -p1->dx; + // Calculate extrusions + p1->dmx = (dlx0 + dlx1) * 0.5f; + p1->dmy = (dly0 + dly1) * 0.5f; + dmr2 = p1->dmx * p1->dmx + p1->dmy * p1->dmy; + if (dmr2 > 0.000001f) { + float s2 = 1.0f / dmr2; + if (s2 > 600.0f) { + s2 = 600.0f; + } + p1->dmx *= s2; + p1->dmy *= s2; + } + + // Clear flags, but keep the corner. + p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0; + + // Keep track of left turns. + cross = p1->dx * p0->dy - p0->dx * p1->dy; + if (cross > 0.0f) + p1->flags |= NSVG_PT_LEFT; + + // Check to see if the corner needs to be beveled. + if (p1->flags & NSVG_PT_CORNER) { + if ((dmr2 * miterLimit * miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) { + p1->flags |= NSVG_PT_BEVEL; + } + } + + p0 = p1++; + } +} + +static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float scale) { + int i, j, closed; + NSVGpath* path; + NSVGpoint *p0, *p1; + float miterLimit = shape->miterLimit; + int lineJoin = shape->strokeLineJoin; + int lineCap = shape->strokeLineCap; + float lineWidth = shape->strokeWidth * scale; + + for (path = shape->paths; path != NULL; path = path->next) { + // Flatten path + r->npoints = 0; + nsvg__addPathPoint(r, path->pts[0] * scale, path->pts[1] * scale, NSVG_PT_CORNER); + for (i = 0; i < path->npts - 1; i += 3) { + float* p = &path->pts[i * 2]; + nsvg__flattenCubicBez(r, p[0] * scale, p[1] * scale, p[2] * scale, p[3] * scale, p[4] * scale, p[5] * scale, p[6] * scale, p[7] * scale, 0, + NSVG_PT_CORNER); + } + if (r->npoints < 2) + continue; + + closed = path->closed; + + // If the first and last points are the same, remove the last, mark as closed path. + p0 = &r->points[r->npoints - 1]; + p1 = &r->points[0]; + if (nsvg__ptEquals(p0->x, p0->y, p1->x, p1->y, r->distTol)) { + r->npoints--; + p0 = &r->points[r->npoints - 1]; + closed = 1; + } + + if (shape->strokeDashCount > 0) { + int idash = 0, dashState = 1; + float totalDist = 0, dashLen, allDashLen, dashOffset; + NSVGpoint cur; + + if (closed) + nsvg__appendPathPoint(r, r->points[0]); + + // Duplicate points -> points2. + nsvg__duplicatePoints(r); + + r->npoints = 0; + cur = r->points2[0]; + nsvg__appendPathPoint(r, cur); + + // Figure out dash offset. + allDashLen = 0; + for (j = 0; j < shape->strokeDashCount; j++) + allDashLen += shape->strokeDashArray[j]; + if (shape->strokeDashCount & 1) + allDashLen *= 2.0f; + // Find location inside pattern + dashOffset = fmodf(shape->strokeDashOffset, allDashLen); + if (dashOffset < 0.0f) + dashOffset += allDashLen; + + while (dashOffset > shape->strokeDashArray[idash]) { + dashOffset -= shape->strokeDashArray[idash]; + idash = (idash + 1) % shape->strokeDashCount; + } + dashLen = (shape->strokeDashArray[idash] - dashOffset) * scale; + + for (j = 1; j < r->npoints2;) { + float dx = r->points2[j].x - cur.x; + float dy = r->points2[j].y - cur.y; + float dist = sqrtf(dx * dx + dy * dy); + + if ((totalDist + dist) > dashLen) { + // Calculate intermediate point + float d = (dashLen - totalDist) / dist; + float x = cur.x + dx * d; + float y = cur.y + dy * d; + nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER); + + // Stroke + if (r->npoints > 1 && dashState) { + nsvg__prepareStroke(r, miterLimit, lineJoin); + nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); + } + // Advance dash pattern + dashState = !dashState; + idash = (idash + 1) % shape->strokeDashCount; + dashLen = shape->strokeDashArray[idash] * scale; + // Restart + cur.x = x; + cur.y = y; + cur.flags = NSVG_PT_CORNER; + totalDist = 0.0f; + r->npoints = 0; + nsvg__appendPathPoint(r, cur); + } else { + totalDist += dist; + cur = r->points2[j]; + nsvg__appendPathPoint(r, cur); + j++; + } + } + // Stroke any leftover path + if (r->npoints > 1 && dashState) + nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); + } else { + nsvg__prepareStroke(r, miterLimit, lineJoin); + nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth); + } + } +} + +static int nsvg__cmpEdge(const void* p, const void* q) { + const NSVGedge* a = (const NSVGedge*)p; + const NSVGedge* b = (const NSVGedge*)q; + + if (a->y0 < b->y0) + return -1; + if (a->y0 > b->y0) + return 1; + return 0; +} + +static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float startPoint) { + NSVGactiveEdge* z; + + if (r->freelist != NULL) { + // Restore from freelist. + z = r->freelist; + r->freelist = z->next; + } else { + // Alloc new edge. + z = (NSVGactiveEdge*)nsvg__alloc(r, sizeof(NSVGactiveEdge)); + if (z == NULL) + return NULL; + } + + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + // STBTT_assert(e->y0 <= start_point); + // round dx down to avoid going too far + if (dxdy < 0) + z->dx = (int)(-nsvg__roundf(NSVG__FIX * -dxdy)); + else + z->dx = (int)nsvg__roundf(NSVG__FIX * dxdy); + z->x = (int)nsvg__roundf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0))); + // z->x -= off_x * FIX; + z->ey = e->y1; + z->next = 0; + z->dir = e->dir; + + return z; +} + +static void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z) { + z->next = r->freelist; + r->freelist = z; +} + +static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax) { + int i = x0 >> NSVG__FIXSHIFT; + int j = x1 >> NSVG__FIXSHIFT; + if (i < *xmin) + *xmin = i; + if (j > *xmax) + *xmax = j; + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT)); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT)); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT)); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = (unsigned char)(scanline[i] + maxWeight); + } + } +} + +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule) { + // non-zero winding fill + int x0 = 0, w = 0; + + if (fillRule == NSVG_FILLRULE_NONZERO) { + // Non-zero + while (e != NULL) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; + w += e->dir; + } else { + int x1 = e->x; + w += e->dir; + // if we went to zero, we need to draw + if (w == 0) + nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); + } + e = e->next; + } + } else if (fillRule == NSVG_FILLRULE_EVENODD) { + // Even-odd + while (e != NULL) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; + w = 1; + } else { + int x1 = e->x; + w = 0; + nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); + } + e = e->next; + } + } +} + +static float nsvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); } + +static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + return ((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16) | ((unsigned int)a << 24); +} + +static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u) { + int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f); + int r = (((c0) & 0xff) * (256 - iu) + (((c1) & 0xff) * iu)) >> 8; + int g = (((c0 >> 8) & 0xff) * (256 - iu) + (((c1 >> 8) & 0xff) * iu)) >> 8; + int b = (((c0 >> 16) & 0xff) * (256 - iu) + (((c1 >> 16) & 0xff) * iu)) >> 8; + int a = (((c0 >> 24) & 0xff) * (256 - iu) + (((c1 >> 24) & 0xff) * iu)) >> 8; + return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); +} + +static unsigned int nsvg__applyOpacity(unsigned int c, float u) { + int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f); + int r = (c) & 0xff; + int g = (c >> 8) & 0xff; + int b = (c >> 16) & 0xff; + int a = (((c >> 24) & 0xff) * iu) >> 8; + return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); +} + +static inline int nsvg__div255(int x) { return ((x + 1) * 257) >> 16; } + +static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y, float tx, float ty, float scale, NSVGcachedPaint* cache) { + + if (cache->type == NSVG_PAINT_COLOR) { + int i, cr, cg, cb, ca; + cr = cache->colors[0] & 0xff; + cg = (cache->colors[0] >> 8) & 0xff; + cb = (cache->colors[0] >> 16) & 0xff; + ca = (cache->colors[0] >> 24) & 0xff; + + for (i = 0; i < count; i++) { + int r, g, b; + int a = nsvg__div255((int)cover[0] * ca); + int ia = 255 - a; + // Premultiply + r = nsvg__div255(cr * a); + g = nsvg__div255(cg * a); + b = nsvg__div255(cb * a); + + // Blend over + r += nsvg__div255(ia * (int)dst[0]); + g += nsvg__div255(ia * (int)dst[1]); + b += nsvg__div255(ia * (int)dst[2]); + a += nsvg__div255(ia * (int)dst[3]); + + dst[0] = (unsigned char)r; + dst[1] = (unsigned char)g; + dst[2] = (unsigned char)b; + dst[3] = (unsigned char)a; + + cover++; + dst += 4; + } + } else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) { + // TODO: spread modes. + // TODO: plenty of opportunities to optimize. + float fx, fy, dx, gy; + float* t = cache->xform; + int i, cr, cg, cb, ca; + unsigned int c; + + fx = ((float)x - tx) / scale; + fy = ((float)y - ty) / scale; + dx = 1.0f / scale; + + for (i = 0; i < count; i++) { + int r, g, b, a, ia; + gy = fx * t[1] + fy * t[3] + t[5]; + c = cache->colors[(int)nsvg__clampf(gy * 255.0f, 0, 255.0f)]; + cr = (c) & 0xff; + cg = (c >> 8) & 0xff; + cb = (c >> 16) & 0xff; + ca = (c >> 24) & 0xff; + + a = nsvg__div255((int)cover[0] * ca); + ia = 255 - a; + + // Premultiply + r = nsvg__div255(cr * a); + g = nsvg__div255(cg * a); + b = nsvg__div255(cb * a); + + // Blend over + r += nsvg__div255(ia * (int)dst[0]); + g += nsvg__div255(ia * (int)dst[1]); + b += nsvg__div255(ia * (int)dst[2]); + a += nsvg__div255(ia * (int)dst[3]); + + dst[0] = (unsigned char)r; + dst[1] = (unsigned char)g; + dst[2] = (unsigned char)b; + dst[3] = (unsigned char)a; + + cover++; + dst += 4; + fx += dx; + } + } else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) { + // TODO: spread modes. + // TODO: plenty of opportunities to optimize. + // TODO: focus (fx,fy) + float fx, fy, dx, gx, gy, gd; + float* t = cache->xform; + int i, cr, cg, cb, ca; + unsigned int c; + + fx = ((float)x - tx) / scale; + fy = ((float)y - ty) / scale; + dx = 1.0f / scale; + + for (i = 0; i < count; i++) { + int r, g, b, a, ia; + gx = fx * t[0] + fy * t[2] + t[4]; + gy = fx * t[1] + fy * t[3] + t[5]; + gd = sqrtf(gx * gx + gy * gy); + c = cache->colors[(int)nsvg__clampf(gd * 255.0f, 0, 255.0f)]; + cr = (c) & 0xff; + cg = (c >> 8) & 0xff; + cb = (c >> 16) & 0xff; + ca = (c >> 24) & 0xff; + + a = nsvg__div255((int)cover[0] * ca); + ia = 255 - a; + + // Premultiply + r = nsvg__div255(cr * a); + g = nsvg__div255(cg * a); + b = nsvg__div255(cb * a); + + // Blend over + r += nsvg__div255(ia * (int)dst[0]); + g += nsvg__div255(ia * (int)dst[1]); + b += nsvg__div255(ia * (int)dst[2]); + a += nsvg__div255(ia * (int)dst[3]); + + dst[0] = (unsigned char)r; + dst[1] = (unsigned char)g; + dst[2] = (unsigned char)b; + dst[3] = (unsigned char)a; + + cover++; + dst += 4; + fx += dx; + } + } +} + +static void nsvg__rasterizeSortedEdges(NSVGrasterizer* r, float tx, float ty, float scale, NSVGcachedPaint* cache, char fillRule) { + NSVGactiveEdge* active = NULL; + int y, s; + int e = 0; + int maxWeight = (255 / NSVG__SUBSAMPLES); // weight per vertical scanline + int xmin, xmax; + + for (y = 0; y < r->height; y++) { + memset(r->scanline, 0, r->width); + xmin = r->width; + xmax = 0; + for (s = 0; s < NSVG__SUBSAMPLES; ++s) { + // find center of pixel for this scanline + float scany = (float)(y * NSVG__SUBSAMPLES + s) + 0.5f; + NSVGactiveEdge** step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + NSVGactiveEdge* z = *step; + if (z->ey <= scany) { + *step = z->next; // delete from list + // NSVG__assert(z->valid); + nsvg__freeActive(r, z); + } else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for (;;) { + int changed = 0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + NSVGactiveEdge* t = *step; + NSVGactiveEdge* q = t->next; + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) + break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e < r->nedges && r->edges[e].y0 <= scany) { + if (r->edges[e].y1 > scany) { + NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany); + if (z == NULL) + break; + // find insertion point + if (active == NULL) { + active = z; + } else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + NSVGactiveEdge* p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + e++; + } + + // now process all active edges in non-zero fashion + if (active != NULL) + nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule); + } + // Blit + if (xmin < 0) + xmin = 0; + if (xmax > r->width - 1) + xmax = r->width - 1; + if (xmin <= xmax) { + nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin * 4, xmax - xmin + 1, &r->scanline[xmin], xmin, y, tx, ty, scale, cache); + } + } +} + +static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride) { + int x, y; + + // Unpremultiply + for (y = 0; y < h; y++) { + unsigned char* row = &image[y * stride]; + for (x = 0; x < w; x++) { + int r = row[0], g = row[1], b = row[2], a = row[3]; + if (a != 0) { + row[0] = (unsigned char)(r * 255 / a); + row[1] = (unsigned char)(g * 255 / a); + row[2] = (unsigned char)(b * 255 / a); + } + row += 4; + } + } + + // Defringe + for (y = 0; y < h; y++) { + unsigned char* row = &image[y * stride]; + for (x = 0; x < w; x++) { + int r = 0, g = 0, b = 0, a = row[3], n = 0; + if (a == 0) { + if (x - 1 > 0 && row[-1] != 0) { + r += row[-4]; + g += row[-3]; + b += row[-2]; + n++; + } + if (x + 1 < w && row[7] != 0) { + r += row[4]; + g += row[5]; + b += row[6]; + n++; + } + if (y - 1 > 0 && row[-stride + 3] != 0) { + r += row[-stride]; + g += row[-stride + 1]; + b += row[-stride + 2]; + n++; + } + if (y + 1 < h && row[stride + 3] != 0) { + r += row[stride]; + g += row[stride + 1]; + b += row[stride + 2]; + n++; + } + if (n > 0) { + row[0] = (unsigned char)(r / n); + row[1] = (unsigned char)(g / n); + row[2] = (unsigned char)(b / n); + } + } + row += 4; + } + } +} + +static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opacity) { + int i, j; + NSVGgradient* grad; + + cache->type = paint->type; + + if (paint->type == NSVG_PAINT_COLOR) { + cache->colors[0] = nsvg__applyOpacity(paint->color, opacity); + return; + } + + grad = paint->gradient; + + cache->spread = grad->spread; + memcpy(cache->xform, grad->xform, sizeof(float) * 6); + + if (grad->nstops == 0) { + for (i = 0; i < 256; i++) + cache->colors[i] = 0; + } else if (grad->nstops == 1) { + unsigned int color = nsvg__applyOpacity(grad->stops[0].color, opacity); + for (i = 0; i < 256; i++) + cache->colors[i] = color; + } else { + unsigned int ca, cb = 0; + float ua, ub, du, u; + int ia, ib, count; + + ca = nsvg__applyOpacity(grad->stops[0].color, opacity); + ua = nsvg__clampf(grad->stops[0].offset, 0, 1); + ub = nsvg__clampf(grad->stops[grad->nstops - 1].offset, ua, 1); + ia = (int)(ua * 255.0f); + ib = (int)(ub * 255.0f); + for (i = 0; i < ia; i++) { + cache->colors[i] = ca; + } + + for (i = 0; i < grad->nstops - 1; i++) { + ca = nsvg__applyOpacity(grad->stops[i].color, opacity); + cb = nsvg__applyOpacity(grad->stops[i + 1].color, opacity); + ua = nsvg__clampf(grad->stops[i].offset, 0, 1); + ub = nsvg__clampf(grad->stops[i + 1].offset, 0, 1); + ia = (int)(ua * 255.0f); + ib = (int)(ub * 255.0f); + count = ib - ia; + if (count <= 0) + continue; + u = 0; + du = 1.0f / (float)count; + for (j = 0; j < count; j++) { + cache->colors[ia + j] = nsvg__lerpRGBA(ca, cb, u); + u += du; + } + } + + for (i = ib; i < 256; i++) + cache->colors[i] = cb; + } +} + +/* +static void dumpEdges(NSVGrasterizer* r, const char* name) +{ + float xmin = 0, xmax = 0, ymin = 0, ymax = 0; + NSVGedge *e = NULL; + int i; + if (r->nedges == 0) return; + FILE* fp = fopen(name, "w"); + if (fp == NULL) return; + + xmin = xmax = r->edges[0].x0; + ymin = ymax = r->edges[0].y0; + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + xmin = nsvg__minf(xmin, e->x0); + xmin = nsvg__minf(xmin, e->x1); + xmax = nsvg__maxf(xmax, e->x0); + xmax = nsvg__maxf(xmax, e->x1); + ymin = nsvg__minf(ymin, e->y0); + ymin = nsvg__minf(ymin, e->y1); + ymax = nsvg__maxf(ymax, e->y0); + ymax = nsvg__maxf(ymax, e->y1); + } + + fprintf(fp, "", xmin, ymin, (xmax - xmin), (ymax - ymin)); + + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + fprintf(fp ,"", e->x0,e->y0, e->x1,e->y1); + } + + for (i = 0; i < r->npoints; i++) { + if (i+1 < r->npoints) + fprintf(fp ,"", r->points[i].x, r->points[i].y, r->points[i+1].x, +r->points[i+1].y); fprintf(fp ,"", r->points[i].x, r->points[i].y, r->points[i].flags == 0 ? "#f00" : +"#0f0"); + } + + fprintf(fp, ""); + fclose(fp); +} +*/ + +void nsvgRasterize(NSVGrasterizer* r, NSVGimage* image, float tx, float ty, float scale, unsigned char* dst, int w, int h, int stride) { + NSVGshape* shape = NULL; + NSVGedge* e = NULL; + NSVGcachedPaint cache; + int i; + int j; + unsigned char paintOrder; + + r->bitmap = dst; + r->width = w; + r->height = h; + r->stride = stride; + + if (w > r->cscanline) { + r->cscanline = w; + r->scanline = (unsigned char*)realloc(r->scanline, w); + if (r->scanline == NULL) + return; + } + + for (i = 0; i < h; i++) + memset(&dst[i * stride], 0, w * 4); + + for (shape = image->shapes; shape != NULL; shape = shape->next) { + if (!(shape->flags & NSVG_FLAGS_VISIBLE)) + continue; + + for (j = 0; j < 3; j++) { + paintOrder = (shape->paintOrder >> (2 * j)) & 0x03; + + if (paintOrder == NSVG_PAINT_FILL && shape->fill.type != NSVG_PAINT_NONE) { + nsvg__resetPool(r); + r->freelist = NULL; + r->nedges = 0; + + nsvg__flattenShape(r, shape, scale); + + // Scale and translate edges + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + e->x0 = tx + e->x0; + e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES; + e->x1 = tx + e->x1; + e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; + } + + // Rasterize edges + if (r->nedges != 0) + qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); + + // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule + nsvg__initPaint(&cache, &shape->fill, shape->opacity); + + nsvg__rasterizeSortedEdges(r, tx, ty, scale, &cache, shape->fillRule); + } + if (paintOrder == NSVG_PAINT_STROKE && shape->stroke.type != NSVG_PAINT_NONE && (shape->strokeWidth * scale) > 0.01f) { + nsvg__resetPool(r); + r->freelist = NULL; + r->nedges = 0; + + nsvg__flattenShapeStroke(r, shape, scale); + + // dumpEdges(r, "edge.svg"); + + // Scale and translate edges + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + e->x0 = tx + e->x0; + e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES; + e->x1 = tx + e->x1; + e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; + } + + // Rasterize edges + if (r->nedges != 0) + qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); + + // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule + nsvg__initPaint(&cache, &shape->stroke, shape->opacity); + + nsvg__rasterizeSortedEdges(r, tx, ty, scale, &cache, NSVG_FILLRULE_NONZERO); + } + } + } + + nsvg__unpremultiplyAlpha(dst, w, h, stride); + + r->bitmap = NULL; + r->width = 0; + r->height = 0; + r->stride = 0; +} + +#endif // NANOSVGRAST_IMPLEMENTATION + +#endif // NANOSVGRAST_H \ No newline at end of file diff --git a/src/COMMON.h b/src/COMMON.h deleted file mode 100644 index 03b777f..0000000 --- a/src/COMMON.h +++ /dev/null @@ -1,400 +0,0 @@ -#pragma once - -#include -#define GLAD_GL_IMPLEMENTATION -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace glm; - -#define PREFERENCES_DIRECTORY "anm2ed" - -#define ROUND_NEAREST_MULTIPLE(value, multiple) (roundf((value) / (multiple)) * (multiple)) -#define FLOAT_TO_UINT8(x) (static_cast((x) * 255.0f)) -#define UINT8_TO_FLOAT(x) ((x) / 255.0f) -#define PERCENT_TO_UNIT(x) (x / 100.0f) -#define UNIT_TO_PERCENT(x) (x * 100.0f) -#define SECOND 1000.0f -#define TICK_DELAY (SECOND / 30.0) -#define UPDATE_DELAY (SECOND / 120.0) -#define ID_NONE -1 -#define INDEX_NONE -1 -#define VALUE_NONE -1 -#define TIME_NONE -1.0f -#define GL_ID_NONE 0 - -#ifdef _WIN32 -#define POPEN _popen -#define PCLOSE _pclose -#define PWRITE_MODE "wb" -#define PREAD_MODE "r" -#else -#define POPEN popen -#define PCLOSE pclose -#define PWRITE_MODE "w" -#define PREAD_MODE "r" -#endif - -static const GLuint GL_TEXTURE_INDICES[] = {0, 1, 2, 2, 3, 0}; -static const vec4 COLOR_RED = {1.0f, 0.0f, 0.0f, 1.0f}; -static const vec4 COLOR_GREEN = {0.0f, 1.0f, 0.0f, 1.0f}; -static const vec4 COLOR_BLUE = {0.0f, 0.0f, 1.0f, 1.0f}; -static const vec4 COLOR_PINK = {1.0f, 0.0f, 1.0f, 1.0f}; -static const vec4 COLOR_OPAQUE = {1.0f, 1.0f, 1.0f, 1.0f}; -static const vec4 COLOR_TRANSPARENT = {0.0f, 0.0f, 0.0f, 0.0f}; -static const vec3 COLOR_OFFSET_NONE = {0.0f, 0.0f, 0.0f}; - -static inline std::string preferences_path_get(void) { - char* preferencesPath = SDL_GetPrefPath("", PREFERENCES_DIRECTORY); - std::string preferencesPathString = preferencesPath; - SDL_free(preferencesPath); - return preferencesPathString; -} - -static inline bool string_to_bool(const std::string& string) { - if (string == "1") - return true; - - std::string lower = string; - std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); - - return lower == "true"; -} - -static inline std::string string_quote(const std::string& string) { return "\"" + string + "\""; } - -static inline std::string string_to_lowercase(std::string string) { - std::transform(string.begin(), string.end(), string.begin(), [](char character) { return std::tolower(character); }); - return string; -} - -static inline std::string string_backslash_replace(std::string string) { - for (char& character : string) - if (character == '\\') - character = '/'; - return string; -} - -#define FLOAT_FORMAT_MAX_DECIMALS 5 -#define FLOAT_FORMAT_EPSILON 1e-5f -static constexpr float FLOAT_FORMAT_POW10[] = {1.f, 10.f, 100.f, 1000.f, 10000.f, 100000.f}; - -static inline int float_decimals_needed(float value) { - for (int decimalCount = 0; decimalCount <= FLOAT_FORMAT_MAX_DECIMALS; ++decimalCount) { - float scale = FLOAT_FORMAT_POW10[decimalCount]; - float rounded = roundf(value * scale) / scale; - if (fabsf(value - rounded) < FLOAT_FORMAT_EPSILON) - return decimalCount; - } - return FLOAT_FORMAT_MAX_DECIMALS; -} - -static inline const char* float_format_get(float value) { - static std::string formatString; - const int decimalCount = float_decimals_needed(value); - formatString = (decimalCount == 0) ? "%.0f" : ("%." + std::to_string(decimalCount) + "f"); - return formatString.c_str(); -} - -static inline const char* vec2_format_get(const vec2& value) { - static std::string formatString; - const int decimalCountX = float_decimals_needed(value.x); - const int decimalCountY = float_decimals_needed(value.y); - const int decimalCount = (decimalCountX > decimalCountY) ? decimalCountX : decimalCountY; - formatString = (decimalCount == 0) ? "%.0f" : ("%." + std::to_string(decimalCount) + "f"); - return formatString.c_str(); -} - -static inline std::string working_directory_from_file_set(const std::string& path) { - std::filesystem::path filePath = path; - std::filesystem::path parentPath = filePath.parent_path(); - std::filesystem::current_path(parentPath); - return parentPath.string(); -}; - -static inline std::string path_extension_change(const std::string& path, const std::string& extension) { - std::filesystem::path filePath(path); - filePath.replace_extension(extension); - return filePath.string(); -} - -static inline bool path_is_extension(const std::string& path, const std::string& extension) { - auto e = std::filesystem::path(path).extension().string(); - std::transform(e.begin(), e.end(), e.begin(), ::tolower); - return e == ("." + extension); -} - -static inline bool path_exists(const std::filesystem::path& pathCheck) { - std::error_code errorCode; - return std::filesystem::exists(pathCheck, errorCode) && ((void)std::filesystem::status(pathCheck, errorCode), !errorCode); -} - -static inline bool path_is_valid(const std::filesystem::path& pathCheck) { - namespace fs = std::filesystem; - std::error_code ec; - - if (fs::is_directory(pathCheck, ec)) - return false; - - fs::path parentDir = pathCheck.has_parent_path() ? pathCheck.parent_path() : fs::path("."); - if (!fs::is_directory(parentDir, ec)) - return false; - - bool existedBefore = fs::exists(pathCheck, ec); - std::ofstream testStream(pathCheck, std::ios::app | std::ios::binary); - bool isValid = testStream.is_open(); - testStream.close(); - - if (!existedBefore && isValid) - fs::remove(pathCheck, ec); - - return isValid; -} - -static inline int string_to_enum(const std::string& string, const char* const* array, int n) { - for (int i = 0; i < n; i++) - if (string == array[i]) - return i; - return -1; -}; - -template T& dummy_value() { - static T value{}; - return value; -} - -template static inline int map_next_id_get(const std::map& map) { - int id = 0; - - for (const auto& [key, value] : map) { - if (key != id) - break; - ++id; - } - - return id; -} - -template static inline auto map_find(Map& map, typename Map::key_type id) -> typename Map::mapped_type* { - if (auto it = map.find(id); it != map.end()) - return &it->second; - return nullptr; -} - -template static inline void map_swap(Map& map, const Key& key1, const Key& key2) { - if (key1 == key2) - return; - - auto it1 = map.find(key1); - auto it2 = map.find(key2); - - if (it1 != map.end() && it2 != map.end()) { - using std::swap; - swap(it1->second, it2->second); - } else if (it1 != map.end()) { - map[key2] = std::move(it1->second); - map.erase(it1); - } else if (it2 != map.end()) { - map[key1] = std::move(it2->second); - map.erase(it2); - } -}; - -template static inline void map_insert_shift(std::map& map, int id, const T& value) { - const int insertID = id + 1; - - std::vector> toShift; - for (auto it = map.rbegin(); it != map.rend(); ++it) { - if (it->first < insertID) - break; - toShift.emplace_back(it->first + 1, std::move(it->second)); - } - - for (const auto& [newKey, _] : toShift) - map.erase(newKey - 1); - - for (auto& [newKey, val] : toShift) - map[newKey] = std::move(val); - - map[insertID] = value; -} - -template auto map_keys_to_set(const Map& m) { - using Key = typename Map::key_type; - std::unordered_set s; - s.reserve(m.size()); - for (const auto& [key, _] : m) { - s.insert(key); - } - return s; -} - -template Set set_symmetric_difference(const Set& a, const Set& b) { - Set result; - result.reserve(a.size() + b.size()); - - for (const auto& x : a) { - if (!b.contains(x)) { - result.insert(x); - } - } - - for (const auto& x : b) { - if (!a.contains(x)) { - result.insert(x); - } - } - - return result; -} - -template static inline T* vector_find(std::vector& v, const T& value) { - auto it = std::find(v.begin(), v.end(), value); - return (it != v.end()) ? &(*it) : nullptr; -} - -template static inline void vector_value_erase(std::vector& v, const T& value) { v.erase(std::remove(v.begin(), v.end(), value), v.end()); } - -template static inline void vector_value_swap(std::vector& v, const T& a, const T& b) { - for (auto& element : v) { - if (element == a) - element = b; - else if (element == b) - element = a; - } -} - -template static inline T* vector_get(std::vector& v, size_t index) { - if (index < v.size()) - return &v[index]; - return nullptr; -} - -template static inline void vector_move(std::vector& v, size_t from, size_t to) { - if (from >= v.size() || to >= v.size() || from == to) - return; - - if (from < to) { - std::rotate(v.begin() + from, v.begin() + from + 1, v.begin() + to + 1); - } else { - std::rotate(v.begin() + to, v.begin() + from, v.begin() + from + 1); - } -} - -template void vector_erase_indices(std::vector& v, const std::set& indices) { - size_t i = 0; - v.erase(std::remove_if(v.begin(), v.end(), [&](const T&) { return indices.count(i++) > 0; }), v.end()); -} - -template static inline void set_key_toggle(std::set& set, T key) { - if (auto it = set.find(key); it != set.end()) - set.erase(it); - else - set.insert(key); -} - -template static inline void set_list(std::set& s, const T& key, bool isCtrl, bool isShift, T* lastSelected) { - if (isShift && lastSelected) { - s.clear(); - T a = std::min(*lastSelected, key); - T b = std::max(*lastSelected, key); - for (T i = a; i <= b; i++) - s.insert(i); - } else if (isCtrl) { - set_key_toggle(s, key); - *lastSelected = key; - } else { - s = {key}; - *lastSelected = key; - } -} - -static inline mat4 quad_model_get(vec2 size = {}, vec2 position = {}, vec2 pivot = {}, vec2 scale = vec2(1.0f), float rotation = {}) { - vec2 scaleAbsolute = glm::abs(scale); - vec2 scaleSign = glm::sign(scale); - vec2 pivotScaled = pivot * scaleAbsolute; - vec2 sizeScaled = size * scaleAbsolute; - - mat4 model(1.0f); - model = glm::translate(model, vec3(position - pivotScaled, 0.0f)); - model = glm::translate(model, vec3(pivotScaled, 0.0f)); - model = glm::scale(model, vec3(scaleSign, 1.0f)); - model = glm::rotate(model, glm::radians(rotation), vec3(0, 0, 1)); - model = glm::translate(model, vec3(-pivotScaled, 0.0f)); - model = glm::scale(model, vec3(sizeScaled, 1.0f)); - return model; -} - -static inline mat4 quad_model_parent_get(vec2 position = {}, vec2 pivot = {}, vec2 scale = vec2(1.0f), float rotation = {}) { - vec2 scaleSign = glm::sign(scale); - vec2 scaleAbsolute = glm::abs(scale); - float handedness = (scaleSign.x * scaleSign.y) < 0.0f ? -1.0f : 1.0f; - - mat4 local(1.0f); - local = glm::translate(local, vec3(pivot, 0.0f)); - local = glm::scale(local, vec3(scaleSign, 1.0f)); - local = glm::rotate(local, glm::radians(rotation) * handedness, vec3(0, 0, 1)); - local = glm::translate(local, vec3(-pivot, 0.0f)); - local = glm::scale(local, vec3(scaleAbsolute, 1.0f)); - - return glm::translate(mat4(1.0f), vec3(position, 0.0f)) * local; -} - -#define DEFINE_STRING_TO_ENUM_FUNCTION(function, enumType, stringArray, count) \ - static inline enumType function(const std::string& string) { return static_cast(string_to_enum(string, stringArray, count)); }; - -#define DATATYPE_LIST \ - X(TYPE_INT, int) \ - X(TYPE_BOOL, bool) \ - X(TYPE_FLOAT, float) \ - X(TYPE_STRING, std::string) \ - X(TYPE_IVEC2, ivec2) \ - X(TYPE_IVEC2_WH, ivec2) \ - X(TYPE_VEC2, vec2) \ - X(TYPE_VEC2_WH, vec2) \ - X(TYPE_VEC3, vec3) \ - X(TYPE_VEC4, vec4) - -enum DataType { -#define X(symbol, ctype) symbol, - DATATYPE_LIST -#undef X -}; - -#define DATATYPE_TO_CTYPE(dt) DATATYPE_CTYPE_##dt -#define X(symbol, ctype) typedef ctype DATATYPE_CTYPE_##symbol; -DATATYPE_LIST -#undef X - -enum OriginType { ORIGIN_TOP_LEFT, ORIGIN_CENTER }; - -struct WorkingDirectory { - std::filesystem::path previous; - WorkingDirectory(const std::string& file) { - previous = std::filesystem::current_path(); - working_directory_from_file_set(file); - } - ~WorkingDirectory() { std::filesystem::current_path(previous); } -}; \ No newline at end of file diff --git a/src/RESOURCE.h b/src/RESOURCE.h deleted file mode 100644 index 21852db..0000000 --- a/src/RESOURCE.h +++ /dev/null @@ -1,3992 +0,0 @@ -#pragma once - -#include "COMMON.h" - -#define ATLAS_PATH "resources/atlas.png" -#define FONT_REGULAR_PATH "resources/font_regular.ttf" -#define FONT_BOLD_PATH "resources/font_bold.ttf" -#define FONT_SIZE 16 - -const vec2 TEXTURE_ATLAS_SIZE = {96, 160}; - -enum AtlasType { - ATLAS_NONE, - ATLAS_FOLDER, - ATLAS_ROOT, - ATLAS_LAYER, - ATLAS_NULL, - ATLAS_TRIGGERS, - ATLAS_VISIBLE, - ATLAS_INVISIBLE, - ATLAS_SHOW_RECT, - ATLAS_HIDE_RECT, - ATLAS_SHOW_UNUSED, - ATLAS_HIDE_UNUSED, - ATLAS_PAN, - ATLAS_MOVE, - ATLAS_ROTATE, - ATLAS_SCALE, - ATLAS_CROP, - ATLAS_DRAW, - ATLAS_ERASE, - ATLAS_COLOR_PICKER, - ATLAS_UNDO, - ATLAS_REDO, - ATLAS_ANIMATION, - ATLAS_SPRITESHEET, - ATLAS_EVENT, - ATLAS_PLAY, - ATLAS_PAUSE, - ATLAS_ADD, - ATLAS_REMOVE, - ATLAS_TRIGGER, - ATLAS_PIVOT, - ATLAS_SQUARE, - ATLAS_CIRCLE, - ATLAS_PICKER, - ATLAS_FRAME, - ATLAS_FRAME_ALT, - ATLAS_TARGET, - ATLAS_TARGET_ALT, - ATLAS_COUNT -}; - -struct AtlasEntry { - vec2 position; - vec2 size; -}; - -const vec2 ATLAS_SIZE_SMALL = {8, 8}; -const vec2 ATLAS_SIZE_NORMAL = {16, 16}; -const vec2 ATLAS_SIZE_OBLONG = {16, 40}; -const vec2 ATLAS_SIZE_BIG = {40, 40}; - -const inline AtlasEntry ATLAS_ENTRIES[ATLAS_COUNT] = { - {{0, 0}, ATLAS_SIZE_NORMAL}, {{16, 0}, ATLAS_SIZE_NORMAL}, {{32, 0}, ATLAS_SIZE_NORMAL}, {{48, 0}, ATLAS_SIZE_NORMAL}, {{64, 0}, ATLAS_SIZE_NORMAL}, - {{80, 0}, ATLAS_SIZE_NORMAL}, {{0, 16}, ATLAS_SIZE_NORMAL}, {{16, 16}, ATLAS_SIZE_NORMAL}, {{32, 16}, ATLAS_SIZE_NORMAL}, {{48, 16}, ATLAS_SIZE_NORMAL}, - {{64, 16}, ATLAS_SIZE_NORMAL}, {{80, 16}, ATLAS_SIZE_NORMAL}, {{0, 32}, ATLAS_SIZE_NORMAL}, {{16, 32}, ATLAS_SIZE_NORMAL}, {{32, 32}, ATLAS_SIZE_NORMAL}, - {{48, 32}, ATLAS_SIZE_NORMAL}, {{64, 32}, ATLAS_SIZE_NORMAL}, {{80, 32}, ATLAS_SIZE_NORMAL}, {{0, 48}, ATLAS_SIZE_NORMAL}, {{16, 48}, ATLAS_SIZE_NORMAL}, - {{32, 48}, ATLAS_SIZE_NORMAL}, {{48, 48}, ATLAS_SIZE_NORMAL}, {{64, 48}, ATLAS_SIZE_NORMAL}, {{80, 48}, ATLAS_SIZE_NORMAL}, {{0, 64}, ATLAS_SIZE_NORMAL}, - {{16, 64}, ATLAS_SIZE_NORMAL}, {{32, 64}, ATLAS_SIZE_NORMAL}, {{48, 64}, ATLAS_SIZE_NORMAL}, {{64, 64}, ATLAS_SIZE_NORMAL}, {{80, 64}, ATLAS_SIZE_SMALL}, - {{88, 64}, ATLAS_SIZE_SMALL}, {{80, 72}, ATLAS_SIZE_SMALL}, {{88, 72}, ATLAS_SIZE_SMALL}, {{0, 80}, ATLAS_SIZE_OBLONG}, {{16, 80}, ATLAS_SIZE_OBLONG}, - {{32, 80}, ATLAS_SIZE_OBLONG}, {{48, 80}, ATLAS_SIZE_BIG}, {{48, 120}, ATLAS_SIZE_BIG}}; - -#define ATLAS_POSITION(type) ATLAS_ENTRIES[type].position -#define ATLAS_SIZE(type) ATLAS_ENTRIES[type].size -#define ATLAS_UV_MIN(type) (ATLAS_POSITION(type) / TEXTURE_ATLAS_SIZE) -#define ATLAS_UV_MAX(type) ((ATLAS_POSITION(type) + ATLAS_SIZE(type)) / TEXTURE_ATLAS_SIZE) -#define ATLAS_UV_ARGS(type) ATLAS_UV_MIN(type), ATLAS_UV_MAX(type) -#define ATLAS_UV_VERTICES(type) UV_VERTICES(ATLAS_UV_MIN(type), ATLAS_UV_MAX(type)) - -struct ShaderData { - std::string vertex; - std::string fragment; -}; - -enum ShaderType { SHADER_LINE, SHADER_TEXTURE, SHADER_AXIS, SHADER_GRID, SHADER_COUNT }; - -const std::string SHADER_VERTEX = R"( -#version 330 core -layout (location = 0) in vec2 i_position; -layout (location = 1) in vec2 i_uv; -out vec2 i_uv_out; -uniform mat4 u_transform; -void main() -{ - i_uv_out = i_uv; - gl_Position = u_transform * vec4(i_position, 0.0, 1.0); -} -)"; - -const std::string SHADER_AXIS_VERTEX = R"( -#version 330 core -layout (location = 0) in vec2 i_position; // full screen line segment: -1..1 -uniform vec2 u_origin_ndc; // world origin in NDC -uniform int u_axis; // 0 = X axis, 1 = Y axis - -void main() -{ - vec2 pos = (u_axis == 0) - ? vec2(i_position.x, u_origin_ndc.y) // horizontal line across screen - : vec2(u_origin_ndc.x, i_position.x); // vertical line across screen; - - gl_Position = vec4(pos, 0.0, 1.0); -} -)"; - -const std::string SHADER_GRID_VERTEX = R"( -#version 330 core -layout ( location = 0 ) in vec2 i_position; -out vec2 clip; - -void main() { - clip = i_position; - gl_Position = vec4(i_position, 0.0, 1.0); -} -)"; - -const std::string SHADER_FRAGMENT = R"( -#version 330 core -out vec4 o_fragColor; -uniform vec4 u_color; -void main() -{ - o_fragColor = u_color; -} -)"; - -const std::string SHADER_TEXTURE_FRAGMENT = R"( -#version 330 core -in vec2 i_uv_out; -uniform sampler2D u_texture; -uniform vec4 u_tint; -uniform vec3 u_color_offset; -out vec4 o_fragColor; -void main() -{ - vec4 texColor = texture(u_texture, i_uv_out); - texColor *= u_tint; - texColor.rgb += u_color_offset; - o_fragColor = texColor; -} -)"; - -const std::string SHADER_GRID_FRAGMENT = R"( -#version 330 core -in vec2 clip; - -uniform mat4 u_model; -uniform vec2 u_size; -uniform vec2 u_offset; -uniform vec4 u_color; - -out vec4 o_fragColor; - -void main() -{ - vec4 w = u_model * vec4(clip, 0.0, 1.0); - w /= w.w; - vec2 world = w.xy; - - vec2 g = (world - u_offset) / u_size; - - vec2 d = abs(fract(g) - 0.5); - float distance = min(d.x, d.y); - - float fw = min(fwidth(g.x), fwidth(g.y)); - float alpha = 1.0 - smoothstep(0.0, fw, distance); - - if (alpha <= 0.0) discard; - o_fragColor = vec4(u_color.rgb, u_color.a * alpha); -} -)"; - -#define SHADER_UNIFORM_AXIS "u_axis" -#define SHADER_UNIFORM_COLOR "u_color" -#define SHADER_UNIFORM_TRANSFORM "u_transform" -#define SHADER_UNIFORM_TINT "u_tint" -#define SHADER_UNIFORM_COLOR_OFFSET "u_color_offset" -#define SHADER_UNIFORM_OFFSET "u_offset" -#define SHADER_UNIFORM_ORIGIN_NDC "u_origin_ndc" -#define SHADER_UNIFORM_SIZE "u_size" -#define SHADER_UNIFORM_MODEL "u_model" -#define SHADER_UNIFORM_TEXTURE "u_texture" - -const ShaderData SHADER_DATA[SHADER_COUNT] = {{SHADER_VERTEX, SHADER_FRAGMENT}, - {SHADER_VERTEX, SHADER_TEXTURE_FRAGMENT}, - {SHADER_AXIS_VERTEX, SHADER_FRAGMENT}, - {SHADER_GRID_VERTEX, SHADER_GRID_FRAGMENT}}; - -enum FontType { FONT_REGULAR, FONT_ITALICS, FONT_BOLD, FONT_BOLD_ITALICS, FONT_COUNT }; - -struct Font { - const void* data; - size_t length; -}; - -const inline uint8_t TEXTURE_ATLAS[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xa0, 0x04, 0x03, - 0x00, 0x00, 0x00, 0x01, 0x5e, 0x74, 0xbf, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, - 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x0f, 0x50, 0x4c, 0x54, 0x45, 0x00, 0x00, 0x00, 0x76, 0x76, 0x76, 0xff, 0xff, 0xff, 0x60, 0x60, 0x60, 0xff, 0xff, 0xff, 0x3e, - 0xd5, 0x47, 0x6d, 0x00, 0x00, 0x00, 0x03, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x00, 0x00, 0xfa, 0x76, 0xc4, 0xde, 0x00, 0x00, 0x04, 0x62, 0x49, 0x44, 0x41, 0x54, - 0x58, 0xc3, 0xed, 0x59, 0x5b, 0x6e, 0x24, 0x37, 0x0c, 0x2c, 0x80, 0xbc, 0x40, 0xee, 0x90, 0x03, 0x10, 0x20, 0x0f, 0xc0, 0x80, 0x75, 0xff, 0x33, 0xe5, 0x83, - 0xa2, 0x5a, 0x63, 0xcf, 0xae, 0xa7, 0x37, 0xb1, 0x03, 0x6c, 0xac, 0x0f, 0x77, 0x6b, 0x5a, 0xd5, 0x7c, 0x15, 0x49, 0xb5, 0x0c, 0xfc, 0xc2, 0x20, 0x9f, 0xff, - 0xae, 0xd9, 0xd7, 0x28, 0x00, 0xe0, 0xb1, 0x9e, 0x04, 0x40, 0x9a, 0x92, 0x76, 0xac, 0x27, 0xf3, 0x78, 0x21, 0xbd, 0x00, 0x01, 0xa0, 0x04, 0x98, 0xd0, 0x46, - 0x26, 0x00, 0x04, 0x49, 0xe8, 0x9e, 0x36, 0xc0, 0x95, 0x80, 0x2e, 0x51, 0x64, 0xdf, 0xee, 0x15, 0xa4, 0x92, 0x83, 0x58, 0x2a, 0x29, 0x4b, 0xd8, 0x00, 0x9d, - 0x17, 0xf6, 0x02, 0xc9, 0x56, 0x68, 0xe6, 0x6d, 0x4b, 0xbf, 0xa2, 0x67, 0x4c, 0x4d, 0x35, 0xec, 0xb5, 0x89, 0x41, 0x24, 0x9e, 0x01, 0x94, 0xd0, 0xd4, 0xb6, - 0x34, 0x35, 0x7b, 0x81, 0x78, 0x90, 0xe5, 0xf6, 0x08, 0x28, 0x40, 0x13, 0xcc, 0x13, 0x50, 0x08, 0x03, 0x20, 0xee, 0x51, 0xee, 0x06, 0x48, 0xfb, 0x8e, 0x61, - 0x64, 0x02, 0x9a, 0x4a, 0x1c, 0x00, 0xe1, 0xf2, 0xb8, 0xb8, 0xbb, 0x1b, 0x80, 0x48, 0xad, 0xb6, 0x75, 0x59, 0xcf, 0x04, 0xda, 0x4b, 0x00, 0x12, 0x03, 0x30, - 0x77, 0x37, 0x33, 0x21, 0x01, 0xd2, 0xae, 0xc0, 0x75, 0xd4, 0x2e, 0x40, 0xb0, 0x00, 0x40, 0x44, 0xc4, 0x45, 0xa0, 0x4c, 0x40, 0x99, 0x17, 0x60, 0x02, 0x37, - 0x5e, 0xd2, 0x15, 0x5f, 0x98, 0x99, 0xd9, 0x13, 0xc0, 0xa2, 0x86, 0xb4, 0xdf, 0xed, 0x22, 0x8d, 0x88, 0x00, 0x10, 0x5a, 0xff, 0xe1, 0xc7, 0xe4, 0x83, 0xe1, - 0x8b, 0xc6, 0xd0, 0x5c, 0xde, 0x48, 0x94, 0x07, 0x72, 0x5f, 0xf3, 0xa1, 0xf9, 0xdb, 0xe7, 0x93, 0x17, 0xc1, 0xa6, 0x80, 0x93, 0xa4, 0x5f, 0x9c, 0x92, 0xe5, - 0x13, 0xbc, 0x71, 0x2f, 0x0a, 0x00, 0x02, 0x08, 0x02, 0xac, 0xcd, 0x5a, 0x09, 0xba, 0xb3, 0xec, 0x12, 0x45, 0x77, 0x27, 0x81, 0x26, 0x28, 0x40, 0xeb, 0x3c, - 0x19, 0x40, 0x3f, 0xb7, 0x2d, 0x4a, 0xe8, 0x1e, 0xa4, 0x0d, 0x40, 0x3a, 0x4f, 0x6c, 0xab, 0xd4, 0xcf, 0x01, 0x68, 0xb9, 0x47, 0x42, 0xcb, 0x9d, 0x15, 0x39, - 0x80, 0xc9, 0x93, 0xa1, 0xf9, 0x7e, 0x2e, 0x15, 0x51, 0x15, 0xa6, 0xe5, 0x41, 0x8f, 0x44, 0x42, 0xb3, 0x01, 0x4a, 0x68, 0x0e, 0xcd, 0xf7, 0x73, 0x9a, 0x6a, - 0xa6, 0x30, 0xd2, 0x59, 0xae, 0xd5, 0x00, 0xd9, 0x79, 0x32, 0x34, 0xd7, 0x72, 0x96, 0x47, 0x42, 0x52, 0x4d, 0x52, 0x4d, 0x4b, 0x09, 0x8c, 0x4a, 0x57, 0x9e, - 0xc0, 0xdc, 0x1d, 0x80, 0x66, 0xd0, 0xa1, 0x09, 0x28, 0x48, 0x24, 0x84, 0x2c, 0xf7, 0x65, 0x34, 0x09, 0x21, 0x13, 0x4e, 0x53, 0x29, 0xb1, 0x9e, 0x97, 0x39, - 0x01, 0x48, 0x01, 0x61, 0x00, 0xe9, 0xee, 0xed, 0x56, 0x8d, 0x4a, 0x90, 0x10, 0xa7, 0x81, 0x66, 0x6b, 0x6e, 0xe2, 0xb4, 0x0e, 0x6d, 0x01, 0x50, 0xba, 0xaf, - 0xc0, 0x95, 0x66, 0x20, 0x08, 0x67, 0x39, 0x28, 0xc7, 0x3c, 0xfd, 0x19, 0x35, 0x4c, 0x4d, 0xb2, 0xa9, 0x01, 0x53, 0x24, 0xd4, 0x24, 0x05, 0x24, 0xf9, 0xc0, - 0xbf, 0x83, 0x5c, 0x64, 0xcf, 0xdd, 0xcf, 0x8c, 0xb9, 0xe6, 0xbf, 0xca, 0xf7, 0xb9, 0xbe, 0xdc, 0x1f, 0xd6, 0x75, 0xa9, 0xa6, 0x49, 0x4d, 0x5e, 0x57, 0x00, - 0x40, 0x57, 0xc2, 0x29, 0xa1, 0x47, 0xed, 0xc6, 0x94, 0x9d, 0x7d, 0x5d, 0xc5, 0xcd, 0xde, 0xab, 0xb6, 0xd8, 0xa9, 0xfd, 0x86, 0x5d, 0x11, 0x01, 0x40, 0xcd, - 0xed, 0xf4, 0xce, 0x2a, 0xba, 0xec, 0x6a, 0xd7, 0x45, 0x71, 0xcc, 0x4a, 0x00, 0x28, 0x0a, 0x80, 0x0c, 0x93, 0x52, 0x6c, 0x96, 0xae, 0xc2, 0xa5, 0x00, 0xa2, - 0x25, 0x6d, 0x0d, 0x82, 0x06, 0x68, 0x16, 0x10, 0x9a, 0x9a, 0x88, 0x82, 0xa6, 0x76, 0xfa, 0xa5, 0x2e, 0x09, 0x87, 0x4a, 0xc5, 0x4a, 0x80, 0x99, 0x9a, 0xba, - 0x12, 0x91, 0xa4, 0x76, 0x8c, 0xba, 0x09, 0xc5, 0xa9, 0x92, 0x06, 0x03, 0xcf, 0x01, 0xd9, 0x12, 0x98, 0x38, 0x55, 0x6a, 0x01, 0x4f, 0x55, 0xa2, 0x32, 0xb5, - 0x99, 0xd5, 0x2a, 0x69, 0x26, 0xd0, 0x02, 0xde, 0x19, 0x2d, 0x4c, 0xb0, 0x7b, 0x76, 0x8e, 0x77, 0x3a, 0x6f, 0xb4, 0xf2, 0x0d, 0xe9, 0xc6, 0xad, 0xb9, 0xda, - 0xf4, 0x14, 0x9c, 0xbe, 0x67, 0xc6, 0x73, 0x4e, 0x29, 0x93, 0xcc, 0x01, 0xe4, 0x05, 0xe0, 0xdb, 0x2d, 0xc2, 0xa6, 0xc6, 0x29, 0x61, 0xab, 0x24, 0x91, 0x3f, - 0x22, 0x5f, 0xef, 0x08, 0x94, 0x4c, 0x6a, 0x02, 0xd4, 0xa4, 0xe6, 0x43, 0xe9, 0xbe, 0x4d, 0xef, 0x7f, 0x3a, 0x0e, 0x39, 0xba, 0xb3, 0xf7, 0xb1, 0x8b, 0x2d, - 0xfd, 0xd4, 0xa2, 0x1e, 0x15, 0x5b, 0xf7, 0xf4, 0x01, 0x58, 0xff, 0xb0, 0xe6, 0x52, 0x5c, 0x3d, 0xe2, 0xec, 0x19, 0xd0, 0xea, 0x38, 0x09, 0x6b, 0x3d, 0x94, - 0x58, 0x8b, 0x62, 0xf7, 0x83, 0x69, 0x03, 0x4c, 0xb0, 0x37, 0x0c, 0x10, 0xa6, 0x5a, 0x2f, 0xf4, 0xae, 0x64, 0x50, 0xb0, 0xb0, 0x38, 0x88, 0x7d, 0x33, 0xb5, - 0x27, 0x3c, 0xb5, 0x2b, 0x9f, 0x04, 0xe9, 0x6d, 0xad, 0xda, 0x74, 0x9c, 0x01, 0x24, 0x9c, 0x4e, 0x27, 0x84, 0x4e, 0x76, 0x4a, 0x1b, 0xbb, 0x75, 0x69, 0xd7, - 0xd9, 0xde, 0xb5, 0xf5, 0x0e, 0x46, 0x89, 0x01, 0x28, 0x49, 0x46, 0x02, 0x10, 0xea, 0x08, 0xb0, 0x8c, 0xe5, 0x19, 0x4d, 0x9d, 0xbd, 0x59, 0x1b, 0x0c, 0x05, - 0xd9, 0xfc, 0x0e, 0xe6, 0x08, 0xd0, 0x1d, 0x87, 0x01, 0x00, 0x70, 0x77, 0x77, 0x87, 0x82, 0xac, 0x55, 0x41, 0x29, 0x23, 0xe0, 0x08, 0xc0, 0x0e, 0x87, 0x01, - 0x02, 0x81, 0x92, 0x5e, 0xab, 0xc4, 0xb6, 0x1f, 0x1e, 0x0a, 0xc4, 0xb2, 0xe1, 0x04, 0xa4, 0x7a, 0x0d, 0xab, 0x97, 0x26, 0x79, 0xf1, 0x9d, 0xd7, 0x26, 0x76, - 0x01, 0xba, 0x26, 0x74, 0xe0, 0xcb, 0x05, 0x86, 0x38, 0x13, 0xe4, 0x00, 0x2c, 0x1b, 0x00, 0x19, 0x80, 0xb8, 0xd9, 0x63, 0xc9, 0x9c, 0x48, 0x7f, 0x15, 0xdd, - 0xf1, 0x3e, 0xbd, 0x24, 0x5f, 0x04, 0x0c, 0x68, 0x95, 0xd3, 0xb1, 0xc0, 0xba, 0xbe, 0x82, 0xf5, 0x03, 0xc0, 0x2a, 0xa7, 0xcc, 0x8f, 0x00, 0x57, 0x5d, 0x99, - 0x52, 0xf1, 0x1a, 0x40, 0xb9, 0xdb, 0x74, 0xfe, 0x04, 0x70, 0xd4, 0xc6, 0xb2, 0x01, 0x74, 0x33, 0x69, 0x00, 0xd7, 0xde, 0x6f, 0xae, 0xdb, 0x06, 0xd9, 0x1f, - 0x4d, 0x9d, 0x9b, 0x3f, 0x03, 0x6c, 0x22, 0xd4, 0x00, 0xea, 0xc7, 0x80, 0x63, 0x38, 0x73, 0x01, 0xca, 0x2e, 0x95, 0xdc, 0x59, 0xee, 0x57, 0x3e, 0x1c, 0x05, - 0x79, 0xdc, 0xba, 0x32, 0xf5, 0xb9, 0xd1, 0xba, 0xea, 0xed, 0xe9, 0xd6, 0x36, 0xfe, 0x63, 0xc0, 0xaa, 0x83, 0x6b, 0xfd, 0x0b, 0x80, 0xfe, 0xd4, 0xc0, 0xec, - 0x0a, 0xc4, 0x6d, 0xed, 0x10, 0x1e, 0x36, 0x3b, 0xa7, 0x4a, 0xaf, 0x91, 0xf5, 0xb1, 0x0b, 0xdd, 0x18, 0xfe, 0x66, 0xd8, 0xfb, 0x57, 0x3f, 0x07, 0x8c, 0x05, - 0x1f, 0x02, 0x82, 0x13, 0xe2, 0xaf, 0x02, 0xe0, 0x1b, 0xf0, 0x7b, 0x00, 0xd6, 0xde, 0xef, 0x65, 0x80, 0xae, 0xae, 0xfd, 0x32, 0x80, 0xa9, 0x7c, 0xd8, 0x7e, - 0x7c, 0x08, 0xe8, 0xcf, 0xbf, 0x97, 0x01, 0xfd, 0xbd, 0x78, 0x9e, 0x07, 0xfc, 0x7b, 0x00, 0x3e, 0x19, 0xff, 0x31, 0xe0, 0xf3, 0x8d, 0xfe, 0xc5, 0x38, 0xdc, - 0x8f, 0xf4, 0x6d, 0x2e, 0xdd, 0x66, 0xeb, 0xef, 0x99, 0xd3, 0x73, 0x36, 0xf6, 0x32, 0x60, 0xce, 0x93, 0x5e, 0x07, 0xac, 0xd3, 0x9f, 0x97, 0xfb, 0xc3, 0x9c, - 0x6b, 0xdc, 0x00, 0xf4, 0x97, 0xe2, 0x0d, 0x40, 0x9f, 0x59, 0xde, 0x01, 0x88, 0xe1, 0x5d, 0x37, 0xfd, 0x29, 0xe0, 0x7b, 0x7c, 0x8f, 0xaf, 0x19, 0x77, 0x3f, - 0xb6, 0xf6, 0x3f, 0x15, 0x5e, 0x1c, 0xca, 0x9b, 0x04, 0x27, 0x70, 0xeb, 0xc0, 0x63, 0x8e, 0x1d, 0x3e, 0x0f, 0xb0, 0x56, 0xfe, 0x99, 0x77, 0x00, 0x7f, 0xdc, - 0x05, 0xfc, 0xf5, 0xe9, 0x12, 0x6e, 0x01, 0x3e, 0xdf, 0xad, 0xb7, 0x23, 0x7d, 0x9f, 0x4b, 0xb7, 0xd9, 0x7a, 0x3f, 0x1f, 0xbe, 0xc7, 0xff, 0x75, 0xfc, 0x0d, - 0x3b, 0xd4, 0xd5, 0x4b, 0x3b, 0xfe, 0xb6, 0x75, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82}; -const inline size_t TEXTURE_ATLAS_LENGTH = 1242; - -const inline uint8_t FONT_REGULAR_DATA[] = { - 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x05, 0xd0, 0x02, 0xf1, 0x00, 0x00, 0x4f, 0xd8, 0x00, 0x00, - 0x00, 0x56, 0x47, 0x50, 0x4f, 0x53, 0x28, 0x98, 0x0a, 0xef, 0x00, 0x00, 0x50, 0x30, 0x00, 0x00, 0x07, 0xb2, 0x47, 0x53, 0x55, 0x42, 0x39, 0x7a, 0x34, 0x30, - 0x00, 0x00, 0x57, 0xe4, 0x00, 0x00, 0x01, 0x50, 0x4f, 0x53, 0x2f, 0x32, 0x69, 0x4f, 0x5e, 0x78, 0x00, 0x00, 0x3c, 0xe0, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, - 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, 0x20, 0x3e, 0x0e, 0x1b, 0x37, 0x00, 0x00, 0x4c, 0x88, - 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, 0x0b, 0x83, 0x00, 0x00, 0x3d, 0x74, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x4f, 0xd0, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0xaf, 0xdf, 0xf8, 0x38, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x38, 0x4e, - 0x68, 0x65, 0x61, 0x64, 0x28, 0x83, 0xdb, 0xfe, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00, 0x00, 0x36, 0x68, 0x68, 0x65, 0x61, 0x0c, 0xb3, 0x0b, 0xe0, 0x00, 0x00, - 0x3c, 0xbc, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0xe7, 0xb3, 0x14, 0xa5, 0x00, 0x00, 0x3a, 0xd0, 0x00, 0x00, 0x01, 0xea, 0x6c, 0x6f, 0x63, 0x61, - 0x0d, 0xd0, 0xff, 0xd0, 0x00, 0x00, 0x39, 0x8c, 0x00, 0x00, 0x01, 0x0a, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x55, 0x10, 0x75, 0x00, 0x00, 0x39, 0x6c, 0x00, 0x00, - 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2a, 0x6f, 0x43, 0x21, 0x00, 0x00, 0x4d, 0xb4, 0x00, 0x00, 0x01, 0xfc, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x9f, 0x00, 0x32, - 0x00, 0x00, 0x4f, 0xb0, 0x00, 0x00, 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0x44, 0x7e, 0xc6, 0xb9, 0x00, 0x00, 0x4b, 0x80, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, - 0x00, 0x48, 0xff, 0xf2, 0x00, 0xc4, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, - 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x24, 0x23, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x37, 0x23, 0x03, 0x33, 0x03, 0x34, 0x36, - 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0xa3, 0x39, 0x19, 0x6b, 0x74, 0x24, 0x1a, 0x19, 0x25, 0x25, 0x19, 0x1a, 0x24, 0xc9, 0x02, 0x01, 0xfd, - 0x6c, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x02, 0x00, 0x41, 0x01, 0xc8, 0x01, 0x57, 0x02, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x40, 0x21, - 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x05, 0x03, 0x04, 0x03, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, - 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0x21, 0x03, 0x23, 0x03, 0xa0, 0x14, 0x37, 0x14, 0x01, 0x16, 0x14, 0x37, 0x14, 0x02, - 0xca, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x00, 0x19, 0x00, 0x00, 0x02, 0x6c, 0x02, 0xca, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, - 0x40, 0x44, 0x0c, 0x0a, 0x02, 0x08, 0x0f, 0x10, 0x0d, 0x03, 0x07, 0x00, 0x08, 0x07, 0x68, 0x0e, 0x06, 0x02, 0x00, 0x05, 0x03, 0x02, 0x01, 0x02, 0x00, 0x01, - 0x67, 0x0b, 0x01, 0x09, 0x09, 0x6a, 0x4d, 0x04, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, 0x1c, 0x00, 0x1b, 0x00, 0x1b, 0x1a, 0x19, - 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0d, 0x1f, 0x2b, 0x01, 0x07, 0x33, 0x15, 0x23, 0x07, 0x23, - 0x37, 0x23, 0x07, 0x23, 0x37, 0x23, 0x35, 0x33, 0x37, 0x23, 0x35, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, 0x15, 0x05, 0x33, 0x37, 0x23, 0x01, - 0xe0, 0x1f, 0x89, 0x96, 0x29, 0x47, 0x29, 0x8f, 0x27, 0x46, 0x26, 0x7e, 0x8b, 0x20, 0x86, 0x92, 0x28, 0x48, 0x28, 0x90, 0x28, 0x45, 0x28, 0x7f, 0xfe, 0x7f, - 0x8f, 0x1f, 0x8f, 0x01, 0xb4, 0xa0, 0x43, 0xd1, 0xd1, 0xd1, 0xd1, 0x43, 0xa0, 0x42, 0xd4, 0xd4, 0xd4, 0xd4, 0x42, 0xa0, 0xa0, 0x00, 0x00, 0x03, 0x00, 0x3e, - 0xff, 0xc6, 0x02, 0x04, 0x02, 0xf7, 0x00, 0x22, 0x00, 0x29, 0x00, 0x30, 0x00, 0x69, 0x40, 0x14, 0x30, 0x2a, 0x29, 0x23, 0x19, 0x18, 0x15, 0x14, 0x08, 0x04, - 0x0a, 0x01, 0x02, 0x20, 0x03, 0x02, 0x00, 0x01, 0x02, 0x4c, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x1c, 0x04, 0x01, 0x02, 0x03, 0x01, 0x03, 0x02, 0x01, 0x80, - 0x00, 0x05, 0x00, 0x05, 0x86, 0x00, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x6a, 0x00, 0x03, 0x03, 0x6c, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x03, 0x02, 0x03, - 0x85, 0x04, 0x01, 0x02, 0x01, 0x02, 0x85, 0x00, 0x05, 0x00, 0x05, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x62, 0x00, 0x00, 0x01, - 0x00, 0x52, 0x59, 0x40, 0x09, 0x1f, 0x11, 0x11, 0x16, 0x15, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x37, 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x35, 0x26, 0x26, - 0x35, 0x34, 0x36, 0x37, 0x35, 0x33, 0x15, 0x16, 0x16, 0x17, 0x07, 0x26, 0x26, 0x27, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x15, 0x23, 0x11, 0x06, 0x06, - 0x15, 0x14, 0x16, 0x17, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0xfd, 0x37, 0x68, 0x20, 0x22, 0x6a, 0x33, 0x63, 0x5c, 0x67, 0x58, 0x40, 0x35, 0x57, 0x24, - 0x1b, 0x20, 0x4d, 0x28, 0x42, 0x58, 0x2d, 0x68, 0x5f, 0x40, 0x36, 0x33, 0x2d, 0x3c, 0x40, 0x3b, 0x36, 0x30, 0x41, 0x31, 0x01, 0x11, 0x0f, 0x55, 0x10, 0x18, - 0x01, 0xca, 0x1b, 0x52, 0x47, 0x4a, 0x54, 0x05, 0x58, 0x57, 0x01, 0x15, 0x0f, 0x4a, 0x0d, 0x13, 0x03, 0xc9, 0x13, 0x2b, 0x3f, 0x32, 0x46, 0x57, 0x0a, 0x6f, - 0x02, 0x8c, 0x04, 0x2a, 0x21, 0x28, 0x2b, 0x0f, 0xfe, 0xe2, 0x06, 0x2b, 0x22, 0x26, 0x27, 0x10, 0x00, 0x05, 0x00, 0x31, 0xff, 0xf6, 0x03, 0x0e, 0x02, 0xd4, - 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x25, 0x00, 0x2f, 0x00, 0x99, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x2c, 0x0d, 0x01, 0x06, 0x0e, 0x01, 0x08, 0x05, - 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, 0x0b, 0x03, 0x0a, 0x03, 0x00, 0x00, 0x70, 0x4d, 0x00, - 0x09, 0x09, 0x02, 0x61, 0x07, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x34, 0x0d, 0x01, 0x06, 0x0e, 0x01, 0x08, 0x05, 0x06, 0x08, 0x6a, 0x00, 0x05, - 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0b, 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, 0x0a, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x02, - 0x02, 0x6b, 0x4d, 0x00, 0x09, 0x09, 0x07, 0x61, 0x00, 0x07, 0x07, 0x71, 0x07, 0x4e, 0x59, 0x40, 0x2b, 0x27, 0x26, 0x1b, 0x1a, 0x11, 0x10, 0x0c, 0x0c, 0x01, - 0x00, 0x2d, 0x2b, 0x26, 0x2f, 0x27, 0x2f, 0x21, 0x1f, 0x1a, 0x25, 0x1b, 0x25, 0x17, 0x15, 0x10, 0x19, 0x11, 0x19, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, - 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x05, 0x01, 0x23, 0x01, 0x05, - 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x35, 0x34, 0x05, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, - 0x16, 0x33, 0x32, 0x35, 0x34, 0xc3, 0x4a, 0x4c, 0x49, 0x4d, 0x47, 0x4b, 0x46, 0x02, 0x15, 0xfe, 0x74, 0x4d, 0x01, 0x8c, 0xfe, 0x84, 0x26, 0x23, 0x23, 0x26, - 0x4d, 0x01, 0x68, 0x49, 0x4d, 0x49, 0x4d, 0x47, 0x4b, 0x46, 0x4c, 0x26, 0x23, 0x23, 0x26, 0x4d, 0x02, 0xd4, 0x75, 0x6a, 0x6a, 0x77, 0x77, 0x6a, 0x6a, 0x75, - 0x0a, 0xfd, 0x36, 0x02, 0xca, 0x34, 0x51, 0x50, 0x50, 0x52, 0xa2, 0xa1, 0xe0, 0x75, 0x6a, 0x6a, 0x77, 0x77, 0x6a, 0x6a, 0x75, 0x3f, 0x50, 0x50, 0x51, 0x51, - 0xa2, 0xa0, 0x00, 0x03, 0x00, 0x35, 0xff, 0xf6, 0x02, 0xda, 0x02, 0xd5, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x35, 0x00, 0x7a, 0x40, 0x0f, 0x26, 0x1a, 0x06, 0x03, - 0x01, 0x04, 0x35, 0x11, 0x0e, 0x07, 0x04, 0x05, 0x01, 0x02, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x23, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, - 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, - 0x4e, 0x1b, 0x40, 0x21, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6b, 0x4d, - 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x59, 0x40, 0x17, 0x21, 0x20, 0x01, 0x00, 0x33, 0x31, 0x20, 0x2b, 0x21, 0x2b, 0x15, 0x13, - 0x10, 0x0f, 0x0b, 0x0a, 0x00, 0x1f, 0x01, 0x1f, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, - 0x07, 0x17, 0x23, 0x27, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x36, - 0x36, 0x35, 0x34, 0x26, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x01, 0x30, 0x50, 0x5d, 0x51, 0x3e, 0xc1, 0x1a, 0x21, 0x0b, 0x59, 0x10, - 0x30, 0x26, 0x92, 0x77, 0x57, 0x2f, 0x74, 0x53, 0x67, 0x7a, 0x53, 0x47, 0x20, 0x37, 0x63, 0x52, 0x2a, 0x35, 0x26, 0x24, 0x3b, 0x33, 0x30, 0x52, 0x36, 0x3d, - 0x4a, 0x3e, 0x40, 0x5c, 0x1f, 0x02, 0xd5, 0x51, 0x49, 0x3f, 0x58, 0x24, 0xba, 0x1f, 0x51, 0x2f, 0x40, 0x6e, 0x29, 0x8e, 0x54, 0x2a, 0x34, 0x66, 0x5e, 0x4d, - 0x5d, 0x28, 0x24, 0x52, 0x37, 0x4a, 0x52, 0x48, 0x2c, 0x27, 0x24, 0x3d, 0x25, 0x22, 0x3d, 0x28, 0x24, 0x2e, 0xfe, 0xc8, 0x20, 0x42, 0x36, 0x37, 0x42, 0x2a, - 0x1d, 0x00, 0x00, 0x01, 0x00, 0x41, 0x01, 0xc8, 0x00, 0xa0, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, - 0x01, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0xa0, 0x14, 0x37, 0x14, 0x02, 0xca, 0xfe, - 0xfe, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, 0x62, 0x01, 0x0e, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, 0x00, 0x01, 0x00, 0x01, 0x86, 0x00, - 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x16, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x13, 0x34, 0x36, 0x37, 0x33, 0x06, 0x06, 0x15, 0x14, 0x16, 0x17, 0x23, 0x26, 0x26, 0x28, - 0x47, 0x4c, 0x53, 0x46, 0x47, 0x47, 0x45, 0x52, 0x4c, 0x47, 0x01, 0x12, 0x7a, 0xe3, 0x5b, 0x5e, 0xe2, 0x77, 0x74, 0xdf, 0x5e, 0x58, 0xdf, 0x00, 0x00, 0x01, - 0x00, 0x1e, 0xff, 0x62, 0x01, 0x04, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x01, 0x00, 0x86, 0x00, 0x01, 0x01, 0x6a, 0x01, 0x4e, 0x16, - 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x23, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x01, 0x04, 0x47, 0x4c, 0x52, 0x45, 0x47, - 0x47, 0x46, 0x53, 0x4c, 0x47, 0x01, 0x12, 0x79, 0xdf, 0x58, 0x5e, 0xdf, 0x74, 0x77, 0xe2, 0x5e, 0x5b, 0xe3, 0x00, 0x01, 0x00, 0x29, 0x01, 0x36, 0x01, 0xfc, - 0x02, 0xf8, 0x00, 0x0e, 0x00, 0x33, 0x40, 0x10, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x0d, 0x00, 0x49, 0x4b, 0xb0, - 0x29, 0x50, 0x58, 0xb6, 0x01, 0x01, 0x00, 0x00, 0x6c, 0x00, 0x4e, 0x1b, 0xb4, 0x01, 0x01, 0x00, 0x00, 0x76, 0x59, 0x40, 0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, - 0x0e, 0x02, 0x0d, 0x16, 0x2b, 0x01, 0x07, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x27, 0x01, 0x42, 0x14, 0xc0, 0x0e, 0xb8, - 0x77, 0x56, 0x55, 0x4d, 0x59, 0x75, 0xb6, 0x0e, 0xbe, 0x15, 0x02, 0xf8, 0xc0, 0x36, 0x5c, 0x0f, 0x9e, 0x2f, 0xaf, 0xaf, 0x2f, 0x9e, 0x0f, 0x5c, 0x36, 0xc0, - 0x00, 0x01, 0x00, 0x32, 0x00, 0x6f, 0x02, 0x08, 0x02, 0x53, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x00, 0x05, 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, - 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, 0x05, 0x02, 0x5f, 0x00, 0x02, 0x05, 0x02, 0x4f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, - 0x01, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, 0x01, 0x41, 0xc7, 0xc7, 0x48, 0xc7, 0xc7, 0x48, 0x01, 0x84, 0x47, 0xce, 0xce, 0x47, - 0xcf, 0x00, 0x00, 0x01, 0x00, 0x29, 0xff, 0x7f, 0x00, 0xc0, 0x00, 0x74, 0x00, 0x08, 0x00, 0x18, 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, - 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x13, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x37, 0x06, 0x06, 0x07, 0x23, 0x36, 0x36, 0x37, 0x33, 0xc0, 0x0d, 0x31, - 0x18, 0x41, 0x0e, 0x1d, 0x07, 0x5e, 0x69, 0x35, 0x7f, 0x36, 0x39, 0x88, 0x34, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0xe5, 0x01, 0x1a, 0x01, 0x33, 0x00, 0x03, - 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, 0x35, 0x33, 0x15, 0x28, 0xf2, 0xe5, 0x4e, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x48, 0xff, 0xf2, 0x00, 0xc4, 0x00, 0x79, - 0x00, 0x0b, 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x22, 0x02, 0x0d, 0x18, 0x2b, 0x37, 0x34, 0x36, - 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x48, 0x24, 0x19, 0x1a, 0x25, 0x25, 0x1a, 0x19, 0x24, 0x36, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, - 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x6a, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, - 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x01, 0x01, 0x23, 0x01, 0x01, 0x6a, 0xfe, 0xf6, 0x56, 0x01, 0x0a, 0x02, 0xca, - 0xfd, 0x36, 0x02, 0xca, 0x00, 0x02, 0x00, 0x31, 0xff, 0xf6, 0x02, 0x0b, 0x02, 0xd5, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, - 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x24, 0x25, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, - 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, - 0x0b, 0x30, 0x68, 0x56, 0x79, 0x73, 0x2f, 0x68, 0x55, 0x78, 0x76, 0xfe, 0x7e, 0x43, 0x51, 0x50, 0x45, 0x45, 0x50, 0x51, 0x43, 0x01, 0x66, 0x73, 0xa5, 0x58, - 0xc3, 0xad, 0x74, 0xa4, 0x57, 0xc1, 0xae, 0x93, 0x92, 0x91, 0x94, 0x92, 0x92, 0x92, 0x00, 0x01, 0x00, 0x59, 0x00, 0x00, 0x01, 0x63, 0x02, 0xca, 0x00, 0x0c, - 0x00, 0x1b, 0x40, 0x18, 0x0a, 0x09, 0x05, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1a, 0x10, 0x02, - 0x0d, 0x18, 0x2b, 0x21, 0x23, 0x11, 0x34, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, 0x01, 0x63, 0x56, 0x02, 0x02, 0x10, 0x1a, 0x14, 0x4c, 0x2e, - 0xc1, 0x49, 0x01, 0xf3, 0x2b, 0x34, 0x1c, 0x10, 0x16, 0x11, 0x3e, 0x3b, 0x96, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x00, 0x02, 0x08, 0x02, 0xd4, 0x00, 0x1b, - 0x00, 0x2a, 0x40, 0x27, 0x0e, 0x0d, 0x02, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, - 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x27, 0x25, 0x28, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x3e, 0x02, 0x35, 0x34, - 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x15, 0x21, 0x02, 0x08, 0xfe, 0x28, 0xbb, 0x36, 0x4a, - 0x26, 0x46, 0x38, 0x34, 0x4f, 0x29, 0x2f, 0x2a, 0x6d, 0x44, 0x64, 0x74, 0x2e, 0x52, 0x37, 0x95, 0x01, 0x69, 0x49, 0xbd, 0x36, 0x54, 0x51, 0x30, 0x3b, 0x3d, - 0x24, 0x20, 0x3b, 0x23, 0x31, 0x65, 0x59, 0x38, 0x62, 0x5f, 0x36, 0x93, 0x04, 0x00, 0x00, 0x01, 0x00, 0x2d, 0xff, 0xf6, 0x02, 0x03, 0x02, 0xd4, 0x00, 0x2a, - 0x00, 0x40, 0x40, 0x3d, 0x24, 0x01, 0x03, 0x04, 0x03, 0x01, 0x02, 0x03, 0x0f, 0x01, 0x01, 0x02, 0x0e, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x25, 0x01, 0x04, 0x01, - 0x4b, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, - 0x00, 0x71, 0x00, 0x4e, 0x25, 0x24, 0x21, 0x24, 0x25, 0x2a, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, - 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, - 0x36, 0x36, 0x33, 0x32, 0x16, 0x01, 0xed, 0x50, 0x44, 0x56, 0x54, 0x3a, 0x79, 0x5f, 0x38, 0x60, 0x2c, 0x2d, 0x68, 0x30, 0x60, 0x55, 0x69, 0x5f, 0x45, 0x46, - 0x58, 0x5b, 0x46, 0x3c, 0x3a, 0x52, 0x28, 0x2c, 0x26, 0x71, 0x48, 0x70, 0x6d, 0x02, 0x23, 0x48, 0x55, 0x0e, 0x04, 0x0a, 0x58, 0x47, 0x3e, 0x61, 0x36, 0x11, - 0x16, 0x52, 0x16, 0x19, 0x4b, 0x42, 0x43, 0x3b, 0x4b, 0x4a, 0x3d, 0x34, 0x39, 0x22, 0x1a, 0x3c, 0x1e, 0x2c, 0x64, 0x00, 0x00, 0x02, 0x00, 0x15, 0x00, 0x00, - 0x02, 0x28, 0x02, 0xce, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x2b, 0x40, 0x28, 0x0e, 0x01, 0x04, 0x03, 0x06, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x05, 0x01, 0x04, 0x02, - 0x01, 0x00, 0x01, 0x04, 0x00, 0x68, 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x19, 0x11, 0x12, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, - 0x2b, 0x25, 0x23, 0x15, 0x23, 0x35, 0x21, 0x35, 0x01, 0x33, 0x11, 0x33, 0x27, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x07, 0x03, 0x21, 0x02, 0x28, 0x68, 0x55, - 0xfe, 0xaa, 0x01, 0x50, 0x5b, 0x68, 0xbd, 0x04, 0x01, 0x04, 0x08, 0x18, 0x0b, 0xd6, 0x01, 0x00, 0xa2, 0xa2, 0xa2, 0x4b, 0x01, 0xe1, 0xfe, 0x23, 0xe1, 0x34, - 0x49, 0x21, 0x13, 0x2c, 0x0f, 0xfe, 0xcf, 0x00, 0x00, 0x01, 0x00, 0x3f, 0xff, 0xf6, 0x02, 0x03, 0x02, 0xca, 0x00, 0x1e, 0x00, 0x44, 0x40, 0x41, 0x1c, 0x17, - 0x02, 0x03, 0x00, 0x16, 0x0a, 0x02, 0x02, 0x03, 0x09, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x03, 0x02, 0x00, 0x03, 0x69, 0x00, 0x05, 0x05, - 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x01, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x14, 0x12, - 0x0e, 0x0c, 0x07, 0x05, 0x00, 0x1e, 0x01, 0x1e, 0x07, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, - 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x15, 0x21, 0x07, 0x36, 0x36, 0x01, 0x13, 0x6e, 0x82, 0x8d, 0x7e, 0x37, 0x61, 0x21, - 0x24, 0x67, 0x2f, 0x4f, 0x61, 0x56, 0x5d, 0x1c, 0x48, 0x16, 0x2c, 0x1b, 0x01, 0x66, 0xfe, 0xe5, 0x11, 0x11, 0x3a, 0x01, 0xb6, 0x6e, 0x64, 0x6f, 0x7f, 0x14, - 0x13, 0x53, 0x16, 0x19, 0x4b, 0x4f, 0x46, 0x4b, 0x0a, 0x05, 0x1c, 0x01, 0x51, 0x50, 0xcf, 0x03, 0x08, 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x0d, - 0x02, 0xd4, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x3e, 0x40, 0x3b, 0x08, 0x01, 0x01, 0x00, 0x09, 0x01, 0x02, 0x01, 0x11, 0x01, 0x04, 0x05, 0x03, 0x4c, 0x00, 0x02, - 0x00, 0x05, 0x04, 0x02, 0x05, 0x69, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x70, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, - 0x03, 0x4e, 0x20, 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x24, 0x27, 0x25, 0x24, 0x07, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, - 0x15, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x26, 0x17, 0x32, 0x36, 0x35, 0x34, - 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x37, 0x1b, 0x47, 0x80, 0x65, 0x15, 0x33, 0x10, 0x12, 0x2d, 0x17, 0x45, 0x5c, 0x35, 0x18, 0x03, 0x06, - 0x17, 0x52, 0x40, 0x5d, 0x72, 0x7b, 0x68, 0x44, 0x6e, 0x41, 0xf2, 0x3f, 0x4e, 0x45, 0x45, 0x2f, 0x46, 0x27, 0x22, 0x44, 0x01, 0x31, 0x4d, 0x95, 0x79, 0x48, - 0x04, 0x05, 0x4b, 0x06, 0x06, 0x2e, 0x50, 0x68, 0x3b, 0x23, 0x31, 0x71, 0x68, 0x70, 0x80, 0x44, 0x8c, 0x86, 0x51, 0x55, 0x44, 0x50, 0x27, 0x3c, 0x20, 0x2b, - 0x55, 0x37, 0x00, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x02, 0x0b, 0x02, 0xca, 0x00, 0x06, 0x00, 0x25, 0x40, 0x22, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x00, - 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, - 0x2b, 0x33, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x88, 0x01, 0x25, 0xfe, 0x7f, 0x01, 0xdf, 0xfe, 0xde, 0x02, 0x7a, 0x50, 0x44, 0xfd, 0x7a, 0x00, 0x00, 0x03, - 0x00, 0x31, 0xff, 0xf6, 0x02, 0x0a, 0x02, 0xd4, 0x00, 0x1b, 0x00, 0x28, 0x00, 0x35, 0x00, 0x36, 0x40, 0x33, 0x33, 0x23, 0x15, 0x07, 0x04, 0x03, 0x02, 0x01, - 0x4c, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1d, 0x1c, - 0x01, 0x00, 0x2d, 0x2b, 0x1c, 0x28, 0x1d, 0x28, 0x0f, 0x0d, 0x00, 0x1b, 0x01, 0x1b, 0x06, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, - 0x1e, 0x02, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, - 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x27, 0x06, 0x06, 0x01, 0x1d, 0x5e, 0x78, 0x25, 0x3e, 0x25, - 0x2c, 0x48, 0x2b, 0x7f, 0x6b, 0x73, 0x7c, 0x29, 0x44, 0x27, 0x34, 0x49, 0x38, 0x60, 0x3c, 0x37, 0x47, 0x23, 0x3c, 0x24, 0x34, 0x47, 0x46, 0xcf, 0x4a, 0x4d, - 0x49, 0x4d, 0x52, 0x44, 0x10, 0x42, 0x45, 0x02, 0xd4, 0x58, 0x53, 0x2b, 0x40, 0x31, 0x13, 0x15, 0x35, 0x46, 0x31, 0x5a, 0x69, 0x65, 0x5b, 0x31, 0x48, 0x34, - 0x12, 0x1e, 0x55, 0x42, 0x37, 0x4b, 0x28, 0x47, 0x35, 0x32, 0x25, 0x32, 0x23, 0x10, 0x16, 0x3e, 0x36, 0x32, 0x35, 0xfe, 0x28, 0x34, 0x45, 0x45, 0x37, 0x34, - 0x45, 0x1a, 0x06, 0x1c, 0x49, 0x00, 0x00, 0x02, 0x00, 0x32, 0xff, 0xf6, 0x02, 0x08, 0x02, 0xd4, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x3e, 0x40, 0x3b, 0x10, 0x01, - 0x05, 0x04, 0x09, 0x01, 0x01, 0x02, 0x08, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, - 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x20, 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x25, 0x27, - 0x24, 0x24, 0x07, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, - 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x27, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x26, 0x02, 0x08, 0x1b, - 0x47, 0x81, 0x65, 0x14, 0x35, 0x11, 0x27, 0x31, 0x46, 0x5b, 0x36, 0x18, 0x02, 0x06, 0x16, 0x53, 0x41, 0x5c, 0x71, 0x39, 0x66, 0x45, 0x44, 0x6e, 0x40, 0xf2, - 0x3e, 0x4f, 0x43, 0x46, 0x30, 0x46, 0x27, 0x22, 0x44, 0x01, 0x99, 0x4d, 0x95, 0x79, 0x48, 0x05, 0x05, 0x4b, 0x0d, 0x2e, 0x4f, 0x69, 0x3a, 0x22, 0x31, 0x71, - 0x67, 0x4b, 0x6c, 0x3a, 0x45, 0x8b, 0x86, 0x52, 0x54, 0x45, 0x4f, 0x27, 0x3c, 0x20, 0x2b, 0x54, 0x38, 0x00, 0x00, 0x02, 0x00, 0x48, 0xff, 0xf2, 0x00, 0xc4, - 0x02, 0x26, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, - 0x03, 0x03, 0x71, 0x03, 0x4e, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x11, - 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x48, 0x24, 0x19, 0x1a, 0x25, 0x25, 0x1a, 0x19, 0x24, 0x24, 0x19, 0x1a, 0x25, 0x25, 0x1a, - 0x19, 0x24, 0x01, 0xe2, 0x26, 0x1e, 0x1e, 0x26, 0x24, 0x20, 0x20, 0xfe, 0x78, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x02, 0x00, 0x1f, 0xff, 0x7f, - 0x00, 0xc2, 0x02, 0x26, 0x00, 0x0b, 0x00, 0x15, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x02, 0x03, 0x02, 0x63, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, - 0x00, 0x73, 0x01, 0x4e, 0x14, 0x15, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x13, 0x06, - 0x06, 0x07, 0x23, 0x3e, 0x02, 0x37, 0x33, 0x46, 0x24, 0x19, 0x1a, 0x25, 0x25, 0x1a, 0x19, 0x24, 0x71, 0x0d, 0x31, 0x18, 0x42, 0x0a, 0x13, 0x11, 0x05, 0x5e, - 0x01, 0xe2, 0x26, 0x1e, 0x1e, 0x26, 0x24, 0x20, 0x20, 0xfe, 0xab, 0x34, 0x81, 0x35, 0x26, 0x57, 0x55, 0x23, 0x00, 0x01, 0x00, 0x32, 0x00, 0x74, 0x02, 0x09, - 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, 0x32, 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, 0x05, 0x02, 0x09, 0xfe, 0x29, 0x01, 0xd7, 0xfe, - 0x87, 0x01, 0x79, 0x74, 0xcf, 0x32, 0xeb, 0x4e, 0xb2, 0x9e, 0x00, 0x02, 0x00, 0x38, 0x00, 0xd9, 0x02, 0x02, 0x01, 0xe7, 0x00, 0x03, 0x00, 0x07, 0x00, 0x2f, - 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, - 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, - 0x35, 0x21, 0x15, 0x38, 0x01, 0xca, 0xfe, 0x36, 0x01, 0xca, 0x01, 0xa0, 0x47, 0x47, 0xc7, 0x47, 0x47, 0x00, 0x00, 0x01, 0x00, 0x32, 0x00, 0x74, 0x02, 0x09, - 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, 0x25, 0x25, 0x35, 0x05, 0x15, 0x05, 0x32, 0x01, 0x79, 0xfe, 0x87, 0x01, 0xd7, - 0xfe, 0x29, 0xc2, 0x9d, 0xb3, 0x4e, 0xeb, 0x32, 0xcf, 0x00, 0x00, 0x02, 0x00, 0x0c, 0xff, 0xf2, 0x01, 0x98, 0x02, 0xd4, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x32, - 0x40, 0x2f, 0x0f, 0x01, 0x00, 0x01, 0x0e, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, - 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x04, 0x4e, 0x24, 0x23, 0x1b, 0x25, 0x2a, 0x05, 0x0d, 0x1b, 0x2b, 0x37, 0x34, - 0x36, 0x36, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x0e, 0x02, 0x15, - 0x15, 0x23, 0x07, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x8c, 0x0f, 0x25, 0x20, 0x27, 0x2b, 0x12, 0x3e, 0x3b, 0x31, 0x4c, 0x23, - 0x1f, 0x28, 0x61, 0x3c, 0x5f, 0x68, 0x1d, 0x35, 0x24, 0x21, 0x23, 0x0c, 0x46, 0x17, 0x23, 0x1b, 0x19, 0x24, 0x24, 0x19, 0x1b, 0x23, 0xe4, 0x26, 0x37, 0x32, - 0x1b, 0x21, 0x2c, 0x2a, 0x1e, 0x30, 0x34, 0x19, 0x11, 0x46, 0x15, 0x1c, 0x5e, 0x51, 0x2d, 0x3f, 0x35, 0x1e, 0x1c, 0x2a, 0x29, 0x1d, 0x11, 0x93, 0x25, 0x1e, - 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x00, 0x02, 0x00, 0x3a, 0xff, 0xa7, 0x03, 0x49, 0x02, 0xca, 0x00, 0x3f, 0x00, 0x4d, 0x00, 0x7b, 0x40, 0x13, 0x16, 0x01, - 0x09, 0x02, 0x47, 0x08, 0x02, 0x03, 0x09, 0x2f, 0x01, 0x05, 0x00, 0x30, 0x01, 0x06, 0x05, 0x04, 0x4c, 0x4b, 0xb0, 0x1e, 0x50, 0x58, 0x40, 0x26, 0x08, 0x01, - 0x03, 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, 0x00, 0x07, 0x07, 0x6a, 0x4d, 0x00, - 0x09, 0x09, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x24, 0x00, 0x02, 0x00, 0x09, 0x03, 0x02, 0x09, 0x69, 0x08, 0x01, 0x03, 0x01, 0x01, - 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, 0x00, 0x07, 0x07, 0x6a, 0x04, 0x4e, 0x59, 0x40, 0x0e, - 0x4b, 0x49, 0x25, 0x27, 0x25, 0x25, 0x26, 0x28, 0x25, 0x25, 0x24, 0x0a, 0x0d, 0x1f, 0x2b, 0x01, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, - 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x06, 0x14, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x26, 0x23, - 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x16, 0x05, - 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x03, 0x49, 0x15, 0x2c, 0x40, 0x2c, 0x2e, 0x35, 0x06, 0x05, 0x12, 0x46, 0x35, - 0x4c, 0x53, 0x34, 0x5f, 0x41, 0x2c, 0x55, 0x18, 0x0a, 0x01, 0x25, 0x19, 0x1f, 0x2b, 0x17, 0x4b, 0x83, 0x53, 0x72, 0x9d, 0x51, 0x9c, 0x93, 0x3d, 0x6f, 0x2b, - 0x2b, 0x6b, 0x41, 0x76, 0xa8, 0x59, 0x3a, 0x6e, 0x9d, 0x63, 0x68, 0xa2, 0x5d, 0xfe, 0x07, 0x33, 0x2b, 0x38, 0x31, 0x04, 0x06, 0x0d, 0x28, 0x15, 0x31, 0x3c, - 0x1a, 0x01, 0x65, 0x2e, 0x58, 0x47, 0x2b, 0x35, 0x22, 0x25, 0x32, 0x66, 0x54, 0x42, 0x65, 0x3a, 0x0f, 0x09, 0xcb, 0x12, 0x0f, 0x03, 0x34, 0x22, 0x33, 0x55, - 0x33, 0x5d, 0x81, 0x44, 0x5e, 0xa5, 0x6a, 0x94, 0x9e, 0x1b, 0x10, 0x44, 0x12, 0x17, 0x58, 0xa5, 0x74, 0x5d, 0x9f, 0x75, 0x41, 0x56, 0xa0, 0xaf, 0x40, 0x3a, - 0x54, 0x43, 0x7d, 0x04, 0x06, 0x30, 0x4b, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7e, 0x02, 0xcd, 0x00, 0x07, 0x00, 0x11, 0x00, 0x2c, 0x40, 0x29, - 0x0c, 0x01, 0x04, 0x02, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x68, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, - 0x4e, 0x00, 0x00, 0x11, 0x10, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x21, 0x27, 0x21, 0x07, 0x23, 0x01, 0x33, 0x01, 0x01, 0x2e, - 0x02, 0x27, 0x06, 0x06, 0x07, 0x07, 0x33, 0x02, 0x21, 0x56, 0xfe, 0xe5, 0x55, 0x5b, 0x01, 0x17, 0x51, 0x01, 0x16, 0xfe, 0xe2, 0x03, 0x0e, 0x0d, 0x04, 0x07, - 0x12, 0x06, 0x51, 0xe2, 0xdd, 0xdd, 0x02, 0xcd, 0xfd, 0x33, 0x02, 0x05, 0x08, 0x2a, 0x2d, 0x0c, 0x1f, 0x3b, 0x11, 0xd8, 0x00, 0x03, 0x00, 0x61, 0x00, 0x00, - 0x02, 0x54, 0x02, 0xca, 0x00, 0x10, 0x00, 0x19, 0x00, 0x22, 0x00, 0x44, 0x40, 0x41, 0x06, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x08, 0x01, 0x05, - 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x04, 0x04, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, - 0x1a, 0x1a, 0x12, 0x11, 0x01, 0x00, 0x1a, 0x22, 0x1a, 0x21, 0x1d, 0x1b, 0x18, 0x16, 0x11, 0x19, 0x12, 0x19, 0x0f, 0x0d, 0x00, 0x10, 0x01, 0x10, 0x09, 0x0d, - 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x23, 0x23, 0x11, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, - 0x15, 0x15, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x2d, 0x86, 0x89, 0x46, 0x42, 0x2d, 0x49, 0x2a, 0x85, 0x73, 0xfb, 0xde, 0x5c, 0x44, 0x53, - 0x5b, 0x76, 0x90, 0x5f, 0x4a, 0x4d, 0x63, 0x02, 0xca, 0x4f, 0x62, 0x3f, 0x53, 0x0c, 0x05, 0x07, 0x26, 0x46, 0x38, 0x61, 0x6a, 0x02, 0xca, 0xfe, 0xd0, 0x3b, - 0x3a, 0x3b, 0x33, 0xe3, 0x4b, 0xfe, 0xfd, 0x4a, 0x3c, 0x38, 0x45, 0x00, 0x00, 0x01, 0x00, 0x3d, 0xff, 0xf6, 0x02, 0x59, 0x02, 0xd4, 0x00, 0x1a, 0x00, 0x37, - 0x40, 0x34, 0x17, 0x01, 0x00, 0x03, 0x18, 0x09, 0x02, 0x01, 0x00, 0x0a, 0x01, 0x02, 0x01, 0x03, 0x4c, 0x04, 0x01, 0x00, 0x00, 0x03, 0x61, 0x00, 0x03, 0x03, - 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x01, 0x00, 0x16, 0x14, 0x0e, 0x0c, 0x07, 0x05, 0x00, 0x1a, 0x01, 0x1a, 0x05, - 0x0d, 0x16, 0x2b, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, - 0x17, 0x07, 0x26, 0x26, 0x01, 0x93, 0x73, 0x84, 0x7b, 0x7b, 0x2f, 0x54, 0x28, 0x28, 0x55, 0x3b, 0x6d, 0x92, 0x49, 0x4f, 0x9a, 0x6e, 0x71, 0x54, 0x24, 0x21, - 0x51, 0x02, 0x85, 0x9a, 0x86, 0x85, 0x9b, 0x10, 0x0c, 0x4e, 0x0f, 0x0e, 0x5a, 0xa6, 0x70, 0x6c, 0xa5, 0x5d, 0x2a, 0x4c, 0x0f, 0x18, 0x00, 0x02, 0x00, 0x61, - 0x00, 0x00, 0x02, 0x9d, 0x02, 0xca, 0x00, 0x09, 0x00, 0x11, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x03, - 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x21, 0x25, 0x21, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x23, 0x23, 0x11, 0x33, 0x32, 0x16, - 0x16, 0x07, 0x34, 0x26, 0x23, 0x23, 0x11, 0x33, 0x20, 0x02, 0x9d, 0xc5, 0xb0, 0xc7, 0xdc, 0x6c, 0x9e, 0x56, 0x5f, 0x8d, 0x81, 0x75, 0x61, 0x01, 0x22, 0x01, - 0x6c, 0xb5, 0xb7, 0x02, 0xca, 0x50, 0x9b, 0x76, 0x8f, 0x85, 0xfd, 0xd0, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, 0xf0, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x29, - 0x40, 0x26, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x5f, 0x00, - 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x21, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, - 0x21, 0x01, 0xf0, 0xfe, 0x71, 0x01, 0x8f, 0xfe, 0xcb, 0x01, 0x23, 0xfe, 0xdd, 0x01, 0x35, 0x02, 0xca, 0x4f, 0xdf, 0x4e, 0xff, 0x00, 0x00, 0x01, 0x00, 0x61, - 0x00, 0x00, 0x01, 0xf0, 0x02, 0xca, 0x00, 0x09, 0x00, 0x23, 0x40, 0x20, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, - 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x10, 0x05, 0x0d, 0x1b, 0x2b, 0x33, 0x23, 0x11, 0x21, 0x15, 0x21, 0x15, - 0x21, 0x15, 0x21, 0xbb, 0x5a, 0x01, 0x8f, 0xfe, 0xcb, 0x01, 0x22, 0xfe, 0xde, 0x02, 0xca, 0x4f, 0xfd, 0x4f, 0x00, 0x01, 0x00, 0x3d, 0xff, 0xf6, 0x02, 0x8e, - 0x02, 0xd4, 0x00, 0x20, 0x00, 0x3b, 0x40, 0x38, 0x10, 0x01, 0x03, 0x02, 0x11, 0x01, 0x00, 0x03, 0x1e, 0x01, 0x04, 0x05, 0x02, 0x01, 0x01, 0x04, 0x04, 0x4c, - 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x67, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, - 0x71, 0x01, 0x4e, 0x13, 0x25, 0x25, 0x26, 0x23, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x11, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, - 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x35, 0x23, 0x01, 0x97, 0xf7, 0x3a, 0x76, 0x4b, - 0x6f, 0x98, 0x4f, 0x58, 0xa5, 0x75, 0x3c, 0x6b, 0x2e, 0x22, 0x26, 0x5f, 0x33, 0x80, 0x8f, 0x37, 0x76, 0x60, 0x2f, 0x42, 0x1b, 0x9d, 0x01, 0x79, 0xfe, 0xa2, - 0x13, 0x12, 0x59, 0xa5, 0x71, 0x70, 0xa4, 0x5b, 0x16, 0x14, 0x4e, 0x11, 0x18, 0x9a, 0x86, 0x55, 0x83, 0x49, 0x0a, 0x07, 0xd4, 0x00, 0x00, 0x01, 0x00, 0x61, - 0x00, 0x00, 0x02, 0x83, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x21, 0x40, 0x1e, 0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x01, 0x67, 0x05, 0x01, 0x03, 0x03, 0x6a, 0x4d, - 0x02, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, - 0x21, 0x11, 0x33, 0x02, 0x83, 0x5a, 0xfe, 0x92, 0x5a, 0x5a, 0x01, 0x6e, 0x5a, 0x01, 0x4d, 0xfe, 0xb3, 0x02, 0xca, 0xfe, 0xd2, 0x01, 0x2e, 0x00, 0x00, 0x01, - 0x00, 0x28, 0x00, 0x00, 0x01, 0x2a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x0a, 0x09, 0x08, 0x05, 0x04, 0x03, 0x02, 0x08, 0x00, 0x01, 0x01, - 0x4c, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x11, 0x27, 0x35, 0x21, - 0x15, 0x07, 0x11, 0x17, 0x01, 0x2a, 0xfe, 0xfe, 0x54, 0x54, 0x01, 0x02, 0x54, 0x54, 0x34, 0x13, 0x02, 0x3b, 0x14, 0x34, 0x34, 0x14, 0xfd, 0xc5, 0x13, 0x00, - 0x00, 0x01, 0xff, 0xb2, 0xff, 0x42, 0x00, 0xb6, 0x02, 0xca, 0x00, 0x10, 0x00, 0x28, 0x40, 0x25, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, - 0x00, 0x01, 0x03, 0x01, 0x00, 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, 0x01, 0x00, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x10, 0x01, 0x10, 0x04, 0x0d, - 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x04, 0x18, 0x24, 0x0e, 0x10, 0x24, 0x14, - 0x19, 0x2d, 0x1c, 0x5a, 0x66, 0xbe, 0x07, 0x06, 0x4c, 0x04, 0x06, 0x14, 0x32, 0x2d, 0x02, 0xc6, 0xfd, 0x41, 0x67, 0x62, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, - 0x02, 0x6b, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x20, 0x40, 0x1d, 0x0e, 0x08, 0x03, 0x02, 0x04, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, - 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x11, 0x13, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x07, 0x11, 0x23, 0x11, 0x33, 0x11, 0x36, 0x36, 0x37, - 0x37, 0x33, 0x01, 0x02, 0x6b, 0x6a, 0xfd, 0x49, 0x5a, 0x5a, 0x1e, 0x3e, 0x1f, 0xc1, 0x69, 0xfe, 0xe5, 0x01, 0x55, 0x40, 0xfe, 0xeb, 0x02, 0xca, 0xfe, 0xa0, - 0x22, 0x44, 0x22, 0xd8, 0xfe, 0xc9, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, 0xf3, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x6a, - 0x4d, 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, - 0x11, 0x33, 0x11, 0x21, 0x15, 0x61, 0x5a, 0x01, 0x38, 0x02, 0xca, 0xfd, 0x86, 0x50, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x03, 0x2a, 0x02, 0xca, 0x00, 0x15, - 0x00, 0x27, 0x40, 0x24, 0x13, 0x0a, 0x01, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x05, 0x04, 0x03, 0x03, 0x00, 0x00, 0x6b, 0x00, - 0x4e, 0x00, 0x00, 0x00, 0x15, 0x00, 0x15, 0x11, 0x13, 0x11, 0x16, 0x06, 0x0d, 0x1a, 0x2b, 0x21, 0x03, 0x23, 0x16, 0x16, 0x15, 0x11, 0x23, 0x11, 0x33, 0x13, - 0x33, 0x13, 0x33, 0x11, 0x23, 0x11, 0x34, 0x36, 0x37, 0x23, 0x03, 0x01, 0x9c, 0xeb, 0x04, 0x03, 0x04, 0x53, 0x85, 0xdc, 0x04, 0xe0, 0x84, 0x59, 0x05, 0x02, - 0x04, 0xee, 0x02, 0x72, 0x1f, 0x69, 0x39, 0xfe, 0x4f, 0x02, 0xca, 0xfd, 0xb7, 0x02, 0x49, 0xfd, 0x36, 0x01, 0xb7, 0x34, 0x66, 0x20, 0xfd, 0x8f, 0x00, 0x01, - 0x00, 0x61, 0x00, 0x00, 0x02, 0x97, 0x02, 0xca, 0x00, 0x12, 0x00, 0x1d, 0x40, 0x1a, 0x02, 0x01, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, - 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x17, 0x11, 0x16, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x01, 0x23, 0x16, 0x16, 0x15, 0x11, 0x23, 0x11, 0x33, - 0x01, 0x33, 0x2e, 0x02, 0x35, 0x11, 0x33, 0x02, 0x97, 0x69, 0xfe, 0x82, 0x04, 0x02, 0x06, 0x53, 0x68, 0x01, 0x7d, 0x04, 0x01, 0x03, 0x03, 0x54, 0x02, 0x51, - 0x23, 0x68, 0x37, 0xfe, 0x71, 0x02, 0xca, 0xfd, 0xb1, 0x10, 0x40, 0x4c, 0x20, 0x01, 0x93, 0x00, 0x00, 0x02, 0x00, 0x3d, 0xff, 0xf6, 0x02, 0xd0, 0x02, 0xd5, - 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, - 0x71, 0x00, 0x4e, 0x24, 0x25, 0x26, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, - 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xd0, 0x4b, 0x92, 0x6c, 0x6f, 0x93, 0x48, 0x48, 0x93, 0x70, 0x6b, 0x92, - 0x4b, 0xfd, 0xcc, 0x72, 0x79, 0x7a, 0x70, 0x70, 0x79, 0x79, 0x73, 0x01, 0x66, 0x6f, 0xa5, 0x5c, 0x5c, 0xa6, 0x6f, 0x6e, 0xa4, 0x5c, 0x5b, 0xa5, 0x6f, 0x87, - 0x9b, 0x9b, 0x87, 0x87, 0x99, 0x99, 0x00, 0x02, 0x00, 0x61, 0x00, 0x00, 0x02, 0x2a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x32, 0x40, 0x2f, 0x00, 0x04, - 0x00, 0x01, 0x02, 0x04, 0x01, 0x67, 0x06, 0x01, 0x03, 0x03, 0x00, 0x5f, 0x05, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0d, 0x0c, - 0x01, 0x00, 0x10, 0x0e, 0x0c, 0x14, 0x0d, 0x14, 0x0a, 0x09, 0x08, 0x06, 0x00, 0x0b, 0x01, 0x0b, 0x07, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, - 0x06, 0x23, 0x23, 0x11, 0x23, 0x11, 0x17, 0x23, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x1e, 0x8c, 0x80, 0x35, 0x7d, 0x6b, 0x52, 0x5a, 0xb5, 0x5b, - 0x48, 0x66, 0x64, 0x58, 0x02, 0xca, 0x6e, 0x64, 0x3b, 0x67, 0x40, 0xfe, 0xea, 0x02, 0xca, 0x4d, 0xfe, 0xe6, 0x42, 0x4f, 0x45, 0x44, 0x00, 0x02, 0x00, 0x3d, - 0xff, 0x56, 0x02, 0xd0, 0x02, 0xd5, 0x00, 0x14, 0x00, 0x20, 0x00, 0x2b, 0x40, 0x28, 0x03, 0x01, 0x01, 0x03, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x86, 0x00, - 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x25, 0x26, 0x41, 0x14, 0x05, - 0x0d, 0x1b, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x17, 0x23, 0x27, 0x22, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, - 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xd0, 0x69, 0x67, 0xab, 0x81, 0x8a, 0x06, 0x0d, 0x06, 0x6f, 0x93, 0x48, 0x48, 0x93, 0x70, - 0x6b, 0x92, 0x4b, 0xfd, 0xcc, 0x72, 0x79, 0x7a, 0x70, 0x70, 0x79, 0x79, 0x73, 0x01, 0x66, 0x83, 0xb8, 0x23, 0xb2, 0xa1, 0x01, 0x5c, 0xa6, 0x6f, 0x6e, 0xa4, - 0x5c, 0x5b, 0xa5, 0x6f, 0x87, 0x9b, 0x9b, 0x87, 0x87, 0x99, 0x99, 0x00, 0x00, 0x02, 0x00, 0x61, 0x00, 0x00, 0x02, 0x5f, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x17, - 0x00, 0x3b, 0x40, 0x38, 0x07, 0x01, 0x02, 0x05, 0x01, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x5f, 0x06, 0x01, - 0x00, 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x10, 0x0f, 0x01, 0x00, 0x13, 0x11, 0x0f, 0x17, 0x10, 0x17, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, - 0x08, 0x00, 0x0e, 0x01, 0x0e, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x11, 0x23, 0x11, 0x17, 0x23, - 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x26, 0x85, 0x7f, 0x2a, 0x41, 0x24, 0xc4, 0x69, 0xad, 0x8e, 0x5a, 0xc0, 0x66, 0x6b, 0x57, 0x50, 0x54, 0x02, - 0xca, 0x65, 0x66, 0x39, 0x4c, 0x2d, 0x0d, 0xfe, 0xc0, 0x01, 0x27, 0xfe, 0xd9, 0x02, 0xca, 0x4e, 0xfe, 0xf7, 0x45, 0x43, 0x46, 0x3b, 0x00, 0x01, 0x00, 0x33, - 0xff, 0xf6, 0x01, 0xf6, 0x02, 0xd4, 0x00, 0x29, 0x00, 0x2e, 0x40, 0x2b, 0x1b, 0x01, 0x03, 0x02, 0x1c, 0x07, 0x02, 0x01, 0x03, 0x06, 0x01, 0x00, 0x01, 0x03, - 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, 0x2c, 0x25, 0x22, - 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x26, 0x26, 0x35, 0x34, - 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xf6, 0x8a, 0x75, 0x3c, 0x66, 0x22, - 0x24, 0x6b, 0x39, 0x50, 0x51, 0x1e, 0x49, 0x41, 0x5b, 0x5d, 0x3a, 0x67, 0x43, 0x3b, 0x62, 0x28, 0x1c, 0x25, 0x57, 0x2f, 0x43, 0x44, 0x1e, 0x44, 0x3a, 0x3f, - 0x57, 0x2d, 0xbf, 0x5f, 0x6a, 0x12, 0x10, 0x56, 0x10, 0x1a, 0x3e, 0x35, 0x23, 0x30, 0x29, 0x17, 0x21, 0x60, 0x53, 0x39, 0x51, 0x2c, 0x16, 0x12, 0x4d, 0x10, - 0x16, 0x39, 0x2f, 0x24, 0x30, 0x26, 0x16, 0x17, 0x35, 0x4a, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x02, 0x21, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1b, 0x40, 0x18, - 0x03, 0x01, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, - 0x23, 0x11, 0x23, 0x35, 0x21, 0x15, 0x23, 0x01, 0x43, 0x5a, 0xdf, 0x02, 0x17, 0xde, 0x02, 0x7b, 0x4f, 0x4f, 0x00, 0x01, 0x00, 0x5a, 0xff, 0xf6, 0x02, 0x80, - 0x02, 0xca, 0x00, 0x12, 0x00, 0x1b, 0x40, 0x18, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x13, - 0x23, 0x13, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, - 0x02, 0x80, 0x3c, 0x7b, 0x5f, 0x85, 0x8b, 0x5a, 0x5d, 0x5e, 0x61, 0x57, 0x59, 0xfc, 0x4a, 0x77, 0x45, 0x91, 0x77, 0x01, 0xcc, 0xfe, 0x31, 0x57, 0x60, 0x67, - 0x51, 0x01, 0xce, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x58, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x21, 0x40, 0x1e, 0x08, 0x01, 0x00, 0x01, 0x01, 0x4c, - 0x03, 0x02, 0x02, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x01, - 0x03, 0x23, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x36, 0x36, 0x37, 0x13, 0x02, 0x58, 0xff, 0x5a, 0xff, 0x5e, 0xa1, 0x10, 0x16, 0x07, 0x07, 0x16, 0x10, 0xa0, - 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0xfe, 0x36, 0x2c, 0x4d, 0x23, 0x23, 0x4e, 0x2d, 0x01, 0xc8, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x03, 0x95, 0x02, 0xca, - 0x00, 0x1f, 0x00, 0x27, 0x40, 0x24, 0x1b, 0x12, 0x07, 0x03, 0x00, 0x02, 0x01, 0x4c, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, - 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x18, 0x11, 0x19, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x01, 0x03, 0x23, 0x03, 0x2e, 0x02, 0x27, 0x06, 0x06, - 0x07, 0x03, 0x23, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x36, 0x36, 0x37, 0x13, 0x33, 0x13, 0x16, 0x16, 0x17, 0x36, 0x36, 0x37, 0x13, 0x03, 0x95, 0xbe, 0x5b, - 0x8b, 0x08, 0x10, 0x0a, 0x02, 0x01, 0x13, 0x0e, 0x87, 0x5b, 0xbd, 0x5e, 0x6f, 0x0c, 0x11, 0x05, 0x05, 0x14, 0x0d, 0x7e, 0x5d, 0x83, 0x0e, 0x14, 0x05, 0x05, - 0x12, 0x0c, 0x6e, 0x02, 0xca, 0xfd, 0x36, 0x01, 0xd4, 0x1d, 0x3a, 0x2d, 0x09, 0x0d, 0x55, 0x2e, 0xfe, 0x2f, 0x02, 0xca, 0xfe, 0x4c, 0x2e, 0x56, 0x26, 0x27, - 0x5c, 0x2c, 0x01, 0xaf, 0xfe, 0x4e, 0x2e, 0x5b, 0x23, 0x25, 0x57, 0x2f, 0x01, 0xb3, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x02, 0x46, 0x02, 0xca, 0x00, 0x0b, - 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x08, 0x05, 0x02, 0x04, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, - 0x12, 0x12, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x03, 0x23, 0x13, 0x03, 0x33, 0x13, 0x13, 0x33, 0x03, 0x02, 0x46, 0x66, 0xbd, 0xc0, 0x5f, - 0xed, 0xde, 0x64, 0xaf, 0xb0, 0x5f, 0xdd, 0x01, 0x36, 0xfe, 0xca, 0x01, 0x74, 0x01, 0x56, 0xfe, 0xe8, 0x01, 0x18, 0xfe, 0xac, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x36, 0x02, 0xca, 0x00, 0x08, 0x00, 0x1c, 0x40, 0x19, 0x06, 0x03, 0x02, 0x01, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, - 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x12, 0x12, 0x11, 0x03, 0x0d, 0x19, 0x2b, 0x01, 0x13, 0x33, 0x03, 0x11, 0x23, 0x11, 0x03, 0x33, 0x01, 0x1b, 0xba, 0x61, 0xee, - 0x5a, 0xee, 0x62, 0x01, 0x6b, 0x01, 0x5f, 0xfe, 0x4b, 0xfe, 0xeb, 0x01, 0x11, 0x01, 0xb9, 0x00, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x02, 0x15, 0x02, 0xca, - 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x4d, - 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, - 0x15, 0x01, 0x21, 0x02, 0x15, 0xfe, 0x11, 0x01, 0x78, 0xfe, 0x94, 0x01, 0xd9, 0xfe, 0x88, 0x01, 0x82, 0x44, 0x02, 0x36, 0x50, 0x44, 0xfd, 0xca, 0x00, 0x01, - 0x00, 0x50, 0xff, 0x62, 0x01, 0x30, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x63, 0x00, 0x02, 0x02, 0x01, 0x5f, - 0x00, 0x01, 0x01, 0x6a, 0x02, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x05, 0x23, 0x11, 0x33, 0x15, 0x23, 0x11, 0x33, 0x01, 0x30, 0xe0, 0xe0, - 0x8a, 0x8a, 0x9e, 0x03, 0x68, 0x48, 0xfd, 0x28, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x6b, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, - 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x01, 0x23, 0x01, 0x60, - 0x01, 0x0b, 0x57, 0xfe, 0xf6, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0x00, 0x00, 0x01, 0x00, 0x19, 0xff, 0x62, 0x00, 0xf9, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, - 0x40, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x63, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, - 0x1a, 0x2b, 0x17, 0x33, 0x11, 0x23, 0x35, 0x33, 0x11, 0x23, 0x19, 0x8a, 0x8a, 0xe0, 0xe0, 0x56, 0x02, 0xd8, 0x48, 0xfc, 0x98, 0x00, 0x00, 0x01, 0x00, 0x26, - 0x01, 0x0b, 0x02, 0x16, 0x02, 0xcf, 0x00, 0x06, 0x00, 0x27, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, - 0x85, 0x03, 0x02, 0x02, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x13, 0x13, 0x33, - 0x13, 0x23, 0x03, 0x03, 0x26, 0xd4, 0x32, 0xea, 0x4e, 0xb4, 0xa0, 0x01, 0x0b, 0x01, 0xc4, 0xfe, 0x3c, 0x01, 0x67, 0xfe, 0x99, 0x00, 0x00, 0x01, 0xff, 0xfe, - 0xff, 0x66, 0x01, 0xbe, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x20, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, - 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x05, 0x21, 0x35, 0x21, 0x01, 0xbe, 0xfe, 0x40, 0x01, 0xc0, - 0x9a, 0x40, 0x00, 0x01, 0x00, 0x28, 0x02, 0x5e, 0x00, 0xf1, 0x02, 0xfe, 0x00, 0x0b, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x0a, 0x04, 0x02, 0x00, - 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x00, 0x01, 0x85, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, - 0x00, 0x44, 0x13, 0x1e, 0x02, 0x17, 0x15, 0x23, 0x2e, 0x02, 0x27, 0x35, 0x91, 0x0b, 0x21, 0x25, 0x0f, 0x3b, 0x17, 0x3a, 0x31, 0x0c, 0x02, 0xfe, 0x16, 0x37, - 0x34, 0x13, 0x0c, 0x12, 0x39, 0x39, 0x12, 0x0a, 0x00, 0x02, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xe0, 0x02, 0x21, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x7b, 0x40, 0x0e, - 0x19, 0x01, 0x04, 0x00, 0x18, 0x01, 0x03, 0x04, 0x06, 0x01, 0x06, 0x05, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x20, 0x00, 0x03, 0x08, 0x01, 0x05, - 0x06, 0x03, 0x05, 0x67, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, - 0x4e, 0x1b, 0x40, 0x24, 0x00, 0x03, 0x08, 0x01, 0x05, 0x06, 0x03, 0x05, 0x67, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x01, - 0x01, 0x6b, 0x4d, 0x00, 0x06, 0x06, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, 0x26, 0x1d, - 0x26, 0x16, 0x14, 0x11, 0x0f, 0x0b, 0x09, 0x05, 0x04, 0x00, 0x1b, 0x01, 0x1b, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x27, 0x23, 0x06, - 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x13, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, - 0x32, 0x36, 0x35, 0x35, 0x01, 0x20, 0x62, 0x5e, 0x40, 0x11, 0x04, 0x23, 0x4d, 0x44, 0x49, 0x60, 0x7e, 0x83, 0x5b, 0x3a, 0x35, 0x2a, 0x4c, 0x21, 0x1b, 0x23, - 0x60, 0x4e, 0x64, 0x4d, 0x37, 0x2b, 0x44, 0x5a, 0x02, 0x21, 0x56, 0x5e, 0xfe, 0x93, 0x4c, 0x2c, 0x2a, 0x4d, 0x52, 0x50, 0x57, 0x04, 0x03, 0x20, 0x43, 0x34, - 0x19, 0x10, 0x42, 0x13, 0x1b, 0xfe, 0xe2, 0x04, 0x38, 0x33, 0x2d, 0x2a, 0x4b, 0x4e, 0x30, 0x00, 0x00, 0x02, 0x00, 0x55, 0xff, 0xf6, 0x02, 0x30, 0x02, 0xf8, - 0x00, 0x15, 0x00, 0x21, 0x00, 0x8a, 0xb6, 0x10, 0x03, 0x02, 0x05, 0x04, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x6c, 0x4d, - 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1b, 0x4b, 0xb0, - 0x29, 0x50, 0x58, 0x40, 0x20, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x4d, - 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1b, 0x40, 0x20, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, - 0x03, 0x03, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x59, 0x59, 0x40, 0x0f, 0x17, 0x16, - 0x1e, 0x1c, 0x16, 0x21, 0x17, 0x21, 0x11, 0x14, 0x24, 0x26, 0x07, 0x0d, 0x1a, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, - 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x07, 0x23, 0x11, 0x33, 0x13, 0x22, 0x06, 0x15, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0xad, 0x03, 0x02, 0x05, - 0x17, 0x50, 0x3f, 0x64, 0x79, 0x7a, 0x63, 0x3f, 0x50, 0x17, 0x07, 0x12, 0x3f, 0x58, 0x97, 0x55, 0x42, 0x41, 0x58, 0x48, 0x47, 0x02, 0x3f, 0x22, 0x3b, 0x11, - 0x22, 0x2e, 0x8b, 0x8a, 0x8a, 0x8c, 0x2e, 0x20, 0x44, 0x02, 0xf8, 0xfe, 0xe0, 0x62, 0x67, 0x04, 0x63, 0x69, 0x6a, 0x64, 0xcb, 0x00, 0x00, 0x01, 0x00, 0x37, - 0xff, 0xf6, 0x01, 0xbf, 0x02, 0x22, 0x00, 0x1a, 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, 0x02, 0x01, 0x17, 0x0c, 0x02, 0x03, 0x02, 0x18, 0x01, 0x00, 0x03, 0x03, - 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x15, - 0x13, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1a, 0x01, 0x1a, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, - 0x26, 0x26, 0x23, 0x22, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x01, 0x2c, 0x47, 0x6f, 0x3f, 0x42, 0x71, 0x48, 0x29, 0x4c, 0x18, 0x1b, - 0x18, 0x40, 0x1c, 0x9e, 0x4d, 0x4c, 0x2c, 0x43, 0x1c, 0x1b, 0x41, 0x0a, 0x3a, 0x7a, 0x5f, 0x63, 0x7c, 0x3a, 0x11, 0x0c, 0x49, 0x09, 0x10, 0xcb, 0x61, 0x67, - 0x12, 0x0d, 0x4e, 0x0e, 0x0f, 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x12, 0x02, 0xf8, 0x00, 0x15, 0x00, 0x22, 0x00, 0x95, 0xb6, 0x12, 0x09, 0x02, - 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, - 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, - 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, - 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6b, 0x4d, - 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x22, 0x17, - 0x22, 0x11, 0x10, 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, - 0x26, 0x26, 0x35, 0x35, 0x33, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x27, 0x32, 0x36, 0x35, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x01, 0x13, - 0x64, 0x78, 0x79, 0x64, 0x3e, 0x4f, 0x19, 0x06, 0x01, 0x05, 0x58, 0x47, 0x0d, 0x04, 0x18, 0x50, 0x31, 0x55, 0x45, 0x42, 0x59, 0x47, 0x47, 0x47, 0x0a, 0x8b, - 0x8a, 0x8a, 0x8d, 0x2e, 0x21, 0x0d, 0x33, 0x0f, 0xd6, 0xfd, 0x08, 0x48, 0x22, 0x30, 0x49, 0x5d, 0x5e, 0x10, 0x64, 0x6b, 0x71, 0x5f, 0x60, 0x6a, 0x00, 0x02, - 0x00, 0x37, 0xff, 0xf6, 0x02, 0x01, 0x02, 0x22, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x43, 0x40, 0x40, 0x0c, 0x01, 0x02, 0x01, 0x0d, 0x01, 0x03, 0x02, 0x02, 0x4c, - 0x00, 0x05, 0x00, 0x01, 0x02, 0x05, 0x01, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, - 0x03, 0x03, 0x71, 0x03, 0x4e, 0x19, 0x18, 0x01, 0x00, 0x1c, 0x1b, 0x18, 0x1e, 0x19, 0x1e, 0x11, 0x0f, 0x0a, 0x08, 0x06, 0x05, 0x00, 0x17, 0x01, 0x17, 0x08, - 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x15, 0x21, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, - 0x36, 0x17, 0x22, 0x06, 0x07, 0x21, 0x26, 0x26, 0x01, 0x24, 0x45, 0x63, 0x35, 0xfe, 0x91, 0x02, 0x59, 0x50, 0x33, 0x4f, 0x2a, 0x29, 0x50, 0x37, 0x4c, 0x75, - 0x41, 0x3b, 0x6b, 0x46, 0x3f, 0x49, 0x07, 0x01, 0x11, 0x01, 0x3e, 0x02, 0x22, 0x3c, 0x6d, 0x49, 0x35, 0x5b, 0x5f, 0x13, 0x12, 0x4d, 0x12, 0x11, 0x3e, 0x7b, - 0x59, 0x58, 0x7e, 0x44, 0x48, 0x51, 0x48, 0x44, 0x55, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x83, 0x02, 0xfd, 0x00, 0x17, 0x00, 0x5c, 0x40, 0x0f, - 0x0e, 0x01, 0x04, 0x03, 0x0f, 0x07, 0x02, 0x05, 0x04, 0x06, 0x01, 0x00, 0x05, 0x03, 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, - 0x61, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x19, - 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x69, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, - 0x40, 0x09, 0x13, 0x25, 0x25, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x37, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, - 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x15, 0x33, 0x01, 0x4c, 0x87, 0x58, 0x5e, 0x5e, 0x5c, 0x52, 0x20, 0x35, 0x13, 0x17, 0x10, 0x2a, 0x16, 0x2c, - 0x2b, 0x87, 0x01, 0xd4, 0xfe, 0x2c, 0x01, 0xd4, 0x29, 0x1e, 0x1f, 0x68, 0x5b, 0x0b, 0x07, 0x45, 0x05, 0x0a, 0x3b, 0x3f, 0x23, 0x00, 0x00, 0x02, 0x00, 0x37, - 0xff, 0x10, 0x02, 0x12, 0x02, 0x22, 0x00, 0x1e, 0x00, 0x2b, 0x00, 0x80, 0x40, 0x0f, 0x16, 0x03, 0x02, 0x06, 0x05, 0x0d, 0x01, 0x03, 0x04, 0x0c, 0x01, 0x02, - 0x03, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x08, 0x01, 0x05, 0x05, 0x00, 0x61, 0x01, 0x07, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, - 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x01, 0x01, 0x6d, 0x4d, - 0x08, 0x01, 0x05, 0x05, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, - 0x61, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x20, 0x1f, 0x01, 0x00, 0x26, 0x24, 0x1f, 0x2b, 0x20, 0x2b, 0x1a, 0x18, 0x10, 0x0e, 0x0b, 0x09, - 0x06, 0x05, 0x00, 0x1e, 0x01, 0x1e, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x14, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, - 0x32, 0x36, 0x35, 0x35, 0x34, 0x36, 0x37, 0x23, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x35, - 0x34, 0x26, 0x01, 0x13, 0x35, 0x55, 0x1e, 0x05, 0x0c, 0x46, 0x75, 0x7b, 0x76, 0x4b, 0x4f, 0x77, 0x45, 0x4f, 0x02, 0x01, 0x04, 0x36, 0x70, 0x68, 0x75, 0x75, - 0x73, 0x43, 0x4a, 0x49, 0x46, 0x51, 0x4a, 0x4c, 0x02, 0x22, 0x28, 0x29, 0x47, 0xfd, 0xdf, 0x73, 0x74, 0x22, 0x51, 0x2a, 0x51, 0x46, 0x15, 0x0c, 0x2d, 0x09, - 0x51, 0x92, 0x83, 0x80, 0x97, 0x4a, 0x6b, 0x63, 0x63, 0x69, 0x57, 0x61, 0x15, 0x6e, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x02, 0x19, 0x02, 0xf8, - 0x00, 0x15, 0x00, 0x48, 0xb5, 0x02, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x16, 0x00, 0x04, 0x04, 0x6c, 0x4d, 0x00, 0x02, 0x02, - 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, - 0x4d, 0x00, 0x04, 0x04, 0x01, 0x5f, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0xb7, 0x11, 0x13, 0x22, 0x13, 0x25, 0x05, 0x0d, 0x1b, 0x2b, 0x13, 0x14, - 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0xad, 0x05, 0x06, 0x1a, 0x59, 0x34, - 0x62, 0x62, 0x57, 0x78, 0x5a, 0x43, 0x58, 0x58, 0x02, 0x19, 0x28, 0x23, 0x29, 0x2a, 0x5d, 0x67, 0xfe, 0xa3, 0x01, 0x57, 0x81, 0x65, 0x5e, 0xfe, 0xeb, 0x02, - 0xf8, 0x00, 0x00, 0x02, 0x00, 0x4e, 0x00, 0x00, 0x00, 0xb5, 0x02, 0xe1, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x8d, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x17, 0x00, - 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x6c, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, - 0x50, 0x58, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, - 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x6c, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, - 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x15, 0x04, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x01, 0x69, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, - 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x13, 0x0c, 0x0c, 0x01, 0x00, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, - 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x11, 0x23, 0x11, 0x82, 0x14, 0x1f, 0x1f, 0x14, 0x16, 0x1e, - 0x1e, 0x41, 0x58, 0x02, 0xe1, 0x1b, 0x1d, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1b, 0xc9, 0xfd, 0xe8, 0x02, 0x18, 0x00, 0x02, 0xff, 0xc9, 0xff, 0x10, 0x00, 0xb5, - 0x02, 0xe1, 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xa5, 0x40, 0x0a, 0x10, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, - 0x1b, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, - 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, - 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, - 0x00, 0x6c, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x19, 0x00, 0x00, 0x00, - 0x01, 0x04, 0x00, 0x01, 0x69, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x59, 0x59, 0x40, - 0x0f, 0x0d, 0x0c, 0x18, 0x17, 0x14, 0x12, 0x0c, 0x1b, 0x0d, 0x1b, 0x24, 0x22, 0x06, 0x0d, 0x18, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, - 0x23, 0x22, 0x26, 0x03, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x4e, 0x1e, 0x16, 0x14, 0x1f, 0x1f, 0x14, - 0x16, 0x1e, 0x38, 0x19, 0x26, 0x0e, 0x0f, 0x20, 0x13, 0x20, 0x2a, 0x58, 0x48, 0x02, 0xa9, 0x1d, 0x1b, 0x1b, 0x1d, 0x1c, 0x1c, 0x1c, 0xfc, 0x83, 0x07, 0x05, - 0x47, 0x04, 0x06, 0x23, 0x31, 0x02, 0x6b, 0xfd, 0x98, 0x4b, 0x55, 0x00, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x02, 0x0d, 0x02, 0xf8, 0x00, 0x13, 0x00, 0x47, - 0x40, 0x09, 0x0f, 0x0e, 0x0b, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x11, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x00, 0x00, 0x00, - 0x6d, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x03, 0x03, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x4d, 0x00, 0x00, 0x00, - 0x6d, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0xb6, 0x11, 0x13, 0x12, 0x19, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x3e, 0x02, - 0x37, 0x37, 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x15, 0x23, 0x11, 0x33, 0xac, 0x03, 0x01, 0x04, 0x06, 0x18, 0x19, 0x09, 0xab, 0x67, 0xd9, 0xe8, 0x6a, 0xba, - 0x3d, 0x57, 0x57, 0x01, 0x6b, 0x10, 0x34, 0x13, 0x08, 0x1e, 0x1f, 0x0a, 0xb5, 0xe5, 0xfe, 0xcd, 0xfa, 0x35, 0xc5, 0x02, 0xf8, 0x00, 0x00, 0x01, 0x00, 0x55, - 0x00, 0x00, 0x00, 0xad, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x28, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0b, 0x00, 0x01, 0x01, 0x6c, 0x4d, 0x00, 0x00, 0x00, 0x6b, - 0x00, 0x4e, 0x1b, 0x40, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x59, 0xb4, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x33, 0x23, - 0x11, 0x33, 0xad, 0x58, 0x58, 0x02, 0xf8, 0x00, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x03, 0x56, 0x02, 0x22, 0x00, 0x21, 0x00, 0x5d, 0xb6, 0x1e, 0x18, 0x02, - 0x01, 0x02, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x04, 0x01, 0x02, 0x02, 0x00, 0x61, 0x07, 0x06, 0x08, 0x03, 0x00, 0x00, 0x73, 0x4d, 0x05, - 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x1a, 0x00, 0x06, 0x06, 0x6d, 0x4d, 0x04, 0x01, 0x02, 0x02, 0x00, 0x61, 0x07, 0x08, 0x02, 0x00, 0x00, - 0x73, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x17, 0x01, 0x00, 0x1d, 0x1b, 0x17, 0x16, 0x15, 0x14, 0x11, 0x0f, 0x0d, 0x0c, 0x09, - 0x07, 0x05, 0x04, 0x00, 0x21, 0x01, 0x21, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, - 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x33, 0x32, 0x17, 0x33, 0x36, 0x36, 0x02, 0xa1, 0x5b, 0x5a, 0x57, 0x6d, 0x4e, - 0x43, 0x57, 0x6e, 0x51, 0x3e, 0x58, 0x47, 0x0d, 0x05, 0x19, 0x55, 0x30, 0x7e, 0x26, 0x05, 0x1b, 0x5d, 0x02, 0x22, 0x5d, 0x68, 0xfe, 0xa3, 0x01, 0x59, 0x7f, - 0x5a, 0x56, 0xfe, 0xd8, 0x01, 0x59, 0x7f, 0x64, 0x5e, 0xfe, 0xea, 0x02, 0x18, 0x49, 0x2a, 0x29, 0x5a, 0x2e, 0x2c, 0x00, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, - 0x02, 0x19, 0x02, 0x22, 0x00, 0x13, 0x00, 0x50, 0xb5, 0x10, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x00, 0x02, 0x02, 0x00, - 0x61, 0x04, 0x05, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x02, 0x02, - 0x00, 0x61, 0x05, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x09, 0x07, - 0x05, 0x04, 0x00, 0x13, 0x01, 0x13, 0x06, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, - 0x17, 0x33, 0x36, 0x36, 0x01, 0x57, 0x60, 0x62, 0x57, 0x78, 0x59, 0x44, 0x58, 0x47, 0x0d, 0x05, 0x1a, 0x5c, 0x02, 0x22, 0x5d, 0x68, 0xfe, 0xa3, 0x01, 0x57, - 0x81, 0x64, 0x5e, 0xfe, 0xea, 0x02, 0x18, 0x49, 0x2a, 0x29, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x27, 0x02, 0x22, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x1f, - 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x25, 0x25, - 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, - 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x27, 0x87, 0x73, 0x47, 0x6f, 0x40, 0x86, 0x73, 0x49, 0x6f, 0x3f, 0xfe, 0x6b, 0x4b, 0x52, 0x51, 0x4c, 0x4c, 0x52, 0x52, - 0x4a, 0x01, 0x0d, 0x85, 0x92, 0x41, 0x7d, 0x59, 0x85, 0x90, 0x41, 0x7b, 0x59, 0x5f, 0x6f, 0x6f, 0x5f, 0x5f, 0x6c, 0x6c, 0x00, 0x02, 0x00, 0x55, 0xff, 0x10, - 0x02, 0x30, 0x02, 0x22, 0x00, 0x15, 0x00, 0x23, 0x00, 0x6b, 0xb6, 0x12, 0x09, 0x02, 0x05, 0x04, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x07, - 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, - 0x02, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, - 0x61, 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x23, 0x17, 0x23, 0x11, - 0x10, 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x16, 0x16, - 0x15, 0x15, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x17, 0x22, 0x06, 0x07, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x01, 0x54, 0x63, - 0x79, 0x79, 0x64, 0x3e, 0x51, 0x17, 0x06, 0x02, 0x04, 0x58, 0x48, 0x0c, 0x04, 0x18, 0x4e, 0x31, 0x52, 0x43, 0x02, 0x41, 0x58, 0x31, 0x3f, 0x1f, 0x47, 0x02, - 0x22, 0x8a, 0x8b, 0x89, 0x8e, 0x2f, 0x1f, 0x11, 0x34, 0x13, 0xdc, 0x03, 0x08, 0x49, 0x23, 0x30, 0x4a, 0x5c, 0x5e, 0x11, 0x63, 0x6b, 0x36, 0x5d, 0x3c, 0x5c, - 0x6e, 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0x10, 0x02, 0x12, 0x02, 0x22, 0x00, 0x15, 0x00, 0x22, 0x00, 0x61, 0xb6, 0x10, 0x03, 0x02, 0x04, 0x05, 0x01, 0x4c, - 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, - 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, - 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x17, 0x16, 0x1e, 0x1c, 0x16, - 0x22, 0x17, 0x22, 0x11, 0x14, 0x24, 0x26, 0x07, 0x0d, 0x1a, 0x2b, 0x05, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, - 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x23, 0x03, 0x32, 0x36, 0x37, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x01, 0xba, 0x02, 0x03, 0x06, 0x17, - 0x51, 0x40, 0x61, 0x79, 0x7b, 0x62, 0x3f, 0x50, 0x18, 0x04, 0x0d, 0x46, 0x58, 0x98, 0x53, 0x45, 0x01, 0x44, 0x57, 0x48, 0x46, 0x47, 0x0b, 0x12, 0x30, 0x11, - 0x22, 0x30, 0x8b, 0x8a, 0x8a, 0x8d, 0x30, 0x23, 0x49, 0xfc, 0xf8, 0x01, 0x2f, 0x5b, 0x5e, 0x12, 0x66, 0x69, 0x71, 0x5f, 0x5f, 0x6b, 0x00, 0x01, 0x00, 0x55, - 0x00, 0x00, 0x01, 0x8e, 0x02, 0x22, 0x00, 0x13, 0x00, 0x66, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0b, 0x03, 0x01, 0x01, 0x00, 0x10, 0x04, 0x02, 0x02, 0x01, - 0x02, 0x4c, 0x1b, 0x40, 0x0b, 0x03, 0x01, 0x03, 0x00, 0x10, 0x04, 0x02, 0x02, 0x01, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x01, - 0x01, 0x00, 0x61, 0x03, 0x04, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x01, - 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0f, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x08, 0x06, - 0x00, 0x13, 0x01, 0x13, 0x05, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, - 0x36, 0x36, 0x01, 0x4f, 0x0f, 0x23, 0x0d, 0x0b, 0x0d, 0x1f, 0x0e, 0x29, 0x48, 0x2b, 0x58, 0x48, 0x0a, 0x04, 0x1a, 0x52, 0x02, 0x22, 0x03, 0x03, 0x51, 0x03, - 0x04, 0x2d, 0x51, 0x36, 0xfe, 0xe2, 0x02, 0x18, 0x62, 0x2c, 0x40, 0x00, 0x00, 0x01, 0x00, 0x33, 0xff, 0xf6, 0x01, 0xb2, 0x02, 0x22, 0x00, 0x29, 0x00, 0x2e, - 0x40, 0x2b, 0x1b, 0x01, 0x03, 0x02, 0x1c, 0x07, 0x02, 0x01, 0x03, 0x06, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, - 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, 0x2c, 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, 0x22, 0x26, - 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, - 0x06, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xb2, 0x74, 0x62, 0x38, 0x51, 0x1f, 0x20, 0x5b, 0x2f, 0x43, 0x3c, 0x16, 0x39, 0x35, 0x34, 0x4a, 0x28, - 0x6f, 0x5a, 0x31, 0x55, 0x25, 0x1e, 0x22, 0x4a, 0x27, 0x36, 0x39, 0x1a, 0x3d, 0x33, 0x33, 0x48, 0x26, 0x94, 0x4e, 0x50, 0x12, 0x10, 0x50, 0x10, 0x1b, 0x2b, - 0x24, 0x14, 0x20, 0x20, 0x14, 0x14, 0x28, 0x38, 0x2c, 0x44, 0x4a, 0x13, 0x11, 0x46, 0x0e, 0x14, 0x23, 0x1e, 0x16, 0x1f, 0x1d, 0x14, 0x13, 0x28, 0x39, 0x00, - 0x00, 0x01, 0x00, 0x10, 0xff, 0xf6, 0x01, 0x53, 0x02, 0x93, 0x00, 0x18, 0x00, 0x40, 0x40, 0x3d, 0x0e, 0x01, 0x02, 0x04, 0x03, 0x01, 0x00, 0x02, 0x04, 0x01, - 0x01, 0x00, 0x03, 0x4c, 0x00, 0x03, 0x04, 0x03, 0x85, 0x05, 0x01, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x06, 0x01, 0x00, 0x00, 0x01, 0x61, - 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x01, 0x00, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x18, 0x01, 0x18, 0x07, 0x0d, 0x16, 0x2b, - 0x25, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x11, 0x23, 0x35, 0x37, 0x37, 0x33, 0x15, 0x33, 0x15, 0x23, 0x11, 0x14, 0x16, 0x01, - 0x08, 0x14, 0x2a, 0x0d, 0x0e, 0x34, 0x18, 0x2a, 0x47, 0x2c, 0x4c, 0x4d, 0x23, 0x34, 0x9b, 0x9b, 0x2f, 0x3e, 0x07, 0x04, 0x43, 0x07, 0x09, 0x1d, 0x48, 0x41, - 0x01, 0x38, 0x2a, 0x23, 0x72, 0x7b, 0x44, 0xfe, 0xca, 0x31, 0x2f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0xff, 0xf6, 0x02, 0x15, 0x02, 0x18, 0x00, 0x13, 0x00, 0x4c, - 0xb5, 0x03, 0x01, 0x03, 0x02, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, - 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1b, 0x40, 0x17, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0x00, 0x03, 0x03, 0x01, - 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x13, 0x22, 0x13, 0x24, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x01, 0x11, - 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x33, 0x32, 0x36, 0x35, 0x11, 0x02, 0x15, 0x48, 0x0d, 0x04, 0x1a, 0x5c, 0x34, - 0x61, 0x62, 0x59, 0x77, 0x59, 0x45, 0x02, 0x18, 0xfd, 0xe8, 0x47, 0x2a, 0x27, 0x5d, 0x66, 0x01, 0x5f, 0xfe, 0xa7, 0x80, 0x64, 0x5e, 0x01, 0x17, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x02, 0x18, 0x00, 0x0f, 0x00, 0x21, 0x40, 0x1e, 0x07, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, - 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x1b, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x17, - 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x03, 0xcb, 0xcb, 0x5e, 0x72, 0x08, 0x12, 0x0e, 0x03, 0x04, 0x04, 0x0f, 0x13, 0x07, 0x72, 0x5e, 0xcc, 0x02, 0x18, 0xfe, - 0xc4, 0x16, 0x36, 0x31, 0x11, 0x11, 0x32, 0x36, 0x15, 0x01, 0x3c, 0xfd, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x01, 0x03, 0x07, 0x02, 0x19, 0x00, 0x22, - 0x00, 0x21, 0x40, 0x1e, 0x1a, 0x0f, 0x03, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x02, 0x02, 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, - 0x11, 0x19, 0x1a, 0x11, 0x18, 0x05, 0x0d, 0x1b, 0x2b, 0x01, 0x26, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x03, 0x23, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, - 0x3e, 0x02, 0x37, 0x13, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0x23, 0x01, 0xaf, 0x0d, 0x13, 0x05, 0x04, 0x04, 0x12, 0x0e, - 0x60, 0x64, 0x93, 0x5b, 0x4a, 0x0b, 0x14, 0x04, 0x04, 0x04, 0x0b, 0x0e, 0x07, 0x5f, 0x60, 0x5c, 0x0b, 0x15, 0x04, 0x04, 0x03, 0x15, 0x0c, 0x4b, 0x5a, 0x95, - 0x67, 0x01, 0x2f, 0x29, 0x4f, 0x16, 0x16, 0x4f, 0x2a, 0xfe, 0xd3, 0x02, 0x18, 0xfe, 0xe2, 0x2b, 0x58, 0x1d, 0x11, 0x32, 0x37, 0x16, 0x01, 0x2e, 0xfe, 0xd2, - 0x22, 0x50, 0x1d, 0x19, 0x58, 0x2e, 0x01, 0x1e, 0xfd, 0xe8, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x01, 0xff, 0x02, 0x18, 0x00, 0x0b, 0x00, 0x1f, 0x40, 0x1c, - 0x09, 0x06, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x12, 0x12, 0x12, 0x11, 0x04, - 0x0d, 0x1a, 0x2b, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x23, 0xd4, 0xb9, 0x64, 0x8a, 0x89, 0x63, 0xb9, 0xc3, 0x64, 0x92, 0x94, - 0x63, 0x01, 0x12, 0x01, 0x06, 0xca, 0xca, 0xfe, 0xfa, 0xfe, 0xee, 0xd6, 0xd6, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0x10, 0x01, 0xfe, 0x02, 0x18, 0x00, 0x1a, - 0x00, 0x27, 0x40, 0x24, 0x1a, 0x13, 0x05, 0x03, 0x03, 0x00, 0x12, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, - 0x61, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x25, 0x23, 0x19, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, - 0x33, 0x03, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x01, 0x5e, 0x74, 0x0f, 0x18, 0x06, 0x04, 0x06, 0x1a, 0x0e, - 0x6d, 0x5f, 0xe7, 0x1c, 0x59, 0x4e, 0x18, 0x24, 0x0d, 0x0b, 0x1f, 0x11, 0x2e, 0x39, 0x10, 0x1c, 0x02, 0x18, 0xfe, 0xcf, 0x28, 0x49, 0x21, 0x19, 0x51, 0x29, - 0x01, 0x30, 0xfd, 0x9e, 0x4c, 0x5a, 0x05, 0x03, 0x46, 0x02, 0x04, 0x34, 0x2b, 0x47, 0x00, 0x01, 0x00, 0x27, 0x00, 0x00, 0x01, 0xaf, 0x02, 0x18, 0x00, 0x09, - 0x00, 0x29, 0x40, 0x26, 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x03, - 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, - 0x21, 0x01, 0xaf, 0xfe, 0x78, 0x01, 0x20, 0xfe, 0xf1, 0x01, 0x70, 0xfe, 0xe4, 0x01, 0x23, 0x3a, 0x01, 0x9a, 0x44, 0x42, 0xfe, 0x6e, 0x00, 0x01, 0x00, 0x1c, - 0xff, 0x62, 0x01, 0x5c, 0x02, 0xca, 0x00, 0x1d, 0x00, 0x2c, 0x40, 0x29, 0x16, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, 0x4e, 0x1b, 0x11, 0x15, 0x11, 0x15, 0x10, 0x06, 0x0d, - 0x1c, 0x2b, 0x05, 0x26, 0x26, 0x35, 0x35, 0x34, 0x26, 0x23, 0x35, 0x36, 0x36, 0x35, 0x35, 0x34, 0x36, 0x33, 0x15, 0x06, 0x06, 0x15, 0x15, 0x14, 0x07, 0x15, - 0x16, 0x15, 0x15, 0x14, 0x16, 0x17, 0x01, 0x5c, 0x5c, 0x6a, 0x3f, 0x3b, 0x3b, 0x3f, 0x6e, 0x58, 0x34, 0x3b, 0x6d, 0x6d, 0x3a, 0x35, 0x9e, 0x01, 0x4e, 0x50, - 0x93, 0x33, 0x2b, 0x49, 0x01, 0x2a, 0x32, 0x94, 0x50, 0x4e, 0x48, 0x01, 0x2c, 0x31, 0x90, 0x67, 0x13, 0x06, 0x13, 0x67, 0x93, 0x31, 0x2b, 0x01, 0x00, 0x01, - 0x00, 0xef, 0xff, 0x0f, 0x01, 0x38, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x28, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x01, - 0x01, 0x6f, 0x01, 0x4e, 0x1b, 0x40, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x85, 0x00, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x59, 0xb4, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, - 0x13, 0x33, 0x11, 0x23, 0xef, 0x49, 0x49, 0x02, 0xf8, 0xfc, 0x17, 0x00, 0x00, 0x01, 0x00, 0x20, 0xff, 0x62, 0x01, 0x60, 0x02, 0xca, 0x00, 0x1d, 0x00, 0x2c, - 0x40, 0x29, 0x06, 0x01, 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, 0x00, 0x01, 0x01, - 0x02, 0x61, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x15, 0x11, 0x15, 0x11, 0x1b, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x17, 0x36, 0x36, 0x35, 0x35, 0x34, 0x37, 0x35, - 0x26, 0x35, 0x35, 0x34, 0x26, 0x27, 0x35, 0x16, 0x16, 0x15, 0x15, 0x14, 0x16, 0x33, 0x15, 0x06, 0x06, 0x15, 0x15, 0x14, 0x06, 0x23, 0x20, 0x34, 0x3b, 0x6d, - 0x6d, 0x3a, 0x35, 0x5c, 0x6a, 0x3f, 0x3b, 0x3b, 0x3f, 0x6e, 0x58, 0x56, 0x02, 0x2b, 0x31, 0x91, 0x67, 0x13, 0x06, 0x13, 0x67, 0x92, 0x31, 0x2b, 0x01, 0x48, - 0x01, 0x4e, 0x50, 0x92, 0x33, 0x2b, 0x49, 0x01, 0x2a, 0x32, 0x95, 0x4f, 0x4f, 0x00, 0x00, 0x01, 0x00, 0x32, 0x01, 0x1f, 0x02, 0x09, 0x01, 0xa2, 0x00, 0x17, - 0x00, 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, 0x02, 0x01, 0x13, 0x01, 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, - 0x00, 0x02, 0x00, 0x03, 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, 0x03, 0x51, 0x24, 0x24, - 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, 0x33, - 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x01, 0x0d, 0x24, 0x2f, 0x16, 0x1c, 0x3e, 0x18, 0x30, 0x48, 0x1d, 0x39, 0x2e, 0x24, 0x2f, 0x15, 0x1d, 0x3e, - 0x18, 0x31, 0x47, 0x1c, 0x3b, 0x01, 0x3f, 0x10, 0x0b, 0x22, 0x19, 0x4e, 0x35, 0x0c, 0x14, 0x10, 0x0b, 0x22, 0x19, 0x4d, 0x36, 0x0d, 0x00, 0x01, 0x00, 0x18, - 0x01, 0xa0, 0x01, 0x33, 0x03, 0x55, 0x00, 0x19, 0x00, 0x30, 0x40, 0x2d, 0x0e, 0x01, 0x01, 0x02, 0x0d, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, 0x03, 0x4c, - 0x00, 0x02, 0x00, 0x01, 0x03, 0x02, 0x01, 0x69, 0x00, 0x03, 0x00, 0x00, 0x03, 0x57, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x00, 0x4f, 0x16, 0x25, - 0x28, 0x10, 0x04, 0x0c, 0x1a, 0x2b, 0x01, 0x21, 0x35, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, - 0x14, 0x06, 0x07, 0x07, 0x33, 0x01, 0x32, 0xfe, 0xe6, 0x73, 0x29, 0x29, 0x0f, 0x25, 0x1e, 0x1e, 0x31, 0x1a, 0x23, 0x1d, 0x45, 0x2b, 0x40, 0x49, 0x3b, 0x38, - 0x51, 0xc3, 0x01, 0xa0, 0x36, 0x70, 0x27, 0x31, 0x27, 0x16, 0x20, 0x20, 0x17, 0x14, 0x2e, 0x19, 0x1e, 0x3f, 0x37, 0x31, 0x4e, 0x35, 0x4d, 0x00, 0x00, 0x01, - 0x00, 0x11, 0x01, 0x98, 0x01, 0x41, 0x03, 0x55, 0x00, 0x28, 0x00, 0x4d, 0x40, 0x4a, 0x26, 0x01, 0x05, 0x00, 0x25, 0x01, 0x04, 0x05, 0x06, 0x01, 0x03, 0x04, - 0x11, 0x01, 0x02, 0x03, 0x10, 0x01, 0x01, 0x02, 0x05, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x69, 0x00, 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, - 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x01, 0x00, 0x23, 0x21, 0x1d, 0x1b, 0x1a, 0x18, 0x14, - 0x12, 0x0e, 0x0c, 0x00, 0x28, 0x01, 0x28, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, - 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, - 0xa5, 0x47, 0x48, 0x2b, 0x1e, 0x27, 0x2f, 0x54, 0x59, 0x25, 0x40, 0x1e, 0x46, 0x3e, 0x34, 0x30, 0x3a, 0x34, 0x39, 0x39, 0x32, 0x2f, 0x29, 0x1d, 0x1f, 0x35, - 0x1b, 0x24, 0x1f, 0x45, 0x03, 0x55, 0x3e, 0x30, 0x28, 0x34, 0x0a, 0x03, 0x07, 0x33, 0x29, 0x3a, 0x49, 0x0d, 0x0f, 0x3f, 0x22, 0x29, 0x23, 0x24, 0x21, 0x37, - 0x27, 0x1f, 0x20, 0x1d, 0x15, 0x11, 0x2e, 0x17, 0x1a, 0x00, 0x00, 0x01, 0x00, 0x25, 0x01, 0xa0, 0x00, 0xf0, 0x03, 0x4c, 0x00, 0x0c, 0x00, 0x27, 0x40, 0x24, - 0x0b, 0x0a, 0x06, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x00, 0x00, 0x01, 0x57, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, - 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x11, 0x03, 0x0c, 0x17, 0x2b, 0x13, 0x11, 0x23, 0x11, 0x34, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0xf0, 0x47, - 0x03, 0x01, 0x0a, 0x18, 0x0d, 0x36, 0x23, 0x82, 0x03, 0x4c, 0xfe, 0x54, 0x01, 0x14, 0x1a, 0x2a, 0x15, 0x09, 0x15, 0x09, 0x27, 0x31, 0x5c, 0x00, 0x00, 0x01, - 0xff, 0x41, 0x00, 0x00, 0x01, 0x40, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x01, 0x01, 0x23, 0x01, 0x01, 0x40, 0xfe, 0x4c, 0x4b, 0x01, 0xb4, 0x02, 0xca, 0xfd, 0x36, - 0x02, 0xca, 0x00, 0x02, 0x00, 0x0a, 0x01, 0xa0, 0x01, 0x55, 0x03, 0x4f, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x30, 0x40, 0x2d, 0x0e, 0x01, 0x04, 0x03, 0x06, 0x01, - 0x00, 0x04, 0x02, 0x4c, 0x00, 0x03, 0x04, 0x01, 0x03, 0x57, 0x05, 0x01, 0x04, 0x02, 0x01, 0x00, 0x01, 0x04, 0x00, 0x67, 0x00, 0x03, 0x03, 0x01, 0x5f, 0x00, - 0x01, 0x03, 0x01, 0x4f, 0x18, 0x11, 0x12, 0x11, 0x11, 0x10, 0x06, 0x0c, 0x1c, 0x2b, 0x01, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x13, 0x33, 0x11, 0x33, 0x27, - 0x34, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x33, 0x01, 0x55, 0x3d, 0x4b, 0xc3, 0xc5, 0x49, 0x3d, 0x88, 0x02, 0x01, 0x05, 0x20, 0x0b, 0x50, 0x7d, 0x02, 0x00, - 0x60, 0x60, 0x34, 0x01, 0x1b, 0xfe, 0xed, 0x5d, 0x15, 0x38, 0x18, 0x0b, 0x31, 0x11, 0x75, 0x00, 0x00, 0x01, 0x00, 0x1e, 0x01, 0x97, 0x01, 0x40, 0x03, 0x4c, - 0x00, 0x1e, 0x00, 0x42, 0x40, 0x3f, 0x1d, 0x03, 0x02, 0x04, 0x01, 0x1c, 0x10, 0x02, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x03, 0x4c, 0x06, 0x01, 0x05, 0x00, - 0x00, 0x01, 0x05, 0x00, 0x67, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x69, 0x00, 0x03, 0x02, 0x02, 0x03, 0x59, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, - 0x03, 0x02, 0x51, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1e, 0x24, 0x25, 0x24, 0x23, 0x11, 0x07, 0x0c, 0x1b, 0x2b, 0x01, 0x15, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, - 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x37, 0x01, 0x2b, 0xb9, - 0x09, 0x0c, 0x1d, 0x11, 0x43, 0x5a, 0x54, 0x52, 0x20, 0x46, 0x16, 0x1b, 0x45, 0x1a, 0x2d, 0x35, 0x35, 0x30, 0x1a, 0x25, 0x0f, 0x1f, 0x10, 0x03, 0x4c, 0x37, - 0x6d, 0x02, 0x04, 0x44, 0x40, 0x46, 0x4d, 0x0d, 0x0d, 0x43, 0x10, 0x13, 0x28, 0x2b, 0x26, 0x2a, 0x08, 0x04, 0x14, 0xd0, 0x00, 0x01, 0x00, 0x1c, 0x01, 0xa0, - 0x01, 0x43, 0x03, 0x4c, 0x00, 0x06, 0x00, 0x2a, 0x40, 0x27, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, - 0x23, 0x35, 0x21, 0x15, 0x03, 0x4f, 0xaa, 0xdd, 0x01, 0x27, 0xaa, 0x01, 0xa0, 0x01, 0x70, 0x3c, 0x31, 0xfe, 0x85, 0x00, 0x00, 0x03, 0x00, 0x19, 0x01, 0x98, - 0x01, 0x45, 0x03, 0x54, 0x00, 0x18, 0x00, 0x24, 0x00, 0x31, 0x00, 0x38, 0x40, 0x35, 0x1f, 0x12, 0x06, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x04, 0x01, 0x00, 0x05, - 0x01, 0x02, 0x03, 0x00, 0x02, 0x69, 0x00, 0x03, 0x01, 0x01, 0x03, 0x59, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x03, 0x01, 0x51, 0x1a, 0x19, 0x01, 0x00, - 0x2c, 0x2a, 0x19, 0x24, 0x1a, 0x24, 0x0d, 0x0b, 0x00, 0x18, 0x01, 0x18, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, - 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, - 0x26, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0xb0, 0x37, 0x50, 0x2a, 0x1e, 0x27, 0x2f, 0x53, 0x42, 0x49, 0x4e, 0x2d, - 0x20, 0x1f, 0x21, 0x26, 0x3f, 0x24, 0x20, 0x24, 0x28, 0x1e, 0x1d, 0x25, 0x24, 0x2f, 0x21, 0x22, 0x28, 0x29, 0x2a, 0x28, 0x2d, 0x26, 0x03, 0x54, 0x35, 0x37, - 0x25, 0x30, 0x10, 0x10, 0x37, 0x29, 0x38, 0x43, 0x40, 0x38, 0x29, 0x36, 0x11, 0x14, 0x2b, 0x26, 0x24, 0x31, 0x1a, 0x37, 0x1d, 0x1a, 0x1a, 0x22, 0x0c, 0x0b, - 0x21, 0x1c, 0x1a, 0x1d, 0xb8, 0x10, 0x28, 0x1d, 0x1c, 0x24, 0x24, 0x1c, 0x1d, 0x26, 0x0d, 0x00, 0x00, 0x02, 0x00, 0x13, 0x01, 0x98, 0x01, 0x4a, 0x03, 0x54, - 0x00, 0x0b, 0x00, 0x15, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, - 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x0d, 0x0c, 0x01, 0x00, 0x11, 0x0f, 0x0c, 0x15, 0x0d, 0x15, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, - 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x27, 0x32, 0x35, 0x34, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0xae, - 0x4d, 0x4e, 0x4a, 0x51, 0x4d, 0x4f, 0x49, 0x53, 0x54, 0x54, 0x2b, 0x27, 0x27, 0x01, 0x98, 0x73, 0x6c, 0x6a, 0x73, 0x72, 0x6b, 0x6a, 0x75, 0x3f, 0xa0, 0x9f, - 0x4f, 0x51, 0x4f, 0x50, 0x00, 0x02, 0x00, 0x14, 0x01, 0x98, 0x01, 0x4c, 0x03, 0x54, 0x00, 0x1c, 0x00, 0x29, 0x00, 0x4a, 0x40, 0x47, 0x03, 0x01, 0x01, 0x00, - 0x04, 0x01, 0x02, 0x01, 0x0b, 0x01, 0x04, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 0x69, 0x00, 0x02, 0x07, 0x01, 0x04, 0x05, 0x02, - 0x04, 0x69, 0x00, 0x05, 0x03, 0x03, 0x05, 0x59, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x05, 0x03, 0x51, 0x1e, 0x1d, 0x01, 0x00, 0x25, 0x23, 0x1d, 0x29, - 0x1e, 0x29, 0x16, 0x14, 0x10, 0x0e, 0x08, 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x17, 0x15, 0x26, 0x26, 0x23, 0x22, 0x06, - 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, - 0x32, 0x36, 0x35, 0x34, 0x26, 0xec, 0x0e, 0x23, 0x0b, 0x0b, 0x22, 0x13, 0x36, 0x3e, 0x1b, 0x03, 0x04, 0x0e, 0x36, 0x29, 0x3b, 0x4a, 0x52, 0x45, 0x44, 0x5d, - 0x12, 0x2f, 0x54, 0x0d, 0x2b, 0x32, 0x14, 0x28, 0x1e, 0x26, 0x2f, 0x29, 0x03, 0x54, 0x04, 0x03, 0x3b, 0x04, 0x05, 0x29, 0x46, 0x2a, 0x15, 0x1d, 0x46, 0x40, - 0x46, 0x50, 0x5f, 0x61, 0x2f, 0x5a, 0x48, 0x2b, 0xd7, 0x2d, 0x1a, 0x18, 0x2f, 0x1e, 0x2d, 0x2e, 0x26, 0x2b, 0x00, 0x02, 0x00, 0x11, 0x01, 0x98, 0x01, 0x49, - 0x03, 0x56, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x4a, 0x40, 0x47, 0x12, 0x01, 0x03, 0x05, 0x0b, 0x01, 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, - 0x00, 0x07, 0x01, 0x04, 0x05, 0x00, 0x04, 0x69, 0x00, 0x05, 0x00, 0x03, 0x02, 0x05, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, - 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, 0x27, 0x1d, 0x27, 0x17, 0x15, 0x0f, 0x0d, 0x09, 0x07, 0x00, 0x1b, 0x01, 0x1b, - 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, - 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xa8, 0x44, 0x5d, 0x12, 0x2d, 0x54, 0x42, 0x25, 0x1a, - 0x0b, 0x20, 0x18, 0x37, 0x3c, 0x1b, 0x02, 0x05, 0x0d, 0x33, 0x28, 0x40, 0x4a, 0x52, 0x45, 0x24, 0x2f, 0x27, 0x2a, 0x2b, 0x33, 0x2d, 0x03, 0x56, 0x5c, 0x63, - 0x2f, 0x5b, 0x49, 0x2c, 0x07, 0x3c, 0x04, 0x06, 0x2c, 0x47, 0x28, 0x13, 0x1f, 0x48, 0x40, 0x41, 0x53, 0x39, 0x2c, 0x2c, 0x26, 0x2e, 0x2d, 0x1a, 0x2a, 0x3b, - 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x02, 0xdb, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x47, 0x01, 0x58, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x0f, 0x00, 0x00, 0x02, 0x0d, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, - 0x00, 0x00, 0x02, 0x05, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, - 0x03, 0x65, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x58, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x02, 0xb0, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x5d, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x58, 0x00, 0x00, 0x00, 0x07, - 0x00, 0x4d, 0x02, 0xb0, 0x00, 0x00, 0xff, 0xff, 0x00, 0x13, 0xff, 0xf8, 0x01, 0x4a, 0x01, 0xb4, 0x03, 0x07, 0x00, 0x68, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, - 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x25, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xac, 0x03, 0x07, 0x00, 0x62, 0x00, 0x00, - 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x18, 0x00, 0x00, 0x01, 0x33, 0x01, 0xb5, 0x03, 0x07, - 0x00, 0x60, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0xff, 0xf8, 0x01, 0x41, - 0x01, 0xb5, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0a, - 0x00, 0x00, 0x01, 0x55, 0x01, 0xaf, 0x03, 0x07, 0x00, 0x64, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, - 0xff, 0xff, 0x00, 0x1e, 0xff, 0xf7, 0x01, 0x40, 0x01, 0xac, 0x03, 0x07, 0x00, 0x65, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, - 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x14, 0xff, 0xf8, 0x01, 0x4c, 0x01, 0xb4, 0x03, 0x07, 0x00, 0x69, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, - 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x43, 0x01, 0xac, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xfe, 0x60, - 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x19, 0xff, 0xf8, 0x01, 0x45, 0x01, 0xb4, 0x03, 0x07, 0x00, 0x67, - 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0xff, 0xf8, 0x01, 0x49, 0x01, 0xb6, - 0x03, 0x07, 0x00, 0x6a, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x13, 0x01, 0x16, - 0x01, 0x4a, 0x02, 0xd2, 0x03, 0x07, 0x00, 0x68, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, - 0x00, 0x25, 0x01, 0x1e, 0x00, 0xf0, 0x02, 0xca, 0x03, 0x07, 0x00, 0x62, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, - 0x2b, 0x00, 0xff, 0xff, 0x00, 0x18, 0x01, 0x1e, 0x01, 0x33, 0x02, 0xd3, 0x03, 0x07, 0x00, 0x60, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, - 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0x01, 0x16, 0x01, 0x41, 0x02, 0xd3, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, - 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x01, 0x1e, 0x01, 0x55, 0x02, 0xcd, 0x03, 0x07, 0x00, 0x64, 0x00, 0x00, - 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x01, 0x15, 0x01, 0x40, 0x02, 0xca, 0x03, 0x07, - 0x00, 0x65, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x14, 0x01, 0x16, 0x01, 0x4c, - 0x02, 0xd2, 0x03, 0x07, 0x00, 0x69, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1c, - 0x01, 0x1e, 0x01, 0x43, 0x02, 0xca, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, - 0xff, 0xff, 0x00, 0x19, 0x01, 0x16, 0x01, 0x45, 0x02, 0xd2, 0x03, 0x07, 0x00, 0x67, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xff, 0x7e, - 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0x01, 0x16, 0x01, 0x49, 0x02, 0xd4, 0x03, 0x07, 0x00, 0x6a, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, - 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, 0x01, 0x04, 0x00, 0x18, 0x00, 0x66, 0x00, 0x06, 0x00, 0x02, - 0x00, 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x89, 0x0e, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x54, - 0x00, 0xa8, 0x01, 0x27, 0x01, 0xbc, 0x02, 0x4b, 0x02, 0x66, 0x02, 0x8a, 0x02, 0xae, 0x02, 0xe6, 0x03, 0x0e, 0x03, 0x2e, 0x03, 0x49, 0x03, 0x68, 0x03, 0x84, - 0x03, 0xbd, 0x03, 0xe4, 0x04, 0x25, 0x04, 0x83, 0x04, 0xbe, 0x05, 0x11, 0x05, 0x71, 0x05, 0x96, 0x06, 0x02, 0x06, 0x63, 0x06, 0x98, 0x06, 0xcb, 0x06, 0xe1, - 0x07, 0x0c, 0x07, 0x22, 0x07, 0x7b, 0x08, 0x25, 0x08, 0x5f, 0x08, 0xb6, 0x08, 0xfc, 0x09, 0x2b, 0x09, 0x57, 0x09, 0x7c, 0x09, 0xcc, 0x09, 0xf4, 0x0a, 0x1c, - 0x0a, 0x4d, 0x0a, 0x7a, 0x0a, 0x98, 0x0a, 0xd1, 0x0b, 0x01, 0x0b, 0x3d, 0x0b, 0x79, 0x0b, 0xc2, 0x0c, 0x08, 0x0c, 0x5d, 0x0c, 0x7b, 0x0c, 0xa8, 0x0c, 0xd5, - 0x0d, 0x22, 0x0d, 0x4d, 0x0d, 0x71, 0x0d, 0x9c, 0x0d, 0xbb, 0x0d, 0xd7, 0x0d, 0xf6, 0x0e, 0x1d, 0x0e, 0x3a, 0x0e, 0x64, 0x0e, 0xdd, 0x0f, 0x55, 0x0f, 0x9b, - 0x10, 0x19, 0x10, 0x6d, 0x10, 0xc1, 0x11, 0x40, 0x11, 0x87, 0x11, 0xea, 0x12, 0x69, 0x12, 0xaf, 0x12, 0xcf, 0x13, 0x30, 0x13, 0x79, 0x13, 0xb2, 0x14, 0x1e, - 0x14, 0x83, 0x14, 0xd9, 0x15, 0x2e, 0x15, 0x75, 0x15, 0xbc, 0x15, 0xeb, 0x16, 0x37, 0x16, 0x60, 0x16, 0xa1, 0x16, 0xcc, 0x17, 0x0e, 0x17, 0x2f, 0x17, 0x71, - 0x17, 0xb6, 0x17, 0xf8, 0x18, 0x59, 0x18, 0x87, 0x18, 0xa3, 0x18, 0xde, 0x19, 0x2e, 0x19, 0x55, 0x19, 0xbb, 0x19, 0xf6, 0x1a, 0x58, 0x1a, 0xb7, 0x1a, 0xc3, - 0x1a, 0xcf, 0x1a, 0xdb, 0x1a, 0xeb, 0x1a, 0xfb, 0x1b, 0x0a, 0x1b, 0x19, 0x1b, 0x28, 0x1b, 0x37, 0x1b, 0x46, 0x1b, 0x55, 0x1b, 0x64, 0x1b, 0x73, 0x1b, 0x82, - 0x1b, 0x91, 0x1b, 0xa0, 0x1b, 0xaf, 0x1b, 0xbe, 0x1b, 0xcd, 0x1b, 0xdc, 0x1b, 0xeb, 0x1b, 0xfa, 0x1c, 0x09, 0x1c, 0x18, 0x1c, 0x27, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, 0xb1, 0xf9, 0xad, 0x18, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xd3, 0xe7, - 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc0, 0xb7, 0xfd, 0x93, 0xfe, 0x7b, 0x0a, 0xf0, 0x04, 0x2b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x58, 0x00, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x48, 0x01, 0x98, 0x00, 0x41, 0x02, 0x86, 0x00, 0x19, 0x02, 0x3c, 0x00, 0x3e, - 0x03, 0x3f, 0x00, 0x31, 0x02, 0xdc, 0x00, 0x35, 0x00, 0xe1, 0x00, 0x41, 0x01, 0x2c, 0x00, 0x28, 0x01, 0x2c, 0x00, 0x1e, 0x02, 0x27, 0x00, 0x29, 0x02, 0x3c, - 0x00, 0x32, 0x01, 0x0c, 0x00, 0x29, 0x01, 0x42, 0x00, 0x28, 0x01, 0x0c, 0x00, 0x48, 0x01, 0x74, 0x00, 0x0a, 0x02, 0x3c, 0x00, 0x31, 0x02, 0x3c, 0x00, 0x59, - 0x02, 0x3c, 0x00, 0x30, 0x02, 0x3c, 0x00, 0x2d, 0x02, 0x3c, 0x00, 0x15, 0x02, 0x3c, 0x00, 0x3f, 0x02, 0x3c, 0x00, 0x37, 0x02, 0x3c, 0x00, 0x2c, 0x02, 0x3c, - 0x00, 0x31, 0x02, 0x3c, 0x00, 0x32, 0x01, 0x0c, 0x00, 0x48, 0x01, 0x0c, 0x00, 0x1f, 0x02, 0x3c, 0x00, 0x32, 0x02, 0x3c, 0x00, 0x38, 0x02, 0x3c, 0x00, 0x32, - 0x01, 0xb2, 0x00, 0x0c, 0x03, 0x83, 0x00, 0x3a, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x8a, 0x00, 0x61, 0x02, 0x78, 0x00, 0x3d, 0x02, 0xda, 0x00, 0x61, 0x02, 0x2c, - 0x00, 0x61, 0x02, 0x07, 0x00, 0x61, 0x02, 0xd8, 0x00, 0x3d, 0x02, 0xe5, 0x00, 0x61, 0x01, 0x53, 0x00, 0x28, 0x01, 0x11, 0xff, 0xb2, 0x02, 0x6b, 0x00, 0x61, - 0x02, 0x0c, 0x00, 0x61, 0x03, 0x8b, 0x00, 0x61, 0x02, 0xf8, 0x00, 0x61, 0x03, 0x0d, 0x00, 0x3d, 0x02, 0x5d, 0x00, 0x61, 0x03, 0x0d, 0x00, 0x3d, 0x02, 0x6e, - 0x00, 0x61, 0x02, 0x25, 0x00, 0x33, 0x02, 0x2c, 0x00, 0x0a, 0x02, 0xdb, 0x00, 0x5a, 0x02, 0x58, 0x00, 0x00, 0x03, 0xa2, 0x00, 0x0c, 0x02, 0x4a, 0x00, 0x04, - 0x02, 0x36, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x26, 0x01, 0x49, 0x00, 0x50, 0x01, 0x74, 0x00, 0x0a, 0x01, 0x49, 0x00, 0x19, 0x02, 0x3c, 0x00, 0x26, 0x01, 0xbc, - 0xff, 0xfe, 0x01, 0x19, 0x00, 0x28, 0x02, 0x31, 0x00, 0x2e, 0x02, 0x67, 0x00, 0x55, 0x01, 0xe0, 0x00, 0x37, 0x02, 0x67, 0x00, 0x37, 0x02, 0x34, 0x00, 0x37, - 0x01, 0x58, 0x00, 0x0f, 0x02, 0x67, 0x00, 0x37, 0x02, 0x6a, 0x00, 0x55, 0x01, 0x02, 0x00, 0x4e, 0x01, 0x02, 0xff, 0xc9, 0x02, 0x16, 0x00, 0x55, 0x01, 0x02, - 0x00, 0x55, 0x03, 0xa7, 0x00, 0x55, 0x02, 0x6a, 0x00, 0x55, 0x02, 0x5d, 0x00, 0x37, 0x02, 0x67, 0x00, 0x55, 0x02, 0x67, 0x00, 0x37, 0x01, 0x9d, 0x00, 0x55, - 0x01, 0xdf, 0x00, 0x33, 0x01, 0x69, 0x00, 0x10, 0x02, 0x6a, 0x00, 0x4f, 0x01, 0xfc, 0x00, 0x00, 0x03, 0x12, 0x00, 0x0b, 0x02, 0x11, 0x00, 0x12, 0x01, 0xfe, - 0x00, 0x01, 0x01, 0xd6, 0x00, 0x27, 0x01, 0x7c, 0x00, 0x1c, 0x02, 0x27, 0x00, 0xef, 0x01, 0x7c, 0x00, 0x20, 0x02, 0x3c, 0x00, 0x32, 0x01, 0x5e, 0x00, 0x18, - 0x01, 0x5e, 0x00, 0x11, 0x01, 0x5e, 0x00, 0x25, 0x00, 0x82, 0xff, 0x41, 0x01, 0x5e, 0x00, 0x0a, 0x01, 0x5e, 0x00, 0x1e, 0x01, 0x5e, 0x00, 0x1c, 0x01, 0x5e, - 0x00, 0x19, 0x01, 0x5e, 0x00, 0x13, 0x01, 0x5e, 0x00, 0x14, 0x01, 0x5e, 0x00, 0x11, 0x02, 0xb0, 0x00, 0x0f, 0x02, 0x5a, 0x00, 0x0f, 0x02, 0x5a, 0x00, 0x0f, - 0x03, 0xb2, 0x00, 0x0f, 0x03, 0xb2, 0x00, 0x0f, 0x01, 0x5e, 0x00, 0x13, 0x00, 0x25, 0x00, 0x18, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x1c, - 0x00, 0x19, 0x00, 0x11, 0x00, 0x13, 0x00, 0x25, 0x00, 0x18, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x19, 0x00, 0x11, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x0b, 0x18, 0xfd, 0x93, 0xfd, 0x94, 0x0a, 0xf0, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x04, 0x02, 0x41, 0x01, 0x90, 0x00, 0x05, 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x00, - 0x00, 0x4b, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x32, 0x01, 0x42, 0x00, 0x00, 0x02, 0x0b, 0x05, 0x02, 0x04, 0x05, 0x04, 0x02, 0x02, 0x04, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0xc0, 0x00, 0x20, 0x00, 0x7e, - 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x02, 0xca, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, - 0x34, 0x1b, 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, - 0x21, 0xb0, 0x00, 0x59, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, - 0x02, 0x2c, 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, - 0xb1, 0x02, 0x14, 0x43, 0x42, 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, 0x04, - 0x50, 0x78, 0xb2, 0x02, 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, 0x20, 0xb0, - 0x02, 0x43, 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, - 0xb0, 0x04, 0x2c, 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x1b, - 0x20, 0x64, 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, 0x21, 0xb0, 0x03, 0x25, - 0x59, 0x52, 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, - 0xb0, 0x38, 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, - 0x20, 0xb0, 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, - 0x60, 0x1b, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, - 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, 0xb0, - 0x1e, 0x50, 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, - 0x01, 0x2b, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, 0x20, 0x45, - 0x20, 0xb0, 0x04, 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, 0x59, 0xb0, 0x01, - 0x60, 0x2d, 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, - 0x58, 0x1b, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, 0xb0, 0x08, 0x43, 0x20, - 0x8a, 0x20, 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, - 0x20, 0xb0, 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, - 0x43, 0x2b, 0xb2, 0x00, 0x02, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, - 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, - 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, 0x0e, - 0x00, 0x43, 0x45, 0x42, 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, - 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, - 0x61, 0x20, 0x64, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, 0x23, 0xb0, 0x00, - 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, - 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, - 0x00, 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, - 0x0c, 0x00, 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, - 0xb0, 0x10, 0x2c, 0xb0, 0x01, 0x60, 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, - 0xb0, 0x00, 0x52, 0x58, 0x20, 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, 0x00, - 0x63, 0x8a, 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, - 0x64, 0x44, 0x59, 0x24, 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x1b, 0x21, - 0x59, 0x24, 0xb0, 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, 0x61, 0x42, 0xb0, - 0x11, 0x2b, 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, - 0x03, 0x25, 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x23, 0xb0, 0x01, - 0x61, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, - 0x21, 0x59, 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, - 0x63, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, - 0x00, 0x13, 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, - 0x54, 0x58, 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, 0x00, - 0x11, 0x00, 0x13, 0x00, 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, - 0x59, 0x2d, 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, - 0xb0, 0x19, 0x2c, 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, 0x2d, 0xb0, 0x1c, - 0x2c, 0xb1, 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, - 0x09, 0x15, 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, - 0x01, 0x5d, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, - 0x20, 0x2e, 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, - 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, - 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, 0x01, - 0x00, 0x11, 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, - 0xb0, 0x22, 0x2c, 0xb1, 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, 0xb0, 0x25, - 0x2c, 0xb1, 0x04, 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, 0x28, 0x2c, 0xb1, - 0x07, 0x20, 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, - 0x01, 0x60, 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x01, 0x60, 0xb0, - 0x2e, 0x2a, 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, - 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, - 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, - 0x23, 0x61, 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, - 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, - 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x34, - 0x2c, 0x20, 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, - 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, - 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3e, 0x23, 0x38, 0xb1, - 0x34, 0x01, 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, - 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, - 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, - 0x60, 0xb0, 0x00, 0x43, 0x61, 0xb0, 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, - 0x42, 0xb0, 0x02, 0x25, 0x49, 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, 0x01, - 0x15, 0x14, 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, - 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, - 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, - 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, - 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, - 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, - 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, - 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, - 0x02, 0x25, 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, - 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, 0x25, - 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, 0x60, 0x64, - 0x23, 0xb0, 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, - 0x3c, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x3c, 0x38, 0x2d, - 0xb0, 0x3d, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, - 0x38, 0x2d, 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, - 0x58, 0x2e, 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, - 0x23, 0x47, 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, - 0x1b, 0x21, 0x59, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, - 0x20, 0x3c, 0x8a, 0x38, 0x23, 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, 0x23, - 0x47, 0x23, 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, - 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, - 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, - 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, - 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, - 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, - 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, - 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, - 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, - 0xb0, 0x04, 0x26, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, 0x20, - 0x3c, 0x20, 0x2e, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, - 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, - 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, 0xb0, 0x06, 0x43, - 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, - 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, - 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, - 0x23, 0x38, 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, - 0xb1, 0x00, 0x3a, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, - 0x42, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, - 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, - 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, 0xb0, 0x4c, - 0x2c, 0xb0, 0x39, 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, - 0x2d, 0xb0, 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, - 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x53, 0x2c, 0xb2, - 0x00, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, - 0xb2, 0x01, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, - 0xb0, 0x59, 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, - 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, - 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, 0x2d, - 0xb0, 0x61, 0x2c, 0xb2, 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, 0x48, 0x2b, - 0x2d, 0xb0, 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, - 0x2b, 0x2d, 0xb0, 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x69, 0x2c, 0xb3, - 0x01, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x44, 0x2b, 0x2d, - 0xb0, 0x6c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, - 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, - 0x40, 0x2b, 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, - 0x2b, 0x2d, 0xb0, 0x73, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, - 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, - 0xb0, 0x77, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, - 0x00, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, - 0x41, 0x2b, 0x2d, 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, - 0x2b, 0x2d, 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, - 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, 0x2c, 0xb1, 0x01, 0x3e, - 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, - 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, - 0xb0, 0x87, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, - 0x01, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, - 0x50, 0x58, 0xb0, 0x06, 0x1b, 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, 0x50, - 0x78, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, 0xb9, 0x08, - 0x00, 0x08, 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, 0x51, 0x41, 0x00, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, - 0x42, 0x40, 0x14, 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, 0x02, 0x56, 0x06, 0x46, 0x08, 0x3a, 0x06, 0x32, 0x04, 0x24, 0x07, 0x09, 0x0a, 0x2a, 0xb1, 0x00, - 0x07, 0x42, 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x4e, 0x06, 0x40, 0x04, 0x36, 0x02, 0x2b, 0x05, 0x09, 0x0a, 0x2a, 0xb1, - 0x00, 0x10, 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, 0x11, 0xc0, 0x0e, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, - 0x0b, 0x2a, 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, - 0x00, 0x09, 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, - 0x44, 0xb1, 0x28, 0x01, 0x88, 0x51, 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, - 0xba, 0x08, 0x80, 0x00, 0x01, 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, 0x06, - 0x7a, 0x06, 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x48, 0x06, 0x3c, 0x04, 0x34, 0x02, 0x26, 0x05, 0x09, 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, - 0xb1, 0x02, 0x00, 0x44, 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x5d, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, - 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4b, 0x00, 0x4b, 0x02, 0x3c, 0x00, 0x00, 0x02, 0x45, 0xff, 0xf8, 0x00, 0x5c, 0x00, 0x5c, - 0x00, 0x4b, 0x00, 0x4b, 0x02, 0x3c, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x45, 0x02, 0x45, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x49, - 0x00, 0x49, 0x02, 0xca, 0xff, 0xf6, 0x02, 0xf8, 0x02, 0x18, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xfd, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, - 0x00, 0x48, 0x00, 0x48, 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x48, - 0x00, 0x48, 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0x00, 0x00, 0x02, 0xec, 0x02, 0x18, - 0x00, 0x00, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xec, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x2c, 0x00, 0x2c, 0x01, 0x2a, - 0xff, 0x7e, 0x01, 0x61, 0x00, 0xe2, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x32, 0xff, 0x76, 0x01, 0x61, 0x00, 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x3b, 0x00, 0x3b, - 0x00, 0x2c, 0x00, 0x2c, 0x02, 0xcb, 0x01, 0xa0, 0x02, 0xe0, 0x02, 0x61, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe0, 0x01, 0x98, 0x02, 0xe0, 0x02, 0x67, 0x01, 0x19, - 0x00, 0x8f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, - 0x00, 0x01, 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x0e, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, - 0x00, 0x36, 0x00, 0xd6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x22, 0x01, 0x0c, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, - 0x01, 0x2e, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x20, 0x01, 0x82, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, - 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, - 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, - 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, - 0x00, 0x73, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, - 0x00, 0x6d, 0x00, 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, - 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, - 0x00, 0x72, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, - 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, - 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, - 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x4e, 0x00, 0x6f, - 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, - 0x00, 0x61, 0x00, 0x72, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, - 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x68, 0x00, 0x69, - 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, - 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, - 0x00, 0x2d, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9c, - 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, - 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x1f, 0x00, 0x01, - 0x00, 0x22, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x42, 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x05, 0x00, 0x18, 0x00, 0x18, - 0x00, 0x18, 0x00, 0x20, 0x00, 0x20, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x2d, 0x00, 0x02, - 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x3b, 0x00, 0x01, 0x02, 0x77, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, - 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0x65, 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x06, 0x07, 0x2c, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0xf6, 0x00, 0x01, 0x00, 0x34, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, - 0x00, 0x62, 0x00, 0xe2, 0x00, 0x74, 0x00, 0x7a, 0x00, 0xb2, 0x00, 0x84, 0x00, 0x8a, 0x00, 0xb2, 0x00, 0xa8, 0x00, 0xb2, 0x00, 0xb8, 0x00, 0xdc, 0x00, 0xdc, - 0x00, 0xc2, 0x00, 0xe2, 0x00, 0xcc, 0x00, 0xd2, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xe2, 0x00, 0x01, 0x00, 0x15, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, - 0x00, 0x23, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3c, 0x00, 0x40, - 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, 0x37, 0xff, 0xec, 0x00, 0x38, 0xff, 0xec, 0x00, 0x3a, - 0xff, 0xe2, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x32, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xf6, 0x00, 0x0f, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x07, - 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, 0xec, 0x00, 0x3e, 0x00, 0x14, 0x00, 0x5e, - 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x39, 0xff, 0xec, 0x00, 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, - 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x5f, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, - 0x00, 0x14, 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, 0x04, 0x32, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x86, 0x05, 0x50, 0x00, 0x17, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, 0xff, 0xe2, - 0xff, 0xce, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xce, 0xff, 0xd8, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, - 0xff, 0xec, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xec, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xce, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x00, - 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xe2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xba, - 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xff, 0xc4, 0xff, 0xba, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, - 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x60, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, - 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x28, 0x00, 0x03, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x2c, - 0x00, 0x2d, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x42, - 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, - 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6b, 0x00, 0x02, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x09, - 0x00, 0x13, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x22, 0x00, 0x02, - 0x00, 0x24, 0x00, 0x24, 0x00, 0x08, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x26, 0x00, 0x26, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x12, 0x00, 0x2d, - 0x00, 0x2d, 0x00, 0x09, 0x00, 0x30, 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, - 0x00, 0x0c, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x0a, 0x00, 0x39, 0x00, 0x39, 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x07, - 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0e, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x49, - 0x00, 0x49, 0x00, 0x01, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0d, 0x00, 0x57, 0x00, 0x58, - 0x00, 0x05, 0x00, 0x59, 0x00, 0x59, 0x00, 0x16, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x15, - 0x00, 0x01, 0x00, 0x03, 0x00, 0x6d, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0d, 0x00, 0x12, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, - 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, - 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, - 0x00, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, - 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0d, - 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x36, 0x00, 0x6c, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, - 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x1a, 0x66, 0x72, 0x61, 0x63, 0x00, 0x20, - 0x6c, 0x69, 0x67, 0x61, 0x00, 0x2a, 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x32, 0x00, 0x10, 0x00, 0x1e, 0x00, 0x32, 0x00, 0x4a, - 0x00, 0x88, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x5f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, - 0x00, 0x01, 0x00, 0x06, 0x00, 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x69, - 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, - 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, - 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x70, 0x00, 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, 0x7a, 0x00, 0x83, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, - 0x00, 0x01, 0x00, 0x36, 0x00, 0x01, 0x00, 0x08, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6f, 0x00, 0x03, 0x00, 0x47, - 0x00, 0x4d, 0x00, 0x6e, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x6d, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6b, 0x00, 0x02, - 0x00, 0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x47}; - -const inline uint8_t FONT_ITALICS_DATA[] = { - 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x09, 0x76, 0x04, 0x22, 0x00, 0x00, 0x59, 0xdc, 0x00, 0x00, - 0x00, 0x7a, 0x47, 0x50, 0x4f, 0x53, 0x33, 0x4f, 0x0e, 0xa7, 0x00, 0x00, 0x5a, 0x58, 0x00, 0x00, 0x07, 0x4e, 0x47, 0x53, 0x55, 0x42, 0xfc, 0xd3, 0xd8, 0xce, - 0x00, 0x00, 0x61, 0xa8, 0x00, 0x00, 0x01, 0xd4, 0x4f, 0x53, 0x2f, 0x32, 0x69, 0x50, 0x5f, 0x5f, 0x00, 0x00, 0x46, 0xec, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, - 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x47, 0x4c, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, 0x20, 0x3d, 0xa5, 0x1a, 0xce, 0x00, 0x00, 0x56, 0x94, - 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, 0x0b, 0x83, 0x00, 0x00, 0x47, 0x80, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x59, 0xd4, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0x07, 0xce, 0x9d, 0x67, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x42, 0x36, - 0x68, 0x65, 0x61, 0x64, 0x28, 0x38, 0xd8, 0x22, 0x00, 0x00, 0x44, 0x8c, 0x00, 0x00, 0x00, 0x36, 0x68, 0x68, 0x65, 0x61, 0x0d, 0x3b, 0x0b, 0x91, 0x00, 0x00, - 0x46, 0xc8, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0xec, 0x2d, 0x0f, 0x0b, 0x00, 0x00, 0x44, 0xc4, 0x00, 0x00, 0x02, 0x02, 0x6c, 0x6f, 0x63, 0x61, - 0xd3, 0x44, 0xc2, 0xf3, 0x00, 0x00, 0x43, 0x74, 0x00, 0x00, 0x01, 0x16, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x5b, 0x10, 0x84, 0x00, 0x00, 0x43, 0x54, 0x00, 0x00, - 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x5c, 0x42, 0x2a, 0x00, 0x00, 0x57, 0xc0, 0x00, 0x00, 0x01, 0xf4, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x93, 0x00, 0x32, - 0x00, 0x00, 0x59, 0xb4, 0x00, 0x00, 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0xff, 0x8d, 0x0b, 0xc2, 0x00, 0x00, 0x55, 0x8c, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, - 0x00, 0x14, 0xff, 0xf2, 0x01, 0x13, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x2f, 0x40, 0x2c, 0x04, 0x01, 0x01, 0x00, 0x03, 0x00, 0x01, 0x03, 0x80, 0x00, - 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x05, 0x04, 0x00, 0x00, 0x0a, 0x08, 0x04, 0x0e, 0x05, 0x0e, - 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x37, 0x13, 0x33, 0x03, 0x07, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x4d, 0x5b, - 0x6b, 0x7f, 0x4b, 0x35, 0x24, 0x27, 0x17, 0x1c, 0x23, 0xc9, 0x02, 0x01, 0xfd, 0xff, 0xd7, 0x36, 0x20, 0x31, 0x1c, 0x1a, 0x1d, 0x34, 0x00, 0x02, 0x00, 0x6d, - 0x01, 0xc8, 0x01, 0x9c, 0x02, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x40, 0x21, 0x05, 0x03, 0x04, 0x03, 0x01, 0x01, 0x00, 0x5f, 0x02, 0x01, 0x00, 0x00, - 0x6a, 0x01, 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x01, 0x13, 0x33, 0x03, - 0x23, 0x13, 0x33, 0x03, 0x01, 0x19, 0x23, 0x60, 0x4b, 0xe4, 0x23, 0x60, 0x4b, 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x02, - 0x00, 0x1e, 0x00, 0x00, 0x02, 0x8e, 0x02, 0xca, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, 0x40, 0x44, 0x07, 0x05, 0x02, 0x03, 0x0f, 0x08, 0x02, 0x02, 0x01, 0x03, - 0x02, 0x68, 0x0e, 0x09, 0x02, 0x01, 0x0c, 0x0a, 0x02, 0x00, 0x0b, 0x01, 0x00, 0x67, 0x06, 0x01, 0x04, 0x04, 0x6a, 0x4d, 0x10, 0x0d, 0x02, 0x0b, 0x0b, 0x6b, - 0x0b, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, 0x1c, 0x00, 0x1b, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x0d, 0x1f, 0x2b, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, 0x07, 0x23, - 0x07, 0x33, 0x07, 0x23, 0x07, 0x23, 0x37, 0x23, 0x07, 0x13, 0x33, 0x37, 0x23, 0x61, 0x3b, 0x7e, 0x06, 0x8b, 0x30, 0x86, 0x06, 0x92, 0x3c, 0x48, 0x3d, 0x90, - 0x3e, 0x44, 0x3c, 0x80, 0x07, 0x8d, 0x2f, 0x8a, 0x06, 0x97, 0x3c, 0x48, 0x3f, 0x90, 0x3d, 0x50, 0x90, 0x2d, 0x8f, 0xd1, 0x42, 0xa2, 0x41, 0xd4, 0xd4, 0xd4, - 0xd4, 0x41, 0xa2, 0x42, 0xd1, 0xd1, 0xd1, 0x01, 0x13, 0xa2, 0x00, 0x03, 0x00, 0x22, 0xff, 0xc6, 0x02, 0x0d, 0x02, 0xf6, 0x00, 0x23, 0x00, 0x2a, 0x00, 0x31, - 0x00, 0x82, 0x40, 0x14, 0x15, 0x12, 0x02, 0x03, 0x02, 0x31, 0x2a, 0x1a, 0x16, 0x08, 0x04, 0x06, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x4b, 0xb0, - 0x0c, 0x50, 0x58, 0x40, 0x19, 0x00, 0x04, 0x00, 0x00, 0x04, 0x71, 0x00, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x03, 0x03, 0x02, 0x5f, 0x00, 0x02, - 0x02, 0x6c, 0x03, 0x4e, 0x1b, 0x4b, 0xb0, 0x31, 0x50, 0x58, 0x40, 0x18, 0x00, 0x04, 0x00, 0x04, 0x86, 0x00, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, - 0x03, 0x03, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6c, 0x03, 0x4e, 0x1b, 0x40, 0x1d, 0x00, 0x04, 0x00, 0x04, 0x86, 0x00, 0x02, 0x00, 0x03, 0x01, 0x02, 0x03, 0x69, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, 0x00, 0x51, 0x59, 0x59, 0xb7, 0x19, 0x17, 0x19, 0x15, 0x10, 0x05, 0x0d, - 0x1b, 0x2b, 0x37, 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x37, 0x37, 0x33, 0x07, 0x16, 0x16, 0x17, 0x07, 0x26, - 0x26, 0x27, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x23, 0x13, 0x06, 0x06, 0x15, 0x14, 0x16, 0x17, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, - 0xbe, 0x29, 0x54, 0x1f, 0x27, 0x5c, 0x27, 0x2f, 0x3d, 0x47, 0x35, 0x5c, 0x39, 0x13, 0x41, 0x12, 0x26, 0x46, 0x1e, 0x21, 0x17, 0x3e, 0x23, 0x2d, 0x44, 0x45, - 0x38, 0x5e, 0x3b, 0x18, 0x41, 0x8c, 0x2f, 0x3b, 0x21, 0x22, 0x03, 0x2e, 0x40, 0x1f, 0x26, 0x32, 0x02, 0x13, 0x0f, 0x50, 0x14, 0x17, 0x01, 0xd7, 0x17, 0x45, - 0x3f, 0x39, 0x4c, 0x2b, 0x05, 0x55, 0x56, 0x03, 0x12, 0x10, 0x47, 0x0d, 0x15, 0x02, 0xd1, 0x19, 0x43, 0x3b, 0x3a, 0x4f, 0x2d, 0x07, 0x6d, 0x02, 0x92, 0x05, - 0x34, 0x31, 0x19, 0x2a, 0x0d, 0xfe, 0xdf, 0x06, 0x37, 0x2f, 0x1a, 0x28, 0x0f, 0x00, 0x00, 0x05, 0x00, 0x50, 0xff, 0xf6, 0x02, 0xf3, 0x02, 0xd4, 0x00, 0x11, - 0x00, 0x15, 0x00, 0x26, 0x00, 0x38, 0x00, 0x49, 0x00, 0x99, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x2c, 0x00, 0x07, 0x00, 0x09, 0x04, 0x07, 0x09, 0x6a, 0x0c, - 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x70, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x03, 0x61, - 0x0d, 0x06, 0x0b, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x34, 0x00, 0x07, 0x00, 0x09, 0x04, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, - 0x08, 0x04, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x0b, 0x01, 0x03, 0x03, 0x6b, 0x4d, 0x0e, - 0x01, 0x08, 0x08, 0x06, 0x61, 0x0d, 0x01, 0x06, 0x06, 0x71, 0x06, 0x4e, 0x59, 0x40, 0x2b, 0x3a, 0x39, 0x28, 0x27, 0x17, 0x16, 0x12, 0x12, 0x01, 0x00, 0x43, - 0x41, 0x39, 0x49, 0x3a, 0x49, 0x31, 0x2f, 0x27, 0x38, 0x28, 0x38, 0x20, 0x1e, 0x16, 0x26, 0x17, 0x26, 0x12, 0x15, 0x12, 0x15, 0x14, 0x13, 0x0a, 0x08, 0x00, - 0x11, 0x01, 0x11, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x03, 0x03, 0x01, 0x33, 0x01, 0x13, - 0x32, 0x3e, 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x14, 0x01, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x03, - 0x27, 0x32, 0x3e, 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x14, 0xc3, 0x37, 0x3c, 0x0a, 0x19, 0x2b, 0x42, 0x2e, 0x39, 0x3c, 0x0b, 0x1a, 0x2d, - 0x41, 0x7f, 0x02, 0x12, 0x4e, 0xfd, 0xee, 0x0b, 0x1a, 0x27, 0x1a, 0x0f, 0x07, 0x1a, 0x19, 0x1a, 0x26, 0x1a, 0x0f, 0x07, 0x01, 0x9a, 0x37, 0x3c, 0x0a, 0x19, - 0x2c, 0x41, 0x2e, 0x3a, 0x3c, 0x0c, 0x1a, 0x2c, 0x42, 0x26, 0x1a, 0x27, 0x1a, 0x0f, 0x07, 0x1a, 0x19, 0x1a, 0x26, 0x19, 0x0f, 0x07, 0x01, 0x14, 0x4b, 0x46, - 0x1d, 0x4e, 0x52, 0x47, 0x2b, 0x47, 0x42, 0x1b, 0x4f, 0x55, 0x4a, 0x2e, 0xfe, 0xec, 0x02, 0xca, 0xfd, 0x36, 0x01, 0x56, 0x27, 0x3d, 0x42, 0x3a, 0x0f, 0x29, - 0x25, 0x24, 0x38, 0x41, 0x3c, 0x14, 0x50, 0xfe, 0xa0, 0x4a, 0x46, 0x1e, 0x4f, 0x52, 0x46, 0x2b, 0x47, 0x41, 0x1b, 0x4f, 0x55, 0x4b, 0x2e, 0x42, 0x27, 0x3d, - 0x43, 0x39, 0x0f, 0x29, 0x25, 0x24, 0x38, 0x41, 0x3c, 0x14, 0x50, 0x00, 0x00, 0x03, 0x00, 0x20, 0xff, 0xf6, 0x02, 0x85, 0x02, 0xd5, 0x00, 0x21, 0x00, 0x2d, - 0x00, 0x38, 0x00, 0x7b, 0x40, 0x0f, 0x32, 0x14, 0x06, 0x03, 0x02, 0x04, 0x31, 0x1f, 0x1c, 0x15, 0x04, 0x05, 0x02, 0x02, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, - 0x40, 0x24, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x4d, 0x07, 0x01, - 0x05, 0x05, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, - 0x02, 0x02, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x2f, - 0x2e, 0x01, 0x00, 0x2e, 0x38, 0x2f, 0x38, 0x2a, 0x28, 0x1e, 0x1d, 0x19, 0x18, 0x0e, 0x0c, 0x00, 0x21, 0x01, 0x21, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, - 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, 0x07, - 0x17, 0x23, 0x27, 0x06, 0x06, 0x13, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x03, 0x32, 0x36, 0x37, 0x27, 0x0e, 0x02, 0x15, 0x14, 0x16, - 0xd8, 0x51, 0x67, 0x63, 0x5b, 0x13, 0x1e, 0x2d, 0x56, 0x3d, 0x49, 0x56, 0x35, 0x58, 0x35, 0x84, 0x21, 0x2e, 0x10, 0x58, 0x19, 0x46, 0x2c, 0x63, 0x68, 0x37, - 0x2f, 0x6a, 0x02, 0x20, 0x42, 0x2e, 0x28, 0x26, 0x31, 0x37, 0x18, 0x35, 0x51, 0x25, 0x91, 0x24, 0x40, 0x28, 0x40, 0x0a, 0x5b, 0x57, 0x50, 0x69, 0x2b, 0x20, - 0x4b, 0x2a, 0x33, 0x51, 0x30, 0x4d, 0x42, 0x32, 0x48, 0x37, 0x1b, 0xb8, 0x1d, 0x4b, 0x28, 0x3d, 0x66, 0x2a, 0x85, 0x4e, 0x26, 0x32, 0x01, 0xbb, 0x10, 0x27, - 0x34, 0x23, 0x23, 0x2c, 0x3a, 0x33, 0x3b, 0xfe, 0x59, 0x2b, 0x1e, 0xce, 0x13, 0x2c, 0x3d, 0x2c, 0x33, 0x3c, 0x00, 0x01, 0x00, 0x6d, 0x01, 0xc8, 0x00, 0xf0, - 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, - 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x13, 0x33, 0x03, 0x6d, 0x23, 0x60, 0x4b, 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, 0x62, - 0x01, 0x6f, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, - 0x00, 0x0e, 0x16, 0x03, 0x0d, 0x17, 0x2b, 0x17, 0x26, 0x26, 0x35, 0x34, 0x12, 0x37, 0x33, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x17, 0x70, 0x22, 0x26, 0x80, 0x76, - 0x51, 0x47, 0x6e, 0x3e, 0x1d, 0x1b, 0x9e, 0x3d, 0x94, 0x52, 0xb3, 0x01, 0x19, 0x79, 0x4e, 0xb5, 0xcd, 0x74, 0x57, 0x8f, 0x3e, 0x00, 0x00, 0x01, 0xff, 0xb3, - 0xff, 0x62, 0x00, 0xf9, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x00, - 0x00, 0x0e, 0x00, 0x0e, 0x17, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x15, 0x14, 0x02, 0x07, 0x4d, 0x47, 0x6d, - 0x3e, 0x1c, 0x1b, 0x44, 0x22, 0x25, 0x7f, 0x77, 0x9e, 0x4f, 0xb4, 0xce, 0x73, 0x56, 0x91, 0x3d, 0x3d, 0x94, 0x53, 0xb2, 0xfe, 0xe7, 0x79, 0x00, 0x00, 0x01, - 0x00, 0x67, 0x01, 0x2c, 0x02, 0x33, 0x02, 0xfb, 0x00, 0x0e, 0x00, 0x1d, 0x40, 0x1a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x05, 0x00, 0x4a, 0x0e, 0x0d, 0x0c, 0x04, - 0x03, 0x02, 0x01, 0x07, 0x00, 0x49, 0x00, 0x00, 0x00, 0x76, 0x1a, 0x01, 0x0d, 0x17, 0x2b, 0x01, 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x37, 0x17, 0x07, - 0x37, 0x07, 0x27, 0x17, 0x01, 0x74, 0x36, 0x7b, 0x3d, 0x95, 0xb4, 0x1c, 0xb4, 0x14, 0x57, 0x3b, 0xcc, 0x04, 0xbe, 0x57, 0x01, 0x2c, 0xc3, 0xa5, 0x3d, 0x89, - 0x35, 0x4e, 0x59, 0xc1, 0x11, 0xba, 0x0a, 0x52, 0x17, 0xb9, 0x00, 0x01, 0x00, 0x46, 0x00, 0x6f, 0x02, 0x1c, 0x02, 0x53, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, - 0x00, 0x05, 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, 0x05, 0x02, 0x5f, 0x00, 0x02, 0x05, 0x02, 0x4f, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, 0x01, 0x55, 0xc7, 0xc7, - 0x48, 0xc7, 0xc7, 0x48, 0x01, 0x84, 0x47, 0xce, 0xce, 0x47, 0xcf, 0x00, 0x00, 0x01, 0xff, 0xd5, 0xff, 0x7f, 0x00, 0x9c, 0x00, 0x74, 0x00, 0x08, 0x00, 0x17, - 0x40, 0x14, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x13, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x36, 0x36, - 0x37, 0x33, 0x17, 0x06, 0x06, 0x07, 0x2b, 0x1a, 0x36, 0x13, 0x60, 0x04, 0x19, 0x48, 0x23, 0x81, 0x3b, 0x86, 0x34, 0x0b, 0x35, 0x7e, 0x37, 0x00, 0x00, 0x01, - 0x00, 0x1a, 0x00, 0xe3, 0x01, 0x18, 0x01, 0x34, 0x00, 0x03, 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, - 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, 0x37, 0x33, 0x07, 0x1a, 0x12, 0xec, 0x12, 0xe3, 0x51, - 0x51, 0x00, 0x00, 0x01, 0x00, 0x14, 0xff, 0xf2, 0x00, 0x92, 0x00, 0x79, 0x00, 0x0a, 0x00, 0x1a, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x02, 0x01, 0x00, - 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x06, 0x04, 0x00, 0x0a, 0x01, 0x0a, 0x03, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, - 0x06, 0x48, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0x0e, 0x34, 0x21, 0x32, 0x1b, 0x1a, 0x1f, 0x33, 0x00, 0x01, 0xff, 0xd2, 0x00, 0x00, 0x01, 0xb9, 0x02, 0xca, - 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, - 0x0d, 0x17, 0x2b, 0x23, 0x01, 0x33, 0x01, 0x2e, 0x01, 0x8d, 0x5a, 0xfe, 0x74, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x00, 0x02, 0x00, 0x39, 0xff, 0xf6, 0x02, 0x16, - 0x02, 0xd5, 0x00, 0x11, 0x00, 0x23, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, - 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x13, 0x12, 0x01, 0x00, 0x1c, 0x1a, 0x12, 0x23, 0x13, 0x23, 0x0a, 0x08, 0x00, 0x11, 0x01, 0x11, 0x06, 0x0d, 0x16, - 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x03, 0x27, 0x32, 0x3e, 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, - 0x15, 0x14, 0x16, 0xec, 0x58, 0x5b, 0x14, 0x2b, 0x46, 0x63, 0x41, 0x5c, 0x58, 0x16, 0x2d, 0x46, 0x62, 0x35, 0x28, 0x3f, 0x2f, 0x20, 0x10, 0x2f, 0x30, 0x26, - 0x40, 0x31, 0x22, 0x12, 0x30, 0x0a, 0x7e, 0x75, 0x3b, 0x86, 0x81, 0x6a, 0x40, 0x77, 0x6f, 0x48, 0x90, 0x82, 0x65, 0x3a, 0x4b, 0x34, 0x59, 0x70, 0x79, 0x3a, - 0x4a, 0x4f, 0x33, 0x57, 0x6c, 0x75, 0x36, 0x51, 0x57, 0x00, 0x00, 0x01, 0x00, 0x8f, 0x00, 0x00, 0x01, 0xbc, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x1b, 0x40, 0x18, - 0x08, 0x07, 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x11, 0x19, 0x02, 0x0d, 0x18, 0x2b, 0x01, - 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, 0x03, 0x23, 0x01, 0x29, 0x0a, 0x17, 0x09, 0x0f, 0x20, 0x14, 0x58, 0x29, 0xe0, 0x4d, 0x99, 0x59, - 0x01, 0xba, 0x2f, 0x60, 0x1d, 0x10, 0x18, 0x0d, 0x37, 0x42, 0x8e, 0xfd, 0x36, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x10, 0x02, 0xd4, 0x00, 0x1b, - 0x00, 0x2c, 0x40, 0x29, 0x0d, 0x0c, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, - 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x1b, 0x27, 0x25, 0x28, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x37, 0x37, 0x3e, 0x02, 0x35, - 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x15, 0x21, 0x07, 0x03, 0x10, 0xe3, 0x42, 0x54, - 0x28, 0x37, 0x33, 0x2c, 0x4a, 0x23, 0x2a, 0x29, 0x64, 0x40, 0x5b, 0x61, 0x2c, 0x63, 0x53, 0xa8, 0x01, 0x46, 0x0f, 0x4b, 0xcd, 0x3c, 0x54, 0x4c, 0x2f, 0x2d, - 0x39, 0x24, 0x1a, 0x3c, 0x21, 0x2c, 0x5b, 0x48, 0x3a, 0x5f, 0x6a, 0x48, 0x92, 0x04, 0x50, 0x00, 0x00, 0x01, 0x00, 0x16, 0xff, 0xf6, 0x02, 0x0d, 0x02, 0xd4, - 0x00, 0x2b, 0x00, 0x4a, 0x40, 0x47, 0x1b, 0x01, 0x04, 0x05, 0x1a, 0x01, 0x03, 0x04, 0x24, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, - 0x05, 0x4c, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, - 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1f, 0x1d, 0x18, 0x16, 0x11, 0x0f, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x2b, 0x01, 0x2b, 0x07, 0x0d, 0x16, 0x2b, - 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, - 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xd2, 0x3a, 0x5b, 0x27, 0x23, 0x66, 0x34, 0x50, - 0x56, 0x4b, 0x45, 0x40, 0x0f, 0x41, 0x32, 0x55, 0x33, 0x39, 0x2d, 0x2e, 0x4c, 0x26, 0x29, 0x29, 0x65, 0x43, 0x5a, 0x5e, 0x62, 0x57, 0x39, 0x49, 0x36, 0x72, - 0x0a, 0x15, 0x12, 0x55, 0x13, 0x1f, 0x4d, 0x41, 0x3e, 0x40, 0x49, 0x23, 0x44, 0x2f, 0x2e, 0x31, 0x20, 0x1a, 0x3e, 0x1e, 0x28, 0x57, 0x47, 0x4c, 0x6a, 0x10, - 0x04, 0x0a, 0x4f, 0x41, 0x38, 0x65, 0x3f, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x02, 0x18, 0x02, 0xca, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x2e, 0x40, 0x2b, - 0x11, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x05, 0x01, 0x02, 0x03, 0x01, 0x00, 0x04, 0x02, 0x00, 0x68, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x6b, - 0x04, 0x4e, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0d, 0x1a, 0x2b, 0x21, 0x37, 0x21, 0x37, 0x01, 0x33, 0x03, 0x33, - 0x07, 0x23, 0x07, 0x25, 0x33, 0x37, 0x3e, 0x02, 0x37, 0x23, 0x0e, 0x02, 0x07, 0x01, 0x20, 0x23, 0xfe, 0xc3, 0x0f, 0x01, 0x93, 0x65, 0x63, 0x6e, 0x11, 0x6f, - 0x23, 0xfe, 0xfa, 0xe5, 0x24, 0x08, 0x15, 0x15, 0x06, 0x04, 0x08, 0x1a, 0x19, 0x09, 0xa2, 0x50, 0x01, 0xd8, 0xfe, 0x26, 0x4e, 0xa2, 0xf0, 0xab, 0x25, 0x51, - 0x48, 0x17, 0x0d, 0x24, 0x22, 0x0a, 0x00, 0x01, 0x00, 0x25, 0xff, 0xf6, 0x02, 0x18, 0x02, 0xca, 0x00, 0x20, 0x00, 0x44, 0x40, 0x41, 0x16, 0x11, 0x02, 0x02, - 0x05, 0x10, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, - 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1a, 0x18, 0x15, 0x14, 0x13, 0x12, 0x0e, 0x0c, - 0x07, 0x05, 0x00, 0x20, 0x01, 0x20, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, - 0x07, 0x27, 0x13, 0x21, 0x07, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0xc8, 0x61, 0x42, 0x24, 0x53, 0x2c, 0x46, 0x56, 0x27, 0x48, - 0x3e, 0x1e, 0x34, 0x20, 0x25, 0x61, 0x01, 0x49, 0x11, 0xfd, 0x3c, 0x12, 0x2a, 0x1b, 0x59, 0x69, 0x1d, 0x41, 0x6f, 0x0a, 0x27, 0x55, 0x16, 0x1c, 0x30, 0x4f, - 0x2e, 0x3e, 0x44, 0x0a, 0x08, 0x1d, 0x01, 0x50, 0x50, 0xcf, 0x04, 0x06, 0x65, 0x58, 0x2d, 0x5b, 0x4c, 0x2e, 0x00, 0x02, 0x00, 0x3f, 0xff, 0xf6, 0x02, 0x22, - 0x02, 0xd4, 0x00, 0x1e, 0x00, 0x30, 0x00, 0x47, 0x40, 0x44, 0x0c, 0x01, 0x02, 0x01, 0x0d, 0x01, 0x03, 0x02, 0x13, 0x01, 0x04, 0x05, 0x03, 0x4c, 0x00, 0x03, - 0x00, 0x05, 0x04, 0x03, 0x05, 0x69, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, - 0x71, 0x00, 0x4e, 0x20, 0x1f, 0x01, 0x00, 0x27, 0x25, 0x1f, 0x30, 0x20, 0x30, 0x18, 0x16, 0x11, 0x0f, 0x0b, 0x09, 0x00, 0x1e, 0x01, 0x1e, 0x08, 0x0d, 0x16, - 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x37, 0x36, 0x36, 0x33, 0x32, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, - 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0xfb, 0x54, 0x68, - 0x20, 0x44, 0x35, 0x2b, 0x76, 0x4d, 0x36, 0x26, 0x12, 0x10, 0x29, 0x1b, 0x5f, 0x91, 0x23, 0x04, 0x1d, 0x54, 0x34, 0x4a, 0x58, 0x1e, 0x3d, 0x5e, 0x37, 0x31, - 0x44, 0x24, 0x34, 0x35, 0x24, 0x3c, 0x29, 0x09, 0x07, 0x05, 0x16, 0x30, 0x0a, 0x6b, 0x70, 0x46, 0x9d, 0x91, 0x33, 0x2c, 0x30, 0x0b, 0x4c, 0x05, 0x07, 0x84, - 0x97, 0x26, 0x2d, 0x5e, 0x56, 0x32, 0x63, 0x51, 0x31, 0x4a, 0x38, 0x5b, 0x32, 0x38, 0x3d, 0x20, 0x2e, 0x15, 0x10, 0x28, 0x14, 0x24, 0x3f, 0x28, 0x00, 0x01, - 0x00, 0x51, 0x00, 0x00, 0x02, 0x32, 0x02, 0xca, 0x00, 0x06, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, - 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x37, 0x21, 0x07, 0x01, 0x51, 0x01, - 0x75, 0xfe, 0xa5, 0x10, 0x01, 0xb7, 0x0d, 0xfe, 0x8b, 0x02, 0x7c, 0x4e, 0x46, 0xfd, 0x7c, 0x00, 0x00, 0x03, 0x00, 0x2d, 0xff, 0xf6, 0x02, 0x1f, 0x02, 0xd5, - 0x00, 0x1c, 0x00, 0x28, 0x00, 0x36, 0x00, 0x35, 0x40, 0x32, 0x30, 0x16, 0x07, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, - 0x70, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x2a, 0x29, 0x01, 0x00, 0x29, 0x36, 0x2a, 0x36, 0x24, 0x22, 0x0f, - 0x0d, 0x00, 0x1c, 0x01, 0x1c, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, - 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x03, 0x32, - 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x0e, 0x02, 0x15, 0x14, 0x16, 0xf6, 0x45, 0x59, 0x2b, 0x64, 0x59, 0x26, 0x2f, 0x38, 0x61, 0x3b, 0x42, 0x50, 0x24, 0x2f, - 0x4c, 0x2c, 0x34, 0x3d, 0x33, 0x6c, 0x0f, 0x44, 0x47, 0x36, 0x2e, 0x35, 0x41, 0x2c, 0x19, 0x32, 0x40, 0x1e, 0x32, 0x35, 0x2d, 0x49, 0x2a, 0x43, 0x0a, 0x31, - 0x51, 0x31, 0x4d, 0x68, 0x22, 0x1c, 0x46, 0x37, 0x3b, 0x54, 0x2d, 0x2d, 0x48, 0x29, 0x35, 0x49, 0x32, 0x13, 0x1f, 0x53, 0x41, 0x35, 0x5d, 0x39, 0x01, 0xa6, - 0x1a, 0x43, 0x35, 0x2b, 0x32, 0x3d, 0x35, 0x2d, 0x3a, 0xfe, 0x8d, 0x25, 0x3b, 0x20, 0x30, 0x48, 0x1c, 0x0e, 0x29, 0x3f, 0x2f, 0x34, 0x3b, 0x00, 0x00, 0x02, - 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x0a, 0x02, 0xd4, 0x00, 0x1f, 0x00, 0x2e, 0x00, 0x47, 0x40, 0x44, 0x0a, 0x01, 0x04, 0x05, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, - 0x00, 0x01, 0x03, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, - 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x21, 0x20, 0x01, 0x00, 0x29, 0x27, 0x20, 0x2e, 0x21, 0x2e, 0x16, 0x14, 0x0f, 0x0d, 0x08, 0x06, 0x00, - 0x1f, 0x01, 0x1f, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, - 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x07, 0x06, 0x06, 0x13, 0x32, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, - 0x16, 0xa5, 0x1e, 0x3e, 0x1a, 0x1b, 0x3b, 0x22, 0x64, 0x77, 0x1e, 0x05, 0x19, 0x4f, 0x30, 0x52, 0x5a, 0x3c, 0x70, 0x4d, 0x58, 0x62, 0x12, 0x22, 0x31, 0x20, - 0x2e, 0x71, 0x2f, 0x2f, 0x4c, 0x15, 0x0e, 0x36, 0x32, 0x32, 0x46, 0x25, 0x34, 0x0a, 0x09, 0x08, 0x51, 0x09, 0x0d, 0x8a, 0x8b, 0x23, 0x2b, 0x62, 0x5b, 0x48, - 0x7b, 0x4b, 0x6f, 0x6d, 0x34, 0x75, 0x73, 0x64, 0x23, 0x33, 0x2c, 0x01, 0x5a, 0x32, 0x2e, 0x22, 0x32, 0x3b, 0x4b, 0x34, 0x57, 0x35, 0x3a, 0x40, 0x00, 0x02, - 0x00, 0x14, 0xff, 0xf2, 0x00, 0xe1, 0x02, 0x26, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x2d, 0x40, 0x2a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, - 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x0c, 0x0b, 0x01, 0x00, 0x11, 0x0f, 0x0b, 0x15, 0x0c, 0x15, 0x06, 0x04, 0x00, - 0x0a, 0x01, 0x0a, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x03, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, - 0x15, 0x14, 0x06, 0x97, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0x75, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0x01, 0x9f, 0x33, 0x22, 0x32, 0x1a, 0x1b, 0x1f, 0x33, - 0xfe, 0x53, 0x34, 0x21, 0x32, 0x1b, 0x1a, 0x1f, 0x33, 0x00, 0x00, 0x02, 0xff, 0xcf, 0xff, 0x7f, 0x00, 0xe1, 0x02, 0x26, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x2f, - 0x40, 0x2c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, 0x03, 0x80, 0x05, 0x01, 0x03, 0x03, 0x84, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x00, - 0x4e, 0x0b, 0x0b, 0x01, 0x00, 0x0b, 0x13, 0x0b, 0x13, 0x0f, 0x0e, 0x06, 0x04, 0x00, 0x0a, 0x01, 0x0a, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x35, 0x34, 0x36, - 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x03, 0x36, 0x36, 0x37, 0x33, 0x17, 0x06, 0x06, 0x07, 0x97, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0xee, 0x1a, 0x36, 0x13, - 0x60, 0x04, 0x19, 0x48, 0x23, 0x01, 0x9f, 0x33, 0x22, 0x32, 0x1a, 0x1b, 0x1f, 0x33, 0xfd, 0xe0, 0x3b, 0x86, 0x34, 0x0b, 0x35, 0x7e, 0x37, 0x00, 0x00, 0x01, - 0x00, 0x46, 0x00, 0x74, 0x02, 0x1d, 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, 0x32, 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, 0x05, 0x02, - 0x1d, 0xfe, 0x29, 0x01, 0xd7, 0xfe, 0x87, 0x01, 0x79, 0x74, 0xcf, 0x32, 0xeb, 0x4e, 0xb2, 0x9e, 0x00, 0x02, 0x00, 0x4c, 0x00, 0xd9, 0x02, 0x16, 0x01, 0xe7, - 0x00, 0x03, 0x00, 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, - 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, - 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, 0x35, 0x21, 0x15, 0x4c, 0x01, 0xca, 0xfe, 0x36, 0x01, 0xca, 0x01, 0xa0, 0x47, 0x47, 0xc7, 0x47, 0x47, 0x00, 0x00, 0x01, - 0x00, 0x46, 0x00, 0x74, 0x02, 0x1d, 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, 0x25, 0x25, 0x35, 0x05, 0x15, 0x05, 0x46, - 0x01, 0x79, 0xfe, 0x87, 0x01, 0xd7, 0xfe, 0x29, 0xc2, 0x9d, 0xb3, 0x4e, 0xeb, 0x32, 0xcf, 0x00, 0x00, 0x02, 0x00, 0x4d, 0xff, 0xf2, 0x01, 0xc6, 0x02, 0xd4, - 0x00, 0x1c, 0x00, 0x27, 0x00, 0x3f, 0x40, 0x3c, 0x0f, 0x01, 0x00, 0x01, 0x0e, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x05, 0x01, 0x02, 0x00, 0x04, 0x00, 0x02, 0x04, - 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x1e, 0x1d, 0x00, - 0x00, 0x23, 0x21, 0x1d, 0x27, 0x1e, 0x27, 0x00, 0x1c, 0x00, 0x1c, 0x25, 0x2a, 0x07, 0x0d, 0x18, 0x2b, 0x37, 0x3e, 0x02, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, - 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x0e, 0x02, 0x07, 0x07, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, - 0x14, 0x06, 0x7f, 0x07, 0x1b, 0x2f, 0x24, 0x20, 0x37, 0x22, 0x30, 0x2e, 0x26, 0x49, 0x21, 0x20, 0x29, 0x62, 0x2f, 0x4f, 0x5e, 0x49, 0x46, 0x27, 0x2b, 0x17, - 0x08, 0x45, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0xc9, 0x2b, 0x40, 0x37, 0x1c, 0x19, 0x2e, 0x38, 0x26, 0x2c, 0x30, 0x19, 0x10, 0x43, 0x16, 0x1c, 0x4e, 0x4f, - 0x43, 0x64, 0x34, 0x1c, 0x28, 0x2c, 0x23, 0xd7, 0x34, 0x21, 0x32, 0x1b, 0x1a, 0x1f, 0x33, 0x00, 0x00, 0x02, 0x00, 0x35, 0xff, 0xa5, 0x03, 0x36, 0x02, 0xc9, - 0x00, 0x40, 0x00, 0x4e, 0x00, 0x90, 0x40, 0x13, 0x22, 0x01, 0x09, 0x04, 0x45, 0x14, 0x02, 0x05, 0x09, 0x3d, 0x01, 0x07, 0x02, 0x3e, 0x01, 0x00, 0x07, 0x04, - 0x4c, 0x4b, 0xb0, 0x1b, 0x50, 0x58, 0x40, 0x28, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, 0x07, 0x05, 0x02, 0x69, 0x00, 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, - 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x09, 0x09, 0x04, 0x61, 0x00, 0x04, 0x04, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x26, 0x00, - 0x04, 0x00, 0x09, 0x05, 0x04, 0x09, 0x69, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, 0x07, 0x05, 0x02, 0x69, 0x00, 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, 0x65, - 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x06, 0x4e, 0x59, 0x40, 0x1f, 0x42, 0x41, 0x01, 0x00, 0x49, 0x47, 0x41, 0x4e, 0x42, 0x4e, 0x3b, 0x39, - 0x33, 0x31, 0x2a, 0x28, 0x20, 0x1e, 0x19, 0x17, 0x12, 0x10, 0x0a, 0x08, 0x00, 0x40, 0x01, 0x40, 0x0c, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, 0x34, - 0x3e, 0x02, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, - 0x16, 0x17, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, - 0x37, 0x15, 0x06, 0x06, 0x03, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x01, 0x81, 0x65, 0x95, 0x52, 0x40, 0x7a, 0xad, - 0x6c, 0x6a, 0x85, 0x3f, 0x37, 0x60, 0x3e, 0x38, 0x2d, 0x04, 0x04, 0x16, 0x44, 0x32, 0x37, 0x42, 0x45, 0x73, 0x44, 0x30, 0x40, 0x1a, 0x2f, 0x08, 0x08, 0x1c, - 0x14, 0x1f, 0x32, 0x23, 0x13, 0x2f, 0x6a, 0x59, 0x56, 0x8b, 0x64, 0x36, 0x88, 0x84, 0x36, 0x6c, 0x2c, 0x34, 0x70, 0x3c, 0x30, 0x3f, 0x13, 0x21, 0x0a, 0x1e, - 0x14, 0x2e, 0x4c, 0x2c, 0x20, 0x5b, 0x50, 0x97, 0x6a, 0x5b, 0xa8, 0x83, 0x4d, 0x53, 0x87, 0x50, 0x59, 0x8c, 0x50, 0x36, 0x23, 0x25, 0x34, 0x49, 0x43, 0x51, - 0x7b, 0x44, 0x12, 0x0b, 0xb3, 0x1e, 0x27, 0x11, 0x1f, 0x18, 0x2a, 0x45, 0x55, 0x2b, 0x42, 0x6c, 0x41, 0x3d, 0x6d, 0x90, 0x53, 0x7f, 0x93, 0x19, 0x11, 0x41, - 0x15, 0x17, 0x01, 0x04, 0x55, 0x43, 0x7c, 0x04, 0x07, 0x36, 0x5c, 0x39, 0x2c, 0x28, 0x00, 0x02, 0xff, 0xc7, 0x00, 0x00, 0x02, 0x01, 0x02, 0xca, 0x00, 0x07, - 0x00, 0x11, 0x00, 0x2c, 0x40, 0x29, 0x0d, 0x01, 0x04, 0x00, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, 0x68, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, - 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x09, 0x08, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x33, 0x13, - 0x23, 0x27, 0x23, 0x07, 0x13, 0x33, 0x27, 0x26, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x39, 0x01, 0x84, 0x5e, 0x58, 0x58, 0x1b, 0xf1, 0x74, 0x9f, 0xbd, 0x10, - 0x04, 0x07, 0x01, 0x03, 0x10, 0x2a, 0x17, 0x02, 0xca, 0xfd, 0x36, 0xde, 0xde, 0x01, 0x2e, 0x96, 0x26, 0x5c, 0x23, 0x26, 0x57, 0x2c, 0x00, 0x03, 0x00, 0x29, - 0x00, 0x00, 0x02, 0x4d, 0x02, 0xca, 0x00, 0x10, 0x00, 0x1a, 0x00, 0x23, 0x00, 0x43, 0x40, 0x40, 0x08, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x00, - 0x05, 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x08, 0x01, 0x04, 0x04, 0x01, 0x5f, 0x06, 0x01, 0x01, 0x01, 0x6b, - 0x01, 0x4e, 0x1c, 0x1b, 0x12, 0x11, 0x00, 0x00, 0x22, 0x20, 0x1b, 0x23, 0x1c, 0x23, 0x19, 0x17, 0x11, 0x1a, 0x12, 0x1a, 0x00, 0x10, 0x00, 0x0f, 0x21, 0x09, - 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x13, 0x32, 0x36, 0x36, 0x35, 0x34, - 0x26, 0x23, 0x23, 0x07, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0xb9, 0x63, 0x71, 0x58, 0x49, 0x31, 0x42, 0x47, 0x7b, 0x50, 0x41, - 0x2d, 0x49, 0x2c, 0x3c, 0x46, 0x65, 0x30, 0x37, 0x55, 0x5c, 0x3e, 0x4a, 0x70, 0x37, 0x02, 0xca, 0x4e, 0x56, 0x49, 0x5b, 0x0e, 0x05, 0x0d, 0x48, 0x3c, 0x49, - 0x63, 0x32, 0x01, 0x9a, 0x1c, 0x39, 0x2c, 0x2f, 0x33, 0xe3, 0xfe, 0xb2, 0x4c, 0x46, 0x30, 0x42, 0xfe, 0xfc, 0x00, 0x01, 0x00, 0x48, 0xff, 0xf6, 0x02, 0x78, - 0x02, 0xd4, 0x00, 0x1d, 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, 0x02, 0x01, 0x1a, 0x0c, 0x02, 0x03, 0x02, 0x1b, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, - 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x18, 0x16, 0x10, 0x0e, 0x0a, - 0x08, 0x00, 0x1d, 0x01, 0x1d, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, - 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x01, 0x46, 0x77, 0x87, 0x1e, 0x3d, 0x5d, 0x7c, 0x4e, 0x64, 0x4a, 0x24, 0x1b, 0x43, 0x2c, 0x4b, - 0x6d, 0x48, 0x23, 0x5d, 0x52, 0x29, 0x4f, 0x26, 0x27, 0x4f, 0x0a, 0x92, 0x7f, 0x40, 0x84, 0x76, 0x5d, 0x36, 0x28, 0x4a, 0x0e, 0x15, 0x43, 0x6f, 0x86, 0x44, - 0x5b, 0x69, 0x10, 0x0d, 0x4e, 0x0e, 0x10, 0x00, 0x00, 0x02, 0x00, 0x29, 0x00, 0x00, 0x02, 0x7c, 0x02, 0xca, 0x00, 0x09, 0x00, 0x13, 0x00, 0x2c, 0x40, 0x29, - 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x01, 0x5f, 0x04, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x0b, 0x0a, 0x00, - 0x00, 0x12, 0x10, 0x0a, 0x13, 0x0b, 0x13, 0x00, 0x09, 0x00, 0x08, 0x21, 0x06, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, - 0x37, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0xa9, 0x81, 0x92, 0x61, 0xbb, 0x87, 0x05, 0x68, 0x8e, 0x4a, 0x69, 0x57, 0x55, 0x77, - 0x02, 0xca, 0x8c, 0x91, 0x7c, 0xc2, 0x6f, 0x4d, 0x5e, 0xa0, 0x63, 0x6e, 0x61, 0xfd, 0xd0, 0x00, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x02, 0x2a, 0x02, 0xca, - 0x00, 0x0b, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x04, - 0x04, 0x05, 0x5f, 0x06, 0x01, 0x05, 0x05, 0x6b, 0x05, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x33, - 0x13, 0x21, 0x07, 0x21, 0x07, 0x33, 0x07, 0x21, 0x07, 0x21, 0x07, 0x29, 0x97, 0x01, 0x6a, 0x11, 0xfe, 0xef, 0x2f, 0xff, 0x0f, 0xff, 0x00, 0x37, 0x01, 0x12, - 0x11, 0x02, 0xca, 0x4f, 0xdf, 0x4e, 0xff, 0x4f, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x02, 0x2a, 0x02, 0xca, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x00, 0x02, - 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x04, 0x04, 0x6b, 0x04, 0x4e, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x09, 0x11, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x21, 0x07, 0x21, 0x07, 0x21, 0x07, 0x21, 0x03, 0x29, 0x97, 0x01, 0x6a, 0x10, - 0xfe, 0xee, 0x35, 0x01, 0x00, 0x11, 0xff, 0x00, 0x40, 0x02, 0xca, 0x4f, 0xfe, 0x4f, 0xfe, 0xd2, 0x00, 0x01, 0x00, 0x48, 0xff, 0xf6, 0x02, 0x98, 0x02, 0xd4, - 0x00, 0x21, 0x00, 0x3e, 0x40, 0x3b, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, 0x05, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x67, 0x00, 0x02, - 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1e, 0x1d, 0x1c, 0x1b, - 0x18, 0x16, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x21, 0x01, 0x21, 0x07, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, - 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x23, 0x37, 0x33, 0x03, 0x06, 0x06, 0x01, 0x57, 0x7f, 0x90, 0x37, - 0x67, 0x8d, 0x56, 0x41, 0x62, 0x2c, 0x22, 0x25, 0x56, 0x33, 0x52, 0x83, 0x4c, 0x27, 0x52, 0x40, 0x26, 0x3f, 0x16, 0x2e, 0x8c, 0x11, 0xe5, 0x4c, 0x2d, 0x64, - 0x0a, 0x8e, 0x7f, 0x62, 0xa9, 0x7f, 0x47, 0x16, 0x14, 0x4e, 0x11, 0x18, 0x62, 0xab, 0x6f, 0x37, 0x59, 0x34, 0x0b, 0x07, 0xd3, 0x4e, 0xfe, 0xa3, 0x10, 0x15, - 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x02, 0xac, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x27, 0x40, 0x24, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x68, 0x02, 0x01, - 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x05, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x07, 0x0d, 0x1b, - 0x2b, 0x33, 0x13, 0x33, 0x03, 0x21, 0x13, 0x33, 0x03, 0x23, 0x13, 0x21, 0x03, 0x2a, 0x97, 0x59, 0x40, 0x01, 0x3a, 0x40, 0x58, 0x97, 0x58, 0x46, 0xfe, 0xc6, - 0x46, 0x02, 0xca, 0xfe, 0xd2, 0x01, 0x2e, 0xfd, 0x36, 0x01, 0x4d, 0xfe, 0xb3, 0x00, 0x00, 0x01, 0xff, 0xec, 0x00, 0x00, 0x01, 0x7d, 0x02, 0xca, 0x00, 0x0b, - 0x00, 0x22, 0x40, 0x1f, 0x0a, 0x09, 0x04, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, - 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0x23, 0x37, 0x37, 0x13, 0x27, 0x37, 0x33, 0x07, 0x07, 0x03, 0x17, 0x07, 0x14, 0x0a, 0x55, 0x7a, - 0x4c, 0x0a, 0xfa, 0x0a, 0x56, 0x7a, 0x4d, 0x0a, 0x31, 0x14, 0x02, 0x40, 0x13, 0x32, 0x32, 0x13, 0xfd, 0xc0, 0x14, 0x31, 0x00, 0x01, 0xff, 0x64, 0xff, 0x42, - 0x01, 0x1a, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x28, 0x40, 0x25, 0x03, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, 0x00, 0x01, - 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, 0x01, 0x00, 0x0b, 0x0a, 0x07, 0x05, 0x00, 0x0e, 0x01, 0x0e, 0x04, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x27, 0x37, - 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x50, 0x32, 0x1a, 0x03, 0x0f, 0x24, 0x14, 0x2c, 0x44, 0x0d, 0x96, 0x59, 0x97, 0x16, 0x6d, - 0xbe, 0x0c, 0x4d, 0x04, 0x06, 0x38, 0x40, 0x02, 0xc1, 0xfd, 0x35, 0x65, 0x58, 0x00, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x02, 0x8b, 0x02, 0xca, 0x00, 0x0c, - 0x00, 0x25, 0x40, 0x22, 0x0a, 0x07, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, - 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x12, 0x13, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x37, 0x01, 0x33, 0x01, 0x13, 0x23, 0x03, 0x07, 0x03, - 0x29, 0x97, 0x59, 0x4a, 0x3e, 0x01, 0x12, 0x6c, 0xfe, 0xca, 0xa9, 0x62, 0x8b, 0x53, 0x3c, 0x02, 0xca, 0xfe, 0xa5, 0x42, 0x01, 0x19, 0xfe, 0xc6, 0xfe, 0x70, - 0x01, 0x5a, 0x3d, 0xfe, 0xe3, 0x00, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x01, 0xa4, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x6a, - 0x4d, 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, - 0x13, 0x33, 0x03, 0x21, 0x07, 0x29, 0x97, 0x59, 0x87, 0x01, 0x12, 0x11, 0x02, 0xca, 0xfd, 0x86, 0x50, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x03, 0x4c, - 0x02, 0xca, 0x00, 0x16, 0x00, 0x27, 0x40, 0x24, 0x10, 0x0c, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x04, 0x03, 0x03, - 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x16, 0x00, 0x16, 0x16, 0x11, 0x13, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x01, 0x33, - 0x03, 0x23, 0x13, 0x36, 0x36, 0x37, 0x23, 0x01, 0x23, 0x03, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x28, 0x97, 0x7e, 0x45, 0x04, 0x01, 0x3d, 0x89, 0x94, 0x5a, 0x5a, - 0x0e, 0x19, 0x09, 0x02, 0xfe, 0xa8, 0x47, 0x4c, 0x04, 0x02, 0x0a, 0x0d, 0x07, 0x5b, 0x02, 0xca, 0xfd, 0xb9, 0x02, 0x47, 0xfd, 0x36, 0x01, 0xa8, 0x41, 0x6a, - 0x20, 0xfd, 0x8d, 0x02, 0x72, 0x14, 0x43, 0x4b, 0x23, 0xfe, 0x53, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x02, 0xc8, 0x02, 0xca, 0x00, 0x12, 0x00, 0x24, - 0x40, 0x21, 0x0c, 0x03, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x12, 0x11, 0x16, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0x23, 0x03, 0x23, 0x0e, 0x02, - 0x07, 0x03, 0x28, 0x97, 0x5f, 0xdb, 0x03, 0x05, 0x13, 0x0b, 0x54, 0x55, 0x97, 0x5f, 0xdd, 0x03, 0x02, 0x0b, 0x0f, 0x08, 0x52, 0x02, 0xca, 0xfd, 0xb2, 0x24, - 0x6f, 0x32, 0x01, 0x89, 0xfd, 0x36, 0x02, 0x50, 0x15, 0x44, 0x4e, 0x25, 0xfe, 0x7c, 0x00, 0x02, 0x00, 0x48, 0xff, 0xf6, 0x02, 0xb2, 0x02, 0xd5, 0x00, 0x0f, - 0x00, 0x1f, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, - 0x71, 0x00, 0x4e, 0x11, 0x10, 0x01, 0x00, 0x19, 0x17, 0x10, 0x1f, 0x11, 0x1f, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, - 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, - 0x51, 0x80, 0x89, 0x31, 0x5e, 0x86, 0x54, 0x7a, 0x87, 0x2d, 0x59, 0x84, 0x54, 0x3c, 0x5e, 0x42, 0x23, 0x5a, 0x4e, 0x3c, 0x60, 0x44, 0x24, 0x5c, 0x0a, 0x95, - 0x80, 0x5c, 0xa6, 0x7f, 0x49, 0x96, 0x83, 0x5d, 0xa4, 0x7d, 0x48, 0x4f, 0x3c, 0x69, 0x88, 0x4c, 0x5f, 0x69, 0x3b, 0x67, 0x89, 0x4e, 0x5e, 0x6a, 0x00, 0x02, - 0x00, 0x29, 0x00, 0x00, 0x02, 0x37, 0x02, 0xca, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x30, 0x40, 0x2d, 0x06, 0x01, 0x03, 0x00, 0x01, 0x02, 0x03, 0x01, 0x69, 0x00, - 0x04, 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0c, 0x0b, 0x00, 0x00, 0x12, 0x10, 0x0b, 0x13, 0x0c, 0x13, - 0x00, 0x0a, 0x00, 0x0a, 0x24, 0x21, 0x07, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x23, 0x03, 0x13, 0x32, 0x36, 0x35, 0x34, - 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0xa1, 0x74, 0x62, 0xa0, 0x9a, 0x40, 0x3b, 0x89, 0x60, 0x71, 0x43, 0x44, 0x4c, 0x3c, 0x02, 0xca, 0x67, 0x53, 0x79, 0x80, - 0xfe, 0xe9, 0x01, 0x62, 0x53, 0x58, 0x3b, 0x35, 0xfe, 0xe5, 0x00, 0x02, 0x00, 0x48, 0xff, 0x56, 0x02, 0xb2, 0x02, 0xd5, 0x00, 0x14, 0x00, 0x24, 0x00, 0x32, - 0x40, 0x2f, 0x12, 0x01, 0x00, 0x03, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x02, 0x86, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x03, - 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x16, 0x15, 0x1e, 0x1c, 0x15, 0x24, 0x16, 0x24, 0x17, 0x26, 0x22, 0x06, 0x0d, 0x19, 0x2b, 0x05, 0x06, - 0x22, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x17, 0x23, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, - 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x61, 0x04, 0x08, 0x04, 0x80, 0x89, 0x31, 0x5e, 0x86, 0x54, 0x7a, 0x87, 0x3a, 0x6f, 0x50, 0x86, 0x72, 0x79, 0x3d, - 0x5f, 0x41, 0x22, 0x5a, 0x4e, 0x3c, 0x60, 0x44, 0x24, 0x5c, 0x09, 0x01, 0x95, 0x80, 0x5c, 0xa6, 0x7f, 0x49, 0x96, 0x83, 0x67, 0xb3, 0x80, 0x1b, 0xb1, 0xef, - 0x3c, 0x69, 0x88, 0x4c, 0x5f, 0x69, 0x3b, 0x67, 0x89, 0x4e, 0x5e, 0x6a, 0x00, 0x02, 0x00, 0x29, 0x00, 0x00, 0x02, 0x39, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x15, - 0x00, 0x38, 0x40, 0x35, 0x07, 0x01, 0x02, 0x04, 0x01, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, 0x67, 0x00, 0x05, 0x05, 0x00, 0x5f, 0x00, 0x00, - 0x00, 0x6a, 0x4d, 0x06, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x0e, 0x0d, 0x00, 0x00, 0x14, 0x12, 0x0d, 0x15, 0x0e, 0x15, 0x00, 0x0c, 0x00, 0x0c, 0x11, - 0x15, 0x21, 0x08, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x15, 0x14, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x03, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, - 0x23, 0x03, 0x29, 0x97, 0x9d, 0xdc, 0x51, 0x61, 0x76, 0x62, 0x66, 0x75, 0x3e, 0x9c, 0x64, 0x5b, 0x44, 0x44, 0x4c, 0x39, 0x02, 0xca, 0xb5, 0x4d, 0x72, 0x1b, - 0xfe, 0xc5, 0x01, 0x27, 0xfe, 0xd9, 0x01, 0x73, 0x57, 0x45, 0x3d, 0x30, 0xfe, 0xf7, 0x00, 0x01, 0x00, 0x13, 0xff, 0xf6, 0x02, 0x07, 0x02, 0xd4, 0x00, 0x2a, - 0x00, 0x37, 0x40, 0x34, 0x19, 0x01, 0x03, 0x02, 0x1a, 0x04, 0x02, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, - 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1e, 0x1c, 0x17, 0x15, 0x08, 0x06, 0x00, 0x2a, 0x01, - 0x2a, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x36, - 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x15, 0x14, 0x06, 0xb9, 0x34, 0x4f, 0x23, 0x1e, 0x53, - 0x36, 0x2d, 0x4c, 0x2e, 0x35, 0x41, 0x26, 0x3b, 0x21, 0x40, 0x6b, 0x40, 0x38, 0x55, 0x26, 0x22, 0x1a, 0x4e, 0x29, 0x3d, 0x4f, 0x16, 0x2e, 0x22, 0x2b, 0x41, - 0x25, 0x8f, 0x0a, 0x10, 0x10, 0x58, 0x10, 0x1a, 0x1c, 0x3a, 0x2e, 0x28, 0x39, 0x25, 0x17, 0x31, 0x41, 0x2e, 0x42, 0x5d, 0x30, 0x16, 0x14, 0x4c, 0x0e, 0x19, - 0x40, 0x3a, 0x1e, 0x29, 0x21, 0x15, 0x1a, 0x32, 0x42, 0x31, 0x6b, 0x6e, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0x4d, 0x02, 0xca, 0x00, 0x07, 0x00, 0x21, - 0x40, 0x1e, 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, - 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x23, 0x37, 0x21, 0x07, 0x23, 0x03, 0x98, 0x86, 0xc4, 0x11, 0x01, 0xe2, 0x10, 0xc4, 0x87, 0x02, 0x7b, - 0x4f, 0x4f, 0xfd, 0x85, 0x00, 0x01, 0x00, 0x4f, 0xff, 0xf6, 0x02, 0xb0, 0x02, 0xca, 0x00, 0x18, 0x00, 0x24, 0x40, 0x21, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, - 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x14, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x00, 0x18, 0x01, 0x18, 0x05, 0x0d, - 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x0e, 0x02, - 0x01, 0x2c, 0x70, 0x6d, 0x06, 0x06, 0x5c, 0x59, 0x5d, 0x05, 0x06, 0x45, 0x44, 0x59, 0x57, 0x13, 0x63, 0x59, 0x64, 0x10, 0x45, 0x74, 0x0a, 0x67, 0x5f, 0x11, - 0x32, 0x1c, 0x01, 0xaf, 0xfe, 0x4c, 0x17, 0x32, 0x10, 0x38, 0x40, 0x5c, 0x59, 0x01, 0xd0, 0xfe, 0x29, 0x4e, 0x72, 0x3d, 0x00, 0x01, 0x00, 0x5c, 0x00, 0x00, - 0x02, 0x84, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, - 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x16, 0x07, 0x33, 0x36, 0x36, 0x37, - 0x13, 0x33, 0x01, 0xa9, 0x4d, 0x58, 0x2d, 0x05, 0x05, 0x01, 0x02, 0x0f, 0x26, 0x18, 0xe8, 0x63, 0xfe, 0x84, 0x02, 0xca, 0xfe, 0x3c, 0x29, 0x54, 0x24, 0x24, - 0x4f, 0x2f, 0x01, 0xc3, 0xfd, 0x36, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x00, 0x03, 0xaf, 0x02, 0xca, 0x00, 0x21, 0x00, 0x27, 0x40, 0x24, 0x1c, 0x10, 0x06, 0x03, - 0x03, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x02, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x21, 0x11, - 0x19, 0x19, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x13, 0x16, 0x16, 0x07, 0x33, 0x36, - 0x36, 0x37, 0x13, 0x33, 0x01, 0x23, 0x03, 0x26, 0x26, 0x35, 0x23, 0x06, 0x06, 0x07, 0x03, 0x89, 0x1e, 0x58, 0x0e, 0x02, 0x04, 0x02, 0x03, 0x0e, 0x28, 0x15, - 0xc4, 0x5b, 0x14, 0x03, 0x02, 0x01, 0x03, 0x0e, 0x1f, 0x13, 0xbb, 0x5f, 0xfe, 0xbc, 0x5b, 0x16, 0x02, 0x02, 0x03, 0x0a, 0x1a, 0x17, 0xd3, 0x02, 0xca, 0xfe, - 0x4d, 0x29, 0x58, 0x28, 0x27, 0x65, 0x2c, 0x01, 0xa4, 0xfe, 0x5e, 0x2f, 0x66, 0x25, 0x26, 0x5a, 0x2c, 0x01, 0xb0, 0xfd, 0x36, 0x01, 0xcc, 0x21, 0x4b, 0x1f, - 0x1e, 0x3e, 0x32, 0xfe, 0x37, 0x00, 0x00, 0x01, 0xff, 0xcc, 0x00, 0x00, 0x02, 0x61, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, - 0x04, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x12, - 0x12, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x03, 0x33, 0x13, 0x13, 0x33, 0x01, 0x13, 0x23, 0x03, 0x03, 0x34, 0x01, 0x23, 0x7f, 0x5a, 0x61, 0xd4, 0x62, - 0xfe, 0xf2, 0x87, 0x5e, 0x66, 0xe8, 0x01, 0x7a, 0x01, 0x50, 0xfe, 0xef, 0x01, 0x11, 0xfe, 0xac, 0xfe, 0x8a, 0x01, 0x35, 0xfe, 0xcb, 0x00, 0x01, 0x00, 0x5c, - 0x00, 0x00, 0x02, 0x59, 0x02, 0xca, 0x00, 0x08, 0x00, 0x22, 0x40, 0x1f, 0x04, 0x01, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x03, - 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x12, 0x12, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x03, 0x33, 0x13, 0x13, 0x33, 0x01, - 0x03, 0x96, 0x3a, 0x74, 0x59, 0x55, 0xea, 0x65, 0xfe, 0xce, 0x37, 0x01, 0x0c, 0x01, 0xbe, 0xfe, 0x9a, 0x01, 0x66, 0xfe, 0x3f, 0xfe, 0xf7, 0x00, 0x00, 0x01, - 0xff, 0xf6, 0x00, 0x00, 0x02, 0x3d, 0x02, 0xca, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, - 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x01, - 0x21, 0x37, 0x21, 0x07, 0x01, 0x21, 0x07, 0x0a, 0x0e, 0x01, 0xbd, 0xfe, 0xc5, 0x11, 0x01, 0xa6, 0x0d, 0xfe, 0x43, 0x01, 0x4f, 0x10, 0x46, 0x02, 0x34, 0x50, - 0x47, 0xfd, 0xcd, 0x50, 0x00, 0x01, 0xff, 0xf7, 0xff, 0x62, 0x01, 0x72, 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x02, 0x04, 0x01, 0x03, 0x02, - 0x03, 0x63, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, - 0x07, 0x13, 0x33, 0x07, 0x23, 0x03, 0x33, 0x07, 0x09, 0xba, 0xc1, 0x10, 0x6e, 0x9a, 0x6e, 0x10, 0x9e, 0x03, 0x68, 0x48, 0xfd, 0x28, 0x48, 0x00, 0x00, 0x01, - 0x00, 0x6c, 0x00, 0x00, 0x01, 0x26, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x33, 0x03, 0x33, 0x13, 0xd6, 0x6a, 0x50, 0x6a, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x00, 0x01, - 0xff, 0xb8, 0xff, 0x62, 0x01, 0x32, 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x00, 0x04, 0x01, 0x03, 0x00, 0x03, 0x63, 0x00, 0x01, 0x01, 0x02, - 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x07, 0x37, 0x33, 0x13, 0x23, 0x37, - 0x33, 0x03, 0x48, 0x0f, 0x6e, 0x9a, 0x6e, 0x10, 0xc1, 0xba, 0x9e, 0x48, 0x02, 0xd8, 0x48, 0xfc, 0x98, 0x00, 0x00, 0x01, 0x00, 0x26, 0x01, 0x0b, 0x02, 0x16, - 0x02, 0xcf, 0x00, 0x06, 0x00, 0x27, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x03, 0x02, 0x02, - 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x13, 0x13, 0x33, 0x13, 0x23, 0x03, 0x03, - 0x26, 0xd4, 0x32, 0xea, 0x4e, 0xb4, 0xa0, 0x01, 0x0b, 0x01, 0xc4, 0xfe, 0x3c, 0x01, 0x67, 0xfe, 0x99, 0x00, 0x00, 0x01, 0xff, 0xa4, 0xff, 0x62, 0x01, 0x40, - 0xff, 0xa6, 0x00, 0x03, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, - 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x07, 0x37, 0x21, 0x07, 0x5c, 0x0f, 0x01, 0x8d, - 0x0f, 0x9e, 0x44, 0x44, 0x00, 0x01, 0x00, 0x92, 0x02, 0x5e, 0x01, 0x36, 0x02, 0xfe, 0x00, 0x0a, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x09, 0x04, - 0x02, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x15, 0x03, 0x0d, 0x17, 0x2b, - 0xb1, 0x06, 0x00, 0x44, 0x01, 0x2e, 0x02, 0x27, 0x35, 0x33, 0x16, 0x16, 0x17, 0x15, 0x01, 0x00, 0x13, 0x2b, 0x26, 0x0a, 0x5e, 0x0b, 0x27, 0x14, 0x02, 0x5e, - 0x13, 0x36, 0x38, 0x15, 0x0a, 0x25, 0x4d, 0x22, 0x0c, 0x00, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf6, 0x02, 0x26, 0x02, 0x22, 0x00, 0x14, 0x00, 0x26, 0x00, 0x67, - 0xb6, 0x11, 0x0b, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x19, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, - 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, - 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, - 0x17, 0x16, 0x15, 0x01, 0x00, 0x20, 0x1e, 0x15, 0x26, 0x16, 0x26, 0x10, 0x0f, 0x0e, 0x0d, 0x09, 0x07, 0x00, 0x14, 0x01, 0x14, 0x08, 0x0d, 0x16, 0x2b, 0x17, - 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0x27, 0x32, 0x36, 0x36, 0x37, 0x36, 0x36, - 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0xc1, 0x40, 0x51, 0x27, 0x46, 0x60, 0x3a, 0x35, 0x42, 0x10, 0x05, 0x20, 0x43, 0x72, 0x46, 0x0d, - 0x04, 0x22, 0x5c, 0x1b, 0x25, 0x47, 0x3a, 0x0f, 0x08, 0x05, 0x34, 0x2c, 0x27, 0x42, 0x32, 0x1b, 0x2c, 0x0a, 0x5d, 0x5a, 0x4b, 0x87, 0x67, 0x3c, 0x38, 0x25, - 0x53, 0xfd, 0xe8, 0x63, 0x2c, 0x41, 0x49, 0x36, 0x5c, 0x39, 0x1d, 0x31, 0x15, 0x2f, 0x3c, 0x31, 0x55, 0x6c, 0x3b, 0x36, 0x36, 0x00, 0x00, 0x02, 0x00, 0x1c, - 0xff, 0xf6, 0x02, 0x12, 0x02, 0xf8, 0x00, 0x18, 0x00, 0x27, 0x00, 0x94, 0xb5, 0x03, 0x01, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, - 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x62, 0x01, 0x06, 0x02, 0x00, 0x00, - 0x71, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, - 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x62, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x03, 0x02, 0x85, - 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x62, 0x06, 0x01, 0x00, 0x00, 0x71, - 0x00, 0x4e, 0x59, 0x59, 0x40, 0x17, 0x1a, 0x19, 0x01, 0x00, 0x21, 0x1f, 0x19, 0x27, 0x1a, 0x27, 0x12, 0x10, 0x08, 0x07, 0x06, 0x05, 0x00, 0x18, 0x01, 0x18, - 0x08, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x27, 0x23, 0x07, 0x23, 0x13, 0x33, 0x07, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, - 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x0d, 0x36, 0x43, 0x10, 0x05, 0x21, 0x42, 0xa1, 0x58, 0x26, 0x07, - 0x11, 0x0c, 0x01, 0x04, 0x24, 0x55, 0x38, 0x42, 0x51, 0x24, 0x44, 0x60, 0x44, 0x28, 0x42, 0x2f, 0x19, 0x55, 0x21, 0x45, 0x3a, 0x23, 0x32, 0x0a, 0x37, 0x25, - 0x52, 0x02, 0xf8, 0xb4, 0x22, 0x41, 0x2b, 0x02, 0x2c, 0x41, 0x5c, 0x5a, 0x49, 0x86, 0x69, 0x3d, 0x49, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x31, 0x55, 0x6c, 0x3b, - 0x30, 0x3c, 0x00, 0x01, 0x00, 0x30, 0xff, 0xf6, 0x01, 0xcd, 0x02, 0x22, 0x00, 0x1c, 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, 0x02, 0x01, 0x19, 0x0c, 0x02, 0x03, - 0x02, 0x1a, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, - 0x71, 0x00, 0x4e, 0x01, 0x00, 0x17, 0x15, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1c, 0x01, 0x1c, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, - 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0xf7, 0x59, 0x6e, 0x27, 0x49, - 0x68, 0x40, 0x23, 0x46, 0x1c, 0x19, 0x14, 0x37, 0x20, 0x39, 0x56, 0x30, 0x3f, 0x37, 0x23, 0x3f, 0x1f, 0x1c, 0x45, 0x0a, 0x64, 0x64, 0x48, 0x81, 0x62, 0x39, - 0x0e, 0x0c, 0x49, 0x09, 0x10, 0x4d, 0x80, 0x4c, 0x3d, 0x43, 0x14, 0x0d, 0x4a, 0x0e, 0x12, 0x00, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf6, 0x02, 0x55, 0x02, 0xf8, - 0x00, 0x17, 0x00, 0x26, 0x00, 0x95, 0xb6, 0x14, 0x0b, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, - 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x4b, - 0xb0, 0x29, 0x50, 0x58, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, - 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x01, 0x02, 0x85, 0x00, 0x05, 0x05, 0x01, 0x61, - 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x59, 0x40, - 0x17, 0x19, 0x18, 0x01, 0x00, 0x21, 0x1f, 0x18, 0x26, 0x19, 0x26, 0x13, 0x12, 0x11, 0x10, 0x09, 0x07, 0x00, 0x17, 0x01, 0x17, 0x08, 0x0d, 0x16, 0x2b, 0x17, - 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0x27, 0x32, 0x3e, 0x02, - 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xc1, 0x40, 0x51, 0x24, 0x45, 0x61, 0x3d, 0x36, 0x41, 0x10, 0x05, 0x05, 0x09, 0x08, 0x25, 0x57, 0xa1, - 0x48, 0x0b, 0x04, 0x24, 0x56, 0x1a, 0x21, 0x44, 0x3a, 0x23, 0x2f, 0x35, 0x28, 0x41, 0x30, 0x1a, 0x0a, 0x5c, 0x5b, 0x4a, 0x85, 0x69, 0x3c, 0x37, 0x25, 0x22, - 0x3e, 0x24, 0xaf, 0xfd, 0x08, 0x63, 0x2d, 0x40, 0x49, 0x31, 0x54, 0x6c, 0x3c, 0x30, 0x3c, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf6, - 0x01, 0xd5, 0x02, 0x22, 0x00, 0x1c, 0x00, 0x27, 0x00, 0x43, 0x40, 0x40, 0x19, 0x01, 0x03, 0x02, 0x1a, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x07, 0x01, 0x04, 0x00, - 0x02, 0x03, 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, - 0x4e, 0x1e, 0x1d, 0x01, 0x00, 0x25, 0x23, 0x1d, 0x27, 0x1e, 0x27, 0x17, 0x15, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1c, 0x01, 0x1c, 0x08, 0x0d, 0x16, 0x2b, 0x17, - 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x23, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, - 0x06, 0x03, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0xf2, 0x5d, 0x65, 0x25, 0x46, 0x63, 0x3e, 0x4c, 0x4d, 0x41, 0x8a, 0x6e, 0x11, 0x01, - 0x01, 0x3c, 0x3d, 0x26, 0x44, 0x28, 0x26, 0x49, 0x86, 0x3c, 0x66, 0x3e, 0x23, 0x25, 0x30, 0x59, 0x16, 0x0a, 0x6d, 0x5d, 0x40, 0x7d, 0x67, 0x3e, 0x42, 0x3b, - 0x34, 0x56, 0x33, 0x09, 0x14, 0x08, 0x3d, 0x47, 0x16, 0x13, 0x4b, 0x11, 0x16, 0x01, 0x39, 0x15, 0x31, 0x29, 0x1a, 0x21, 0x59, 0x51, 0x00, 0x01, 0xff, 0x90, - 0xff, 0x10, 0x01, 0xbb, 0x02, 0xfd, 0x00, 0x24, 0x00, 0x77, 0x40, 0x12, 0x16, 0x01, 0x04, 0x03, 0x17, 0x01, 0x05, 0x04, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, - 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x21, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, 0x02, 0x02, 0x05, - 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x1f, 0x00, 0x03, 0x00, 0x04, 0x05, - 0x03, 0x04, 0x69, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, - 0x59, 0x40, 0x15, 0x01, 0x00, 0x21, 0x20, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x24, 0x01, 0x24, 0x08, 0x0d, 0x16, 0x2b, 0x07, - 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, - 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x24, 0x28, 0x0c, 0x6e, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, - 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0x73, 0x0d, 0x73, 0x70, 0x12, 0x4c, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x3b, 0x37, - 0x02, 0x0a, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, 0x5e, 0x00, 0x00, 0x02, 0x00, 0x19, - 0xff, 0x10, 0x02, 0x27, 0x02, 0x22, 0x00, 0x23, 0x00, 0x32, 0x00, 0x80, 0x40, 0x0f, 0x1d, 0x0e, 0x02, 0x05, 0x06, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, - 0x01, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x00, 0x06, 0x06, 0x03, 0x61, 0x04, 0x01, 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, - 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x04, 0x04, 0x6d, 0x4d, - 0x00, 0x06, 0x06, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, - 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, 0x19, 0x25, 0x24, 0x01, 0x00, 0x2d, 0x2b, 0x24, 0x32, 0x25, 0x32, 0x20, 0x1f, 0x1b, 0x19, 0x13, 0x11, - 0x08, 0x06, 0x00, 0x23, 0x01, 0x23, 0x09, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, 0x37, 0x23, - 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x06, 0x06, 0x03, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, - 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xba, 0x31, 0x53, 0x1d, 0x1a, 0x59, 0x2b, 0x3e, 0x50, 0x10, 0x09, 0x05, 0x0f, 0x05, 0x04, 0x22, 0x57, 0x38, 0x41, 0x51, - 0x24, 0x45, 0x61, 0x3d, 0x36, 0x42, 0x10, 0x04, 0x21, 0x43, 0x7a, 0x18, 0x7b, 0x3b, 0x22, 0x44, 0x39, 0x22, 0x2d, 0x35, 0x28, 0x42, 0x30, 0x1a, 0xf0, 0x13, - 0x0f, 0x51, 0x10, 0x1a, 0x3c, 0x46, 0x26, 0x17, 0x38, 0x13, 0x2c, 0x41, 0x5d, 0x5a, 0x49, 0x86, 0x69, 0x3d, 0x38, 0x25, 0x53, 0xfd, 0xc9, 0x71, 0x60, 0x01, - 0x2f, 0x32, 0x55, 0x6c, 0x3a, 0x30, 0x3c, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x02, 0x0b, 0x02, 0xf8, 0x00, 0x1e, 0x00, 0x50, - 0xb5, 0x06, 0x01, 0x02, 0x03, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x17, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, - 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x00, 0x01, 0x00, 0x85, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, - 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1e, 0x25, 0x16, 0x28, 0x11, 0x06, 0x0d, - 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x06, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x03, 0x23, 0x13, 0x36, 0x35, 0x34, 0x26, - 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x1c, 0xa1, 0x58, 0x2b, 0x06, 0x12, 0x08, 0x05, 0x13, 0x34, 0x43, 0x2b, 0x3e, 0x49, 0x06, 0x05, 0x46, 0x58, 0x47, 0x09, - 0x21, 0x25, 0x22, 0x4f, 0x43, 0x13, 0x31, 0x02, 0xf8, 0xc5, 0x1e, 0x41, 0x20, 0x19, 0x32, 0x22, 0x45, 0x44, 0x13, 0x28, 0x17, 0xfe, 0xba, 0x01, 0x50, 0x2d, - 0x15, 0x21, 0x25, 0x2f, 0x6a, 0x58, 0xe7, 0x00, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x0e, 0x02, 0xe0, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x4d, 0x4b, 0xb0, - 0x2d, 0x50, 0x58, 0x40, 0x17, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6b, - 0x03, 0x4e, 0x1b, 0x40, 0x15, 0x00, 0x01, 0x04, 0x01, 0x00, 0x02, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, - 0x59, 0x40, 0x13, 0x0b, 0x0b, 0x01, 0x00, 0x0b, 0x0e, 0x0b, 0x0e, 0x0d, 0x0c, 0x07, 0x05, 0x00, 0x0a, 0x01, 0x0a, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, - 0x35, 0x34, 0x36, 0x33, 0x32, 0x15, 0x14, 0x06, 0x03, 0x13, 0x33, 0x03, 0xd5, 0x15, 0x1b, 0x1f, 0x1c, 0x2e, 0x24, 0xce, 0x72, 0x58, 0x72, 0x02, 0x71, 0x19, - 0x16, 0x1a, 0x26, 0x2d, 0x1f, 0x23, 0xfd, 0x8f, 0x02, 0x18, 0xfd, 0xe8, 0x00, 0x02, 0xff, 0x82, 0xff, 0x10, 0x01, 0x0d, 0x02, 0xe0, 0x00, 0x0a, 0x00, 0x18, - 0x00, 0x65, 0x40, 0x0a, 0x0e, 0x01, 0x03, 0x04, 0x0d, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x1c, 0x05, 0x01, 0x00, 0x00, 0x01, - 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x06, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x1a, - 0x00, 0x01, 0x05, 0x01, 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x06, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, - 0x59, 0x40, 0x15, 0x0c, 0x0b, 0x01, 0x00, 0x15, 0x14, 0x12, 0x10, 0x0b, 0x18, 0x0c, 0x18, 0x07, 0x05, 0x00, 0x0a, 0x01, 0x0a, 0x07, 0x0d, 0x16, 0x2b, 0x13, - 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x15, 0x14, 0x06, 0x01, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0xd4, 0x14, - 0x1b, 0x1f, 0x1c, 0x2d, 0x24, 0xfe, 0xd7, 0x25, 0x19, 0x0c, 0x1e, 0x10, 0x3d, 0x15, 0x80, 0x57, 0x82, 0x10, 0x49, 0x02, 0x71, 0x19, 0x16, 0x1a, 0x26, 0x2d, - 0x1f, 0x23, 0xfc, 0x9f, 0x0a, 0x4a, 0x04, 0x07, 0x62, 0x02, 0x5d, 0xfd, 0x9b, 0x4b, 0x58, 0x00, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x02, 0x0d, 0x02, 0xf8, - 0x00, 0x0f, 0x00, 0x47, 0xb7, 0x0d, 0x0a, 0x06, 0x03, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x12, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, - 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x12, 0x00, 0x00, 0x01, 0x00, 0x85, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x04, - 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x12, 0x16, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, - 0x03, 0x06, 0x06, 0x07, 0x33, 0x13, 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x07, 0x1b, 0xa1, 0x59, 0x41, 0x11, 0x19, 0x05, 0x02, 0xfe, 0x68, 0xe6, 0x8f, 0x61, - 0x71, 0x48, 0x28, 0x02, 0xf8, 0xfe, 0xd2, 0x50, 0x57, 0x0e, 0x01, 0x03, 0xe6, 0xfe, 0xce, 0xfb, 0x39, 0xc2, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x15, - 0x02, 0xf8, 0x00, 0x03, 0x00, 0x30, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, - 0x40, 0x0c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, - 0x17, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x1b, 0xa2, 0x58, 0xa2, 0x02, 0xf8, 0xfd, 0x08, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x03, 0x33, 0x02, 0x22, 0x00, 0x30, - 0x00, 0x56, 0xb6, 0x0b, 0x03, 0x02, 0x03, 0x04, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x02, 0x01, 0x02, - 0x00, 0x00, 0x6d, 0x4d, 0x08, 0x07, 0x05, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x1a, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x01, - 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x08, 0x07, 0x05, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x59, 0x40, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x25, - 0x14, 0x26, 0x16, 0x26, 0x25, 0x11, 0x09, 0x0d, 0x1d, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x3e, 0x02, 0x33, 0x32, - 0x16, 0x15, 0x14, 0x06, 0x07, 0x03, 0x23, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x23, 0x13, 0x36, 0x35, 0x34, 0x26, 0x23, - 0x22, 0x06, 0x06, 0x07, 0x07, 0x1c, 0x72, 0x48, 0x0b, 0x05, 0x12, 0x31, 0x41, 0x29, 0x37, 0x3b, 0x06, 0x04, 0x14, 0x37, 0x44, 0x29, 0x3e, 0x44, 0x06, 0x05, - 0x45, 0x59, 0x48, 0x05, 0x04, 0x21, 0x23, 0x20, 0x49, 0x3f, 0x11, 0x33, 0x58, 0x47, 0x09, 0x1e, 0x23, 0x20, 0x4a, 0x40, 0x13, 0x31, 0x02, 0x18, 0x63, 0x19, - 0x32, 0x22, 0x3f, 0x38, 0x1e, 0x36, 0x23, 0x44, 0x40, 0x18, 0x29, 0x17, 0xfe, 0xba, 0x01, 0x50, 0x17, 0x20, 0x0f, 0x1e, 0x24, 0x30, 0x65, 0x51, 0xf2, 0x01, - 0x50, 0x2d, 0x15, 0x21, 0x25, 0x2f, 0x6a, 0x58, 0xe7, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x02, 0x0e, 0x02, 0x25, 0x00, 0x1b, 0x00, 0x4c, 0xb5, 0x03, - 0x01, 0x02, 0x03, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x00, 0x03, 0x03, 0x00, 0x61, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, - 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, - 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x1b, 0x25, 0x16, 0x25, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x07, - 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x03, 0x23, 0x13, 0x36, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x18, 0x73, 0x4e, - 0x0b, 0x01, 0x13, 0x33, 0x44, 0x2b, 0x41, 0x49, 0x07, 0x04, 0x47, 0x5e, 0x48, 0x05, 0x05, 0x44, 0x21, 0x4d, 0x43, 0x13, 0x32, 0x02, 0x1b, 0x63, 0x19, 0x32, - 0x22, 0x47, 0x40, 0x17, 0x30, 0x12, 0xfe, 0xbb, 0x01, 0x51, 0x17, 0x1f, 0x0e, 0x40, 0x2e, 0x68, 0x58, 0xe7, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf8, 0x02, 0x04, - 0x02, 0x1f, 0x00, 0x0f, 0x00, 0x1e, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, - 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x11, 0x10, 0x01, 0x00, 0x19, 0x17, 0x10, 0x1e, 0x11, 0x1e, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, - 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x26, 0x23, 0x22, 0x06, - 0x06, 0x15, 0x14, 0x16, 0xf8, 0x5d, 0x6b, 0x22, 0x43, 0x65, 0x42, 0x5e, 0x6a, 0x22, 0x43, 0x64, 0x3e, 0x30, 0x4e, 0x2f, 0x15, 0x30, 0x28, 0x37, 0x51, 0x2c, - 0x3d, 0x08, 0x6f, 0x5f, 0x3e, 0x7a, 0x64, 0x3d, 0x6f, 0x60, 0x3d, 0x7a, 0x64, 0x3d, 0x49, 0x43, 0x7e, 0x58, 0x1e, 0x39, 0x25, 0x4b, 0x7d, 0x4b, 0x3e, 0x44, - 0x00, 0x02, 0xff, 0xea, 0xff, 0x10, 0x02, 0x12, 0x02, 0x21, 0x00, 0x17, 0x00, 0x26, 0x00, 0x68, 0xb6, 0x12, 0x03, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, - 0x1b, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, - 0x4d, 0x06, 0x01, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, - 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x14, 0x19, 0x18, 0x00, 0x00, 0x20, - 0x1e, 0x18, 0x26, 0x19, 0x26, 0x00, 0x17, 0x00, 0x17, 0x26, 0x24, 0x11, 0x08, 0x0d, 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, - 0x15, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x07, 0x13, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, - 0x16, 0xa4, 0x48, 0x0c, 0x04, 0x23, 0x58, 0x38, 0x41, 0x50, 0x24, 0x44, 0x61, 0x3c, 0x36, 0x42, 0x11, 0x05, 0x01, 0x08, 0x04, 0x31, 0xc5, 0x28, 0x42, 0x2f, - 0x19, 0x55, 0x21, 0x45, 0x3a, 0x23, 0x32, 0xf0, 0x03, 0x08, 0x64, 0x2c, 0x41, 0x5c, 0x5b, 0x49, 0x86, 0x69, 0x3c, 0x37, 0x25, 0x10, 0x39, 0x12, 0xe7, 0x01, - 0x2f, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x31, 0x54, 0x6c, 0x3c, 0x30, 0x3c, 0x00, 0x02, 0x00, 0x30, 0xff, 0x10, 0x02, 0x26, 0x02, 0x22, 0x00, 0x17, 0x00, 0x26, - 0x00, 0x61, 0xb6, 0x12, 0x03, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, - 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x02, 0x02, 0x6d, - 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, - 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x19, 0x18, 0x21, 0x1f, 0x18, 0x26, 0x19, 0x26, 0x11, 0x14, 0x26, 0x26, 0x07, 0x0d, 0x1a, 0x2b, 0x05, 0x36, 0x36, 0x37, 0x23, - 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x03, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, - 0x22, 0x0e, 0x02, 0x15, 0x14, 0x01, 0x5a, 0x05, 0x11, 0x07, 0x04, 0x22, 0x57, 0x38, 0x41, 0x51, 0x24, 0x45, 0x62, 0x3d, 0x35, 0x41, 0x10, 0x05, 0x21, 0x42, - 0xa5, 0x57, 0x4b, 0x21, 0x44, 0x39, 0x23, 0x2e, 0x34, 0x28, 0x42, 0x30, 0x1a, 0x0c, 0x13, 0x43, 0x19, 0x2c, 0x41, 0x5c, 0x5b, 0x49, 0x86, 0x69, 0x3d, 0x38, - 0x25, 0x53, 0xfc, 0xf8, 0x01, 0x2f, 0x32, 0x55, 0x6c, 0x3a, 0x2c, 0x40, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x01, 0xad, - 0x02, 0x22, 0x00, 0x13, 0x00, 0x63, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0b, 0x0c, 0x03, 0x02, 0x03, 0x02, 0x01, 0x4c, 0x0b, 0x01, 0x00, 0x4a, 0x1b, 0x40, - 0x0b, 0x0b, 0x01, 0x00, 0x01, 0x0c, 0x03, 0x02, 0x03, 0x02, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x02, 0x02, 0x00, 0x61, 0x01, - 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, - 0x01, 0x01, 0x73, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x59, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x13, 0x00, 0x13, 0x24, 0x25, 0x11, 0x05, 0x0d, 0x19, - 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x1c, 0x72, 0x48, 0x0b, 0x05, 0x15, - 0x2e, 0x3a, 0x26, 0x0e, 0x1f, 0x0d, 0x13, 0x1b, 0x18, 0x32, 0x4e, 0x34, 0x0b, 0x34, 0x02, 0x18, 0x63, 0x1c, 0x31, 0x20, 0x03, 0x04, 0x4f, 0x06, 0x42, 0x66, - 0x35, 0xf5, 0x00, 0x01, 0x00, 0x05, 0xff, 0xf6, 0x01, 0x9c, 0x02, 0x22, 0x00, 0x26, 0x00, 0x37, 0x40, 0x34, 0x16, 0x01, 0x03, 0x02, 0x17, 0x04, 0x02, 0x01, - 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, - 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1b, 0x19, 0x14, 0x12, 0x08, 0x06, 0x00, 0x26, 0x01, 0x26, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, - 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, - 0x1e, 0x02, 0x15, 0x14, 0x06, 0x9b, 0x31, 0x49, 0x1c, 0x1a, 0x4f, 0x2a, 0x3b, 0x3e, 0x26, 0x34, 0x39, 0x3a, 0x63, 0x53, 0x31, 0x53, 0x1e, 0x1c, 0x1a, 0x40, - 0x2c, 0x2b, 0x33, 0x23, 0x35, 0x22, 0x36, 0x1f, 0x71, 0x0a, 0x13, 0x0f, 0x51, 0x10, 0x1b, 0x2f, 0x25, 0x1d, 0x27, 0x1d, 0x20, 0x44, 0x33, 0x44, 0x54, 0x17, - 0x0e, 0x46, 0x0c, 0x15, 0x29, 0x20, 0x1a, 0x27, 0x1d, 0x14, 0x28, 0x34, 0x26, 0x51, 0x54, 0x00, 0x00, 0x01, 0x00, 0x2c, 0xff, 0xf6, 0x01, 0x6c, 0x02, 0x92, - 0x00, 0x1c, 0x00, 0x66, 0x40, 0x0a, 0x19, 0x01, 0x05, 0x01, 0x1a, 0x01, 0x00, 0x05, 0x02, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x03, - 0x03, 0x02, 0x70, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, - 0x1b, 0x40, 0x1c, 0x00, 0x02, 0x03, 0x02, 0x85, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, - 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x13, 0x01, 0x00, 0x17, 0x15, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x07, 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x07, 0x0d, - 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x33, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, - 0x37, 0x15, 0x06, 0x06, 0xb9, 0x36, 0x4a, 0x09, 0x3d, 0x53, 0x08, 0x5a, 0x3e, 0x34, 0x1b, 0x87, 0x0e, 0x86, 0x3e, 0x03, 0x06, 0x19, 0x1c, 0x12, 0x22, 0x13, - 0x0c, 0x32, 0x0a, 0x34, 0x41, 0x20, 0x27, 0x01, 0x23, 0x28, 0x26, 0x6f, 0x7a, 0x43, 0xfe, 0xdc, 0x0d, 0x21, 0x0e, 0x17, 0x20, 0x07, 0x06, 0x43, 0x06, 0x0c, - 0x00, 0x01, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x26, 0x02, 0x18, 0x00, 0x1b, 0x00, 0x50, 0xb5, 0x17, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, - 0x40, 0x13, 0x03, 0x01, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x05, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x17, 0x03, 0x01, - 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x04, 0x04, 0x6b, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x05, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, - 0x16, 0x15, 0x14, 0x13, 0x0f, 0x0d, 0x08, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, - 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x0e, 0x02, 0xbd, 0x3d, 0x49, 0x07, 0x04, 0x46, 0x59, 0x48, 0x09, - 0x21, 0x25, 0x22, 0x4f, 0x44, 0x13, 0x31, 0x57, 0x72, 0x48, 0x0b, 0x05, 0x13, 0x33, 0x43, 0x0a, 0x44, 0x41, 0x17, 0x29, 0x16, 0x01, 0x47, 0xfe, 0xaf, 0x2b, - 0x18, 0x20, 0x25, 0x30, 0x6a, 0x58, 0xe7, 0xfd, 0xe8, 0x63, 0x18, 0x33, 0x22, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x00, 0x02, 0x03, 0x02, 0x18, 0x00, 0x0f, - 0x00, 0x21, 0x40, 0x1e, 0x07, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, - 0x0f, 0x00, 0x0f, 0x1b, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x15, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x01, 0x6e, 0x3e, 0x58, - 0x1e, 0x03, 0x05, 0x03, 0x03, 0x0b, 0x1e, 0x1f, 0x0b, 0x9e, 0x5e, 0xfe, 0xde, 0x02, 0x18, 0xfe, 0xd6, 0x1a, 0x46, 0x3d, 0x0e, 0x19, 0x40, 0x40, 0x15, 0x01, - 0x27, 0xfd, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x39, 0x00, 0x00, 0x02, 0xf9, 0x02, 0x18, 0x00, 0x22, 0x00, 0x27, 0x40, 0x24, 0x1d, 0x11, 0x06, 0x03, 0x03, 0x00, - 0x01, 0x4c, 0x02, 0x01, 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x22, 0x11, 0x19, 0x1a, - 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x13, 0x16, 0x16, 0x07, 0x33, 0x36, 0x36, 0x37, - 0x13, 0x33, 0x03, 0x23, 0x03, 0x26, 0x36, 0x35, 0x23, 0x06, 0x06, 0x07, 0x03, 0x4f, 0x16, 0x56, 0x08, 0x02, 0x04, 0x02, 0x04, 0x08, 0x16, 0x19, 0x0a, 0x8d, - 0x5f, 0x11, 0x01, 0x02, 0x02, 0x04, 0x0d, 0x28, 0x18, 0x75, 0x5d, 0xf8, 0x6a, 0x0f, 0x02, 0x01, 0x04, 0x0d, 0x1b, 0x18, 0x8c, 0x02, 0x18, 0xfe, 0xe2, 0x37, - 0x59, 0x1d, 0x15, 0x39, 0x39, 0x15, 0x01, 0x2f, 0xfe, 0xe1, 0x25, 0x61, 0x26, 0x26, 0x67, 0x37, 0x01, 0x07, 0xfd, 0xe8, 0x01, 0x22, 0x28, 0x4a, 0x2f, 0x25, - 0x3f, 0x33, 0xfe, 0xd4, 0x00, 0x01, 0xff, 0xdb, 0x00, 0x00, 0x01, 0xfe, 0x02, 0x18, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, 0x04, 0x02, - 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x12, 0x12, 0x12, - 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x25, 0xe8, 0x74, 0x59, 0x53, 0x9d, 0x66, 0xdf, 0x7b, 0x59, - 0x5b, 0xa5, 0x01, 0x14, 0x01, 0x04, 0xc6, 0xc6, 0xfe, 0xf8, 0xfe, 0xf0, 0xd0, 0xd0, 0x00, 0x01, 0xff, 0xa2, 0xff, 0x10, 0x02, 0x03, 0x02, 0x18, 0x00, 0x1c, - 0x00, 0x30, 0x40, 0x2d, 0x12, 0x0b, 0x04, 0x03, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, - 0x61, 0x04, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x01, 0x00, 0x19, 0x18, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x05, 0x0d, 0x16, 0x2b, 0x07, 0x22, - 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x15, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x01, 0x06, 0x06, 0x19, - 0x18, 0x1f, 0x0e, 0x0e, 0x20, 0x12, 0x29, 0x39, 0x1a, 0x23, 0x51, 0x58, 0x23, 0x05, 0x05, 0x03, 0x03, 0x07, 0x1b, 0x20, 0x0c, 0x9c, 0x5e, 0xfe, 0xac, 0x28, - 0x59, 0xf0, 0x06, 0x04, 0x47, 0x04, 0x05, 0x32, 0x30, 0x3e, 0x02, 0x20, 0xfe, 0xf7, 0x20, 0x4d, 0x45, 0x15, 0x10, 0x40, 0x44, 0x16, 0x01, 0x26, 0xfd, 0x8e, - 0x4b, 0x4b, 0x00, 0x01, 0xff, 0xf1, 0x00, 0x00, 0x01, 0xb7, 0x02, 0x18, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, - 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, - 0x2b, 0x23, 0x37, 0x01, 0x23, 0x37, 0x21, 0x07, 0x01, 0x33, 0x07, 0x0f, 0x0c, 0x01, 0x4d, 0xe6, 0x0e, 0x01, 0x45, 0x0e, 0xfe, 0xb9, 0xff, 0x0d, 0x3c, 0x01, - 0x9a, 0x42, 0x47, 0xfe, 0x71, 0x42, 0x00, 0x01, 0x00, 0x0b, 0xff, 0x62, 0x01, 0x90, 0x02, 0xca, 0x00, 0x2c, 0x00, 0x37, 0x40, 0x34, 0x1d, 0x01, 0x01, 0x02, - 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, 0x05, 0x06, 0x01, 0x00, 0x05, 0x00, 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, - 0x6a, 0x04, 0x4e, 0x01, 0x00, 0x2b, 0x2a, 0x17, 0x16, 0x15, 0x13, 0x0e, 0x0d, 0x0c, 0x0b, 0x00, 0x2c, 0x01, 0x2c, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, - 0x35, 0x34, 0x36, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x23, 0x37, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, 0x33, 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x06, 0x06, - 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x15, 0xd9, 0x46, 0x4b, 0x06, 0x04, 0x18, 0x03, 0x04, 0x66, 0x11, - 0x3a, 0x46, 0x0a, 0x21, 0x11, 0x53, 0x53, 0x12, 0x0f, 0x2c, 0x32, 0x0b, 0x23, 0x0b, 0x39, 0x3b, 0x27, 0x24, 0x05, 0x04, 0x16, 0x03, 0x04, 0x29, 0x22, 0x9e, - 0x35, 0x39, 0x10, 0x21, 0x13, 0x69, 0x10, 0x1a, 0x0c, 0x46, 0x49, 0x2a, 0x33, 0x9d, 0x4f, 0x3f, 0x49, 0x1e, 0x2f, 0x9c, 0x33, 0x42, 0x0a, 0x02, 0x0a, 0x37, - 0x27, 0x0d, 0x22, 0x10, 0x66, 0x0d, 0x17, 0x0a, 0x1d, 0x14, 0x49, 0x00, 0x00, 0x01, 0x01, 0x04, 0xff, 0x0f, 0x01, 0x4c, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x30, - 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x1b, 0x40, 0x0c, 0x00, 0x00, 0x01, 0x00, - 0x85, 0x02, 0x01, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x59, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x05, 0x11, 0x33, 0x11, - 0x01, 0x04, 0x48, 0xf1, 0x03, 0xe9, 0xfc, 0x17, 0x00, 0x01, 0xff, 0xdb, 0xff, 0x62, 0x01, 0x59, 0x02, 0xca, 0x00, 0x2d, 0x00, 0x31, 0x40, 0x2e, 0x07, 0x01, - 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, - 0x02, 0x6a, 0x01, 0x4e, 0x2c, 0x2b, 0x25, 0x24, 0x23, 0x22, 0x18, 0x16, 0x15, 0x14, 0x10, 0x06, 0x0d, 0x17, 0x2b, 0x07, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, - 0x37, 0x35, 0x26, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x37, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, 0x06, 0x06, - 0x15, 0x14, 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x0e, 0x02, 0x23, 0x23, 0x25, 0x30, 0x38, 0x0a, 0x23, 0x0b, 0x3a, 0x3a, 0x27, 0x23, 0x05, 0x04, 0x17, 0x03, - 0x04, 0x2e, 0x29, 0x0f, 0x06, 0x48, 0x4b, 0x05, 0x05, 0x18, 0x03, 0x05, 0x66, 0x10, 0x3a, 0x45, 0x0b, 0x21, 0x0c, 0x2e, 0x4a, 0x38, 0x07, 0x55, 0x1e, 0x2f, - 0x9c, 0x33, 0x41, 0x0a, 0x03, 0x0b, 0x35, 0x27, 0x0e, 0x21, 0x10, 0x67, 0x0d, 0x17, 0x0a, 0x1d, 0x14, 0x49, 0x35, 0x39, 0x10, 0x21, 0x13, 0x6a, 0x10, 0x19, - 0x0c, 0x46, 0x49, 0x2a, 0x33, 0x9d, 0x38, 0x3e, 0x18, 0x00, 0x00, 0x01, 0x00, 0x46, 0x01, 0x1f, 0x02, 0x1d, 0x01, 0xa2, 0x00, 0x17, 0x00, 0x3c, 0xb1, 0x06, - 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, 0x02, 0x01, 0x13, 0x01, 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, 0x00, 0x02, 0x00, 0x03, - 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, 0x03, 0x51, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, - 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, - 0x06, 0x23, 0x22, 0x26, 0x01, 0x21, 0x24, 0x2f, 0x16, 0x1c, 0x3e, 0x18, 0x30, 0x48, 0x1d, 0x39, 0x2e, 0x24, 0x2f, 0x15, 0x1d, 0x3e, 0x18, 0x31, 0x47, 0x1c, - 0x3b, 0x01, 0x3f, 0x10, 0x0b, 0x22, 0x19, 0x4e, 0x35, 0x0c, 0x14, 0x10, 0x0b, 0x22, 0x19, 0x4d, 0x36, 0x0d, 0x00, 0x01, 0x00, 0x47, 0x01, 0xa0, 0x01, 0x8e, - 0x03, 0x55, 0x00, 0x19, 0x00, 0x32, 0x40, 0x2f, 0x0b, 0x01, 0x00, 0x01, 0x0a, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x69, - 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x19, 0x18, 0x24, 0x27, - 0x05, 0x0c, 0x19, 0x2b, 0x13, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, - 0x07, 0x07, 0x33, 0x07, 0x47, 0x0c, 0x81, 0x3c, 0x38, 0x1d, 0x1c, 0x2f, 0x30, 0x1f, 0x1f, 0x43, 0x28, 0x2a, 0x32, 0x17, 0x17, 0x36, 0x2e, 0x68, 0xbf, 0x0d, - 0x01, 0xa0, 0x37, 0x6e, 0x34, 0x44, 0x27, 0x19, 0x1e, 0x27, 0x2f, 0x19, 0x19, 0x1e, 0x2f, 0x19, 0x21, 0x38, 0x3c, 0x26, 0x57, 0x3d, 0x00, 0x01, 0x00, 0x51, - 0x01, 0x99, 0x01, 0x8c, 0x03, 0x56, 0x00, 0x27, 0x00, 0x4d, 0x40, 0x4a, 0x18, 0x01, 0x04, 0x05, 0x17, 0x01, 0x03, 0x04, 0x21, 0x01, 0x02, 0x03, 0x04, 0x01, - 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x69, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x01, 0x00, 0x51, 0x01, 0x00, 0x1c, 0x1a, 0x15, 0x13, 0x10, 0x0e, 0x0d, 0x0b, 0x08, - 0x06, 0x00, 0x27, 0x01, 0x27, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, 0x23, 0x37, 0x33, 0x32, - 0x36, 0x35, 0x34, 0x07, 0x06, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0xc4, 0x21, 0x3b, - 0x17, 0x1a, 0x3e, 0x1d, 0x32, 0x31, 0x54, 0x2e, 0x0c, 0x2e, 0x2e, 0x38, 0x40, 0x1a, 0x2d, 0x15, 0x1c, 0x17, 0x44, 0x2a, 0x3c, 0x3c, 0x36, 0x30, 0x23, 0x25, - 0x53, 0x01, 0x99, 0x0f, 0x0c, 0x41, 0x0f, 0x14, 0x2c, 0x25, 0x40, 0x37, 0x27, 0x22, 0x3b, 0x02, 0x01, 0x11, 0x0f, 0x30, 0x12, 0x19, 0x39, 0x2c, 0x2d, 0x37, - 0x0d, 0x04, 0x08, 0x31, 0x22, 0x3a, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x94, 0x01, 0x9f, 0x01, 0x60, 0x03, 0x4b, 0x00, 0x0c, 0x00, 0x19, 0x40, 0x16, 0x08, 0x07, - 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x00, 0x01, 0x01, 0x76, 0x11, 0x19, 0x02, 0x0c, 0x18, 0x2b, 0x13, 0x36, 0x36, 0x37, 0x06, - 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, 0x03, 0x23, 0xf3, 0x05, 0x11, 0x06, 0x08, 0x17, 0x0c, 0x34, 0x1c, 0x8e, 0x3e, 0x5b, 0x47, 0x02, 0x9a, 0x19, 0x3f, 0x15, - 0x07, 0x15, 0x09, 0x22, 0x2f, 0x5c, 0xfe, 0x54, 0x00, 0x01, 0xff, 0x10, 0x00, 0x00, 0x01, 0x71, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, - 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x23, 0x01, 0x33, 0x01, 0xf0, - 0x02, 0x12, 0x4f, 0xfd, 0xee, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x00, 0x02, 0x00, 0x4b, 0x01, 0xa0, 0x01, 0x8a, 0x03, 0x4f, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x61, - 0xb5, 0x10, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x0d, 0x50, 0x58, 0x40, 0x1f, 0x00, 0x01, 0x02, 0x01, 0x85, 0x06, 0x01, 0x04, 0x00, 0x00, 0x04, 0x71, - 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, 0x02, 0x02, 0x00, 0x60, 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, 0x1b, 0x40, 0x1e, 0x00, 0x01, 0x02, 0x01, - 0x85, 0x06, 0x01, 0x04, 0x00, 0x04, 0x86, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, 0x02, 0x02, 0x00, 0x60, 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, - 0x59, 0x40, 0x0f, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0c, 0x1a, 0x2b, 0x13, 0x37, 0x23, 0x37, 0x13, 0x33, 0x03, - 0x33, 0x07, 0x23, 0x07, 0x27, 0x33, 0x37, 0x36, 0x36, 0x37, 0x0e, 0x02, 0x07, 0xe9, 0x14, 0xb2, 0x0b, 0xeb, 0x47, 0x3b, 0x3d, 0x0b, 0x3f, 0x14, 0x8e, 0x6c, - 0x14, 0x06, 0x0a, 0x07, 0x04, 0x13, 0x16, 0x08, 0x01, 0xa0, 0x61, 0x34, 0x01, 0x1a, 0xfe, 0xed, 0x3b, 0x61, 0x9c, 0x5c, 0x1a, 0x2f, 0x18, 0x07, 0x1b, 0x1c, - 0x09, 0x00, 0x00, 0x01, 0x00, 0x5f, 0x01, 0x99, 0x01, 0x98, 0x03, 0x4d, 0x00, 0x1e, 0x00, 0x47, 0x40, 0x44, 0x15, 0x10, 0x02, 0x02, 0x05, 0x0f, 0x03, 0x02, - 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x01, 0x00, 0x51, 0x01, 0x00, 0x19, 0x17, 0x14, 0x13, 0x12, 0x11, 0x0d, 0x0b, 0x07, - 0x05, 0x00, 0x1e, 0x01, 0x1e, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, - 0x37, 0x33, 0x07, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc6, 0x3b, 0x2c, 0x1a, 0x36, 0x1c, 0x32, 0x36, 0x2e, 0x21, 0x10, 0x20, - 0x11, 0x1b, 0x3c, 0xd4, 0x0c, 0x9b, 0x1f, 0x09, 0x17, 0x0d, 0x38, 0x3f, 0x22, 0x4d, 0x01, 0x99, 0x19, 0x43, 0x10, 0x12, 0x33, 0x2a, 0x22, 0x22, 0x05, 0x06, - 0x17, 0xcd, 0x3e, 0x69, 0x02, 0x04, 0x3e, 0x37, 0x25, 0x49, 0x30, 0x00, 0x00, 0x01, 0x00, 0x71, 0x01, 0xa1, 0x01, 0xae, 0x03, 0x4d, 0x00, 0x06, 0x00, 0x24, - 0x40, 0x21, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, - 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, 0x23, 0x37, 0x21, 0x07, 0x03, 0x71, 0xe4, 0xc0, 0x0d, 0x01, 0x0c, 0x0a, 0xe4, 0x01, - 0xa1, 0x01, 0x71, 0x3b, 0x30, 0xfe, 0x84, 0x00, 0x00, 0x03, 0x00, 0x58, 0x01, 0x99, 0x01, 0x94, 0x03, 0x55, 0x00, 0x16, 0x00, 0x22, 0x00, 0x2e, 0x00, 0x39, - 0x40, 0x36, 0x29, 0x11, 0x05, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x05, 0x01, 0x03, 0x00, 0x00, 0x03, 0x59, 0x05, - 0x01, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x03, 0x00, 0x51, 0x24, 0x23, 0x01, 0x00, 0x23, 0x2e, 0x24, 0x2e, 0x1e, 0x1c, 0x0c, 0x0a, 0x00, 0x16, 0x01, - 0x16, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, - 0x14, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x07, 0x16, 0x36, 0x35, 0x34, 0x26, 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, - 0xd7, 0x38, 0x47, 0x6e, 0x18, 0x1d, 0x4c, 0x43, 0x3a, 0x3a, 0x35, 0x2e, 0x1e, 0x24, 0x55, 0x1b, 0x1b, 0x32, 0x1f, 0x18, 0x21, 0x24, 0x1c, 0x13, 0x26, 0x2a, - 0x23, 0x17, 0x25, 0x33, 0x25, 0x01, 0x99, 0x39, 0x32, 0x58, 0x29, 0x12, 0x29, 0x23, 0x32, 0x40, 0x3a, 0x28, 0x28, 0x3a, 0x10, 0x13, 0x30, 0x25, 0x37, 0x49, - 0x01, 0x04, 0x0a, 0x22, 0x24, 0x17, 0x1a, 0x22, 0x1a, 0x1a, 0x1f, 0xd9, 0x01, 0x29, 0x1f, 0x1a, 0x28, 0x0c, 0x0d, 0x2a, 0x23, 0x1b, 0x1f, 0x00, 0x00, 0x02, - 0x00, 0x65, 0x01, 0x98, 0x01, 0x96, 0x03, 0x59, 0x00, 0x0e, 0x00, 0x1d, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, - 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x10, 0x0f, 0x01, 0x00, 0x17, 0x15, 0x0f, 0x1d, 0x10, - 0x1d, 0x09, 0x07, 0x00, 0x0e, 0x01, 0x0e, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, - 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0xdc, 0x39, 0x3e, 0x13, 0x2b, 0x47, 0x33, 0x79, 0x15, 0x2d, 0x47, 0x2c, 0x1d, 0x2a, 0x1b, - 0x0e, 0x38, 0x1a, 0x29, 0x1d, 0x0f, 0x1a, 0x01, 0x98, 0x4d, 0x4c, 0x2d, 0x67, 0x5a, 0x3a, 0x90, 0x37, 0x6c, 0x59, 0x35, 0x3e, 0x2c, 0x49, 0x56, 0x29, 0x51, - 0x2a, 0x45, 0x52, 0x29, 0x2c, 0x2f, 0x00, 0x02, 0x00, 0x6a, 0x01, 0x99, 0x01, 0x9d, 0x03, 0x53, 0x00, 0x1a, 0x00, 0x27, 0x00, 0x4b, 0x40, 0x48, 0x09, 0x01, - 0x02, 0x01, 0x0a, 0x01, 0x03, 0x02, 0x10, 0x01, 0x05, 0x03, 0x03, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x00, 0x03, 0x00, 0x05, 0x04, 0x03, - 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x00, 0x04, 0x59, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x04, 0x00, 0x51, 0x1c, 0x1b, 0x01, 0x00, 0x22, - 0x20, 0x1b, 0x27, 0x1c, 0x27, 0x15, 0x13, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x1a, 0x01, 0x1a, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, - 0x33, 0x32, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x27, 0x32, 0x36, 0x35, 0x34, 0x26, - 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0xe2, 0x35, 0x43, 0x33, 0x6c, 0x53, 0x23, 0x1e, 0x0f, 0x0c, 0x21, 0x13, 0x3c, 0x4d, 0x0f, 0x04, 0x0b, 0x2f, 0x25, - 0x2f, 0x38, 0x22, 0x46, 0x30, 0x29, 0x2c, 0x1c, 0x1d, 0x23, 0x27, 0x0e, 0x1c, 0x01, 0x99, 0x44, 0x44, 0x52, 0x8b, 0x55, 0x08, 0x3b, 0x04, 0x05, 0x4e, 0x45, - 0x0e, 0x20, 0x3c, 0x35, 0x2a, 0x4e, 0x32, 0x3a, 0x41, 0x2a, 0x1d, 0x21, 0x24, 0x2d, 0x0d, 0x1d, 0x2e, 0x00, 0x00, 0x02, 0x00, 0x5f, 0x01, 0x99, 0x01, 0x91, - 0x03, 0x53, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x4a, 0x40, 0x47, 0x11, 0x01, 0x03, 0x04, 0x0a, 0x01, 0x02, 0x03, 0x09, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, - 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, - 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, 0x26, 0x1d, 0x26, 0x16, 0x14, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x1b, 0x01, 0x1b, - 0x08, 0x0c, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, - 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x01, 0x18, 0x36, 0x43, 0x37, 0x6c, 0x50, 0x22, 0x1d, - 0x0c, 0x27, 0x13, 0x2f, 0x42, 0x28, 0x06, 0x02, 0x11, 0x34, 0x1c, 0x2e, 0x38, 0x22, 0x46, 0x14, 0x26, 0x32, 0x1b, 0x21, 0x29, 0x2c, 0x03, 0x53, 0x43, 0x45, - 0x52, 0x8b, 0x55, 0x08, 0x3f, 0x05, 0x08, 0x2e, 0x46, 0x25, 0x1a, 0x19, 0x3c, 0x34, 0x2a, 0x4e, 0x32, 0xe2, 0x37, 0x27, 0x1d, 0x2d, 0x41, 0x2a, 0x3d, 0x00, - 0x00, 0x01, 0x00, 0x2b, 0x00, 0x00, 0x01, 0xbb, 0x02, 0xfd, 0x00, 0x18, 0x00, 0x35, 0x40, 0x32, 0x0c, 0x01, 0x02, 0x01, 0x0d, 0x01, 0x03, 0x02, 0x02, 0x4c, - 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x04, 0x01, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x28, 0x4d, 0x06, 0x01, 0x05, 0x05, 0x27, 0x05, 0x4e, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x11, 0x13, 0x25, 0x26, 0x11, 0x07, 0x07, 0x1b, 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, - 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x2b, 0x63, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, - 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0x73, 0x0d, 0x73, 0x63, 0x01, 0xd5, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, - 0x33, 0x43, 0xfe, 0x2b, 0x00, 0x01, 0xff, 0x90, 0xff, 0x10, 0x02, 0xfb, 0x02, 0xfd, 0x00, 0x44, 0x00, 0x93, 0x40, 0x16, 0x27, 0x16, 0x02, 0x04, 0x03, 0x28, - 0x17, 0x02, 0x05, 0x04, 0x39, 0x04, 0x02, 0x01, 0x02, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x27, 0x07, 0x01, 0x04, - 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, - 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x25, 0x06, 0x01, 0x03, 0x07, 0x01, 0x04, 0x05, 0x03, 0x04, 0x69, 0x0c, 0x09, 0x02, - 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, - 0x21, 0x01, 0x00, 0x41, 0x40, 0x3d, 0x3b, 0x37, 0x35, 0x32, 0x31, 0x30, 0x2f, 0x2c, 0x2a, 0x25, 0x23, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, 0x08, - 0x06, 0x00, 0x44, 0x01, 0x44, 0x0e, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, - 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, - 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x06, 0x06, 0x30, 0x13, 0x20, - 0x0d, 0x0e, 0x1a, 0x10, 0x1e, 0x2d, 0x0d, 0x6e, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, - 0x0c, 0xe7, 0x0c, 0x10, 0x2f, 0x46, 0x31, 0x1a, 0x35, 0x10, 0x18, 0x0e, 0x21, 0x13, 0x28, 0x2d, 0x0e, 0x0c, 0x74, 0x0e, 0x73, 0x70, 0x12, 0x4b, 0x49, 0x26, - 0x19, 0x0c, 0x1c, 0x10, 0x1e, 0x2c, 0x0d, 0x6e, 0xe7, 0x70, 0x12, 0x4c, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x32, 0x40, 0x02, 0x0a, 0x25, 0x21, 0x30, 0x45, - 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x34, 0x44, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, - 0x5e, 0x0a, 0x4a, 0x04, 0x07, 0x33, 0x3f, 0x02, 0x0a, 0xfd, 0xec, 0x53, 0x5e, 0x00, 0x00, 0x03, 0xff, 0x90, 0xff, 0x10, 0x03, 0x8c, 0x02, 0xfd, 0x00, 0x44, - 0x00, 0x4f, 0x00, 0x53, 0x01, 0x05, 0x40, 0x16, 0x27, 0x16, 0x02, 0x0e, 0x03, 0x28, 0x17, 0x02, 0x0d, 0x04, 0x39, 0x04, 0x02, 0x01, 0x10, 0x38, 0x03, 0x02, - 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x39, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x6c, 0x4d, 0x12, 0x01, 0x0d, - 0x0d, 0x0e, 0x61, 0x00, 0x0e, 0x0e, 0x70, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, - 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x37, 0x06, 0x01, - 0x03, 0x07, 0x01, 0x04, 0x0d, 0x03, 0x04, 0x69, 0x12, 0x01, 0x0d, 0x0d, 0x0e, 0x61, 0x00, 0x0e, 0x0e, 0x70, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, - 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, - 0x4e, 0x1b, 0x40, 0x35, 0x06, 0x01, 0x03, 0x07, 0x01, 0x04, 0x0d, 0x03, 0x04, 0x69, 0x00, 0x0e, 0x12, 0x01, 0x0d, 0x05, 0x0e, 0x0d, 0x69, 0x0c, 0x09, 0x02, - 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, - 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x31, 0x50, 0x50, 0x46, 0x45, 0x01, 0x00, 0x50, 0x53, 0x50, 0x53, 0x52, 0x51, 0x4c, 0x4a, 0x45, 0x4f, 0x46, - 0x4f, 0x41, 0x40, 0x3d, 0x3b, 0x37, 0x35, 0x32, 0x31, 0x30, 0x2f, 0x2c, 0x2a, 0x25, 0x23, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, 0x08, 0x06, 0x00, - 0x44, 0x01, 0x44, 0x14, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, - 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, - 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x06, 0x06, 0x01, 0x22, 0x26, 0x35, 0x34, - 0x36, 0x33, 0x32, 0x15, 0x14, 0x06, 0x03, 0x13, 0x33, 0x03, 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x1e, 0x2d, 0x0d, 0x6e, 0x5d, 0x07, 0x64, 0x0b, 0x10, - 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0c, 0x10, 0x2f, 0x46, 0x31, 0x1a, 0x35, 0x10, 0x18, 0x0e, 0x21, - 0x13, 0x28, 0x2d, 0x0e, 0x0c, 0x74, 0x0e, 0x73, 0x70, 0x12, 0x4b, 0x49, 0x26, 0x19, 0x0c, 0x1c, 0x10, 0x1e, 0x2c, 0x0d, 0x6e, 0xe7, 0x70, 0x12, 0x4c, 0x03, - 0x3b, 0x13, 0x1c, 0x1f, 0x1c, 0x2d, 0x24, 0xce, 0x73, 0x58, 0x73, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x32, 0x40, 0x02, 0x0a, 0x25, 0x21, 0x30, 0x45, 0x4d, - 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x34, 0x44, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, 0x5e, - 0x0a, 0x4a, 0x04, 0x07, 0x33, 0x3f, 0x02, 0x0a, 0xfd, 0xec, 0x53, 0x5e, 0x03, 0x61, 0x19, 0x16, 0x1a, 0x26, 0x2d, 0x1f, 0x23, 0xfd, 0x8f, 0x02, 0x18, 0xfd, - 0xe8, 0x00, 0x00, 0x02, 0xff, 0x90, 0xff, 0x10, 0x03, 0x93, 0x02, 0xfd, 0x00, 0x44, 0x00, 0x48, 0x01, 0x04, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x16, 0x27, - 0x16, 0x02, 0x04, 0x03, 0x28, 0x17, 0x02, 0x05, 0x04, 0x39, 0x04, 0x02, 0x01, 0x0e, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x1b, 0x40, 0x16, 0x27, 0x16, - 0x02, 0x04, 0x0d, 0x28, 0x17, 0x02, 0x05, 0x04, 0x39, 0x04, 0x02, 0x01, 0x0e, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x1d, 0x50, 0x58, - 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, - 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, - 0x50, 0x58, 0x40, 0x2c, 0x0d, 0x06, 0x02, 0x03, 0x07, 0x01, 0x04, 0x05, 0x03, 0x04, 0x69, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, - 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x33, 0x00, - 0x0d, 0x03, 0x04, 0x03, 0x0d, 0x04, 0x80, 0x06, 0x01, 0x03, 0x07, 0x01, 0x04, 0x05, 0x03, 0x04, 0x69, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, - 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, - 0x40, 0x29, 0x45, 0x45, 0x01, 0x00, 0x45, 0x48, 0x45, 0x48, 0x47, 0x46, 0x41, 0x40, 0x3d, 0x3b, 0x37, 0x35, 0x32, 0x31, 0x30, 0x2f, 0x2c, 0x2a, 0x25, 0x23, - 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x44, 0x01, 0x44, 0x11, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, - 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, - 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, - 0x37, 0x13, 0x23, 0x03, 0x06, 0x06, 0x25, 0x13, 0x33, 0x03, 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x1e, 0x2d, 0x0d, 0x6e, 0x5d, 0x07, 0x64, 0x0b, 0x10, - 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0c, 0x10, 0x2f, 0x46, 0x31, 0x1a, 0x35, 0x10, 0x18, 0x0e, 0x21, - 0x13, 0x28, 0x2d, 0x0e, 0x0c, 0x74, 0x0e, 0x73, 0x70, 0x12, 0x4b, 0x49, 0x26, 0x19, 0x0c, 0x1c, 0x10, 0x1e, 0x2c, 0x0d, 0x6e, 0xe7, 0x70, 0x12, 0x4c, 0x02, - 0x82, 0xa1, 0x58, 0xa2, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x32, 0x40, 0x02, 0x0a, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, - 0x3e, 0x33, 0x34, 0x44, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, 0x5e, 0x0a, 0x4a, 0x04, 0x07, 0x33, 0x3f, 0x02, - 0x0a, 0xfd, 0xec, 0x53, 0x5e, 0xf0, 0x02, 0xf8, 0xfd, 0x08, 0xff, 0xff, 0xff, 0x90, 0xff, 0x10, 0x02, 0x4c, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, - 0x00, 0x07, 0x00, 0x4a, 0x01, 0x3e, 0x00, 0x00, 0xff, 0xff, 0xff, 0x90, 0xff, 0x10, 0x02, 0x53, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, - 0x00, 0x4d, 0x01, 0x3e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x00, 0x02, 0xf9, 0x02, 0xfd, 0x00, 0x2d, 0x00, 0x42, 0x40, 0x3f, 0x1d, 0x0c, 0x02, 0x02, - 0x01, 0x1e, 0x0d, 0x02, 0x03, 0x02, 0x02, 0x4c, 0x04, 0x01, 0x01, 0x05, 0x01, 0x02, 0x03, 0x01, 0x02, 0x69, 0x09, 0x07, 0x02, 0x00, 0x00, 0x03, 0x5f, 0x06, - 0x01, 0x03, 0x03, 0x28, 0x4d, 0x0b, 0x0a, 0x02, 0x08, 0x08, 0x27, 0x08, 0x4e, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x2d, 0x2c, 0x2b, 0x11, 0x11, 0x13, 0x25, 0x24, - 0x13, 0x25, 0x26, 0x11, 0x0c, 0x07, 0x1f, 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, - 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x23, 0x13, 0x23, 0x03, 0x2b, - 0x63, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0b, 0x0f, 0x2f, 0x47, 0x31, - 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0x73, 0x0d, 0x73, 0x63, 0x58, 0x63, 0xe6, 0x63, 0x01, 0xd5, 0x25, 0x21, 0x30, 0x45, 0x4d, - 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x33, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfe, 0x2b, 0x01, 0xd5, - 0xfe, 0x2b, 0xff, 0xff, 0x00, 0x2b, 0x00, 0x00, 0x03, 0x8a, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x02, 0x7c, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x2b, 0x00, 0x00, 0x03, 0x91, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x02, 0x7c, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x2b, 0x00, 0x00, 0x02, 0x4c, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, 0x3e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2b, - 0x00, 0x00, 0x02, 0x53, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x3e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0d, 0xff, 0xf8, - 0x01, 0x3e, 0x01, 0xb9, 0x01, 0x07, 0x00, 0x68, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, - 0x00, 0x40, 0x00, 0x00, 0x01, 0x0c, 0x01, 0xac, 0x01, 0x07, 0x00, 0x62, 0xff, 0xac, 0xfe, 0x61, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x61, 0xb0, 0x35, - 0x2b, 0x00, 0xff, 0xff, 0xff, 0xef, 0x00, 0x00, 0x01, 0x36, 0x01, 0xb5, 0x01, 0x07, 0x00, 0x60, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, - 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x04, 0xff, 0xf9, 0x01, 0x3f, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x61, 0xff, 0xb3, 0xfe, 0x60, 0x00, 0x09, - 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x3e, 0x01, 0xaf, 0x01, 0x07, 0x00, 0x64, 0xff, 0xb4, - 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0d, 0xff, 0xf9, 0x01, 0x46, 0x01, 0xad, 0x01, 0x07, - 0x00, 0x65, 0xff, 0xae, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0xff, 0xf9, 0x01, 0x44, - 0x01, 0xb3, 0x01, 0x07, 0x00, 0x69, 0xff, 0xa7, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1f, - 0x00, 0x00, 0x01, 0x5c, 0x01, 0xac, 0x01, 0x07, 0x00, 0x66, 0xff, 0xae, 0xfe, 0x5f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x5f, 0xb0, 0x35, 0x2b, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x01, 0x3b, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x67, 0xff, 0xa7, 0xfe, 0x61, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x61, - 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x07, 0xff, 0xf9, 0x01, 0x39, 0x01, 0xb3, 0x01, 0x07, 0x00, 0x6a, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, - 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x4a, 0x01, 0x17, 0x01, 0x7b, 0x02, 0xd8, 0x01, 0x07, 0x00, 0x68, 0xff, 0xe5, 0xff, 0x7f, - 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x75, 0x01, 0x1e, 0x01, 0x41, 0x02, 0xca, 0x01, 0x07, 0x00, 0x62, - 0xff, 0xe1, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x2b, 0x01, 0x1f, 0x01, 0x72, 0x02, 0xd4, - 0x01, 0x07, 0x00, 0x60, 0xff, 0xe4, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x37, 0x01, 0x18, - 0x01, 0x72, 0x02, 0xd5, 0x01, 0x07, 0x00, 0x61, 0xff, 0xe6, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, - 0x00, 0x31, 0x01, 0x1f, 0x01, 0x70, 0x02, 0xce, 0x01, 0x07, 0x00, 0x64, 0xff, 0xe6, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, 0x35, - 0x2b, 0x00, 0xff, 0xff, 0x00, 0x45, 0x01, 0x18, 0x01, 0x7e, 0x02, 0xcc, 0x01, 0x07, 0x00, 0x65, 0xff, 0xe6, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, - 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x53, 0x01, 0x18, 0x01, 0x86, 0x02, 0xd2, 0x01, 0x07, 0x00, 0x69, 0xff, 0xe9, 0xff, 0x7f, 0x00, 0x09, - 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x5b, 0x01, 0x20, 0x01, 0x98, 0x02, 0xcc, 0x01, 0x07, 0x00, 0x66, 0xff, 0xea, - 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x3b, 0x01, 0x18, 0x01, 0x77, 0x02, 0xd4, 0x01, 0x07, - 0x00, 0x67, 0xff, 0xe3, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x49, 0x01, 0x18, 0x01, 0x7b, - 0x02, 0xd2, 0x01, 0x07, 0x00, 0x6a, 0xff, 0xea, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x8a, 0x01, 0x08, 0x00, 0x18, 0x00, 0x71, 0x00, 0x06, 0x00, 0x02, 0x00, 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x89, 0x0e, 0x0c, - 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x5b, 0x00, 0xaf, 0x01, 0x40, 0x01, 0xf5, 0x02, 0x87, 0x02, 0xa2, 0x02, 0xca, - 0x02, 0xf2, 0x03, 0x1f, 0x03, 0x47, 0x03, 0x67, 0x03, 0x83, 0x03, 0xa4, 0x03, 0xbf, 0x04, 0x09, 0x04, 0x32, 0x04, 0x74, 0x04, 0xd8, 0x05, 0x18, 0x05, 0x6c, - 0x05, 0xd7, 0x05, 0xfa, 0x06, 0x66, 0x06, 0xce, 0x07, 0x08, 0x07, 0x43, 0x07, 0x59, 0x07, 0x84, 0x07, 0x9a, 0x07, 0xf5, 0x08, 0xaa, 0x08, 0xe2, 0x09, 0x3b, - 0x09, 0x84, 0x09, 0xbc, 0x09, 0xec, 0x0a, 0x17, 0x0a, 0x6a, 0x0a, 0x98, 0x0a, 0xc2, 0x0a, 0xf3, 0x0b, 0x23, 0x0b, 0x43, 0x0b, 0x81, 0x0b, 0xb6, 0x0b, 0xfc, - 0x0c, 0x36, 0x0c, 0x85, 0x0c, 0xc7, 0x0d, 0x21, 0x0d, 0x44, 0x0d, 0x80, 0x0d, 0xad, 0x0d, 0xfb, 0x0e, 0x2a, 0x0e, 0x52, 0x0e, 0x7c, 0x0e, 0xa0, 0x0e, 0xba, - 0x0e, 0xde, 0x0f, 0x05, 0x0f, 0x25, 0x0f, 0x4f, 0x0f, 0xbd, 0x10, 0x42, 0x10, 0x8a, 0x11, 0x0e, 0x11, 0x6a, 0x11, 0xdf, 0x12, 0x69, 0x12, 0xc2, 0x13, 0x05, - 0x13, 0x62, 0x13, 0xa4, 0x13, 0xc9, 0x14, 0x3c, 0x14, 0x8e, 0x14, 0xd3, 0x15, 0x41, 0x15, 0xac, 0x15, 0xff, 0x16, 0x54, 0x16, 0xb4, 0x17, 0x09, 0x17, 0x38, - 0x17, 0x86, 0x17, 0xb2, 0x17, 0xfa, 0x18, 0x23, 0x18, 0x81, 0x18, 0xa6, 0x19, 0x02, 0x19, 0x47, 0x19, 0x8a, 0x19, 0xeb, 0x1a, 0x12, 0x1a, 0x2d, 0x1a, 0x84, - 0x1a, 0xd7, 0x1a, 0xfc, 0x1b, 0x5f, 0x1b, 0xa4, 0x1c, 0x05, 0x1c, 0x64, 0x1c, 0xa7, 0x1d, 0x55, 0x1e, 0x53, 0x1f, 0x41, 0x1f, 0x4d, 0x1f, 0x59, 0x1f, 0xbf, - 0x1f, 0xcb, 0x1f, 0xd7, 0x1f, 0xe3, 0x1f, 0xef, 0x1f, 0xfe, 0x20, 0x0d, 0x20, 0x1c, 0x20, 0x2b, 0x20, 0x3a, 0x20, 0x49, 0x20, 0x58, 0x20, 0x67, 0x20, 0x76, - 0x20, 0x85, 0x20, 0x94, 0x20, 0xa3, 0x20, 0xb2, 0x20, 0xc1, 0x20, 0xd0, 0x20, 0xdf, 0x20, 0xee, 0x20, 0xfd, 0x21, 0x0c, 0x21, 0x1b, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, 0x57, 0x3e, 0x69, 0x66, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xcc, 0xa2, - 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc4, 0x0f, 0xfd, 0x67, 0xfe, 0x7b, 0x0a, 0xcf, 0x04, 0x3c, 0x00, 0x02, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x58, 0x00, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x01, 0x05, 0x00, 0x14, 0x01, 0x88, 0x00, 0x6d, 0x02, 0x86, 0x00, 0x1e, 0x02, 0x27, 0x00, 0x22, - 0x03, 0x1f, 0x00, 0x50, 0x02, 0xa1, 0x00, 0x20, 0x00, 0xdc, 0x00, 0x6d, 0x01, 0x22, 0x00, 0x28, 0x01, 0x22, 0xff, 0xb3, 0x02, 0x27, 0x00, 0x67, 0x02, 0x3c, - 0x00, 0x46, 0x01, 0x00, 0xff, 0xd5, 0x01, 0x39, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x14, 0x01, 0x64, 0xff, 0xd2, 0x02, 0x27, 0x00, 0x39, 0x02, 0x27, 0x00, 0x8f, - 0x02, 0x27, 0x00, 0x03, 0x02, 0x27, 0x00, 0x16, 0x02, 0x27, 0x00, 0x06, 0x02, 0x27, 0x00, 0x25, 0x02, 0x27, 0x00, 0x3f, 0x02, 0x27, 0x00, 0x51, 0x02, 0x27, - 0x00, 0x2d, 0x02, 0x27, 0x00, 0x2f, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0xff, 0xcf, 0x02, 0x3c, 0x00, 0x46, 0x02, 0x3c, 0x00, 0x4c, 0x02, 0x3c, 0x00, 0x46, - 0x01, 0xae, 0x00, 0x4d, 0x03, 0x50, 0x00, 0x35, 0x02, 0x32, 0xff, 0xc7, 0x02, 0x58, 0x00, 0x29, 0x02, 0x4b, 0x00, 0x48, 0x02, 0x9b, 0x00, 0x29, 0x02, 0x02, - 0x00, 0x29, 0x01, 0xdd, 0x00, 0x29, 0x02, 0xa6, 0x00, 0x48, 0x02, 0xa8, 0x00, 0x2a, 0x01, 0x44, 0xff, 0xec, 0x01, 0x11, 0xff, 0x64, 0x02, 0x32, 0x00, 0x29, - 0x01, 0xde, 0x00, 0x29, 0x03, 0x49, 0x00, 0x28, 0x02, 0xc3, 0x00, 0x28, 0x02, 0xd1, 0x00, 0x48, 0x02, 0x37, 0x00, 0x29, 0x02, 0xd1, 0x00, 0x48, 0x02, 0x3d, - 0x00, 0x29, 0x01, 0xf9, 0x00, 0x13, 0x01, 0xf5, 0x00, 0x5a, 0x02, 0xa5, 0x00, 0x4f, 0x02, 0x28, 0x00, 0x5c, 0x03, 0x58, 0x00, 0x6b, 0x02, 0x0f, 0xff, 0xcc, - 0x01, 0xfd, 0x00, 0x5c, 0x02, 0x13, 0xff, 0xf6, 0x01, 0x22, 0xff, 0xf7, 0x01, 0x64, 0x00, 0x6c, 0x01, 0x22, 0xff, 0xb8, 0x02, 0x3c, 0x00, 0x26, 0x01, 0x8b, - 0xff, 0xa4, 0x01, 0x16, 0x00, 0x92, 0x02, 0x38, 0x00, 0x30, 0x02, 0x43, 0x00, 0x1c, 0x01, 0xc5, 0x00, 0x30, 0x02, 0x43, 0x00, 0x30, 0x01, 0xf3, 0x00, 0x30, - 0x01, 0x3e, 0xff, 0x90, 0x02, 0x43, 0x00, 0x19, 0x02, 0x43, 0x00, 0x1c, 0x01, 0x02, 0x00, 0x1c, 0x01, 0x02, 0xff, 0x82, 0x01, 0xef, 0x00, 0x1b, 0x01, 0x02, - 0x00, 0x1b, 0x03, 0x6b, 0x00, 0x1c, 0x02, 0x43, 0x00, 0x18, 0x02, 0x33, 0x00, 0x30, 0x02, 0x43, 0xff, 0xea, 0x02, 0x43, 0x00, 0x30, 0x01, 0x8e, 0x00, 0x1c, - 0x01, 0xb0, 0x00, 0x05, 0x01, 0x4c, 0x00, 0x2c, 0x02, 0x43, 0x00, 0x37, 0x01, 0xd3, 0x00, 0x30, 0x02, 0xd3, 0x00, 0x39, 0x01, 0xe3, 0xff, 0xdb, 0x01, 0xd3, - 0xff, 0xa2, 0x01, 0xbd, 0xff, 0xf1, 0x01, 0x5e, 0x00, 0x0b, 0x02, 0x27, 0x01, 0x04, 0x01, 0x5e, 0xff, 0xdb, 0x02, 0x3c, 0x00, 0x46, 0x01, 0x61, 0x00, 0x47, - 0x01, 0x61, 0x00, 0x51, 0x01, 0x61, 0x00, 0x94, 0x00, 0x82, 0xff, 0x10, 0x01, 0x61, 0x00, 0x4b, 0x01, 0x61, 0x00, 0x5f, 0x01, 0x61, 0x00, 0x71, 0x01, 0x61, - 0x00, 0x58, 0x01, 0x61, 0x00, 0x65, 0x01, 0x61, 0x00, 0x6a, 0x01, 0x61, 0x00, 0x5f, 0x01, 0x3e, 0x00, 0x2b, 0x02, 0x7e, 0xff, 0x90, 0x03, 0x80, 0xff, 0x90, - 0x03, 0x80, 0xff, 0x90, 0x02, 0x40, 0xff, 0x90, 0x02, 0x40, 0xff, 0x90, 0x02, 0x7c, 0x00, 0x2b, 0x03, 0x7e, 0x00, 0x2b, 0x03, 0x7e, 0x00, 0x2b, 0x02, 0x40, - 0x00, 0x2b, 0x02, 0x40, 0x00, 0x2b, 0x01, 0x61, 0x00, 0x0d, 0x00, 0x40, 0xff, 0xef, 0x00, 0x04, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x1f, 0xff, 0xff, - 0x00, 0x07, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x2b, 0x00, 0x37, 0x00, 0x31, 0x00, 0x45, 0x00, 0x53, 0x00, 0x5b, 0x00, 0x3b, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x0a, 0xf0, 0xfd, 0x67, 0xfd, 0x67, 0x0a, 0xcf, 0x03, 0xe8, 0x00, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, 0x02, 0x26, 0x01, 0x90, 0x00, 0x05, 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, 0xff, 0xf0, 0x00, 0x4b, - 0x02, 0x8a, 0x02, 0x58, 0x00, 0x4a, 0x01, 0x5e, 0x00, 0x32, 0x01, 0x42, 0x00, 0x00, 0x02, 0x0b, 0x05, 0x02, 0x04, 0x05, 0x04, 0x09, 0x02, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x01, 0x81, 0x00, 0x20, 0x00, 0x7e, 0x04, 0x2d, - 0xfe, 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x02, 0xca, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, - 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, 0x21, 0xb0, - 0x00, 0x59, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, 0x02, 0x2c, - 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, - 0x14, 0x43, 0x42, 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, 0x04, 0x50, 0x78, - 0xb2, 0x02, 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, 0x20, 0xb0, 0x02, 0x43, - 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, - 0x2c, 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x1b, 0x20, 0x64, - 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, - 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, 0x38, - 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x20, 0xb0, - 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, - 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, 0x1b, 0xb0, - 0x02, 0x25, 0xb0, 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, 0xb0, 0x1e, 0x50, - 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, - 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, 0x20, 0x45, 0x20, 0xb0, - 0x04, 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, 0x59, 0xb0, 0x01, 0x60, 0x2d, - 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, - 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, 0xb0, 0x08, 0x43, 0x20, 0x8a, 0x20, - 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, - 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, 0x43, 0x2b, - 0xb2, 0x00, 0x02, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, 0x62, 0x66, - 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, - 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, 0x0e, 0x00, 0x43, - 0x45, 0x42, 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, - 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, - 0x64, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, - 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, - 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, - 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, 0x0c, 0x00, - 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, - 0x2c, 0xb0, 0x01, 0x60, 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, 0xb0, 0x00, - 0x52, 0x58, 0x20, 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, 0x00, 0x63, 0x8a, - 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, - 0x59, 0x24, 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x1b, 0x21, 0x59, 0x24, - 0xb0, 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, 0x61, 0x42, 0xb0, 0x11, 0x2b, - 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, - 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x23, 0xb0, 0x01, 0x61, 0x20, - 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, - 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x20, - 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, 0x00, 0x13, - 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, - 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, - 0x13, 0x00, 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, - 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, - 0x2c, 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, - 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, - 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x5d, - 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, - 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, - 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, - 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, 0x01, 0x00, 0x11, - 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, - 0x2c, 0xb1, 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, 0xb0, 0x25, 0x2c, 0xb1, - 0x04, 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, 0x28, 0x2c, 0xb1, 0x07, 0x20, - 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, - 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x01, 0x60, 0xb0, 0x2e, 0x2a, - 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, - 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, 0x20, 0x47, - 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, - 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, - 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, - 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x34, 0x2c, 0x20, - 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, - 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, - 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, - 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, - 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, 0x20, 0x3c, - 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, - 0x00, 0x43, 0x61, 0xb0, 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb0, - 0x02, 0x25, 0x49, 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, 0x01, 0x15, 0x14, - 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, - 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, - 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, - 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, - 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, - 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, - 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, - 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, 0x02, 0x25, - 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, - 0xb0, 0x01, 0x63, 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, 0x25, 0xb0, 0x02, - 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, 0x60, 0x64, 0x23, 0xb0, - 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, - 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x3c, 0x38, 0x2d, 0xb0, 0x3d, - 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, - 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, 0x2e, - 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, - 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, - 0x59, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, 0x20, 0x3c, - 0x8a, 0x38, 0x23, 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, - 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, - 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, - 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, - 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, - 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, - 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, - 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, 0x20, 0x20, - 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, - 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, - 0x26, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, 0x20, 0x3c, 0x20, - 0x2e, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, - 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, - 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, 0xb0, 0x06, 0x43, 0xb0, 0x02, - 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, - 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, - 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, 0x23, 0x38, - 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, - 0x3a, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x23, - 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, - 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, - 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, 0xb0, 0x4c, 0x2c, 0xb0, - 0x39, 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, - 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, - 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x53, 0x2c, 0xb2, 0x00, 0x00, - 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, - 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x59, - 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x43, - 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, - 0x01, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x61, - 0x2c, 0xb2, 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, 0x48, 0x2b, 0x2d, 0xb0, - 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, - 0xb0, 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x69, 0x2c, 0xb3, 0x01, 0x00, - 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, - 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x44, - 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, - 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, - 0xb0, 0x73, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, 0x2c, 0xb0, - 0x00, 0x16, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x77, - 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, - 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, - 0x2d, 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, - 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, - 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, - 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, - 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x87, - 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, 0x01, 0x3f, - 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, - 0xb0, 0x06, 0x1b, 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, 0x50, 0x78, 0xb1, - 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, 0xb9, 0x08, 0x00, 0x08, - 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, 0x00, 0x49, 0x39, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, - 0x14, 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, 0x02, 0x56, 0x06, 0x4e, 0x04, 0x3e, 0x08, 0x32, 0x06, 0x24, 0x07, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x07, 0x42, - 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x52, 0x02, 0x46, 0x06, 0x38, 0x04, 0x2b, 0x05, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, - 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, 0x13, 0xc0, 0x0f, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, - 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x09, - 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, - 0x28, 0x01, 0x88, 0x51, 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, 0xba, 0x08, - 0x80, 0x00, 0x01, 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, 0x06, 0x7a, 0x06, - 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x50, 0x02, 0x40, 0x06, 0x34, 0x04, 0x26, 0x05, 0x09, 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, - 0x00, 0x44, 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x48, 0x02, 0xca, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd6, 0xff, 0xf6, 0x02, 0x20, - 0xff, 0xf6, 0xff, 0x10, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4c, 0x00, 0x4c, 0x02, 0x3b, 0x02, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x44, 0x02, 0x47, 0xff, 0xf8, - 0x00, 0x00, 0x00, 0x59, 0x00, 0x59, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0xff, 0xf6, 0x02, 0xf8, 0x02, 0x18, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, - 0x02, 0xfd, 0x02, 0x21, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4c, 0x00, 0x4c, 0x02, 0x3b, 0x00, 0x00, 0x02, 0x44, 0xff, 0xf8, 0x00, 0x45, - 0x00, 0x45, 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x45, 0x00, 0x45, - 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x59, 0x00, 0x59, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0x00, 0x00, 0x02, 0xec, 0x02, 0x18, 0x00, 0x00, - 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xec, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x2c, 0x00, 0x2c, 0x01, 0x2b, 0xff, 0x7e, - 0x01, 0x61, 0x00, 0xe2, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x34, 0xff, 0x77, 0x01, 0x61, 0x00, 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x2c, - 0x00, 0x2c, 0x02, 0xcb, 0x01, 0x9f, 0x02, 0xe0, 0x02, 0x61, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe0, 0x01, 0x98, 0x02, 0xe0, 0x02, 0x67, 0x01, 0x19, 0x00, 0x8f, - 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, - 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x0c, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x34, - 0x00, 0xd4, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x20, 0x01, 0x08, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, 0x01, 0x28, - 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x1e, 0x01, 0x7c, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, - 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x4e, - 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x41, - 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, - 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, - 0x00, 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, - 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, - 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, - 0x00, 0x6e, 0x00, 0x73, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, - 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, - 0x00, 0x73, 0x00, 0x2d, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, - 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x56, 0x00, 0x65, - 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x20, - 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, - 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, - 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, - 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x03, 0x00, 0x00, 0xff, 0xf4, 0x00, 0x00, 0xff, 0x9c, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, - 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x22, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x42, 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6b, - 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x02, 0x00, 0x18, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x32, 0x00, 0x3c, 0x00, 0x4a, 0x00, 0x4a, 0x00, 0x2a, 0x00, 0x32, - 0x00, 0x3c, 0x00, 0x4a, 0x00, 0x4a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0xfa, 0x00, 0x01, - 0x00, 0x04, 0x00, 0x01, 0x00, 0xff, 0x00, 0x02, 0x00, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0xf7, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x00, 0xf9, - 0x00, 0x01, 0x02, 0x2d, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, - 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0x65, 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x06, 0x06, 0xc8, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x01, 0x08, 0x00, 0x01, 0x00, 0x38, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, - 0x00, 0x6a, 0x00, 0xf4, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x8c, 0x00, 0xb4, 0x00, 0x92, 0x00, 0x98, 0x00, 0xb4, 0x00, 0xaa, 0x00, 0xb4, 0x00, 0xba, 0x00, 0xc4, - 0x00, 0xc4, 0x00, 0xce, 0x00, 0xd8, 0x00, 0xf4, 0x00, 0xde, 0x00, 0xe4, 0x00, 0xee, 0x00, 0xee, 0x00, 0xee, 0x00, 0xf4, 0x00, 0x01, 0x00, 0x17, 0x00, 0x07, - 0x00, 0x09, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, 0x00, 0x38, - 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, 0x37, - 0xff, 0xd8, 0x00, 0x38, 0xff, 0xd8, 0x00, 0x3a, 0xff, 0xc4, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x4b, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xec, 0x00, 0x0f, 0xff, 0xec, - 0x00, 0x01, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x04, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, 0x00, 0x20, 0x00, 0x14, - 0x00, 0x22, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x39, 0xff, 0xec, 0x00, 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, - 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, - 0x00, 0x07, 0xff, 0xec, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, - 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, 0x03, 0xd8, 0x00, 0x04, 0x00, 0x00, 0x04, 0x26, 0x04, 0xe4, 0x00, 0x16, 0x00, 0x16, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, - 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, 0xff, 0xe2, 0xff, 0xce, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, - 0x00, 0x00, 0xff, 0xc4, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xf6, 0x00, 0x00, 0xff, 0xd8, 0xff, 0xec, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xec, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xf6, 0x00, 0x00, 0xff, 0xce, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0xff, 0xe2, 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, - 0xff, 0xce, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x0a, 0xff, 0xc4, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, - 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x88, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, - 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x25, 0x00, 0x03, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, - 0x00, 0x25, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, - 0x00, 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x4c, 0x00, 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, - 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x09, - 0x00, 0x13, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x22, 0x00, 0x22, 0x00, 0x01, - 0x00, 0x24, 0x00, 0x24, 0x00, 0x07, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x08, 0x00, 0x30, - 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, - 0x00, 0x05, 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x39, 0x00, 0x39, 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x06, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0d, - 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x02, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x10, 0x00, 0x53, - 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0c, 0x00, 0x57, 0x00, 0x58, 0x00, 0x04, 0x00, 0x59, 0x00, 0x59, 0x00, 0x10, 0x00, 0x5a, 0x00, 0x5a, - 0x00, 0x04, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x15, 0x00, 0x02, 0x00, 0x23, 0x00, 0x03, 0x00, 0x03, 0x00, 0x11, 0x00, 0x08, - 0x00, 0x08, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, - 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x05, 0x00, 0x24, 0x00, 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x28, 0x00, 0x02, - 0x00, 0x30, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x32, 0x00, 0x02, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, - 0x00, 0x38, 0x00, 0x09, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x08, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, - 0x00, 0x04, 0x00, 0x44, 0x00, 0x46, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x48, 0x00, 0x48, 0x00, 0x0d, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x03, - 0x00, 0x50, 0x00, 0x50, 0x00, 0x01, 0x00, 0x51, 0x00, 0x51, 0x00, 0x03, 0x00, 0x52, 0x00, 0x52, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x03, 0x00, 0x54, - 0x00, 0x54, 0x00, 0x0a, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0e, 0x00, 0x56, 0x00, 0x56, 0x00, 0x03, 0x00, 0x57, 0x00, 0x58, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x5a, - 0x00, 0x07, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x5e, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x15, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, - 0x00, 0x08, 0x00, 0x02, 0x00, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x02, 0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, - 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x50, 0x00, 0x92, 0x00, 0x04, - 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1e, 0x00, 0x0e, - 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x45, 0x57, 0x45, 0x20, 0x00, 0x18, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x20, 0x66, 0x72, - 0x61, 0x63, 0x00, 0x26, 0x6c, 0x69, 0x67, 0x61, 0x00, 0x30, 0x6c, 0x6f, 0x63, 0x6c, 0x00, 0x36, 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x3c, 0x00, 0x4a, 0x00, 0x5e, 0x00, 0x76, 0x00, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x12, 0x00, 0x06, 0x00, 0x6b, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x01, 0x00, 0x06, - 0x00, 0x47, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x65, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0a, - 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, - 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x01, 0x00, 0x76, 0x00, 0x7f, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x00, 0x89, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x66, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x38, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, - 0x00, 0x22, 0x00, 0x28, 0x00, 0x6e, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x4a, - 0x00, 0x70, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x47, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x73, - 0x00, 0x03, 0x00, 0x6b, 0x00, 0x4d, 0x00, 0x72, 0x00, 0x03, 0x00, 0x6b, 0x00, 0x4a, 0x00, 0x74, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x02, 0x00, 0x4d, - 0x00, 0x71, 0x00, 0x02, 0x00, 0x6b, 0x00, 0x01, 0x00, 0x02, 0x00, 0x47, 0x00, 0x6b}; - -const inline uint8_t FONT_BOLD_DATA[] = { - 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x06, 0x75, 0x08, 0xc3, 0x00, 0x00, 0x4f, 0x3c, 0x00, 0x00, - 0x00, 0x6c, 0x47, 0x50, 0x4f, 0x53, 0x28, 0x98, 0x0a, 0xef, 0x00, 0x00, 0x4f, 0xa8, 0x00, 0x00, 0x07, 0xb2, 0x47, 0x53, 0x55, 0x42, 0x39, 0x7a, 0x34, 0x30, - 0x00, 0x00, 0x57, 0x5c, 0x00, 0x00, 0x01, 0x50, 0x4f, 0x53, 0x2f, 0x32, 0x6a, 0x81, 0x61, 0x8b, 0x00, 0x00, 0x3c, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, - 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x3c, 0xbc, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, 0x20, 0x41, 0xb6, 0x1e, 0xcf, 0x00, 0x00, 0x4c, 0x04, - 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, 0x0b, 0x83, 0x00, 0x00, 0x3c, 0xf0, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x4f, 0x34, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0xea, 0xe8, 0x66, 0x13, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x37, 0xca, - 0x68, 0x65, 0x61, 0x64, 0x28, 0x6e, 0xdc, 0x4a, 0x00, 0x00, 0x3a, 0x14, 0x00, 0x00, 0x00, 0x36, 0x68, 0x68, 0x65, 0x61, 0x0c, 0x9d, 0x0b, 0xd8, 0x00, 0x00, - 0x3c, 0x38, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0xf4, 0x22, 0x11, 0xe6, 0x00, 0x00, 0x3a, 0x4c, 0x00, 0x00, 0x01, 0xea, 0x6c, 0x6f, 0x63, 0x61, - 0x08, 0xbe, 0xfb, 0x1b, 0x00, 0x00, 0x39, 0x08, 0x00, 0x00, 0x01, 0x0a, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x55, 0x10, 0x44, 0x00, 0x00, 0x38, 0xe8, 0x00, 0x00, - 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x27, 0x83, 0x40, 0x7b, 0x00, 0x00, 0x4d, 0x30, 0x00, 0x00, 0x01, 0xe4, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x9f, 0x00, 0x32, - 0x00, 0x00, 0x4f, 0x14, 0x00, 0x00, 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0x44, 0x7e, 0xc6, 0xb9, 0x00, 0x00, 0x4a, 0xfc, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, - 0x00, 0x36, 0xff, 0xf3, 0x00, 0xe3, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, - 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x24, 0x23, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x37, 0x23, 0x03, 0x33, 0x03, 0x34, 0x36, - 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0xc9, 0x78, 0x19, 0xaa, 0xac, 0x33, 0x24, 0x23, 0x33, 0x33, 0x23, 0x24, 0x33, 0xe8, 0x01, 0xe2, 0xfd, - 0x7c, 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x02, 0x00, 0x3d, 0x01, 0xc8, 0x01, 0xa1, 0x02, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x40, 0x21, - 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x05, 0x03, 0x04, 0x03, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, - 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0x21, 0x03, 0x23, 0x03, 0xcd, 0x14, 0x68, 0x14, 0x01, 0x64, 0x14, 0x67, 0x14, 0x02, - 0xca, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x00, 0x16, 0x00, 0x00, 0x02, 0x70, 0x02, 0xc9, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, - 0x40, 0x44, 0x0c, 0x0a, 0x02, 0x08, 0x0f, 0x10, 0x0d, 0x03, 0x07, 0x00, 0x08, 0x07, 0x68, 0x0e, 0x06, 0x02, 0x00, 0x05, 0x03, 0x02, 0x01, 0x02, 0x00, 0x01, - 0x67, 0x0b, 0x01, 0x09, 0x09, 0x6a, 0x4d, 0x04, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, 0x1c, 0x00, 0x1b, 0x00, 0x1b, 0x1a, 0x19, - 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0d, 0x1f, 0x2b, 0x01, 0x07, 0x33, 0x15, 0x23, 0x07, 0x23, - 0x37, 0x23, 0x07, 0x23, 0x37, 0x23, 0x35, 0x33, 0x37, 0x23, 0x35, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, 0x15, 0x05, 0x33, 0x37, 0x23, 0x01, - 0xe8, 0x17, 0x7e, 0x91, 0x26, 0x6b, 0x26, 0x5f, 0x25, 0x69, 0x24, 0x74, 0x87, 0x17, 0x7b, 0x8d, 0x26, 0x6b, 0x26, 0x61, 0x26, 0x69, 0x26, 0x75, 0xfe, 0x97, - 0x60, 0x17, 0x60, 0x01, 0x9c, 0x71, 0x65, 0xc6, 0xc6, 0xc6, 0xc6, 0x65, 0x71, 0x66, 0xc7, 0xc7, 0xc7, 0xc7, 0x66, 0x71, 0x71, 0x00, 0x00, 0x03, 0x00, 0x2b, - 0xff, 0xc6, 0x02, 0x15, 0x02, 0xf7, 0x00, 0x22, 0x00, 0x28, 0x00, 0x2e, 0x00, 0x3f, 0x40, 0x3c, 0x2e, 0x29, 0x28, 0x23, 0x19, 0x18, 0x15, 0x14, 0x08, 0x04, - 0x0a, 0x01, 0x03, 0x20, 0x03, 0x02, 0x00, 0x01, 0x02, 0x4c, 0x0f, 0x01, 0x03, 0x01, 0x4b, 0x00, 0x03, 0x02, 0x01, 0x02, 0x03, 0x01, 0x80, 0x00, 0x01, 0x00, - 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x04, 0x04, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6c, 0x04, 0x4e, 0x1e, 0x11, 0x19, 0x15, 0x10, 0x05, 0x0d, 0x1b, 0x2b, 0x37, - 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x35, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x37, 0x35, 0x33, 0x15, 0x16, 0x17, 0x07, 0x26, 0x26, 0x27, 0x15, 0x1e, 0x02, - 0x15, 0x14, 0x06, 0x07, 0x15, 0x23, 0x11, 0x06, 0x15, 0x14, 0x16, 0x17, 0x13, 0x36, 0x35, 0x34, 0x26, 0x27, 0xfd, 0x41, 0x66, 0x2a, 0x29, 0x74, 0x34, 0x4d, - 0x5d, 0x28, 0x75, 0x5d, 0x43, 0x6f, 0x5b, 0x2e, 0x28, 0x51, 0x23, 0x36, 0x62, 0x3d, 0x6a, 0x6b, 0x43, 0x3f, 0x1e, 0x21, 0x43, 0x42, 0x21, 0x21, 0x28, 0x02, - 0x15, 0x13, 0x81, 0x14, 0x21, 0x03, 0x97, 0x1e, 0x39, 0x46, 0x31, 0x4b, 0x59, 0x08, 0x4b, 0x49, 0x04, 0x29, 0x72, 0x11, 0x12, 0x03, 0x90, 0x14, 0x2f, 0x48, - 0x3b, 0x49, 0x62, 0x0a, 0x64, 0x02, 0x6d, 0x09, 0x2a, 0x15, 0x1c, 0x0f, 0xfe, 0xde, 0x0c, 0x2e, 0x14, 0x1d, 0x0f, 0x00, 0x00, 0x05, 0x00, 0x1e, 0xff, 0xf7, - 0x03, 0x68, 0x02, 0xd4, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x33, 0x00, 0xd2, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x2c, 0x0d, 0x01, 0x06, - 0x0e, 0x01, 0x08, 0x01, 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, 0x0b, 0x03, 0x0a, 0x03, 0x00, - 0x00, 0x70, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x07, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x1a, 0x50, 0x58, 0x40, 0x30, 0x0d, 0x01, 0x06, - 0x0e, 0x01, 0x08, 0x01, 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0b, 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x0c, 0x01, 0x04, 0x04, 0x00, - 0x61, 0x0a, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x07, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x34, 0x0d, 0x01, 0x06, 0x0e, - 0x01, 0x08, 0x01, 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0b, 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, - 0x0a, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x09, 0x09, 0x07, 0x61, 0x00, 0x07, 0x07, 0x71, 0x07, 0x4e, 0x59, 0x59, 0x40, 0x2b, - 0x29, 0x28, 0x1d, 0x1c, 0x11, 0x10, 0x0c, 0x0c, 0x01, 0x00, 0x2f, 0x2d, 0x28, 0x33, 0x29, 0x33, 0x23, 0x21, 0x1c, 0x27, 0x1d, 0x27, 0x17, 0x15, 0x10, 0x1b, - 0x11, 0x1b, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, - 0x26, 0x35, 0x34, 0x36, 0x05, 0x01, 0x23, 0x01, 0x05, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x05, 0x32, 0x16, 0x15, 0x14, 0x06, - 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xc6, 0x50, 0x5c, 0x56, 0x56, 0x4e, 0x5a, 0x55, - 0x02, 0x50, 0xfe, 0x74, 0x77, 0x01, 0x8c, 0xfe, 0x7b, 0x1b, 0x18, 0x18, 0x1b, 0x1c, 0x19, 0x19, 0x01, 0xd9, 0x4f, 0x5d, 0x57, 0x55, 0x4e, 0x5a, 0x55, 0x54, - 0x1c, 0x17, 0x17, 0x1c, 0x1c, 0x19, 0x19, 0x02, 0xd4, 0x75, 0x6a, 0x6a, 0x77, 0x77, 0x6a, 0x6a, 0x75, 0x0a, 0xfd, 0x36, 0x02, 0xca, 0x57, 0x42, 0x3d, 0x3d, - 0x43, 0x42, 0x3e, 0x3d, 0x42, 0xbc, 0x75, 0x6a, 0x6a, 0x77, 0x77, 0x6a, 0x6a, 0x75, 0x61, 0x42, 0x3d, 0x3d, 0x43, 0x42, 0x3e, 0x3e, 0x41, 0x00, 0x00, 0x03, - 0x00, 0x28, 0xff, 0xf6, 0x02, 0xee, 0x02, 0xd4, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x37, 0x00, 0x7d, 0x40, 0x12, 0x28, 0x1b, 0x02, 0x01, 0x04, 0x37, 0x0f, 0x08, - 0x07, 0x04, 0x05, 0x01, 0x12, 0x01, 0x02, 0x05, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x23, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, - 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, - 0x1b, 0x40, 0x21, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6b, 0x4d, 0x00, - 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x59, 0x40, 0x17, 0x23, 0x22, 0x01, 0x00, 0x35, 0x33, 0x22, 0x2d, 0x23, 0x2d, 0x16, 0x14, 0x11, - 0x10, 0x0c, 0x0b, 0x00, 0x21, 0x01, 0x21, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, - 0x07, 0x17, 0x23, 0x27, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, - 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x01, 0x36, 0x3a, 0x5a, 0x34, 0x52, 0x3d, 0x8b, 0x14, 0x1e, 0x0a, - 0x9b, 0x0f, 0x3a, 0x2d, 0x93, 0xb8, 0x38, 0x2b, 0x6a, 0x3e, 0x7a, 0x89, 0x46, 0x3d, 0x27, 0x1f, 0x35, 0x5f, 0x3c, 0x19, 0x2d, 0x19, 0x15, 0x2a, 0x2d, 0x28, - 0x4a, 0x1c, 0x21, 0x40, 0x30, 0x20, 0x38, 0x17, 0x02, 0xd4, 0x24, 0x45, 0x32, 0x45, 0x5e, 0x23, 0x87, 0x22, 0x4b, 0x26, 0x38, 0x80, 0x38, 0x8f, 0x37, 0x1e, - 0x23, 0x70, 0x5b, 0x4c, 0x5b, 0x23, 0x2d, 0x4c, 0x2b, 0x33, 0x4a, 0x28, 0x73, 0x19, 0x23, 0x19, 0x2e, 0x18, 0x17, 0x2e, 0x1e, 0x1e, 0x1a, 0xfe, 0xd1, 0x15, - 0x2f, 0x1f, 0x2b, 0x31, 0x10, 0x0e, 0x00, 0x01, 0x00, 0x3d, 0x01, 0xc8, 0x00, 0xcd, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x01, - 0x5f, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0xcd, 0x14, 0x68, - 0x14, 0x02, 0xca, 0xfe, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, 0x62, 0x01, 0x35, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, 0x00, 0x01, - 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x16, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x13, 0x34, 0x36, 0x37, 0x33, 0x06, 0x06, 0x15, 0x14, 0x16, 0x17, - 0x23, 0x26, 0x26, 0x28, 0x47, 0x4c, 0x7a, 0x44, 0x47, 0x47, 0x43, 0x79, 0x4c, 0x47, 0x01, 0x12, 0x7a, 0xe3, 0x5b, 0x5e, 0xe2, 0x77, 0x74, 0xe1, 0x5c, 0x58, - 0xdf, 0x00, 0x00, 0x01, 0x00, 0x1e, 0xff, 0x62, 0x01, 0x2b, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, - 0x6a, 0x00, 0x4e, 0x16, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x23, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x01, 0x2b, 0x47, - 0x4c, 0x79, 0x44, 0x46, 0x47, 0x44, 0x7a, 0x4c, 0x47, 0x01, 0x12, 0x79, 0xdf, 0x58, 0x5c, 0xe1, 0x74, 0x77, 0xe2, 0x5e, 0x5b, 0xe3, 0x00, 0x01, 0x00, 0x1d, - 0x01, 0x24, 0x02, 0x01, 0x02, 0xf8, 0x00, 0x0e, 0x00, 0x23, 0x40, 0x20, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x0d, - 0x00, 0x49, 0x01, 0x01, 0x00, 0x00, 0x6c, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x02, 0x0d, 0x16, 0x2b, 0x01, 0x07, 0x37, 0x17, 0x07, 0x17, 0x07, - 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x27, 0x01, 0x4f, 0x14, 0xb5, 0x11, 0xa5, 0x6c, 0x6f, 0x4c, 0x43, 0x74, 0x6c, 0xa5, 0x13, 0xb2, 0x14, 0x02, 0xf8, - 0xb4, 0x33, 0x7c, 0x0c, 0x90, 0x3b, 0x98, 0x98, 0x3b, 0x90, 0x0e, 0x7a, 0x33, 0xb4, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x6f, 0x02, 0x10, 0x02, 0x54, 0x00, 0x0b, - 0x00, 0x26, 0x40, 0x23, 0x00, 0x05, 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, 0x05, 0x02, 0x5f, 0x00, - 0x02, 0x05, 0x02, 0x4f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, - 0x01, 0x53, 0xbd, 0xbd, 0x6b, 0xbd, 0xbd, 0x6b, 0x01, 0x96, 0x6b, 0xbc, 0xbc, 0x6b, 0xbe, 0x00, 0x00, 0x01, 0x00, 0x1f, 0xff, 0x7f, 0x00, 0xe0, 0x00, 0x74, - 0x00, 0x08, 0x00, 0x18, 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x13, 0x13, 0x02, 0x0d, - 0x18, 0x2b, 0x37, 0x06, 0x06, 0x07, 0x23, 0x36, 0x36, 0x37, 0x33, 0xe0, 0x0d, 0x30, 0x19, 0x6b, 0x0e, 0x1c, 0x07, 0x89, 0x69, 0x35, 0x7e, 0x37, 0x3b, 0x86, - 0x34, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0xce, 0x01, 0x23, 0x01, 0x4a, 0x00, 0x03, 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, - 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, 0x35, 0x21, 0x15, 0x1c, 0x01, - 0x07, 0xce, 0x7c, 0x7c, 0x00, 0x01, 0x00, 0x36, 0xff, 0xf3, 0x00, 0xe3, 0x00, 0x9a, 0x00, 0x0b, 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, - 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x22, 0x02, 0x0d, 0x18, 0x2b, 0x37, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x36, 0x33, 0x24, - 0x23, 0x33, 0x33, 0x23, 0x24, 0x33, 0x46, 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x01, 0x00, 0x07, 0xff, 0xfa, 0x01, 0x9a, 0x02, 0xd0, 0x00, 0x03, - 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, - 0x2b, 0x01, 0x01, 0x23, 0x01, 0x01, 0x9a, 0xfe, 0xf6, 0x89, 0x01, 0x0a, 0x02, 0xd0, 0xfd, 0x2a, 0x02, 0xd6, 0x00, 0x02, 0x00, 0x24, 0xff, 0xf6, 0x02, 0x17, - 0x02, 0xd5, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, - 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x24, 0x25, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, - 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x17, 0x31, 0x6d, 0x5c, 0x81, 0x78, 0x30, 0x6e, 0x5b, 0x80, 0x7a, 0xfe, - 0xa3, 0x2a, 0x39, 0x38, 0x2c, 0x2c, 0x38, 0x39, 0x2a, 0x01, 0x65, 0x73, 0xa4, 0x58, 0xc3, 0xac, 0x74, 0xa4, 0x58, 0xc2, 0xae, 0x7a, 0x7b, 0x7a, 0x7b, 0x7a, - 0x7c, 0x7c, 0x00, 0x01, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x9d, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x1b, 0x40, 0x18, 0x0a, 0x09, 0x05, 0x03, 0x00, 0x01, 0x01, 0x4c, - 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1a, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x21, 0x23, 0x11, 0x34, 0x36, 0x37, 0x06, 0x06, 0x07, - 0x07, 0x27, 0x37, 0x33, 0x01, 0x9d, 0x97, 0x03, 0x01, 0x05, 0x21, 0x0e, 0x52, 0x49, 0xe6, 0x7c, 0x01, 0x9d, 0x1a, 0x54, 0x20, 0x06, 0x1f, 0x0c, 0x42, 0x5b, - 0xb7, 0x00, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x02, 0x1b, 0x02, 0xd4, 0x00, 0x1d, 0x00, 0x2d, 0x40, 0x2a, 0x0e, 0x01, 0x01, 0x02, 0x0d, 0x01, 0x03, 0x01, - 0x02, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, - 0x4e, 0x28, 0x26, 0x28, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x3e, 0x02, 0x33, - 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x15, 0x21, 0x02, 0x1b, 0xfe, 0x0d, 0xb3, 0x36, 0x42, 0x1e, 0x2f, 0x28, 0x29, 0x4e, 0x2b, 0x52, 0x1f, - 0x45, 0x5b, 0x40, 0x46, 0x65, 0x37, 0x2f, 0x59, 0x3f, 0x5c, 0x01, 0x37, 0x69, 0xb5, 0x38, 0x4b, 0x3d, 0x23, 0x2b, 0x2a, 0x26, 0x23, 0x61, 0x1b, 0x2e, 0x1d, - 0x33, 0x57, 0x37, 0x3b, 0x62, 0x60, 0x3a, 0x56, 0x07, 0x00, 0x00, 0x01, 0x00, 0x26, 0xff, 0xf6, 0x02, 0x14, 0x02, 0xd4, 0x00, 0x2b, 0x00, 0x3f, 0x40, 0x3c, - 0x26, 0x01, 0x04, 0x05, 0x25, 0x01, 0x03, 0x04, 0x03, 0x01, 0x02, 0x03, 0x0e, 0x01, 0x01, 0x02, 0x0d, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x03, 0x00, 0x02, - 0x01, 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, - 0x25, 0x21, 0x25, 0x24, 0x2a, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, - 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x23, 0x23, 0x35, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, - 0x16, 0x01, 0xff, 0x59, 0x41, 0x56, 0x59, 0x3d, 0x7f, 0x64, 0x74, 0x5a, 0x2e, 0x65, 0x2b, 0x51, 0x41, 0x1e, 0x4b, 0x43, 0x36, 0x37, 0x42, 0x45, 0x19, 0x2f, - 0x37, 0x33, 0x4b, 0x1a, 0x46, 0x2a, 0x71, 0x4e, 0x6e, 0x81, 0x02, 0x2a, 0x4a, 0x58, 0x10, 0x03, 0x0a, 0x54, 0x47, 0x3e, 0x63, 0x39, 0x27, 0x80, 0x17, 0x18, - 0x38, 0x33, 0x1e, 0x29, 0x15, 0x74, 0x19, 0x2b, 0x1c, 0x26, 0x2b, 0x23, 0x11, 0x68, 0x1e, 0x28, 0x59, 0x00, 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x02, 0x2b, - 0x02, 0xca, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x27, 0x40, 0x24, 0x06, 0x01, 0x00, 0x04, 0x01, 0x4c, 0x05, 0x01, 0x04, 0x02, 0x01, 0x00, 0x01, 0x04, 0x00, 0x67, - 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1a, 0x11, 0x12, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x25, 0x23, 0x15, 0x23, 0x35, - 0x21, 0x35, 0x01, 0x33, 0x11, 0x33, 0x27, 0x34, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x07, 0x07, 0x33, 0x02, 0x2b, 0x56, 0x93, 0xfe, 0xcf, 0x01, 0x39, 0x8b, - 0x56, 0xe9, 0x02, 0x03, 0x01, 0x04, 0x09, 0x14, 0x0e, 0x83, 0xac, 0x94, 0x94, 0x94, 0x69, 0x01, 0xcd, 0xfe, 0x3f, 0x79, 0x17, 0x42, 0x39, 0x09, 0x14, 0x26, - 0x14, 0xc6, 0x00, 0x01, 0x00, 0x31, 0xff, 0xf6, 0x02, 0x0e, 0x02, 0xca, 0x00, 0x1e, 0x00, 0x44, 0x40, 0x41, 0x1c, 0x17, 0x02, 0x03, 0x00, 0x16, 0x0b, 0x02, - 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x03, 0x02, 0x00, 0x03, 0x69, 0x00, 0x05, 0x05, 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6a, - 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x01, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x14, 0x12, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x1e, - 0x01, 0x1e, 0x07, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, - 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x15, 0x23, 0x07, 0x36, 0x36, 0x01, 0x2c, 0x41, 0x66, 0x3b, 0x90, 0x8d, 0x38, 0x63, 0x25, 0x25, 0x68, 0x2e, 0x43, 0x47, - 0x8f, 0x1c, 0x3c, 0x14, 0x3c, 0x1b, 0x01, 0x83, 0xff, 0x0d, 0x11, 0x27, 0x01, 0xc8, 0x32, 0x60, 0x47, 0x74, 0x85, 0x14, 0x13, 0x82, 0x13, 0x1b, 0x37, 0x3a, - 0x6c, 0x0b, 0x05, 0x20, 0x01, 0x6c, 0x80, 0x8c, 0x03, 0x07, 0x00, 0x02, 0x00, 0x23, 0xff, 0xf6, 0x02, 0x1b, 0x02, 0xd2, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x69, - 0x40, 0x0e, 0x09, 0x01, 0x01, 0x00, 0x0a, 0x01, 0x02, 0x01, 0x11, 0x01, 0x05, 0x02, 0x03, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1e, 0x00, 0x02, 0x00, - 0x05, 0x04, 0x02, 0x05, 0x69, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, - 0x4e, 0x1b, 0x40, 0x1e, 0x00, 0x02, 0x00, 0x05, 0x04, 0x02, 0x05, 0x69, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x70, 0x4d, 0x06, 0x01, 0x04, 0x04, - 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x20, 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x24, 0x26, 0x24, 0x35, 0x07, 0x0d, 0x1a, - 0x2b, 0x13, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x17, 0x15, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, - 0x23, 0x22, 0x26, 0x26, 0x05, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x23, 0x12, 0x2d, 0x51, 0x7d, 0x59, 0x15, 0x38, - 0x13, 0x13, 0x2d, 0x16, 0x59, 0x61, 0x28, 0x03, 0x06, 0x14, 0x4b, 0x3c, 0x5e, 0x6e, 0x83, 0x70, 0x49, 0x76, 0x46, 0x01, 0x02, 0x2c, 0x38, 0x30, 0x31, 0x21, - 0x32, 0x1c, 0x18, 0x31, 0x01, 0x2f, 0x3e, 0x78, 0x6b, 0x53, 0x2f, 0x03, 0x04, 0x79, 0x05, 0x05, 0x38, 0x65, 0x42, 0x23, 0x30, 0x76, 0x6c, 0x74, 0x84, 0x43, - 0x8b, 0x55, 0x3d, 0x40, 0x34, 0x3c, 0x1d, 0x2e, 0x18, 0x21, 0x3f, 0x2a, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x02, 0x1b, 0x02, 0xca, 0x00, 0x06, 0x00, 0x25, - 0x40, 0x22, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, - 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x6f, 0x01, 0x0c, 0xfe, 0xa0, 0x02, 0x00, 0xfe, - 0xf2, 0x02, 0x4b, 0x7f, 0x5f, 0xfd, 0x95, 0x00, 0x00, 0x03, 0x00, 0x23, 0xff, 0xf6, 0x02, 0x18, 0x02, 0xd3, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x35, 0x00, 0x36, - 0x40, 0x33, 0x33, 0x22, 0x15, 0x07, 0x04, 0x03, 0x02, 0x01, 0x4c, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x03, 0x03, - 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1d, 0x1c, 0x01, 0x00, 0x2c, 0x2a, 0x1c, 0x27, 0x1d, 0x27, 0x10, 0x0e, 0x00, 0x1b, 0x01, 0x1b, 0x06, 0x0d, - 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, - 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, - 0x27, 0x06, 0x06, 0x01, 0x1e, 0x3e, 0x67, 0x3f, 0x49, 0x37, 0x26, 0x45, 0x2b, 0x3f, 0x71, 0x4a, 0x78, 0x83, 0x50, 0x39, 0x30, 0x43, 0x40, 0x69, 0x3b, 0x25, - 0x31, 0x34, 0x23, 0x22, 0x34, 0x31, 0x94, 0x37, 0x36, 0x38, 0x38, 0x20, 0x2f, 0x19, 0x0d, 0x2e, 0x3a, 0x02, 0xd3, 0x26, 0x4c, 0x3a, 0x40, 0x53, 0x1b, 0x14, - 0x35, 0x47, 0x30, 0x3b, 0x58, 0x30, 0x66, 0x59, 0x4a, 0x5a, 0x1c, 0x1e, 0x55, 0x40, 0x39, 0x4c, 0x26, 0x6e, 0x26, 0x23, 0x25, 0x2e, 0x11, 0x10, 0x2d, 0x27, - 0x23, 0x26, 0xfe, 0x59, 0x27, 0x32, 0x30, 0x28, 0x1b, 0x29, 0x21, 0x0e, 0x07, 0x16, 0x3a, 0x00, 0x00, 0x02, 0x00, 0x20, 0xff, 0xf6, 0x02, 0x18, 0x02, 0xd2, - 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x3e, 0x40, 0x3b, 0x11, 0x01, 0x02, 0x05, 0x0a, 0x01, 0x01, 0x02, 0x09, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, - 0x01, 0x05, 0x02, 0x69, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, - 0x20, 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x24, 0x26, 0x24, 0x35, 0x07, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x0e, 0x03, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, - 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x16, 0x25, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, - 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x26, 0x02, 0x18, 0x12, 0x2d, 0x51, 0x7d, 0x59, 0x15, 0x38, 0x13, 0x14, 0x2c, 0x16, 0x59, 0x61, 0x28, 0x03, 0x06, 0x15, - 0x45, 0x44, 0x5b, 0x6e, 0x83, 0x70, 0x49, 0x76, 0x46, 0xfe, 0xfe, 0x2c, 0x38, 0x30, 0x31, 0x22, 0x31, 0x1c, 0x18, 0x30, 0x01, 0x99, 0x3d, 0x79, 0x6b, 0x53, - 0x2f, 0x03, 0x04, 0x79, 0x04, 0x06, 0x39, 0x64, 0x42, 0x23, 0x30, 0x76, 0x6c, 0x74, 0x84, 0x43, 0x8b, 0x55, 0x3c, 0x41, 0x34, 0x3c, 0x1e, 0x2d, 0x18, 0x21, - 0x40, 0x29, 0x00, 0x02, 0x00, 0x36, 0xff, 0xf3, 0x00, 0xe3, 0x02, 0x2c, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, - 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, - 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x11, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x36, 0x33, 0x24, 0x23, 0x33, - 0x33, 0x23, 0x24, 0x33, 0x33, 0x24, 0x23, 0x33, 0x33, 0x23, 0x24, 0x33, 0x01, 0xd9, 0x2e, 0x25, 0x25, 0x2e, 0x2d, 0x27, 0x27, 0xfe, 0x9a, 0x2e, 0x26, 0x26, - 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x02, 0x00, 0x1f, 0xff, 0x7f, 0x00, 0xe4, 0x02, 0x2c, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x02, - 0x03, 0x02, 0x63, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x01, 0x4e, 0x13, 0x15, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, 0x33, - 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x13, 0x06, 0x06, 0x07, 0x23, 0x36, 0x36, 0x37, 0x33, 0x39, 0x32, 0x24, 0x23, 0x32, 0x32, 0x23, 0x24, 0x32, - 0xa7, 0x0d, 0x30, 0x19, 0x6b, 0x0e, 0x1c, 0x07, 0x89, 0x01, 0xd9, 0x2e, 0x25, 0x25, 0x2e, 0x2c, 0x27, 0x27, 0xfe, 0xbc, 0x35, 0x7e, 0x37, 0x3b, 0x86, 0x34, - 0x00, 0x01, 0x00, 0x2b, 0x00, 0x63, 0x02, 0x10, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, 0x32, 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, - 0x05, 0x02, 0x10, 0xfe, 0x1b, 0x01, 0xe5, 0xfe, 0xb2, 0x01, 0x4e, 0x63, 0xd6, 0x46, 0xf2, 0x75, 0x9b, 0x89, 0x00, 0x02, 0x00, 0x2b, 0x00, 0xcc, 0x02, 0x10, - 0x01, 0xf4, 0x00, 0x03, 0x00, 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, - 0x02, 0x02, 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, - 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, 0x35, 0x21, 0x15, 0x2b, 0x01, 0xe5, 0xfe, 0x1b, 0x01, 0xe5, 0x01, 0x8a, 0x6a, 0x6a, 0xbe, 0x6b, 0x6b, 0x00, - 0x00, 0x01, 0x00, 0x2b, 0x00, 0x63, 0x02, 0x10, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, 0x25, 0x25, 0x35, 0x05, 0x15, - 0x05, 0x2b, 0x01, 0x4e, 0xfe, 0xb2, 0x01, 0xe5, 0xfe, 0x1b, 0xd8, 0x89, 0x9b, 0x75, 0xf2, 0x46, 0xd6, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0xf3, 0x01, 0xc8, - 0x02, 0xd4, 0x00, 0x1d, 0x00, 0x29, 0x00, 0x32, 0x40, 0x2f, 0x0e, 0x01, 0x00, 0x01, 0x0d, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, - 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x04, 0x4e, 0x24, 0x23, 0x1a, - 0x25, 0x29, 0x05, 0x0d, 0x1b, 0x2b, 0x13, 0x34, 0x36, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, - 0x14, 0x06, 0x07, 0x0e, 0x02, 0x15, 0x15, 0x23, 0x07, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x8e, 0x24, 0x33, 0x24, 0x24, 0x0d, - 0x2f, 0x29, 0x2a, 0x53, 0x2b, 0x35, 0x31, 0x72, 0x44, 0x69, 0x73, 0x3a, 0x3b, 0x1f, 0x22, 0x0d, 0x77, 0x15, 0x32, 0x25, 0x22, 0x33, 0x33, 0x22, 0x25, 0x32, - 0x01, 0x0c, 0x32, 0x45, 0x24, 0x19, 0x24, 0x21, 0x14, 0x1f, 0x22, 0x1a, 0x16, 0x6d, 0x1b, 0x22, 0x60, 0x51, 0x3d, 0x54, 0x2a, 0x16, 0x21, 0x1e, 0x15, 0x16, - 0xa2, 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xb0, 0x03, 0x53, 0x02, 0xcf, 0x00, 0x3e, 0x00, 0x4c, 0x00, 0x7e, 0x40, 0x16, - 0x16, 0x01, 0x09, 0x02, 0x46, 0x01, 0x03, 0x09, 0x08, 0x01, 0x00, 0x03, 0x2e, 0x01, 0x05, 0x00, 0x2f, 0x01, 0x06, 0x05, 0x05, 0x4c, 0x4b, 0xb0, 0x2c, 0x50, - 0x58, 0x40, 0x26, 0x08, 0x01, 0x03, 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, 0x00, - 0x07, 0x07, 0x6a, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x24, 0x00, 0x02, 0x00, 0x09, 0x03, 0x02, 0x09, 0x69, - 0x08, 0x01, 0x03, 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, 0x00, 0x07, 0x07, 0x6a, - 0x04, 0x4e, 0x59, 0x40, 0x0e, 0x4a, 0x48, 0x25, 0x27, 0x25, 0x25, 0x25, 0x28, 0x25, 0x25, 0x24, 0x0a, 0x0d, 0x1f, 0x2b, 0x01, 0x14, 0x0e, 0x02, 0x23, 0x22, - 0x26, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x14, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, - 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, - 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x03, 0x53, 0x17, 0x2e, 0x43, 0x2d, 0x27, 0x3c, 0x0e, - 0x06, 0x15, 0x42, 0x2e, 0x56, 0x59, 0x37, 0x69, 0x4c, 0x2f, 0x5a, 0x1c, 0x0a, 0x01, 0x17, 0x10, 0x17, 0x21, 0x11, 0x8e, 0x7d, 0x69, 0x8f, 0x4a, 0x8e, 0x8b, - 0x39, 0x7e, 0x36, 0x31, 0x76, 0x42, 0x7c, 0xb0, 0x5e, 0x3c, 0x70, 0x9f, 0x63, 0x6f, 0xa8, 0x5f, 0xfe, 0x12, 0x2a, 0x23, 0x2e, 0x28, 0x04, 0x05, 0x0b, 0x18, - 0x0e, 0x2c, 0x36, 0x19, 0x01, 0x6c, 0x2e, 0x5a, 0x49, 0x2b, 0x27, 0x1e, 0x1d, 0x28, 0x6a, 0x57, 0x42, 0x68, 0x3c, 0x12, 0x0a, 0xcd, 0x0a, 0x17, 0x09, 0x23, - 0x18, 0x2d, 0x4b, 0x2c, 0x7b, 0x8b, 0x56, 0x98, 0x62, 0x82, 0x94, 0x1a, 0x13, 0x5e, 0x15, 0x17, 0x59, 0xa6, 0x74, 0x5b, 0x9c, 0x75, 0x40, 0x56, 0x9f, 0xa9, - 0x37, 0x31, 0x48, 0x47, 0x5f, 0x02, 0x04, 0x28, 0x3f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0xb4, 0x02, 0xcd, 0x00, 0x07, 0x00, 0x12, 0x00, 0x2c, - 0x40, 0x29, 0x0c, 0x01, 0x04, 0x02, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x68, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, - 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x12, 0x11, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x21, 0x27, 0x23, 0x07, 0x23, 0x13, 0x33, 0x13, - 0x01, 0x2e, 0x02, 0x27, 0x0e, 0x02, 0x07, 0x07, 0x33, 0x02, 0x0f, 0x37, 0xfc, 0x37, 0xa5, 0xfb, 0xbc, 0xfd, 0xfe, 0xcf, 0x04, 0x11, 0x10, 0x05, 0x04, 0x0f, - 0x0e, 0x05, 0x33, 0xb5, 0xa8, 0xa8, 0x02, 0xcd, 0xfd, 0x33, 0x01, 0xc3, 0x0f, 0x3c, 0x3f, 0x14, 0x17, 0x3b, 0x39, 0x13, 0x9b, 0x00, 0x00, 0x03, 0x00, 0x55, - 0x00, 0x00, 0x02, 0x67, 0x02, 0xca, 0x00, 0x10, 0x00, 0x19, 0x00, 0x22, 0x00, 0x44, 0x40, 0x41, 0x06, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x08, - 0x01, 0x05, 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x04, 0x04, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6b, - 0x01, 0x4e, 0x1a, 0x1a, 0x12, 0x11, 0x01, 0x00, 0x1a, 0x22, 0x1a, 0x21, 0x1d, 0x1b, 0x18, 0x16, 0x11, 0x19, 0x12, 0x19, 0x0f, 0x0d, 0x00, 0x10, 0x01, 0x10, - 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, - 0x23, 0x23, 0x1d, 0x02, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x3c, 0x93, 0x86, 0x47, 0x32, 0x23, 0x40, 0x28, 0x8d, 0x7a, 0xfe, 0xf5, 0xef, 0x41, - 0x33, 0x3c, 0x3f, 0x4f, 0x61, 0x44, 0x35, 0x36, 0x48, 0x02, 0xca, 0x57, 0x5b, 0x43, 0x4f, 0x0b, 0x05, 0x07, 0x24, 0x44, 0x38, 0x62, 0x6d, 0x02, 0xca, 0xfe, - 0xe2, 0x30, 0x27, 0x29, 0x27, 0xa7, 0x73, 0xc0, 0x37, 0x2b, 0x27, 0x37, 0x00, 0x01, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x63, 0x02, 0xd4, 0x00, 0x1a, 0x00, 0x37, - 0x40, 0x34, 0x17, 0x01, 0x00, 0x03, 0x18, 0x09, 0x02, 0x01, 0x00, 0x0a, 0x01, 0x02, 0x01, 0x03, 0x4c, 0x04, 0x01, 0x00, 0x00, 0x03, 0x61, 0x00, 0x03, 0x03, - 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x01, 0x00, 0x15, 0x13, 0x0d, 0x0b, 0x07, 0x05, 0x00, 0x1a, 0x01, 0x1a, 0x05, - 0x0d, 0x16, 0x2b, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, - 0x17, 0x07, 0x26, 0x26, 0x01, 0x8e, 0x56, 0x63, 0x5f, 0x60, 0x2f, 0x57, 0x2c, 0x55, 0x6e, 0x72, 0x93, 0x47, 0x50, 0x9a, 0x6f, 0x35, 0x6d, 0x31, 0x32, 0x24, - 0x51, 0x02, 0x55, 0x81, 0x71, 0x71, 0x7d, 0x16, 0x11, 0x82, 0x24, 0x5b, 0xa5, 0x6e, 0x6c, 0xa6, 0x5e, 0x17, 0x18, 0x7a, 0x11, 0x19, 0x00, 0x02, 0x00, 0x55, - 0x00, 0x00, 0x02, 0xa6, 0x02, 0xca, 0x00, 0x09, 0x00, 0x11, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x03, - 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x21, 0x24, 0x21, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, 0x23, 0x23, 0x11, 0x33, 0x32, - 0x16, 0x07, 0x34, 0x26, 0x23, 0x23, 0x11, 0x33, 0x32, 0x02, 0xa6, 0x5c, 0xa8, 0x73, 0xda, 0xec, 0xa8, 0xbd, 0xa0, 0x66, 0x63, 0x4f, 0x40, 0xd8, 0x01, 0x71, - 0x7b, 0xa4, 0x52, 0x02, 0xca, 0xb1, 0xae, 0x73, 0x6f, 0xfe, 0x31, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x01, 0xf5, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x29, - 0x40, 0x26, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x5f, 0x00, - 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x21, 0x11, 0x21, 0x15, 0x21, 0x15, 0x33, 0x15, 0x23, 0x15, - 0x21, 0x01, 0xf5, 0xfe, 0x65, 0x01, 0x9b, 0xfe, 0xfc, 0xf2, 0xf2, 0x01, 0x04, 0x02, 0xca, 0x7c, 0x9d, 0x7c, 0xb8, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, - 0x01, 0xf3, 0x02, 0xca, 0x00, 0x09, 0x00, 0x23, 0x40, 0x20, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, - 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x10, 0x05, 0x0d, 0x1b, 0x2b, 0x33, 0x23, 0x11, 0x21, 0x15, 0x21, 0x15, 0x33, 0x15, - 0x23, 0xef, 0x95, 0x01, 0x99, 0xfe, 0xfc, 0xf2, 0xf2, 0x02, 0xca, 0x7c, 0xb8, 0x7c, 0x00, 0x01, 0x00, 0x3a, 0xff, 0xf6, 0x02, 0x84, 0x02, 0xd4, 0x00, 0x20, - 0x00, 0x3b, 0x40, 0x38, 0x0f, 0x01, 0x03, 0x02, 0x10, 0x01, 0x00, 0x03, 0x1e, 0x01, 0x04, 0x05, 0x02, 0x01, 0x01, 0x04, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x05, - 0x04, 0x00, 0x05, 0x67, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x13, - 0x26, 0x25, 0x25, 0x23, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x21, 0x11, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, - 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x35, 0x23, 0x01, 0x69, 0x01, 0x1b, 0x38, 0x79, 0x4d, 0xa0, 0xac, 0x57, - 0xa6, 0x78, 0x39, 0x6e, 0x2d, 0x32, 0x21, 0x54, 0x2e, 0x42, 0x61, 0x35, 0x26, 0x52, 0x42, 0x20, 0x2d, 0x13, 0x87, 0x01, 0x91, 0xfe, 0x8e, 0x13, 0x16, 0xbc, - 0xb4, 0x70, 0xa4, 0x5a, 0x18, 0x14, 0x79, 0x11, 0x16, 0x3c, 0x6d, 0x4a, 0x46, 0x6c, 0x3d, 0x06, 0x04, 0x95, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0xa3, - 0x02, 0xca, 0x00, 0x0b, 0x00, 0x21, 0x40, 0x1e, 0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x01, 0x67, 0x05, 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x02, 0x01, 0x00, 0x00, - 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x02, - 0xa3, 0x97, 0xfe, 0xe5, 0x97, 0x97, 0x01, 0x1b, 0x97, 0x01, 0x34, 0xfe, 0xcc, 0x02, 0xca, 0xfe, 0xe8, 0x01, 0x18, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, - 0x01, 0x65, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x0a, 0x09, 0x08, 0x05, 0x04, 0x03, 0x02, 0x08, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x01, 0x01, - 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x11, 0x27, 0x35, 0x21, 0x15, 0x07, 0x11, 0x17, - 0x01, 0x65, 0xfe, 0xbb, 0x57, 0x57, 0x01, 0x45, 0x57, 0x57, 0x56, 0x28, 0x01, 0xce, 0x28, 0x56, 0x56, 0x28, 0xfe, 0x32, 0x28, 0x00, 0x00, 0x01, 0xff, 0xb6, - 0xff, 0x2e, 0x00, 0xf1, 0x02, 0xca, 0x00, 0x11, 0x00, 0x28, 0x40, 0x25, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, - 0x00, 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, 0x01, 0x00, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x11, 0x01, 0x11, 0x04, 0x0d, 0x16, 0x2b, 0x17, 0x22, - 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x06, 0x0f, 0x1d, 0x2c, 0x10, 0x10, 0x23, 0x14, 0x1a, 0x2b, 0x18, - 0x97, 0x39, 0x66, 0xd2, 0x07, 0x04, 0x7e, 0x04, 0x06, 0x14, 0x38, 0x34, 0x02, 0x9d, 0xfd, 0x64, 0x5c, 0x71, 0x33, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, - 0x02, 0x98, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x20, 0x40, 0x1d, 0x0e, 0x08, 0x03, 0x02, 0x04, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, - 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x11, 0x13, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x07, 0x15, 0x23, 0x11, 0x33, 0x11, 0x36, 0x36, 0x37, - 0x37, 0x33, 0x03, 0x02, 0x98, 0xac, 0xbb, 0x40, 0x97, 0x97, 0x0f, 0x1e, 0x0f, 0xc1, 0xa8, 0xf9, 0x01, 0x2d, 0x2e, 0xff, 0x02, 0xca, 0xfe, 0xb9, 0x15, 0x2a, - 0x15, 0xf3, 0xfe, 0xc4, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x02, 0x0f, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, - 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x11, 0x33, - 0x11, 0x21, 0x15, 0x55, 0x99, 0x01, 0x21, 0x02, 0xca, 0xfd, 0xb4, 0x7e, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x03, 0x55, 0x02, 0xca, 0x00, 0x17, 0x00, 0x26, - 0x40, 0x23, 0x15, 0x0b, 0x02, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x05, 0x04, 0x03, 0x03, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, - 0x00, 0x17, 0x00, 0x17, 0x11, 0x13, 0x11, 0x17, 0x06, 0x0d, 0x1a, 0x2b, 0x21, 0x03, 0x23, 0x1e, 0x02, 0x15, 0x11, 0x23, 0x11, 0x33, 0x13, 0x33, 0x13, 0x33, - 0x11, 0x23, 0x11, 0x34, 0x36, 0x36, 0x37, 0x23, 0x03, 0x01, 0x88, 0xac, 0x04, 0x01, 0x04, 0x04, 0x87, 0xce, 0xa9, 0x03, 0xb3, 0xce, 0x8d, 0x03, 0x03, 0x01, - 0x04, 0xb8, 0x02, 0x30, 0x14, 0x50, 0x5b, 0x25, 0xfe, 0xb4, 0x02, 0xca, 0xfd, 0xde, 0x02, 0x22, 0xfd, 0x36, 0x01, 0x52, 0x22, 0x58, 0x4f, 0x14, 0xfd, 0xd1, - 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0xd3, 0x02, 0xca, 0x00, 0x11, 0x00, 0x1e, 0x40, 0x1b, 0x0b, 0x02, 0x02, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, - 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x16, 0x11, 0x16, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x01, 0x23, 0x16, 0x16, 0x17, 0x11, - 0x23, 0x11, 0x33, 0x01, 0x33, 0x26, 0x26, 0x27, 0x11, 0x33, 0x02, 0xd3, 0xc0, 0xfe, 0xc9, 0x04, 0x02, 0x05, 0x02, 0x87, 0xbf, 0x01, 0x36, 0x03, 0x01, 0x04, - 0x02, 0x88, 0x02, 0x1c, 0x33, 0x66, 0x33, 0xfe, 0xb0, 0x02, 0xca, 0xfd, 0xe9, 0x32, 0x62, 0x31, 0x01, 0x52, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0xdf, - 0x02, 0xd5, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, - 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x25, 0x26, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, - 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xdf, 0x49, 0x96, 0x75, 0x74, 0x97, 0x49, 0x49, 0x97, 0x75, - 0x74, 0x97, 0x48, 0xfd, 0xf9, 0x55, 0x5e, 0x60, 0x53, 0x53, 0x5f, 0x5f, 0x55, 0x01, 0x66, 0x6f, 0xa5, 0x5c, 0x5c, 0xa6, 0x6f, 0x6e, 0xa5, 0x5b, 0x5b, 0xa5, - 0x6f, 0x70, 0x7f, 0x7f, 0x70, 0x70, 0x80, 0x80, 0x00, 0x02, 0x00, 0x55, 0x00, 0x00, 0x02, 0x43, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x32, 0x40, 0x2f, - 0x00, 0x04, 0x00, 0x01, 0x02, 0x04, 0x01, 0x69, 0x06, 0x01, 0x03, 0x03, 0x00, 0x5f, 0x05, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, - 0x0d, 0x0c, 0x01, 0x00, 0x10, 0x0e, 0x0c, 0x14, 0x0d, 0x14, 0x0a, 0x09, 0x08, 0x06, 0x00, 0x0b, 0x01, 0x0b, 0x07, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, - 0x14, 0x06, 0x06, 0x23, 0x23, 0x15, 0x23, 0x11, 0x17, 0x23, 0x15, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x35, 0x8a, 0x84, 0x34, 0x79, 0x67, 0x41, 0x99, - 0xdb, 0x42, 0x33, 0x3f, 0x49, 0x3b, 0x02, 0xca, 0x73, 0x69, 0x3f, 0x6e, 0x44, 0xfd, 0x02, 0xca, 0x7d, 0xd2, 0x32, 0x3c, 0x30, 0x34, 0x00, 0x02, 0x00, 0x37, - 0xff, 0x56, 0x02, 0xdf, 0x02, 0xd5, 0x00, 0x14, 0x00, 0x20, 0x00, 0x2b, 0x40, 0x28, 0x03, 0x01, 0x01, 0x03, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x86, 0x00, - 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x25, 0x26, 0x41, 0x14, 0x05, - 0x0d, 0x1b, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x17, 0x23, 0x27, 0x22, 0x22, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, - 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xdf, 0x55, 0x5a, 0xad, 0xc5, 0x7f, 0x03, 0x08, 0x03, 0x74, 0x97, 0x49, 0x49, 0x97, 0x75, - 0x74, 0x97, 0x48, 0xfd, 0xf9, 0x55, 0x5e, 0x60, 0x53, 0x53, 0x5f, 0x5f, 0x55, 0x01, 0x66, 0x77, 0xb0, 0x29, 0xc0, 0xa0, 0x5c, 0xa6, 0x6f, 0x6e, 0xa5, 0x5b, - 0x5b, 0xa5, 0x6f, 0x70, 0x7f, 0x7f, 0x70, 0x70, 0x80, 0x80, 0x00, 0x02, 0x00, 0x55, 0x00, 0x00, 0x02, 0x91, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x15, 0x00, 0x3b, - 0x40, 0x38, 0x05, 0x01, 0x02, 0x05, 0x01, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, - 0x6a, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x0e, 0x0d, 0x01, 0x00, 0x11, 0x0f, 0x0d, 0x15, 0x0e, 0x15, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x00, - 0x0c, 0x01, 0x0c, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x20, 0x15, 0x14, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x11, 0x23, 0x11, 0x17, 0x23, 0x15, 0x33, 0x32, 0x36, - 0x35, 0x34, 0x26, 0x01, 0x30, 0x01, 0x17, 0x4a, 0x37, 0xcb, 0xaf, 0x9f, 0x55, 0x99, 0xd8, 0x3f, 0x3f, 0x3d, 0x42, 0x3d, 0x02, 0xca, 0xd0, 0x49, 0x5c, 0x1a, - 0xfe, 0xc5, 0x01, 0x12, 0xfe, 0xee, 0x02, 0xca, 0x77, 0xcb, 0x32, 0x39, 0x30, 0x30, 0x00, 0x01, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xff, 0x02, 0xd4, 0x00, 0x28, - 0x00, 0x2e, 0x40, 0x2b, 0x1b, 0x01, 0x03, 0x02, 0x1c, 0x06, 0x02, 0x01, 0x03, 0x05, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, - 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, 0x2d, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, - 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x2e, 0x03, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, - 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xff, 0x89, 0x7e, 0x71, 0x59, 0x33, 0x6d, 0x36, 0x38, 0x2f, 0x25, 0x3e, 0x28, 0x19, 0x3a, 0x35, 0x22, - 0x82, 0x70, 0x38, 0x65, 0x37, 0x31, 0x31, 0x4e, 0x29, 0x2b, 0x2e, 0x44, 0x43, 0x37, 0x4d, 0x2a, 0xc6, 0x5f, 0x71, 0x2b, 0x8d, 0x16, 0x25, 0x2b, 0x21, 0x1b, - 0x26, 0x21, 0x13, 0x0c, 0x21, 0x31, 0x46, 0x31, 0x60, 0x6b, 0x1a, 0x18, 0x76, 0x14, 0x16, 0x28, 0x20, 0x26, 0x2c, 0x20, 0x1a, 0x38, 0x4c, 0x00, 0x00, 0x01, - 0x00, 0x13, 0x00, 0x00, 0x02, 0x2e, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1b, 0x40, 0x18, 0x03, 0x01, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, - 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x11, 0x23, 0x35, 0x21, 0x15, 0x23, 0x01, 0x6d, 0x99, 0xc1, 0x02, - 0x1b, 0xc1, 0x02, 0x4b, 0x7f, 0x7f, 0x00, 0x01, 0x00, 0x55, 0xff, 0xf6, 0x02, 0x9f, 0x02, 0xca, 0x00, 0x12, 0x00, 0x1b, 0x40, 0x18, 0x03, 0x01, 0x01, 0x01, - 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x13, 0x23, 0x13, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x06, 0x23, - 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x02, 0x9f, 0x41, 0x83, 0x64, 0x8e, 0x94, 0x97, 0x48, 0x47, 0x4a, 0x43, - 0x97, 0xfc, 0x4a, 0x77, 0x45, 0x91, 0x77, 0x01, 0xcc, 0xfe, 0x4b, 0x58, 0x48, 0x4e, 0x53, 0x01, 0xb4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x8a, - 0x02, 0xca, 0x00, 0x0e, 0x00, 0x21, 0x40, 0x1e, 0x09, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x02, 0x02, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, - 0x4e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x01, 0x03, 0x23, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x17, 0x3e, 0x02, 0x37, 0x13, - 0x02, 0x8a, 0xf3, 0xa5, 0xf2, 0x99, 0x86, 0x04, 0x0f, 0x10, 0x03, 0x03, 0x0f, 0x10, 0x03, 0x87, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0xfe, 0x57, 0x0b, 0x3b, - 0x41, 0x16, 0x16, 0x41, 0x3b, 0x0b, 0x01, 0xa9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc7, 0x02, 0xca, 0x00, 0x26, 0x00, 0x27, 0x40, 0x24, 0x21, 0x16, - 0x08, 0x03, 0x00, 0x02, 0x01, 0x4c, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x26, 0x00, - 0x26, 0x1a, 0x11, 0x1c, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x01, 0x03, 0x23, 0x03, 0x2e, 0x03, 0x27, 0x0e, 0x03, 0x07, 0x03, 0x23, 0x03, 0x33, 0x13, 0x1e, 0x02, - 0x17, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x13, 0x1e, 0x02, 0x17, 0x3e, 0x02, 0x37, 0x13, 0x03, 0xc7, 0xb6, 0xac, 0x61, 0x03, 0x09, 0x0b, 0x08, 0x02, 0x01, 0x09, - 0x0a, 0x0a, 0x03, 0x60, 0xac, 0xb6, 0x95, 0x5b, 0x06, 0x0e, 0x0c, 0x03, 0x03, 0x0c, 0x0d, 0x05, 0x68, 0x8f, 0x68, 0x05, 0x0d, 0x0c, 0x03, 0x03, 0x0c, 0x0f, - 0x05, 0x5b, 0x02, 0xca, 0xfd, 0x36, 0x01, 0x77, 0x0b, 0x2c, 0x34, 0x2f, 0x0d, 0x0d, 0x2f, 0x33, 0x2d, 0x0c, 0xfe, 0x8a, 0x02, 0xca, 0xfe, 0x7a, 0x17, 0x46, - 0x46, 0x18, 0x19, 0x45, 0x41, 0x12, 0x01, 0x90, 0xfe, 0x70, 0x11, 0x42, 0x46, 0x18, 0x19, 0x45, 0x46, 0x17, 0x01, 0x86, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, - 0x02, 0x9a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x08, 0x05, 0x02, 0x04, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, - 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x12, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x03, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, - 0x02, 0x9a, 0xb0, 0x9e, 0x9f, 0xaa, 0xed, 0xdf, 0xaa, 0x93, 0x90, 0xab, 0xe0, 0x01, 0x01, 0xfe, 0xff, 0x01, 0x70, 0x01, 0x5a, 0xf4, 0xf4, 0xfe, 0x9d, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x72, 0x02, 0xca, 0x00, 0x08, 0x00, 0x1c, 0x40, 0x19, 0x06, 0x03, 0x02, 0x01, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x00, - 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x12, 0x12, 0x11, 0x03, 0x0d, 0x19, 0x2b, 0x01, 0x13, 0x33, 0x03, 0x11, 0x23, 0x11, 0x03, 0x33, 0x01, - 0x39, 0x93, 0xa6, 0xec, 0x9a, 0xec, 0xa6, 0x01, 0x9f, 0x01, 0x2b, 0xfe, 0x4c, 0xfe, 0xea, 0x01, 0x11, 0x01, 0xb9, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, - 0x02, 0x2b, 0x02, 0xca, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, - 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, - 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x21, 0x02, 0x2b, 0xfd, 0xed, 0x01, 0x56, 0xfe, 0xb3, 0x02, 0x01, 0xfe, 0xaa, 0x01, 0x5f, 0x62, 0x01, 0xeb, 0x7d, 0x62, - 0xfe, 0x15, 0x00, 0x01, 0x00, 0x46, 0xff, 0x62, 0x01, 0x32, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x63, 0x00, - 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x02, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x05, 0x23, 0x11, 0x33, 0x15, 0x23, 0x11, 0x33, - 0x01, 0x32, 0xec, 0xec, 0x6d, 0x6d, 0x9e, 0x03, 0x68, 0x67, 0xfd, 0x66, 0x00, 0x01, 0x00, 0x06, 0xff, 0xfa, 0x01, 0x99, 0x02, 0xd0, 0x00, 0x03, 0x00, 0x19, - 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, - 0x01, 0x23, 0x01, 0x8e, 0x01, 0x0b, 0x89, 0xfe, 0xf6, 0x02, 0xd0, 0xfd, 0x2a, 0x02, 0xd6, 0x00, 0x00, 0x01, 0x00, 0x19, 0xff, 0x62, 0x01, 0x05, 0x02, 0xca, - 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x63, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x11, 0x11, - 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x17, 0x33, 0x11, 0x23, 0x35, 0x33, 0x11, 0x23, 0x19, 0x6d, 0x6d, 0xec, 0xec, 0x37, 0x02, 0x9a, 0x67, 0xfc, 0x98, 0x00, - 0x00, 0x01, 0x00, 0x17, 0x00, 0xfe, 0x02, 0x25, 0x02, 0xce, 0x00, 0x06, 0x00, 0x27, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, - 0x00, 0x00, 0x01, 0x00, 0x85, 0x03, 0x02, 0x02, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, - 0x44, 0x37, 0x13, 0x33, 0x13, 0x23, 0x03, 0x03, 0x17, 0xd6, 0x46, 0xf2, 0x75, 0x9d, 0x89, 0xfe, 0x01, 0xd0, 0xfe, 0x30, 0x01, 0x3a, 0xfe, 0xc6, 0x00, 0x01, - 0xff, 0xfe, 0xff, 0x62, 0x01, 0x9d, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x20, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, - 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x05, 0x21, 0x35, 0x21, 0x01, 0x9d, 0xfe, 0x61, - 0x01, 0x9f, 0x9e, 0x44, 0x00, 0x01, 0x00, 0x28, 0x02, 0x5e, 0x01, 0x45, 0x02, 0xfe, 0x00, 0x0c, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x0b, 0x04, - 0x02, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x00, 0x01, 0x85, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x15, 0x03, 0x0d, 0x17, 0x2b, - 0xb1, 0x06, 0x00, 0x44, 0x13, 0x1e, 0x02, 0x17, 0x15, 0x23, 0x2e, 0x03, 0x27, 0x35, 0xd1, 0x0f, 0x2a, 0x2a, 0x11, 0x65, 0x13, 0x33, 0x35, 0x2f, 0x0e, 0x02, - 0xfe, 0x16, 0x37, 0x33, 0x13, 0x0d, 0x0d, 0x27, 0x2c, 0x28, 0x0e, 0x0a, 0x00, 0x02, 0x00, 0x28, 0xff, 0xf6, 0x02, 0x10, 0x02, 0x2c, 0x00, 0x1b, 0x00, 0x26, - 0x00, 0x7b, 0x40, 0x0e, 0x19, 0x01, 0x04, 0x00, 0x18, 0x01, 0x03, 0x04, 0x06, 0x01, 0x01, 0x06, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x20, 0x00, - 0x03, 0x08, 0x01, 0x05, 0x06, 0x03, 0x05, 0x69, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x01, 0x61, 0x02, 0x01, - 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x24, 0x00, 0x03, 0x08, 0x01, 0x05, 0x06, 0x03, 0x05, 0x69, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, - 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x00, 0x06, 0x06, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x1d, 0x1c, 0x01, 0x00, 0x23, - 0x21, 0x1c, 0x26, 0x1d, 0x26, 0x16, 0x14, 0x11, 0x0f, 0x0b, 0x09, 0x05, 0x04, 0x00, 0x1b, 0x01, 0x1b, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, - 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x13, 0x06, 0x06, - 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x35, 0x01, 0x3d, 0x66, 0x6d, 0x69, 0x1d, 0x04, 0x24, 0x4d, 0x45, 0x48, 0x60, 0x7c, 0x7b, 0x5b, 0x2d, 0x27, 0x25, - 0x4e, 0x26, 0x2c, 0x2b, 0x6f, 0x46, 0x48, 0x37, 0x27, 0x21, 0x2f, 0x41, 0x02, 0x2c, 0x61, 0x5f, 0xfe, 0x94, 0x4a, 0x2c, 0x28, 0x54, 0x57, 0x55, 0x57, 0x05, - 0x03, 0x11, 0x31, 0x27, 0x18, 0x11, 0x67, 0x16, 0x1a, 0xfe, 0xce, 0x02, 0x2a, 0x26, 0x23, 0x21, 0x38, 0x34, 0x2d, 0x00, 0x00, 0x02, 0x00, 0x49, 0xff, 0xf6, - 0x02, 0x48, 0x02, 0xf8, 0x00, 0x15, 0x00, 0x21, 0x00, 0x6b, 0xb5, 0x03, 0x01, 0x05, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x21, 0x07, 0x01, - 0x05, 0x05, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6c, 0x4d, 0x00, 0x06, 0x06, 0x01, 0x61, 0x03, 0x01, - 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1b, 0x40, 0x25, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, - 0x04, 0x6c, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x59, 0x40, 0x10, 0x17, 0x16, 0x1e, 0x1c, - 0x16, 0x21, 0x17, 0x21, 0x11, 0x11, 0x12, 0x24, 0x26, 0x08, 0x0d, 0x1b, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, - 0x23, 0x22, 0x26, 0x27, 0x23, 0x07, 0x23, 0x11, 0x33, 0x13, 0x22, 0x06, 0x15, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0xe0, 0x04, 0x02, 0x06, 0x16, - 0x4a, 0x3b, 0x5b, 0x72, 0x73, 0x5e, 0x3c, 0x45, 0x16, 0x0a, 0x19, 0x74, 0x97, 0x6a, 0x39, 0x31, 0x2f, 0x3d, 0x31, 0x32, 0x02, 0x47, 0x1f, 0x38, 0x15, 0x22, - 0x2f, 0x8f, 0x8b, 0x8c, 0x90, 0x2b, 0x1a, 0x3b, 0x02, 0xf8, 0xfe, 0xbc, 0x48, 0x4d, 0x12, 0x4e, 0x4f, 0x54, 0x50, 0xa0, 0x00, 0x01, 0x00, 0x2f, 0xff, 0xf6, - 0x01, 0xe8, 0x02, 0x2c, 0x00, 0x1b, 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, 0x02, 0x01, 0x18, 0x0c, 0x02, 0x03, 0x02, 0x19, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, - 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x16, 0x14, 0x10, - 0x0e, 0x09, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, - 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x01, 0x37, 0x4f, 0x77, 0x42, 0x48, 0x7c, 0x4f, 0x2f, 0x56, 0x21, 0x2d, 0x1e, - 0x3d, 0x1e, 0x3a, 0x3f, 0x3f, 0x38, 0x2a, 0x4e, 0x21, 0x20, 0x4d, 0x0a, 0x3b, 0x7c, 0x61, 0x64, 0x7f, 0x3b, 0x14, 0x11, 0x72, 0x0d, 0x11, 0x52, 0x52, 0x51, - 0x4e, 0x17, 0x13, 0x7b, 0x13, 0x16, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x2f, 0x02, 0xf8, 0x00, 0x15, 0x00, 0x22, 0x00, 0x82, 0x4b, 0xb0, 0x19, 0x50, - 0x58, 0x40, 0x0a, 0x09, 0x01, 0x05, 0x01, 0x12, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x09, 0x01, 0x05, 0x01, 0x12, 0x01, 0x03, 0x04, 0x02, 0x4c, - 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, - 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, - 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, - 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x22, 0x17, 0x22, 0x11, 0x10, 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, - 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x26, 0x26, 0x35, 0x35, 0x33, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x27, 0x32, 0x36, 0x37, 0x35, 0x34, 0x26, 0x23, - 0x22, 0x06, 0x15, 0x14, 0x16, 0xfc, 0x5b, 0x72, 0x74, 0x5e, 0x3a, 0x48, 0x17, 0x05, 0x03, 0x05, 0x98, 0x74, 0x1e, 0x06, 0x15, 0x4a, 0x07, 0x3d, 0x32, 0x01, - 0x30, 0x41, 0x31, 0x37, 0x37, 0x0a, 0x8f, 0x8b, 0x8d, 0x8f, 0x2e, 0x22, 0x12, 0x41, 0x1b, 0xae, 0xfd, 0x08, 0x47, 0x22, 0x2f, 0x79, 0x47, 0x49, 0x10, 0x4f, - 0x54, 0x54, 0x50, 0x50, 0x4f, 0x00, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x27, 0x02, 0x2c, 0x00, 0x15, 0x00, 0x1c, 0x00, 0x43, 0x40, 0x40, 0x0b, 0x01, - 0x02, 0x01, 0x0c, 0x01, 0x03, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x01, 0x02, 0x05, 0x01, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, - 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x17, 0x16, 0x01, 0x00, 0x1a, 0x19, 0x16, 0x1c, 0x17, 0x1c, 0x10, 0x0e, 0x09, - 0x07, 0x05, 0x04, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x15, 0x21, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, - 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x07, 0x33, 0x26, 0x26, 0x01, 0x32, 0x72, 0x83, 0xfe, 0xa1, 0x03, 0x47, 0x43, 0x33, 0x54, 0x2c, - 0x28, 0x5a, 0x41, 0x51, 0x7d, 0x48, 0x8f, 0x78, 0x2d, 0x39, 0x04, 0xce, 0x01, 0x31, 0x02, 0x2c, 0x80, 0x78, 0x49, 0x3e, 0x47, 0x14, 0x14, 0x71, 0x14, 0x13, - 0x3d, 0x7c, 0x5e, 0x8f, 0x90, 0x6b, 0x39, 0x38, 0x31, 0x40, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x01, 0xb0, 0x02, 0xfd, 0x00, 0x18, 0x00, 0x86, 0x40, 0x13, - 0x0f, 0x01, 0x04, 0x03, 0x10, 0x01, 0x05, 0x04, 0x06, 0x01, 0x00, 0x05, 0x03, 0x4c, 0x07, 0x01, 0x05, 0x01, 0x4b, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1b, - 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, - 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, - 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x02, 0x01, 0x00, - 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x59, 0x40, 0x09, 0x13, 0x25, 0x26, 0x11, 0x11, 0x10, 0x06, 0x0d, - 0x1c, 0x2b, 0x01, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x37, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x15, - 0x33, 0x01, 0x7c, 0x81, 0x95, 0x52, 0x52, 0x2f, 0x57, 0x3b, 0x2c, 0x47, 0x16, 0x26, 0x11, 0x28, 0x1a, 0x1f, 0x1d, 0x81, 0x01, 0xb2, 0xfe, 0x4e, 0x01, 0xb2, - 0x48, 0x28, 0x28, 0x46, 0x4d, 0x20, 0x0e, 0x09, 0x6d, 0x05, 0x09, 0x26, 0x1d, 0x22, 0x00, 0x02, 0x00, 0x2f, 0xff, 0x10, 0x02, 0x2f, 0x02, 0x2c, 0x00, 0x21, - 0x00, 0x2d, 0x00, 0x9e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x03, 0x01, 0x05, 0x00, 0x18, 0x01, 0x04, 0x06, 0x0e, 0x01, 0x03, 0x04, 0x0d, 0x01, 0x02, - 0x03, 0x04, 0x4c, 0x1b, 0x40, 0x12, 0x03, 0x01, 0x05, 0x01, 0x18, 0x01, 0x04, 0x06, 0x0e, 0x01, 0x03, 0x04, 0x0d, 0x01, 0x02, 0x03, 0x04, 0x4c, 0x59, 0x4b, - 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x08, 0x01, 0x05, 0x05, 0x00, 0x61, 0x01, 0x07, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, - 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x08, 0x01, 0x05, 0x05, - 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, - 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x23, 0x22, 0x01, 0x00, 0x28, 0x26, 0x22, 0x2d, 0x23, 0x2d, 0x1d, 0x1b, 0x12, 0x10, 0x0b, 0x09, 0x06, 0x05, 0x00, 0x21, - 0x01, 0x21, 0x09, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, - 0x35, 0x35, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x33, 0x32, 0x36, 0x35, 0x35, 0x34, 0x26, - 0xff, 0x38, 0x4d, 0x19, 0x05, 0x0d, 0x80, 0x86, 0x8c, 0x3f, 0x64, 0x2c, 0x2e, 0x5e, 0x3e, 0x3e, 0x42, 0x03, 0x02, 0x05, 0x17, 0x4b, 0x38, 0x5f, 0x70, 0x72, - 0x8f, 0x32, 0x35, 0x6a, 0x3c, 0x33, 0x33, 0x02, 0x2c, 0x2b, 0x24, 0x45, 0xfd, 0xda, 0x74, 0x78, 0x0f, 0x12, 0x80, 0x14, 0x16, 0x3a, 0x33, 0x0f, 0x0c, 0x28, - 0x0f, 0x24, 0x2c, 0x92, 0x88, 0x88, 0x94, 0x77, 0x56, 0x51, 0xa2, 0x46, 0x4a, 0x16, 0x52, 0x51, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x02, 0x43, 0x02, 0xf8, - 0x00, 0x16, 0x00, 0x27, 0x40, 0x24, 0x03, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x00, 0x04, 0x04, 0x6c, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, - 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x11, 0x13, 0x22, 0x13, 0x26, 0x05, 0x0d, 0x1b, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, - 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0xe0, 0x04, 0x03, 0x08, 0x1b, 0x51, 0x32, 0x58, 0x6c, 0x97, 0x57, 0x43, - 0x32, 0x97, 0x97, 0x02, 0x5f, 0x2d, 0x43, 0x13, 0x2a, 0x26, 0x5f, 0x69, 0xfe, 0x9c, 0x01, 0x3e, 0x76, 0x5d, 0x57, 0xff, 0x00, 0x02, 0xf8, 0x00, 0x00, 0x02, - 0x00, 0x44, 0x00, 0x00, 0x00, 0xe8, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x72, - 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0c, 0x0c, 0x01, 0x00, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, - 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x11, 0x23, 0x11, 0x96, 0x21, 0x31, - 0x31, 0x21, 0x22, 0x30, 0x30, 0x6d, 0x97, 0x02, 0xf9, 0x1f, 0x2b, 0x29, 0x20, 0x20, 0x29, 0x2b, 0x1f, 0xd7, 0xfd, 0xde, 0x02, 0x22, 0x00, 0x02, 0xff, 0xcb, - 0xff, 0x10, 0x00, 0xe8, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x1c, 0x00, 0x37, 0x40, 0x34, 0x10, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x00, 0x01, - 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x72, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x62, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x0d, - 0x0c, 0x18, 0x17, 0x14, 0x12, 0x0c, 0x1c, 0x0d, 0x1c, 0x24, 0x22, 0x06, 0x0d, 0x18, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, - 0x26, 0x03, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x06, 0x44, 0x2f, 0x23, 0x21, 0x31, 0x31, 0x21, 0x23, - 0x2f, 0x1c, 0x18, 0x33, 0x12, 0x10, 0x1c, 0x12, 0x1b, 0x25, 0x97, 0x24, 0x51, 0x02, 0xaf, 0x2b, 0x1f, 0x1f, 0x2b, 0x29, 0x20, 0x20, 0xfc, 0x8a, 0x07, 0x05, - 0x77, 0x05, 0x05, 0x22, 0x32, 0x02, 0x45, 0xfd, 0xa3, 0x32, 0x52, 0x31, 0x00, 0x01, 0x00, 0x4e, 0x00, 0x00, 0x02, 0x6c, 0x02, 0xf8, 0x00, 0x12, 0x00, 0x24, - 0x40, 0x21, 0x0e, 0x0d, 0x0a, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, - 0x01, 0x4e, 0x11, 0x13, 0x12, 0x18, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x37, 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x15, - 0x23, 0x11, 0x33, 0xe3, 0x05, 0x03, 0x02, 0x0f, 0x20, 0x12, 0x99, 0xa8, 0xd9, 0xe6, 0xac, 0x9d, 0x40, 0x95, 0x95, 0x01, 0xa4, 0x1f, 0x3d, 0x1f, 0x15, 0x2b, - 0x13, 0xa6, 0xed, 0xfe, 0xcb, 0xdd, 0x33, 0xaa, 0x02, 0xf8, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x00, 0xe0, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x13, 0x40, 0x10, - 0x00, 0x01, 0x01, 0x6c, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x33, 0x23, 0x11, 0x33, 0xe0, 0x97, 0x97, 0x02, 0xf8, - 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x03, 0x88, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x6c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0xb6, 0x21, 0x1a, 0x02, 0x02, 0x00, 0x01, - 0x4c, 0x1b, 0xb6, 0x21, 0x1a, 0x02, 0x02, 0x06, 0x01, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x04, 0x01, 0x02, 0x02, 0x00, 0x61, 0x07, 0x06, - 0x08, 0x03, 0x00, 0x00, 0x73, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x1a, 0x00, 0x06, 0x06, 0x6d, 0x4d, 0x04, 0x01, 0x02, 0x02, - 0x00, 0x61, 0x07, 0x08, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x17, 0x01, 0x00, 0x1f, 0x1d, 0x19, 0x18, - 0x17, 0x16, 0x13, 0x11, 0x0e, 0x0d, 0x0a, 0x08, 0x05, 0x04, 0x00, 0x24, 0x01, 0x24, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, - 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, - 0x33, 0x36, 0x36, 0x02, 0xca, 0x5e, 0x60, 0x96, 0x2a, 0x2a, 0x3b, 0x2f, 0x97, 0x28, 0x2a, 0x3e, 0x2d, 0x97, 0x74, 0x16, 0x05, 0x17, 0x54, 0x38, 0x3d, 0x51, - 0x17, 0x05, 0x1b, 0x56, 0x02, 0x2c, 0x5f, 0x69, 0xfe, 0x9c, 0x01, 0x3e, 0x3f, 0x37, 0x55, 0x4e, 0xfe, 0xef, 0x01, 0x3e, 0x3d, 0x39, 0x5d, 0x57, 0xff, 0x00, - 0x02, 0x22, 0x46, 0x25, 0x2b, 0x2a, 0x28, 0x29, 0x29, 0x00, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x02, 0x43, 0x02, 0x2c, 0x00, 0x12, 0x00, 0x5e, 0x4b, 0xb0, - 0x19, 0x50, 0x58, 0xb5, 0x10, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x1b, 0xb5, 0x10, 0x01, 0x02, 0x04, 0x01, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, - 0x00, 0x02, 0x02, 0x00, 0x61, 0x04, 0x05, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x04, 0x04, 0x6d, - 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x05, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, 0x0f, 0x0e, - 0x0d, 0x0c, 0x09, 0x07, 0x05, 0x04, 0x00, 0x12, 0x01, 0x12, 0x06, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, - 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x01, 0x81, 0x5a, 0x68, 0x96, 0x58, 0x44, 0x31, 0x97, 0x74, 0x15, 0x06, 0x36, 0x02, 0x2c, 0x5f, 0x69, 0xfe, 0x9c, - 0x01, 0x3e, 0x76, 0x5d, 0x57, 0xff, 0x00, 0x02, 0x22, 0x49, 0x53, 0x00, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x41, 0x02, 0x2c, 0x00, 0x0d, 0x00, 0x19, - 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, - 0x25, 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, - 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x41, 0x8f, 0x7b, 0x4d, 0x77, 0x44, 0x8f, 0x7c, 0x4d, 0x76, 0x44, 0xfe, 0x88, 0x34, 0x3c, 0x3a, 0x34, 0x34, - 0x3b, 0x3b, 0x34, 0x01, 0x12, 0x88, 0x94, 0x42, 0x7f, 0x5b, 0x88, 0x92, 0x41, 0x7e, 0x5b, 0x50, 0x59, 0x59, 0x50, 0x51, 0x56, 0x56, 0x00, 0x02, 0x00, 0x49, - 0xff, 0x10, 0x02, 0x48, 0x02, 0x2c, 0x00, 0x15, 0x00, 0x21, 0x00, 0x82, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x12, 0x01, 0x04, 0x00, 0x09, 0x01, 0x01, - 0x05, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x12, 0x01, 0x04, 0x03, 0x09, 0x01, 0x01, 0x05, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x07, 0x01, - 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, - 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, - 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x21, 0x17, 0x21, 0x11, 0x10, - 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x16, 0x16, 0x15, - 0x15, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x17, 0x22, 0x06, 0x07, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x01, 0x7b, 0x5e, 0x6f, 0x75, 0x5c, - 0x3c, 0x47, 0x14, 0x06, 0x02, 0x04, 0x97, 0x7b, 0x15, 0x07, 0x16, 0x48, 0x0b, 0x3a, 0x2d, 0x02, 0x2d, 0x3d, 0x33, 0x32, 0x02, 0x2c, 0x8f, 0x8b, 0x8c, 0x90, - 0x2b, 0x1a, 0x12, 0x2f, 0x19, 0xd1, 0x03, 0x12, 0x47, 0x21, 0x30, 0x78, 0x48, 0x49, 0x10, 0x4f, 0x54, 0x54, 0x50, 0xa0, 0x00, 0x02, 0x00, 0x2f, 0xff, 0x10, - 0x02, 0x2f, 0x02, 0x2c, 0x00, 0x15, 0x00, 0x21, 0x00, 0x78, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x10, 0x01, 0x05, 0x01, 0x03, 0x01, 0x00, 0x04, 0x02, - 0x4c, 0x1b, 0x40, 0x0a, 0x10, 0x01, 0x05, 0x02, 0x03, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, - 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, - 0x20, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, - 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x17, 0x16, 0x1e, 0x1c, 0x16, 0x21, 0x17, 0x21, 0x11, 0x14, 0x24, 0x26, 0x07, 0x0d, 0x1a, 0x2b, - 0x05, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x23, 0x03, 0x32, 0x36, 0x35, - 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x01, 0x98, 0x02, 0x03, 0x06, 0x15, 0x49, 0x3c, 0x5c, 0x72, 0x74, 0x5d, 0x3c, 0x4a, 0x17, 0x04, 0x0e, 0x80, - 0x97, 0x65, 0x3d, 0x31, 0x2f, 0x42, 0x34, 0x33, 0x0b, 0x13, 0x2c, 0x13, 0x22, 0x2f, 0x8f, 0x8b, 0x8c, 0x90, 0x2e, 0x22, 0x46, 0xfc, 0xee, 0x01, 0x5d, 0x47, - 0x49, 0x15, 0x4f, 0x55, 0x58, 0x50, 0xa1, 0x00, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x01, 0xb3, 0x02, 0x2c, 0x00, 0x13, 0x00, 0x69, 0x4b, 0xb0, 0x19, 0x50, - 0x58, 0x40, 0x0b, 0x10, 0x03, 0x02, 0x01, 0x00, 0x04, 0x01, 0x02, 0x01, 0x02, 0x4c, 0x1b, 0x40, 0x0e, 0x03, 0x01, 0x03, 0x00, 0x10, 0x01, 0x01, 0x03, 0x04, - 0x01, 0x02, 0x01, 0x03, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x01, 0x01, 0x00, 0x61, 0x03, 0x04, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, - 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, - 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0f, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x13, 0x01, 0x13, 0x05, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, - 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x01, 0x77, 0x0f, 0x22, 0x0b, 0x0f, 0x0b, 0x1e, 0x15, - 0x1f, 0x3e, 0x29, 0x97, 0x73, 0x16, 0x07, 0x18, 0x53, 0x02, 0x2c, 0x04, 0x02, 0x8d, 0x03, 0x03, 0x1a, 0x3c, 0x34, 0xfe, 0xeb, 0x02, 0x22, 0x5c, 0x2a, 0x3c, - 0x00, 0x01, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xcc, 0x02, 0x2c, 0x00, 0x27, 0x00, 0x2e, 0x40, 0x2b, 0x1a, 0x01, 0x03, 0x02, 0x1b, 0x07, 0x02, 0x01, 0x03, 0x06, - 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, - 0x25, 0x2b, 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, - 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xcc, 0x6f, 0x73, 0x3a, - 0x58, 0x29, 0x2c, 0x65, 0x26, 0x2e, 0x29, 0x15, 0x35, 0x31, 0x49, 0x4b, 0x77, 0x62, 0x34, 0x5c, 0x2f, 0x2c, 0x26, 0x50, 0x1f, 0x48, 0x15, 0x35, 0x30, 0x31, - 0x43, 0x21, 0xa1, 0x4e, 0x5d, 0x0f, 0x11, 0x7d, 0x15, 0x18, 0x1a, 0x16, 0x0f, 0x18, 0x1a, 0x13, 0x1d, 0x47, 0x44, 0x4c, 0x4e, 0x16, 0x14, 0x67, 0x11, 0x16, - 0x28, 0x0f, 0x15, 0x18, 0x13, 0x14, 0x2a, 0x3d, 0x00, 0x01, 0x00, 0x17, 0xff, 0xf6, 0x01, 0x92, 0x02, 0x96, 0x00, 0x18, 0x00, 0x40, 0x40, 0x3d, 0x0e, 0x01, - 0x02, 0x04, 0x03, 0x01, 0x00, 0x02, 0x04, 0x01, 0x01, 0x00, 0x03, 0x4c, 0x00, 0x03, 0x04, 0x03, 0x85, 0x05, 0x01, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, 0x04, - 0x6d, 0x4d, 0x06, 0x01, 0x00, 0x00, 0x01, 0x62, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x01, 0x00, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0d, 0x0c, 0x08, 0x06, - 0x00, 0x18, 0x01, 0x18, 0x07, 0x0d, 0x16, 0x2b, 0x25, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x11, 0x23, 0x35, 0x37, 0x37, 0x33, - 0x15, 0x33, 0x15, 0x23, 0x11, 0x14, 0x16, 0x01, 0x34, 0x19, 0x2e, 0x17, 0x18, 0x47, 0x2a, 0x31, 0x4d, 0x2d, 0x47, 0x52, 0x2b, 0x5f, 0x99, 0x99, 0x24, 0x6d, - 0x0a, 0x07, 0x6f, 0x0a, 0x0f, 0x20, 0x4f, 0x46, 0x01, 0x07, 0x3f, 0x32, 0x73, 0x74, 0x70, 0xfe, 0xf9, 0x1f, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x46, 0xff, 0xf6, - 0x02, 0x40, 0x02, 0x22, 0x00, 0x14, 0x00, 0x50, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x18, 0x00, 0x01, 0x01, 0x03, 0x5f, 0x06, 0x05, 0x02, 0x03, 0x03, 0x6d, - 0x4d, 0x00, 0x04, 0x04, 0x00, 0x62, 0x02, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1b, 0x40, 0x1c, 0x00, 0x01, 0x01, 0x03, 0x5f, 0x06, 0x05, 0x02, 0x03, 0x03, - 0x6d, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0x00, 0x04, 0x04, 0x02, 0x62, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x59, 0x40, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, - 0x14, 0x23, 0x13, 0x22, 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x01, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, - 0x33, 0x32, 0x36, 0x35, 0x11, 0x02, 0x40, 0x74, 0x13, 0x09, 0x1a, 0x5a, 0x34, 0x57, 0x6b, 0x98, 0x29, 0x2d, 0x44, 0x31, 0x02, 0x22, 0xfd, 0xde, 0x46, 0x2a, - 0x26, 0x5f, 0x69, 0x01, 0x64, 0xfe, 0xc2, 0x3a, 0x3b, 0x5c, 0x57, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3b, 0x02, 0x22, 0x00, 0x0d, - 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, - 0x0d, 0x00, 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0xd0, 0xd0, 0x9e, - 0x66, 0x05, 0x0f, 0x02, 0x04, 0x02, 0x0f, 0x06, 0x68, 0x9e, 0xd0, 0x02, 0x22, 0xfe, 0xbe, 0x10, 0x37, 0x13, 0x14, 0x33, 0x12, 0x01, 0x43, 0xfd, 0xde, 0x00, - 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x03, 0x4e, 0x02, 0x22, 0x00, 0x2a, 0x00, 0x21, 0x40, 0x1e, 0x21, 0x14, 0x05, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x02, - 0x02, 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x1b, 0x1c, 0x11, 0x1c, 0x05, 0x0d, 0x1b, 0x2b, 0x25, 0x2e, 0x03, 0x27, 0x23, - 0x0e, 0x03, 0x07, 0x07, 0x23, 0x03, 0x33, 0x17, 0x1e, 0x02, 0x17, 0x33, 0x3e, 0x03, 0x37, 0x13, 0x33, 0x13, 0x1e, 0x02, 0x15, 0x33, 0x3e, 0x02, 0x37, 0x37, - 0x33, 0x03, 0x23, 0x01, 0xe5, 0x04, 0x0f, 0x12, 0x10, 0x03, 0x04, 0x03, 0x0f, 0x12, 0x10, 0x04, 0x2c, 0xa0, 0x9b, 0x94, 0x3f, 0x07, 0x0b, 0x0a, 0x02, 0x04, - 0x01, 0x06, 0x09, 0x07, 0x02, 0x43, 0xa4, 0x40, 0x04, 0x0b, 0x09, 0x04, 0x02, 0x0a, 0x0d, 0x07, 0x41, 0x92, 0x9d, 0xa2, 0xbf, 0x11, 0x43, 0x4d, 0x41, 0x0f, - 0x0f, 0x41, 0x4d, 0x44, 0x12, 0xbd, 0x02, 0x22, 0xf2, 0x19, 0x46, 0x41, 0x13, 0x0e, 0x2f, 0x32, 0x29, 0x07, 0x01, 0x06, 0xfe, 0xfa, 0x0e, 0x3e, 0x40, 0x13, - 0x11, 0x41, 0x48, 0x19, 0xf2, 0xfd, 0xde, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x02, 0x3d, 0x02, 0x22, 0x00, 0x0b, 0x00, 0x1f, 0x40, 0x1c, 0x09, 0x06, - 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x12, 0x12, 0x12, 0x11, 0x04, 0x0d, 0x1a, - 0x2b, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x23, 0xbe, 0xb0, 0xa9, 0x6a, 0x6b, 0xa9, 0xb2, 0xba, 0xa9, 0x73, 0x73, 0xa9, 0x01, - 0x17, 0x01, 0x0b, 0xae, 0xae, 0xfe, 0xf5, 0xfe, 0xe9, 0xbb, 0xbb, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0x10, 0x02, 0x3b, 0x02, 0x22, 0x00, 0x1a, 0x00, 0x27, - 0x40, 0x24, 0x1a, 0x13, 0x05, 0x03, 0x03, 0x00, 0x12, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x62, 0x00, - 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x25, 0x23, 0x19, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x11, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, - 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x9f, 0x67, 0x07, 0x0d, 0x03, 0x04, 0x03, 0x0f, 0x07, 0x65, 0x9c, 0xe0, - 0x22, 0x69, 0x61, 0x1a, 0x25, 0x0d, 0x0a, 0x20, 0x11, 0x2e, 0x32, 0x0f, 0x0c, 0x02, 0x22, 0xfe, 0xc8, 0x16, 0x31, 0x16, 0x15, 0x32, 0x16, 0x01, 0x38, 0xfd, - 0xac, 0x5c, 0x62, 0x05, 0x03, 0x77, 0x02, 0x04, 0x35, 0x27, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x01, 0xce, 0x02, 0x22, 0x00, 0x09, 0x00, 0x29, - 0x40, 0x26, 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x00, - 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x13, 0x23, 0x35, 0x21, 0x15, 0x03, 0x33, 0x01, - 0xce, 0xfe, 0x50, 0xfc, 0xee, 0x01, 0x99, 0xf5, 0xfe, 0x59, 0x01, 0x56, 0x73, 0x61, 0xfe, 0xb3, 0x00, 0x01, 0x00, 0x0f, 0xff, 0x62, 0x01, 0x62, 0x02, 0xca, - 0x00, 0x1f, 0x00, 0x2c, 0x40, 0x29, 0x18, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, 0x4e, 0x1b, 0x11, 0x16, 0x11, 0x16, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x05, 0x22, 0x26, 0x26, - 0x35, 0x35, 0x34, 0x26, 0x23, 0x35, 0x32, 0x36, 0x35, 0x35, 0x34, 0x36, 0x36, 0x33, 0x15, 0x06, 0x06, 0x15, 0x15, 0x14, 0x07, 0x15, 0x16, 0x15, 0x15, 0x14, - 0x16, 0x17, 0x01, 0x62, 0x55, 0x5d, 0x24, 0x40, 0x3d, 0x3d, 0x40, 0x24, 0x5d, 0x55, 0x27, 0x2e, 0x72, 0x72, 0x2e, 0x27, 0x9e, 0x1c, 0x3c, 0x30, 0x9a, 0x2f, - 0x28, 0x75, 0x28, 0x2f, 0x9b, 0x30, 0x3c, 0x1c, 0x6e, 0x01, 0x1a, 0x2a, 0x92, 0x5b, 0x11, 0x06, 0x11, 0x5b, 0x92, 0x2a, 0x1a, 0x01, 0x00, 0x01, 0x00, 0xde, - 0xff, 0x1d, 0x01, 0x49, 0x02, 0xf5, 0x00, 0x03, 0x00, 0x28, 0x4b, 0xb0, 0x27, 0x50, 0x58, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x01, 0x01, 0x6f, - 0x01, 0x4e, 0x1b, 0x40, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x4e, 0x59, 0xb4, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x13, 0x33, - 0x11, 0x23, 0xde, 0x6b, 0x6b, 0x02, 0xf5, 0xfc, 0x28, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, 0x62, 0x01, 0x7b, 0x02, 0xca, 0x00, 0x1f, 0x00, 0x2c, 0x40, 0x29, - 0x06, 0x01, 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, 0x00, 0x01, 0x01, 0x02, 0x61, - 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x16, 0x11, 0x16, 0x11, 0x1b, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x17, 0x36, 0x36, 0x35, 0x35, 0x34, 0x37, 0x35, 0x26, 0x35, - 0x35, 0x34, 0x26, 0x27, 0x35, 0x32, 0x16, 0x16, 0x15, 0x15, 0x14, 0x16, 0x33, 0x15, 0x22, 0x06, 0x15, 0x15, 0x14, 0x06, 0x06, 0x23, 0x28, 0x27, 0x2e, 0x72, - 0x72, 0x2e, 0x27, 0x56, 0x5c, 0x24, 0x40, 0x3d, 0x3d, 0x40, 0x24, 0x5c, 0x56, 0x30, 0x01, 0x1a, 0x2a, 0x92, 0x5b, 0x11, 0x06, 0x11, 0x5b, 0x92, 0x2a, 0x1a, - 0x01, 0x6e, 0x1c, 0x3c, 0x30, 0x9b, 0x2f, 0x28, 0x75, 0x28, 0x2f, 0x9a, 0x30, 0x3c, 0x1c, 0x00, 0x00, 0x01, 0x00, 0x2b, 0x01, 0x0d, 0x02, 0x10, 0x01, 0xb4, - 0x00, 0x17, 0x00, 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, 0x02, 0x01, 0x13, 0x01, 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, - 0x03, 0x49, 0x00, 0x02, 0x00, 0x03, 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, 0x03, 0x51, - 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, - 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x01, 0x0c, 0x25, 0x33, 0x17, 0x1c, 0x3d, 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x2f, 0x25, 0x34, 0x16, - 0x1d, 0x3c, 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x01, 0x2d, 0x10, 0x0b, 0x22, 0x19, 0x71, 0x35, 0x0b, 0x14, 0x10, 0x0b, 0x22, 0x19, 0x71, 0x35, 0x0c, 0x00, 0x01, - 0x00, 0x17, 0x01, 0xa0, 0x01, 0x57, 0x03, 0x56, 0x00, 0x17, 0x00, 0x30, 0x40, 0x2d, 0x0c, 0x01, 0x01, 0x02, 0x0b, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, - 0x03, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x03, 0x02, 0x01, 0x69, 0x00, 0x03, 0x00, 0x00, 0x03, 0x57, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x00, 0x4f, - 0x16, 0x24, 0x27, 0x10, 0x04, 0x0c, 0x1a, 0x2b, 0x01, 0x21, 0x35, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, - 0x15, 0x14, 0x06, 0x07, 0x07, 0x33, 0x01, 0x57, 0xfe, 0xc4, 0x6d, 0x2d, 0x21, 0x17, 0x14, 0x27, 0x31, 0x3c, 0x20, 0x4f, 0x35, 0x41, 0x4f, 0x32, 0x3b, 0x33, - 0xac, 0x01, 0xa0, 0x52, 0x6b, 0x2c, 0x2f, 0x1a, 0x12, 0x14, 0x2b, 0x4a, 0x1c, 0x23, 0x3f, 0x3b, 0x2d, 0x4a, 0x35, 0x2e, 0x00, 0x01, 0x00, 0x1a, 0x01, 0x98, - 0x01, 0x5e, 0x03, 0x55, 0x00, 0x26, 0x00, 0x4d, 0x40, 0x4a, 0x24, 0x01, 0x05, 0x00, 0x23, 0x01, 0x04, 0x05, 0x05, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, - 0x0e, 0x01, 0x01, 0x02, 0x05, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x69, 0x00, 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, - 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x01, 0x00, 0x21, 0x1f, 0x1b, 0x19, 0x18, 0x16, 0x13, 0x11, 0x0c, 0x0a, 0x00, - 0x26, 0x01, 0x26, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x07, 0x15, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, - 0x32, 0x35, 0x34, 0x26, 0x23, 0x23, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0xb9, 0x49, 0x4e, 0x4d, 0x5b, 0x5d, - 0x56, 0x29, 0x49, 0x1e, 0x21, 0x48, 0x23, 0x4a, 0x24, 0x2f, 0x35, 0x2e, 0x2c, 0x23, 0x1c, 0x1b, 0x1a, 0x30, 0x1a, 0x31, 0x1f, 0x4e, 0x03, 0x55, 0x3b, 0x30, - 0x4e, 0x1b, 0x04, 0x15, 0x51, 0x3b, 0x44, 0x0f, 0x11, 0x5e, 0x14, 0x12, 0x32, 0x16, 0x1a, 0x50, 0x1c, 0x16, 0x14, 0x18, 0x12, 0x13, 0x45, 0x17, 0x1e, 0x00, - 0x00, 0x01, 0x00, 0x20, 0x01, 0xa0, 0x01, 0x15, 0x03, 0x4c, 0x00, 0x0d, 0x00, 0x27, 0x40, 0x24, 0x0c, 0x0b, 0x07, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, - 0x01, 0x00, 0x00, 0x01, 0x57, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0d, 0x11, 0x03, 0x0c, 0x17, - 0x2b, 0x01, 0x11, 0x23, 0x35, 0x34, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x01, 0x15, 0x70, 0x02, 0x02, 0x01, 0x07, 0x14, 0x0a, 0x2d, 0x38, - 0x97, 0x03, 0x4c, 0xfe, 0x54, 0xd6, 0x0d, 0x27, 0x25, 0x0a, 0x09, 0x14, 0x07, 0x24, 0x45, 0x76, 0x00, 0x01, 0xff, 0x40, 0x00, 0x00, 0x01, 0x41, 0x02, 0xca, - 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, - 0x0d, 0x17, 0x2b, 0x01, 0x01, 0x23, 0x01, 0x01, 0x41, 0xfe, 0x74, 0x75, 0x01, 0x8c, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0x00, 0x02, 0x00, 0x0c, 0x01, 0xa0, - 0x01, 0x73, 0x03, 0x4f, 0x00, 0x0a, 0x00, 0x12, 0x00, 0x5e, 0x40, 0x0a, 0x0d, 0x01, 0x04, 0x03, 0x06, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x4b, 0xb0, 0x10, 0x50, - 0x58, 0x40, 0x1e, 0x00, 0x03, 0x04, 0x03, 0x85, 0x00, 0x01, 0x00, 0x00, 0x01, 0x71, 0x05, 0x01, 0x04, 0x00, 0x00, 0x04, 0x57, 0x05, 0x01, 0x04, 0x04, 0x00, - 0x60, 0x02, 0x01, 0x00, 0x04, 0x00, 0x50, 0x1b, 0x40, 0x1d, 0x00, 0x03, 0x04, 0x03, 0x85, 0x00, 0x01, 0x00, 0x01, 0x86, 0x05, 0x01, 0x04, 0x00, 0x00, 0x04, - 0x57, 0x05, 0x01, 0x04, 0x04, 0x00, 0x60, 0x02, 0x01, 0x00, 0x04, 0x00, 0x50, 0x59, 0x40, 0x09, 0x17, 0x11, 0x12, 0x11, 0x11, 0x10, 0x06, 0x0c, 0x1c, 0x2b, - 0x01, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x13, 0x33, 0x11, 0x33, 0x27, 0x34, 0x37, 0x06, 0x06, 0x07, 0x07, 0x33, 0x01, 0x73, 0x3d, 0x6f, 0xbb, 0xb6, 0x74, - 0x3d, 0xac, 0x03, 0x05, 0x17, 0x09, 0x3e, 0x60, 0x01, 0xef, 0x4f, 0x4f, 0x4c, 0x01, 0x14, 0xfe, 0xf3, 0x56, 0x26, 0x29, 0x0d, 0x2a, 0x0e, 0x60, 0x00, 0x01, - 0x00, 0x28, 0x01, 0x98, 0x01, 0x5d, 0x03, 0x4e, 0x00, 0x1d, 0x00, 0x42, 0x40, 0x3f, 0x1c, 0x03, 0x02, 0x04, 0x01, 0x1b, 0x10, 0x02, 0x03, 0x04, 0x0f, 0x01, - 0x02, 0x03, 0x03, 0x4c, 0x06, 0x01, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x67, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x69, 0x00, 0x03, 0x02, 0x02, 0x03, - 0x59, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x03, 0x02, 0x51, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x1d, 0x23, 0x25, 0x24, 0x23, 0x11, 0x07, 0x0c, 0x1b, 0x2b, - 0x01, 0x15, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, 0x22, - 0x06, 0x07, 0x27, 0x37, 0x01, 0x40, 0xae, 0x07, 0x0a, 0x1c, 0x11, 0x41, 0x5a, 0x5e, 0x58, 0x23, 0x44, 0x18, 0x19, 0x42, 0x1a, 0x26, 0x2d, 0x51, 0x0c, 0x22, - 0x0b, 0x36, 0x12, 0x03, 0x4e, 0x55, 0x48, 0x01, 0x04, 0x46, 0x42, 0x47, 0x4f, 0x0c, 0x0d, 0x5f, 0x10, 0x14, 0x1d, 0x23, 0x3e, 0x05, 0x04, 0x14, 0xd9, 0x00, - 0x00, 0x01, 0x00, 0x1d, 0x01, 0xa0, 0x01, 0x64, 0x03, 0x4c, 0x00, 0x06, 0x00, 0x2a, 0x40, 0x27, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x00, - 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, - 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, 0x23, 0x35, 0x21, 0x15, 0x03, 0x4b, 0xa9, 0xd7, 0x01, 0x47, 0x9d, 0x01, 0xa0, 0x01, 0x55, 0x57, 0x4a, 0xfe, 0x9e, 0x00, - 0x00, 0x03, 0x00, 0x16, 0x01, 0x96, 0x01, 0x66, 0x03, 0x56, 0x00, 0x17, 0x00, 0x22, 0x00, 0x2d, 0x00, 0x39, 0x40, 0x36, 0x23, 0x1d, 0x12, 0x06, 0x04, 0x03, - 0x02, 0x01, 0x4c, 0x04, 0x01, 0x00, 0x05, 0x01, 0x02, 0x03, 0x00, 0x02, 0x69, 0x00, 0x03, 0x01, 0x01, 0x03, 0x59, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, - 0x03, 0x01, 0x51, 0x19, 0x18, 0x01, 0x00, 0x29, 0x27, 0x18, 0x22, 0x19, 0x22, 0x0d, 0x0b, 0x00, 0x17, 0x01, 0x17, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, - 0x15, 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x15, 0x14, 0x16, - 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x35, 0x34, 0x26, 0x27, 0xbf, 0x3f, 0x58, 0x29, 0x1d, 0x25, 0x31, 0x58, 0x4f, - 0x58, 0x51, 0x2e, 0x1f, 0x1d, 0x21, 0x5a, 0x3f, 0x33, 0x1c, 0x18, 0x16, 0x1b, 0x17, 0x24, 0x37, 0x1f, 0x20, 0x40, 0x20, 0x1f, 0x03, 0x56, 0x37, 0x37, 0x25, - 0x2f, 0x11, 0x0f, 0x33, 0x2b, 0x36, 0x4a, 0x49, 0x36, 0x2e, 0x2c, 0x10, 0x13, 0x32, 0x24, 0x36, 0x38, 0x4f, 0x27, 0x13, 0x1a, 0x0b, 0x0a, 0x19, 0x15, 0x0f, - 0x18, 0xb2, 0x17, 0x26, 0x18, 0x1b, 0x30, 0x16, 0x1c, 0x0a, 0x00, 0x02, 0x00, 0x14, 0x01, 0x96, 0x01, 0x67, 0x03, 0x56, 0x00, 0x0b, 0x00, 0x13, 0x00, 0x31, - 0x40, 0x2e, 0x00, 0x01, 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, - 0x02, 0x00, 0x51, 0x0d, 0x0c, 0x01, 0x00, 0x11, 0x0f, 0x0c, 0x13, 0x0d, 0x13, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, - 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x27, 0x32, 0x35, 0x34, 0x23, 0x22, 0x15, 0x14, 0xbc, 0x52, 0x56, 0x50, 0x58, 0x54, 0x57, 0x52, 0x58, - 0x2f, 0x2f, 0x2e, 0x01, 0x96, 0x77, 0x6a, 0x6a, 0x75, 0x75, 0x6a, 0x6a, 0x77, 0x65, 0x7b, 0x7a, 0x7a, 0x7b, 0x00, 0x02, 0x00, 0x16, 0x01, 0x96, 0x01, 0x66, - 0x03, 0x55, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x4a, 0x40, 0x47, 0x03, 0x01, 0x01, 0x00, 0x04, 0x01, 0x02, 0x01, 0x0a, 0x01, 0x04, 0x02, 0x03, 0x4c, 0x06, 0x01, - 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 0x69, 0x00, 0x02, 0x07, 0x01, 0x04, 0x05, 0x02, 0x04, 0x69, 0x00, 0x05, 0x03, 0x03, 0x05, 0x59, 0x00, 0x05, 0x05, 0x03, - 0x61, 0x00, 0x03, 0x05, 0x03, 0x51, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, 0x26, 0x1d, 0x26, 0x15, 0x13, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x1b, 0x01, 0x1b, - 0x08, 0x0c, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x17, 0x15, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, - 0x26, 0x35, 0x34, 0x3e, 0x02, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x35, 0x34, 0x26, 0x01, 0x03, 0x0e, 0x27, 0x0d, 0x0c, 0x1f, 0x14, 0x46, 0x39, - 0x03, 0x05, 0x0e, 0x2f, 0x26, 0x38, 0x42, 0x56, 0x4b, 0x4c, 0x63, 0x13, 0x33, 0x5d, 0x08, 0x1f, 0x21, 0x1d, 0x1f, 0x3b, 0x1d, 0x03, 0x55, 0x03, 0x03, 0x57, - 0x02, 0x04, 0x42, 0x35, 0x14, 0x19, 0x44, 0x41, 0x47, 0x52, 0x60, 0x60, 0x2f, 0x5b, 0x49, 0x2c, 0xea, 0x22, 0x14, 0x1a, 0x30, 0x43, 0x1d, 0x20, 0x00, 0x02, - 0x00, 0x15, 0x01, 0x96, 0x01, 0x64, 0x03, 0x56, 0x00, 0x19, 0x00, 0x24, 0x00, 0x4a, 0x40, 0x47, 0x10, 0x01, 0x03, 0x05, 0x0b, 0x01, 0x02, 0x03, 0x0a, 0x01, - 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x07, 0x01, 0x04, 0x05, 0x00, 0x04, 0x69, 0x00, 0x05, 0x00, 0x03, 0x02, 0x05, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, - 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1b, 0x1a, 0x01, 0x00, 0x20, 0x1e, 0x1a, 0x24, 0x1b, 0x24, 0x15, 0x13, 0x0e, 0x0c, - 0x08, 0x06, 0x00, 0x19, 0x01, 0x19, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, - 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xb8, 0x4a, 0x62, 0x28, 0x62, - 0x58, 0x16, 0x2a, 0x0c, 0x19, 0x30, 0x3f, 0x35, 0x03, 0x05, 0x0e, 0x2d, 0x25, 0x3a, 0x42, 0x57, 0x51, 0x3a, 0x1b, 0x1b, 0x1f, 0x22, 0x1e, 0x03, 0x56, 0x5f, - 0x60, 0x46, 0x75, 0x46, 0x04, 0x04, 0x58, 0x08, 0x43, 0x34, 0x14, 0x19, 0x45, 0x41, 0x46, 0x52, 0x54, 0x43, 0x1d, 0x21, 0x22, 0x14, 0x1d, 0x2e, 0xff, 0xff, - 0x00, 0x14, 0x00, 0x00, 0x03, 0x32, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x47, 0x01, 0x82, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, - 0x00, 0x00, 0x02, 0x6a, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, 0x82, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0x00, 0x00, - 0x02, 0x63, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x83, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0x00, 0x00, 0x03, 0xec, - 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x82, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x03, 0x04, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x14, 0x00, 0x00, 0x03, 0xe6, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x83, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, - 0x03, 0x06, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0xff, 0xf6, 0x01, 0x67, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x68, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, - 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x20, 0x00, 0x00, 0x01, 0x15, 0x01, 0xac, 0x03, 0x07, 0x00, 0x62, 0x00, 0x00, 0xfe, 0x60, - 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0x00, 0x01, 0x57, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x60, - 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1a, 0xff, 0xf8, 0x01, 0x5e, 0x01, 0xb5, - 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x00, - 0x01, 0x73, 0x01, 0xaf, 0x03, 0x07, 0x00, 0x64, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, - 0x00, 0x28, 0xff, 0xf8, 0x01, 0x5d, 0x01, 0xae, 0x03, 0x07, 0x00, 0x65, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, - 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0xff, 0xf6, 0x01, 0x66, 0x01, 0xb5, 0x03, 0x07, 0x00, 0x69, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, - 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x64, 0x01, 0xac, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, - 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0xff, 0xf6, 0x01, 0x66, 0x01, 0xb6, 0x03, 0x07, 0x00, 0x67, 0x00, 0x00, - 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x15, 0xff, 0xf6, 0x01, 0x64, 0x01, 0xb6, 0x03, 0x07, - 0x00, 0x6a, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x14, 0x01, 0x14, 0x01, 0x67, - 0x02, 0xd4, 0x01, 0x07, 0x00, 0x68, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x20, - 0x01, 0x1e, 0x01, 0x15, 0x02, 0xca, 0x03, 0x07, 0x00, 0x62, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, - 0xff, 0xff, 0x00, 0x17, 0x01, 0x1e, 0x01, 0x57, 0x02, 0xd4, 0x01, 0x07, 0x00, 0x60, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, - 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1a, 0x01, 0x16, 0x01, 0x5e, 0x02, 0xd3, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, - 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x01, 0x1e, 0x01, 0x73, 0x02, 0xcd, 0x03, 0x07, 0x00, 0x64, 0x00, 0x00, 0xff, 0x7e, - 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x28, 0x01, 0x16, 0x01, 0x5d, 0x02, 0xcc, 0x03, 0x07, 0x00, 0x65, - 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0x01, 0x14, 0x01, 0x66, 0x02, 0xd3, - 0x03, 0x07, 0x00, 0x69, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x1e, - 0x01, 0x64, 0x02, 0xca, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, - 0x00, 0x16, 0x01, 0x14, 0x01, 0x66, 0x02, 0xd4, 0x03, 0x07, 0x00, 0x67, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xff, 0x7e, 0xb0, 0x35, - 0x2b, 0x00, 0xff, 0xff, 0x00, 0x15, 0x01, 0x14, 0x01, 0x64, 0x02, 0xd4, 0x03, 0x07, 0x00, 0x6a, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, - 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, 0x00, 0xd4, 0x00, 0x18, 0x00, 0x65, 0x00, 0x06, 0x00, 0x02, 0x00, 0x98, - 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x89, 0x0e, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x54, 0x00, 0xa8, - 0x01, 0x0f, 0x01, 0xc7, 0x02, 0x5a, 0x02, 0x75, 0x02, 0x99, 0x02, 0xbd, 0x02, 0xed, 0x03, 0x15, 0x03, 0x35, 0x03, 0x50, 0x03, 0x6f, 0x03, 0x8b, 0x03, 0xc4, - 0x03, 0xeb, 0x04, 0x30, 0x04, 0x8f, 0x04, 0xc8, 0x05, 0x1a, 0x05, 0x90, 0x05, 0xb5, 0x06, 0x21, 0x06, 0x82, 0x06, 0xb7, 0x06, 0xe9, 0x06, 0xff, 0x07, 0x2a, - 0x07, 0x40, 0x07, 0x96, 0x08, 0x40, 0x08, 0x7a, 0x08, 0xd0, 0x09, 0x16, 0x09, 0x45, 0x09, 0x70, 0x09, 0x94, 0x09, 0xe4, 0x0a, 0x0c, 0x0a, 0x34, 0x0a, 0x67, - 0x0a, 0x93, 0x0a, 0xb1, 0x0a, 0xec, 0x0b, 0x1c, 0x0b, 0x58, 0x0b, 0x93, 0x0b, 0xdb, 0x0c, 0x1e, 0x0c, 0x71, 0x0c, 0x8f, 0x0c, 0xbc, 0x0c, 0xeb, 0x0d, 0x3f, - 0x0d, 0x69, 0x0d, 0x8d, 0x0d, 0xb8, 0x0d, 0xd7, 0x0d, 0xf3, 0x0e, 0x12, 0x0e, 0x38, 0x0e, 0x55, 0x0e, 0x80, 0x0e, 0xf9, 0x0f, 0x61, 0x0f, 0xa8, 0x10, 0x1d, - 0x10, 0x6d, 0x10, 0xd7, 0x11, 0x67, 0x11, 0x9f, 0x11, 0xd2, 0x12, 0x1b, 0x12, 0x4e, 0x12, 0x63, 0x12, 0xd0, 0x13, 0x1f, 0x13, 0x58, 0x13, 0xcc, 0x14, 0x3b, - 0x14, 0x92, 0x14, 0xe4, 0x15, 0x2b, 0x15, 0x76, 0x15, 0xa3, 0x15, 0xf5, 0x16, 0x1e, 0x16, 0x5f, 0x16, 0x88, 0x16, 0xcc, 0x16, 0xed, 0x17, 0x31, 0x17, 0x76, - 0x17, 0xb5, 0x18, 0x13, 0x18, 0x42, 0x18, 0x5e, 0x18, 0xae, 0x18, 0xfd, 0x19, 0x24, 0x19, 0x84, 0x19, 0xbc, 0x1a, 0x1a, 0x1a, 0x75, 0x1a, 0x81, 0x1a, 0x8d, - 0x1a, 0x99, 0x1a, 0xa9, 0x1a, 0xb9, 0x1a, 0xc8, 0x1a, 0xd7, 0x1a, 0xe6, 0x1a, 0xf5, 0x1b, 0x04, 0x1b, 0x13, 0x1b, 0x22, 0x1b, 0x31, 0x1b, 0x40, 0x1b, 0x4f, - 0x1b, 0x5e, 0x1b, 0x6d, 0x1b, 0x7c, 0x1b, 0x8b, 0x1b, 0x9a, 0x1b, 0xa9, 0x1b, 0xb8, 0x1b, 0xc7, 0x1b, 0xd6, 0x1b, 0xe5, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x02, 0x03, 0xd7, 0x28, 0x5e, 0xd5, 0x8c, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xd3, 0xe7, 0x00, 0x00, - 0x00, 0x00, 0xe3, 0x63, 0xc1, 0x01, 0xfd, 0x7c, 0xfe, 0x7b, 0x0a, 0xf1, 0x04, 0x2d, 0x00, 0x01, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x4d, 0x00, 0x59, 0x01, 0x04, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x36, 0x01, 0xdf, 0x00, 0x3d, 0x02, 0x86, 0x00, 0x16, 0x02, 0x3c, 0x00, 0x2b, 0x03, 0x86, - 0x00, 0x1e, 0x02, 0xee, 0x00, 0x28, 0x01, 0x0a, 0x00, 0x3d, 0x01, 0x53, 0x00, 0x28, 0x01, 0x53, 0x00, 0x1e, 0x02, 0x1e, 0x00, 0x1d, 0x02, 0x3c, 0x00, 0x2b, - 0x01, 0x1d, 0x00, 0x1f, 0x01, 0x40, 0x00, 0x1c, 0x01, 0x19, 0x00, 0x36, 0x01, 0x9f, 0x00, 0x07, 0x02, 0x3c, 0x00, 0x24, 0x02, 0x3c, 0x00, 0x3b, 0x02, 0x3c, - 0x00, 0x26, 0x02, 0x3c, 0x00, 0x26, 0x02, 0x3c, 0x00, 0x11, 0x02, 0x3c, 0x00, 0x31, 0x02, 0x3c, 0x00, 0x23, 0x02, 0x3c, 0x00, 0x1b, 0x02, 0x3c, 0x00, 0x23, - 0x02, 0x3c, 0x00, 0x20, 0x01, 0x19, 0x00, 0x36, 0x01, 0x1d, 0x00, 0x1f, 0x02, 0x3c, 0x00, 0x2b, 0x02, 0x3c, 0x00, 0x2b, 0x02, 0x3c, 0x00, 0x2b, 0x01, 0xdd, - 0x00, 0x05, 0x03, 0x82, 0x00, 0x2f, 0x02, 0xb4, 0x00, 0x00, 0x02, 0x99, 0x00, 0x55, 0x02, 0x82, 0x00, 0x37, 0x02, 0xdc, 0x00, 0x55, 0x02, 0x30, 0x00, 0x5a, - 0x02, 0x25, 0x00, 0x5a, 0x02, 0xd4, 0x00, 0x3a, 0x02, 0xfd, 0x00, 0x5a, 0x01, 0x85, 0x00, 0x20, 0x01, 0x4b, 0xff, 0xb6, 0x02, 0x98, 0x00, 0x5a, 0x02, 0x2f, - 0x00, 0x55, 0x03, 0xaf, 0x00, 0x5a, 0x03, 0x2d, 0x00, 0x5a, 0x03, 0x17, 0x00, 0x37, 0x02, 0x6d, 0x00, 0x55, 0x03, 0x17, 0x00, 0x37, 0x02, 0x90, 0x00, 0x55, - 0x02, 0x27, 0x00, 0x2e, 0x02, 0x41, 0x00, 0x13, 0x02, 0xf4, 0x00, 0x55, 0x02, 0x8a, 0x00, 0x00, 0x03, 0xc7, 0x00, 0x00, 0x02, 0x9e, 0x00, 0x03, 0x02, 0x72, - 0x00, 0x00, 0x02, 0x43, 0x00, 0x18, 0x01, 0x4b, 0x00, 0x46, 0x01, 0x9f, 0x00, 0x06, 0x01, 0x4b, 0x00, 0x19, 0x02, 0x3c, 0x00, 0x17, 0x01, 0x9b, 0xff, 0xfe, - 0x01, 0x6d, 0x00, 0x28, 0x02, 0x57, 0x00, 0x28, 0x02, 0x78, 0x00, 0x49, 0x02, 0x04, 0x00, 0x2f, 0x02, 0x78, 0x00, 0x2f, 0x02, 0x55, 0x00, 0x2f, 0x01, 0x83, - 0x00, 0x14, 0x02, 0x78, 0x00, 0x2f, 0x02, 0x8a, 0x00, 0x49, 0x01, 0x2b, 0x00, 0x44, 0x01, 0x2a, 0xff, 0xcb, 0x02, 0x6c, 0x00, 0x4e, 0x01, 0x2a, 0x00, 0x49, - 0x03, 0xcf, 0x00, 0x49, 0x02, 0x8a, 0x00, 0x49, 0x02, 0x71, 0x00, 0x2f, 0x02, 0x78, 0x00, 0x49, 0x02, 0x78, 0x00, 0x2f, 0x01, 0xbf, 0x00, 0x49, 0x01, 0xf6, - 0x00, 0x2e, 0x01, 0xb2, 0x00, 0x17, 0x02, 0x8a, 0x00, 0x46, 0x02, 0x3b, 0x00, 0x00, 0x03, 0x58, 0x00, 0x0a, 0x02, 0x42, 0x00, 0x05, 0x02, 0x3b, 0x00, 0x00, - 0x01, 0xed, 0x00, 0x1e, 0x01, 0x8a, 0x00, 0x0f, 0x02, 0x27, 0x00, 0xde, 0x01, 0x8a, 0x00, 0x28, 0x02, 0x3c, 0x00, 0x2b, 0x01, 0x7b, 0x00, 0x17, 0x01, 0x7c, - 0x00, 0x1a, 0x01, 0x7c, 0x00, 0x20, 0x00, 0x82, 0xff, 0x40, 0x01, 0x7c, 0x00, 0x0c, 0x01, 0x7c, 0x00, 0x28, 0x01, 0x7c, 0x00, 0x1d, 0x01, 0x7c, 0x00, 0x16, - 0x01, 0x7b, 0x00, 0x14, 0x01, 0x7c, 0x00, 0x16, 0x01, 0x7c, 0x00, 0x15, 0x03, 0x04, 0x00, 0x14, 0x02, 0xad, 0x00, 0x14, 0x02, 0xb4, 0x00, 0x14, 0x04, 0x2f, - 0x00, 0x14, 0x04, 0x37, 0x00, 0x14, 0x01, 0x7c, 0x00, 0x14, 0x00, 0x20, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x0c, 0x00, 0x28, 0x00, 0x16, 0x00, 0x1d, 0x00, 0x16, - 0x00, 0x15, 0x00, 0x14, 0x00, 0x20, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x0c, 0x00, 0x28, 0x00, 0x16, 0x00, 0x1d, 0x00, 0x16, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x0b, 0x17, 0xfd, 0x7c, 0xfd, 0x8d, 0x0a, 0xf1, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x04, 0x02, 0x6a, 0x02, 0xbc, 0x00, 0x05, 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x00, 0x00, 0x4b, - 0x02, 0x8a, 0x02, 0x58, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x32, 0x01, 0x48, 0x00, 0x00, 0x02, 0x0b, 0x08, 0x02, 0x04, 0x05, 0x04, 0x02, 0x02, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0xa0, 0x00, 0x20, 0x00, 0x7e, 0x04, 0x2d, - 0xfe, 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x22, 0x02, 0xca, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, - 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, 0x21, 0xb0, - 0x00, 0x59, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, 0x02, 0x2c, - 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, - 0x14, 0x43, 0x42, 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, 0x04, 0x50, 0x78, - 0xb2, 0x02, 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, 0x20, 0xb0, 0x02, 0x43, - 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, - 0x2c, 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x1b, 0x20, 0x64, - 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, - 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, 0x38, - 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x20, 0xb0, - 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, - 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, 0x1b, 0xb0, - 0x02, 0x25, 0xb0, 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, 0xb0, 0x1e, 0x50, - 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, - 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, 0x20, 0x45, 0x20, 0xb0, - 0x04, 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, 0x59, 0xb0, 0x01, 0x60, 0x2d, - 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, - 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, 0xb0, 0x08, 0x43, 0x20, 0x8a, 0x20, - 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, - 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, 0x43, 0x2b, - 0xb2, 0x00, 0x02, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, 0x62, 0x66, - 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, - 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, 0x0e, 0x00, 0x43, - 0x45, 0x42, 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, - 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, - 0x64, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, - 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, - 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, - 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, 0x0c, 0x00, - 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, - 0x2c, 0xb0, 0x01, 0x60, 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, 0xb0, 0x00, - 0x52, 0x58, 0x20, 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, 0x00, 0x63, 0x8a, - 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, - 0x59, 0x24, 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x1b, 0x21, 0x59, 0x24, - 0xb0, 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, 0x61, 0x42, 0xb0, 0x11, 0x2b, - 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, - 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x23, 0xb0, 0x01, 0x61, 0x20, - 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, - 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x20, - 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, 0x00, 0x13, - 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, - 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, - 0x13, 0x00, 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, - 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, - 0x2c, 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, - 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, - 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x5d, - 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, - 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, - 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, - 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, 0x01, 0x00, 0x11, - 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, - 0x2c, 0xb1, 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, 0xb0, 0x25, 0x2c, 0xb1, - 0x04, 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, 0x28, 0x2c, 0xb1, 0x07, 0x20, - 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, - 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x01, 0x60, 0xb0, 0x2e, 0x2a, - 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, - 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, 0x20, 0x47, - 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, - 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, - 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, - 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x34, 0x2c, 0x20, - 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, - 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, - 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, - 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, - 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, 0x20, 0x3c, - 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, - 0x00, 0x43, 0x61, 0xb0, 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb0, - 0x02, 0x25, 0x49, 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, 0x01, 0x15, 0x14, - 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, - 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, - 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, - 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, - 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, - 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, - 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, - 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, 0x02, 0x25, - 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, - 0xb0, 0x01, 0x63, 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, 0x25, 0xb0, 0x02, - 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, 0x60, 0x64, 0x23, 0xb0, - 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, - 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x3c, 0x38, 0x2d, 0xb0, 0x3d, - 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, - 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, 0x2e, - 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, - 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, - 0x59, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, 0x20, 0x3c, - 0x8a, 0x38, 0x23, 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, - 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, - 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, - 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, - 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, - 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, - 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, - 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, 0x20, 0x20, - 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, - 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, - 0x26, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, 0x20, 0x3c, 0x20, - 0x2e, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, - 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, - 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, 0xb0, 0x06, 0x43, 0xb0, 0x02, - 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, - 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, - 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, 0x23, 0x38, - 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, - 0x3a, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x23, - 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, - 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, - 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, 0xb0, 0x4c, 0x2c, 0xb0, - 0x39, 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, - 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, - 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x53, 0x2c, 0xb2, 0x00, 0x00, - 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, - 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x59, - 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x43, - 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, - 0x01, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x61, - 0x2c, 0xb2, 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, 0x48, 0x2b, 0x2d, 0xb0, - 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, - 0xb0, 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x69, 0x2c, 0xb3, 0x01, 0x00, - 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, - 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x44, - 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, - 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, - 0xb0, 0x73, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, 0x2c, 0xb0, - 0x00, 0x16, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x77, - 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, - 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, - 0x2d, 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, - 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, - 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, - 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, - 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x87, - 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, 0x01, 0x3f, - 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, - 0xb0, 0x06, 0x1b, 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, 0x50, 0x78, 0xb1, - 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, 0xb9, 0x08, 0x00, 0x08, - 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, 0x51, 0x41, 0x00, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, - 0x14, 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, 0x02, 0x56, 0x06, 0x46, 0x08, 0x3a, 0x06, 0x32, 0x04, 0x24, 0x07, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x07, 0x42, - 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x4e, 0x06, 0x40, 0x04, 0x36, 0x02, 0x2b, 0x05, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, - 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, 0x11, 0xc0, 0x0e, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, - 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x09, - 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, - 0x28, 0x01, 0x88, 0x51, 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, 0xba, 0x08, - 0x80, 0x00, 0x01, 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, 0x06, 0x7a, 0x06, - 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x48, 0x06, 0x3c, 0x04, 0x34, 0x02, 0x26, 0x05, 0x09, 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, - 0x00, 0x44, 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x98, 0x00, 0x98, 0x00, 0x72, 0x00, 0x72, 0x02, 0xca, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd4, 0xff, 0xf6, 0x02, 0x2c, - 0xff, 0xf6, 0xff, 0x10, 0x00, 0x95, 0x00, 0x95, 0x00, 0x73, 0x00, 0x73, 0x02, 0x48, 0x00, 0x00, 0x02, 0x50, 0xff, 0xf8, 0x00, 0x95, 0x00, 0x95, 0x00, 0x73, - 0x00, 0x73, 0x02, 0x48, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x50, 0x02, 0x50, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x73, 0x00, 0x73, - 0x02, 0xca, 0xff, 0xf6, 0x02, 0xf8, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xfd, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x7b, - 0x00, 0x7b, 0x00, 0x65, 0x00, 0x65, 0x01, 0x68, 0x00, 0xee, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x7b, 0x00, 0x7b, - 0x00, 0x65, 0x00, 0x65, 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x73, 0x00, 0x73, 0x02, 0xca, 0x00, 0x00, 0x02, 0xf8, 0x02, 0x22, 0x00, 0x00, - 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xf9, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x64, 0x00, 0x64, 0x00, 0x45, 0x00, 0x45, 0x01, 0x2c, 0xff, 0x7e, - 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x34, 0xff, 0x74, 0x01, 0x68, 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x64, 0x00, 0x64, 0x00, 0x45, - 0x00, 0x45, 0x02, 0xcb, 0x01, 0xa0, 0x02, 0xe7, 0x02, 0x67, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe7, 0x01, 0x96, 0x02, 0xe7, 0x02, 0x6d, 0x01, 0x19, 0x00, 0x8f, - 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, - 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x08, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x30, - 0x00, 0xd0, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, 0x01, 0x1c, - 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x1a, 0x01, 0x70, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, - 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x4e, - 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x41, - 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, - 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, - 0x00, 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, - 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, - 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, - 0x00, 0x6e, 0x00, 0x73, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, - 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, - 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, - 0x00, 0x20, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, - 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, - 0x00, 0x6f, 0x00, 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x34, - 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, - 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9c, - 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, - 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x1f, 0x00, 0x01, - 0x00, 0x22, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x42, 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x05, 0x00, 0x18, 0x00, 0x18, - 0x00, 0x20, 0x00, 0x28, 0x00, 0x36, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x56, 0x00, 0x01, - 0x00, 0x04, 0x00, 0x01, 0x01, 0x5a, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x65, 0x00, 0x01, 0x02, 0xca, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, - 0x00, 0x01, 0x01, 0x68, 0x00, 0x01, 0x02, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, - 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0x65, 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x07, 0x2c, - 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0xf6, 0x00, 0x01, 0x00, 0x34, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x62, 0x00, 0xe2, 0x00, 0x74, - 0x00, 0x7a, 0x00, 0xb2, 0x00, 0x84, 0x00, 0x8a, 0x00, 0xb2, 0x00, 0xa8, 0x00, 0xb2, 0x00, 0xb8, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xc2, 0x00, 0xe2, 0x00, 0xcc, - 0x00, 0xd2, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xe2, 0x00, 0x01, 0x00, 0x15, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, 0x00, 0x23, 0x00, 0x25, 0x00, 0x26, - 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, - 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, 0x37, 0xff, 0xec, 0x00, 0x38, 0xff, 0xec, 0x00, 0x3a, 0xff, 0xe2, 0x00, 0x01, 0x00, 0x2b, - 0x00, 0x32, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xf6, 0x00, 0x0f, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x07, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0d, - 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, 0xec, 0x00, 0x3e, 0x00, 0x14, 0x00, 0x5e, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, - 0xff, 0xf6, 0x00, 0x39, 0xff, 0xec, 0x00, 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, - 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x5f, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x00, 0x20, - 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, 0x04, 0x32, 0x00, 0x04, 0x00, 0x00, 0x04, 0x86, 0x05, 0x50, 0x00, 0x17, - 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, 0xff, 0xe2, 0xff, 0xce, 0xff, 0xc4, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xce, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xec, 0x00, 0x00, 0xff, 0xec, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, - 0xff, 0xf6, 0xff, 0xec, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xf6, 0xff, 0xf6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xba, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xff, 0xc4, 0xff, 0xba, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x60, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x03, - 0x00, 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x31, - 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, - 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6b, - 0x00, 0x02, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x09, 0x00, 0x13, 0x00, 0x0d, 0x00, 0x0d, - 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x22, 0x00, 0x02, 0x00, 0x24, 0x00, 0x24, 0x00, 0x08, - 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x26, 0x00, 0x26, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x09, 0x00, 0x30, - 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0c, 0x00, 0x36, 0x00, 0x36, - 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x0a, 0x00, 0x39, 0x00, 0x39, 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x07, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0e, - 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x49, 0x00, 0x49, 0x00, 0x01, 0x00, 0x4e, - 0x00, 0x4f, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0d, 0x00, 0x57, 0x00, 0x58, 0x00, 0x05, 0x00, 0x59, 0x00, 0x59, - 0x00, 0x16, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x15, 0x00, 0x01, 0x00, 0x03, 0x00, 0x6d, - 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x12, 0x00, 0x0d, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x16, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, - 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, - 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x16, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x1e, 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x36, 0x00, 0x6c, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, - 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x1a, 0x66, 0x72, 0x61, 0x63, 0x00, 0x20, 0x6c, 0x69, 0x67, 0x61, 0x00, 0x2a, - 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x32, 0x00, 0x10, 0x00, 0x1e, 0x00, 0x32, 0x00, 0x4a, 0x00, 0x88, 0x00, 0xa0, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x5f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x53, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x69, 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, - 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x70, 0x00, 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, - 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, 0x7a, 0x00, 0x83, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x36, 0x00, 0x01, - 0x00, 0x08, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6f, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4d, 0x00, 0x6e, 0x00, 0x03, - 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x6d, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6b, 0x00, 0x02, 0x00, 0x47, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x47}; - -const inline uint8_t FONT_BOLD_ITALICS_DATA[] = { - 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x0a, 0x6b, 0x06, 0xbf, 0x00, 0x00, 0x5a, 0xd0, 0x00, 0x00, - 0x00, 0x7e, 0x47, 0x50, 0x4f, 0x53, 0x33, 0x4f, 0x0e, 0xbf, 0x00, 0x00, 0x5b, 0x50, 0x00, 0x00, 0x07, 0x4e, 0x47, 0x53, 0x55, 0x42, 0xfc, 0xd3, 0xd8, 0xce, - 0x00, 0x00, 0x62, 0xa0, 0x00, 0x00, 0x01, 0xd4, 0x4f, 0x53, 0x2f, 0x32, 0x6a, 0x82, 0x62, 0xb3, 0x00, 0x00, 0x47, 0xbc, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, - 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, 0x20, 0x41, 0x2b, 0x1e, 0x46, 0x00, 0x00, 0x57, 0x64, - 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, 0x0b, 0x83, 0x00, 0x00, 0x48, 0x50, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x5a, 0xc8, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0xb2, 0xab, 0x07, 0x57, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x43, 0x06, - 0x68, 0x65, 0x61, 0x64, 0x28, 0x3b, 0xd8, 0x55, 0x00, 0x00, 0x45, 0x5c, 0x00, 0x00, 0x00, 0x36, 0x68, 0x68, 0x65, 0x61, 0x0d, 0x3d, 0x0b, 0xc5, 0x00, 0x00, - 0x47, 0x98, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0xfa, 0xcf, 0x0a, 0x08, 0x00, 0x00, 0x45, 0x94, 0x00, 0x00, 0x02, 0x02, 0x6c, 0x6f, 0x63, 0x61, - 0xde, 0x29, 0xcd, 0xbc, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x01, 0x16, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x5b, 0x10, 0x44, 0x00, 0x00, 0x44, 0x24, 0x00, 0x00, - 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x7e, 0x45, 0xc4, 0x00, 0x00, 0x58, 0x90, 0x00, 0x00, 0x02, 0x18, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x93, 0x00, 0x32, - 0x00, 0x00, 0x5a, 0xa8, 0x00, 0x00, 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0xff, 0x8d, 0x0b, 0xc2, 0x00, 0x00, 0x56, 0x5c, 0x00, 0x00, 0x01, 0x05, 0x00, 0x02, - 0x00, 0x0b, 0xff, 0xf3, 0x01, 0x3e, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x2c, 0x40, 0x29, 0x04, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, - 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x05, 0x04, 0x00, 0x00, 0x0b, 0x09, 0x04, 0x0f, 0x05, 0x0f, 0x00, 0x03, 0x00, - 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x37, 0x13, 0x33, 0x03, 0x07, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x43, 0x52, 0xa9, 0x7d, - 0x69, 0x2a, 0x23, 0x32, 0x34, 0x23, 0x27, 0x36, 0xe8, 0x01, 0xe2, 0xfe, 0x1e, 0xf5, 0x27, 0x1b, 0x2a, 0x3c, 0x24, 0x20, 0x2e, 0x36, 0x00, 0x02, 0x00, 0x62, - 0x01, 0xc8, 0x01, 0xd2, 0x02, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x40, 0x21, 0x05, 0x03, 0x04, 0x03, 0x01, 0x01, 0x00, 0x5f, 0x02, 0x01, 0x00, 0x00, - 0x6a, 0x01, 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x01, 0x13, 0x33, 0x03, - 0x21, 0x13, 0x33, 0x03, 0x01, 0x27, 0x24, 0x87, 0x4a, 0xfe, 0xda, 0x23, 0x87, 0x4a, 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x02, - 0x00, 0x14, 0x00, 0x00, 0x02, 0x8b, 0x02, 0xca, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, 0x40, 0x44, 0x07, 0x05, 0x02, 0x03, 0x0f, 0x08, 0x02, 0x02, 0x01, 0x03, - 0x02, 0x68, 0x0e, 0x09, 0x02, 0x01, 0x0c, 0x0a, 0x02, 0x00, 0x0b, 0x01, 0x00, 0x67, 0x06, 0x01, 0x04, 0x04, 0x6a, 0x4d, 0x10, 0x0d, 0x02, 0x0b, 0x0b, 0x6b, - 0x0b, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, 0x1c, 0x00, 0x1b, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x0d, 0x1f, 0x2b, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, 0x07, 0x23, - 0x07, 0x33, 0x07, 0x23, 0x07, 0x23, 0x37, 0x23, 0x07, 0x13, 0x33, 0x37, 0x23, 0x51, 0x37, 0x74, 0x09, 0x87, 0x22, 0x7b, 0x09, 0x8d, 0x3a, 0x6a, 0x39, 0x61, - 0x39, 0x69, 0x39, 0x75, 0x09, 0x88, 0x22, 0x7e, 0x09, 0x91, 0x39, 0x6b, 0x39, 0x5f, 0x38, 0x54, 0x60, 0x22, 0x60, 0xc7, 0x65, 0x71, 0x66, 0xc7, 0xc7, 0xc7, - 0xc7, 0x66, 0x71, 0x65, 0xc7, 0xc7, 0xc7, 0x01, 0x2c, 0x71, 0x00, 0x03, 0x00, 0x19, 0xff, 0xc6, 0x02, 0x23, 0x02, 0xf8, 0x00, 0x24, 0x00, 0x2a, 0x00, 0x31, - 0x00, 0x70, 0x40, 0x17, 0x13, 0x01, 0x02, 0x03, 0x16, 0x01, 0x04, 0x02, 0x31, 0x2a, 0x1b, 0x17, 0x08, 0x04, 0x06, 0x01, 0x04, 0x03, 0x01, 0x00, 0x01, 0x04, - 0x4c, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x20, 0x00, 0x06, 0x00, 0x00, 0x06, 0x71, 0x00, 0x02, 0x04, 0x00, 0x02, 0x59, 0x00, 0x01, 0x05, 0x01, 0x00, 0x06, - 0x01, 0x00, 0x69, 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6c, 0x04, 0x4e, 0x1b, 0x40, 0x1f, 0x00, 0x06, 0x00, 0x06, 0x86, 0x00, 0x02, 0x04, 0x00, - 0x02, 0x59, 0x00, 0x01, 0x05, 0x01, 0x00, 0x06, 0x01, 0x00, 0x69, 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6c, 0x04, 0x4e, 0x59, 0x40, 0x0a, 0x11, - 0x17, 0x17, 0x11, 0x18, 0x15, 0x10, 0x07, 0x0d, 0x1d, 0x2b, 0x37, 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x37, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x36, 0x37, - 0x37, 0x33, 0x07, 0x16, 0x16, 0x17, 0x07, 0x26, 0x26, 0x27, 0x07, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x07, 0x23, 0x13, 0x06, 0x06, 0x15, 0x14, 0x17, 0x13, - 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0xc6, 0x33, 0x56, 0x24, 0x26, 0x65, 0x3a, 0x23, 0x2b, 0x47, 0x2a, 0x3c, 0x69, 0x44, 0x11, 0x44, 0x10, 0x29, 0x44, 0x23, - 0x34, 0x1c, 0x3d, 0x1d, 0x1f, 0x2d, 0x48, 0x2a, 0x71, 0x80, 0x13, 0x44, 0x84, 0x19, 0x27, 0x27, 0x06, 0x1f, 0x26, 0x18, 0x11, 0x28, 0x03, 0x14, 0x13, 0x82, - 0x15, 0x22, 0x02, 0x9d, 0x11, 0x2e, 0x43, 0x30, 0x3c, 0x54, 0x30, 0x04, 0x4a, 0x4a, 0x05, 0x14, 0x13, 0x71, 0x0e, 0x14, 0x02, 0x92, 0x11, 0x2c, 0x41, 0x33, - 0x52, 0x70, 0x09, 0x61, 0x02, 0x6f, 0x03, 0x1e, 0x21, 0x26, 0x10, 0xfe, 0xe0, 0x05, 0x23, 0x1e, 0x17, 0x1c, 0x07, 0x00, 0x00, 0x05, 0x00, 0x38, 0xff, 0xf7, - 0x03, 0x34, 0x02, 0xd4, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x21, 0x00, 0x31, 0x00, 0x3f, 0x00, 0xd2, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x2c, 0x00, 0x07, 0x00, - 0x09, 0x00, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x70, 0x4d, - 0x0e, 0x01, 0x08, 0x08, 0x03, 0x61, 0x0d, 0x06, 0x0b, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x4b, 0xb0, 0x1a, 0x50, 0x58, 0x40, 0x30, 0x00, 0x07, 0x00, - 0x09, 0x00, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, - 0x01, 0x01, 0x70, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x03, 0x61, 0x0d, 0x06, 0x0b, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x34, 0x00, 0x07, 0x00, 0x09, - 0x00, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, - 0x01, 0x70, 0x4d, 0x0b, 0x01, 0x03, 0x03, 0x6b, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x06, 0x61, 0x0d, 0x01, 0x06, 0x06, 0x71, 0x06, 0x4e, 0x59, 0x59, 0x40, 0x2b, - 0x33, 0x32, 0x23, 0x22, 0x15, 0x14, 0x10, 0x10, 0x01, 0x00, 0x3a, 0x38, 0x32, 0x3f, 0x33, 0x3f, 0x2b, 0x29, 0x22, 0x31, 0x23, 0x31, 0x1c, 0x1a, 0x14, 0x21, - 0x15, 0x21, 0x10, 0x13, 0x10, 0x13, 0x12, 0x11, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, - 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x03, 0x01, 0x33, 0x01, 0x03, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x01, 0x22, 0x26, 0x35, - 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xc2, 0x43, 0x47, 0x15, - 0x2f, 0x4f, 0x3a, 0x43, 0x49, 0x15, 0x30, 0x4f, 0x8c, 0x02, 0x13, 0x73, 0xfd, 0xef, 0x1b, 0x12, 0x1d, 0x14, 0x0b, 0x1c, 0x10, 0x1d, 0x14, 0x0c, 0x01, 0xb8, - 0x46, 0x47, 0x16, 0x31, 0x4e, 0x38, 0x43, 0x49, 0x15, 0x30, 0x4e, 0x33, 0x12, 0x1d, 0x14, 0x0b, 0x1c, 0x10, 0x1d, 0x14, 0x0c, 0x01, 0x14, 0x52, 0x4a, 0x2c, - 0x65, 0x5a, 0x39, 0x4e, 0x4d, 0x2b, 0x65, 0x5b, 0x3a, 0xfe, 0xec, 0x02, 0xca, 0xfd, 0x36, 0x01, 0x79, 0x27, 0x3c, 0x45, 0x1e, 0x2f, 0x24, 0x3c, 0x45, 0x21, - 0x2f, 0xfe, 0x7e, 0x4d, 0x46, 0x35, 0x6a, 0x58, 0x36, 0x4d, 0x4a, 0x2d, 0x67, 0x5b, 0x3a, 0x65, 0x27, 0x3c, 0x45, 0x1e, 0x2f, 0x24, 0x3c, 0x45, 0x21, 0x2f, - 0x00, 0x03, 0x00, 0x21, 0xff, 0xf6, 0x02, 0xba, 0x02, 0xd5, 0x00, 0x20, 0x00, 0x2c, 0x00, 0x36, 0x00, 0x99, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x06, - 0x01, 0x02, 0x04, 0x31, 0x30, 0x1b, 0x14, 0x13, 0x05, 0x05, 0x02, 0x1e, 0x01, 0x00, 0x05, 0x03, 0x4c, 0x1b, 0x40, 0x12, 0x06, 0x01, 0x02, 0x04, 0x31, 0x30, - 0x1b, 0x14, 0x13, 0x05, 0x05, 0x02, 0x1e, 0x01, 0x03, 0x05, 0x03, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x24, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, - 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x4d, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, - 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6b, - 0x4d, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x2e, 0x2d, 0x01, 0x00, 0x2d, 0x36, 0x2e, 0x36, 0x28, - 0x26, 0x1d, 0x1c, 0x18, 0x17, 0x0d, 0x0b, 0x00, 0x20, 0x01, 0x20, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x35, 0x34, 0x36, - 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, 0x07, 0x17, 0x23, 0x27, 0x06, 0x06, 0x13, 0x36, 0x36, 0x35, - 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x03, 0x32, 0x36, 0x37, 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, 0xf4, 0x65, 0x6e, 0x54, 0x58, 0x25, 0x38, 0x60, - 0x3c, 0x3f, 0x4e, 0x24, 0x5f, 0x53, 0x5f, 0x1c, 0x22, 0x10, 0x92, 0x1e, 0x49, 0x30, 0x64, 0xab, 0x23, 0x27, 0x5f, 0x10, 0x28, 0x39, 0x1d, 0x14, 0x22, 0x22, - 0x0c, 0x31, 0x20, 0x36, 0x16, 0x6e, 0x23, 0x2a, 0x2a, 0x0a, 0x60, 0x59, 0x4b, 0x65, 0x2b, 0x3e, 0x40, 0x44, 0x5b, 0x2e, 0x2a, 0x44, 0x28, 0x4a, 0x64, 0x22, - 0x80, 0x23, 0x45, 0x28, 0x47, 0x7a, 0x32, 0x8c, 0x30, 0x1a, 0x20, 0x01, 0xcb, 0x14, 0x33, 0x26, 0x1c, 0x19, 0x30, 0x21, 0x16, 0x2d, 0xfe, 0xa4, 0x11, 0x0c, - 0xa0, 0x14, 0x33, 0x2c, 0x1d, 0x2d, 0x00, 0x01, 0x00, 0x62, 0x01, 0xc8, 0x01, 0x0c, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, - 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x13, 0x33, 0x03, 0x62, 0x23, 0x87, - 0x4a, 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x24, 0xff, 0x62, 0x01, 0x9a, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, - 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x16, 0x03, 0x0d, 0x17, 0x2b, 0x17, 0x26, 0x26, 0x35, 0x34, - 0x12, 0x37, 0x33, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x17, 0x6d, 0x25, 0x24, 0x7e, 0x78, 0x80, 0x47, 0x6e, 0x3f, 0x1e, 0x1b, 0x9e, 0x41, 0x96, 0x50, 0xad, 0x01, - 0x18, 0x7c, 0x4d, 0xb3, 0xcf, 0x77, 0x4c, 0x94, 0x42, 0x00, 0x00, 0x01, 0xff, 0xba, 0xff, 0x62, 0x01, 0x30, 0x02, 0xd6, 0x00, 0x0e, 0x00, 0x2e, 0x4b, 0xb0, - 0x29, 0x50, 0x58, 0x40, 0x0c, 0x02, 0x01, 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x1b, 0x40, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, - 0x01, 0x01, 0x01, 0x76, 0x59, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x17, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x27, 0x33, - 0x16, 0x16, 0x15, 0x14, 0x02, 0x07, 0x46, 0x47, 0x6e, 0x3f, 0x1e, 0x1b, 0x72, 0x25, 0x24, 0x7d, 0x78, 0x9e, 0x4e, 0xb2, 0xcf, 0x77, 0x4c, 0xa0, 0x42, 0x41, - 0xa2, 0x50, 0xae, 0xfe, 0xe8, 0x7b, 0x00, 0x01, 0x00, 0x55, 0x01, 0x19, 0x02, 0x35, 0x02, 0xfd, 0x00, 0x0e, 0x00, 0x1d, 0x40, 0x1a, 0x09, 0x08, 0x07, 0x06, - 0x04, 0x00, 0x4a, 0x0e, 0x0d, 0x0c, 0x05, 0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0x49, 0x00, 0x00, 0x00, 0x76, 0x1a, 0x01, 0x0d, 0x17, 0x2b, 0x01, 0x27, 0x07, - 0x27, 0x37, 0x27, 0x37, 0x17, 0x37, 0x17, 0x07, 0x37, 0x07, 0x27, 0x17, 0x01, 0x5f, 0x2d, 0x61, 0x62, 0x86, 0xa0, 0x29, 0xa5, 0x11, 0x7e, 0x3a, 0xbd, 0x08, - 0xa6, 0x4e, 0x01, 0x19, 0xa6, 0x89, 0x4f, 0x7a, 0x2e, 0x71, 0x54, 0xb3, 0x18, 0xac, 0x0d, 0x79, 0x15, 0xa5, 0x00, 0x01, 0x00, 0x35, 0x00, 0x6f, 0x02, 0x1a, - 0x02, 0x54, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x00, 0x05, 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, - 0x05, 0x02, 0x5f, 0x00, 0x02, 0x05, 0x02, 0x4f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, - 0x35, 0x33, 0x35, 0x33, 0x01, 0x5d, 0xbd, 0xbd, 0x6b, 0xbd, 0xbd, 0x6b, 0x01, 0x96, 0x6b, 0xbc, 0xbc, 0x6b, 0xbe, 0x00, 0x00, 0x01, 0xff, 0xd0, 0xff, 0x7f, - 0x00, 0xc0, 0x00, 0x74, 0x00, 0x08, 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, - 0x4f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x13, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x36, 0x36, 0x37, 0x33, 0x17, 0x06, 0x06, 0x07, 0x30, 0x1a, 0x32, 0x13, 0x8d, - 0x04, 0x18, 0x44, 0x24, 0x81, 0x3b, 0x86, 0x34, 0x0b, 0x35, 0x7e, 0x37, 0x00, 0x01, 0x00, 0x11, 0x00, 0xce, 0x01, 0x2c, 0x01, 0x4a, 0x00, 0x03, 0x00, 0x1e, - 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, - 0x03, 0x0d, 0x17, 0x2b, 0x37, 0x37, 0x21, 0x07, 0x11, 0x1a, 0x01, 0x01, 0x1a, 0xce, 0x7c, 0x7c, 0x00, 0x01, 0x00, 0x08, 0xff, 0xf3, 0x00, 0xb7, 0x00, 0x9b, - 0x00, 0x0b, 0x00, 0x1a, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x02, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, - 0x03, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x50, 0x21, 0x27, 0x3a, 0x2c, 0x21, 0x28, 0x37, 0x0d, 0x21, - 0x21, 0x31, 0x35, 0x21, 0x22, 0x34, 0x31, 0x00, 0x00, 0x01, 0xff, 0xd3, 0xff, 0xfa, 0x01, 0xf1, 0x02, 0xd0, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, - 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x01, 0x33, 0x01, 0x2d, - 0x01, 0x95, 0x89, 0xfe, 0x6c, 0x06, 0x02, 0xd6, 0xfd, 0x2a, 0x00, 0x02, 0x00, 0x20, 0xff, 0xf6, 0x02, 0x1e, 0x02, 0xd5, 0x00, 0x0f, 0x00, 0x21, 0x00, 0x2d, - 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x11, - 0x10, 0x01, 0x00, 0x1a, 0x18, 0x10, 0x21, 0x11, 0x21, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, - 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x14, 0x16, 0xe5, 0x65, 0x60, 0x28, 0x50, - 0x76, 0x4d, 0x5c, 0x67, 0x24, 0x4b, 0x77, 0x47, 0x1c, 0x30, 0x26, 0x19, 0x0e, 0x1e, 0x1e, 0x1e, 0x31, 0x25, 0x19, 0x0d, 0x1b, 0x0a, 0x7c, 0x72, 0x62, 0xb3, - 0x8b, 0x51, 0x6e, 0x79, 0x5f, 0xb4, 0x90, 0x55, 0x7a, 0x31, 0x53, 0x65, 0x6b, 0x2f, 0x36, 0x32, 0x36, 0x57, 0x65, 0x63, 0x25, 0x37, 0x3a, 0x00, 0x00, 0x01, - 0x00, 0x59, 0x00, 0x00, 0x01, 0xe7, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x1b, 0x40, 0x18, 0x08, 0x07, 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6a, - 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x11, 0x19, 0x02, 0x0d, 0x18, 0x2b, 0x01, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x25, 0x33, 0x03, 0x23, - 0x01, 0x13, 0x05, 0x16, 0x0a, 0x09, 0x26, 0x10, 0x5f, 0x41, 0x01, 0x14, 0x7a, 0x97, 0x95, 0x01, 0x95, 0x1a, 0x52, 0x20, 0x07, 0x1d, 0x0a, 0x3c, 0x69, 0xaa, - 0xfd, 0x36, 0x00, 0x01, 0xff, 0xe8, 0x00, 0x00, 0x02, 0x18, 0x02, 0xd4, 0x00, 0x1c, 0x00, 0x2f, 0x40, 0x2c, 0x0d, 0x01, 0x00, 0x01, 0x0c, 0x01, 0x02, 0x00, - 0x02, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, - 0x00, 0x1c, 0x00, 0x1c, 0x28, 0x25, 0x28, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, - 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x15, 0x21, 0x07, 0x18, 0x15, 0xe9, 0x3a, 0x44, 0x1d, 0x28, 0x22, 0x24, 0x44, 0x2e, 0x47, 0x32, - 0x77, 0x4c, 0x46, 0x59, 0x2a, 0x37, 0x5e, 0x3d, 0x83, 0x01, 0x15, 0x1a, 0x68, 0xcf, 0x34, 0x4a, 0x3b, 0x1b, 0x25, 0x26, 0x24, 0x26, 0x63, 0x2b, 0x3a, 0x32, - 0x4f, 0x2d, 0x3f, 0x68, 0x5d, 0x32, 0x6c, 0x05, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x07, 0xff, 0xf6, 0x02, 0x1b, 0x02, 0xd4, 0x00, 0x2b, 0x00, 0x4a, 0x40, 0x47, - 0x1b, 0x01, 0x04, 0x05, 0x1a, 0x01, 0x03, 0x04, 0x24, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x03, 0x00, 0x02, - 0x01, 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, - 0x01, 0x00, 0x1f, 0x1d, 0x18, 0x16, 0x11, 0x0f, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x2b, 0x01, 0x2b, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, - 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, - 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc4, 0x37, 0x62, 0x24, 0x29, 0x60, 0x2d, 0x47, 0x59, 0x35, 0x49, 0x43, 0x16, 0x24, - 0x2b, 0x50, 0x34, 0x26, 0x2a, 0x2c, 0x46, 0x1a, 0x3e, 0x30, 0x6b, 0x4f, 0x63, 0x63, 0x5a, 0x54, 0x36, 0x4c, 0x3e, 0x84, 0x0a, 0x14, 0x13, 0x82, 0x18, 0x19, - 0x3a, 0x3b, 0x24, 0x30, 0x6c, 0x16, 0x32, 0x2a, 0x1d, 0x28, 0x20, 0x11, 0x64, 0x20, 0x27, 0x5d, 0x46, 0x4a, 0x67, 0x0f, 0x04, 0x0a, 0x48, 0x44, 0x38, 0x68, - 0x41, 0x00, 0x00, 0x02, 0xff, 0xf4, 0x00, 0x00, 0x02, 0x1b, 0x02, 0xca, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x2e, 0x40, 0x2b, 0x11, 0x01, 0x02, 0x01, 0x01, 0x4c, - 0x05, 0x01, 0x02, 0x03, 0x01, 0x00, 0x04, 0x02, 0x00, 0x68, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x6b, 0x04, 0x4e, 0x00, 0x00, 0x0c, 0x0b, - 0x00, 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0d, 0x1a, 0x2b, 0x33, 0x37, 0x21, 0x37, 0x01, 0x33, 0x03, 0x33, 0x07, 0x23, 0x07, 0x03, 0x33, 0x37, - 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x07, 0xf5, 0x1f, 0xfe, 0xe0, 0x17, 0x01, 0x78, 0x98, 0x5f, 0x53, 0x19, 0x53, 0x1f, 0xef, 0x98, 0x1c, 0x06, 0x0f, 0x0f, - 0x04, 0x05, 0x0b, 0x22, 0x11, 0x94, 0x72, 0x01, 0xc4, 0xfe, 0x3f, 0x75, 0x94, 0x01, 0x09, 0x79, 0x1a, 0x3c, 0x33, 0x0c, 0x13, 0x30, 0x15, 0x00, 0x00, 0x01, - 0x00, 0x0d, 0xff, 0xf6, 0x02, 0x27, 0x02, 0xca, 0x00, 0x21, 0x00, 0x44, 0x40, 0x41, 0x17, 0x12, 0x02, 0x02, 0x05, 0x11, 0x04, 0x02, 0x01, 0x02, 0x03, 0x01, - 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x00, - 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1b, 0x19, 0x16, 0x15, 0x14, 0x13, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x21, 0x01, 0x21, 0x07, 0x0d, - 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x07, 0x23, 0x07, - 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc7, 0x3a, 0x61, 0x1f, 0x24, 0x58, 0x30, 0x3c, 0x46, 0x1e, 0x2f, 0x3e, 0x1e, 0x38, 0x12, 0x33, - 0x65, 0x01, 0x71, 0x1b, 0xef, 0x2b, 0x0c, 0x1f, 0x13, 0x36, 0x58, 0x33, 0x3f, 0x83, 0x0a, 0x17, 0x11, 0x83, 0x14, 0x1c, 0x27, 0x3b, 0x1f, 0x26, 0x36, 0x0b, - 0x05, 0x26, 0x01, 0x66, 0x80, 0x8f, 0x02, 0x05, 0x29, 0x54, 0x41, 0x4a, 0x7b, 0x49, 0x00, 0x02, 0x00, 0x2b, 0xff, 0xf6, 0x02, 0x33, 0x02, 0xd5, 0x00, 0x1f, - 0x00, 0x30, 0x00, 0x47, 0x40, 0x44, 0x0d, 0x01, 0x02, 0x01, 0x0e, 0x01, 0x03, 0x02, 0x14, 0x01, 0x05, 0x03, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x05, 0x04, 0x03, - 0x05, 0x69, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x21, - 0x20, 0x01, 0x00, 0x28, 0x26, 0x20, 0x30, 0x21, 0x30, 0x19, 0x17, 0x12, 0x10, 0x0b, 0x09, 0x00, 0x1f, 0x01, 0x1f, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, - 0x35, 0x34, 0x36, 0x36, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, - 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0xfc, 0x67, 0x6a, 0x26, 0x47, 0x31, 0x31, - 0x7a, 0x52, 0x1f, 0x3b, 0x13, 0x19, 0x12, 0x33, 0x18, 0x64, 0x74, 0x1e, 0x04, 0x19, 0x4a, 0x35, 0x4a, 0x56, 0x19, 0x3c, 0x65, 0x46, 0x25, 0x30, 0x18, 0x21, - 0x21, 0x1c, 0x30, 0x1f, 0x04, 0x02, 0x02, 0x26, 0x0a, 0x7c, 0x73, 0x4e, 0x99, 0x84, 0x2d, 0x2c, 0x2c, 0x08, 0x05, 0x78, 0x05, 0x07, 0x6f, 0x6e, 0x23, 0x2e, - 0x5c, 0x59, 0x2a, 0x65, 0x5b, 0x3b, 0x79, 0x30, 0x4a, 0x27, 0x23, 0x29, 0x1e, 0x2c, 0x17, 0x0b, 0x17, 0x0b, 0x29, 0x36, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, - 0x02, 0x52, 0x02, 0xca, 0x00, 0x06, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, - 0x4e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x37, 0x21, 0x07, 0x01, 0x26, 0x01, 0x68, 0xfe, 0xcd, 0x1b, - 0x01, 0xdc, 0x14, 0xfe, 0x91, 0x02, 0x4b, 0x7f, 0x5f, 0xfd, 0x95, 0x00, 0x00, 0x03, 0x00, 0x1b, 0xff, 0xf6, 0x02, 0x26, 0x02, 0xd5, 0x00, 0x1c, 0x00, 0x28, - 0x00, 0x34, 0x00, 0x35, 0x40, 0x32, 0x2f, 0x15, 0x06, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, - 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x2a, 0x29, 0x01, 0x00, 0x29, 0x34, 0x2a, 0x34, 0x24, 0x22, 0x0e, 0x0c, 0x00, 0x1c, 0x01, - 0x1c, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, - 0x07, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x03, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, - 0x06, 0x06, 0x15, 0x14, 0x16, 0xfb, 0x70, 0x70, 0x58, 0x52, 0x1e, 0x33, 0x36, 0x69, 0x4d, 0x43, 0x57, 0x2c, 0x2b, 0x45, 0x28, 0x1a, 0x31, 0x1f, 0x36, 0x70, - 0x14, 0x2a, 0x30, 0x26, 0x1f, 0x27, 0x2a, 0x21, 0x1d, 0x33, 0x30, 0x2b, 0x22, 0x38, 0x38, 0x31, 0x0a, 0x68, 0x4d, 0x4d, 0x65, 0x1e, 0x17, 0x49, 0x32, 0x37, - 0x5b, 0x36, 0x2d, 0x4a, 0x2c, 0x34, 0x49, 0x31, 0x0e, 0x11, 0x30, 0x43, 0x2e, 0x34, 0x5f, 0x3b, 0x01, 0xbe, 0x11, 0x34, 0x27, 0x21, 0x26, 0x2f, 0x22, 0x23, - 0x30, 0xfe, 0xa2, 0x3a, 0x24, 0x29, 0x38, 0x16, 0x16, 0x3d, 0x2c, 0x27, 0x2f, 0x00, 0x00, 0x02, 0x00, 0x2a, 0xff, 0xf6, 0x02, 0x15, 0x02, 0xd5, 0x00, 0x21, - 0x00, 0x32, 0x00, 0x47, 0x40, 0x44, 0x0c, 0x01, 0x02, 0x04, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, - 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x23, - 0x22, 0x01, 0x00, 0x2d, 0x2b, 0x22, 0x32, 0x23, 0x32, 0x19, 0x17, 0x11, 0x0f, 0x08, 0x06, 0x00, 0x21, 0x01, 0x21, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, - 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, - 0x07, 0x06, 0x06, 0x13, 0x32, 0x36, 0x36, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x9f, 0x21, 0x40, 0x14, 0x13, 0x3b, - 0x21, 0x36, 0x4c, 0x32, 0x20, 0x0a, 0x04, 0x18, 0x46, 0x32, 0x55, 0x52, 0x19, 0x3c, 0x6a, 0x50, 0x5c, 0x6e, 0x1e, 0x3c, 0x2e, 0x2a, 0x74, 0x26, 0x1d, 0x2c, - 0x1c, 0x04, 0x02, 0x02, 0x22, 0x25, 0x24, 0x30, 0x18, 0x25, 0x0a, 0x0a, 0x06, 0x7d, 0x07, 0x0d, 0x25, 0x3e, 0x4e, 0x28, 0x22, 0x2b, 0x6c, 0x52, 0x28, 0x61, - 0x59, 0x3a, 0x6f, 0x7d, 0x46, 0x98, 0x88, 0x30, 0x2b, 0x32, 0x01, 0x79, 0x1f, 0x2e, 0x16, 0x0b, 0x17, 0x0b, 0x29, 0x34, 0x2f, 0x45, 0x23, 0x2a, 0x2c, 0x00, - 0x00, 0x02, 0x00, 0x08, 0xff, 0xf3, 0x01, 0x10, 0x02, 0x2c, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x2d, 0x40, 0x2a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, - 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x0d, 0x0c, 0x01, 0x00, 0x13, 0x11, 0x0c, 0x17, 0x0d, 0x17, 0x07, - 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x03, 0x22, 0x26, 0x35, 0x34, - 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0xa9, 0x21, 0x27, 0x39, 0x2d, 0x20, 0x29, 0x37, 0x89, 0x21, 0x27, 0x3a, 0x2c, 0x21, 0x28, 0x37, 0x01, 0x85, 0x21, - 0x20, 0x32, 0x34, 0x20, 0x22, 0x34, 0x31, 0xfe, 0x6e, 0x21, 0x21, 0x31, 0x35, 0x21, 0x22, 0x34, 0x31, 0x00, 0x00, 0x02, 0xff, 0xca, 0xff, 0x7f, 0x01, 0x10, - 0x02, 0x2c, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x2a, 0x40, 0x27, 0x00, 0x02, 0x05, 0x01, 0x03, 0x02, 0x03, 0x63, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, - 0x01, 0x73, 0x00, 0x4e, 0x0c, 0x0c, 0x01, 0x00, 0x0c, 0x14, 0x0c, 0x14, 0x10, 0x0f, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, - 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x36, 0x36, 0x37, 0x33, 0x17, 0x06, 0x06, 0x07, 0xa9, 0x21, 0x27, 0x39, 0x2d, 0x20, 0x29, - 0x37, 0xfe, 0xf1, 0x1a, 0x32, 0x13, 0x8d, 0x04, 0x18, 0x44, 0x24, 0x01, 0x85, 0x21, 0x20, 0x32, 0x34, 0x20, 0x22, 0x34, 0x31, 0xfd, 0xfa, 0x3b, 0x86, 0x34, - 0x0b, 0x35, 0x7e, 0x37, 0x00, 0x01, 0x00, 0x35, 0x00, 0x63, 0x02, 0x1a, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, 0x32, 0x2b, 0x25, 0x25, - 0x35, 0x25, 0x15, 0x05, 0x05, 0x02, 0x1a, 0xfe, 0x1b, 0x01, 0xe5, 0xfe, 0xb2, 0x01, 0x4e, 0x63, 0xd6, 0x46, 0xf2, 0x75, 0x9b, 0x89, 0x00, 0x02, 0x00, 0x35, - 0x00, 0xcc, 0x02, 0x1a, 0x01, 0xf4, 0x00, 0x03, 0x00, 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, - 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, - 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, 0x35, 0x21, 0x15, 0x35, 0x01, 0xe5, 0xfe, 0x1b, 0x01, 0xe5, 0x01, 0x8a, 0x6a, 0x6a, - 0xbe, 0x6b, 0x6b, 0x00, 0x00, 0x01, 0x00, 0x35, 0x00, 0x63, 0x02, 0x1a, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, 0x25, - 0x25, 0x35, 0x05, 0x15, 0x05, 0x35, 0x01, 0x4e, 0xfe, 0xb2, 0x01, 0xe5, 0xfe, 0x1b, 0xd8, 0x89, 0x9b, 0x75, 0xf2, 0x46, 0xd6, 0x00, 0x00, 0x02, 0x00, 0x4d, - 0xff, 0xf3, 0x01, 0xeb, 0x02, 0xd4, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x3f, 0x40, 0x3c, 0x0d, 0x01, 0x00, 0x01, 0x0c, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x05, 0x01, - 0x02, 0x00, 0x04, 0x00, 0x02, 0x04, 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, - 0x71, 0x03, 0x4e, 0x1d, 0x1c, 0x00, 0x00, 0x23, 0x21, 0x1c, 0x27, 0x1d, 0x27, 0x00, 0x1b, 0x00, 0x1b, 0x25, 0x28, 0x07, 0x0d, 0x18, 0x2b, 0x37, 0x36, 0x36, - 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x0e, 0x02, 0x07, 0x07, 0x22, - 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x7f, 0x0d, 0x36, 0x3c, 0x31, 0x2c, 0x1e, 0x23, 0x23, 0x47, 0x2c, 0x2d, 0x2d, 0x6d, 0x3f, 0x58, - 0x63, 0x26, 0x43, 0x2a, 0x1d, 0x23, 0x14, 0x07, 0x64, 0x2a, 0x22, 0x2d, 0x37, 0x21, 0x28, 0x35, 0xed, 0x45, 0x5b, 0x28, 0x21, 0x2d, 0x1f, 0x1b, 0x1f, 0x1c, - 0x15, 0x6c, 0x19, 0x24, 0x56, 0x4c, 0x32, 0x47, 0x38, 0x1c, 0x13, 0x21, 0x27, 0x1d, 0xfa, 0x2b, 0x1a, 0x24, 0x3d, 0x25, 0x22, 0x29, 0x36, 0x00, 0x00, 0x02, - 0x00, 0x2d, 0xff, 0xa5, 0x03, 0x4e, 0x02, 0xca, 0x00, 0x40, 0x00, 0x4f, 0x00, 0x93, 0x40, 0x16, 0x23, 0x01, 0x09, 0x04, 0x45, 0x01, 0x05, 0x09, 0x14, 0x01, - 0x02, 0x05, 0x3d, 0x01, 0x07, 0x02, 0x3e, 0x01, 0x00, 0x07, 0x05, 0x4c, 0x4b, 0xb0, 0x15, 0x50, 0x58, 0x40, 0x28, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, - 0x07, 0x05, 0x02, 0x69, 0x00, 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x09, 0x09, 0x04, - 0x61, 0x00, 0x04, 0x04, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x04, 0x00, 0x09, 0x05, 0x04, 0x09, 0x69, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, 0x07, - 0x05, 0x02, 0x69, 0x00, 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x06, 0x4e, 0x59, 0x40, 0x1f, 0x42, - 0x41, 0x01, 0x00, 0x49, 0x47, 0x41, 0x4f, 0x42, 0x4f, 0x3b, 0x39, 0x33, 0x31, 0x2b, 0x29, 0x21, 0x1f, 0x19, 0x17, 0x12, 0x10, 0x0a, 0x08, 0x00, 0x40, 0x01, - 0x40, 0x0c, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, - 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, - 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x03, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, - 0x14, 0x16, 0x01, 0x87, 0x72, 0x9a, 0x4e, 0x4c, 0x83, 0xa9, 0x5d, 0x9b, 0xb1, 0x20, 0x3f, 0x5a, 0x39, 0x27, 0x3a, 0x09, 0x05, 0x15, 0x39, 0x2f, 0x37, 0x4c, - 0x23, 0x42, 0x5f, 0x3b, 0x36, 0x4c, 0x1e, 0x34, 0x05, 0x08, 0x10, 0x0c, 0x1b, 0x2d, 0x21, 0x12, 0x73, 0x79, 0x63, 0x9d, 0x5c, 0x32, 0x6e, 0x59, 0x3e, 0x65, - 0x34, 0x2f, 0x71, 0x40, 0x27, 0x31, 0x10, 0x1c, 0x09, 0x12, 0x0d, 0x23, 0x34, 0x22, 0x11, 0x1c, 0x5b, 0x59, 0x98, 0x5e, 0x72, 0xaf, 0x78, 0x3d, 0xa0, 0x90, - 0x3b, 0x6f, 0x58, 0x34, 0x23, 0x25, 0x21, 0x27, 0x47, 0x50, 0x33, 0x61, 0x4e, 0x2e, 0x10, 0x0b, 0xcd, 0x16, 0x1f, 0x10, 0x12, 0x0f, 0x27, 0x40, 0x4d, 0x27, - 0x63, 0x73, 0x5a, 0xa5, 0x70, 0x44, 0x74, 0x45, 0x16, 0x14, 0x5b, 0x13, 0x19, 0x01, 0x18, 0x49, 0x3b, 0x6c, 0x02, 0x03, 0x23, 0x37, 0x3d, 0x1a, 0x26, 0x1e, - 0x00, 0x02, 0xff, 0xc4, 0x00, 0x00, 0x02, 0x38, 0x02, 0xca, 0x00, 0x07, 0x00, 0x11, 0x00, 0x2c, 0x40, 0x29, 0x0d, 0x01, 0x04, 0x00, 0x01, 0x4c, 0x00, 0x04, - 0x00, 0x02, 0x01, 0x04, 0x02, 0x68, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x09, 0x08, 0x00, 0x07, 0x00, - 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x33, 0x13, 0x23, 0x27, 0x23, 0x07, 0x13, 0x33, 0x27, 0x26, 0x26, 0x37, 0x23, 0x06, 0x06, 0x07, - 0x3c, 0x01, 0x76, 0xb6, 0x48, 0x91, 0x0c, 0xe7, 0x54, 0x91, 0xa3, 0x0d, 0x02, 0x04, 0x01, 0x02, 0x0a, 0x18, 0x0f, 0x02, 0xca, 0xfd, 0x36, 0xaa, 0xaa, 0x01, - 0x29, 0xb8, 0x1d, 0x3c, 0x1f, 0x1b, 0x35, 0x1f, 0x00, 0x03, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x63, 0x02, 0xca, 0x00, 0x10, 0x00, 0x18, 0x00, 0x21, 0x00, 0x43, - 0x40, 0x40, 0x08, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x00, 0x05, 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, - 0x4d, 0x08, 0x01, 0x04, 0x04, 0x01, 0x5f, 0x06, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1a, 0x19, 0x12, 0x11, 0x00, 0x00, 0x20, 0x1e, 0x19, 0x21, 0x1a, 0x21, - 0x17, 0x15, 0x11, 0x18, 0x12, 0x18, 0x00, 0x10, 0x00, 0x0f, 0x21, 0x09, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, - 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x13, 0x32, 0x36, 0x35, 0x34, 0x23, 0x23, 0x07, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x07, 0x1a, 0x97, 0xd0, - 0x66, 0x7c, 0x52, 0x4a, 0x31, 0x3a, 0x4a, 0x7f, 0x50, 0x3a, 0x35, 0x41, 0x53, 0x4a, 0x22, 0x17, 0x37, 0x43, 0x2c, 0x2d, 0x51, 0x28, 0x02, 0xca, 0x49, 0x56, - 0x49, 0x5e, 0x10, 0x04, 0x0d, 0x45, 0x35, 0x51, 0x67, 0x31, 0x01, 0xaf, 0x2b, 0x31, 0x43, 0x9f, 0xfe, 0xce, 0x37, 0x34, 0x26, 0x29, 0xba, 0x00, 0x00, 0x01, - 0x00, 0x3b, 0xff, 0xf6, 0x02, 0x8c, 0x02, 0xd5, 0x00, 0x1d, 0x00, 0x37, 0x40, 0x34, 0x0c, 0x01, 0x02, 0x01, 0x1b, 0x0d, 0x02, 0x03, 0x02, 0x1c, 0x01, 0x00, - 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, - 0x00, 0x19, 0x17, 0x11, 0x0f, 0x0a, 0x08, 0x00, 0x1d, 0x01, 0x1d, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x17, - 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x01, 0x3f, 0x80, 0x84, 0x1d, 0x3b, 0x5a, 0x7c, 0x50, 0x3f, - 0x67, 0x2d, 0x3a, 0x26, 0x49, 0x2a, 0x38, 0x55, 0x39, 0x1d, 0x46, 0x3f, 0x2b, 0x51, 0x2f, 0x5c, 0x0a, 0x97, 0x7d, 0x40, 0x83, 0x76, 0x5c, 0x36, 0x1d, 0x1a, - 0x78, 0x16, 0x19, 0x38, 0x5d, 0x73, 0x3c, 0x4b, 0x51, 0x14, 0x12, 0x7e, 0x27, 0x00, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x86, 0x02, 0xca, 0x00, 0x09, - 0x00, 0x13, 0x00, 0x2c, 0x40, 0x29, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x01, 0x5f, 0x04, 0x01, 0x01, 0x01, - 0x6b, 0x01, 0x4e, 0x0b, 0x0a, 0x00, 0x00, 0x12, 0x10, 0x0a, 0x13, 0x0b, 0x13, 0x00, 0x09, 0x00, 0x08, 0x21, 0x06, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, - 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x37, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, 0x1a, 0x97, 0xbd, 0x83, 0x95, 0x61, 0xb8, 0x82, 0x13, 0x4a, - 0x6b, 0x39, 0x49, 0x3f, 0x36, 0x62, 0x02, 0xca, 0x8b, 0x89, 0x85, 0xc5, 0x6c, 0x7e, 0x4f, 0x8a, 0x59, 0x50, 0x4d, 0xfe, 0x31, 0x00, 0x00, 0x01, 0x00, 0x1a, - 0x00, 0x00, 0x02, 0x41, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, - 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x04, 0x04, 0x05, 0x5f, 0x06, 0x01, 0x05, 0x05, 0x6b, 0x05, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x33, 0x13, 0x21, 0x07, 0x23, 0x07, 0x33, 0x07, 0x23, 0x07, 0x33, 0x07, 0x1a, 0x97, 0x01, 0x90, 0x1b, 0xf8, 0x21, 0xe8, 0x1b, - 0xe8, 0x27, 0xf9, 0x1a, 0x02, 0xca, 0x7d, 0x9c, 0x7d, 0xb5, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x3f, 0x02, 0xca, 0x00, 0x09, 0x00, 0x29, - 0x40, 0x26, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x04, 0x04, 0x6b, 0x04, - 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x11, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x21, 0x07, 0x23, 0x07, 0x33, 0x07, 0x23, 0x03, 0x1a, - 0x97, 0x01, 0x8e, 0x1b, 0xf7, 0x26, 0xe6, 0x1b, 0xe7, 0x3a, 0x02, 0xca, 0x7d, 0xb6, 0x7e, 0xfe, 0xe7, 0x00, 0x00, 0x01, 0x00, 0x3b, 0xff, 0xf6, 0x02, 0xa7, - 0x02, 0xd5, 0x00, 0x21, 0x00, 0x3e, 0x40, 0x3b, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, 0x05, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x67, - 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1e, 0x1d, - 0x1c, 0x1b, 0x18, 0x16, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x21, 0x01, 0x21, 0x07, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, - 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x23, 0x37, 0x21, 0x03, 0x06, 0x06, 0x01, 0x48, 0x7b, 0x92, - 0x35, 0x67, 0x97, 0x62, 0x40, 0x6b, 0x2c, 0x3a, 0x21, 0x4f, 0x2e, 0x3f, 0x5d, 0x3e, 0x1f, 0x43, 0x43, 0x1b, 0x29, 0x14, 0x21, 0x7b, 0x1b, 0x01, 0x0f, 0x50, - 0x30, 0x72, 0x0a, 0x8f, 0x88, 0x5a, 0xa4, 0x80, 0x4a, 0x19, 0x17, 0x7b, 0x11, 0x1a, 0x39, 0x5e, 0x73, 0x3a, 0x4a, 0x51, 0x06, 0x05, 0x97, 0x7a, 0xfe, 0x8b, - 0x10, 0x17, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x02, 0xc1, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x27, 0x40, 0x24, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x68, - 0x02, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x05, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x07, - 0x0d, 0x1b, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x33, 0x13, 0x33, 0x03, 0x23, 0x13, 0x23, 0x03, 0x1a, 0x97, 0x97, 0x3a, 0xe2, 0x3b, 0x96, 0x97, 0x96, 0x40, 0xe2, - 0x41, 0x02, 0xca, 0xfe, 0xe9, 0x01, 0x17, 0xfd, 0x36, 0x01, 0x33, 0xfe, 0xcd, 0x00, 0x00, 0x01, 0xff, 0xe3, 0x00, 0x00, 0x01, 0xb6, 0x02, 0xca, 0x00, 0x0b, - 0x00, 0x22, 0x40, 0x1f, 0x0a, 0x09, 0x04, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, - 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0x23, 0x37, 0x37, 0x13, 0x27, 0x37, 0x21, 0x07, 0x07, 0x03, 0x17, 0x07, 0x1d, 0x12, 0x5b, 0x62, - 0x4a, 0x12, 0x01, 0x3c, 0x12, 0x5d, 0x62, 0x4c, 0x12, 0x56, 0x28, 0x01, 0xce, 0x28, 0x56, 0x56, 0x28, 0xfe, 0x32, 0x28, 0x56, 0x00, 0x00, 0x01, 0xff, 0x62, - 0xff, 0x2d, 0x01, 0x54, 0x02, 0xca, 0x00, 0x0f, 0x00, 0x28, 0x40, 0x25, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, - 0x00, 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, 0x01, 0x00, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x0f, 0x01, 0x0f, 0x04, 0x0d, 0x16, 0x2b, 0x07, 0x22, - 0x26, 0x27, 0x37, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x41, 0x19, 0x32, 0x12, 0x01, 0x11, 0x26, 0x18, 0x2d, 0x3e, 0x0f, 0x91, - 0x97, 0x94, 0x1b, 0x78, 0xd3, 0x07, 0x06, 0x7d, 0x04, 0x07, 0x34, 0x46, 0x02, 0xa4, 0xfd, 0x4a, 0x7e, 0x69, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x02, 0xc1, - 0x02, 0xca, 0x00, 0x0c, 0x00, 0x25, 0x40, 0x22, 0x0a, 0x07, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, - 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x12, 0x13, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x37, 0x37, 0x33, 0x01, 0x13, - 0x23, 0x03, 0x07, 0x07, 0x1a, 0x97, 0x95, 0x4b, 0x4c, 0xca, 0xb0, 0xfe, 0xde, 0x8e, 0xa5, 0x67, 0x3d, 0x35, 0x02, 0xca, 0xfe, 0xa7, 0x66, 0xf3, 0xfe, 0xaa, - 0xfe, 0x8c, 0x01, 0x21, 0x22, 0xff, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x01, 0xc3, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x6a, - 0x4d, 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, - 0x13, 0x33, 0x03, 0x33, 0x07, 0x1a, 0x97, 0x95, 0x7d, 0xfa, 0x1a, 0x02, 0xca, 0xfd, 0xb3, 0x7d, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x03, 0x75, 0x02, 0xca, - 0x00, 0x17, 0x00, 0x27, 0x40, 0x24, 0x11, 0x0d, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, - 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x17, 0x17, 0x11, 0x13, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x01, 0x33, 0x03, 0x23, - 0x13, 0x3e, 0x02, 0x37, 0x23, 0x01, 0x23, 0x03, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x1a, 0x97, 0xc5, 0x20, 0x04, 0x01, 0x0c, 0xcf, 0x97, 0x89, 0x47, 0x07, 0x13, - 0x13, 0x08, 0x04, 0xfe, 0xea, 0x89, 0x1e, 0x04, 0x02, 0x0c, 0x0f, 0x09, 0x46, 0x02, 0xca, 0xfd, 0xea, 0x02, 0x16, 0xfd, 0x36, 0x01, 0x52, 0x22, 0x4d, 0x4b, - 0x1d, 0xfd, 0xd7, 0x02, 0x29, 0x15, 0x49, 0x56, 0x29, 0xfe, 0xb4, 0x00, 0x00, 0x01, 0x00, 0x19, 0x00, 0x00, 0x02, 0xfb, 0x02, 0xca, 0x00, 0x13, 0x00, 0x24, - 0x40, 0x21, 0x0d, 0x03, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x13, 0x11, 0x17, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x03, 0x23, 0x03, 0x23, 0x0e, 0x02, - 0x07, 0x03, 0x19, 0x97, 0xad, 0xab, 0x03, 0x03, 0x0a, 0x0c, 0x06, 0x48, 0x89, 0x97, 0xad, 0xac, 0x04, 0x01, 0x09, 0x0d, 0x08, 0x46, 0x02, 0xca, 0xfd, 0xf5, - 0x17, 0x42, 0x46, 0x1c, 0x01, 0x50, 0xfd, 0x36, 0x02, 0x19, 0x10, 0x47, 0x53, 0x22, 0xfe, 0xb3, 0x00, 0x02, 0x00, 0x3b, 0xff, 0xf6, 0x02, 0xbc, 0x02, 0xd5, - 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, - 0x00, 0x00, 0x71, 0x00, 0x4e, 0x11, 0x10, 0x01, 0x00, 0x19, 0x17, 0x10, 0x1f, 0x11, 0x1f, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, 0x2b, 0x05, - 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, - 0x16, 0x01, 0x4a, 0x86, 0x89, 0x30, 0x5e, 0x8e, 0x5d, 0x80, 0x88, 0x2d, 0x5c, 0x8b, 0x53, 0x2d, 0x4b, 0x36, 0x1e, 0x40, 0x39, 0x30, 0x4d, 0x38, 0x1d, 0x42, - 0x0a, 0x96, 0x7e, 0x57, 0xa4, 0x83, 0x4d, 0x96, 0x7f, 0x57, 0xa4, 0x82, 0x4d, 0x7f, 0x34, 0x5c, 0x77, 0x43, 0x47, 0x50, 0x37, 0x5e, 0x76, 0x40, 0x48, 0x4e, - 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x67, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x30, 0x40, 0x2d, 0x06, 0x01, 0x03, 0x00, 0x01, 0x02, 0x03, 0x01, - 0x67, 0x00, 0x04, 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0e, 0x0d, 0x00, 0x00, 0x13, 0x11, 0x0d, 0x14, - 0x0e, 0x14, 0x00, 0x0c, 0x00, 0x0c, 0x26, 0x21, 0x07, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x23, 0x07, 0x13, - 0x32, 0x36, 0x35, 0x34, 0x23, 0x23, 0x07, 0x1a, 0x97, 0xc7, 0x57, 0x69, 0x2f, 0x52, 0x8c, 0x59, 0x4c, 0x35, 0x8d, 0x43, 0x52, 0x5f, 0x46, 0x2d, 0x02, 0xca, - 0x34, 0x5e, 0x3e, 0x55, 0x70, 0x37, 0xfe, 0x01, 0x7a, 0x42, 0x3a, 0x58, 0xd4, 0x00, 0x00, 0x02, 0x00, 0x3b, 0xff, 0x56, 0x02, 0xbc, 0x02, 0xd5, 0x00, 0x14, - 0x00, 0x23, 0x00, 0x32, 0x40, 0x2f, 0x12, 0x01, 0x00, 0x03, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x02, 0x86, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, - 0x4d, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x16, 0x15, 0x1e, 0x1c, 0x15, 0x23, 0x16, 0x23, 0x17, 0x26, 0x40, 0x06, 0x0d, - 0x19, 0x2b, 0x05, 0x22, 0x22, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x17, 0x23, 0x03, 0x32, 0x3e, 0x02, - 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x01, 0x4e, 0x03, 0x07, 0x03, 0x7f, 0x87, 0x30, 0x5f, 0x8e, 0x5e, 0x7e, 0x88, 0x32, 0x64, 0x4a, - 0x7b, 0xaf, 0x58, 0x30, 0x4d, 0x37, 0x1d, 0x3f, 0x38, 0x3f, 0x60, 0x35, 0x41, 0x0a, 0x96, 0x7e, 0x57, 0xa4, 0x83, 0x4d, 0x96, 0x7f, 0x5a, 0xa8, 0x83, 0x22, - 0xc3, 0x01, 0x21, 0x34, 0x5c, 0x76, 0x43, 0x48, 0x4d, 0x5b, 0x96, 0x5b, 0x46, 0x4c, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x52, 0x02, 0xca, 0x00, 0x0d, - 0x00, 0x16, 0x00, 0x38, 0x40, 0x35, 0x08, 0x01, 0x02, 0x04, 0x01, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, 0x67, 0x00, 0x05, 0x05, 0x00, 0x5f, - 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x0f, 0x0e, 0x00, 0x00, 0x15, 0x13, 0x0e, 0x16, 0x0f, 0x16, 0x00, 0x0d, 0x00, - 0x0d, 0x11, 0x16, 0x21, 0x08, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x03, 0x13, 0x32, 0x36, 0x35, - 0x34, 0x26, 0x23, 0x23, 0x07, 0x1a, 0x97, 0xb0, 0x76, 0x7b, 0x57, 0x43, 0x7d, 0xa5, 0x62, 0x43, 0x3a, 0x81, 0x3e, 0x4a, 0x2d, 0x31, 0x2d, 0x2b, 0x02, 0xca, - 0x5f, 0x5f, 0x5a, 0x6a, 0x17, 0xfe, 0xcf, 0x01, 0x12, 0xfe, 0xee, 0x01, 0x88, 0x3e, 0x3c, 0x27, 0x2a, 0xcb, 0x00, 0x01, 0x00, 0x14, 0xff, 0xf6, 0x02, 0x1e, - 0x02, 0xd4, 0x00, 0x27, 0x00, 0x37, 0x40, 0x34, 0x18, 0x01, 0x03, 0x02, 0x19, 0x04, 0x02, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, - 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1c, 0x1a, 0x16, 0x14, 0x08, - 0x06, 0x00, 0x27, 0x01, 0x27, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x2e, 0x02, 0x35, - 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc2, 0x36, 0x59, 0x1f, - 0x2c, 0x56, 0x2d, 0x32, 0x42, 0x30, 0x26, 0x1e, 0x38, 0x24, 0x3c, 0x6f, 0x4a, 0x38, 0x5e, 0x2c, 0x35, 0x4c, 0x41, 0x28, 0x34, 0x2e, 0x2a, 0x3b, 0x3b, 0x49, - 0x79, 0x0a, 0x18, 0x14, 0x86, 0x19, 0x1c, 0x26, 0x28, 0x29, 0x2f, 0x1c, 0x16, 0x36, 0x49, 0x31, 0x40, 0x61, 0x38, 0x18, 0x18, 0x72, 0x24, 0x2b, 0x25, 0x26, - 0x2d, 0x1c, 0x27, 0x5e, 0x3f, 0x4b, 0x62, 0x30, 0x00, 0x01, 0x00, 0x51, 0x00, 0x00, 0x02, 0x5b, 0x02, 0xca, 0x00, 0x07, 0x00, 0x21, 0x40, 0x1e, 0x02, 0x01, - 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, - 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x23, 0x37, 0x21, 0x07, 0x23, 0x03, 0x81, 0x7b, 0xab, 0x1c, 0x01, 0xee, 0x1c, 0xab, 0x7b, 0x02, 0x4b, 0x7f, 0x7f, 0xfd, 0xb5, - 0x00, 0x01, 0x00, 0x44, 0xff, 0xf6, 0x02, 0xbc, 0x02, 0xca, 0x00, 0x17, 0x00, 0x24, 0x40, 0x21, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, - 0x62, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x13, 0x12, 0x0f, 0x0d, 0x08, 0x07, 0x00, 0x17, 0x01, 0x17, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, - 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x0e, 0x02, 0x01, 0x2b, 0x70, 0x77, 0x04, - 0x04, 0x5f, 0x98, 0x5f, 0x08, 0x2e, 0x2e, 0x3c, 0x41, 0x11, 0x5f, 0x97, 0x62, 0x12, 0x48, 0x79, 0x0a, 0x6f, 0x5c, 0x10, 0x29, 0x15, 0x01, 0xbb, 0xfe, 0x46, - 0x27, 0x1e, 0x28, 0x2d, 0x48, 0x4d, 0x01, 0xbf, 0xfe, 0x33, 0x54, 0x75, 0x3e, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0xa8, 0x02, 0xca, 0x00, 0x0d, - 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, - 0x0d, 0x00, 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, 0x98, 0x3e, 0x90, - 0x19, 0x02, 0x01, 0x02, 0x04, 0x0b, 0x1b, 0x10, 0xd2, 0x9a, 0xfe, 0x93, 0x02, 0xca, 0xfe, 0x52, 0x1f, 0x4e, 0x1d, 0x21, 0x47, 0x22, 0x01, 0xae, 0xfd, 0x36, - 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x03, 0xdc, 0x02, 0xca, 0x00, 0x22, 0x00, 0x27, 0x40, 0x24, 0x1e, 0x11, 0x06, 0x03, 0x03, 0x00, 0x01, 0x4c, 0x02, 0x01, - 0x02, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x22, 0x11, 0x1a, 0x19, 0x11, 0x06, 0x0d, 0x1a, - 0x2b, 0x33, 0x03, 0x33, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x13, 0x16, 0x06, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, - 0x23, 0x03, 0x26, 0x26, 0x34, 0x37, 0x23, 0x06, 0x07, 0x03, 0x70, 0x16, 0x8c, 0x03, 0x03, 0x04, 0x04, 0x0e, 0x22, 0x0d, 0xb4, 0x84, 0x0a, 0x01, 0x01, 0x02, - 0x02, 0x04, 0x0e, 0x23, 0x0e, 0xa1, 0x97, 0xfe, 0xc4, 0xa9, 0x08, 0x01, 0x01, 0x01, 0x04, 0x1a, 0x1d, 0x9e, 0x02, 0xca, 0xfe, 0x7a, 0x25, 0x5d, 0x27, 0x27, - 0x59, 0x1f, 0x01, 0x90, 0xfe, 0x70, 0x11, 0x36, 0x3d, 0x1b, 0x29, 0x5f, 0x22, 0x01, 0x85, 0xfd, 0x36, 0x01, 0x45, 0x2c, 0x39, 0x2e, 0x19, 0x50, 0x42, 0xfe, - 0xa1, 0x00, 0x00, 0x01, 0xff, 0xc7, 0x00, 0x00, 0x02, 0xb0, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, 0x04, 0x02, 0x00, 0x01, - 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x12, 0x12, 0x12, 0x05, 0x0d, - 0x19, 0x2b, 0x23, 0x01, 0x03, 0x33, 0x17, 0x37, 0x33, 0x01, 0x13, 0x23, 0x03, 0x03, 0x39, 0x01, 0x19, 0x74, 0x9f, 0x4a, 0xaf, 0xac, 0xfe, 0xf6, 0x83, 0xa6, - 0x53, 0xbf, 0x01, 0x7b, 0x01, 0x4f, 0xf6, 0xf6, 0xfe, 0xa3, 0xfe, 0x93, 0x01, 0x0d, 0xfe, 0xf3, 0x00, 0x01, 0x00, 0x5b, 0x00, 0x00, 0x02, 0x90, 0x02, 0xca, - 0x00, 0x08, 0x00, 0x22, 0x40, 0x1f, 0x04, 0x01, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x12, 0x12, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x03, 0x33, 0x13, 0x13, 0x33, 0x01, 0x03, 0x94, 0x3a, 0x73, 0x98, 0x3f, - 0xb7, 0xa7, 0xfe, 0xd2, 0x3a, 0x01, 0x11, 0x01, 0xb9, 0xfe, 0xdf, 0x01, 0x21, 0xfe, 0x47, 0xfe, 0xef, 0x00, 0x00, 0x01, 0xff, 0xe2, 0x00, 0x00, 0x02, 0x4a, - 0x02, 0xca, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, - 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x01, 0x21, 0x37, 0x21, 0x07, 0x01, 0x21, - 0x07, 0x1e, 0x13, 0x01, 0x7b, 0xfe, 0xf7, 0x1a, 0x01, 0xc9, 0x14, 0xfe, 0x82, 0x01, 0x23, 0x1a, 0x62, 0x01, 0xeb, 0x7d, 0x63, 0xfe, 0x16, 0x7d, 0x00, 0x01, - 0xff, 0xee, 0xff, 0x62, 0x01, 0x8f, 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x02, 0x04, 0x01, 0x03, 0x02, 0x03, 0x63, 0x00, 0x01, 0x01, 0x00, - 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, 0x23, 0x03, - 0x33, 0x07, 0x12, 0xba, 0xe7, 0x16, 0x69, 0x8e, 0x69, 0x16, 0x9e, 0x03, 0x68, 0x67, 0xfd, 0x66, 0x67, 0x00, 0x00, 0x01, 0x00, 0x6c, 0xff, 0xfa, 0x01, 0x5a, - 0x02, 0xd0, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, - 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x17, 0x03, 0x33, 0x13, 0xdc, 0x70, 0x7b, 0x73, 0x06, 0x02, 0xd6, 0xfd, 0x2a, 0x00, 0x01, 0xff, 0xbd, 0xff, 0x62, 0x01, 0x5d, - 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x00, 0x04, 0x01, 0x03, 0x00, 0x03, 0x63, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, - 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x07, 0x37, 0x33, 0x13, 0x23, 0x37, 0x33, 0x03, 0x43, 0x16, 0x68, 0x8e, - 0x69, 0x16, 0xe7, 0xba, 0x9e, 0x67, 0x02, 0x9a, 0x67, 0xfc, 0x98, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0xfe, 0x02, 0x0e, 0x02, 0xce, 0x00, 0x06, 0x00, 0x27, - 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x03, 0x02, 0x02, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x37, 0x01, 0x33, 0x13, 0x23, 0x03, 0x03, 0x11, 0x01, 0x2e, 0x48, 0x87, 0x6d, - 0x55, 0xc4, 0xfe, 0x01, 0xd0, 0xfe, 0x30, 0x01, 0x35, 0xfe, 0xcb, 0x00, 0x00, 0x01, 0xff, 0xa5, 0xff, 0x62, 0x01, 0x45, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x26, - 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x07, 0x37, 0x21, 0x07, 0x5b, 0x0f, 0x01, 0x91, 0x0f, 0x9e, 0x44, 0x44, 0x00, 0x01, - 0x00, 0x91, 0x02, 0x5e, 0x01, 0x63, 0x02, 0xfe, 0x00, 0x09, 0x00, 0x2d, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x22, 0x08, 0x04, 0x02, 0x01, 0x00, 0x01, 0x4c, 0x00, - 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x15, 0x03, 0x0d, 0x17, - 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x2e, 0x02, 0x27, 0x35, 0x33, 0x16, 0x17, 0x15, 0x01, 0x07, 0x15, 0x2e, 0x28, 0x0b, 0x9a, 0x11, 0x27, 0x02, 0x5e, 0x14, - 0x34, 0x37, 0x17, 0x0a, 0x48, 0x4c, 0x0c, 0x00, 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x42, 0x02, 0x2c, 0x00, 0x15, 0x00, 0x24, 0x00, 0x7e, 0x4b, 0xb0, - 0x19, 0x50, 0x58, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x01, 0x12, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x02, 0x12, 0x01, 0x03, 0x04, - 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x19, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, - 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, - 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, - 0x20, 0x1e, 0x16, 0x24, 0x17, 0x24, 0x11, 0x10, 0x0f, 0x0e, 0x0a, 0x08, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, 0x34, - 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0x37, 0x32, 0x36, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, - 0x06, 0x06, 0x15, 0x14, 0xc4, 0x2b, 0x45, 0x28, 0x21, 0x40, 0x5e, 0x3d, 0x32, 0x3e, 0x13, 0x04, 0x1d, 0x76, 0x74, 0x77, 0x08, 0x04, 0x1b, 0x48, 0x07, 0x1b, - 0x32, 0x26, 0x0a, 0x09, 0x21, 0x1d, 0x24, 0x3b, 0x23, 0x0a, 0x29, 0x58, 0x47, 0x3c, 0x80, 0x6e, 0x44, 0x30, 0x23, 0x49, 0xfd, 0xde, 0x4b, 0x24, 0x31, 0x79, - 0x2d, 0x4a, 0x2d, 0x29, 0x22, 0x26, 0x2f, 0x46, 0x6d, 0x3c, 0x55, 0x00, 0x00, 0x02, 0x00, 0x12, 0xff, 0xf6, 0x02, 0x27, 0x02, 0xf8, 0x00, 0x19, 0x00, 0x28, - 0x00, 0x82, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x0d, 0x01, 0x05, 0x03, 0x03, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x0d, 0x01, 0x05, 0x03, - 0x03, 0x01, 0x01, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, - 0x03, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x01, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, - 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, - 0x4e, 0x59, 0x40, 0x17, 0x1b, 0x1a, 0x01, 0x00, 0x22, 0x20, 0x1a, 0x28, 0x1b, 0x28, 0x12, 0x10, 0x08, 0x07, 0x06, 0x05, 0x00, 0x19, 0x01, 0x19, 0x08, 0x0d, - 0x16, 0x2b, 0x05, 0x22, 0x26, 0x27, 0x23, 0x07, 0x23, 0x13, 0x33, 0x07, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x0e, 0x02, - 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x2a, 0x34, 0x41, 0x12, 0x04, 0x1c, 0x71, 0xa1, 0x93, 0x1e, 0x04, 0x0e, - 0x10, 0x07, 0x04, 0x1a, 0x3e, 0x32, 0x28, 0x46, 0x2c, 0x24, 0x42, 0x5d, 0x53, 0x1b, 0x2f, 0x23, 0x14, 0x40, 0x24, 0x32, 0x20, 0x0f, 0x25, 0x0a, 0x2c, 0x24, - 0x46, 0x02, 0xf8, 0x8d, 0x14, 0x35, 0x35, 0x14, 0x21, 0x32, 0x27, 0x57, 0x48, 0x43, 0x82, 0x6b, 0x40, 0x77, 0x2b, 0x46, 0x56, 0x2b, 0x56, 0x34, 0x4f, 0x52, - 0x1d, 0x27, 0x2f, 0x00, 0x00, 0x01, 0x00, 0x2c, 0xff, 0xf6, 0x01, 0xef, 0x02, 0x2c, 0x00, 0x1e, 0x00, 0x37, 0x40, 0x34, 0x0c, 0x01, 0x02, 0x01, 0x1b, 0x0d, - 0x02, 0x03, 0x02, 0x1c, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, - 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x19, 0x17, 0x11, 0x0f, 0x0a, 0x08, 0x00, 0x1e, 0x01, 0x1e, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, - 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0xf7, 0x39, - 0x5c, 0x36, 0x28, 0x4c, 0x6b, 0x42, 0x2e, 0x4f, 0x25, 0x2f, 0x17, 0x39, 0x1d, 0x22, 0x36, 0x25, 0x13, 0x2c, 0x27, 0x23, 0x41, 0x22, 0x22, 0x50, 0x0a, 0x2d, - 0x60, 0x4b, 0x49, 0x7f, 0x60, 0x36, 0x11, 0x11, 0x71, 0x0a, 0x11, 0x28, 0x41, 0x4f, 0x26, 0x36, 0x31, 0x16, 0x11, 0x79, 0x12, 0x15, 0x00, 0x02, 0x00, 0x2c, - 0xff, 0xf6, 0x02, 0x6e, 0x02, 0xf8, 0x00, 0x19, 0x00, 0x28, 0x00, 0x82, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x01, 0x16, 0x01, 0x00, - 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x01, 0x16, 0x01, 0x03, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, - 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, - 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, - 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x1b, 0x1a, 0x01, 0x00, 0x23, 0x21, 0x1a, 0x28, 0x1b, 0x28, 0x15, 0x14, - 0x13, 0x12, 0x0a, 0x08, 0x00, 0x19, 0x01, 0x19, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x34, - 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0x37, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xc6, 0x27, - 0x47, 0x2c, 0x24, 0x42, 0x5d, 0x3a, 0x31, 0x38, 0x13, 0x04, 0x03, 0x06, 0x04, 0x25, 0x93, 0xa1, 0x70, 0x09, 0x04, 0x1d, 0x4a, 0x09, 0x23, 0x31, 0x1f, 0x0f, - 0x24, 0x20, 0x1b, 0x2f, 0x23, 0x14, 0x0a, 0x27, 0x57, 0x49, 0x42, 0x83, 0x6a, 0x40, 0x2e, 0x22, 0x03, 0x25, 0x31, 0x14, 0xaf, 0xfd, 0x08, 0x47, 0x24, 0x2d, - 0x77, 0x35, 0x4f, 0x51, 0x1d, 0x27, 0x2f, 0x2b, 0x46, 0x56, 0x2b, 0x56, 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x14, 0x02, 0x2c, 0x00, 0x1b, 0x00, 0x25, - 0x00, 0x43, 0x40, 0x40, 0x18, 0x01, 0x03, 0x02, 0x19, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x03, 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, - 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1d, 0x1c, 0x01, 0x00, 0x22, 0x20, 0x1c, - 0x25, 0x1d, 0x25, 0x16, 0x14, 0x0f, 0x0d, 0x09, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x08, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, - 0x16, 0x15, 0x14, 0x06, 0x23, 0x23, 0x06, 0x14, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x03, 0x32, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, - 0x06, 0x07, 0x01, 0x04, 0x60, 0x78, 0x27, 0x4d, 0x72, 0x4b, 0x5c, 0x5b, 0x9b, 0x9f, 0x19, 0x01, 0x33, 0x2e, 0x2b, 0x46, 0x30, 0x2b, 0x58, 0x58, 0x55, 0x4b, - 0x33, 0x1b, 0x36, 0x29, 0x09, 0x0a, 0x69, 0x6a, 0x45, 0x7f, 0x64, 0x3b, 0x54, 0x41, 0x56, 0x68, 0x06, 0x09, 0x05, 0x2c, 0x34, 0x14, 0x16, 0x6f, 0x15, 0x15, - 0x01, 0x46, 0x35, 0x23, 0x2e, 0x22, 0x3c, 0x28, 0x00, 0x01, 0xff, 0x96, 0xff, 0x10, 0x01, 0xe5, 0x02, 0xfd, 0x00, 0x23, 0x00, 0xa3, 0x40, 0x12, 0x15, 0x01, - 0x04, 0x03, 0x16, 0x01, 0x05, 0x04, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x21, 0x00, 0x04, 0x04, - 0x03, 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, - 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x21, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, 0x02, 0x02, - 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x04, 0x04, 0x03, - 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, - 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x15, 0x01, 0x00, 0x20, 0x1f, 0x1e, 0x1d, 0x1a, 0x18, 0x13, 0x11, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x23, 0x01, 0x23, 0x08, - 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, - 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x13, 0x18, 0x2f, 0x10, 0x0e, 0x1c, 0x0f, 0x24, 0x26, 0x09, 0x63, 0x55, 0x0f, 0x5f, - 0x0a, 0x15, 0x5f, 0x50, 0x22, 0x41, 0x16, 0x26, 0x0e, 0x22, 0x11, 0x19, 0x21, 0x07, 0x0a, 0x6c, 0x19, 0x6b, 0x69, 0x11, 0x5a, 0xf0, 0x07, 0x05, 0x77, 0x04, - 0x06, 0x29, 0x29, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x61, 0x51, 0x0e, 0x0a, 0x69, 0x06, 0x08, 0x1c, 0x22, 0x2a, 0x70, 0xfe, 0x13, 0x51, 0x64, 0x00, 0x00, 0x02, - 0x00, 0x12, 0xff, 0x10, 0x02, 0x42, 0x02, 0x2c, 0x00, 0x23, 0x00, 0x32, 0x00, 0x9e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x1c, 0x01, 0x06, 0x03, 0x0d, - 0x01, 0x02, 0x05, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x1b, 0x40, 0x12, 0x1c, 0x01, 0x06, 0x04, 0x0d, 0x01, 0x02, 0x05, 0x04, 0x01, - 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x00, 0x06, 0x06, 0x03, 0x61, 0x04, 0x01, 0x03, 0x03, 0x73, - 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, - 0x26, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x06, 0x06, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, - 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, 0x19, 0x25, 0x24, 0x01, 0x00, 0x2d, 0x2b, 0x24, 0x32, 0x25, 0x32, - 0x1f, 0x1e, 0x1a, 0x18, 0x12, 0x10, 0x08, 0x06, 0x00, 0x23, 0x01, 0x23, 0x09, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x37, - 0x37, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x0e, 0x02, 0x11, 0x32, - 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xbd, 0x38, 0x53, 0x20, 0x21, 0x58, 0x2e, 0x67, 0x18, 0x07, 0x03, 0x0a, 0x05, 0x04, 0x1a, - 0x43, 0x32, 0x40, 0x52, 0x20, 0x3f, 0x5e, 0x3f, 0x32, 0x3b, 0x16, 0x04, 0x1d, 0x76, 0x78, 0x12, 0x4c, 0x6d, 0x1b, 0x30, 0x25, 0x16, 0x1d, 0x21, 0x1c, 0x2f, - 0x24, 0x13, 0xf0, 0x13, 0x0d, 0x7e, 0x12, 0x18, 0x63, 0x1c, 0x0f, 0x27, 0x0f, 0x21, 0x2e, 0x5c, 0x68, 0x3c, 0x80, 0x6f, 0x44, 0x2c, 0x27, 0x49, 0xfd, 0xca, - 0x52, 0x60, 0x2a, 0x01, 0x5f, 0x2b, 0x47, 0x54, 0x29, 0x26, 0x2f, 0x29, 0x45, 0x55, 0x2c, 0x55, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x02, 0x29, 0x02, 0xf8, - 0x00, 0x1c, 0x00, 0x2d, 0x40, 0x2a, 0x07, 0x01, 0x03, 0x01, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, - 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1c, 0x24, 0x15, 0x28, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, - 0x07, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x03, 0x23, 0x13, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x12, - 0xa1, 0x93, 0x1c, 0x04, 0x10, 0x10, 0x07, 0x04, 0x1e, 0x4a, 0x31, 0x47, 0x46, 0x0b, 0x41, 0x93, 0x43, 0x08, 0x35, 0x21, 0x36, 0x27, 0x0d, 0x30, 0x02, 0xf8, - 0x84, 0x16, 0x3a, 0x37, 0x14, 0x26, 0x2d, 0x55, 0x48, 0x24, 0x34, 0xfe, 0xc9, 0x01, 0x3f, 0x23, 0x17, 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0x00, 0x02, 0x00, 0x12, - 0x00, 0x00, 0x01, 0x41, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x2d, 0x40, 0x2a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x72, 0x4d, 0x00, - 0x02, 0x02, 0x6d, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x0c, 0x0c, 0x01, 0x00, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, 0x0b, 0x01, - 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x13, 0x33, 0x03, 0xe8, 0x21, 0x2b, 0x30, 0x2b, - 0x20, 0x2a, 0x2f, 0xff, 0x00, 0x73, 0x97, 0x75, 0x02, 0x65, 0x1d, 0x20, 0x28, 0x2f, 0x1c, 0x20, 0x28, 0x30, 0xfd, 0x9b, 0x02, 0x22, 0xfd, 0xde, 0x00, 0x02, - 0xff, 0x80, 0xff, 0x10, 0x01, 0x43, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x1b, 0x00, 0x3e, 0x40, 0x3b, 0x10, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x02, 0x4c, - 0x05, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x72, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x06, 0x01, 0x02, 0x02, 0x6f, - 0x02, 0x4e, 0x0d, 0x0c, 0x01, 0x00, 0x17, 0x16, 0x13, 0x11, 0x0c, 0x1b, 0x0d, 0x1b, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x07, 0x0d, 0x16, 0x2b, 0x13, 0x22, - 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x0e, 0x02, 0xea, - 0x20, 0x2b, 0x2f, 0x2b, 0x20, 0x2a, 0x2f, 0xfe, 0xc2, 0x17, 0x30, 0x0f, 0x1c, 0x1c, 0x1e, 0x2d, 0x09, 0x7c, 0x95, 0x80, 0x0b, 0x2e, 0x50, 0x02, 0x65, 0x1d, - 0x20, 0x28, 0x2f, 0x1c, 0x20, 0x28, 0x30, 0xfc, 0xab, 0x07, 0x05, 0x77, 0x0a, 0x27, 0x2b, 0x02, 0x47, 0xfd, 0xa4, 0x32, 0x53, 0x31, 0x00, 0x01, 0x00, 0x12, - 0x00, 0x00, 0x02, 0x69, 0x02, 0xf8, 0x00, 0x0f, 0x00, 0x29, 0x40, 0x26, 0x0d, 0x0a, 0x06, 0x03, 0x02, 0x01, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, - 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x12, 0x16, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, - 0x13, 0x33, 0x03, 0x06, 0x06, 0x07, 0x33, 0x37, 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x07, 0x12, 0xa1, 0x93, 0x48, 0x05, 0x14, 0x05, 0x04, 0xdd, 0xa8, 0xf3, - 0x8b, 0xa4, 0x59, 0x3b, 0x24, 0x02, 0xf8, 0xfe, 0xad, 0x19, 0x41, 0x11, 0xe8, 0xf6, 0xfe, 0xd4, 0xcd, 0x23, 0xaa, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, - 0x01, 0x48, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x11, 0xa2, 0x95, 0xa1, 0x02, 0xf8, 0xfd, 0x08, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, - 0x03, 0x56, 0x02, 0x2c, 0x00, 0x2a, 0x00, 0x56, 0xb6, 0x0a, 0x03, 0x02, 0x04, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x06, 0x01, 0x04, - 0x04, 0x00, 0x61, 0x02, 0x01, 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x08, 0x07, 0x05, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x1a, 0x00, 0x00, 0x00, 0x6d, - 0x4d, 0x06, 0x01, 0x04, 0x04, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x08, 0x07, 0x05, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x59, 0x40, 0x10, 0x00, - 0x00, 0x00, 0x2a, 0x00, 0x2a, 0x24, 0x14, 0x24, 0x15, 0x25, 0x24, 0x11, 0x09, 0x0d, 0x1d, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, - 0x17, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x03, 0x23, 0x13, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x23, 0x13, 0x36, 0x35, - 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x12, 0x74, 0x70, 0x0a, 0x04, 0x20, 0x53, 0x39, 0x38, 0x3e, 0x0a, 0x04, 0x1f, 0x56, 0x39, 0x44, 0x44, 0x0b, 0x41, - 0x93, 0x43, 0x08, 0x30, 0x21, 0x36, 0x28, 0x0c, 0x2f, 0x93, 0x43, 0x08, 0x30, 0x21, 0x36, 0x27, 0x0d, 0x30, 0x02, 0x22, 0x65, 0x31, 0x3e, 0x3b, 0x34, 0x31, - 0x3e, 0x55, 0x48, 0x24, 0x34, 0xfe, 0xc9, 0x01, 0x3f, 0x23, 0x17, 0x3c, 0x38, 0x5f, 0x3b, 0xe3, 0x01, 0x3f, 0x23, 0x17, 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0x00, - 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x02, 0x29, 0x02, 0x2c, 0x00, 0x18, 0x00, 0x4c, 0xb5, 0x03, 0x01, 0x03, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, - 0x40, 0x13, 0x00, 0x03, 0x03, 0x00, 0x61, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x00, - 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, - 0x00, 0x18, 0x00, 0x18, 0x24, 0x15, 0x24, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x03, - 0x23, 0x13, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x12, 0x74, 0x70, 0x0a, 0x04, 0x20, 0x53, 0x39, 0x47, 0x46, 0x0b, 0x41, 0x93, 0x43, 0x08, - 0x35, 0x21, 0x36, 0x27, 0x0d, 0x30, 0x02, 0x22, 0x65, 0x31, 0x3e, 0x55, 0x48, 0x24, 0x34, 0xfe, 0xc9, 0x01, 0x3f, 0x23, 0x17, 0x3c, 0x39, 0x60, 0x3a, 0xe2, - 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x1d, 0x02, 0x2c, 0x00, 0x10, 0x00, 0x1e, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, - 0x73, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x12, 0x11, 0x01, 0x00, 0x19, 0x17, 0x11, 0x1e, 0x12, 0x1e, 0x0a, - 0x08, 0x00, 0x10, 0x01, 0x10, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, - 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xfd, 0x3d, 0x5f, 0x35, 0x24, 0x48, 0x6d, 0x49, 0x5f, 0x70, 0x22, 0x47, 0x6d, 0x3e, 0x29, - 0x39, 0x1e, 0x1f, 0x27, 0x21, 0x32, 0x20, 0x10, 0x0a, 0x33, 0x5e, 0x41, 0x48, 0x81, 0x63, 0x38, 0x72, 0x66, 0x45, 0x7e, 0x62, 0x39, 0x78, 0x42, 0x69, 0x3b, - 0x29, 0x37, 0x2d, 0x48, 0x52, 0x25, 0x5a, 0x00, 0x00, 0x02, 0xff, 0xdf, 0xff, 0x10, 0x02, 0x27, 0x02, 0x2c, 0x00, 0x18, 0x00, 0x27, 0x00, 0x6c, 0x40, 0x0a, - 0x03, 0x01, 0x05, 0x00, 0x13, 0x01, 0x02, 0x04, 0x02, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x01, 0x01, 0x00, 0x00, - 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x00, 0x00, - 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, 0x03, - 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x14, 0x1a, 0x19, 0x00, 0x00, 0x21, 0x1f, 0x19, 0x27, 0x1a, 0x27, 0x00, 0x18, 0x00, 0x18, 0x27, 0x24, 0x11, 0x08, 0x0d, - 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x07, - 0x13, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x21, 0xa7, 0x70, 0x08, 0x04, 0x1a, 0x4c, 0x35, 0x28, 0x46, 0x2c, 0x24, 0x42, - 0x5d, 0x3a, 0x32, 0x36, 0x14, 0x04, 0x03, 0x0a, 0x08, 0x23, 0x9f, 0x1b, 0x2f, 0x23, 0x14, 0x40, 0x24, 0x32, 0x20, 0x0f, 0x25, 0xf0, 0x03, 0x12, 0x53, 0x23, - 0x3a, 0x27, 0x57, 0x49, 0x42, 0x83, 0x6a, 0x40, 0x2e, 0x22, 0x28, 0x42, 0x26, 0xa6, 0x01, 0x5d, 0x2b, 0x46, 0x56, 0x2b, 0x56, 0x34, 0x4e, 0x52, 0x1e, 0x27, - 0x2f, 0x00, 0x00, 0x02, 0x00, 0x2c, 0xff, 0x10, 0x02, 0x41, 0x02, 0x2c, 0x00, 0x19, 0x00, 0x29, 0x00, 0x78, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x14, - 0x01, 0x05, 0x01, 0x04, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x14, 0x01, 0x05, 0x02, 0x04, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, - 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, - 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, - 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x1b, 0x1a, 0x23, 0x21, 0x1a, 0x29, 0x1b, 0x29, - 0x11, 0x14, 0x27, 0x27, 0x07, 0x0d, 0x1a, 0x2b, 0x05, 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, - 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x03, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x2b, 0x04, 0x0e, 0x11, 0x06, - 0x04, 0x1a, 0x44, 0x33, 0x24, 0x43, 0x2c, 0x24, 0x42, 0x5d, 0x3a, 0x31, 0x3e, 0x18, 0x04, 0x1c, 0x71, 0xa7, 0x93, 0x02, 0x23, 0x31, 0x1e, 0x0f, 0x24, 0x20, - 0x1b, 0x2f, 0x23, 0x14, 0x24, 0x4b, 0x12, 0x35, 0x38, 0x15, 0x22, 0x31, 0x27, 0x57, 0x48, 0x43, 0x82, 0x6b, 0x40, 0x2a, 0x26, 0x46, 0xfc, 0xee, 0x01, 0x5d, - 0x35, 0x4f, 0x51, 0x1d, 0x27, 0x2f, 0x2b, 0x46, 0x56, 0x2b, 0x2b, 0x2b, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x01, 0xcc, 0x02, 0x2c, 0x00, 0x12, 0x00, 0x69, - 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0e, 0x03, 0x01, 0x02, 0x00, 0x0b, 0x01, 0x03, 0x02, 0x02, 0x4c, 0x0a, 0x01, 0x00, 0x4a, 0x1b, 0x40, 0x0e, 0x0a, 0x01, - 0x00, 0x01, 0x03, 0x01, 0x02, 0x00, 0x0b, 0x01, 0x03, 0x02, 0x03, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x02, 0x02, 0x00, 0x61, 0x01, - 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, - 0x01, 0x01, 0x73, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x59, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x12, 0x25, 0x24, 0x11, 0x05, 0x0d, 0x19, - 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x12, 0x73, 0x79, 0x0a, 0x04, 0x22, - 0x4b, 0x38, 0x0c, 0x1a, 0x09, 0x21, 0x0c, 0x1c, 0x10, 0x39, 0x4e, 0x11, 0x34, 0x02, 0x22, 0x5e, 0x33, 0x35, 0x02, 0x03, 0x91, 0x04, 0x05, 0x5c, 0x4f, 0xf4, - 0x00, 0x01, 0x00, 0x0b, 0xff, 0xf6, 0x01, 0xc7, 0x02, 0x2c, 0x00, 0x26, 0x00, 0x37, 0x40, 0x34, 0x17, 0x01, 0x03, 0x02, 0x18, 0x04, 0x02, 0x01, 0x03, 0x03, - 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, - 0x4e, 0x01, 0x00, 0x1c, 0x1a, 0x15, 0x13, 0x08, 0x06, 0x00, 0x26, 0x01, 0x26, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, - 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, - 0x16, 0x15, 0x14, 0x06, 0xb0, 0x35, 0x51, 0x1f, 0x25, 0x4f, 0x28, 0x22, 0x36, 0x0d, 0x23, 0x22, 0x36, 0x33, 0x6a, 0x67, 0x34, 0x58, 0x26, 0x2f, 0x1b, 0x44, - 0x22, 0x1c, 0x20, 0x21, 0x29, 0x37, 0x3b, 0x7e, 0x0a, 0x11, 0x0f, 0x7c, 0x15, 0x16, 0x19, 0x1c, 0x0f, 0x16, 0x1a, 0x13, 0x1d, 0x47, 0x34, 0x4b, 0x5b, 0x18, - 0x16, 0x66, 0x10, 0x19, 0x1a, 0x17, 0x13, 0x1c, 0x16, 0x1c, 0x48, 0x35, 0x5f, 0x5d, 0x00, 0x01, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xad, 0x02, 0x96, 0x00, 0x1b, - 0x00, 0x66, 0x40, 0x0a, 0x18, 0x01, 0x05, 0x01, 0x19, 0x01, 0x00, 0x05, 0x02, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x03, 0x03, 0x02, - 0x70, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, - 0x1c, 0x00, 0x02, 0x03, 0x02, 0x85, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, - 0x71, 0x00, 0x4e, 0x59, 0x40, 0x13, 0x01, 0x00, 0x16, 0x14, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x07, 0x06, 0x00, 0x1b, 0x01, 0x1b, 0x07, 0x0d, 0x16, 0x2b, - 0x17, 0x22, 0x26, 0x35, 0x34, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x33, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, - 0x06, 0xc8, 0x40, 0x4e, 0x06, 0x38, 0x4a, 0x0e, 0x60, 0x40, 0x5f, 0x18, 0x8a, 0x18, 0x8a, 0x38, 0x03, 0x18, 0x13, 0x14, 0x25, 0x16, 0x17, 0x42, 0x0a, 0x37, - 0x47, 0x19, 0x1e, 0x01, 0x07, 0x48, 0x29, 0x73, 0x74, 0x70, 0xfe, 0xf9, 0x0f, 0x0b, 0x13, 0x11, 0x09, 0x08, 0x6e, 0x0b, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x36, - 0xff, 0xf6, 0x02, 0x4b, 0x02, 0x22, 0x00, 0x19, 0x00, 0x5e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0xb5, 0x16, 0x01, 0x00, 0x02, 0x01, 0x4c, 0x1b, 0xb5, 0x16, 0x01, - 0x04, 0x02, 0x01, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x03, 0x01, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x05, 0x02, - 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x17, 0x03, 0x01, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x04, 0x04, 0x6b, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x05, 0x01, - 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, 0x15, 0x14, 0x13, 0x12, 0x0e, 0x0c, 0x08, 0x07, 0x00, 0x19, 0x01, 0x19, 0x06, 0x0d, 0x16, 0x2b, - 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x15, 0x14, 0x33, 0x32, 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, - 0xc1, 0x46, 0x45, 0x06, 0x06, 0x3e, 0x93, 0x43, 0x08, 0x35, 0x22, 0x35, 0x28, 0x0c, 0x30, 0x93, 0x74, 0x70, 0x0a, 0x05, 0x1f, 0x53, 0x0a, 0x55, 0x48, 0x12, - 0x39, 0x1d, 0x01, 0x27, 0xfe, 0xc1, 0x23, 0x17, 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0xfd, 0xde, 0x65, 0x31, 0x3e, 0x00, 0x01, 0x00, 0x32, 0x00, 0x00, 0x02, 0x3a, - 0x02, 0x22, 0x00, 0x0d, 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, - 0x4e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x16, 0x15, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, - 0x01, 0x75, 0x43, 0x90, 0x16, 0x02, 0x01, 0x05, 0x09, 0x18, 0x0a, 0x91, 0x9e, 0xfe, 0xd9, 0x02, 0x22, 0xfe, 0xe2, 0x13, 0x43, 0x1b, 0x19, 0x41, 0x13, 0x01, - 0x22, 0xfd, 0xde, 0x00, 0x00, 0x01, 0x00, 0x3d, 0x00, 0x00, 0x03, 0x47, 0x02, 0x22, 0x00, 0x25, 0x00, 0x27, 0x40, 0x24, 0x1f, 0x11, 0x06, 0x03, 0x03, 0x00, - 0x01, 0x4c, 0x02, 0x01, 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x25, 0x00, 0x25, 0x11, 0x1a, 0x1a, - 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x03, 0x33, 0x17, 0x14, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x11, 0x14, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, - 0x37, 0x33, 0x01, 0x23, 0x27, 0x34, 0x36, 0x36, 0x37, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x56, 0x19, 0x89, 0x02, 0x01, 0x04, 0x04, 0x07, 0x16, 0x13, 0x04, 0x71, - 0xa0, 0x01, 0x04, 0x05, 0x07, 0x15, 0x16, 0x08, 0x6b, 0x96, 0xfe, 0xfd, 0xa1, 0x03, 0x01, 0x03, 0x01, 0x06, 0x08, 0x15, 0x14, 0x08, 0x72, 0x02, 0x22, 0xf2, - 0x28, 0x4f, 0x2e, 0x19, 0x3d, 0x32, 0x09, 0x01, 0x06, 0xfe, 0xfa, 0x22, 0x46, 0x29, 0x17, 0x3e, 0x3d, 0x13, 0xf2, 0xfd, 0xde, 0xfe, 0x15, 0x3b, 0x3e, 0x18, - 0x18, 0x3b, 0x36, 0x13, 0xfe, 0xf8, 0x00, 0x01, 0xff, 0xce, 0x00, 0x00, 0x02, 0x47, 0x02, 0x22, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, - 0x04, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x12, - 0x12, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x32, 0xe8, 0x6b, 0xa0, 0x37, 0x75, 0xb0, 0xe1, - 0x73, 0xa2, 0x3b, 0x7f, 0x01, 0x18, 0x01, 0x0a, 0xaa, 0xaa, 0xfe, 0xee, 0xfe, 0xf0, 0xb3, 0xb3, 0x00, 0x01, 0xff, 0xbb, 0xff, 0x10, 0x02, 0x3b, 0x02, 0x22, - 0x00, 0x1a, 0x00, 0x30, 0x40, 0x2d, 0x11, 0x0b, 0x04, 0x03, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x01, - 0x01, 0x00, 0x62, 0x04, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x01, 0x00, 0x17, 0x16, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x1a, 0x01, 0x1a, 0x05, 0x0d, 0x16, 0x2b, - 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x03, 0x33, 0x17, 0x16, 0x16, 0x15, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, 0x06, - 0x06, 0x03, 0x1a, 0x22, 0x0c, 0x0d, 0x1b, 0x11, 0x2f, 0x3c, 0x16, 0x0d, 0x50, 0x90, 0x1b, 0x04, 0x02, 0x04, 0x0a, 0x18, 0x13, 0x7f, 0xa0, 0xfe, 0xb4, 0x2c, - 0x77, 0xf0, 0x05, 0x04, 0x75, 0x02, 0x04, 0x36, 0x2a, 0x18, 0x02, 0x22, 0xfd, 0x22, 0x50, 0x1d, 0x19, 0x43, 0x29, 0x01, 0x07, 0xfd, 0x90, 0x53, 0x4f, 0x00, - 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x01, 0xdf, 0x02, 0x22, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6d, 0x4d, - 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, - 0x37, 0x01, 0x23, 0x37, 0x21, 0x07, 0x01, 0x33, 0x07, 0x12, 0x11, 0x01, 0x18, 0xc2, 0x1a, 0x01, 0x70, 0x15, 0xfe, 0xed, 0xd5, 0x18, 0x59, 0x01, 0x57, 0x72, - 0x63, 0xfe, 0xb4, 0x73, 0x00, 0x01, 0xff, 0xff, 0xff, 0x62, 0x01, 0xa3, 0x02, 0xca, 0x00, 0x2c, 0x00, 0x37, 0x40, 0x34, 0x1d, 0x01, 0x01, 0x02, 0x01, 0x4c, - 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, 0x05, 0x06, 0x01, 0x00, 0x05, 0x00, 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, - 0x4e, 0x01, 0x00, 0x2b, 0x2a, 0x17, 0x16, 0x15, 0x13, 0x0e, 0x0d, 0x0c, 0x0b, 0x00, 0x2c, 0x01, 0x2c, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, - 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x37, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, 0x33, 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x15, - 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x15, 0xde, 0x56, 0x4d, 0x08, 0x14, 0x02, 0x03, 0x2a, 0x33, 0x17, 0x3b, 0x3c, - 0x0a, 0x1d, 0x11, 0x53, 0x5d, 0x2e, 0x18, 0x27, 0x2e, 0x09, 0x1d, 0x0c, 0x43, 0x36, 0x2a, 0x26, 0x04, 0x02, 0x13, 0x02, 0x03, 0x21, 0x1e, 0x9e, 0x41, 0x3c, - 0x1d, 0x24, 0x5c, 0x0a, 0x11, 0x07, 0x22, 0x22, 0x72, 0x28, 0x30, 0x86, 0x4c, 0x4c, 0x70, 0x1b, 0x29, 0x8a, 0x36, 0x37, 0x07, 0x03, 0x0d, 0x38, 0x29, 0x0b, - 0x18, 0x0b, 0x59, 0x0a, 0x10, 0x07, 0x19, 0x14, 0x70, 0x00, 0x00, 0x01, 0x00, 0xde, 0xff, 0x1d, 0x01, 0x49, 0x02, 0xf5, 0x00, 0x03, 0x00, 0x30, 0x4b, 0xb0, - 0x27, 0x50, 0x58, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x1b, 0x40, 0x0c, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, - 0x00, 0x00, 0x00, 0x6c, 0x01, 0x4e, 0x59, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x17, 0x11, 0x33, 0x11, 0xde, 0x6b, - 0xe3, 0x03, 0xd8, 0xfc, 0x28, 0x00, 0x00, 0x01, 0xff, 0xcd, 0xff, 0x62, 0x01, 0x65, 0x02, 0xca, 0x00, 0x2a, 0x00, 0x31, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x03, - 0x01, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6a, - 0x01, 0x4e, 0x2a, 0x28, 0x23, 0x22, 0x21, 0x20, 0x17, 0x15, 0x14, 0x13, 0x10, 0x06, 0x0d, 0x17, 0x2b, 0x07, 0x36, 0x36, 0x37, 0x37, 0x36, 0x36, 0x37, 0x35, - 0x26, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x23, 0x37, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x07, 0x06, 0x06, 0x15, 0x14, 0x33, 0x07, - 0x22, 0x06, 0x07, 0x07, 0x06, 0x06, 0x23, 0x23, 0x33, 0x33, 0x2a, 0x09, 0x1d, 0x0c, 0x43, 0x36, 0x2a, 0x26, 0x04, 0x03, 0x13, 0x02, 0x03, 0x4a, 0x15, 0x15, - 0x56, 0x4c, 0x09, 0x14, 0x02, 0x03, 0x61, 0x17, 0x3b, 0x40, 0x0a, 0x1d, 0x11, 0x58, 0x5d, 0x19, 0x2e, 0x01, 0x1b, 0x29, 0x89, 0x36, 0x36, 0x07, 0x04, 0x0d, - 0x37, 0x2a, 0x0a, 0x19, 0x0b, 0x59, 0x0a, 0x10, 0x07, 0x2d, 0x70, 0x45, 0x38, 0x1d, 0x24, 0x5d, 0x0a, 0x10, 0x07, 0x44, 0x72, 0x28, 0x30, 0x86, 0x4e, 0x4a, - 0x00, 0x01, 0x00, 0x35, 0x01, 0x0d, 0x02, 0x1a, 0x01, 0xb4, 0x00, 0x17, 0x00, 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, 0x02, 0x01, 0x13, 0x01, - 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, 0x00, 0x02, 0x00, 0x03, 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, - 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, 0x03, 0x51, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, - 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x01, 0x16, 0x25, 0x33, 0x17, 0x1c, - 0x3d, 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x2f, 0x25, 0x34, 0x16, 0x1d, 0x3c, 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x01, 0x2d, 0x10, 0x0b, 0x22, 0x19, 0x71, 0x35, 0x0b, - 0x14, 0x10, 0x0b, 0x22, 0x19, 0x71, 0x35, 0x0c, 0x00, 0x01, 0x00, 0x38, 0x01, 0x9f, 0x01, 0xa7, 0x03, 0x55, 0x00, 0x18, 0x00, 0x32, 0x40, 0x2f, 0x0b, 0x01, - 0x00, 0x01, 0x0a, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x69, 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, - 0x5f, 0x04, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x17, 0x24, 0x27, 0x05, 0x0c, 0x19, 0x2b, 0x13, 0x37, 0x37, 0x36, 0x36, 0x35, - 0x34, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x33, 0x07, 0x38, 0x11, 0x85, 0x30, 0x32, 0x19, 0x11, - 0x2a, 0x32, 0x31, 0x24, 0x51, 0x35, 0x3d, 0x47, 0x1f, 0x3d, 0x2d, 0x3f, 0xa9, 0x14, 0x01, 0x9f, 0x51, 0x6b, 0x27, 0x31, 0x1c, 0x14, 0x14, 0x28, 0x4d, 0x1c, - 0x1d, 0x3e, 0x2f, 0x29, 0x3b, 0x34, 0x21, 0x2e, 0x62, 0x00, 0x00, 0x01, 0x00, 0x48, 0x01, 0x97, 0x01, 0xa8, 0x03, 0x54, 0x00, 0x2b, 0x00, 0x4d, 0x40, 0x4a, - 0x1a, 0x01, 0x04, 0x05, 0x19, 0x01, 0x03, 0x04, 0x24, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x05, 0x00, 0x04, - 0x03, 0x05, 0x04, 0x69, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, - 0x01, 0x00, 0x51, 0x01, 0x00, 0x1e, 0x1c, 0x17, 0x15, 0x11, 0x0f, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x2b, 0x01, 0x2b, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, - 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, - 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xca, 0x25, 0x45, 0x18, 0x1d, 0x3d, 0x22, 0x23, 0x32, 0x19, 0x1f, - 0x3e, 0x11, 0x2c, 0x29, 0x2f, 0x19, 0x16, 0x16, 0x2f, 0x17, 0x28, 0x23, 0x4a, 0x2c, 0x33, 0x3c, 0x1b, 0x3e, 0x2c, 0x29, 0x22, 0x37, 0x58, 0x01, 0x97, 0x0f, - 0x0c, 0x5e, 0x10, 0x13, 0x1d, 0x1d, 0x12, 0x19, 0x4e, 0x1b, 0x1c, 0x14, 0x13, 0x11, 0x0f, 0x49, 0x17, 0x16, 0x1d, 0x2f, 0x1b, 0x33, 0x33, 0x0b, 0x04, 0x09, - 0x2c, 0x20, 0x31, 0x3e, 0x1d, 0x00, 0x00, 0x01, 0x00, 0x5b, 0x01, 0x9f, 0x01, 0x83, 0x03, 0x4b, 0x00, 0x0c, 0x00, 0x20, 0x40, 0x1d, 0x08, 0x07, 0x03, 0x03, - 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x00, 0x01, 0x4f, 0x11, 0x19, 0x02, 0x0c, 0x18, 0x2b, - 0x13, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, 0x03, 0x23, 0xd9, 0x07, 0x0f, 0x05, 0x09, 0x17, 0x07, 0x40, 0x32, 0xc3, 0x65, 0x5b, 0x78, - 0x02, 0x61, 0x1f, 0x35, 0x11, 0x07, 0x11, 0x05, 0x28, 0x51, 0x79, 0xfe, 0x54, 0x00, 0x00, 0x01, 0xfe, 0xfb, 0x00, 0x00, 0x01, 0x83, 0x02, 0xca, 0x00, 0x03, - 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, - 0x2b, 0x21, 0x01, 0x33, 0x01, 0xfe, 0xfb, 0x02, 0x13, 0x75, 0xfd, 0xef, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x02, 0x00, 0x32, 0x01, 0x9f, 0x01, 0xa8, 0x03, 0x4e, - 0x00, 0x0a, 0x00, 0x13, 0x00, 0x61, 0xb5, 0x10, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x11, 0x50, 0x58, 0x40, 0x1f, 0x00, 0x01, 0x02, 0x01, 0x85, 0x06, - 0x01, 0x04, 0x00, 0x00, 0x04, 0x71, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, 0x02, 0x02, 0x00, 0x60, 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, 0x1b, - 0x40, 0x1e, 0x00, 0x01, 0x02, 0x01, 0x85, 0x06, 0x01, 0x04, 0x00, 0x04, 0x86, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, 0x02, 0x02, 0x00, 0x60, - 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, 0x59, 0x40, 0x0f, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0c, 0x1a, 0x2b, 0x13, - 0x37, 0x23, 0x37, 0x13, 0x33, 0x03, 0x33, 0x07, 0x23, 0x07, 0x27, 0x33, 0x37, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0xd8, 0x10, 0xb6, 0x0f, 0xe8, 0x7f, 0x3b, - 0x3a, 0x11, 0x3a, 0x10, 0xa8, 0x55, 0x14, 0x05, 0x07, 0x07, 0x09, 0x19, 0x08, 0x01, 0x9f, 0x4a, 0x55, 0x01, 0x10, 0xfe, 0xed, 0x52, 0x4a, 0x9c, 0x50, 0x14, - 0x19, 0x18, 0x0d, 0x1f, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x49, 0x01, 0x97, 0x01, 0xac, 0x03, 0x4b, 0x00, 0x1e, 0x00, 0x47, 0x40, 0x44, 0x15, 0x10, 0x02, 0x02, - 0x05, 0x0f, 0x04, 0x02, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, - 0x02, 0x69, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x01, 0x00, 0x51, 0x01, 0x00, 0x19, 0x17, 0x14, 0x13, 0x12, - 0x11, 0x0d, 0x0b, 0x08, 0x06, 0x00, 0x1e, 0x01, 0x1e, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, - 0x22, 0x06, 0x07, 0x27, 0x37, 0x21, 0x07, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc5, 0x22, 0x43, 0x17, 0x19, 0x3c, 0x1c, 0x32, - 0x2a, 0x40, 0x10, 0x23, 0x0e, 0x25, 0x3a, 0x01, 0x02, 0x14, 0xad, 0x15, 0x08, 0x19, 0x13, 0x38, 0x45, 0x33, 0x58, 0x01, 0x97, 0x0d, 0x0d, 0x59, 0x0f, 0x11, - 0x2b, 0x1d, 0x36, 0x06, 0x04, 0x21, 0xcc, 0x5a, 0x44, 0x02, 0x04, 0x40, 0x35, 0x35, 0x4b, 0x27, 0x00, 0x01, 0x00, 0x62, 0x01, 0x9f, 0x01, 0xd2, 0x03, 0x4b, - 0x00, 0x06, 0x00, 0x24, 0x40, 0x21, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, - 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, 0x23, 0x37, 0x21, 0x07, 0x03, 0x62, 0xe2, 0xc6, 0x13, 0x01, - 0x41, 0x0f, 0xe3, 0x01, 0x9f, 0x01, 0x52, 0x5a, 0x49, 0xfe, 0x9d, 0x00, 0x00, 0x03, 0x00, 0x4c, 0x01, 0x95, 0x01, 0xae, 0x03, 0x55, 0x00, 0x18, 0x00, 0x24, - 0x00, 0x30, 0x00, 0x39, 0x40, 0x36, 0x2b, 0x13, 0x06, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x05, 0x01, 0x03, 0x00, - 0x00, 0x03, 0x59, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x03, 0x00, 0x51, 0x26, 0x25, 0x01, 0x00, 0x25, 0x30, 0x26, 0x30, 0x20, 0x1e, 0x0e, - 0x0c, 0x00, 0x18, 0x01, 0x18, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, - 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x07, 0x32, 0x36, 0x35, 0x34, 0x26, - 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, 0xe4, 0x49, 0x4f, 0x3b, 0x35, 0x19, 0x1c, 0x2b, 0x46, 0x28, 0x48, 0x46, 0x30, 0x2c, 0x20, 0x26, 0x66, 0x1d, 0x14, 0x1a, - 0x10, 0x14, 0x11, 0x18, 0x12, 0x1c, 0x1a, 0x1d, 0x15, 0x13, 0x16, 0x28, 0x1a, 0x01, 0x95, 0x42, 0x30, 0x2e, 0x3b, 0x12, 0x11, 0x2b, 0x1e, 0x27, 0x36, 0x1c, - 0x3a, 0x2c, 0x2b, 0x33, 0x10, 0x11, 0x30, 0x24, 0x43, 0x44, 0x01, 0x17, 0x09, 0x1a, 0x16, 0x0d, 0x16, 0x18, 0x14, 0x10, 0x18, 0xd2, 0x1f, 0x15, 0x15, 0x1c, - 0x0b, 0x07, 0x21, 0x1b, 0x14, 0x19, 0x00, 0x02, 0x00, 0x5d, 0x01, 0x95, 0x01, 0xb6, 0x03, 0x55, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, - 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x10, - 0x0f, 0x01, 0x00, 0x17, 0x15, 0x0f, 0x1c, 0x10, 0x1c, 0x09, 0x07, 0x00, 0x0e, 0x01, 0x0e, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, - 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xe7, 0x40, 0x4a, 0x13, 0x2f, 0x4f, 0x3c, - 0x43, 0x49, 0x30, 0x5c, 0x3a, 0x12, 0x1d, 0x14, 0x0b, 0x1c, 0x10, 0x1d, 0x14, 0x0c, 0x01, 0x95, 0x4d, 0x46, 0x30, 0x68, 0x5c, 0x39, 0x4d, 0x4a, 0x52, 0x87, - 0x50, 0x65, 0x27, 0x3c, 0x45, 0x1e, 0x2f, 0x24, 0x3c, 0x45, 0x21, 0x2f, 0x00, 0x02, 0x00, 0x5b, 0x01, 0x97, 0x01, 0xb7, 0x03, 0x54, 0x00, 0x1d, 0x00, 0x2a, - 0x00, 0x4b, 0x40, 0x48, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, 0x03, 0x02, 0x13, 0x01, 0x05, 0x03, 0x03, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, - 0x00, 0x03, 0x00, 0x05, 0x04, 0x03, 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x00, 0x04, 0x59, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x04, 0x00, - 0x51, 0x1f, 0x1e, 0x01, 0x00, 0x25, 0x23, 0x1e, 0x2a, 0x1f, 0x2a, 0x18, 0x16, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1d, 0x01, 0x1d, 0x08, 0x0c, 0x16, 0x2b, 0x13, - 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, - 0x06, 0x06, 0x27, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0xf0, 0x43, 0x52, 0x16, 0x39, 0x66, 0x4f, 0x14, 0x39, 0x0b, 0x15, - 0x0a, 0x29, 0x1c, 0x2d, 0x36, 0x1b, 0x07, 0x04, 0x0e, 0x30, 0x21, 0x37, 0x37, 0x2b, 0x4e, 0x34, 0x20, 0x22, 0x19, 0x14, 0x19, 0x1c, 0x0c, 0x16, 0x01, 0x97, - 0x57, 0x55, 0x26, 0x5e, 0x56, 0x37, 0x06, 0x04, 0x5c, 0x05, 0x09, 0x23, 0x34, 0x1a, 0x11, 0x1a, 0x40, 0x32, 0x31, 0x4f, 0x2d, 0x55, 0x2f, 0x1f, 0x17, 0x1b, - 0x1b, 0x23, 0x0d, 0x17, 0x1e, 0x00, 0x00, 0x02, 0x00, 0x5b, 0x01, 0x97, 0x01, 0xb1, 0x03, 0x54, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x4a, 0x40, 0x47, 0x12, 0x01, - 0x03, 0x04, 0x0b, 0x01, 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x03, - 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1e, 0x1d, 0x01, 0x00, 0x24, 0x22, - 0x1d, 0x28, 0x1e, 0x28, 0x17, 0x15, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x08, 0x0c, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, - 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x32, 0x36, 0x35, 0x34, - 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x01, 0x1c, 0x4b, 0x4a, 0x40, 0x79, 0x56, 0x13, 0x29, 0x0b, 0x0d, 0x2d, 0x10, 0x31, 0x3c, 0x23, 0x09, 0x03, 0x10, - 0x2f, 0x21, 0x37, 0x37, 0x2b, 0x4f, 0x1f, 0x1f, 0x22, 0x16, 0x17, 0x1e, 0x23, 0x19, 0x03, 0x54, 0x52, 0x46, 0x58, 0x84, 0x49, 0x05, 0x04, 0x5b, 0x05, 0x07, - 0x1e, 0x33, 0x1d, 0x10, 0x18, 0x41, 0x31, 0x32, 0x4e, 0x2d, 0xd3, 0x2b, 0x1f, 0x17, 0x1e, 0x2d, 0x20, 0x17, 0x1b, 0x00, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, - 0x01, 0xe5, 0x02, 0xfd, 0x00, 0x17, 0x00, 0x35, 0x40, 0x32, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, 0x03, 0x02, 0x02, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, - 0x02, 0x69, 0x04, 0x01, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x28, 0x4d, 0x06, 0x01, 0x05, 0x05, 0x27, 0x05, 0x4e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x17, - 0x11, 0x13, 0x25, 0x25, 0x11, 0x07, 0x07, 0x1b, 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, - 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x2a, 0x5b, 0x55, 0x0f, 0x5f, 0x0a, 0x15, 0x5f, 0x50, 0x22, 0x41, 0x16, 0x26, 0x0e, 0x22, 0x11, 0x19, 0x21, 0x07, 0x0a, - 0x6c, 0x19, 0x6b, 0x5c, 0x01, 0xb2, 0x47, 0x29, 0x29, 0x61, 0x51, 0x0e, 0x0a, 0x69, 0x06, 0x08, 0x1c, 0x22, 0x2a, 0x70, 0xfe, 0x4e, 0x00, 0x01, 0xff, 0x95, - 0xff, 0x10, 0x03, 0x36, 0x02, 0xfd, 0x00, 0x41, 0x00, 0xc5, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x03, 0x24, 0x14, 0x02, 0x05, 0x04, 0x36, 0x03, 0x02, 0x01, - 0x02, 0x35, 0x02, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x27, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, - 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, - 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x27, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, - 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x27, - 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, - 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x21, 0x01, 0x00, 0x3d, 0x3c, 0x39, 0x37, 0x34, 0x32, 0x2e, - 0x2d, 0x2c, 0x2b, 0x28, 0x26, 0x21, 0x1f, 0x1c, 0x1b, 0x18, 0x16, 0x11, 0x0f, 0x0a, 0x09, 0x06, 0x04, 0x00, 0x41, 0x01, 0x41, 0x0e, 0x0d, 0x16, 0x2b, 0x07, - 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, - 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x35, - 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x0e, 0x02, 0x16, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, - 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, - 0x06, 0x6b, 0x18, 0x6b, 0x69, 0x0a, 0x2e, 0x4f, 0x3e, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0xc1, 0x69, 0x0a, 0x2e, 0x4f, 0xf0, 0x0c, 0x76, 0x0a, - 0x28, 0x2b, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, - 0x20, 0x1e, 0x70, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x00, 0x03, 0xff, 0x95, 0xff, 0x10, - 0x03, 0xfe, 0x02, 0xfd, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x51, 0x01, 0x75, 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x03, 0x24, 0x14, - 0x02, 0x0d, 0x04, 0x36, 0x03, 0x02, 0x01, 0x10, 0x35, 0x02, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x1b, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x0e, 0x24, 0x14, 0x02, - 0x0d, 0x04, 0x36, 0x03, 0x02, 0x01, 0x10, 0x35, 0x02, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x3c, 0x07, 0x01, 0x04, 0x04, - 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x12, 0x01, 0x0d, 0x0d, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, - 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, - 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x3c, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x12, - 0x01, 0x0d, 0x0d, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, - 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2e, 0x50, 0x58, - 0x40, 0x3c, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x12, 0x01, 0x0d, 0x0d, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, - 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, - 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x39, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, 0x4d, 0x12, - 0x01, 0x0d, 0x0d, 0x0e, 0x61, 0x00, 0x0e, 0x0e, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, - 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x31, 0x4e, 0x4e, 0x43, - 0x42, 0x01, 0x00, 0x4e, 0x51, 0x4e, 0x51, 0x50, 0x4f, 0x49, 0x47, 0x42, 0x4d, 0x43, 0x4d, 0x3d, 0x3c, 0x39, 0x37, 0x34, 0x32, 0x2e, 0x2d, 0x2c, 0x2b, 0x28, - 0x26, 0x21, 0x1f, 0x1c, 0x1b, 0x18, 0x16, 0x11, 0x0f, 0x0a, 0x09, 0x06, 0x04, 0x00, 0x41, 0x01, 0x41, 0x14, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x27, 0x35, 0x16, - 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x36, 0x36, - 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, - 0x37, 0x13, 0x23, 0x03, 0x0e, 0x02, 0x01, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x13, 0x33, 0x03, 0x16, 0x33, 0x22, 0x1e, - 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, - 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0x6b, 0x18, 0x6b, 0x69, 0x0a, 0x2e, 0x4f, 0x3e, 0x33, 0x22, 0x1e, 0x1a, 0x1e, - 0x2d, 0x09, 0x64, 0xc1, 0x69, 0x0a, 0x2e, 0x4f, 0x03, 0x7e, 0x1f, 0x2b, 0x2f, 0x2a, 0x1d, 0x2c, 0x2b, 0xfe, 0xfe, 0x74, 0x93, 0x74, 0xf0, 0x0c, 0x76, 0x0a, - 0x28, 0x2b, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, - 0x20, 0x1e, 0x70, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x03, 0x56, 0x1b, 0x21, 0x2a, 0x2c, - 0x1a, 0x21, 0x27, 0x30, 0xfd, 0x9a, 0x02, 0x22, 0xfd, 0xde, 0x00, 0x02, 0xff, 0x95, 0xff, 0x10, 0x04, 0x05, 0x02, 0xfd, 0x00, 0x41, 0x00, 0x45, 0x01, 0x3c, - 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x03, 0x24, 0x14, 0x02, 0x05, 0x04, 0x36, 0x03, 0x02, 0x01, 0x0e, 0x35, 0x02, 0x02, 0x00, - 0x01, 0x04, 0x4c, 0x1b, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x0d, 0x24, 0x14, 0x02, 0x05, 0x04, 0x36, 0x03, 0x02, 0x01, 0x0e, 0x35, 0x02, 0x02, 0x00, 0x01, - 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, - 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, - 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x0c, - 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, - 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, 0x03, 0x03, 0x72, - 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, - 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x32, 0x00, 0x0d, 0x0d, 0x6c, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, - 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, - 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x29, 0x42, 0x42, 0x01, 0x00, 0x42, 0x45, 0x42, 0x45, 0x44, 0x43, 0x3d, 0x3c, - 0x39, 0x37, 0x34, 0x32, 0x2e, 0x2d, 0x2c, 0x2b, 0x28, 0x26, 0x21, 0x1f, 0x1c, 0x1b, 0x18, 0x16, 0x11, 0x0f, 0x0a, 0x09, 0x06, 0x04, 0x00, 0x41, 0x01, 0x41, - 0x11, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, - 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x0e, - 0x02, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x0e, 0x02, 0x25, 0x13, 0x33, 0x03, 0x16, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, - 0x09, 0x64, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, 0x63, 0x50, 0x22, - 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0x6b, 0x18, 0x6b, 0x69, 0x0a, 0x2e, 0x4f, 0x3e, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, - 0xc1, 0x69, 0x0a, 0x2e, 0x4f, 0x02, 0xa9, 0xa1, 0x93, 0xa1, 0xf0, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, - 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x70, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x0c, 0x76, 0x0a, 0x28, - 0x2b, 0x01, 0xd7, 0xfe, 0x13, 0x32, 0x52, 0x31, 0xf0, 0x02, 0xf8, 0xfd, 0x08, 0x00, 0xff, 0xff, 0xff, 0x96, 0xff, 0x10, 0x02, 0xb6, 0x02, 0xfd, 0x00, 0x26, - 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0xff, 0x96, 0xff, 0x10, 0x02, 0xbd, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, - 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x03, 0x36, 0x02, 0xfd, 0x00, 0x2b, 0x00, 0x42, 0x40, 0x3f, - 0x1b, 0x0b, 0x02, 0x02, 0x01, 0x1c, 0x0c, 0x02, 0x03, 0x02, 0x02, 0x4c, 0x04, 0x01, 0x01, 0x05, 0x01, 0x02, 0x03, 0x01, 0x02, 0x69, 0x09, 0x07, 0x02, 0x00, - 0x00, 0x03, 0x5f, 0x06, 0x01, 0x03, 0x03, 0x28, 0x4d, 0x0b, 0x0a, 0x02, 0x08, 0x08, 0x27, 0x08, 0x4e, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2b, 0x2a, 0x29, 0x11, - 0x11, 0x13, 0x25, 0x23, 0x13, 0x25, 0x25, 0x11, 0x0c, 0x07, 0x1f, 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, - 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x23, - 0x13, 0x23, 0x03, 0x29, 0x5c, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, - 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0x6b, 0x18, 0x6b, 0x5c, 0x93, 0x5c, 0xc1, 0x5c, 0x01, 0xb2, 0x47, 0x29, 0x29, - 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x70, 0xfe, 0x4e, 0x01, 0xb2, - 0xfe, 0x4e, 0xff, 0xff, 0x00, 0x29, 0x00, 0x00, 0x04, 0x0a, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x02, 0xc9, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x29, 0x00, 0x00, 0x04, 0x11, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x02, 0xc9, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x2a, 0x00, 0x00, 0x02, 0xb6, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2a, - 0x00, 0x00, 0x02, 0xbd, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0xff, 0xf5, - 0x01, 0x5c, 0x01, 0xb5, 0x01, 0x07, 0x00, 0x68, 0xff, 0xa6, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, - 0x00, 0x0e, 0xff, 0xff, 0x01, 0x36, 0x01, 0xab, 0x01, 0x07, 0x00, 0x62, 0xff, 0xb3, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, - 0x2b, 0x00, 0xff, 0xff, 0xff, 0xe2, 0xff, 0xff, 0x01, 0x51, 0x01, 0xb5, 0x01, 0x07, 0x00, 0x60, 0xff, 0xaa, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, - 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xf7, 0x01, 0x58, 0x01, 0xb4, 0x01, 0x07, 0x00, 0x61, 0xff, 0xb0, 0xfe, 0x60, 0x00, 0x09, - 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xff, 0x01, 0x57, 0x01, 0xae, 0x01, 0x07, 0x00, 0x64, 0xff, 0xaf, - 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xf7, 0x01, 0x5e, 0x01, 0xab, 0x01, 0x07, - 0x00, 0x65, 0xff, 0xb2, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x04, 0xff, 0xf7, 0x01, 0x60, - 0x01, 0xb4, 0x01, 0x07, 0x00, 0x69, 0xff, 0xa9, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0b, - 0xff, 0xff, 0x01, 0x7b, 0x01, 0xab, 0x01, 0x07, 0x00, 0x66, 0xff, 0xa9, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, - 0xff, 0xff, 0xff, 0xf6, 0xff, 0xf5, 0x01, 0x58, 0x01, 0xb5, 0x01, 0x07, 0x00, 0x67, 0xff, 0xaa, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x60, - 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x03, 0xff, 0xf7, 0x01, 0x59, 0x01, 0xb4, 0x01, 0x07, 0x00, 0x6a, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, - 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x3f, 0x01, 0x13, 0x01, 0x98, 0x02, 0xd3, 0x01, 0x07, 0x00, 0x68, 0xff, 0xe2, 0xff, 0x7e, - 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x47, 0x01, 0x1d, 0x01, 0x6f, 0x02, 0xc9, 0x01, 0x07, 0x00, 0x62, - 0xff, 0xec, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1b, 0x01, 0x1d, 0x01, 0x8a, 0x02, 0xd3, - 0x01, 0x07, 0x00, 0x60, 0xff, 0xe3, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x2f, 0x01, 0x15, - 0x01, 0x8f, 0x02, 0xd2, 0x01, 0x07, 0x00, 0x61, 0xff, 0xe7, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, - 0x00, 0x1c, 0x01, 0x1d, 0x01, 0x92, 0x02, 0xcc, 0x01, 0x07, 0x00, 0x64, 0xff, 0xea, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, - 0x2b, 0x00, 0xff, 0xff, 0x00, 0x37, 0x01, 0x15, 0x01, 0x9a, 0x02, 0xc9, 0x01, 0x07, 0x00, 0x65, 0xff, 0xee, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, - 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x44, 0x01, 0x15, 0x01, 0xa0, 0x02, 0xd2, 0x01, 0x07, 0x00, 0x69, 0xff, 0xe9, 0xff, 0x7e, 0x00, 0x09, - 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x01, 0x1d, 0x01, 0xbd, 0x02, 0xc9, 0x01, 0x07, 0x00, 0x66, 0xff, 0xeb, - 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x33, 0x01, 0x13, 0x01, 0x95, 0x02, 0xd3, 0x01, 0x07, - 0x00, 0x67, 0xff, 0xe7, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x41, 0x01, 0x15, 0x01, 0x97, - 0x02, 0xd2, 0x01, 0x07, 0x00, 0x6a, 0xff, 0xe6, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x8a, 0x00, 0xd3, 0x00, 0x18, 0x00, 0x66, 0x00, 0x06, 0x00, 0x02, 0x00, 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x89, 0x0e, 0x0c, - 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x5b, 0x00, 0xaf, 0x01, 0x36, 0x01, 0xfc, 0x02, 0x9b, 0x02, 0xb6, 0x02, 0xde, - 0x03, 0x10, 0x03, 0x3d, 0x03, 0x65, 0x03, 0x88, 0x03, 0xa4, 0x03, 0xc7, 0x03, 0xe2, 0x04, 0x2a, 0x04, 0x53, 0x04, 0x98, 0x04, 0xfc, 0x05, 0x3b, 0x05, 0x91, - 0x05, 0xfc, 0x06, 0x1f, 0x06, 0x88, 0x06, 0xf6, 0x07, 0x33, 0x07, 0x6d, 0x07, 0x83, 0x07, 0xae, 0x07, 0xc4, 0x08, 0x20, 0x08, 0xd7, 0x09, 0x0f, 0x09, 0x65, - 0x09, 0xae, 0x09, 0xe6, 0x0a, 0x15, 0x0a, 0x3f, 0x0a, 0x92, 0x0a, 0xbf, 0x0a, 0xea, 0x0b, 0x1c, 0x0b, 0x4a, 0x0b, 0x69, 0x0b, 0xa8, 0x0b, 0xde, 0x0c, 0x24, - 0x0c, 0x5f, 0x0c, 0xad, 0x0c, 0xf0, 0x0d, 0x46, 0x0d, 0x69, 0x0d, 0xa4, 0x0d, 0xd1, 0x0e, 0x20, 0x0e, 0x4e, 0x0e, 0x76, 0x0e, 0xa0, 0x0e, 0xc4, 0x0e, 0xde, - 0x0f, 0x02, 0x0f, 0x29, 0x0f, 0x49, 0x0f, 0x75, 0x0f, 0xec, 0x10, 0x6a, 0x10, 0xb4, 0x11, 0x31, 0x11, 0x8a, 0x12, 0x14, 0x12, 0xac, 0x12, 0xf0, 0x13, 0x25, - 0x13, 0x72, 0x13, 0xa5, 0x13, 0xbf, 0x14, 0x2a, 0x14, 0x78, 0x14, 0xbd, 0x15, 0x2f, 0x15, 0xa9, 0x15, 0xfe, 0x16, 0x53, 0x16, 0xb2, 0x17, 0x0b, 0x17, 0x38, - 0x17, 0x87, 0x17, 0xb3, 0x17, 0xf9, 0x18, 0x22, 0x18, 0x80, 0x18, 0xa5, 0x18, 0xfd, 0x19, 0x42, 0x19, 0x84, 0x19, 0xea, 0x1a, 0x15, 0x1a, 0x30, 0x1a, 0x86, - 0x1a, 0xd9, 0x1a, 0xfe, 0x1b, 0x63, 0x1b, 0xa7, 0x1c, 0x0c, 0x1c, 0x6e, 0x1c, 0xb0, 0x1d, 0x72, 0x1e, 0xa5, 0x1f, 0xab, 0x1f, 0xb7, 0x1f, 0xc3, 0x20, 0x27, - 0x20, 0x33, 0x20, 0x3f, 0x20, 0x4b, 0x20, 0x57, 0x20, 0x66, 0x20, 0x75, 0x20, 0x84, 0x20, 0x93, 0x20, 0xa2, 0x20, 0xb1, 0x20, 0xc0, 0x20, 0xcf, 0x20, 0xde, - 0x20, 0xed, 0x20, 0xfc, 0x21, 0x0b, 0x21, 0x1a, 0x21, 0x29, 0x21, 0x38, 0x21, 0x47, 0x21, 0x56, 0x21, 0x65, 0x21, 0x74, 0x21, 0x83, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, 0xbc, 0xcf, 0x60, 0xc2, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xcc, 0xa2, - 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc4, 0x58, 0xfd, 0x5c, 0xfe, 0x7b, 0x0a, 0xdc, 0x04, 0x26, 0x00, 0x03, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x58, 0x00, 0x5f, 0x01, 0x04, 0x00, 0x00, 0x01, 0x1f, 0x00, 0x0b, 0x01, 0xc5, 0x00, 0x62, 0x02, 0x86, 0x00, 0x14, 0x02, 0x27, 0x00, 0x19, - 0x03, 0x58, 0x00, 0x38, 0x02, 0xc4, 0x00, 0x21, 0x00, 0xff, 0x00, 0x62, 0x01, 0x53, 0x00, 0x24, 0x01, 0x55, 0xff, 0xba, 0x02, 0x22, 0x00, 0x55, 0x02, 0x3c, - 0x00, 0x35, 0x01, 0x1f, 0xff, 0xd0, 0x01, 0x43, 0x00, 0x11, 0x01, 0x1f, 0x00, 0x08, 0x01, 0xa8, 0xff, 0xd3, 0x02, 0x27, 0x00, 0x20, 0x02, 0x27, 0x00, 0x59, - 0x02, 0x27, 0xff, 0xe8, 0x02, 0x27, 0x00, 0x07, 0x02, 0x27, 0xff, 0xf4, 0x02, 0x27, 0x00, 0x0d, 0x02, 0x27, 0x00, 0x2b, 0x02, 0x27, 0x00, 0x26, 0x02, 0x27, - 0x00, 0x1b, 0x02, 0x27, 0x00, 0x2a, 0x01, 0x1f, 0x00, 0x08, 0x01, 0x1f, 0xff, 0xca, 0x02, 0x3c, 0x00, 0x35, 0x02, 0x3c, 0x00, 0x35, 0x02, 0x3c, 0x00, 0x35, - 0x01, 0xcb, 0x00, 0x4d, 0x03, 0x58, 0x00, 0x2d, 0x02, 0x74, 0xff, 0xc4, 0x02, 0x6c, 0x00, 0x1a, 0x02, 0x65, 0x00, 0x3b, 0x02, 0xa5, 0x00, 0x1a, 0x02, 0x1f, - 0x00, 0x1a, 0x02, 0x15, 0x00, 0x1a, 0x02, 0xb2, 0x00, 0x3b, 0x02, 0xbd, 0x00, 0x1a, 0x01, 0x7f, 0xff, 0xe3, 0x01, 0x4e, 0xff, 0x62, 0x02, 0x65, 0x00, 0x1a, - 0x02, 0x06, 0x00, 0x1a, 0x03, 0x70, 0x00, 0x1a, 0x02, 0xf6, 0x00, 0x19, 0x02, 0xdb, 0x00, 0x3b, 0x02, 0x62, 0x00, 0x1a, 0x02, 0xdb, 0x00, 0x3b, 0x02, 0x6c, - 0x00, 0x1a, 0x02, 0x12, 0x00, 0x14, 0x02, 0x14, 0x00, 0x51, 0x02, 0xb4, 0x00, 0x44, 0x02, 0x4e, 0x00, 0x5a, 0x03, 0x7e, 0x00, 0x5a, 0x02, 0x62, 0xff, 0xc7, - 0x02, 0x34, 0x00, 0x5b, 0x02, 0x18, 0xff, 0xe2, 0x01, 0x4b, 0xff, 0xee, 0x01, 0xa8, 0x00, 0x6c, 0x01, 0x4b, 0xff, 0xbd, 0x02, 0x27, 0x00, 0x11, 0x01, 0x90, - 0xff, 0xa5, 0x01, 0x44, 0x00, 0x91, 0x02, 0x50, 0x00, 0x2c, 0x02, 0x53, 0x00, 0x12, 0x01, 0xe4, 0x00, 0x2c, 0x02, 0x52, 0x00, 0x2c, 0x02, 0x2d, 0x00, 0x2c, - 0x01, 0x76, 0xff, 0x96, 0x02, 0x54, 0x00, 0x12, 0x02, 0x5c, 0x00, 0x12, 0x01, 0x2b, 0x00, 0x12, 0x01, 0x2b, 0xff, 0x80, 0x02, 0x38, 0x00, 0x12, 0x01, 0x2b, - 0x00, 0x11, 0x03, 0x89, 0x00, 0x12, 0x02, 0x5c, 0x00, 0x12, 0x02, 0x49, 0x00, 0x2c, 0x02, 0x53, 0xff, 0xdf, 0x02, 0x52, 0x00, 0x2c, 0x01, 0xa6, 0x00, 0x12, - 0x01, 0xdb, 0x00, 0x0b, 0x01, 0x9a, 0x00, 0x2e, 0x02, 0x5c, 0x00, 0x36, 0x02, 0x00, 0x00, 0x32, 0x03, 0x14, 0x00, 0x3d, 0x02, 0x16, 0xff, 0xce, 0x02, 0x07, - 0xff, 0xbb, 0x01, 0xd5, 0xff, 0xee, 0x01, 0x63, 0xff, 0xff, 0x02, 0x27, 0x00, 0xde, 0x01, 0x63, 0xff, 0xcd, 0x02, 0x3c, 0x00, 0x35, 0x01, 0x7b, 0x00, 0x38, - 0x01, 0x7b, 0x00, 0x48, 0x01, 0x7b, 0x00, 0x5b, 0x00, 0x7d, 0xfe, 0xfb, 0x01, 0x7b, 0x00, 0x32, 0x01, 0x7b, 0x00, 0x49, 0x01, 0x7b, 0x00, 0x62, 0x01, 0x7b, - 0x00, 0x4c, 0x01, 0x7b, 0x00, 0x5d, 0x01, 0x7b, 0x00, 0x5b, 0x01, 0x7b, 0x00, 0x5b, 0x01, 0x76, 0x00, 0x2a, 0x02, 0xc9, 0xff, 0x95, 0x03, 0xe8, 0xff, 0x95, - 0x03, 0xe8, 0xff, 0x95, 0x02, 0x9e, 0xff, 0x96, 0x02, 0x9e, 0xff, 0x96, 0x02, 0xc9, 0x00, 0x29, 0x03, 0xf2, 0x00, 0x29, 0x03, 0xf2, 0x00, 0x29, 0x02, 0x9e, - 0x00, 0x2a, 0x02, 0x9e, 0x00, 0x2a, 0x01, 0x7b, 0x00, 0x03, 0x00, 0x0e, 0xff, 0xe2, 0xff, 0xf8, 0xff, 0xe1, 0xff, 0xfb, 0x00, 0x04, 0x00, 0x0b, 0xff, 0xf6, - 0x00, 0x03, 0x00, 0x3f, 0x00, 0x47, 0x00, 0x1b, 0x00, 0x2f, 0x00, 0x1c, 0x00, 0x37, 0x00, 0x44, 0x00, 0x4d, 0x00, 0x33, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x0a, 0xf0, 0xfd, 0x5c, 0xfd, 0x9b, 0x0a, 0xdc, 0x03, 0xe8, 0x00, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, 0x02, 0x50, 0x02, 0xbc, 0x00, 0x05, 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, 0xff, 0xf0, 0x00, 0x4b, - 0x02, 0x8a, 0x02, 0x58, 0x00, 0x4a, 0x01, 0x5e, 0x00, 0x32, 0x01, 0x48, 0x00, 0x00, 0x02, 0x0b, 0x08, 0x02, 0x04, 0x05, 0x04, 0x09, 0x02, 0x04, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x01, 0xa1, 0x00, 0x20, 0x00, 0x7e, 0x04, 0x2d, - 0xfe, 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x22, 0x02, 0xca, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, - 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, 0x21, 0xb0, - 0x00, 0x59, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, 0x02, 0x2c, - 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, - 0x14, 0x43, 0x42, 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, 0x04, 0x50, 0x78, - 0xb2, 0x02, 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, 0x20, 0xb0, 0x02, 0x43, - 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, - 0x2c, 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x1b, 0x20, 0x64, - 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, - 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, 0x38, - 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x20, 0xb0, - 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, - 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, 0x1b, 0xb0, - 0x02, 0x25, 0xb0, 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, 0xb0, 0x1e, 0x50, - 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, - 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, 0x20, 0x45, 0x20, 0xb0, - 0x04, 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, 0x59, 0xb0, 0x01, 0x60, 0x2d, - 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, - 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, 0xb0, 0x08, 0x43, 0x20, 0x8a, 0x20, - 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, - 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, 0x43, 0x2b, - 0xb2, 0x00, 0x02, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, 0x62, 0x66, - 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, - 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, 0x0e, 0x00, 0x43, - 0x45, 0x42, 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, - 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, - 0x64, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, - 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, - 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, - 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, 0x0c, 0x00, - 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, - 0x2c, 0xb0, 0x01, 0x60, 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, 0xb0, 0x00, - 0x52, 0x58, 0x20, 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, 0x00, 0x63, 0x8a, - 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, - 0x59, 0x24, 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x1b, 0x21, 0x59, 0x24, - 0xb0, 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, 0x61, 0x42, 0xb0, 0x11, 0x2b, - 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, - 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x23, 0xb0, 0x01, 0x61, 0x20, - 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, - 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x20, - 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, 0x00, 0x13, - 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, - 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, - 0x13, 0x00, 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, - 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, - 0x2c, 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, - 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, - 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x5d, - 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, - 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, - 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, - 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, 0x01, 0x00, 0x11, - 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, - 0x2c, 0xb1, 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, 0xb0, 0x25, 0x2c, 0xb1, - 0x04, 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, 0x28, 0x2c, 0xb1, 0x07, 0x20, - 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, - 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x01, 0x60, 0xb0, 0x2e, 0x2a, - 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, - 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, 0x20, 0x47, - 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, - 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, - 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, - 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x34, 0x2c, 0x20, - 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, - 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, - 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, - 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, - 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, 0x20, 0x3c, - 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, - 0x00, 0x43, 0x61, 0xb0, 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb0, - 0x02, 0x25, 0x49, 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, 0x01, 0x15, 0x14, - 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, - 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, - 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, - 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, - 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, - 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, - 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, - 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, 0x02, 0x25, - 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, - 0xb0, 0x01, 0x63, 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, 0x25, 0xb0, 0x02, - 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, 0x60, 0x64, 0x23, 0xb0, - 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, - 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x3c, 0x38, 0x2d, 0xb0, 0x3d, - 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, - 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, 0x2e, - 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, - 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, - 0x59, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, 0x20, 0x3c, - 0x8a, 0x38, 0x23, 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, - 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, - 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, - 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, - 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, - 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, - 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, - 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, 0x20, 0x20, - 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, - 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, - 0x26, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, 0x20, 0x3c, 0x20, - 0x2e, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, - 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, - 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, 0xb0, 0x06, 0x43, 0xb0, 0x02, - 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, - 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, - 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, 0x23, 0x38, - 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, - 0x3a, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x23, - 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, - 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, - 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, 0xb0, 0x4c, 0x2c, 0xb0, - 0x39, 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, - 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, - 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x53, 0x2c, 0xb2, 0x00, 0x00, - 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, - 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x59, - 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x43, - 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, - 0x01, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x61, - 0x2c, 0xb2, 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, 0x48, 0x2b, 0x2d, 0xb0, - 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, - 0xb0, 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x69, 0x2c, 0xb3, 0x01, 0x00, - 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, - 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x44, - 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, - 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, - 0xb0, 0x73, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, 0x2c, 0xb0, - 0x00, 0x16, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x77, - 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, - 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, - 0x2d, 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, - 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, - 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, - 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, - 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x87, - 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, 0x01, 0x3f, - 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, - 0xb0, 0x06, 0x1b, 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, 0x50, 0x78, 0xb1, - 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, 0xb9, 0x08, 0x00, 0x08, - 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, 0x00, 0x49, 0x39, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, - 0x14, 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, 0x02, 0x56, 0x06, 0x4e, 0x04, 0x3e, 0x08, 0x32, 0x06, 0x24, 0x07, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x07, 0x42, - 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x52, 0x02, 0x46, 0x06, 0x38, 0x04, 0x2b, 0x05, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, - 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, 0x13, 0xc0, 0x0f, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, - 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x09, - 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, - 0x28, 0x01, 0x88, 0x51, 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, 0xba, 0x08, - 0x80, 0x00, 0x01, 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, 0x06, 0x7a, 0x06, - 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x50, 0x02, 0x40, 0x06, 0x34, 0x04, 0x26, 0x05, 0x09, 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, - 0x00, 0x44, 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x73, 0x02, 0xca, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd6, 0xff, 0xf6, 0x02, 0x2c, - 0xff, 0xf6, 0xff, 0x10, 0x00, 0x99, 0x00, 0x99, 0x00, 0x7d, 0x00, 0x7d, 0x02, 0x46, 0x02, 0x46, 0x00, 0x00, 0x00, 0x00, 0x02, 0x4f, 0x02, 0x50, 0xff, 0xf8, - 0x00, 0x00, 0x00, 0x94, 0x00, 0x94, 0x00, 0x78, 0x00, 0x78, 0x02, 0xca, 0xff, 0xf6, 0x02, 0xf8, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, - 0x02, 0xfd, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x99, 0x00, 0x99, 0x00, 0x7d, 0x00, 0x7d, 0x02, 0x46, 0x00, 0x00, 0x02, 0x50, 0xff, 0xf8, 0x00, 0x78, - 0x00, 0x78, 0x00, 0x65, 0x00, 0x65, 0x01, 0x68, 0x00, 0xee, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x78, 0x00, 0x78, - 0x00, 0x65, 0x00, 0x65, 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x94, 0x00, 0x94, 0x00, 0x78, 0x00, 0x78, 0x02, 0xca, 0x00, 0x00, 0x02, 0xf8, 0x02, 0x22, 0x00, 0x00, - 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xf9, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x60, 0x00, 0x60, 0x00, 0x48, 0x00, 0x48, 0x01, 0x29, 0xff, 0x7d, - 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x33, 0xff, 0x73, 0x01, 0x69, 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x60, 0x00, 0x60, 0x00, 0x48, - 0x00, 0x48, 0x02, 0xcb, 0x01, 0x9f, 0x02, 0xe7, 0x02, 0x67, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe8, 0x01, 0x95, 0x02, 0xe8, 0x02, 0x6d, 0x01, 0x19, 0x00, 0x8f, - 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, - 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x16, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x3c, - 0x00, 0xde, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x2a, 0x01, 0x1a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, 0x01, 0x44, - 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x26, 0x01, 0x98, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, - 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x4e, - 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x41, - 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, - 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, - 0x00, 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, - 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, - 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, - 0x00, 0x6e, 0x00, 0x73, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x20, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, - 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x6f, - 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x49, 0x00, 0x74, - 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, - 0x00, 0x20, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x20, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x56, - 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, - 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, - 0x00, 0x28, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, - 0x00, 0x62, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6f, - 0x00, 0x6c, 0x00, 0x64, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x03, 0x00, 0x00, 0xff, 0xf4, 0x00, 0x00, 0xff, 0x9c, - 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, - 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x22, 0x00, 0x3b, 0x00, 0x01, - 0x00, 0x42, 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x02, 0x00, 0x18, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x32, - 0x00, 0x40, 0x00, 0x4e, 0x00, 0x4e, 0x00, 0x2a, 0x00, 0x32, 0x00, 0x40, 0x00, 0x4e, 0x00, 0x4e, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x21, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x15, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x1f, - 0x00, 0x01, 0x02, 0x73, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x25, 0x00, 0x01, 0x02, 0x7d, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x27, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, - 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, - 0x6b, 0x65, 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x06, 0xc8, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, - 0x00, 0x0a, 0x01, 0x08, 0x00, 0x01, 0x00, 0x38, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x6a, 0x00, 0xf4, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x8c, 0x00, 0xb4, - 0x00, 0x92, 0x00, 0x98, 0x00, 0xb4, 0x00, 0xaa, 0x00, 0xb4, 0x00, 0xba, 0x00, 0xc4, 0x00, 0xc4, 0x00, 0xce, 0x00, 0xd8, 0x00, 0xf4, 0x00, 0xde, 0x00, 0xe4, - 0x00, 0xee, 0x00, 0xee, 0x00, 0xee, 0x00, 0xf4, 0x00, 0x01, 0x00, 0x17, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, - 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, - 0x00, 0x58, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, 0x37, 0xff, 0xd8, 0x00, 0x38, 0xff, 0xd8, 0x00, 0x3a, 0xff, 0xc4, 0x00, 0x01, - 0x00, 0x2b, 0x00, 0x4b, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xec, 0x00, 0x0f, 0xff, 0xec, 0x00, 0x01, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, - 0x00, 0x04, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x39, - 0xff, 0xec, 0x00, 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x20, - 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, 0x00, 0x07, 0xff, 0xec, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x6c, 0x00, 0x02, - 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, - 0x03, 0xd8, 0x00, 0x04, 0x00, 0x00, 0x04, 0x26, 0x04, 0xe4, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xf6, - 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, 0xff, 0xe2, - 0xff, 0xce, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xd8, 0xff, 0xec, 0x00, 0x00, 0xff, 0xd8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, - 0xff, 0xf6, 0xff, 0xec, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xce, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0xff, 0xe2, 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xce, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, - 0x00, 0x0a, 0xff, 0xc4, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xc4, - 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x8e, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x25, 0x00, 0x03, - 0x00, 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, - 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x4c, - 0x00, 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x1f, 0x00, 0x03, - 0x00, 0x03, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x09, 0x00, 0x13, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, - 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x22, 0x00, 0x22, 0x00, 0x01, 0x00, 0x24, 0x00, 0x24, 0x00, 0x07, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, - 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x08, 0x00, 0x30, 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, 0x14, 0x00, 0x32, - 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, 0x05, 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x39, 0x00, 0x39, - 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x06, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0d, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x02, - 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x10, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0c, 0x00, 0x57, - 0x00, 0x58, 0x00, 0x04, 0x00, 0x59, 0x00, 0x59, 0x00, 0x10, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, - 0x00, 0x15, 0x00, 0x02, 0x00, 0x23, 0x00, 0x03, 0x00, 0x03, 0x00, 0x11, 0x00, 0x08, 0x00, 0x08, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x0d, - 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, - 0x00, 0x05, 0x00, 0x24, 0x00, 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x28, 0x00, 0x02, 0x00, 0x30, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x32, 0x00, 0x02, - 0x00, 0x35, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x08, 0x00, 0x3b, - 0x00, 0x3b, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x04, 0x00, 0x44, 0x00, 0x46, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, - 0x00, 0x15, 0x00, 0x48, 0x00, 0x48, 0x00, 0x0d, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x03, 0x00, 0x50, 0x00, 0x50, 0x00, 0x01, 0x00, 0x51, 0x00, 0x51, 0x00, 0x03, - 0x00, 0x52, 0x00, 0x52, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x03, 0x00, 0x54, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0e, 0x00, 0x56, - 0x00, 0x56, 0x00, 0x03, 0x00, 0x57, 0x00, 0x58, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x07, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x5e, - 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x15, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, - 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x50, 0x00, 0x92, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, - 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x45, 0x57, 0x45, 0x20, 0x00, 0x18, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, - 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x20, 0x66, 0x72, 0x61, 0x63, 0x00, 0x26, 0x6c, 0x69, 0x67, 0x61, 0x00, 0x30, 0x6c, 0x6f, - 0x63, 0x6c, 0x00, 0x36, 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x3c, - 0x00, 0x4a, 0x00, 0x5e, 0x00, 0x76, 0x00, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x12, 0x00, 0x06, 0x00, 0x6b, - 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x01, 0x00, 0x06, 0x00, 0x47, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x70, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, - 0x00, 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x01, - 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x01, 0x00, 0x76, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, - 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x00, 0x89, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x66, - 0x00, 0x02, 0x00, 0x0a, 0x00, 0x38, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6e, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4d, - 0x00, 0x6d, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x70, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x47, - 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x73, 0x00, 0x03, 0x00, 0x6b, 0x00, 0x4d, 0x00, 0x72, 0x00, 0x03, 0x00, 0x6b, - 0x00, 0x4a, 0x00, 0x74, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x71, 0x00, 0x02, 0x00, 0x6b, 0x00, 0x01, 0x00, 0x02, 0x00, 0x47, - 0x00, 0x6b}; - -const inline Font FONTS[FONT_COUNT] = {{.data = FONT_REGULAR_DATA, .length = std::size(FONT_REGULAR_DATA)}, - {.data = FONT_ITALICS_DATA, .length = std::size(FONT_ITALICS_DATA)}, - {.data = FONT_BOLD_DATA, .length = std::size(FONT_BOLD_DATA)}, - {.data = FONT_BOLD_ITALICS_DATA, .length = std::size(FONT_BOLD_ITALICS_DATA)}}; diff --git a/src/animation_preview.cpp b/src/animation_preview.cpp new file mode 100644 index 0000000..17be4b5 --- /dev/null +++ b/src/animation_preview.cpp @@ -0,0 +1,316 @@ +#include "animation_preview.h" + +#include + +#include "imgui.h" +#include "math.h" +#include "tool.h" +#include "types.h" + +using namespace anm2ed::document_manager; +using namespace anm2ed::settings; +using namespace anm2ed::canvas; +using namespace anm2ed::playback; +using namespace anm2ed::resources; +using namespace anm2ed::types; +using namespace glm; + +namespace anm2ed::animation_preview +{ + constexpr auto TARGET_SIZE = vec2(32, 32); + constexpr auto PIVOT_SIZE = vec2(8, 8); + constexpr auto POINT_SIZE = vec2(4, 4); + constexpr auto NULL_RECT_SIZE = vec2(100); + constexpr auto TRIGGER_TEXT_COLOR = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); + + AnimationPreview::AnimationPreview() : Canvas(vec2()) + { + } + + void AnimationPreview::update(DocumentManager& manager, Settings& settings, Resources& resources, Playback& playback) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& reference = document.reference; + auto animation = document.animation_get(); + auto& pan = document.previewPan; + auto& zoom = document.previewZoom; + auto& backgroundColor = settings.previewBackgroundColor; + auto& axesColor = settings.previewAxesColor; + auto& gridColor = settings.previewGridColor; + auto& gridSize = settings.previewGridSize; + auto& gridOffset = settings.previewGridOffset; + auto& zoomStep = settings.viewZoomStep; + auto& isGrid = settings.previewIsGrid; + auto& overlayTransparency = settings.previewOverlayTransparency; + auto& overlayIndex = document.overlayIndex; + auto& isRootTransform = settings.previewIsRootTransform; + auto& isPivots = settings.previewIsPivots; + auto& isAxes = settings.previewIsAxes; + auto& isIcons = settings.previewIsIcons; + auto& isAltIcons = settings.previewIsAltIcons; + auto& isBorder = settings.previewIsBorder; + auto& tool = settings.tool; + auto& shaderLine = resources.shaders[shader::LINE]; + auto& shaderAxes = resources.shaders[shader::AXIS]; + auto& shaderGrid = resources.shaders[shader::GRID]; + auto& shaderTexture = resources.shaders[shader::TEXTURE]; + + if (ImGui::Begin("Animation Preview", &settings.windowIsAnimationPreview)) + { + + auto childSize = ImVec2(imgui::row_widget_width_get(4), + (ImGui::GetTextLineHeightWithSpacing() * 4) + (ImGui::GetStyle().WindowPadding.y * 2)); + + if (ImGui::BeginChild("##Grid Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + + ImGui::Checkbox("Grid", &isGrid); + ImGui::SameLine(); + ImGui::ColorEdit4("Color", value_ptr(gridColor), ImGuiColorEditFlags_NoInputs); + ImGui::InputInt2("Size", value_ptr(gridSize)); + ImGui::InputInt2("Offset", value_ptr(gridOffset)); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##View Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + ImGui::InputFloat("Zoom", &zoom, zoomStep, zoomStep, "%.0f%%"); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + if (ImGui::Button("Center View", widgetSize)) pan = vec2(); + ImGui::SameLine(); + ImGui::Button("Fit", widgetSize); + ImGui::TextUnformatted(std::format(POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y).c_str()); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##Background Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + ImGui::ColorEdit4("Background", value_ptr(backgroundColor), ImGuiColorEditFlags_NoInputs); + ImGui::SameLine(); + ImGui::Checkbox("Axes", &isAxes); + ImGui::SameLine(); + ImGui::ColorEdit4("Color", value_ptr(axesColor), ImGuiColorEditFlags_NoInputs); + + std::vector animationNames{}; + animationNames.emplace_back("None"); + for (auto& animation : anm2.animations.items) + animationNames.emplace_back(animation.name); + + imgui::combo_strings("Overlay", &overlayIndex, animationNames); + + ImGui::InputFloat("Alpha", &overlayTransparency, 0, 0, "%.0f"); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##Helpers Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + auto helpersChildSize = ImVec2(imgui::row_widget_width_get(2), ImGui::GetContentRegionAvail().y); + + if (ImGui::BeginChild("##Helpers Child 1", helpersChildSize)) + { + ImGui::Checkbox("Root Transform", &isRootTransform); + ImGui::Checkbox("Pivots", &isPivots); + ImGui::Checkbox("Icons", &isIcons); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##Helpers Child 2", helpersChildSize)) + { + ImGui::Checkbox("Alt Icons", &isAltIcons); + ImGui::Checkbox("Border", &isBorder); + } + ImGui::EndChild(); + } + ImGui::EndChild(); + + auto cursorScreenPos = ImGui::GetCursorScreenPos(); + + size_set(to_vec2(ImGui::GetContentRegionAvail())); + bind(); + viewport_set(); + clear(backgroundColor); + if (isAxes) axes_render(shaderAxes, zoom, pan, axesColor); + if (isGrid) grid_render(shaderGrid, zoom, pan, gridSize, gridOffset, gridColor); + + auto frameTime = reference.frameTime > -1 && !playback.isPlaying ? reference.frameTime : playback.time; + + if (animation) + { + auto transform = transform_get(zoom, pan); + auto root = animation->rootAnimation.frame_generate(playback.time, anm2::ROOT); + + if (isRootTransform) + transform *= math::quad_model_parent_get(root.position, {}, math::percent_to_unit(root.scale), root.rotation); + + if (isIcons && root.isVisible && animation->rootAnimation.isVisible) + { + auto rootTransform = transform * math::quad_model_get(TARGET_SIZE, root.position, TARGET_SIZE * 0.5f, + math::percent_to_unit(root.scale), root.rotation); + + texture_render(shaderTexture, resources.icons[icon::TARGET].id, rootTransform, color::GREEN); + } + + for (auto& id : animation->layerOrder) + { + auto& layerAnimation = animation->layerAnimations.at(id); + if (!layerAnimation.isVisible) continue; + + auto& layer = anm2.content.layers.at(id); + + if (auto frame = layerAnimation.frame_generate(frameTime, anm2::LAYER); frame.isVisible) + { + auto spritesheet = anm2.spritesheet_get(layer.spritesheetID); + if (!spritesheet) continue; + + auto& texture = spritesheet->texture; + if (!texture.is_valid()) continue; + + auto layerTransform = transform * math::quad_model_get(frame.size, frame.position, frame.pivot, + math::percent_to_unit(frame.scale), frame.rotation); + + auto inset = 0.5f / vec2(texture.size); // needed to avoid bleed + auto uvMin = frame.crop / vec2(texture.size) + inset; + auto uvMax = (frame.crop + frame.size) / vec2(texture.size) - inset; + auto vertices = math::uv_vertices_get(uvMin, uvMax); + + texture_render(shaderTexture, texture.id, layerTransform, frame.tint, frame.offset, vertices.data()); + + if (isBorder) rect_render(shaderLine, layerTransform, color::RED); + + if (isPivots) + { + auto pivotTransform = + transform * math::quad_model_get(PIVOT_SIZE, frame.position, PIVOT_SIZE * 0.5f, + math::percent_to_unit(frame.scale), frame.rotation); + texture_render(shaderTexture, resources.icons[icon::PIVOT].id, pivotTransform, color::RED); + } + } + } + + if (isIcons) + { + for (auto& [id, nullAnimation] : animation->nullAnimations) + { + if (!nullAnimation.isVisible) continue; + + auto& isShowRect = anm2.content.nulls[id].isShowRect; + + if (auto frame = nullAnimation.frame_generate(frameTime, anm2::NULL_); frame.isVisible) + { + auto icon = isShowRect ? icon::POINT : icon::TARGET; + auto& size = isShowRect ? POINT_SIZE : TARGET_SIZE; + auto& color = id == reference.itemID && reference.itemType == anm2::NULL_ ? color::RED : color::BLUE; + + auto nullTransform = transform * math::quad_model_get(size, frame.position, size * 0.5f, + math::percent_to_unit(frame.scale), frame.rotation); + + texture_render(shaderTexture, resources.icons[icon].id, nullTransform, color); + + if (isShowRect) + { + auto rectTransform = + transform * math::quad_model_get(NULL_RECT_SIZE, frame.position, NULL_RECT_SIZE * 0.5f, + math::percent_to_unit(frame.scale), frame.rotation); + + rect_render(shaderLine, rectTransform, color); + } + } + } + } + } + + unbind(); + + ImGui::Image(texture, to_imvec2(size)); + + isPreviewHovered = ImGui::IsItemHovered(); + + if (animation && animation->triggers.isVisible) + { + if (auto trigger = animation->triggers.frame_generate(frameTime, anm2::TRIGGER); trigger.isVisible) + { + auto clipMin = ImGui::GetItemRectMin(); + auto clipMax = ImGui::GetItemRectMax(); + auto drawList = ImGui::GetWindowDrawList(); + auto textPos = to_imvec2(to_vec2(cursorScreenPos) + to_vec2(ImGui::GetStyle().WindowPadding)); + + drawList->PushClipRect(clipMin, clipMax); + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE_LARGE); + drawList->AddText(textPos, ImGui::GetColorU32(TRIGGER_TEXT_COLOR), + anm2.content.events.at(trigger.eventID).name.c_str()); + ImGui::PopFont(); + drawList->PopClipRect(); + } + } + + if (isPreviewHovered) + { + ImGui::SetKeyboardFocusHere(-1); + + mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos)); + + auto isRound = settings.propertiesIsRound; + auto isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); + auto isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); + auto isLeft = imgui::chord_repeating(ImGuiKey_LeftArrow); + auto isRight = imgui::chord_repeating(ImGuiKey_RightArrow); + auto isUp = imgui::chord_repeating(ImGuiKey_UpArrow); + auto isDown = imgui::chord_repeating(ImGuiKey_DownArrow); + auto isMouseRightDown = ImGui::IsMouseDown(ImGuiMouseButton_Right); + auto mouseDelta = to_vec2(ImGui::GetIO().MouseDelta); + auto mouseWheel = ImGui::GetIO().MouseWheel; + auto isZoomIn = imgui::chord_repeating(imgui::string_to_chord(settings.shortcutZoomIn)); + auto isZoomOut = imgui::chord_repeating(imgui::string_to_chord(settings.shortcutZoomOut)); + auto isMod = ImGui::IsKeyDown(ImGuiMod_Shift); + auto frame = document.frame_get(); + auto useTool = tool; + auto step = isMod ? step::FAST : step::NORMAL; + auto isClick = isMouseDown; + + if (isMouseMiddleDown) useTool = tool::PAN; + if (tool == tool::MOVE && isMouseRightDown) useTool = tool::SCALE; + if (tool == tool::SCALE && isMouseRightDown) useTool = tool::MOVE; + + switch (useTool) + { + case tool::PAN: + if (isClick || isMouseMiddleDown) pan += isRound ? vec2(ivec2(mouseDelta)) : mouseDelta; + break; + case tool::MOVE: + if (!frame) break; + if (isClick) frame->position = isRound ? vec2(ivec2(mousePos)) : mousePos; + if (isLeft) frame->position.x -= step; + if (isRight) frame->position.x += step; + if (isUp) frame->position.y -= step; + if (isDown) frame->position.y += step; + break; + case tool::SCALE: + if (!frame) break; + if (isClick) frame->scale += isRound ? vec2(ivec2(mouseDelta)) : mouseDelta; + break; + case tool::ROTATE: + if (!frame) break; + if (isClick) frame->rotation += isRound ? (int)mouseDelta.y : mouseDelta.y; + break; + default: + break; + } + + if (mouseWheel != 0 || isZoomIn || isZoomOut) + zoom_set(zoom, pan, mousePos, (mouseWheel > 0 || isZoomIn) ? zoomStep : -zoomStep); + } + } + ImGui::End(); + } +} diff --git a/src/animation_preview.h b/src/animation_preview.h new file mode 100644 index 0000000..278c7eb --- /dev/null +++ b/src/animation_preview.h @@ -0,0 +1,21 @@ +#pragma once + +#include "canvas.h" +#include "document_manager.h" +#include "playback.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::animation_preview +{ + class AnimationPreview : public canvas::Canvas + { + bool isPreviewHovered{}; + glm::vec2 mousePos{}; + + public: + AnimationPreview(); + void update(document_manager::DocumentManager& manager, settings::Settings& settings, + resources::Resources& resources, playback::Playback& playback); + }; +} \ No newline at end of file diff --git a/src/animations.cpp b/src/animations.cpp new file mode 100644 index 0000000..f41f35a --- /dev/null +++ b/src/animations.cpp @@ -0,0 +1,293 @@ +#include "animations.h" + +#include +#include + +#include "imgui.h" + +using namespace anm2ed::document_manager; +using namespace anm2ed::settings; +using namespace anm2ed::resources; +using namespace anm2ed::types; + +namespace anm2ed::animations +{ + void Animations::update(DocumentManager& manager, Settings& settings, Resources& resources) + { + auto document = manager.get(); + auto& anm2 = document->anm2; + auto& reference = document->reference; + auto& selection = document->selectedAnimations; + storage.UserData = &selection; + storage.AdapterSetItemSelected = imgui::external_storage_set; + + if (ImGui::Begin("Animations", &settings.windowIsAnimations)) + { + auto childSize = imgui::size_with_footer_get(); + + if (ImGui::BeginChild("##Animations Child", childSize, ImGuiChildFlags_Borders)) + { + ImGuiMultiSelectIO* io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, selection.size(), + anm2.animations.items.size()); + storage.ApplyRequests(io); + + for (auto [i, animation] : std::views::enumerate(anm2.animations.items)) + { + ImGui::PushID(i); + + auto isDefault = anm2.animations.defaultAnimation == animation.name; + auto isReferenced = reference.animationIndex == i; + auto isSelected = selection.contains(i); + + auto font = isDefault && isReferenced ? font::BOLD_ITALICS + : isDefault ? font::BOLD + : isReferenced ? font::ITALICS + : font::REGULAR; + + ImGui::PushFont(resources.fonts[font].get(), font::SIZE); + ImGui::SetNextItemSelectionUserData(i); + if (imgui::selectable_input_text(animation.name, + std::format("###Document #{} Animation #{}", manager.selected, i), + animation.name, isSelected)) + if (!isReferenced) reference = {(int)i}; + ImGui::PopFont(); + + if (ImGui::BeginItemTooltip()) + { + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); + ImGui::TextUnformatted(animation.name.c_str()); + ImGui::PopFont(); + + if (isDefault) + { + + ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); + ImGui::TextUnformatted("(Default Animation)"); + ImGui::PopFont(); + } + + ImGui::TextUnformatted(std::format("Length: {}", animation.frameNum).c_str()); + ImGui::TextUnformatted(std::format("Loop: {}", animation.isLoop).c_str()); + + ImGui::EndTooltip(); + } + + if (ImGui::BeginDragDropSource()) + { + std::vector sorted = {}; + ImGui::SetDragDropPayload("Animation Drag Drop", sorted.data(), sorted.size() * sizeof(int)); + for (auto& index : sorted) + ImGui::TextUnformatted(anm2.animations.items[index].name.c_str()); + ImGui::EndDragDropSource(); + } + + if (ImGui::BeginDragDropTarget()) + { + if (auto payload = ImGui::AcceptDragDropPayload("Animation Drag Drop")) + { + auto count = payload->DataSize / sizeof(int); + auto data = (int*)(payload->Data); + std::vector indices(data, data + count); + //std::vector destinationIndices = vector::indices_move(anm2.animations.items, indices, i); + + selection.clear(); + /* + for (const auto& index : destinationIndices) + selection.insert((int)index); + */ + } + ImGui::EndDragDropTarget(); + } + + ImGui::PopID(); + } + + io = ImGui::EndMultiSelect(); + storage.ApplyRequests(io); + } + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(5); + + imgui::shortcut(settings.shortcutAdd, true); + if (ImGui::Button("Add", widgetSize)) + { + anm2::Animation animation; + if (anm2::Animation* referenceAnimation = document->animation_get()) + { + for (auto [id, layerAnimation] : referenceAnimation->layerAnimations) + animation.layerAnimations[id] = anm2::Item(); + animation.layerOrder = referenceAnimation->layerOrder; + for (auto [id, nullAnimation] : referenceAnimation->nullAnimations) + animation.nullAnimations[id] = anm2::Item(); + } + animation.rootAnimation.frames.emplace_back(anm2::Frame()); + + auto index = selection.empty() ? (int)anm2.animations.items.size() - 1 : (int)std::ranges::max(selection) + 1; + anm2.animations.items.insert(anm2.animations.items.begin() + index, animation); + selection = {index}; + reference = {index}; + } + imgui::set_item_tooltip_shortcut("Add a new animation.", settings.shortcutAdd); + + ImGui::SameLine(); + + ImGui::BeginDisabled(selection.empty()); + { + + imgui::shortcut(settings.shortcutDuplicate, true); + if (ImGui::Button("Duplicate", widgetSize)) + { + auto duplicated = selection; + auto duplicatedEnd = std::ranges::max(duplicated); + for (auto& id : duplicated) + { + anm2.animations.items.insert(anm2.animations.items.begin() + duplicatedEnd, anm2.animations.items[id]); + selection.insert(++duplicatedEnd); + selection.erase(id); + } + } + imgui::set_item_tooltip_shortcut("Duplicate the selected animation(s).", settings.shortcutDuplicate); + + ImGui::SameLine(); + + ImGui::BeginDisabled(selection.size() != 1); + { + if (ImGui::Button("Merge", widgetSize)) + { + ImGui::OpenPopup("Merge Animations"); + mergeSelection.clear(); + mergeTarget = *selection.begin(); + } + } + ImGui::EndDisabled(); + + imgui::set_item_tooltip_shortcut( + "Open the merge popup.\nUsing the shortcut will merge the animations with\nthe last " + "configured merge settings.", + settings.shortcutMerge); + + ImGui::SameLine(); + + imgui::shortcut(settings.shortcutRemove, true); + if (ImGui::Button("Remove", widgetSize)) + { + /* + auto selectionErase = set::to_size_t(selection); + if (selectionErase.contains(document->reference.animationIndex)) document->reference.animationIndex = -1; + vector::range_erase(anm2.animations.items, selectionErase); + */ + selection.clear(); + } + imgui::set_item_tooltip_shortcut("Remove the selected animation(s).", settings.shortcutDuplicate); + + ImGui::SameLine(); + + ImGui::BeginDisabled(selection.size() != 1); + { + imgui::shortcut(settings.shortcutDefault, true); + if (ImGui::Button("Default", widgetSize)) + anm2.animations.defaultAnimation = anm2.animations.items[*selection.begin()].name; + imgui::set_item_tooltip_shortcut("Set the selected animation as the default.", settings.shortcutDuplicate); + } + ImGui::EndDisabled(); + } + ImGui::EndDisabled(); + + auto viewport = ImGui::GetMainViewport(); + + ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_None, ImVec2(0.5f, 0.5f)); + ImGui::SetNextWindowSize(to_imvec2(to_vec2(viewport->Size) * 0.5f)); + + if (ImGui::BeginPopupModal("Merge Animations", nullptr, ImGuiWindowFlags_NoResize)) + { + auto merge_close = [&]() + { + mergeSelection.clear(); + ImGui::CloseCurrentPopup(); + }; + + auto& type = settings.mergeType; + auto& isDeleteAnimationsAfter = settings.mergeIsDeleteAnimationsAfter; + + mergeStorage.UserData = &mergeSelection; + mergeStorage.AdapterSetItemSelected = imgui::external_storage_set; + + auto footerSize = ImVec2(0, imgui::footer_height_get()); + auto optionsSize = imgui::child_size_get(2, true); + auto deleteAfterSize = imgui::child_size_get(); + auto animationsSize = + ImVec2(0, ImGui::GetContentRegionAvail().y - + (optionsSize.y + deleteAfterSize.y + footerSize.y + ImGui::GetStyle().ItemSpacing.y * 3)); + + if (ImGui::BeginChild("Animations", animationsSize, ImGuiChildFlags_Borders)) + { + ImGuiMultiSelectIO* io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, mergeSelection.size(), + anm2.animations.items.size()); + mergeStorage.ApplyRequests(io); + + for (auto [i, animation] : std::views::enumerate(anm2.animations.items)) + { + auto isSelected = mergeSelection.contains(i); + + ImGui::PushID(i); + + ImGui::SetNextItemSelectionUserData(i); + ImGui::Selectable(animation.name.c_str(), isSelected); + + ImGui::PopID(); + } + + io = ImGui::EndMultiSelect(); + mergeStorage.ApplyRequests(io); + } + ImGui::EndChild(); + + if (ImGui::BeginChild("Merge Options", optionsSize, ImGuiChildFlags_Borders)) + { + + auto size = ImVec2(optionsSize.x * 0.5f, optionsSize.y - ImGui::GetStyle().WindowPadding.y * 2); + + if (ImGui::BeginChild("Merge Options 1", size)) + { + ImGui::RadioButton("Append Frames", &type, merge::APPEND); + ImGui::RadioButton("Prepend Frames", &type, merge::PREPEND); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("Merge Options 2", size)) + { + ImGui::RadioButton("Replace Frames", &type, merge::REPLACE); + ImGui::RadioButton("Ignore Frames", &type, merge::IGNORE); + } + ImGui::EndChild(); + } + ImGui::EndChild(); + + if (ImGui::BeginChild("Merge Delete After", deleteAfterSize, ImGuiChildFlags_Borders)) + ImGui::Checkbox("Delete Animations After", &isDeleteAnimationsAfter); + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + if (ImGui::Button("Merge", widgetSize)) + { + /* + std::set sources = set::to_set(mergeSelection); + const auto merged = anm2.animations.merge(mergeTarget, sources, (MergeType)type, isDeleteAnimationsAfter); + selection = {merged}; + reference = {merged}; + */ + merge_close(); + } + ImGui::SameLine(); + if (ImGui::Button("Close", widgetSize)) merge_close(); + + ImGui::EndPopup(); + } + } + ImGui::End(); + } +} \ No newline at end of file diff --git a/src/animations.h b/src/animations.h new file mode 100644 index 0000000..a06a582 --- /dev/null +++ b/src/animations.h @@ -0,0 +1,20 @@ +#pragma once + +#include "document_manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::animations +{ + class Animations + { + ImGuiSelectionExternalStorage mergeStorage{}; + ImGuiSelectionExternalStorage storage{}; + std::set mergeSelection{}; + int mergeTarget{}; + + public: + void update(document_manager::DocumentManager& manager, settings::Settings& settings, + resources::Resources& resources); + }; +} \ No newline at end of file diff --git a/src/anm2.cpp b/src/anm2.cpp index 5808bce..a36d94c 100644 --- a/src/anm2.cpp +++ b/src/anm2.cpp @@ -1,1289 +1,855 @@ #include "anm2.h" +#include + +#include "filesystem.h" +#include "math.h" +#include "texture.h" +#include "util.h" +#include "xml.h" + using namespace tinyxml2; +using namespace anm2ed::filesystem; +using namespace anm2ed::texture; +using namespace anm2ed::types; +using namespace anm2ed::util; -static void _anm2_created_on_set(Anm2* self) { - auto now = std::chrono::system_clock::now(); - std::time_t time = std::chrono::system_clock::to_time_t(now); - std::tm localTime = *std::localtime(&time); - - std::ostringstream timeString; - timeString << std::put_time(&localTime, ANM2_CREATED_ON_FORMAT); - self->createdOn = timeString.str(); -} - -static void _anm2_frame_serialize(Anm2Frame* frame, Anm2Type type, XMLDocument* document = nullptr, XMLElement* addElement = nullptr, - std::string* string = nullptr) { - XMLDocument localDocument; - XMLDocument* useDocument = document ? document : &localDocument; - - XMLElement* element = type == ANM2_TRIGGER ? useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]) - : useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]); - - if (type == ANM2_TRIGGER) { - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_EVENT_ID], frame->eventID); // EventID - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_AT_FRAME], frame->atFrame); // AtFrame - } else { - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_POSITION], frame->position.x); // XPosition - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_POSITION], frame->position.y); // YPosition - - if (type == ANM2_LAYER) { - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_PIVOT], frame->pivot.x); // XPivot - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_PIVOT], frame->pivot.y); // YPivot - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_CROP], frame->crop.x); // XCrop - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_CROP], frame->crop.y); // YCrop - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_WIDTH], frame->size.x); // Width - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_HEIGHT], frame->size.y); // Height - } - - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_SCALE], frame->scale.x); // XScale - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_SCALE], frame->scale.y); // YScale - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DELAY], frame->delay); /* Delay */ - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], frame->isVisible); // Visible - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_TINT], FLOAT_TO_UINT8(frame->tintRGBA.r)); // RedTint - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], FLOAT_TO_UINT8(frame->tintRGBA.g)); // GreenTint - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], FLOAT_TO_UINT8(frame->tintRGBA.b)); // BlueTint - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], FLOAT_TO_UINT8(frame->tintRGBA.a)); // AlphaTint - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], FLOAT_TO_UINT8(frame->offsetRGB.r)); // RedOffset - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], FLOAT_TO_UINT8(frame->offsetRGB.g)); // GreenOffset - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], FLOAT_TO_UINT8(frame->offsetRGB.b)); // BlueOffset - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ROTATION], frame->rotation); // Rotation - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_INTERPOLATED], frame->isInterpolated); // Interpolated - } - - if (addElement) - addElement->InsertEndChild(element); - - if (string && !document) { - useDocument->InsertEndChild(element); - XMLPrinter printer; - useDocument->Print(&printer); - *string = std::string(printer.CStr()); - } -} - -static void _anm2_animation_serialize(Anm2Animation* animation, XMLDocument* document = nullptr, XMLElement* addElement = nullptr, - std::string* string = nullptr) { - XMLDocument localDocument; - XMLDocument* useDocument = document ? document : &localDocument; - - // Animation - XMLElement* element = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION]); - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], animation->name.c_str()); // Name - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_FRAME_NUM], animation->frameNum); // FrameNum - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_LOOP], animation->isLoop); // Loop - - // RootAnimation - XMLElement* rootElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ROOT_ANIMATION]); - - for (auto& frame : animation->rootAnimation.frames) - _anm2_frame_serialize(&frame, ANM2_ROOT, useDocument, rootElement); - - element->InsertEndChild(rootElement); - - // LayerAnimations - XMLElement* layersElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATIONS]); - - for (auto& id : animation->layerOrder) { - // LayerAnimation - Anm2Item& layerAnimation = animation->layerAnimations[id]; - XMLElement* layerElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION]); - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_LAYER_ID], id); // LayerId - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], layerAnimation.isVisible); // Visible - - for (auto& frame : layerAnimation.frames) - _anm2_frame_serialize(&frame, ANM2_LAYER, useDocument, layerElement); - - layersElement->InsertEndChild(layerElement); - } - - element->InsertEndChild(layersElement); - - // Nulls - XMLElement* nullsElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATIONS]); - - for (auto& [id, null] : animation->nullAnimations) { - // NullAnimation - XMLElement* nullElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION]); - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NULL_ID], id); // NullId - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], null.isVisible); // Visible - - for (auto& frame : null.frames) - _anm2_frame_serialize(&frame, ANM2_NULL, useDocument, nullElement); - - nullsElement->InsertEndChild(nullElement); - } - - element->InsertEndChild(nullsElement); - - // Triggers - XMLElement* triggersElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS]); - - for (auto& trigger : animation->triggers.frames) - _anm2_frame_serialize(&trigger, ANM2_TRIGGER, useDocument, triggersElement); - - element->InsertEndChild(triggersElement); - - if (addElement) - addElement->InsertEndChild(element); - - if (string && !document) { - useDocument->InsertEndChild(element); - XMLPrinter printer; - useDocument->Print(&printer); - *string = std::string(printer.CStr()); - } -} - -bool anm2_serialize(Anm2* self, const std::string& path) { - XMLDocument document; - - if (!self || path.empty()) - return false; - - if (self->version == 0) - _anm2_created_on_set(self); - - self->path = path; - self->version++; - - // AnimatedActor - XMLElement* animatedActorElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATED_ACTOR]); - document.InsertFirstChild(animatedActorElement); - - // Info - XMLElement* infoElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_INFO]); - infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_CREATED_BY], self->createdBy.c_str()); // CreatedBy - infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_CREATED_ON], self->createdOn.c_str()); // CreatedOn - infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VERSION], self->version); // Version - infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_FPS], self->fps); // FPS - animatedActorElement->InsertEndChild(infoElement); - - // Content - XMLElement* contentElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_CONTENT]); - - // Spritesheets - XMLElement* spritesheetsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEETS]); - - for (auto& [id, spritesheet] : self->spritesheets) { - // Spritesheet - XMLElement* spritesheetElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET]); - spritesheetElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_PATH], spritesheet.path.c_str()); // Path - spritesheetElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID - spritesheetsElement->InsertEndChild(spritesheetElement); - } - - contentElement->InsertEndChild(spritesheetsElement); - - // Layers - XMLElement* layersElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYERS]); - - for (auto& [id, layer] : self->layers) { - // Layer - XMLElement* layerElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER]); - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], layer.name.c_str()); // Path - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SPRITESHEET_ID], layer.spritesheetID); // SpritesheetId - layersElement->InsertEndChild(layerElement); - } - - contentElement->InsertEndChild(layersElement); - - // Nulls - XMLElement* nullsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULLS]); - - for (auto& [id, null] : self->nulls) { - // Null - XMLElement* nullElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL]); - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], null.name.c_str()); // Name - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID - if (null.isShowRect) - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SHOW_RECT], null.isShowRect); // ShowRect - nullsElement->InsertEndChild(nullElement); - } - - contentElement->InsertEndChild(nullsElement); - - // Events - XMLElement* eventsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENTS]); - - for (auto& [id, event] : self->events) { - // Event - XMLElement* eventElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT]); - eventElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], event.name.c_str()); // Name - eventElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID - eventsElement->InsertEndChild(eventElement); - } - - contentElement->InsertEndChild(eventsElement); - - animatedActorElement->InsertEndChild(contentElement); - - // Animations - XMLElement* animationsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATIONS]); - animationsElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DEFAULT_ANIMATION], self->defaultAnimation.c_str()); // DefaultAnimation - - for (auto& animation : self->animations) - _anm2_animation_serialize(&animation, &document, animationsElement); - - animatedActorElement->InsertEndChild(animationsElement); - - XMLError error = document.SaveFile(path.c_str()); - - if (error != XML_SUCCESS) { - log_error(std::format(ANM2_WRITE_ERROR, path)); - return false; - } - - log_info(std::format(ANM2_WRITE_INFO, path)); - - return true; -} - -static void _anm2_frame_deserialize(Anm2Frame* frame, const XMLElement* element) { - for (const XMLAttribute* attribute = element->FirstAttribute(); attribute; attribute = attribute->Next()) { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { - case ANM2_ATTRIBUTE_X_POSITION: - frame->position.x = std::atof(attribute->Value()); - break; // XPosition - case ANM2_ATTRIBUTE_Y_POSITION: - frame->position.y = std::atof(attribute->Value()); - break; // YPosition - case ANM2_ATTRIBUTE_X_PIVOT: - frame->pivot.x = std::atof(attribute->Value()); - break; // XPivot - case ANM2_ATTRIBUTE_Y_PIVOT: - frame->pivot.y = std::atof(attribute->Value()); - break; // YPivot - case ANM2_ATTRIBUTE_X_CROP: - frame->crop.x = std::atof(attribute->Value()); - break; // XCrop - case ANM2_ATTRIBUTE_Y_CROP: - frame->crop.y = std::atof(attribute->Value()); - break; // YCrop - case ANM2_ATTRIBUTE_WIDTH: - frame->size.x = std::atof(attribute->Value()); - break; // Width - case ANM2_ATTRIBUTE_HEIGHT: - frame->size.y = std::atof(attribute->Value()); - break; // Height - case ANM2_ATTRIBUTE_X_SCALE: - frame->scale.x = std::atof(attribute->Value()); - break; // XScale - case ANM2_ATTRIBUTE_Y_SCALE: - frame->scale.y = std::atof(attribute->Value()); - break; // YScale - case ANM2_ATTRIBUTE_RED_TINT: - frame->tintRGBA.r = UINT8_TO_FLOAT(std::atoi(attribute->Value())); - break; // RedTint - case ANM2_ATTRIBUTE_GREEN_TINT: - frame->tintRGBA.g = UINT8_TO_FLOAT(std::atoi(attribute->Value())); - break; // GreenTint - case ANM2_ATTRIBUTE_BLUE_TINT: - frame->tintRGBA.b = UINT8_TO_FLOAT(std::atoi(attribute->Value())); - break; // BlueTint - case ANM2_ATTRIBUTE_ALPHA_TINT: - frame->tintRGBA.a = UINT8_TO_FLOAT(std::atoi(attribute->Value())); - break; // AlphaTint - case ANM2_ATTRIBUTE_RED_OFFSET: - frame->offsetRGB.r = UINT8_TO_FLOAT(std::atoi(attribute->Value())); - break; // RedOffset - case ANM2_ATTRIBUTE_GREEN_OFFSET: - frame->offsetRGB.g = UINT8_TO_FLOAT(std::atoi(attribute->Value())); - break; // GreenOffset - case ANM2_ATTRIBUTE_BLUE_OFFSET: - frame->offsetRGB.b = UINT8_TO_FLOAT(std::atoi(attribute->Value())); - break; // BlueOffset - case ANM2_ATTRIBUTE_ROTATION: - frame->rotation = std::atof(attribute->Value()); - break; // Rotation - case ANM2_ATTRIBUTE_VISIBLE: - frame->isVisible = string_to_bool(attribute->Value()); - break; // Visible - case ANM2_ATTRIBUTE_INTERPOLATED: - frame->isInterpolated = string_to_bool(attribute->Value()); - break; // Interpolated - case ANM2_ATTRIBUTE_AT_FRAME: - frame->atFrame = std::atoi(attribute->Value()); - break; // AtFrame - case ANM2_ATTRIBUTE_DELAY: - frame->delay = std::atoi(attribute->Value()); - break; // Delay - case ANM2_ATTRIBUTE_EVENT_ID: - frame->eventID = std::atoi(attribute->Value()); - break; // EventID - default: - break; - } - } -} - -static void _anm2_animation_deserialize(Anm2Animation* animation, const XMLElement* element) { - auto frames_deserialize = [&](const XMLElement* itemElement, Anm2Item* item) { - // Frame - for (const XMLElement* frame = itemElement->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]); frame; - frame = frame->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME])) - _anm2_frame_deserialize(&item->frames.emplace_back(Anm2Frame()), frame); - }; - - int id{}; - - for (const XMLAttribute* attribute = element->FirstAttribute(); attribute; attribute = attribute->Next()) { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { - case ANM2_ATTRIBUTE_NAME: - animation->name = std::string(attribute->Value()); - break; // Name - case ANM2_ATTRIBUTE_FRAME_NUM: - animation->frameNum = std::atoi(attribute->Value()); - break; // FrameNum - case ANM2_ATTRIBUTE_LOOP: - animation->isLoop = string_to_bool(attribute->Value()); - break; // Loop - default: - break; - } - } - - // RootAnimation - if (const XMLElement* rootAnimation = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ROOT_ANIMATION])) - frames_deserialize(rootAnimation, &animation->rootAnimation); - - // LayerAnimations - if (const XMLElement* layerAnimations = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATIONS])) { - // LayerAnimation - for (const XMLElement* layerAnimation = layerAnimations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION]); layerAnimation; - layerAnimation = layerAnimation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION])) { - Anm2Item layerAnimationItem; - - for (const XMLAttribute* attribute = layerAnimation->FirstAttribute(); attribute; attribute = attribute->Next()) { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { - case ANM2_ATTRIBUTE_LAYER_ID: - id = std::atoi(attribute->Value()); - break; // LayerID - case ANM2_ATTRIBUTE_VISIBLE: - layerAnimationItem.isVisible = string_to_bool(attribute->Value()); - break; // Visible - default: - break; - } - } - - frames_deserialize(layerAnimation, &layerAnimationItem); - animation->layerAnimations[id] = layerAnimationItem; - animation->layerOrder.push_back(id); - } - } - - // NullAnimations - if (const XMLElement* nullAnimations = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATIONS])) { - // NullAnimation - for (const XMLElement* nullAnimation = nullAnimations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION]); nullAnimation; - nullAnimation = nullAnimation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION])) { - Anm2Item nullAnimationItem; - - for (const XMLAttribute* attribute = nullAnimation->FirstAttribute(); attribute; attribute = attribute->Next()) { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { - case ANM2_ATTRIBUTE_NULL_ID: - id = std::atoi(attribute->Value()); - break; - case ANM2_ATTRIBUTE_VISIBLE: - nullAnimationItem.isVisible = string_to_bool(attribute->Value()); - break; - default: - break; - } - } - - frames_deserialize(nullAnimation, &nullAnimationItem); - animation->nullAnimations[id] = nullAnimationItem; - } - } - - // Triggers - if (const XMLElement* triggers = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS])) { - // Trigger - for (const XMLElement* trigger = triggers->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]); trigger; - trigger = trigger->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER])) - _anm2_frame_deserialize(&animation->triggers.frames.emplace_back(Anm2Frame()), trigger); - } -} - -bool anm2_deserialize(Anm2* self, const std::string& path, bool isTextures) { - if (!self) - return false; - - if (path.empty()) { - log_error(ANM2_EMPTY_ERROR); - return false; - } - - XMLDocument document; - if (document.LoadFile(path.c_str()) != XML_SUCCESS) { - log_error(std::format(ANM2_PARSE_ERROR, path, document.ErrorStr())); - return false; - } - - anm2_new(self); - self->path = path; - int id{}; - - WorkingDirectory workingDirectory(path); - - const XMLElement* root = document.RootElement(); - - // Info - if (const XMLElement* info = root->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_INFO])) { - for (const XMLAttribute* attribute = info->FirstAttribute(); attribute; attribute = attribute->Next()) { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { - case ANM2_ATTRIBUTE_CREATED_BY: - self->createdBy = std::string(attribute->Value()); - break; // CreatedBy - case ANM2_ATTRIBUTE_CREATED_ON: - self->createdOn = std::string(attribute->Value()); - break; // CreatedOn - case ANM2_ATTRIBUTE_VERSION: - self->version = std::atoi(attribute->Value()); - break; // Version - case ANM2_ATTRIBUTE_FPS: - self->fps = std::atoi(attribute->Value()); - break; // FPS - default: - break; - } - } - } - - // Content - if (const XMLElement* content = root->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_CONTENT])) { - // Spritesheets - if (const XMLElement* spritesheets = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEETS])) { - for (const XMLElement* spritesheet = spritesheets->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET]); spritesheet; - spritesheet = spritesheet->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET])) { - Anm2Spritesheet addSpritesheet; - - for (const XMLAttribute* attribute = spritesheet->FirstAttribute(); attribute; attribute = attribute->Next()) { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { - case ANM2_ATTRIBUTE_PATH: - // Spritesheet paths from Isaac Rebirth are made with the assumption that - // the paths are case-insensitive (as the game was developed on Windows) - // However when using the resource dumper, the spritesheet paths are all lowercase (on Linux anyways) - // If the check doesn't work, set the spritesheet path to lowercase - // If the check doesn't work, replace backslashes with slashes - // At the minimum this should make all textures be able to be loaded on Linux - // If it doesn't work beyond that then that's on the user :^) - addSpritesheet.path = attribute->Value(); - if (!path_exists(addSpritesheet.path)) - addSpritesheet.path = string_to_lowercase(addSpritesheet.path); - if (!path_exists(addSpritesheet.path)) - addSpritesheet.path = string_backslash_replace(addSpritesheet.path); - if (isTextures) - texture_from_path_init(&addSpritesheet.texture, addSpritesheet.path); - break; - case ANM2_ATTRIBUTE_ID: - id = std::atoi(attribute->Value()); - break; - default: - break; - } - } - - self->spritesheets[id] = addSpritesheet; - } - } - - // Layers - if (const XMLElement* layers = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYERS])) { - for (const XMLElement* layer = layers->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER]); layer; - layer = layer->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER])) { - Anm2Layer addLayer; - - for (const XMLAttribute* attribute = layer->FirstAttribute(); attribute; attribute = attribute->Next()) { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { - case ANM2_ATTRIBUTE_NAME: - addLayer.name = std::string(attribute->Value()); - break; - case ANM2_ATTRIBUTE_ID: - id = std::atoi(attribute->Value()); - break; - case ANM2_ATTRIBUTE_SPRITESHEET_ID: - addLayer.spritesheetID = std::atoi(attribute->Value()); - break; - default: - break; - } - } - - self->layers[id] = addLayer; - } - } - - // Nulls - if (const XMLElement* nulls = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULLS])) { - for (const XMLElement* null = nulls->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL]); null; - null = null->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL])) { - Anm2Null addNull; - - for (const XMLAttribute* attribute = null->FirstAttribute(); attribute; attribute = attribute->Next()) { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { - case ANM2_ATTRIBUTE_NAME: - addNull.name = std::string(attribute->Value()); - break; // Name - case ANM2_ATTRIBUTE_ID: - id = std::atoi(attribute->Value()); - break; // IDs - default: - break; - } - } - - self->nulls[id] = addNull; - } - } - - // Events - if (const XMLElement* events = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENTS])) { - // Event - for (const XMLElement* event = events->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT]); event; - event = event->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT])) { - Anm2Event addEvent; - - for (const XMLAttribute* attribute = event->FirstAttribute(); attribute; attribute = attribute->Next()) { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { - case ANM2_ATTRIBUTE_NAME: - addEvent.name = std::string(attribute->Value()); - break; // Name - case ANM2_ATTRIBUTE_ID: - id = std::atoi(attribute->Value()); - break; // ID - default: - break; - } - } - - self->events[id] = addEvent; - } - } - } - - // Animations - if (const XMLElement* animations = root->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATIONS])) { - for (const XMLAttribute* attribute = animations->FirstAttribute(); attribute; attribute = attribute->Next()) { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) { - case ANM2_ATTRIBUTE_DEFAULT_ANIMATION: - self->defaultAnimation = std::string(attribute->Value()); - break; // DefaultAnimation - default: - break; - } - } - - // Animation - for (const XMLElement* animation = animations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION]); animation; - animation = animation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION])) - _anm2_animation_deserialize(&self->animations.emplace_back(Anm2Animation()), animation); - } - - if (isTextures) - anm2_spritesheet_texture_pixels_download(self); - - log_info(std::format(ANM2_READ_INFO, path)); - - return true; -} - -void anm2_animation_layer_animation_add(Anm2Animation* animation, int id) { - animation->layerAnimations[id] = Anm2Item{}; - animation->layerOrder.push_back(id); -} - -void anm2_animation_layer_animation_remove(Anm2Animation* animation, int id) { - animation->layerAnimations.erase(id); - vector_value_erase(animation->layerOrder, id); -} - -void anm2_animation_null_animation_add(Anm2Animation* animation, int id) { animation->nullAnimations[id] = Anm2Item{}; } - -void anm2_animation_null_animation_remove(Anm2Animation* animation, int id) { animation->nullAnimations.erase(id); } - -int anm2_layer_add(Anm2* self) { - int id = map_next_id_get(self->layers); - self->layers[id] = Anm2Layer{}; - return id; -} - -void anm2_layer_remove(Anm2* self, int id) { - self->layers.erase(id); - - for (auto& animation : self->animations) - anm2_animation_layer_animation_remove(&animation, id); -} - -int anm2_null_add(Anm2* self) { - int id = map_next_id_get(self->nulls); - self->nulls[id] = Anm2Null{}; - return id; -} - -void anm2_null_remove(Anm2* self, int id) { - if (!self->nulls.contains(id)) - return; - - self->nulls.erase(id); - - for (auto& animation : self->animations) - anm2_animation_null_animation_remove(&animation, id); -} - -int anm2_animation_add(Anm2* self, Anm2Animation* animation, int index) { - - Anm2Animation addAnimation = animation ? *animation : Anm2Animation(); - - if (!animation) - addAnimation.rootAnimation.frames.push_back(Anm2Frame{}); - - int addIndex = index != INDEX_NONE ? index : (int)self->animations.size() - 1; - - self->animations.insert(self->animations.begin() + addIndex, addAnimation); - - return addIndex; -} - -void anm2_animations_remove(Anm2* self, const std::set indices) { vector_erase_indices(self->animations, indices); }; - -void anm2_new(Anm2* self) { - *self = Anm2{}; - _anm2_created_on_set(self); -} - -Anm2Animation* anm2_animation_from_reference(Anm2* self, Anm2Reference reference) { return vector_get(self->animations, reference.animationIndex); } - -Anm2Item* anm2_item_from_reference(Anm2* self, Anm2Reference reference) { - if (reference.itemType == ANM2_NONE) - return nullptr; - - Anm2Animation* animation = anm2_animation_from_reference(self, reference); - - if (!animation) - return nullptr; - - switch (reference.itemType) { - case ANM2_ROOT: - return &animation->rootAnimation; - case ANM2_LAYER: - return map_find(animation->layerAnimations, reference.itemID); - case ANM2_NULL: - return map_find(animation->nullAnimations, reference.itemID); - case ANM2_TRIGGER: - return &animation->triggers; - default: - return nullptr; - } -} - -int anm2_frame_index_from_time(Anm2* self, Anm2Reference reference, float time) { - Anm2Animation* animation = anm2_animation_from_reference(self, reference); - if (!animation) - return INDEX_NONE; - if (time < 0 || time > animation->frameNum) - return INDEX_NONE; - - Anm2Item* item = anm2_item_from_reference(self, reference); - - if (!item) - return INDEX_NONE; - - if (reference.itemType == ANM2_TRIGGER) - for (auto [i, frame] : std::views::enumerate(item->frames)) - if (frame.atFrame == (int)time) - return i; - - int delayCurrent = 0; - int delayNext = 0; - - for (auto [i, frame] : std::views::enumerate(item->frames)) { - delayNext += frame.delay; - - if (time >= delayCurrent && time < delayNext) - return i; - - delayCurrent += frame.delay; - } - - return INDEX_NONE; -} - -float anm2_time_from_reference(Anm2* self, Anm2Reference reference) { - Anm2Animation* animation = anm2_animation_from_reference(self, reference); - if (!animation) - return INDEX_NONE; - - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) - return INDEX_NONE; - - float time = 0.0f; - - if (reference.frameIndex <= 0) - return 0.0f; - - if (reference.frameIndex >= (int)item->frames.size()) { - for (auto& frame : item->frames) - time += (float)frame.delay; - return time; - } - - if (reference.itemType == ANM2_TRIGGER) - return (float)item->frames[reference.frameIndex].atFrame; - - for (int i = 0; i < reference.frameIndex; i++) - time += (float)item->frames[i].delay; - - return time; -} - -Anm2Frame* anm2_frame_from_reference(Anm2* self, Anm2Reference reference) { - Anm2Item* item = anm2_item_from_reference(self, reference); - - if (!item) - return nullptr; - - if (reference.frameIndex <= INDEX_NONE || reference.frameIndex >= (int)item->frames.size()) - return nullptr; - - return &item->frames[reference.frameIndex]; -} - -void anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, float time) { - Anm2Animation* animation = anm2_animation_from_reference(self, reference); - if (!animation) - return; - - time = std::clamp(ROUND_NEAREST_MULTIPLE(time, 1.0f), 0.0f, animation->frameNum - 1.0f); - - Anm2Item* item = anm2_item_from_reference(self, reference); - - if (!item) - return; - - Anm2Frame* frameNext = nullptr; - int delayCurrent = 0; - int delayNext = 0; - - for (auto [i, iFrame] : std::views::enumerate(item->frames)) { - if (reference.itemType == ANM2_TRIGGER) { - if ((int)time == iFrame.atFrame) { - *frame = iFrame; - break; - } - } else { - *frame = iFrame; - - delayNext += frame->delay; - - if (time >= delayCurrent && time < delayNext) { - if (i + 1 < (int)item->frames.size()) - frameNext = &item->frames[i + 1]; - else - frameNext = nullptr; - break; - } - - delayCurrent += frame->delay; - } - } - - if (reference.itemType == ANM2_TRIGGER) - return; - - if (frame->isInterpolated && frameNext && frame->delay > 1) { - float interpolation = (time - delayCurrent) / (delayNext - delayCurrent); - - frame->rotation = glm::mix(frame->rotation, frameNext->rotation, interpolation); - frame->position = glm::mix(frame->position, frameNext->position, interpolation); - frame->scale = glm::mix(frame->scale, frameNext->scale, interpolation); - frame->offsetRGB = glm::mix(frame->offsetRGB, frameNext->offsetRGB, interpolation); - frame->tintRGBA = glm::mix(frame->tintRGBA, frameNext->tintRGBA, interpolation); - } -} - -int anm2_animation_length_get(Anm2Animation* self) { - int length = 0; - - auto accumulate_max_delay = [&](const std::vector& frames) { - int delaySum = 0; - for (const auto& frame : frames) { - delaySum += frame.delay; - length = std::max(length, delaySum); - } - }; - - accumulate_max_delay(self->rootAnimation.frames); - - for (const auto& [_, item] : self->layerAnimations) - accumulate_max_delay(item.frames); - - for (const auto& [_, item] : self->nullAnimations) - accumulate_max_delay(item.frames); - - for (const auto& frame : self->triggers.frames) - length = std::max(length, frame.atFrame + 1); - - return length; -} - -void anm2_animation_length_set(Anm2Animation* self) { self->frameNum = anm2_animation_length_get(self); } - -Anm2Frame* anm2_frame_add(Anm2* self, Anm2Frame* frame, Anm2Reference reference) { - Anm2Animation* animation = anm2_animation_from_reference(self, reference); - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!animation || !item) - return nullptr; - - Anm2Frame frameAdd = frame ? *frame : Anm2Frame{}; - - if (reference.itemType == ANM2_TRIGGER) { - int atFrame = frame ? frame->atFrame : 0; - - for (auto& frameCheck : item->frames) { - if (frameCheck.atFrame == atFrame) { - atFrame++; - break; - } - } - - frameAdd.atFrame = atFrame; - - return &item->frames.emplace_back(frameAdd); - } else { - int index = reference.frameIndex; - - if (index < 0 || index >= (int)item->frames.size()) { - item->frames.push_back(frameAdd); - return &item->frames.back(); - } else { - item->frames.insert(item->frames.begin() + index, frameAdd); - return &item->frames[(size_t)(index)]; - } - } -} - -void anm2_frame_remove(Anm2* self, Anm2Reference reference) { - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) - return; - item->frames.erase(item->frames.begin() + reference.frameIndex); -} - -void anm2_item_frame_set(Anm2* self, Anm2Reference reference, const Anm2FrameChange& change, Anm2ChangeType changeType, int start, int count) { - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) - return; - - int size = (int)item->frames.size(); - if (size == 0 || start >= size) - return; - if (start < 0 || count <= 0) - return; - - int end = std::min(start + count, size); - - for (int i = start; i < end; i++) { - Anm2Frame& dest = item->frames[i]; - -#define X(name, ctype, ...) \ - if (change.name) { \ - if constexpr (std::is_same_v) { \ - dest.name = *change.name; \ - } else { \ - switch (changeType) { \ - case ANM2_CHANGE_SET: \ - dest.name = *change.name; \ - break; \ - case ANM2_CHANGE_ADD: \ - dest.name += *change.name; \ - break; \ - case ANM2_CHANGE_SUBTRACT: \ - dest.name -= *change.name; \ - break; \ - } \ - } \ - } - ANM2_FRAME_MEMBERS -#undef X - } -} - -void anm2_animation_merge(Anm2* self, int animationIndex, std::set mergeIndices, Anm2MergeType type) { - Anm2Animation newAnimation = self->animations[animationIndex]; - - auto merge_item = [&](Anm2Item& destinationItem, const Anm2Item& sourceItem) { - switch (type) { - case ANM2_MERGE_APPEND: - destinationItem.frames.insert(destinationItem.frames.end(), sourceItem.frames.begin(), sourceItem.frames.end()); - break; - case ANM2_MERGE_PREPEND: - destinationItem.frames.insert(destinationItem.frames.begin(), sourceItem.frames.begin(), sourceItem.frames.end()); - break; - case ANM2_MERGE_REPLACE: - if (destinationItem.frames.size() < sourceItem.frames.size()) - destinationItem.frames.resize(sourceItem.frames.size()); - for (int i = 0; i < (int)sourceItem.frames.size(); i++) - destinationItem.frames[i] = sourceItem.frames[i]; - break; - case ANM2_MERGE_IGNORE: - break; - } - }; - - for (auto mergeIndices : mergeIndices) { - if (animationIndex == mergeIndices) - continue; - - const Anm2Animation& mergeAnimation = self->animations[mergeIndices]; - - merge_item(newAnimation.rootAnimation, mergeAnimation.rootAnimation); - - for (const auto& [id, layerAnimation] : mergeAnimation.layerAnimations) - merge_item(newAnimation.layerAnimations[id], layerAnimation); - - for (const auto& [id, nullAnimation] : mergeAnimation.nullAnimations) - merge_item(newAnimation.nullAnimations[id], nullAnimation); - - merge_item(newAnimation.triggers, mergeAnimation.triggers); - } - - self->animations[animationIndex] = newAnimation; - - anm2_animation_length_set(&self->animations[animationIndex]); -} - -void anm2_frame_bake(Anm2* self, Anm2Reference reference, int interval, bool isRoundScale, bool isRoundRotation) { - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) - return; - - Anm2Frame* frame = anm2_frame_from_reference(self, reference); - if (!frame) - return; - - Anm2Reference referenceNext = {reference.animationIndex, reference.itemType, reference.itemID, reference.frameIndex + 1}; - Anm2Frame* frameNext = anm2_frame_from_reference(self, referenceNext); - if (!frameNext) - frameNext = frame; - - const Anm2Frame baseFrame = *frame; - const Anm2Frame baseFrameNext = *frameNext; - - int delay = 0; - int insertIndex = reference.frameIndex; - - while (delay < baseFrame.delay) { - float interpolation = (float)delay / baseFrame.delay; - - Anm2Frame baked = *frame; - baked.delay = std::min(interval, baseFrame.delay - delay); - baked.isInterpolated = (insertIndex == reference.frameIndex) ? baseFrame.isInterpolated : false; - - baked.rotation = glm::mix(baseFrame.rotation, baseFrameNext.rotation, interpolation); - baked.position = glm::mix(baseFrame.position, baseFrameNext.position, interpolation); - baked.scale = glm::mix(baseFrame.scale, baseFrameNext.scale, interpolation); - baked.offsetRGB = glm::mix(baseFrame.offsetRGB, baseFrameNext.offsetRGB, interpolation); - baked.tintRGBA = glm::mix(baseFrame.tintRGBA, baseFrameNext.tintRGBA, interpolation); - - if (isRoundScale) - baked.scale = vec2((int)baked.scale.x, (int)baked.scale.y); - if (isRoundRotation) - baked.rotation = (int)baked.rotation; - - if (insertIndex == reference.frameIndex) - item->frames[insertIndex] = baked; - else - item->frames.insert(item->frames.begin() + insertIndex, baked); - insertIndex++; - - delay += baked.delay; - } -} - -void anm2_scale(Anm2* self, float scale) { - auto frame_scale = [&](Anm2Frame& frame) { - frame.position = vec2((int)(frame.position.x * scale), (int)(frame.position.y * scale)); - frame.size = vec2((int)(frame.size.x * scale), (int)(frame.size.y * scale)); - frame.crop = vec2((int)(frame.crop.x * scale), (int)(frame.crop.y * scale)); - frame.pivot = vec2((int)(frame.pivot.x * scale), (int)(frame.pivot.y * scale)); - }; - - for (auto& animation : self->animations) { - for (auto& frame : animation.rootAnimation.frames) - frame_scale(frame); - - for (auto& [_, layerAnimation] : animation.layerAnimations) - for (auto& frame : layerAnimation.frames) - frame_scale(frame); - - for (auto& [_, nullAnimation] : animation.nullAnimations) - for (auto& frame : nullAnimation.frames) - frame_scale(frame); - } -} - -void anm2_generate_from_grid(Anm2* self, Anm2Reference reference, vec2 startPosition, vec2 size, vec2 pivot, int columns, int count, int delay) { - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) - return; - - Anm2Reference frameReference = reference; - - for (int i = 0; i < count; i++) { - const int row = i / columns; - const int column = i % columns; - - Anm2Frame frame{}; - - frame.delay = delay; - frame.pivot = pivot; - frame.size = size; - frame.crop = startPosition + vec2(size.x * column, size.y * row); - - anm2_frame_add(self, &frame, frameReference); - frameReference.frameIndex++; - } -} - -void anm2_free(Anm2* self) { - for (auto& [id, spritesheet] : self->spritesheets) - texture_free(&spritesheet.texture); -} - -void anm2_spritesheet_texture_pixels_upload(Anm2* self) { - for (auto& [_, spritesheet] : self->spritesheets) { - Texture& texture = spritesheet.texture; - - if (texture.id != GL_ID_NONE && !texture.isInvalid) { - assert(!spritesheet.pixels.empty()); - glBindTexture(GL_TEXTURE_2D, texture.id); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture.size.x, texture.size.y, GL_RGBA, GL_UNSIGNED_BYTE, spritesheet.pixels.data()); - } - } -} - -void anm2_spritesheet_texture_pixels_download(Anm2* self) { - for (auto& [_, spritesheet] : self->spritesheets) { - Texture& texture = spritesheet.texture; - - if (texture.id != GL_ID_NONE && !texture.isInvalid) { - size_t bufferSize = (size_t)texture.size.x * (size_t)texture.size.y * TEXTURE_CHANNELS; - spritesheet.pixels.resize(bufferSize); - glBindTexture(GL_TEXTURE_2D, texture.id); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, spritesheet.pixels.data()); - } - } -} - -vec4 anm2_animation_rect_get(Anm2* self, Anm2Reference reference, bool isRootTransform) { - float minX = std::numeric_limits::infinity(); - float minY = std::numeric_limits::infinity(); - float maxX = -std::numeric_limits::infinity(); - float maxY = -std::numeric_limits::infinity(); - - bool any = false; - - Anm2Frame frame; - Anm2Frame root; - - Anm2Animation* animation = anm2_animation_from_reference(self, reference); - if (!animation) - return vec4(-1.0f); - - for (float t = 0.0f; t <= animation->frameNum; t += 1.0f) { - for (const auto& [id, _] : animation->layerAnimations) { - anm2_frame_from_time(self, &frame, {reference.animationIndex, ANM2_LAYER, id}, t); - if (!frame.isVisible) - continue; - if (frame.size.x <= 0 || frame.size.y <= 0) - continue; - - mat4 rootModel(1.0f); - if (isRootTransform) { - anm2_frame_from_time(self, &root, {reference.animationIndex, ANM2_ROOT}, t); - rootModel = quad_model_parent_get(root.position, root.pivot, PERCENT_TO_UNIT(root.scale), root.rotation); - } - - mat4 model = quad_model_get(frame.size, frame.position, frame.pivot, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 fullModel = rootModel * model; - - vec2 corners[4] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; - - for (auto& corner : corners) { - vec4 world = fullModel * vec4(corner, 0.0f, 1.0f); - minX = std::min(minX, world.x); - minY = std::min(minY, world.y); - maxX = std::max(maxX, world.x); - maxY = std::max(maxY, world.y); - any = true; - } - } - } - - if (!any) - return vec4(-1.0f); - return {minX, minY, maxX - minX, maxY - minY}; -} - -void anm2_animation_serialize_to_string(Anm2Animation* animation, std::string* string) { _anm2_animation_serialize(animation, nullptr, nullptr, string); } - -void anm2_frame_serialize_to_string(Anm2Frame* frame, Anm2Type type, std::string* string) { _anm2_frame_serialize(frame, type, nullptr, nullptr, string); } - -bool anm2_animations_deserialize_from_xml(std::vector& animations, const std::string& xml) { - XMLDocument document; - - auto animation_deserialize_error = [&]() { - log_error(std::format(ANM2_ANIMATION_PARSE_ERROR, xml, document.ErrorStr())); - return false; - }; - - if (document.Parse(xml.c_str()) != XML_SUCCESS) - return animation_deserialize_error(); - - for (const XMLElement* element = document.RootElement(); element; element = element->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION])) { - if (std::string(document.RootElement()->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION])) - return animation_deserialize_error(); - _anm2_animation_deserialize(&animations.emplace_back(Anm2Animation()), element); - } - - return true; -} - -bool anm2_frame_deserialize_from_xml(Anm2Frame* frame, const std::string& xml) { - XMLDocument document; - - auto frame_deserialize_error = [&]() { - log_error(std::format(ANM2_FRAME_PARSE_ERROR, xml, document.ErrorStr())); - return false; - }; - - if (document.Parse(xml.c_str()) != XML_SUCCESS) - return frame_deserialize_error(); - - const XMLElement* element = document.RootElement(); - if (!element) - return frame_deserialize_error(); - - if (std::string(element->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]) && - std::string(element->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER])) - return frame_deserialize_error(); - - _anm2_frame_deserialize(frame, element); - - return true; -} - -/* -void anm2_merge(Anm2* self, const std::string& path, Anm2MergeType type) +namespace anm2ed::anm2 { - Anm2 anm2; + void Reference::previous_frame(int max) + { + frameIndex = glm::clamp(--frameIndex, 0, max); + } - if (anm2_deserialize(&anm2, path, false)) + void Reference::next_frame(int max) + { + frameIndex = glm::clamp(++frameIndex, 0, max); + } + + Info::Info() = default; + + Info::Info(XMLElement* element) + { + if (!element) return; + xml::query_string_attribute(element, "CreatedBy", &createdBy); + xml::query_string_attribute(element, "CreatedOn", &createdOn); + element->QueryIntAttribute("Fps", &fps); + element->QueryIntAttribute("Version", &version); + } + + void Info::serialize(XMLDocument& document, XMLElement* parent) + { + auto infoElement = document.NewElement("Info"); + infoElement->SetAttribute("CreatedBy", createdBy.c_str()); + infoElement->SetAttribute("CreatedOn", createdOn.c_str()); + infoElement->SetAttribute("Fps", fps); + infoElement->SetAttribute("Version", version); + parent->InsertEndChild(infoElement); + } + + Spritesheet::Spritesheet() = default; + + Spritesheet::Spritesheet(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_path_attribute(element, "Path", &path); + // Spritesheet paths from Isaac Rebirth are made with the assumption that + // the paths are case-insensitive (as the game was developed on Windows) + // However when using the resource dumper, the spritesheet paths are all lowercase (on Linux anyway) + // If the check doesn't work, set the spritesheet path to lowercase + // If that check doesn't work, replace backslashes with slashes + // At the minimum this should make all textures be able to be loaded on Linux + // If it doesn't work beyond that then that's on the user :^) + if (!path_is_exist(path)) path = string::to_lower(path); + if (!path_is_exist(path)) path = string::replace_backslash(path); + texture = Texture(path, true); + } + + Spritesheet::Spritesheet(const std::string& directory, const std::string& path) + { + this->path = !path.empty() ? path : this->path.string(); + WorkingDirectory workingDirectory(directory); + texture = Texture(this->path, true); + } + + bool Spritesheet::save(const std::string& directory, const std::string& path) + { + this->path = !path.empty() ? path : this->path.string(); + WorkingDirectory workingDirectory(directory); + return texture.write_png(this->path); + } + + void Spritesheet::serialize(XMLDocument& document, XMLElement* parent, int id) + { + auto element = document.NewElement("Spritesheet"); + element->SetAttribute("Id", id); + element->SetAttribute("Path", path.c_str()); + parent->InsertEndChild(element); + } + + void Spritesheet::reload(const std::string& directory) + { + *this = Spritesheet(directory, this->path); + } + + bool Spritesheet::is_valid() + { + return texture.is_valid(); + } + + Layer::Layer() = default; + + Layer::Layer(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_string_attribute(element, "Name", &name); + element->QueryIntAttribute("SpritesheetId", &spritesheetID); + } + + void Layer::serialize(XMLDocument& document, XMLElement* parent, int id) + { + auto element = document.NewElement("Layer"); + element->SetAttribute("Id", id); + element->SetAttribute("Name", name.c_str()); + element->SetAttribute("SpritesheetId", spritesheetID); + parent->InsertEndChild(element); + } + + Null::Null() = default; + + Null::Null(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_string_attribute(element, "Name", &name); + element->QueryBoolAttribute("ShowRect", &isShowRect); + } + + void Null::serialize(XMLDocument& document, XMLElement* parent, int id) + { + auto element = document.NewElement("Null"); + element->SetAttribute("Id", id); + element->SetAttribute("Name", name.c_str()); + if (isShowRect) element->SetAttribute("ShowRect", isShowRect); + + parent->InsertEndChild(element); + } + + Event::Event() = default; + + Event::Event(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_string_attribute(element, "Name", &name); + } + + void Event::serialize(XMLDocument& document, XMLElement* parent, int id) + { + auto element = document.NewElement("Event"); + element->SetAttribute("Id", id); + element->SetAttribute("Name", name.c_str()); + parent->InsertEndChild(element); + } + + Content::Content() = default; + + void Content::serialize(XMLDocument& document, XMLElement* parent) + { + auto element = document.NewElement("Content"); + + auto spritesheetsElement = document.NewElement("Spritesheets"); + for (auto& [id, spritesheet] : spritesheets) + spritesheet.serialize(document, spritesheetsElement, id); + element->InsertEndChild(spritesheetsElement); + + auto layersElement = document.NewElement("Layers"); + for (auto& [id, layer] : layers) + layer.serialize(document, layersElement, id); + element->InsertEndChild(layersElement); + + auto nullsElement = document.NewElement("Nulls"); + for (auto& [id, null] : nulls) + null.serialize(document, nullsElement, id); + element->InsertEndChild(nullsElement); + + auto eventsElement = document.NewElement("Events"); + for (auto& [id, event] : events) + event.serialize(document, eventsElement, id); + element->InsertEndChild(eventsElement); + + parent->InsertEndChild(element); + } + + Content::Content(XMLElement* element) + { + int id{}; + + if (auto spritesheetsElement = element->FirstChildElement("Spritesheets")) + { + for (auto child = spritesheetsElement->FirstChildElement("Spritesheet"); child; + child = child->NextSiblingElement("Spritesheet")) + spritesheets[id] = Spritesheet(child, id); + } + + if (auto layersElement = element->FirstChildElement("Layers")) + { + for (auto child = layersElement->FirstChildElement("Layer"); child; child = child->NextSiblingElement("Layer")) + layers[id] = Layer(child, id); + } + + if (auto nullsElement = element->FirstChildElement("Nulls")) + { + for (auto child = nullsElement->FirstChildElement("Null"); child; child = child->NextSiblingElement("Null")) + nulls[id] = Null(child, id); + } + + if (auto eventsElement = element->FirstChildElement("Events")) + { + for (auto child = eventsElement->FirstChildElement("Event"); child; child = child->NextSiblingElement("Event")) + events[id] = Event(child, id); + } + } + + bool Content::spritesheet_add(const std::string& directory, const std::string& path, int& id) + { + Spritesheet spritesheet(directory, path); + if (!spritesheet.is_valid()) return false; + id = map::next_id_get(spritesheets); + spritesheets[id] = std::move(spritesheet); + return true; + } + + void Content::spritesheet_remove(int& id) + { + spritesheets.erase(id); + } + + std::set Content::spritesheets_unused() + { + std::set used; + for (auto& layer : layers | std::views::values) + if (layer.spritesheetID != -1) used.insert(layer.spritesheetID); + + std::set unused; + for (auto& id : spritesheets | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + void Content::layer_add(int& id) + { + id = map::next_id_get(layers); + layers[id] = Layer(); + } + + void Content::null_add(int& id) + { + id = map::next_id_get(nulls); + nulls[id] = Null(); + } + + void Content::event_add(int& id) + { + id = map::next_id_get(events); + events[id] = Event(); + } + + Frame::Frame() = default; + + Frame::Frame(XMLElement* element, Type type) + { + if (!element) return; + + if (type != TRIGGER) + { + element->QueryFloatAttribute("XPosition", &position.x); + element->QueryFloatAttribute("YPosition", &position.y); + if (type == LAYER) + { + element->QueryFloatAttribute("XPivot", &pivot.x); + element->QueryFloatAttribute("YPivot", &pivot.y); + element->QueryFloatAttribute("XCrop", &crop.x); + element->QueryFloatAttribute("YCrop", &crop.y); + element->QueryFloatAttribute("Width", &size.x); + element->QueryFloatAttribute("Height", &size.y); + } + element->QueryFloatAttribute("XScale", &scale.x); + element->QueryFloatAttribute("YScale", &scale.y); + element->QueryIntAttribute("Delay", &delay); + element->QueryBoolAttribute("Visible", &isVisible); + xml::query_color_attribute(element, "RedTint", tint.r); + xml::query_color_attribute(element, "GreenTint", tint.g); + xml::query_color_attribute(element, "BlueTint", tint.b); + xml::query_color_attribute(element, "AlphaTint", tint.a); + xml::query_color_attribute(element, "RedOffset", offset.r); + xml::query_color_attribute(element, "GreenOffset", offset.g); + xml::query_color_attribute(element, "BlueOffset", offset.b); + element->QueryFloatAttribute("Rotation", &rotation); + element->QueryBoolAttribute("Interpolated", &isInterpolated); + } + else + { + element->QueryIntAttribute("EventId", &eventID); + element->QueryIntAttribute("AtFrame", &atFrame); + } + } + + void Frame::serialize(XMLDocument& document, XMLElement* parent, Type type) + { + auto element = document.NewElement(type == TRIGGER ? "Trigger" : "Frame"); + + switch (type) + { + case ROOT: + case NULL_: + element->SetAttribute("XPosition", position.x); + element->SetAttribute("YPosition", position.y); + element->SetAttribute("Delay", delay); + element->SetAttribute("Visible", isVisible); + element->SetAttribute("XScale", scale.x); + element->SetAttribute("YScale", scale.y); + element->SetAttribute("RedTint", math::float_to_uint8(tint.r)); + element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); + element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); + element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); + element->SetAttribute("RedOffset", math::float_to_uint8(offset.r)); + element->SetAttribute("GreenOffset", math::float_to_uint8(offset.g)); + element->SetAttribute("BlueOffset", math::float_to_uint8(offset.b)); + element->SetAttribute("Rotation", rotation); + element->SetAttribute("Interpolated", isInterpolated); + break; + case LAYER: + element->SetAttribute("XPosition", position.x); + element->SetAttribute("YPosition", position.y); + element->SetAttribute("XPivot", pivot.x); + element->SetAttribute("YPivot", pivot.y); + element->SetAttribute("XCrop", crop.x); + element->SetAttribute("YCrop", crop.y); + element->SetAttribute("Width", size.x); + element->SetAttribute("Height", size.y); + element->SetAttribute("XScale", scale.x); + element->SetAttribute("YScale", scale.y); + element->SetAttribute("Delay", delay); + element->SetAttribute("Visible", isVisible); + element->SetAttribute("RedTint", math::float_to_uint8(tint.r)); + element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); + element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); + element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); + element->SetAttribute("RedOffset", math::float_to_uint8(offset.r)); + element->SetAttribute("GreenOffset", math::float_to_uint8(offset.g)); + element->SetAttribute("BlueOffset", math::float_to_uint8(offset.b)); + element->SetAttribute("Rotation", rotation); + element->SetAttribute("Interpolated", isInterpolated); + break; + case TRIGGER: + element->SetAttribute("EventId", eventID); + element->SetAttribute("AtFrame", atFrame); + break; + default: + break; + } + + parent->InsertEndChild(element); + } + + void Frame::shorten() + { + delay = glm::clamp(--delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); + } + + void Frame::extend() + { + delay = glm::clamp(++delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); + } + + Item::Item() = default; + + Item::Item(XMLElement* element, Type type, int* id) + { + if (type == LAYER && id) element->QueryIntAttribute("LayerId", id); + if (type == NULL_ && id) element->QueryIntAttribute("NullId", id); + + element->QueryBoolAttribute("Visible", &isVisible); + + for (auto child = type == TRIGGER ? element->FirstChildElement("Trigger") : element->FirstChildElement("Frame"); + child; child = type == TRIGGER ? child->NextSiblingElement("Trigger") : child->NextSiblingElement("Frame")) + frames.push_back(Frame(child, type)); + } + + void Item::serialize(XMLDocument& document, XMLElement* parent, Type type, int id) + { + auto typeString = type == ROOT ? "RootAnimation" + : type == LAYER ? "LayerAnimation" + : type == NULL_ ? "NullAnimation" + : "Triggers"; + + auto element = document.NewElement(typeString); + + if (type == LAYER) element->SetAttribute("LayerId", id); + if (type == NULL_) element->SetAttribute("NullId", id); + if (type == LAYER || type == NULL_) element->SetAttribute("Visible", isVisible); + + for (auto& frame : frames) + frame.serialize(document, element, type); + parent->InsertEndChild(element); + } + + int Item::length(Type type) + { + int length{}; + + if (type == TRIGGER) + for (auto& frame : frames) + length = frame.atFrame > length ? frame.atFrame : length; + else + for (auto& frame : frames) + length += frame.delay; + + return length; + } + + Frame Item::frame_generate(float time, Type type) + { + Frame frame{}; + frame.isVisible = false; + + if (frames.empty()) return frame; + + Frame* frameNext = nullptr; + int delayCurrent = 0; + int delayNext = 0; + + for (auto [i, iFrame] : std::views::enumerate(frames)) + { + if (type == TRIGGER) + { + if ((int)time == iFrame.atFrame) { - std::unordered_map spritesheetMap; - for (auto& [id, spritesheet] : anm2.spritesheets) - { - bool isExists = false; - - for (auto& [selfID, selfSpritesheet] : self->spritesheets) - { - if (spritesheet.path == selfSpritesheet.path) isExists = true; - spritesheetMap[id] = selfID; - } - - if (isExists) continue; - - int nextID = map_next_id_get(self->spritesheets); - self->spritesheet[nextID] = spritesheet; - spritesheetMap[id] = nextID; - } - - std::unordered_map layerMap; - for (auto& [id, layer] : anm2.layers) - { - bool isExists = false; - - layer.spritesheetID = spritesheetMap[layer.spritesheetID]; - - for (auto& [selfID, selfLayer] : self->layers) - { - if (layer.name == selfLayer.name) isExists = true; - layerMap[id] = selfID; - } - - if (isExists) continue; - - int nextID = map_next_id_get(self->layers); - self->layer[nextID] = layer; - layerMap[id] = nextID; - } - - std::unordered_map nullMap; - for (auto& [id, null] : anm2.nulls) - { - bool isExists = false; - - for (auto& [selfID, selfNull] : self->nulls) - { - if (null.name == selfNull.name) isExists = true; - nullMap[id] = selfID; - } - - if (isExists) continue; - - int nextID = map_next_id_get(self->nulls); - self->null[nextID] = null; - nullMap[id] = nextID; - } - - std::unordered_map eventMap; - for (auto& [id, event] : anm2.events) - { - bool isExists = false; - - for (auto& [selfID, selfEvent] : self->events) - { - if (event.name == selfEvent.name) isExists = true; - eventMap[id] = selfID; - } - - if (isExists) continue; - - int nextID = map_next_id_get(self->events); - self->event[nextID] = event; - eventMap[id] = nextID; - } - - for (auto& [id, animation] : anm2.animations) - { - bool isExists = false; - - for (auto& [selfID, selfAnimation] : self->animations) - { - if (event.name == selfAnimation.name) isExists = true; - eventMap[id] = selfID; - } - - if (isExists) continue; - - for (auto& frame : animation.rootAnimation.frames) - { - - - } - - for (auto& [layerID, layerAnimation] : animation.layerAnimations) - { - int newLayerID = layerMap[layerID]; - - - } - } + frame = iFrame; + break; } -} -*/ \ No newline at end of file + } + else + { + frame = iFrame; + + delayNext += frame.delay; + + if (time >= delayCurrent && time < delayNext) + { + if (i + 1 < (int)frames.size()) + frameNext = &frames[i + 1]; + else + frameNext = nullptr; + break; + } + + delayCurrent += frame.delay; + } + } + + if (type != TRIGGER && frame.isInterpolated && frameNext && frame.delay > 1) + { + auto interpolation = (time - delayCurrent) / (delayNext - delayCurrent); + + frame.rotation = glm::mix(frame.rotation, frameNext->rotation, interpolation); + frame.position = glm::mix(frame.position, frameNext->position, interpolation); + frame.scale = glm::mix(frame.scale, frameNext->scale, interpolation); + frame.offset = glm::mix(frame.offset, frameNext->offset, interpolation); + frame.tint = glm::mix(frame.tint, frameNext->tint, interpolation); + } + + return frame; + } + + Animation::Animation() = default; + + Animation::Animation(XMLElement* element) + { + int id{}; + + xml::query_string_attribute(element, "Name", &name); + element->QueryIntAttribute("FrameNum", &frameNum); + element->QueryBoolAttribute("Loop", &isLoop); + + if (auto rootAnimationElement = element->FirstChildElement("RootAnimation")) + rootAnimation = Item(rootAnimationElement, ROOT); + + if (auto layerAnimationsElement = element->FirstChildElement("LayerAnimations")) + { + for (auto child = layerAnimationsElement->FirstChildElement("LayerAnimation"); child; + child = child->NextSiblingElement("LayerAnimation")) + { + layerAnimations[id] = Item(child, LAYER, &id); + layerOrder.push_back(id); + } + } + + if (auto nullAnimationsElement = element->FirstChildElement("NullAnimations")) + { + for (auto child = nullAnimationsElement->FirstChildElement("NullAnimation"); child; + child = child->NextSiblingElement("NullAnimation")) + nullAnimations[id] = Item(child, NULL_, &id); + } + + if (auto triggersElement = element->FirstChildElement("Triggers")) triggers = Item(triggersElement, TRIGGER); + } + + Item* Animation::item_get(Type type, int id) + { + switch (type) + { + case ROOT: + return &rootAnimation; + case LAYER: + return unordered_map::find(layerAnimations, id); + case NULL_: + return map::find(nullAnimations, id); + case TRIGGER: + return &triggers; + default: + return nullptr; + } + return nullptr; + } + + void Animation::serialize(XMLDocument& document, XMLElement* parent) + { + auto element = document.NewElement("Animation"); + element->SetAttribute("Name", name.c_str()); + element->SetAttribute("FrameNum", frameNum); + element->SetAttribute("Loop", isLoop); + + rootAnimation.serialize(document, element, ROOT); + + auto layerAnimationsElement = document.NewElement("LayerAnimations"); + for (auto& i : layerOrder) + { + Item& layerAnimation = layerAnimations.at(i); + layerAnimation.serialize(document, layerAnimationsElement, LAYER, i); + } + element->InsertEndChild(layerAnimationsElement); + + auto nullAnimationsElement = document.NewElement("NullAnimations"); + for (auto& [id, nullAnimation] : nullAnimations) + nullAnimation.serialize(document, nullAnimationsElement, NULL_, id); + element->InsertEndChild(nullAnimationsElement); + + triggers.serialize(document, element, TRIGGER); + + parent->InsertEndChild(element); + } + + int Animation::length() + { + int length{}; + + if (int rootAnimationLength = rootAnimation.length(ROOT); rootAnimationLength > length) + length = rootAnimationLength; + + for (auto& layerAnimation : layerAnimations | std::views::values) + if (int layerAnimationLength = layerAnimation.length(LAYER); layerAnimationLength > length) + length = layerAnimationLength; + + for (auto& nullAnimation : nullAnimations | std::views::values) + if (int nullAnimationLength = nullAnimation.length(NULL_); nullAnimationLength > length) + length = nullAnimationLength; + + if (int triggersLength = triggers.length(TRIGGER); triggersLength > length) length = triggersLength; + + return length; + } + + Animations::Animations() = default; + + Animations::Animations(XMLElement* element) + { + xml::query_string_attribute(element, "DefaultAnimation", &defaultAnimation); + + for (auto child = element->FirstChildElement("Animation"); child; child = child->NextSiblingElement("Animation")) + items.push_back(Animation(child)); + } + + void Animations::serialize(XMLDocument& document, XMLElement* parent) + { + auto element = document.NewElement("Animations"); + element->SetAttribute("DefaultAnimation", defaultAnimation.c_str()); + for (auto& animation : items) + animation.serialize(document, element); + parent->InsertEndChild(element); + } + + int Animations::length() + { + int length{}; + + for (auto& animation : items) + if (int animationLength = animation.length(); animationLength > length) length = animationLength; + + return length; + } + + int Animations::merge(int target, std::set& sources, merge::Type type, bool isDeleteAfter) + { + Animation& animation = items.at(target); + + if (!animation.name.ends_with(MERGED_STRING)) animation.name = animation.name + " " + MERGED_STRING; + + auto merge_item = [&](Item& destination, Item& source) + { + switch (type) + { + case merge::APPEND: + destination.frames.insert(destination.frames.end(), source.frames.begin(), source.frames.end()); + break; + case merge::PREPEND: + destination.frames.insert(destination.frames.begin(), source.frames.begin(), source.frames.end()); + break; + case merge::REPLACE: + if (destination.frames.size() < source.frames.size()) destination.frames.resize(source.frames.size()); + for (int i = 0; i < (int)source.frames.size(); i++) + destination.frames[i] = source.frames[i]; + break; + case merge::IGNORE: + default: + break; + } + }; + + for (auto& i : sources) + { + if (i == target) continue; + if (i < 0 || i >= (int)items.size()) continue; + + auto& source = items.at(i); + + merge_item(animation.rootAnimation, source.rootAnimation); + + for (auto& [id, layerAnimation] : source.layerAnimations) + { + if (!animation.layerAnimations.contains(id)) + { + animation.layerAnimations[id] = layerAnimation; + animation.layerOrder.emplace_back(id); + } + merge_item(animation.layerAnimations[id], layerAnimation); + } + + for (auto& [id, nullAnimation] : source.nullAnimations) + { + if (!animation.nullAnimations.contains(id)) animation.nullAnimations[id] = nullAnimation; + merge_item(animation.nullAnimations[id], nullAnimation); + } + + merge_item(animation.triggers, source.triggers); + } + + if (isDeleteAfter) + { + for (auto& source : std::ranges::reverse_view(sources)) + { + if (source == target) continue; + items.erase(items.begin() + source); + } + } + + int finalIndex = target; + + if (isDeleteAfter) + { + int numDeletedBefore = 0; + for (auto& idx : sources) + { + if (idx == target) continue; + if (idx >= 0 && idx < target) ++numDeletedBefore; + } + finalIndex -= numDeletedBefore; + } + + return finalIndex; + } + + Anm2::Anm2() + { + info.createdOn = time::get("%d-%B-%Y %I:%M:%S"); + } + + bool Anm2::serialize(const std::string& path, std::string* errorString) + { + XMLDocument document; + + auto* element = document.NewElement("AnimatedActor"); + document.InsertFirstChild(element); + + info.serialize(document, element); + content.serialize(document, element); + animations.serialize(document, element); + + if (document.SaveFile(path.c_str()) != XML_SUCCESS) + { + if (errorString) *errorString = document.ErrorStr(); + return false; + } + return true; + } + + std::string Anm2::to_string() + { + XMLDocument document; + + auto* element = document.NewElement("AnimatedActor"); + document.InsertFirstChild(element); + + info.serialize(document, element); + content.serialize(document, element); + animations.serialize(document, element); + + XMLPrinter printer; + document.Print(&printer); + return printer.CStr(); + } + + Anm2::Anm2(const std::string& path, std::string* errorString) + { + XMLDocument document; + + if (document.LoadFile(path.c_str()) != XML_SUCCESS) + { + if (errorString) *errorString = document.ErrorStr(); + return; + } + + isValid = false; + + WorkingDirectory workingDirectory(path, true); + + const XMLElement* element = document.RootElement(); + + if (auto infoElement = element->FirstChildElement("Info")) info = Info((XMLElement*)infoElement); + + if (auto contentElement = element->FirstChildElement("Content")) content = Content((XMLElement*)contentElement); + + if (auto animationsElement = element->FirstChildElement("Animations")) + animations = Animations((XMLElement*)animationsElement); + } + + uint64_t Anm2::hash() + { + return std::hash{}(to_string()); + } + + Animation* Anm2::animation_get(Reference& reference) + { + return vector::find(animations.items, reference.animationIndex); + } + + Item* Anm2::item_get(Reference& reference) + { + if (Animation* animation = animation_get(reference)) + { + switch (reference.itemType) + { + case ROOT: + return &animation->rootAnimation; + case LAYER: + return unordered_map::find(animation->layerAnimations, reference.itemID); + case NULL_: + return map::find(animation->nullAnimations, reference.itemID); + case TRIGGER: + return &animation->triggers; + default: + return nullptr; + } + } + return nullptr; + } + + Frame* Anm2::frame_get(Reference& reference) + { + Item* item = item_get(reference); + if (!item) return nullptr; + return vector::find(item->frames, reference.frameIndex); + return nullptr; + } + + bool Anm2::spritesheet_add(const std::string& directory, const std::string& path, int& id) + { + return content.spritesheet_add(directory, path, id); + } + + Spritesheet* Anm2::spritesheet_get(int id) + { + return map::find(content.spritesheets, id); + } + + void Anm2::spritesheet_remove(int id) + { + content.spritesheet_remove(id); + } + + std::set Anm2::spritesheets_unused() + { + return content.spritesheets_unused(); + } + + void Anm2::layer_add(int& id) + { + content.layer_add(id); + } + + void Anm2::null_add(int& id) + { + content.null_add(id); + } + + void Anm2::event_add(int& id) + { + content.event_add(id); + } + + std::set Anm2::events_unused() + { + std::set used; + for (auto& animation : animations.items) + for (auto& frame : animation.triggers.frames) + used.insert(frame.eventID); + + std::set unused; + for (auto& id : content.events | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + std::set Anm2::layers_unused() + { + std::set used; + for (auto& animation : animations.items) + for (auto& id : animation.layerAnimations | std::views::keys) + used.insert(id); + + std::set unused; + for (auto& id : content.layers | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + std::set Anm2::nulls_unused() + { + std::set used; + for (auto& animation : animations.items) + for (auto& id : animation.nullAnimations | std::views::keys) + used.insert(id); + + std::set unused; + for (auto& id : content.nulls | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } +} \ No newline at end of file diff --git a/src/anm2.h b/src/anm2.h index 4f56dc9..ef9a820 100644 --- a/src/anm2.h +++ b/src/anm2.h @@ -1,266 +1,238 @@ #pragma once -#include "resources.h" +#include +#include +#include +#include +#include +#include -#define ANM2_SCALE_CONVERT(x) ((float)x / 100.0f) -#define ANM2_TINT_CONVERT(x) ((float)x / 255.0f) +#include "texture.h" +#include "types.h" -#define ANM2_FPS_MIN 0 -#define ANM2_FPS_DEFAULT 30 -#define ANM2_FPS_MAX 120 -#define ANM2_FRAME_NUM_MIN 1 -#define ANM2_FRAME_NUM_MAX 1000000 -#define ANM2_FRAME_DELAY_MIN 1 -#define ANM2_STRING_MAX 0xFF +namespace anm2ed::anm2 +{ + constexpr auto FRAME_NUM_MIN = 1; + constexpr auto FRAME_NUM_MAX = 100000000; + constexpr auto FRAME_DELAY_MIN = 1; + constexpr auto FRAME_DELAY_MAX = FRAME_NUM_MAX; + constexpr auto FPS_MIN = 1; + constexpr auto FPS_MAX = 120; -#define ANM2_EMPTY_ERROR "No path given for anm2" -#define ANM2_READ_ERROR "Failed to read anm2 from file: {}" -#define ANM2_PARSE_ERROR "Failed to parse anm2: {} ({})" -#define ANM2_FRAME_PARSE_ERROR "Failed to parse frame: {} ({})" -#define ANM2_ANIMATION_PARSE_ERROR "Failed to parse frame: {} ({})" -#define ANM2_READ_INFO "Read anm2 from file: {}" -#define ANM2_WRITE_ERROR "Failed to write anm2 to file: {}" -#define ANM2_WRITE_INFO "Wrote anm2 to file: {}" -#define ANM2_CREATED_ON_FORMAT "%d-%B-%Y %I:%M:%S %p" + constexpr auto MERGED_STRING = "(Merged)"; -#define ANM2_ANIMATION_DEFAULT "New Animation" -#define ANM2_EXTENSION "anm2" -#define ANM2_SPRITESHEET_EXTENSION "png" + enum Type + { + NONE, + ROOT, + LAYER, + NULL_, + TRIGGER + }; -#define ANM2_ELEMENT_LIST \ - X(ANIMATED_ACTOR, "AnimatedActor") \ - X(INFO, "Info") \ - X(CONTENT, "Content") \ - X(SPRITESHEETS, "Spritesheets") \ - X(SPRITESHEET, "Spritesheet") \ - X(LAYERS, "Layers") \ - X(LAYER, "Layer") \ - X(NULLS, "Nulls") \ - X(NULL, "Null") \ - X(EVENTS, "Events") \ - X(EVENT, "Event") \ - X(ANIMATIONS, "Animations") \ - X(ANIMATION, "Animation") \ - X(ROOT_ANIMATION, "RootAnimation") \ - X(FRAME, "Frame") \ - X(LAYER_ANIMATIONS, "LayerAnimations") \ - X(LAYER_ANIMATION, "LayerAnimation") \ - X(NULL_ANIMATIONS, "NullAnimations") \ - X(NULL_ANIMATION, "NullAnimation") \ - X(TRIGGERS, "Triggers") \ - X(TRIGGER, "Trigger") + class Reference + { + public: + int animationIndex{-1}; + Type itemType{NONE}; + int itemID{-1}; + int frameIndex{-1}; + int frameTime{-1}; -typedef enum { -#define X(name, str) ANM2_ELEMENT_##name, - ANM2_ELEMENT_LIST -#undef X - ANM2_ELEMENT_COUNT -} Anm2Element; + void previous_frame(int max = FRAME_NUM_MAX - 1); + void next_frame(int max = FRAME_NUM_MAX - 1); + auto operator<=>(const Reference&) const = default; + }; -const inline char* ANM2_ELEMENT_STRINGS[] = { -#define X(name, str) str, - ANM2_ELEMENT_LIST -#undef X -}; + class Info + { + public: + std::string createdBy{"robot"}; + std::string createdOn{}; + int fps = 30; + int version{}; -DEFINE_STRING_TO_ENUM_FUNCTION(ANM2_ELEMENT_STRING_TO_ENUM, Anm2Element, ANM2_ELEMENT_STRINGS, ANM2_ELEMENT_COUNT) + Info(); + Info(tinyxml2::XMLElement* element); + void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent); + }; -#define ANM2_ATTRIBUTE_LIST \ - X(CREATED_BY, "CreatedBy") \ - X(CREATED_ON, "CreatedOn") \ - X(VERSION, "Version") \ - X(FPS, "Fps") \ - X(ID, "Id") \ - X(PATH, "Path") \ - X(NAME, "Name") \ - X(SPRITESHEET_ID, "SpritesheetId") \ - X(SHOW_RECT, "ShowRect") \ - X(DEFAULT_ANIMATION, "DefaultAnimation") \ - X(FRAME_NUM, "FrameNum") \ - X(LOOP, "Loop") \ - X(X_POSITION, "XPosition") \ - X(Y_POSITION, "YPosition") \ - X(X_PIVOT, "XPivot") \ - X(Y_PIVOT, "YPivot") \ - X(X_CROP, "XCrop") \ - X(Y_CROP, "YCrop") \ - X(WIDTH, "Width") \ - X(HEIGHT, "Height") \ - X(X_SCALE, "XScale") \ - X(Y_SCALE, "YScale") \ - X(DELAY, "Delay") \ - X(VISIBLE, "Visible") \ - X(RED_TINT, "RedTint") \ - X(GREEN_TINT, "GreenTint") \ - X(BLUE_TINT, "BlueTint") \ - X(ALPHA_TINT, "AlphaTint") \ - X(RED_OFFSET, "RedOffset") \ - X(GREEN_OFFSET, "GreenOffset") \ - X(BLUE_OFFSET, "BlueOffset") \ - X(ROTATION, "Rotation") \ - X(INTERPOLATED, "Interpolated") \ - X(LAYER_ID, "LayerId") \ - X(NULL_ID, "NullId") \ - X(EVENT_ID, "EventId") \ - X(AT_FRAME, "AtFrame") + class Spritesheet + { + public: + std::filesystem::path path{}; + texture::Texture texture; -typedef enum { -#define X(name, str) ANM2_ATTRIBUTE_##name, - ANM2_ATTRIBUTE_LIST -#undef X - ANM2_ATTRIBUTE_COUNT -} Anm2Attribute; + Spritesheet(); + Spritesheet(tinyxml2::XMLElement* element, int& id); + Spritesheet(const std::string& directory, const std::string& path = {}); + bool save(const std::string& directory, const std::string& path = {}); + void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent, int id); + void reload(const std::string& directory); + bool is_valid(); + }; -static const char* ANM2_ATTRIBUTE_STRINGS[] = { -#define X(name, str) str, - ANM2_ATTRIBUTE_LIST -#undef X -}; + class Layer + { + public: + std::string name{"New Layer"}; + int spritesheetID{}; -DEFINE_STRING_TO_ENUM_FUNCTION(ANM2_ATTRIBUTE_STRING_TO_ENUM, Anm2Attribute, ANM2_ATTRIBUTE_STRINGS, ANM2_ATTRIBUTE_COUNT) + Layer(); + Layer(tinyxml2::XMLElement* element, int& id); + void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent, int id); + }; -enum Anm2Type { ANM2_NONE, ANM2_ROOT, ANM2_LAYER, ANM2_NULL, ANM2_TRIGGER, ANM2_COUNT }; + class Null + { + public: + std::string name{"New Null"}; + bool isShowRect{}; -struct Anm2Spritesheet { - std::string path{}; - Texture texture; - std::vector pixels; + Null(); + Null(tinyxml2::XMLElement* element, int& id); + void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent, int id); + }; - auto operator<=>(const Anm2Spritesheet&) const = default; -}; + class Event + { + public: + std::string name{"New Event"}; -struct Anm2Layer { - std::string name = "New Layer"; - int spritesheetID{}; + Event(); + Event(tinyxml2::XMLElement* element, int& id); + void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent, int id); + }; - auto operator<=>(const Anm2Layer&) const = default; -}; + struct Content + { + std::map spritesheets{}; + std::map layers{}; + std::map nulls{}; + std::map events{}; -struct Anm2Null { - std::string name = "New Null"; - bool isShowRect = false; + Content(); - auto operator<=>(const Anm2Null&) const = default; -}; + void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent); + Content(tinyxml2::XMLElement* element); + bool spritesheet_add(const std::string& directory, const std::string& path, int& id); + void spritesheet_remove(int& id); + std::set spritesheets_unused(); + void layer_add(int& id); + void null_add(int& id); + void event_add(int& id); + }; -struct Anm2Event { - std::string name = "New Event"; +#define MEMBERS \ + X(isVisible, bool, true) \ + X(isInterpolated, bool, false) \ + X(rotation, float, 0.0f) \ + X(delay, int, FRAME_DELAY_MIN) \ + X(atFrame, int, -1) \ + X(eventID, int, -1) \ + X(pivot, glm::vec2, {}) \ + X(crop, glm::vec2, {}) \ + X(position, glm::vec2, {}) \ + X(size, glm::vec2, {}) \ + X(scale, glm::vec2, glm::vec2(100.0f)) \ + X(offset, glm::vec3, types::color::TRANSPARENT) \ + X(tint, glm::vec4, types::color::WHITE) - auto operator<=>(const Anm2Event&) const = default; -}; - -#define ANM2_FRAME_MEMBERS \ - X(isVisible, bool, true) \ - X(isInterpolated, bool, false) \ - X(rotation, float, 0.0f) \ - X(delay, int, ANM2_FRAME_DELAY_MIN) \ - X(atFrame, int, INDEX_NONE) \ - X(eventID, int, ID_NONE) \ - X(crop, vec2, {}) \ - X(pivot, vec2, {}) \ - X(position, vec2, {}) \ - X(size, vec2, {}) \ - X(scale, vec2, {100, 100}) \ - X(offsetRGB, vec3, COLOR_OFFSET_NONE) \ - X(tintRGBA, vec4, COLOR_OPAQUE) - -struct Anm2Frame { + class Frame + { + public: #define X(name, type, ...) type name = __VA_ARGS__; - ANM2_FRAME_MEMBERS + MEMBERS #undef X - auto operator<=>(const Anm2Frame&) const = default; -}; -struct Anm2FrameChange { + Frame(); + Frame(tinyxml2::XMLElement* element, Type type); + void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent, Type type); + void shorten(); + void extend(); + }; + + struct FrameChange + { #define X(name, type, ...) std::optional name{}; - ANM2_FRAME_MEMBERS + MEMBERS #undef X -}; + }; -struct Anm2Item { - bool isVisible = true; - std::vector frames; +#undef MEMBERS - auto operator<=>(const Anm2Item&) const = default; -}; + class Item + { + public: + std::vector frames{}; + bool isVisible{true}; -struct Anm2Animation { - int frameNum = ANM2_FRAME_NUM_MIN; - std::string name = ANM2_ANIMATION_DEFAULT; - bool isLoop = true; - Anm2Item rootAnimation; - std::unordered_map layerAnimations; - std::vector layerOrder; - std::map nullAnimations; - Anm2Item triggers; + Item(); - auto operator<=>(const Anm2Animation&) const = default; -}; + Item(tinyxml2::XMLElement* element, Type type, int* id = nullptr); + void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent, Type type, int id = -1); + int length(Type type); + Frame frame_generate(float time, Type type); + }; -struct Anm2 { - std::string path{}; - std::string createdBy = "robot"; - std::string createdOn{}; - std::string defaultAnimation = ANM2_ANIMATION_DEFAULT; - std::map spritesheets; - std::map layers; - std::map nulls; - std::map events; - std::vector animations; - int fps = ANM2_FPS_DEFAULT; - int version{}; + class Animation + { + public: + std::string name{"New Animation"}; + int frameNum{FRAME_NUM_MIN}; + bool isLoop{true}; + Item rootAnimation; + std::unordered_map layerAnimations{}; + std::vector layerOrder{}; + std::map nullAnimations{}; + Item triggers; - auto operator<=>(const Anm2&) const = default; -}; + Animation(); + Animation(tinyxml2::XMLElement* element); + Item* item_get(Type type, int id = -1); + void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent); + int length(); + }; -struct Anm2Reference { - int animationIndex = ID_NONE; - Anm2Type itemType = ANM2_NONE; - int itemID = ID_NONE; - int frameIndex = INDEX_NONE; - float time = VALUE_NONE; - auto operator<=>(const Anm2Reference&) const = default; -}; + struct Animations + { + std::string defaultAnimation{}; + std::vector items{}; -enum Anm2MergeType { ANM2_MERGE_APPEND, ANM2_MERGE_REPLACE, ANM2_MERGE_PREPEND, ANM2_MERGE_IGNORE }; + Animations(); -enum Anm2ChangeType { ANM2_CHANGE_ADD, ANM2_CHANGE_SUBTRACT, ANM2_CHANGE_SET }; + Animations(tinyxml2::XMLElement* element); + void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent); + int length(); + int merge(int target, std::set& sources, types::merge::Type type, bool isDeleteAfter = true); + }; -enum OnionskinDrawOrder { ONIONSKIN_BELOW, ONIONSKIN_ABOVE }; + class Anm2 + { + bool isValid{false}; -Anm2Animation* anm2_animation_from_reference(Anm2* self, Anm2Reference reference); -Anm2Frame* anm2_frame_add(Anm2* self, Anm2Frame* frame, Anm2Reference reference); -Anm2Frame* anm2_frame_from_reference(Anm2* self, Anm2Reference reference); -Anm2Item* anm2_item_from_reference(Anm2* self, Anm2Reference reference); -bool anm2_animations_deserialize_from_xml(std::vector& animations, const std::string& xml); -bool anm2_deserialize(Anm2* self, const std::string& path, bool isTextures = true); -bool anm2_frame_deserialize_from_xml(Anm2Frame* frame, const std::string& xml); -bool anm2_serialize(Anm2* self, const std::string& path); -int anm2_animation_add(Anm2* self, Anm2Animation* animation = nullptr, int index = INDEX_NONE); -int anm2_animation_length_get(Anm2Animation* self); -int anm2_frame_index_from_time(Anm2* self, Anm2Reference reference, float time); -int anm2_layer_add(Anm2* self); -int anm2_null_add(Anm2* self); -vec4 anm2_animation_rect_get(Anm2* anm2, Anm2Reference reference, bool isRootTransform); -void anm2_animation_layer_animation_add(Anm2Animation* animation, int id); -void anm2_animation_layer_animation_remove(Anm2Animation* animation, int id); -void anm2_animation_length_set(Anm2Animation* self); -void anm2_animation_merge(Anm2* self, int animationID, std::set mergeIndices, Anm2MergeType type); -void anm2_animation_null_animation_add(Anm2Animation* animation, int id); -void anm2_animation_null_animation_remove(Anm2Animation* animation, int id); -void anm2_animations_remove(Anm2* self, const std::set indices); -void anm2_animation_serialize_to_string(Anm2Animation* animation, std::string* string); -void anm2_frame_bake(Anm2* self, Anm2Reference reference, int interval, bool isRoundScale, bool isRoundRotation); -void anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, float time); -void anm2_frame_remove(Anm2* self, Anm2Reference reference); -void anm2_frame_serialize_to_string(Anm2Frame* frame, Anm2Type type, std::string* string); -void anm2_free(Anm2* self); -void anm2_generate_from_grid(Anm2* self, Anm2Reference reference, vec2 startPosition, vec2 size, vec2 pivot, int columns, int count, int delay); -void anm2_item_frame_set(Anm2* self, Anm2Reference reference, const Anm2FrameChange& change, Anm2ChangeType changeType, int start, int count); -void anm2_layer_remove(Anm2* self, int id); -void anm2_new(Anm2* self); -void anm2_null_remove(Anm2* self, int id); -void anm2_scale(Anm2* self, float scale); -void anm2_spritesheet_texture_pixels_download(Anm2* self); -void anm2_spritesheet_texture_pixels_upload(Anm2* self); -float anm2_time_from_reference(Anm2* self, Anm2Reference reference); \ No newline at end of file + public: + Info info{}; + Content content{}; + Animations animations{}; + + Anm2(); + bool serialize(const std::string& path, std::string* errorString = nullptr); + std::string to_string(); + Anm2(const std::string& path, std::string* errorString = nullptr); + uint64_t hash(); + Animation* animation_get(Reference& reference); + Item* item_get(Reference& reference); + Frame* frame_get(Reference& reference); + bool spritesheet_add(const std::string& directory, const std::string& path, int& id); + Spritesheet* spritesheet_get(int id); + void spritesheet_remove(int id); + std::set spritesheets_unused(); + void layer_add(int& id); + void null_add(int& id); + void event_add(int& id); + std::set events_unused(); + std::set layers_unused(); + std::set nulls_unused(); + }; +} \ No newline at end of file diff --git a/src/canvas.cpp b/src/canvas.cpp index 5e55649..2932a80 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1,224 +1,282 @@ #include "canvas.h" -static void _canvas_framebuffer_set(Canvas* self, const ivec2& size) { - self->size = size; - self->previousSize = size; +#include "math.h" +#include +#include +#include - glBindFramebuffer(GL_FRAMEBUFFER, self->fbo); +using namespace glm; +using namespace anm2ed::shader; - glBindTexture(GL_TEXTURE_2D, self->framebuffer); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self->size.x, self->size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +namespace anm2ed::canvas +{ + constexpr float AXIS_VERTICES[] = {-1.0f, 0.0f, 1.0f, 0.0f}; + constexpr float GRID_VERTICES[] = {-1.f, -1.f, 0.f, 0.f, 3.f, -1.f, 2.f, 0.f, -1.f, 3.f, 0.f, 2.f}; + constexpr float RECT_VERTICES[] = {0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; + constexpr GLuint TEXTURE_INDICES[] = {0, 1, 2, 2, 3, 0}; - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->framebuffer, 0); + Canvas::Canvas() = default; - glBindRenderbuffer(GL_RENDERBUFFER, self->rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, self->size.x, self->size.y); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, self->rbo); + Canvas::Canvas(vec2 size) + { + this->size = size; + previousSize = size; - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} + // Axis + glGenVertexArrays(1, &axisVAO); + glGenBuffers(1, &axisVBO); -void canvas_init(Canvas* self, const ivec2& size) { - // Axis - glGenVertexArrays(1, &self->axisVAO); - glGenBuffers(1, &self->axisVBO); + glBindVertexArray(axisVAO); - glBindVertexArray(self->axisVAO); + glBindBuffer(GL_ARRAY_BUFFER, axisVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(AXIS_VERTICES), AXIS_VERTICES, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, self->axisVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_AXIS_VERTICES), CANVAS_AXIS_VERTICES, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, sizeof(float), (void*)0); + // Grid + glGenVertexArrays(1, &gridVAO); + glBindVertexArray(gridVAO); - // Grid - glGenVertexArrays(1, &self->gridVAO); - glGenBuffers(1, &self->gridVBO); + glGenBuffers(1, &gridVBO); + glBindBuffer(GL_ARRAY_BUFFER, gridVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(GRID_VERTICES), GRID_VERTICES, GL_STATIC_DRAW); - glBindVertexArray(self->gridVAO); - glBindBuffer(GL_ARRAY_BUFFER, self->gridVBO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)0); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)(sizeof(float) * 2)); - // Rect - glGenVertexArrays(1, &self->rectVAO); - glGenBuffers(1, &self->rectVBO); + glBindVertexArray(0); - glBindVertexArray(self->rectVAO); + // Rect + glGenVertexArrays(1, &rectVAO); + glGenBuffers(1, &rectVBO); - glBindBuffer(GL_ARRAY_BUFFER, self->rectVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_RECT_VERTICES), CANVAS_RECT_VERTICES, GL_STATIC_DRAW); + glBindVertexArray(rectVAO); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); + glBindBuffer(GL_ARRAY_BUFFER, rectVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(RECT_VERTICES), RECT_VERTICES, GL_STATIC_DRAW); - // Grid - glGenVertexArrays(1, &self->gridVAO); - glBindVertexArray(self->gridVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); - glGenBuffers(1, &self->gridVBO); - glBindBuffer(GL_ARRAY_BUFFER, self->gridVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_GRID_VERTICES), CANVAS_GRID_VERTICES, GL_STATIC_DRAW); + // Texture + glGenVertexArrays(1, &textureVAO); + glGenBuffers(1, &textureVBO); + glGenBuffers(1, &textureEBO); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*)0); + glBindVertexArray(textureVAO); - glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, textureVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 4, nullptr, GL_DYNAMIC_DRAW); - // Texture - glGenVertexArrays(1, &self->textureVAO); - glGenBuffers(1, &self->textureVBO); - glGenBuffers(1, &self->textureEBO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, textureEBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(TEXTURE_INDICES), TEXTURE_INDICES, GL_DYNAMIC_DRAW); - glBindVertexArray(self->textureVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); - glBindBuffer(GL_ARRAY_BUFFER, self->textureVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 4, nullptr, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->textureEBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GL_TEXTURE_INDICES), GL_TEXTURE_INDICES, GL_DYNAMIC_DRAW); + glBindVertexArray(0); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); + // Framebuffer + glGenTextures(1, &texture); + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); - - glBindVertexArray(0); - - // Framebuffer - glGenTextures(1, &self->framebuffer); - glGenFramebuffers(1, &self->fbo); - glGenRenderbuffers(1, &self->rbo); - _canvas_framebuffer_set(self, size); - - self->isInit = true; -} - -mat4 canvas_transform_get(Canvas* self, vec2 pan, float zoom, OriginType origin) { - float zoomFactor = PERCENT_TO_UNIT(zoom); - mat4 projection = glm::ortho(0.0f, (float)self->size.x, 0.0f, (float)self->size.y, -1.0f, 1.0f); - mat4 view = mat4{1.0f}; - vec2 size = vec2(self->size.x, self->size.y); - - switch (origin) { - case ORIGIN_TOP_LEFT: - view = glm::translate(view, vec3(pan, 0.0f)); - break; - default: - view = glm::translate(view, vec3((size * 0.5f) + pan, 0.0f)); - break; + framebuffer_set(); } - view = glm::scale(view, vec3(zoomFactor, zoomFactor, 1.0f)); + Canvas::~Canvas() + { + if (!is_valid()) return; - return projection * view; + glDeleteFramebuffers(1, &fbo); + glDeleteRenderbuffers(1, &rbo); + glDeleteTextures(1, &texture); + + glDeleteVertexArrays(1, &axisVAO); + glDeleteBuffers(1, &axisVBO); + + glDeleteVertexArrays(1, &gridVAO); + glDeleteBuffers(1, &gridVBO); + + glDeleteVertexArrays(1, &rectVAO); + glDeleteBuffers(1, &rectVBO); + } + + bool Canvas::is_valid() + { + return fbo != 0; + } + + void Canvas::framebuffer_set() + { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, size.x, size.y); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + void Canvas::framebuffer_resize_check() + { + if (previousSize != size) + { + framebuffer_set(); + previousSize = size; + } + } + + void Canvas::size_set(vec2 size) + { + this->size = size; + framebuffer_resize_check(); + } + + mat4 Canvas::transform_get(float zoom, vec2 pan) + { + auto zoomFactor = math::percent_to_unit(zoom); + auto projection = glm::ortho(0.0f, (float)size.x, 0.0f, (float)size.y, -1.0f, 1.0f); + auto view = mat4{1.0f}; + + view = glm::translate(view, vec3((size * 0.5f) + pan, 0.0f)); + view = glm::scale(view, vec3(zoomFactor, zoomFactor, 1.0f)); + + return projection * view; + } + + void Canvas::axes_render(Shader& shader, float zoom, vec2 pan, vec4 color) + { + auto originNDC = transform_get(zoom, pan) * vec4(0.0f, 0.0f, 0.0f, 1.0f); + originNDC /= originNDC.w; + + glUseProgram(shader.id); + + glUniform4fv(glGetUniformLocation(shader.id, shader::UNIFORM_COLOR), 1, value_ptr(color)); + glUniform2f(glGetUniformLocation(shader.id, shader::UNIFORM_ORIGIN_NDC), originNDC.x, originNDC.y); + + glBindVertexArray(axisVAO); + + glUniform1i(glGetUniformLocation(shader.id, shader::UNIFORM_AXIS), 0); + glDrawArrays(GL_LINES, 0, 2); + + glUniform1i(glGetUniformLocation(shader.id, shader::UNIFORM_AXIS), 1); + glDrawArrays(GL_LINES, 0, 2); + + glBindVertexArray(0); + glUseProgram(0); + } + + void Canvas::grid_render(Shader& shader, float zoom, vec2 pan, ivec2 size, ivec2 offset, vec4 color) + { + auto zoomFactor = math::percent_to_unit(zoom); + + glUseProgram(shader.id); + + glUniform2f(glGetUniformLocation(shader.id, shader::UNIFORM_VIEW_SIZE), this->size.x, this->size.y); + glUniform2f(glGetUniformLocation(shader.id, shader::UNIFORM_PAN), pan.x, pan.y); + glUniform1f(glGetUniformLocation(shader.id, shader::UNIFORM_ZOOM), zoomFactor); + glUniform2f(glGetUniformLocation(shader.id, shader::UNIFORM_SIZE), (float)size.x, (float)size.y); + glUniform2f(glGetUniformLocation(shader.id, shader::UNIFORM_OFFSET), (float)offset.x, (float)offset.y); + glUniform4f(glGetUniformLocation(shader.id, shader::UNIFORM_COLOR), color.r, color.g, color.b, color.a); + + glBindVertexArray(gridVAO); + glDrawArrays(GL_TRIANGLES, 0, 3); + glBindVertexArray(0); + + glUseProgram(0); + } + + void Canvas::texture_render(Shader& shader, GLuint& texture, mat4& transform, vec4 tint, vec3 colorOffset, + float* vertices) + { + glUseProgram(shader.id); + + glUniform1i(glGetUniformLocation(shader.id, shader::UNIFORM_TEXTURE), 0); + glUniform3fv(glGetUniformLocation(shader.id, shader::UNIFORM_COLOR_OFFSET), 1, value_ptr(colorOffset)); + glUniform4fv(glGetUniformLocation(shader.id, shader::UNIFORM_TINT), 1, value_ptr(tint)); + glUniformMatrix4fv(glGetUniformLocation(shader.id, shader::UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); + + glBindVertexArray(textureVAO); + + glBindBuffer(GL_ARRAY_BUFFER, textureVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(TEXTURE_VERTICES), vertices, GL_DYNAMIC_DRAW); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glUseProgram(0); + } + + void Canvas::rect_render(Shader& shader, mat4& transform, vec4 color) + { + glUseProgram(shader.id); + + glUniformMatrix4fv(glGetUniformLocation(shader.id, shader::UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); + glUniform4fv(glGetUniformLocation(shader.id, shader::UNIFORM_COLOR), 1, value_ptr(color)); + + glBindVertexArray(rectVAO); + glDrawArrays(GL_LINE_LOOP, 0, 4); + + glBindVertexArray(0); + glUseProgram(0); + } + + void Canvas::viewport_set() + { + glViewport(0, 0, size.x, size.y); + } + + void Canvas::clear(vec4& color) + { + glClearColor(color.r, color.g, color.b, color.a); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + void Canvas::bind() + { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + } + + void Canvas::unbind() + { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + void Canvas::zoom_set(float& zoom, vec2& pan, vec2& focus, float step) + { + auto zoomFactor = math::percent_to_unit(zoom); + float newZoom = glm::clamp(math::round_nearest_multiple(zoom + step, step), canvas::ZOOM_MIN, canvas::ZOOM_MAX); + if (newZoom != zoom) + { + float newZoomFactor = math::percent_to_unit(newZoom); + pan += focus * (zoomFactor - newZoomFactor); + zoom = newZoom; + } + } + + vec2 Canvas::position_translate(float& zoom, vec2& pan, vec2 position) + { + auto zoomFactor = math::percent_to_unit(zoom); + return (position - pan - (size * 0.5f)) / zoomFactor; + } } - -void canvas_clear(vec4& color) { - glClearColor(color.r, color.g, color.b, color.a); - glClear(GL_COLOR_BUFFER_BIT); -} - -void canvas_viewport_set(Canvas* self) { glViewport(0, 0, (int)self->size.x, (int)self->size.y); } - -void canvas_framebuffer_resize_check(Canvas* self) { - if (self->previousSize != self->size) - _canvas_framebuffer_set(self, self->size); -} - -void canvas_grid_draw(Canvas* self, GLuint& shader, mat4& transform, ivec2& size, ivec2& offset, vec4& color) { - mat4 inverseTransform = glm::inverse(transform); - - glUseProgram(shader); - - glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_MODEL), 1, GL_FALSE, glm::value_ptr(inverseTransform)); - glUniform2f(glGetUniformLocation(shader, SHADER_UNIFORM_SIZE), size.x, size.y); - glUniform2f(glGetUniformLocation(shader, SHADER_UNIFORM_OFFSET), offset.x, offset.y); - glUniform4f(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), color.r, color.g, color.b, color.a); - - glBindVertexArray(self->gridVAO); - glDrawArrays(GL_TRIANGLES, 0, 3); - glBindVertexArray(0); - - glUseProgram(0); -} - -void canvas_texture_draw(Canvas* self, GLuint& shader, GLuint& texture, mat4& transform, const float* vertices, vec4 tint, vec3 colorOffset) { - glUseProgram(shader); - - glBindVertexArray(self->textureVAO); - - glBindBuffer(GL_ARRAY_BUFFER, self->textureVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_TEXTURE_VERTICES), vertices, GL_DYNAMIC_DRAW); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture); - - glUniform1i(glGetUniformLocation(shader, SHADER_UNIFORM_TEXTURE), 0); - glUniform3fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR_OFFSET), 1, value_ptr(colorOffset)); - glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TINT), 1, value_ptr(tint)); - glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); - - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindTexture(GL_TEXTURE_2D, 0); - glUseProgram(0); -} - -void canvas_rect_draw(Canvas* self, const GLuint& shader, const mat4& transform, const vec4& color) { - glUseProgram(shader); - - glBindVertexArray(self->rectVAO); - - glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); - glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), 1, value_ptr(color)); - - glDrawArrays(GL_LINE_LOOP, 0, 4); - - glBindVertexArray(0); - glUseProgram(0); -} - -void canvas_axes_draw(Canvas* self, GLuint& shader, mat4& transform, vec4& color) { - vec4 originNDC = transform * vec4(0.0f, 0.0f, 0.0f, 1.0f); - originNDC /= originNDC.w; - - glUseProgram(shader); - glBindVertexArray(self->axisVAO); - glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), 1, value_ptr(color)); - glUniform2f(glGetUniformLocation(shader, SHADER_UNIFORM_ORIGIN_NDC), originNDC.x, originNDC.y); - glUniform1i(glGetUniformLocation(shader, SHADER_UNIFORM_AXIS), 0); - glDrawArrays(GL_LINES, 0, 2); - glUniform1i(glGetUniformLocation(shader, SHADER_UNIFORM_AXIS), 1); - glDrawArrays(GL_LINES, 0, 2); - glBindVertexArray(0); - glUseProgram(0); -} - -void canvas_bind(Canvas* self) { glBindFramebuffer(GL_FRAMEBUFFER, self->fbo); } - -void canvas_unbind(void) { glBindFramebuffer(GL_FRAMEBUFFER, 0); } - -void canvas_free(Canvas* self) { - if (!self->isInit) - return; - - glDeleteFramebuffers(1, &self->fbo); - glDeleteRenderbuffers(1, &self->rbo); - glDeleteTextures(1, &self->framebuffer); - glDeleteVertexArrays(1, &self->axisVAO); - glDeleteVertexArrays(1, &self->rectVAO); - glDeleteVertexArrays(1, &self->gridVAO); - glDeleteVertexArrays(1, &self->textureVAO); - glDeleteBuffers(1, &self->axisVBO); - glDeleteBuffers(1, &self->rectVBO); - glDeleteBuffers(1, &self->gridVBO); - glDeleteBuffers(1, &self->textureVBO); - glDeleteBuffers(1, &self->textureEBO); -} \ No newline at end of file diff --git a/src/canvas.h b/src/canvas.h index d7f58e2..55e1672 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -1,63 +1,55 @@ #pragma once -#include "resources.h" +#include +#include -#define CANVAS_ZOOM_MIN 1.0f -#define CANVAS_ZOOM_MAX 2000.0f -#define CANVAS_ZOOM_DEFAULT 100.0f -#define CANVAS_ZOOM_STEP 100.0f -#define CANVAS_GRID_MIN 1 -#define CANVAS_GRID_MAX 1000 -#define CANVAS_GRID_DEFAULT 32 +#include "shader.h" -const inline vec2 CANVAS_PIVOT_SIZE = {4, 4}; -const inline vec2 CANVAS_SCALE_DEFAULT = {1.0f, 1.0f}; +namespace anm2ed::canvas +{ + constexpr float TEXTURE_VERTICES[] = {0, 0, 0.0f, 0.0f, 1, 0, 1.0f, 0.0f, 1, 1, 1.0f, 1.0f, 0, 1, 0.0f, 1.0f}; -const inline float CANVAS_AXIS_VERTICES[] = {-1.0f, 1.0f}; + constexpr auto ZOOM_MIN = 1.0f; + constexpr auto ZOOM_MAX = 2000.0f; + constexpr auto POSITION_FORMAT = "Position: ({:8} {:8})"; -const inline float CANVAS_GRID_VERTICES[] = {-1.0f, -1.0f, 3.0f, -1.0f, -1.0f, 3.0f}; + class Canvas + { + public: + GLuint fbo{}; + GLuint rbo{}; + GLuint axisVAO{}; + GLuint axisVBO{}; + GLuint rectVAO{}; + GLuint rectVBO{}; + GLuint gridVAO{}; + GLuint gridVBO{}; + GLuint textureVAO{}; + GLuint textureVBO{}; + GLuint textureEBO{}; + GLuint texture{}; + glm::vec2 previousSize{}; + glm::vec2 size{}; -const inline float CANVAS_RECT_VERTICES[] = {0, 0, 1, 0, 1, 1, 0, 1}; - -const inline float CANVAS_TEXTURE_VERTICES[] = {0, 0, 0.0f, 0.0f, 1, 0, 1.0f, 0.0f, 1, 1, 1.0f, 1.0f, 0, 1, 0.0f, 1.0f}; - -struct Canvas { - GLuint fbo{}; - GLuint rbo{}; - GLuint axisVAO{}; - GLuint axisVBO{}; - GLuint rectVAO{}; - GLuint rectVBO{}; - GLuint gridVAO{}; - GLuint gridVBO{}; - GLuint framebuffer{}; - GLuint textureVAO{}; - GLuint textureVBO{}; - GLuint textureEBO{}; - ivec2 size{}; - ivec2 previousSize{}; - bool isInit = false; -}; - -#define UV_VERTICES(uvMin, uvMax) {0, 0, uvMin.x, uvMin.y, 1, 0, uvMax.x, uvMin.y, 1, 1, uvMax.x, uvMax.y, 0, 1, uvMin.x, uvMax.y} - -#define ATLAS_UV_MIN(type) (ATLAS_POSITION(type) / TEXTURE_ATLAS_SIZE) -#define ATLAS_UV_MAX(type) ((ATLAS_POSITION(type) + ATLAS_SIZE(type)) / TEXTURE_ATLAS_SIZE) -#define ATLAS_UV_ARGS(type) ATLAS_UV_MIN(type), ATLAS_UV_MAX(type) -#define ATLAS_UV_VERTICES(type) UV_VERTICES(ATLAS_UV_MIN(type), ATLAS_UV_MAX(type)) - -mat4 canvas_transform_get(Canvas* self, vec2 pan, float zoom, OriginType origin); -void canvas_axes_draw(Canvas* self, GLuint& shader, mat4& transform, vec4& color); -void canvas_bind(Canvas* self); -void canvas_clear(vec4& color); -void canvas_draw(Canvas* self); -void canvas_free(Canvas* self); -void canvas_grid_draw(Canvas* self, GLuint& shader, mat4& transform, ivec2& size, ivec2& offset, vec4& color); -void canvas_init(Canvas* self, const ivec2& size); -void canvas_rect_draw(Canvas* self, const GLuint& shader, const mat4& transform, const vec4& color); -void canvas_framebuffer_resize_check(Canvas* self); -void canvas_unbind(void); -void canvas_viewport_set(Canvas* self); - -void canvas_texture_draw(Canvas* self, GLuint& shader, GLuint& texture, mat4& transform, const float* vertices = CANVAS_TEXTURE_VERTICES, - vec4 tint = COLOR_OPAQUE, vec3 colorOffset = COLOR_OFFSET_NONE); \ No newline at end of file + Canvas(); + Canvas(glm::vec2 size); + ~Canvas(); + bool is_valid(); + void framebuffer_set(); + void framebuffer_resize_check(); + void size_set(glm::vec2 size); + glm::mat4 transform_get(float zoom, glm::vec2 pan); + void axes_render(shader::Shader& shader, float zoom, glm::vec2 pan, glm::vec4 color = glm::vec4(1.0f)); + void grid_render(shader::Shader& shader, float zoom, glm::vec2 pan, glm::ivec2 size = glm::ivec2(32, 32), + glm::ivec2 offset = {}, glm::vec4 color = glm::vec4(1.0f)); + void texture_render(shader::Shader& shader, GLuint& texture, glm::mat4& transform, glm::vec4 tint = glm::vec4(1.0f), + glm::vec3 colorOffset = {}, float* vertices = (float*)TEXTURE_VERTICES); + void rect_render(shader::Shader& shader, glm::mat4& transform, glm::vec4 color = glm::vec4(1.0f)); + void viewport_set(); + void clear(glm::vec4& color); + void bind(); + void unbind(); + void zoom_set(float& zoom, glm::vec2& pan, glm::vec2& focus, float step); + glm::vec2 position_translate(float& zoom, glm::vec2& pan, glm::vec2 position); + }; +} diff --git a/src/clipboard.cpp b/src/clipboard.cpp deleted file mode 100644 index abe61fd..0000000 --- a/src/clipboard.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "clipboard.h" - -void clipboard_copy(Clipboard* self) { - std::string clipboardText{}; - - auto clipboard_text_set = [&]() { - if (!SDL_SetClipboardText(clipboardText.c_str())) - log_warning(std::format(CLIPBOARD_TEXT_SET_WARNING, SDL_GetError())); - }; - - switch (self->type) { - case CLIPBOARD_FRAME: { - if (Anm2Reference* reference = std::get_if(&self->destination)) { - if (Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *reference)) { - anm2_frame_serialize_to_string(frame, reference->itemType, &clipboardText); - clipboard_text_set(); - } - } - break; - } - case CLIPBOARD_ANIMATION: { - if (std::set* set = std::get_if>(&self->source)) { - for (auto& i : *set) { - if (Anm2Animation* animation = anm2_animation_from_reference(self->anm2, {i})) { - std::string animationText{}; - anm2_animation_serialize_to_string(animation, &animationText); - clipboardText += animationText; - } - } - clipboard_text_set(); - } - break; - } - default: - break; - } -} - -void clipboard_cut(Clipboard* self) { - clipboard_copy(self); - - switch (self->type) { - case CLIPBOARD_FRAME: { - if (Anm2Reference* reference = std::get_if(&self->destination)) - anm2_frame_remove(self->anm2, *reference); - break; - } - case CLIPBOARD_ANIMATION: { - if (std::set* set = std::get_if>(&self->source)) - anm2_animations_remove(self->anm2, *set); - break; - } - default: - break; - } -} - -bool clipboard_paste(Clipboard* self) { - auto clipboard_string = [&]() { - char* clipboardText = SDL_GetClipboardText(); - std::string clipboardString = std::string(clipboardText); - SDL_free(clipboardText); - return clipboardString; - }; - - switch (self->type) { - case CLIPBOARD_FRAME: { - if (Anm2Reference* reference = std::get_if(&self->destination)) { - Anm2Frame frame; - if (!anm2_frame_deserialize_from_xml(&frame, clipboard_string())) - return false; - anm2_frame_add(self->anm2, &frame, *reference); - } - break; - } - case CLIPBOARD_ANIMATION: { - if (int* index = std::get_if(&self->destination)) { - std::vector clipboardAnimations; - if (!anm2_animations_deserialize_from_xml(clipboardAnimations, clipboard_string())) - return false; - - int useIndex = std::clamp(*index + 1, 0, (int)self->anm2->animations.size()); - - for (auto& animation : clipboardAnimations) - anm2_animation_add(self->anm2, &animation, useIndex++); - } - break; - } - default: - break; - } - - return true; -} - -void clipboard_init(Clipboard* self, Anm2* anm2) { self->anm2 = anm2; } -bool clipboard_is_value(void) { return SDL_HasClipboardText(); } \ No newline at end of file diff --git a/src/clipboard.h b/src/clipboard.h deleted file mode 100644 index 2ee4f7c..0000000 --- a/src/clipboard.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "anm2.h" -#include - -#define CLIPBOARD_TEXT_SET_WARNING "Unable to set clipboard text! ({})" - -enum ClipboardType { CLIPBOARD_NONE, CLIPBOARD_FRAME, CLIPBOARD_ANIMATION }; - -using ClipboardValue = std::variant, int>; - -struct Clipboard { - Anm2* anm2 = nullptr; - ClipboardType type; - ClipboardValue source; - ClipboardValue destination; -}; - -bool clipboard_is_value(void); -void clipboard_copy(Clipboard* self); -void clipboard_cut(Clipboard* self); -bool clipboard_paste(Clipboard* self); -void clipboard_init(Clipboard* self, Anm2* anm2); \ No newline at end of file diff --git a/src/dialog.cpp b/src/dialog.cpp index 1db4a23..67da4f6 100644 --- a/src/dialog.cpp +++ b/src/dialog.cpp @@ -1,70 +1,86 @@ #include "dialog.h" #ifdef _WIN32 -#include + #include #endif -static void _dialog_callback(void* userdata, const char* const* filelist, int filter) { - Dialog* self; +#include - self = (Dialog*)userdata; +namespace anm2ed::dialog +{ - if (filelist && filelist[0] && strlen(filelist[0]) > 0) { - self->path = filelist[0]; - self->isSelected = true; - self->selectedFilter = filter; - } else { - self->isSelected = false; - self->selectedFilter = INDEX_NONE; + constexpr SDL_DialogFileFilter FILE_FILTER_ANM2[] = {{"Anm2 file", "anm2;xml"}}; + constexpr SDL_DialogFileFilter FILE_FILTER_SPRITESHEET[] = {{"PNG image", "png"}}; + + void callback(void* userData, const char* const* filelist, int filter) + { + auto self = (Dialog*)(userData); + + if (filelist && filelist[0] && strlen(filelist[0]) > 0) + { + self->path = filelist[0]; + self->selectedFilter = filter; + } + else + self->selectedFilter = -1; } -} -void dialog_init(Dialog* self, SDL_Window* window) { self->window = window; } + Dialog::Dialog() = default; -void dialog_anm2_open(Dialog* self) { - SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_ANM2, std::size(DIALOG_FILE_FILTER_ANM2), nullptr, false); - self->type = DIALOG_ANM2_OPEN; -} + Dialog::Dialog(SDL_Window* window) + { + *this = Dialog(); + this->window = window; + } -void dialog_anm2_save(Dialog* self) { - SDL_ShowSaveFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_ANM2, std::size(DIALOG_FILE_FILTER_ANM2), nullptr); - self->type = DIALOG_ANM2_SAVE; -} + void Dialog::anm2_new() + { + SDL_ShowSaveFileDialog(callback, this, window, FILE_FILTER_ANM2, std::size(FILE_FILTER_ANM2), nullptr); + type = ANM2_NEW; + } -void dialog_spritesheet_add(Dialog* self) { - SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_PNG, std::size(DIALOG_FILE_FILTER_PNG), nullptr, false); - self->type = DIALOG_SPRITESHEET_ADD; -} + void Dialog::anm2_open() + { + SDL_ShowOpenFileDialog(callback, this, window, FILE_FILTER_ANM2, std::size(FILE_FILTER_ANM2), nullptr, false); + type = ANM2_OPEN; + } -void dialog_spritesheet_replace(Dialog* self, int id) { - SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_PNG, std::size(DIALOG_FILE_FILTER_PNG), nullptr, false); - self->replaceID = id; - self->type = DIALOG_SPRITESHEET_REPLACE; -} + void Dialog::anm2_save() + { + SDL_ShowSaveFileDialog(callback, this, window, FILE_FILTER_ANM2, std::size(FILE_FILTER_ANM2), nullptr); + type = ANM2_SAVE; + } -void dialog_render_path_set(Dialog* self, RenderType type) { - SDL_DialogFileFilter filter = DIALOG_RENDER_FILE_FILTERS[type]; + void Dialog::spritesheet_open() + { + SDL_ShowOpenFileDialog(callback, this, window, FILE_FILTER_SPRITESHEET, std::size(FILE_FILTER_SPRITESHEET), nullptr, + false); + type = SPRITESHEET_OPEN; + } - if (type == RENDER_PNG) - SDL_ShowOpenFolderDialog(_dialog_callback, self, self->window, nullptr, false); - else - SDL_ShowSaveFileDialog(_dialog_callback, self, self->window, &filter, 1, nullptr); - self->type = DIALOG_RENDER_PATH_SET; -} + void Dialog::spritesheet_replace() + { + SDL_ShowOpenFileDialog(callback, this, window, FILE_FILTER_SPRITESHEET, std::size(FILE_FILTER_SPRITESHEET), nullptr, + false); + type = SPRITESHEET_REPLACE; + } -void dialog_ffmpeg_path_set(Dialog* self) { - SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_FFMPEG, std::size(DIALOG_FILE_FILTER_FFMPEG), nullptr, false); - self->type = DIALOG_FFMPEG_PATH_SET; -} - -void dialog_explorer_open(const std::string& path) { + void Dialog::file_explorer_open(const std::string& path) + { #ifdef _WIN32 - ShellExecuteA(NULL, DIALOG_FILE_EXPLORER_COMMAND, path.c_str(), NULL, NULL, SW_SHOWNORMAL); + ShellExecuteA(NULL, "open", path.c_str(), NULL, NULL, SW_SHOWNORMAL); #else - char command[DIALOG_FILE_EXPLORER_COMMAND_SIZE]; - snprintf(command, sizeof(command), DIALOG_FILE_EXPLORER_COMMAND, path.c_str()); - system(command); + system(std::format("xdg-open \"{}\" &", path).c_str()); #endif -} + } -void dialog_reset(Dialog* self) { *self = {self->window}; } \ No newline at end of file + void Dialog::reset() + { + *this = Dialog(this->window); + } + + bool Dialog::is_selected_file(Type type) + { + return this->type == type && !path.empty(); + } +}; diff --git a/src/dialog.h b/src/dialog.h index c965e0a..e6983c9 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -1,56 +1,39 @@ #pragma once -#include "render.h" -#include "window.h" +#include -#define DIALOG_FILE_EXPLORER_COMMAND_SIZE 512 +#include -#ifdef _WIN32 -#define DIALOG_FILE_EXPLORER_COMMAND "open" -#else -#define DIALOG_FILE_EXPLORER_COMMAND "xdg-open \"%s\" &" -#endif +namespace anm2ed::dialog +{ + enum Type + { + NONE, + ANM2_NEW, + ANM2_OPEN, + ANM2_SAVE, + SPRITESHEET_OPEN, + SPRITESHEET_REPLACE + }; -const SDL_DialogFileFilter DIALOG_FILE_FILTER_ANM2[] = {{"Anm2 file", "anm2;xml"}}; + class Dialog + { + public: + SDL_Window* window{}; + std::string path{}; + Type type{NONE}; + int selectedFilter{-1}; + int replaceID{-1}; -const SDL_DialogFileFilter DIALOG_FILE_FILTER_PNG[] = {{"PNG image", "png"}}; - -const SDL_DialogFileFilter DIALOG_RENDER_FILE_FILTERS[] = {{"PNG image", "png"}, {"GIF image", "gif"}, {"WebM video", "webm"}, {"MP4 video", "mp4"}}; - -const SDL_DialogFileFilter DIALOG_FILE_FILTER_FFMPEG[] = { -#ifdef _WIN32 - {"Executable", "exe"} -#else - {"Executable", ""} -#endif -}; - -enum DialogType { - DIALOG_NONE, - DIALOG_ANM2_OPEN, - DIALOG_ANM2_SAVE, - DIALOG_SPRITESHEET_ADD, - DIALOG_SPRITESHEET_REPLACE, - DIALOG_RENDER_PATH_SET, - DIALOG_FFMPEG_PATH_SET -}; - -struct Dialog { - SDL_Window* window = nullptr; - std::string path{}; - int selectedFilter = ID_NONE; - int replaceID = ID_NONE; - DialogType type = DIALOG_NONE; - bool isSelected{}; -}; - -void dialog_init(Dialog* self, SDL_Window* window); -void dialog_anm2_open(Dialog* self); -void dialog_spritesheet_add(Dialog* self); -void dialog_spritesheet_replace(Dialog* self, int id); -void dialog_anm2_save(Dialog* self); -void dialog_render_path_set(Dialog* self, RenderType type); -void dialog_render_directory_set(Dialog* self); -void dialog_ffmpeg_path_set(Dialog* self); -void dialog_reset(Dialog* self); -void dialog_explorer_open(const std::string& path); \ No newline at end of file + Dialog(); + Dialog(SDL_Window* window); + void anm2_new(); + void anm2_open(); + void anm2_save(); + void spritesheet_open(); + void spritesheet_replace(); + void file_explorer_open(const std::string& path); + void reset(); + bool is_selected_file(Type type); + }; +} diff --git a/src/dockspace.cpp b/src/dockspace.cpp new file mode 100644 index 0000000..855482a --- /dev/null +++ b/src/dockspace.cpp @@ -0,0 +1,54 @@ +#include "dockspace.h" + +#include "animations.h" +#include "onionskin.h" +#include "tools.h" + +using namespace anm2ed::animations; +using namespace anm2ed::dialog; +using namespace anm2ed::document_manager; +using namespace anm2ed::documents; +using namespace anm2ed::playback; +using namespace anm2ed::resources; +using namespace anm2ed::settings; +using namespace anm2ed::taskbar; + +namespace anm2ed::dockspace +{ + void Dockspace::update(Taskbar& taskbar, Documents& documents, DocumentManager& manager, Settings& settings, + Resources& resources, Dialog& dialog, Playback& playback) + { + + auto viewport = ImGui::GetMainViewport(); + auto windowHeight = viewport->Size.y - taskbar.height - documents.height; + + ImGui::SetNextWindowViewport(viewport->ID); + ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + taskbar.height + documents.height)); + ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, windowHeight)); + + if (ImGui::Begin("##DockSpace", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | + ImGuiWindowFlags_NoNavFocus)) + { + if (ImGui::DockSpace(ImGui::GetID("##DockSpace"), ImVec2(), ImGuiDockNodeFlags_PassthruCentralNode)) + { + if (manager.get()) + { + if (settings.windowIsAnimationPreview) animationPreview.update(manager, settings, resources, playback); + if (settings.windowIsAnimations) animations.update(manager, settings, resources); + if (settings.windowIsEvents) events.update(manager, settings, resources); + if (settings.windowIsFrameProperties) frameProperties.update(manager, settings); + if (settings.windowIsLayers) layers.update(manager, settings, resources); + if (settings.windowIsNulls) nulls.update(manager, settings, resources); + if (settings.windowIsOnionskin) onionskin.update(settings); + if (settings.windowIsSpritesheetEditor) spritesheetEditor.update(manager, settings, resources); + if (settings.windowIsSpritesheets) spritesheets.update(manager, settings, resources, dialog); + if (settings.windowIsTimeline) timeline.update(manager, settings, resources, playback); + if (settings.windowIsTools) tools.update(settings, resources); + } + } + } + ImGui::End(); + } +} diff --git a/src/dockspace.h b/src/dockspace.h new file mode 100644 index 0000000..59f4969 --- /dev/null +++ b/src/dockspace.h @@ -0,0 +1,38 @@ +#pragma once + +#include "animation_preview.h" +#include "animations.h" +#include "documents.h" +#include "events.h" +#include "frame_properties.h" +#include "layers.h" +#include "nulls.h" +#include "onionskin.h" +#include "spritesheet_editor.h" +#include "spritesheets.h" +#include "taskbar.h" +#include "timeline.h" +#include "tools.h" + +namespace anm2ed::dockspace +{ + class Dockspace + { + animation_preview::AnimationPreview animationPreview; + animations::Animations animations; + events::Events events; + frame_properties::FrameProperties frameProperties; + layers::Layers layers; + nulls::Nulls nulls; + onionskin::Onionskin onionskin; + spritesheet_editor::SpritesheetEditor spritesheetEditor; + spritesheets::Spritesheets spritesheets; + timeline::Timeline timeline; + tools::Tools tools; + + public: + void update(taskbar::Taskbar& taskbar, documents::Documents& documents, document_manager::DocumentManager& manager, + settings::Settings& settings, resources::Resources& resources, dialog::Dialog& dialog, + playback::Playback& playback); + }; +} diff --git a/src/document.cpp b/src/document.cpp new file mode 100644 index 0000000..8b002a3 --- /dev/null +++ b/src/document.cpp @@ -0,0 +1,91 @@ +#include "document.h" + +#include "anm2.h" +#include "filesystem.h" + +using namespace anm2ed::anm2; +using namespace anm2ed::filesystem; + +namespace anm2ed::document +{ + Document::Document() = default; + + Document::Document(const std::string& path, bool isNew, std::string* errorString) + { + if (!path_is_exist(path)) return; + + if (isNew) + anm2 = anm2::Anm2(); + else + { + anm2 = Anm2(path, errorString); + if (errorString && !errorString->empty()) return; + } + + this->path = path; + hash_set(); + } + + bool Document::save(const std::string& path, std::string* errorString) + { + this->path = !path.empty() ? path : this->path.string(); + + if (anm2.serialize(this->path, errorString)) + { + hash_set(); + return true; + } + + return false; + } + + void Document::hash_set() + { + saveHash = anm2.hash(); + hash = saveHash; + } + + void Document::hash_time(double time, double interval) + { + if (time - lastHashTime > interval) + { + hash = anm2.hash(); + lastHashTime = time; + } + } + + bool Document::is_dirty() + { + return hash != saveHash; + } + + std::string Document::directory_get() + { + return path.parent_path(); + } + + std::string Document::filename_get() + { + return path.filename().string(); + } + + anm2::Animation* Document::animation_get() + { + return anm2.animation_get(reference); + } + + anm2::Frame* Document::frame_get() + { + return anm2.frame_get(reference); + } + + anm2::Spritesheet* Document::spritesheet_get() + { + return anm2.spritesheet_get(referenceSpritesheet); + } + + bool Document::is_valid() + { + return !path.empty(); + } +}; \ No newline at end of file diff --git a/src/document.h b/src/document.h new file mode 100644 index 0000000..d16377b --- /dev/null +++ b/src/document.h @@ -0,0 +1,51 @@ +#pragma once + +#include "anm2.h" +#include +#include + +#include + +namespace anm2ed::document +{ + class Document + { + public: + std::filesystem::path path{}; + anm2::Anm2 anm2{}; + anm2::Reference reference{}; + + float previewZoom{200}; + glm::vec2 previewPan{}; + glm::vec2 editorPan{}; + float editorZoom{200}; + int overlayIndex{}; + + int referenceSpritesheet{-1}; + + std::set selectedEvents{}; + std::set selectedLayers{}; + std::set selectedNulls{}; + std::set selectedAnimations{}; + std::set selectedSpritesheets{}; + + uint64_t hash{}; + uint64_t saveHash{}; + double lastHashTime{}; + bool isOpen{true}; + + Document(); + + Document(const std::string& path, bool isNew = false, std::string* errorString = nullptr); + bool save(const std::string& path = {}, std::string* errorString = nullptr); + void hash_set(); + void hash_time(double time, double interval = 1.0); + bool is_dirty(); + std::string directory_get(); + std::string filename_get(); + anm2::Animation* animation_get(); + anm2::Frame* frame_get(); + anm2::Spritesheet* spritesheet_get(); + bool is_valid(); + }; +}; \ No newline at end of file diff --git a/src/document_manager.cpp b/src/document_manager.cpp new file mode 100644 index 0000000..f31bb73 --- /dev/null +++ b/src/document_manager.cpp @@ -0,0 +1,76 @@ +#include "document_manager.h" + +#include "toast.h" +#include "util.h" + +using namespace anm2ed::toast; +using namespace anm2ed::util; + +namespace anm2ed::document_manager +{ + Document* DocumentManager::get() + { + return vector::find(documents, selected); + } + + Document* DocumentManager::get(int index) + { + return vector::find(documents, index); + } + + bool DocumentManager::open(const std::string& path, bool isNew) + { + std::string errorString{}; + Document document = Document(path, isNew, &errorString); + if (document.is_valid()) + { + documents.emplace_back(std::move(document)); + selected = documents.size() - 1; + pendingSelected = selected; + toasts.add(std::format("Opened document: {}", path)); + return true; + } + toasts.add_error(std::format("Failed to open document: {} ({})", path, errorString)); + return false; + } + + bool DocumentManager::new_(const std::string& path) + { + return open(path, true); + } + + void DocumentManager::save(int index, const std::string& path) + { + auto document = get(index); + if (!document) return; + std::string errorString{}; + + document->path = !path.empty() ? path : document->path.string(); + + if (document->save(document->path, &errorString)) + toasts.add(std::format("Saved document: {}", document->path.string())); + else + toasts.add_error(std::format("Failed to save document: {} ({})", document->path.string(), errorString)); + } + + void DocumentManager::save(const std::string& path) + { + save(selected, path); + } + + void DocumentManager::close(int index) + { + documents.erase(documents.begin() + index); + } + + void DocumentManager::spritesheet_add(const std::string& path) + { + auto document = get(); + if (!document) return; + + if (int id{}; document->anm2.spritesheet_add(document->directory_get(), path, id)) + toasts.add(std::format("Added spritesheet #{}: {}", id, path)); + else + toasts.add(std::format("Failed to add spritesheet #{}: {}", id, path)); + } +} diff --git a/src/document_manager.h b/src/document_manager.h new file mode 100644 index 0000000..8bd5071 --- /dev/null +++ b/src/document_manager.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#include "document.h" + +using namespace anm2ed::document; + +namespace anm2ed::document_manager +{ + class DocumentManager + { + public: + std::vector documents{}; + int selected{}; + int pendingSelected{}; + + Document* get(); + Document* get(int index); + bool open(const std::string& path, bool isNew = false); + bool new_(const std::string& path); + void save(int index, const std::string& path = {}); + void save(const std::string& path = {}); + void close(int index); + void spritesheet_add(const std::string& path); + }; +} diff --git a/src/documents.cpp b/src/documents.cpp new file mode 100644 index 0000000..59d3bf8 --- /dev/null +++ b/src/documents.cpp @@ -0,0 +1,129 @@ +#include "documents.h" + +#include + +#include "imgui.h" + +using namespace anm2ed::taskbar; +using namespace anm2ed::document_manager; +using namespace anm2ed::resources; + +namespace anm2ed::documents +{ + void Documents::update(Taskbar& taskbar, DocumentManager& manager, Resources& resources) + { + auto viewport = ImGui::GetMainViewport(); + auto windowHeight = ImGui::GetFrameHeightWithSpacing(); + + ImGui::SetNextWindowViewport(viewport->ID); + ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + taskbar.height)); + ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, windowHeight)); + + if (ImGui::Begin("##Documents", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | + ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoScrollWithMouse)) + { + height = ImGui::GetWindowSize().y; + + if (ImGui::BeginTabBar("Documents Bar", ImGuiTabBarFlags_Reorderable)) + { + for (auto [i, document] : std::views::enumerate(manager.documents)) + { + auto isDirty = document.is_dirty(); + auto isRequested = i == manager.pendingSelected; + auto isSelected = i == manager.selected; + + if (isSelected) document.hash_time(ImGui::GetTime()); + + auto font = isDirty ? font::ITALICS : font::REGULAR; + + auto string = isDirty ? std::format("[Not Saved] {}", document.filename_get()) : document.filename_get(); + + auto label = std::format("{}###Document{}", string, i); + + auto flags = isDirty ? ImGuiTabItemFlags_UnsavedDocument : 0; + if (isRequested) flags |= ImGuiTabItemFlags_SetSelected; + + ImGui::PushFont(resources.fonts[font].get(), font::SIZE); + if (ImGui::BeginTabItem(label.c_str(), &document.isOpen, flags)) + { + manager.selected = i; + if (isRequested) manager.pendingSelected = -1; + ImGui::EndTabItem(); + } + ImGui::PopFont(); + + if (!document.isOpen) + { + if (isDirty) + { + isCloseDocument = true; + isOpenCloseDocumentPopup = true; + closeDocumentIndex = i; + document.isOpen = true; + } + else + manager.close(i); + } + } + + ImGui::EndTabBar(); + } + + if (isOpenCloseDocumentPopup) + { + ImGui::OpenPopup("Close Document"); + isOpenCloseDocumentPopup = false; + } + + if (isCloseDocument) + { + ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_None, ImVec2(0.5f, 0.5f)); + ImGui::SetNextWindowSize(ImVec2(), ImGuiCond_None); + + if (ImGui::BeginPopupModal("Close Document", nullptr, ImGuiWindowFlags_NoResize)) + { + auto closeDocument = manager.get(closeDocumentIndex); + + ImGui::TextUnformatted(std::format("The document \"{}\" has been modified.\nDo you want to save it?", + closeDocument->filename_get()) + .c_str()); + + auto widgetSize = imgui::widget_size_with_row_get(3); + + auto close = [&]() + { + closeDocumentIndex = 0; + isCloseDocument = false; + ImGui::CloseCurrentPopup(); + }; + + if (ImGui::Button("Yes", widgetSize)) + { + manager.save(closeDocumentIndex); + manager.close(closeDocumentIndex); + close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("No", widgetSize)) + { + manager.close(closeDocumentIndex); + close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) close(); + + ImGui::EndPopup(); + } + } + } + + ImGui::End(); + } +} diff --git a/src/documents.h b/src/documents.h new file mode 100644 index 0000000..abe724d --- /dev/null +++ b/src/documents.h @@ -0,0 +1,20 @@ +#pragma once + +#include "document_manager.h" +#include "resources.h" +#include "taskbar.h" + +namespace anm2ed::documents +{ + class Documents + { + bool isCloseDocument{}; + bool isOpenCloseDocumentPopup{}; + int closeDocumentIndex{}; + + public: + float height{}; + + void update(taskbar::Taskbar& taskbar, document_manager::DocumentManager& manager, resources::Resources& resources); + }; +} diff --git a/src/editor.cpp b/src/editor.cpp deleted file mode 100644 index 7bd0d3a..0000000 --- a/src/editor.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "editor.h" - -void editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings) { - self->anm2 = anm2; - self->reference = reference; - self->resources = resources; - self->settings = settings; - - canvas_init(&self->canvas, vec2()); -} - -void editor_draw(Editor* self) { - ivec2& gridSize = self->settings->editorGridSize; - ivec2& gridOffset = self->settings->editorGridOffset; - vec4& gridColor = self->settings->editorGridColor; - GLuint& shaderLine = self->resources->shaders[SHADER_LINE]; - GLuint& shaderTexture = self->resources->shaders[SHADER_TEXTURE]; - GLuint& shaderGrid = self->resources->shaders[SHADER_GRID]; - mat4 transform = canvas_transform_get(&self->canvas, self->settings->editorPan, self->settings->editorZoom, ORIGIN_TOP_LEFT); - - canvas_framebuffer_resize_check(&self->canvas); - - canvas_bind(&self->canvas); - canvas_viewport_set(&self->canvas); - canvas_clear(self->settings->editorBackgroundColor); - - if (Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->spritesheetID)) { - Texture& texture = spritesheet->texture; - - mat4 spritesheetTransform = transform * quad_model_get(texture.size); - canvas_texture_draw(&self->canvas, shaderTexture, texture.id, spritesheetTransform); - - if (self->settings->editorIsBorder) - canvas_rect_draw(&self->canvas, shaderLine, spritesheetTransform, EDITOR_BORDER_COLOR); - - Anm2Frame* frame = (Anm2Frame*)anm2_frame_from_reference(self->anm2, *self->reference); - - if (frame) { - mat4 cropTransform = transform * quad_model_get(frame->size, frame->crop); - canvas_rect_draw(&self->canvas, shaderLine, cropTransform, EDITOR_FRAME_COLOR); - - mat4 pivotTransform = transform * quad_model_get(CANVAS_PIVOT_SIZE, frame->crop + frame->pivot, CANVAS_PIVOT_SIZE * 0.5f); - float vertices[] = ATLAS_UV_VERTICES(ATLAS_PIVOT); - canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, pivotTransform, vertices, EDITOR_PIVOT_COLOR); - } - } - - if (self->settings->editorIsGrid) - canvas_grid_draw(&self->canvas, shaderGrid, transform, gridSize, gridOffset, gridColor); - - canvas_unbind(); -} - -void editor_free(Editor* self) { canvas_free(&self->canvas); } \ No newline at end of file diff --git a/src/editor.h b/src/editor.h deleted file mode 100644 index c4a84e8..0000000 --- a/src/editor.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "anm2.h" -#include "canvas.h" -#include "resources.h" -#include "settings.h" - -#define EDITOR_ZOOM_MIN 1.0f -#define EDITOR_ZOOM_MAX 1000.0f -#define EDITOR_ZOOM_STEP 25.0 -#define EDITOR_GRID_MIN 1 -#define EDITOR_GRID_MAX 1000 -#define EDITOR_GRID_OFFSET_MIN 0 -#define EDITOR_GRID_OFFSET_MAX 100 - -static const vec4 EDITOR_BORDER_COLOR = COLOR_OPAQUE; -static const vec4 EDITOR_FRAME_COLOR = COLOR_RED; -static const vec4 EDITOR_PIVOT_COLOR = COLOR_PINK; - -struct Editor { - Anm2* anm2 = nullptr; - Anm2Reference* reference = nullptr; - Resources* resources = nullptr; - Settings* settings = nullptr; - Canvas canvas; - GLuint fbo; - GLuint rbo; - GLuint gridVAO; - GLuint gridVBO; - GLuint texture; - GLuint textureEBO; - GLuint textureVAO; - GLuint textureVBO; - GLuint borderVAO; - GLuint borderVBO; - int spritesheetID = ID_NONE; -}; - -void editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings); -void editor_draw(Editor* self); -void editor_free(Editor* self); \ No newline at end of file diff --git a/src/events.cpp b/src/events.cpp new file mode 100644 index 0000000..c2c624c --- /dev/null +++ b/src/events.cpp @@ -0,0 +1,83 @@ +#include "events.h" + +#include + +#include "imgui.h" + +using namespace anm2ed::document_manager; +using namespace anm2ed::settings; +using namespace anm2ed::resources; +using namespace anm2ed::types; + +namespace anm2ed::events +{ + void Events::update(DocumentManager& manager, Settings& settings, Resources& resources) + { + if (ImGui::Begin("Events", &settings.windowIsEvents)) + { + auto document = manager.get(); + anm2::Anm2& anm2 = document->anm2; + + auto& selection = document->selectedEvents; + storage.UserData = &selection; + storage.AdapterSetItemSelected = imgui::external_storage_set; + + auto childSize = imgui::size_with_footer_get(); + + if (ImGui::BeginChild("##Events Child", childSize, true)) + { + ImGuiMultiSelectIO* io = + ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, selection.size(), anm2.content.events.size()); + storage.ApplyRequests(io); + + for (auto& [id, event] : anm2.content.events) + { + auto isSelected = selection.contains(id); + + ImGui::PushID(id); + ImGui::SetNextItemSelectionUserData(id); + imgui::selectable_input_text(event.name, std::format("###Document #{} Event #{}", manager.selected, id), + event.name, isSelected); + if (ImGui::BeginItemTooltip()) + { + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); + ImGui::TextUnformatted(event.name.c_str()); + ImGui::PopFont(); + ImGui::EndTooltip(); + } + ImGui::PopID(); + } + + io = ImGui::EndMultiSelect(); + storage.ApplyRequests(io); + } + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + imgui::shortcut(settings.shortcutAdd, true); + if (ImGui::Button("Add", widgetSize)) + { + int id{}; + anm2.event_add(id); + selection = {id}; + } + imgui::set_item_tooltip_shortcut("Add an event.", settings.shortcutAdd); + ImGui::SameLine(); + + std::set unusedEventIDs = anm2.events_unused(); + + imgui::shortcut(settings.shortcutRemove, true); + ImGui::BeginDisabled(unusedEventIDs.empty()); + { + if (ImGui::Button("Remove Unused", widgetSize)) + for (auto& id : unusedEventIDs) + anm2.content.layers.erase(id); + } + ImGui::EndDisabled(); + imgui::set_item_tooltip_shortcut("Remove unused events (i.e., ones not used by any trigger in any animation.)", + settings.shortcutRemove); + } + ImGui::End(); + } +} diff --git a/src/events.h b/src/events.h new file mode 100644 index 0000000..9573295 --- /dev/null +++ b/src/events.h @@ -0,0 +1,17 @@ +#pragma once + +#include "document_manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::events +{ + class Events + { + ImGuiSelectionExternalStorage storage{}; + + public: + void update(document_manager::DocumentManager& manager, settings::Settings& settings, + resources::Resources& resources); + }; +} diff --git a/src/ffmpeg.cpp b/src/ffmpeg.cpp deleted file mode 100644 index b8ff2ee..0000000 --- a/src/ffmpeg.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "ffmpeg.h" - -bool ffmpeg_render(const std::string& ffmpegPath, const std::string& outputPath, const std::vector& frames, ivec2 size, int fps, - enum RenderType type) { - if (frames.empty() || size.x <= 0 || size.y <= 0 || fps <= 0 || ffmpegPath.empty() || outputPath.empty()) - return false; - - std::string command{}; - - switch (type) { - case RENDER_GIF: - command = std::format(FFMPEG_GIF_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath); - break; - case RENDER_WEBM: - command = std::format(FFMPEG_WEBM_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath); - break; - case RENDER_MP4: - command = std::format(FFMPEG_MP4_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath); - break; - default: - break; - } - -#if _WIN32 - command = string_quote(command); -#endif - - log_command(command); - - FILE* fp = POPEN(command.c_str(), PWRITE_MODE); - - if (!fp) { - log_error(std::format(FFMPEG_POPEN_ERROR, strerror(errno))); - return false; - } - - size_t frameBytes = size.x * size.y * TEXTURE_CHANNELS; - - for (const auto& frame : frames) { - std::vector rgba = texture_download(&frame); - - if (rgba.size() != frameBytes) { - PCLOSE(fp); - return false; - } - - if (fwrite(rgba.data(), 1, frameBytes, fp) != frameBytes) { - PCLOSE(fp); - return false; - } - } - - const int code = PCLOSE(fp); - - return (code == 0); -} \ No newline at end of file diff --git a/src/ffmpeg.h b/src/ffmpeg.h deleted file mode 100644 index 099978e..0000000 --- a/src/ffmpeg.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "render.h" -#include "texture.h" - -#define FFMPEG_POPEN_ERROR "popen() (for FFmpeg) failed!\n{}" - -static constexpr const char* FFMPEG_GIF_FORMAT = "\"{0}\" -y " - "-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " - "-lavfi \"split[s0][s1];" - "[s0]palettegen=stats_mode=full[p];" - "[s1][p]paletteuse=dither=floyd_steinberg\" " - "-loop 0 \"{4}\""; - -static constexpr const char* FFMPEG_WEBM_FORMAT = "\"{0}\" -y " - "-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " - "-c:v libvpx-vp9 -crf 30 -b:v 0 -pix_fmt yuva420p -row-mt 1 -threads 0 -speed 2 " - "-auto-alt-ref 0 -an \"{4}\""; - -static constexpr const char* FFMPEG_MP4_FORMAT = "\"{0}\" -y " - "-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " - "-vf \"format=yuv420p,scale=trunc(iw/2)*2:trunc(ih/2)*2\" " - "-c:v libx265 -crf 20 -preset slow " - "-tag:v hvc1 -movflags +faststart -an \"{4}\""; - -bool ffmpeg_render(const std::string& ffmpegPath, const std::string& outputPath, const std::vector& frames, ivec2 size, int fps, enum RenderType type); \ No newline at end of file diff --git a/src/filesystem.cpp b/src/filesystem.cpp new file mode 100644 index 0000000..057fa95 --- /dev/null +++ b/src/filesystem.cpp @@ -0,0 +1,47 @@ +#include "filesystem.h" + +#include +#include +#include + +namespace anm2ed::filesystem +{ + std::string path_preferences_get() + { + char* preferencesPath = SDL_GetPrefPath("", "anm2ed"); + std::string preferencesPathString = preferencesPath; + SDL_free(preferencesPath); + return preferencesPathString; + } + + bool path_is_exist(const std::string& path) + { + std::error_code errorCode; + return std::filesystem::exists(path, errorCode) && ((void)std::filesystem::status(path, errorCode), !errorCode); + } + + bool path_is_extension(const std::string& path, const std::string& extension) + { + auto e = std::filesystem::path(path).extension().string(); + std::transform(e.begin(), e.end(), e.begin(), ::tolower); + return e == ("." + extension); + } + + WorkingDirectory::WorkingDirectory(const std::string& path, bool isFile) + { + previous = std::filesystem::current_path(); + if (isFile) + { + std::filesystem::path filePath = path; + std::filesystem::path parentPath = filePath.parent_path(); + std::filesystem::current_path(parentPath); + } + else + std::filesystem::current_path(path); + } + + WorkingDirectory::~WorkingDirectory() + { + std::filesystem::current_path(previous); + } +} \ No newline at end of file diff --git a/src/filesystem.h b/src/filesystem.h new file mode 100644 index 0000000..804ed22 --- /dev/null +++ b/src/filesystem.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +namespace anm2ed::filesystem +{ + std::string path_preferences_get(); + bool path_is_exist(const std::string& path); + bool path_is_extension(const std::string& path, const std::string& extension); + + class WorkingDirectory + { + public: + std::filesystem::path previous; + + WorkingDirectory(const std::string& path, bool isFile = false); + ~WorkingDirectory(); + }; +} \ No newline at end of file diff --git a/src/font.cpp b/src/font.cpp new file mode 100644 index 0000000..39a58ee --- /dev/null +++ b/src/font.cpp @@ -0,0 +1,33 @@ +#include "font.h" + +namespace anm2ed::font +{ + Font::Font() = default; + + Font::Font(void* data, size_t length, int size) + { + ImFontConfig config; + config.FontDataOwnedByAtlas = false; + pointer = ImGui::GetIO().Fonts->AddFontFromMemoryTTF(data, length, size, &config); + } + + Font::~Font() + { + if (get()) ImGui::GetIO().Fonts->RemoveFont(pointer); + } + + ImFont* Font::get() + { + return pointer; + } + + Font& Font::operator=(Font&& other) noexcept + { + if (this != &other) + { + pointer = other.pointer; + other.pointer = nullptr; + } + return *this; + } +} \ No newline at end of file diff --git a/src/font.h b/src/font.h new file mode 100644 index 0000000..e6dccc2 --- /dev/null +++ b/src/font.h @@ -0,0 +1,5238 @@ +/* +Copyright 2018 The Noto Project Authors (github.com/noto-fonts/noto-fonts) + +This Font Software is licensed under the SIL Open Font License, +Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font +creation efforts of academic and linguistic communities, and to +provide a free and open framework in which fonts may be shared and +improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply to +any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software +components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, +deleting, or substituting -- in part or in whole -- any of the +components of the Original Version, by changing formats or by porting +the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, +modify, redistribute, and sell modified and unmodified copies of the +Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in +Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the +corresponding Copyright Holder. This restriction only applies to the +primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created using +the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. +*/ + +#pragma once +#include +#include + +namespace anm2ed::font +{ + constexpr int SIZE = 16; + constexpr int SIZE_LARGE = 32; + + enum Type + { + REGULAR, + ITALICS, + BOLD, + BOLD_ITALICS, + COUNT + }; + + struct Info + { + const void* data; + unsigned int length; + }; + + constexpr unsigned char REGULAR_DATA[] = { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x05, 0xd0, 0x02, + 0xf1, 0x00, 0x00, 0x4f, 0xd8, 0x00, 0x00, 0x00, 0x56, 0x47, 0x50, 0x4f, 0x53, 0x28, 0x98, 0x0a, 0xef, 0x00, 0x00, + 0x50, 0x30, 0x00, 0x00, 0x07, 0xb2, 0x47, 0x53, 0x55, 0x42, 0x39, 0x7a, 0x34, 0x30, 0x00, 0x00, 0x57, 0xe4, 0x00, + 0x00, 0x01, 0x50, 0x4f, 0x53, 0x2f, 0x32, 0x69, 0x4f, 0x5e, 0x78, 0x00, 0x00, 0x3c, 0xe0, 0x00, 0x00, 0x00, 0x60, + 0x63, 0x6d, 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, + 0x20, 0x3e, 0x0e, 0x1b, 0x37, 0x00, 0x00, 0x4c, 0x88, 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, + 0x0b, 0x83, 0x00, 0x00, 0x3d, 0x74, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x4f, 0xd0, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0xaf, 0xdf, 0xf8, 0x38, 0x00, 0x00, 0x01, 0x1c, + 0x00, 0x00, 0x38, 0x4e, 0x68, 0x65, 0x61, 0x64, 0x28, 0x83, 0xdb, 0xfe, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00, 0x00, + 0x36, 0x68, 0x68, 0x65, 0x61, 0x0c, 0xb3, 0x0b, 0xe0, 0x00, 0x00, 0x3c, 0xbc, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, + 0x74, 0x78, 0xe7, 0xb3, 0x14, 0xa5, 0x00, 0x00, 0x3a, 0xd0, 0x00, 0x00, 0x01, 0xea, 0x6c, 0x6f, 0x63, 0x61, 0x0d, + 0xd0, 0xff, 0xd0, 0x00, 0x00, 0x39, 0x8c, 0x00, 0x00, 0x01, 0x0a, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x55, 0x10, 0x75, + 0x00, 0x00, 0x39, 0x6c, 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2a, 0x6f, 0x43, 0x21, 0x00, 0x00, 0x4d, + 0xb4, 0x00, 0x00, 0x01, 0xfc, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x9f, 0x00, 0x32, 0x00, 0x00, 0x4f, 0xb0, 0x00, 0x00, + 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0x44, 0x7e, 0xc6, 0xb9, 0x00, 0x00, 0x4b, 0x80, 0x00, 0x00, 0x01, 0x05, 0x00, + 0x02, 0x00, 0x48, 0xff, 0xf2, 0x00, 0xc4, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, + 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, + 0x24, 0x23, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x37, 0x23, 0x03, 0x33, 0x03, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x23, 0x22, 0x26, 0xa3, 0x39, 0x19, 0x6b, 0x74, 0x24, 0x1a, 0x19, 0x25, 0x25, 0x19, 0x1a, 0x24, 0xc9, + 0x02, 0x01, 0xfd, 0x6c, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x02, 0x00, 0x41, 0x01, 0xc8, 0x01, 0x57, + 0x02, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x40, 0x21, 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x05, 0x03, 0x04, + 0x03, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, + 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0x21, 0x03, 0x23, 0x03, 0xa0, 0x14, 0x37, 0x14, 0x01, + 0x16, 0x14, 0x37, 0x14, 0x02, 0xca, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x00, 0x19, + 0x00, 0x00, 0x02, 0x6c, 0x02, 0xca, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, 0x40, 0x44, 0x0c, 0x0a, 0x02, 0x08, 0x0f, + 0x10, 0x0d, 0x03, 0x07, 0x00, 0x08, 0x07, 0x68, 0x0e, 0x06, 0x02, 0x00, 0x05, 0x03, 0x02, 0x01, 0x02, 0x00, 0x01, + 0x67, 0x0b, 0x01, 0x09, 0x09, 0x6a, 0x4d, 0x04, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, + 0x1c, 0x00, 0x1b, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x0d, 0x1f, 0x2b, 0x01, 0x07, 0x33, 0x15, 0x23, 0x07, 0x23, 0x37, 0x23, 0x07, 0x23, 0x37, + 0x23, 0x35, 0x33, 0x37, 0x23, 0x35, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, 0x15, 0x05, 0x33, 0x37, + 0x23, 0x01, 0xe0, 0x1f, 0x89, 0x96, 0x29, 0x47, 0x29, 0x8f, 0x27, 0x46, 0x26, 0x7e, 0x8b, 0x20, 0x86, 0x92, 0x28, + 0x48, 0x28, 0x90, 0x28, 0x45, 0x28, 0x7f, 0xfe, 0x7f, 0x8f, 0x1f, 0x8f, 0x01, 0xb4, 0xa0, 0x43, 0xd1, 0xd1, 0xd1, + 0xd1, 0x43, 0xa0, 0x42, 0xd4, 0xd4, 0xd4, 0xd4, 0x42, 0xa0, 0xa0, 0x00, 0x00, 0x03, 0x00, 0x3e, 0xff, 0xc6, 0x02, + 0x04, 0x02, 0xf7, 0x00, 0x22, 0x00, 0x29, 0x00, 0x30, 0x00, 0x69, 0x40, 0x14, 0x30, 0x2a, 0x29, 0x23, 0x19, 0x18, + 0x15, 0x14, 0x08, 0x04, 0x0a, 0x01, 0x02, 0x20, 0x03, 0x02, 0x00, 0x01, 0x02, 0x4c, 0x4b, 0xb0, 0x2d, 0x50, 0x58, + 0x40, 0x1c, 0x04, 0x01, 0x02, 0x03, 0x01, 0x03, 0x02, 0x01, 0x80, 0x00, 0x05, 0x00, 0x05, 0x86, 0x00, 0x01, 0x00, + 0x00, 0x05, 0x01, 0x00, 0x6a, 0x00, 0x03, 0x03, 0x6c, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x03, 0x02, 0x03, 0x85, + 0x04, 0x01, 0x02, 0x01, 0x02, 0x85, 0x00, 0x05, 0x00, 0x05, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, + 0x01, 0x00, 0x62, 0x00, 0x00, 0x01, 0x00, 0x52, 0x59, 0x40, 0x09, 0x1f, 0x11, 0x11, 0x16, 0x15, 0x10, 0x06, 0x0d, + 0x1c, 0x2b, 0x37, 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x35, 0x26, 0x26, 0x35, 0x34, 0x36, 0x37, 0x35, 0x33, + 0x15, 0x16, 0x16, 0x17, 0x07, 0x26, 0x26, 0x27, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x15, 0x23, 0x11, 0x06, + 0x06, 0x15, 0x14, 0x16, 0x17, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0xfd, 0x37, 0x68, 0x20, 0x22, 0x6a, 0x33, + 0x63, 0x5c, 0x67, 0x58, 0x40, 0x35, 0x57, 0x24, 0x1b, 0x20, 0x4d, 0x28, 0x42, 0x58, 0x2d, 0x68, 0x5f, 0x40, 0x36, + 0x33, 0x2d, 0x3c, 0x40, 0x3b, 0x36, 0x30, 0x41, 0x31, 0x01, 0x11, 0x0f, 0x55, 0x10, 0x18, 0x01, 0xca, 0x1b, 0x52, + 0x47, 0x4a, 0x54, 0x05, 0x58, 0x57, 0x01, 0x15, 0x0f, 0x4a, 0x0d, 0x13, 0x03, 0xc9, 0x13, 0x2b, 0x3f, 0x32, 0x46, + 0x57, 0x0a, 0x6f, 0x02, 0x8c, 0x04, 0x2a, 0x21, 0x28, 0x2b, 0x0f, 0xfe, 0xe2, 0x06, 0x2b, 0x22, 0x26, 0x27, 0x10, + 0x00, 0x05, 0x00, 0x31, 0xff, 0xf6, 0x03, 0x0e, 0x02, 0xd4, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x25, 0x00, + 0x2f, 0x00, 0x99, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x2c, 0x0d, 0x01, 0x06, 0x0e, 0x01, 0x08, 0x05, 0x06, 0x08, + 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, 0x0b, 0x03, 0x0a, 0x03, + 0x00, 0x00, 0x70, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x07, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x34, + 0x0d, 0x01, 0x06, 0x0e, 0x01, 0x08, 0x05, 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0b, + 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, 0x0a, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x02, + 0x02, 0x6b, 0x4d, 0x00, 0x09, 0x09, 0x07, 0x61, 0x00, 0x07, 0x07, 0x71, 0x07, 0x4e, 0x59, 0x40, 0x2b, 0x27, 0x26, + 0x1b, 0x1a, 0x11, 0x10, 0x0c, 0x0c, 0x01, 0x00, 0x2d, 0x2b, 0x26, 0x2f, 0x27, 0x2f, 0x21, 0x1f, 0x1a, 0x25, 0x1b, + 0x25, 0x17, 0x15, 0x10, 0x19, 0x11, 0x19, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, + 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x05, 0x01, 0x23, + 0x01, 0x05, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x35, 0x34, 0x05, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, + 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x35, 0x34, 0xc3, 0x4a, 0x4c, 0x49, 0x4d, + 0x47, 0x4b, 0x46, 0x02, 0x15, 0xfe, 0x74, 0x4d, 0x01, 0x8c, 0xfe, 0x84, 0x26, 0x23, 0x23, 0x26, 0x4d, 0x01, 0x68, + 0x49, 0x4d, 0x49, 0x4d, 0x47, 0x4b, 0x46, 0x4c, 0x26, 0x23, 0x23, 0x26, 0x4d, 0x02, 0xd4, 0x75, 0x6a, 0x6a, 0x77, + 0x77, 0x6a, 0x6a, 0x75, 0x0a, 0xfd, 0x36, 0x02, 0xca, 0x34, 0x51, 0x50, 0x50, 0x52, 0xa2, 0xa1, 0xe0, 0x75, 0x6a, + 0x6a, 0x77, 0x77, 0x6a, 0x6a, 0x75, 0x3f, 0x50, 0x50, 0x51, 0x51, 0xa2, 0xa0, 0x00, 0x03, 0x00, 0x35, 0xff, 0xf6, + 0x02, 0xda, 0x02, 0xd5, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x35, 0x00, 0x7a, 0x40, 0x0f, 0x26, 0x1a, 0x06, 0x03, 0x01, + 0x04, 0x35, 0x11, 0x0e, 0x07, 0x04, 0x05, 0x01, 0x02, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x23, 0x07, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, + 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x21, 0x07, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6b, + 0x4d, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x59, 0x40, 0x17, 0x21, 0x20, 0x01, 0x00, + 0x33, 0x31, 0x20, 0x2b, 0x21, 0x2b, 0x15, 0x13, 0x10, 0x0f, 0x0b, 0x0a, 0x00, 0x1f, 0x01, 0x1f, 0x08, 0x0d, 0x16, + 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, 0x07, 0x17, 0x23, 0x27, + 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, + 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x01, 0x30, + 0x50, 0x5d, 0x51, 0x3e, 0xc1, 0x1a, 0x21, 0x0b, 0x59, 0x10, 0x30, 0x26, 0x92, 0x77, 0x57, 0x2f, 0x74, 0x53, 0x67, + 0x7a, 0x53, 0x47, 0x20, 0x37, 0x63, 0x52, 0x2a, 0x35, 0x26, 0x24, 0x3b, 0x33, 0x30, 0x52, 0x36, 0x3d, 0x4a, 0x3e, + 0x40, 0x5c, 0x1f, 0x02, 0xd5, 0x51, 0x49, 0x3f, 0x58, 0x24, 0xba, 0x1f, 0x51, 0x2f, 0x40, 0x6e, 0x29, 0x8e, 0x54, + 0x2a, 0x34, 0x66, 0x5e, 0x4d, 0x5d, 0x28, 0x24, 0x52, 0x37, 0x4a, 0x52, 0x48, 0x2c, 0x27, 0x24, 0x3d, 0x25, 0x22, + 0x3d, 0x28, 0x24, 0x2e, 0xfe, 0xc8, 0x20, 0x42, 0x36, 0x37, 0x42, 0x2a, 0x1d, 0x00, 0x00, 0x01, 0x00, 0x41, 0x01, + 0xc8, 0x00, 0xa0, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, + 0x01, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, + 0xa0, 0x14, 0x37, 0x14, 0x02, 0xca, 0xfe, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, 0x62, 0x01, 0x0e, + 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, 0x00, 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, + 0x16, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x13, 0x34, 0x36, 0x37, 0x33, 0x06, 0x06, 0x15, 0x14, 0x16, 0x17, 0x23, 0x26, + 0x26, 0x28, 0x47, 0x4c, 0x53, 0x46, 0x47, 0x47, 0x45, 0x52, 0x4c, 0x47, 0x01, 0x12, 0x7a, 0xe3, 0x5b, 0x5e, 0xe2, + 0x77, 0x74, 0xdf, 0x5e, 0x58, 0xdf, 0x00, 0x00, 0x01, 0x00, 0x1e, 0xff, 0x62, 0x01, 0x04, 0x02, 0xca, 0x00, 0x0d, + 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x01, 0x00, 0x86, 0x00, 0x01, 0x01, 0x6a, 0x01, 0x4e, 0x16, 0x13, 0x02, 0x0d, + 0x18, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x23, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x01, 0x04, 0x47, + 0x4c, 0x52, 0x45, 0x47, 0x47, 0x46, 0x53, 0x4c, 0x47, 0x01, 0x12, 0x79, 0xdf, 0x58, 0x5e, 0xdf, 0x74, 0x77, 0xe2, + 0x5e, 0x5b, 0xe3, 0x00, 0x01, 0x00, 0x29, 0x01, 0x36, 0x01, 0xfc, 0x02, 0xf8, 0x00, 0x0e, 0x00, 0x33, 0x40, 0x10, + 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x0d, 0x00, 0x49, 0x4b, 0xb0, 0x29, + 0x50, 0x58, 0xb6, 0x01, 0x01, 0x00, 0x00, 0x6c, 0x00, 0x4e, 0x1b, 0xb4, 0x01, 0x01, 0x00, 0x00, 0x76, 0x59, 0x40, + 0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x02, 0x0d, 0x16, 0x2b, 0x01, 0x07, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, + 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x27, 0x01, 0x42, 0x14, 0xc0, 0x0e, 0xb8, 0x77, 0x56, 0x55, 0x4d, 0x59, 0x75, + 0xb6, 0x0e, 0xbe, 0x15, 0x02, 0xf8, 0xc0, 0x36, 0x5c, 0x0f, 0x9e, 0x2f, 0xaf, 0xaf, 0x2f, 0x9e, 0x0f, 0x5c, 0x36, + 0xc0, 0x00, 0x01, 0x00, 0x32, 0x00, 0x6f, 0x02, 0x08, 0x02, 0x53, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x00, 0x05, + 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, 0x05, 0x02, 0x5f, + 0x00, 0x02, 0x05, 0x02, 0x4f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x15, 0x23, + 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, 0x01, 0x41, 0xc7, 0xc7, 0x48, 0xc7, 0xc7, 0x48, 0x01, 0x84, 0x47, + 0xce, 0xce, 0x47, 0xcf, 0x00, 0x00, 0x01, 0x00, 0x29, 0xff, 0x7f, 0x00, 0xc0, 0x00, 0x74, 0x00, 0x08, 0x00, 0x18, + 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x13, + 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x37, 0x06, 0x06, 0x07, 0x23, 0x36, 0x36, 0x37, 0x33, 0xc0, 0x0d, 0x31, 0x18, 0x41, + 0x0e, 0x1d, 0x07, 0x5e, 0x69, 0x35, 0x7f, 0x36, 0x39, 0x88, 0x34, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0xe5, 0x01, + 0x1a, 0x01, 0x33, 0x00, 0x03, 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, + 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, + 0x35, 0x33, 0x15, 0x28, 0xf2, 0xe5, 0x4e, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x48, 0xff, 0xf2, 0x00, 0xc4, 0x00, 0x79, + 0x00, 0x0b, 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x22, + 0x02, 0x0d, 0x18, 0x2b, 0x37, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x48, 0x24, 0x19, + 0x1a, 0x25, 0x25, 0x1a, 0x19, 0x24, 0x36, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x01, 0x00, 0x0a, 0x00, + 0x00, 0x01, 0x6a, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, + 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x01, 0x01, 0x23, 0x01, + 0x01, 0x6a, 0xfe, 0xf6, 0x56, 0x01, 0x0a, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0x00, 0x02, 0x00, 0x31, 0xff, 0xf6, + 0x02, 0x0b, 0x02, 0xd5, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x24, 0x25, 0x23, 0x04, + 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x05, 0x14, + 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x0b, 0x30, 0x68, 0x56, 0x79, 0x73, 0x2f, 0x68, + 0x55, 0x78, 0x76, 0xfe, 0x7e, 0x43, 0x51, 0x50, 0x45, 0x45, 0x50, 0x51, 0x43, 0x01, 0x66, 0x73, 0xa5, 0x58, 0xc3, + 0xad, 0x74, 0xa4, 0x57, 0xc1, 0xae, 0x93, 0x92, 0x91, 0x94, 0x92, 0x92, 0x92, 0x00, 0x01, 0x00, 0x59, 0x00, 0x00, + 0x01, 0x63, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x1b, 0x40, 0x18, 0x0a, 0x09, 0x05, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x00, + 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1a, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x21, 0x23, 0x11, + 0x34, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, 0x01, 0x63, 0x56, 0x02, 0x02, 0x10, 0x1a, 0x14, 0x4c, + 0x2e, 0xc1, 0x49, 0x01, 0xf3, 0x2b, 0x34, 0x1c, 0x10, 0x16, 0x11, 0x3e, 0x3b, 0x96, 0x00, 0x00, 0x01, 0x00, 0x30, + 0x00, 0x00, 0x02, 0x08, 0x02, 0xd4, 0x00, 0x1b, 0x00, 0x2a, 0x40, 0x27, 0x0e, 0x0d, 0x02, 0x03, 0x01, 0x02, 0x01, + 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, + 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x27, 0x25, 0x28, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x3e, + 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, + 0x07, 0x15, 0x21, 0x02, 0x08, 0xfe, 0x28, 0xbb, 0x36, 0x4a, 0x26, 0x46, 0x38, 0x34, 0x4f, 0x29, 0x2f, 0x2a, 0x6d, + 0x44, 0x64, 0x74, 0x2e, 0x52, 0x37, 0x95, 0x01, 0x69, 0x49, 0xbd, 0x36, 0x54, 0x51, 0x30, 0x3b, 0x3d, 0x24, 0x20, + 0x3b, 0x23, 0x31, 0x65, 0x59, 0x38, 0x62, 0x5f, 0x36, 0x93, 0x04, 0x00, 0x00, 0x01, 0x00, 0x2d, 0xff, 0xf6, 0x02, + 0x03, 0x02, 0xd4, 0x00, 0x2a, 0x00, 0x40, 0x40, 0x3d, 0x24, 0x01, 0x03, 0x04, 0x03, 0x01, 0x02, 0x03, 0x0f, 0x01, + 0x01, 0x02, 0x0e, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x25, 0x01, 0x04, 0x01, 0x4b, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, + 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x25, 0x24, 0x21, 0x24, 0x25, 0x2a, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x15, + 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, + 0x23, 0x23, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x01, 0xed, 0x50, 0x44, 0x56, 0x54, 0x3a, 0x79, 0x5f, 0x38, 0x60, 0x2c, 0x2d, 0x68, 0x30, 0x60, 0x55, 0x69, 0x5f, + 0x45, 0x46, 0x58, 0x5b, 0x46, 0x3c, 0x3a, 0x52, 0x28, 0x2c, 0x26, 0x71, 0x48, 0x70, 0x6d, 0x02, 0x23, 0x48, 0x55, + 0x0e, 0x04, 0x0a, 0x58, 0x47, 0x3e, 0x61, 0x36, 0x11, 0x16, 0x52, 0x16, 0x19, 0x4b, 0x42, 0x43, 0x3b, 0x4b, 0x4a, + 0x3d, 0x34, 0x39, 0x22, 0x1a, 0x3c, 0x1e, 0x2c, 0x64, 0x00, 0x00, 0x02, 0x00, 0x15, 0x00, 0x00, 0x02, 0x28, 0x02, + 0xce, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x2b, 0x40, 0x28, 0x0e, 0x01, 0x04, 0x03, 0x06, 0x01, 0x00, 0x04, 0x02, 0x4c, + 0x05, 0x01, 0x04, 0x02, 0x01, 0x00, 0x01, 0x04, 0x00, 0x68, 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, + 0x01, 0x4e, 0x19, 0x11, 0x12, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x25, 0x23, 0x15, 0x23, 0x35, 0x21, 0x35, + 0x01, 0x33, 0x11, 0x33, 0x27, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x07, 0x03, 0x21, 0x02, 0x28, 0x68, 0x55, 0xfe, + 0xaa, 0x01, 0x50, 0x5b, 0x68, 0xbd, 0x04, 0x01, 0x04, 0x08, 0x18, 0x0b, 0xd6, 0x01, 0x00, 0xa2, 0xa2, 0xa2, 0x4b, + 0x01, 0xe1, 0xfe, 0x23, 0xe1, 0x34, 0x49, 0x21, 0x13, 0x2c, 0x0f, 0xfe, 0xcf, 0x00, 0x00, 0x01, 0x00, 0x3f, 0xff, + 0xf6, 0x02, 0x03, 0x02, 0xca, 0x00, 0x1e, 0x00, 0x44, 0x40, 0x41, 0x1c, 0x17, 0x02, 0x03, 0x00, 0x16, 0x0a, 0x02, + 0x02, 0x03, 0x09, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x03, 0x02, 0x00, 0x03, 0x69, 0x00, 0x05, + 0x05, 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, + 0x01, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x14, 0x12, 0x0e, 0x0c, 0x07, 0x05, 0x00, 0x1e, 0x01, 0x1e, 0x07, 0x0d, 0x16, + 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x15, 0x21, 0x07, 0x36, 0x36, 0x01, 0x13, 0x6e, 0x82, 0x8d, 0x7e, + 0x37, 0x61, 0x21, 0x24, 0x67, 0x2f, 0x4f, 0x61, 0x56, 0x5d, 0x1c, 0x48, 0x16, 0x2c, 0x1b, 0x01, 0x66, 0xfe, 0xe5, + 0x11, 0x11, 0x3a, 0x01, 0xb6, 0x6e, 0x64, 0x6f, 0x7f, 0x14, 0x13, 0x53, 0x16, 0x19, 0x4b, 0x4f, 0x46, 0x4b, 0x0a, + 0x05, 0x1c, 0x01, 0x51, 0x50, 0xcf, 0x03, 0x08, 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x0d, 0x02, 0xd4, + 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x3e, 0x40, 0x3b, 0x08, 0x01, 0x01, 0x00, 0x09, 0x01, 0x02, 0x01, 0x11, 0x01, 0x04, + 0x05, 0x03, 0x4c, 0x00, 0x02, 0x00, 0x05, 0x04, 0x02, 0x05, 0x69, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x70, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x20, 0x1f, 0x26, 0x24, 0x1f, + 0x2c, 0x20, 0x2c, 0x24, 0x27, 0x25, 0x24, 0x07, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, + 0x15, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, + 0x26, 0x26, 0x17, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x37, 0x1b, 0x47, + 0x80, 0x65, 0x15, 0x33, 0x10, 0x12, 0x2d, 0x17, 0x45, 0x5c, 0x35, 0x18, 0x03, 0x06, 0x17, 0x52, 0x40, 0x5d, 0x72, + 0x7b, 0x68, 0x44, 0x6e, 0x41, 0xf2, 0x3f, 0x4e, 0x45, 0x45, 0x2f, 0x46, 0x27, 0x22, 0x44, 0x01, 0x31, 0x4d, 0x95, + 0x79, 0x48, 0x04, 0x05, 0x4b, 0x06, 0x06, 0x2e, 0x50, 0x68, 0x3b, 0x23, 0x31, 0x71, 0x68, 0x70, 0x80, 0x44, 0x8c, + 0x86, 0x51, 0x55, 0x44, 0x50, 0x27, 0x3c, 0x20, 0x2b, 0x55, 0x37, 0x00, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x02, 0x0b, + 0x02, 0xca, 0x00, 0x06, 0x00, 0x25, 0x40, 0x22, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x5f, + 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, + 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x88, 0x01, 0x25, 0xfe, 0x7f, 0x01, 0xdf, + 0xfe, 0xde, 0x02, 0x7a, 0x50, 0x44, 0xfd, 0x7a, 0x00, 0x00, 0x03, 0x00, 0x31, 0xff, 0xf6, 0x02, 0x0a, 0x02, 0xd4, + 0x00, 0x1b, 0x00, 0x28, 0x00, 0x35, 0x00, 0x36, 0x40, 0x33, 0x33, 0x23, 0x15, 0x07, 0x04, 0x03, 0x02, 0x01, 0x4c, + 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x71, 0x01, 0x4e, 0x1d, 0x1c, 0x01, 0x00, 0x2d, 0x2b, 0x1c, 0x28, 0x1d, 0x28, 0x0f, 0x0d, 0x00, 0x1b, 0x01, + 0x1b, 0x06, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x23, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, + 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x27, 0x06, + 0x06, 0x01, 0x1d, 0x5e, 0x78, 0x25, 0x3e, 0x25, 0x2c, 0x48, 0x2b, 0x7f, 0x6b, 0x73, 0x7c, 0x29, 0x44, 0x27, 0x34, + 0x49, 0x38, 0x60, 0x3c, 0x37, 0x47, 0x23, 0x3c, 0x24, 0x34, 0x47, 0x46, 0xcf, 0x4a, 0x4d, 0x49, 0x4d, 0x52, 0x44, + 0x10, 0x42, 0x45, 0x02, 0xd4, 0x58, 0x53, 0x2b, 0x40, 0x31, 0x13, 0x15, 0x35, 0x46, 0x31, 0x5a, 0x69, 0x65, 0x5b, + 0x31, 0x48, 0x34, 0x12, 0x1e, 0x55, 0x42, 0x37, 0x4b, 0x28, 0x47, 0x35, 0x32, 0x25, 0x32, 0x23, 0x10, 0x16, 0x3e, + 0x36, 0x32, 0x35, 0xfe, 0x28, 0x34, 0x45, 0x45, 0x37, 0x34, 0x45, 0x1a, 0x06, 0x1c, 0x49, 0x00, 0x00, 0x02, 0x00, + 0x32, 0xff, 0xf6, 0x02, 0x08, 0x02, 0xd4, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x3e, 0x40, 0x3b, 0x10, 0x01, 0x05, 0x04, + 0x09, 0x01, 0x01, 0x02, 0x08, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, 0x06, + 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x20, 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x25, 0x27, 0x24, 0x24, 0x07, 0x0d, 0x1a, 0x2b, 0x01, + 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, + 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x27, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, + 0x35, 0x34, 0x26, 0x26, 0x02, 0x08, 0x1b, 0x47, 0x81, 0x65, 0x14, 0x35, 0x11, 0x27, 0x31, 0x46, 0x5b, 0x36, 0x18, + 0x02, 0x06, 0x16, 0x53, 0x41, 0x5c, 0x71, 0x39, 0x66, 0x45, 0x44, 0x6e, 0x40, 0xf2, 0x3e, 0x4f, 0x43, 0x46, 0x30, + 0x46, 0x27, 0x22, 0x44, 0x01, 0x99, 0x4d, 0x95, 0x79, 0x48, 0x05, 0x05, 0x4b, 0x0d, 0x2e, 0x4f, 0x69, 0x3a, 0x22, + 0x31, 0x71, 0x67, 0x4b, 0x6c, 0x3a, 0x45, 0x8b, 0x86, 0x52, 0x54, 0x45, 0x4f, 0x27, 0x3c, 0x20, 0x2b, 0x54, 0x38, + 0x00, 0x00, 0x02, 0x00, 0x48, 0xff, 0xf2, 0x00, 0xc4, 0x02, 0x26, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x1f, 0x40, 0x1c, + 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, + 0x03, 0x4e, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x23, 0x22, 0x26, 0x11, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x48, 0x24, 0x19, 0x1a, + 0x25, 0x25, 0x1a, 0x19, 0x24, 0x24, 0x19, 0x1a, 0x25, 0x25, 0x1a, 0x19, 0x24, 0x01, 0xe2, 0x26, 0x1e, 0x1e, 0x26, + 0x24, 0x20, 0x20, 0xfe, 0x78, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x02, 0x00, 0x1f, 0xff, 0x7f, 0x00, + 0xc2, 0x02, 0x26, 0x00, 0x0b, 0x00, 0x15, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x02, 0x03, 0x02, 0x63, 0x00, + 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x01, 0x4e, 0x14, 0x15, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, + 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x13, 0x06, 0x06, 0x07, 0x23, 0x3e, 0x02, 0x37, + 0x33, 0x46, 0x24, 0x19, 0x1a, 0x25, 0x25, 0x1a, 0x19, 0x24, 0x71, 0x0d, 0x31, 0x18, 0x42, 0x0a, 0x13, 0x11, 0x05, + 0x5e, 0x01, 0xe2, 0x26, 0x1e, 0x1e, 0x26, 0x24, 0x20, 0x20, 0xfe, 0xab, 0x34, 0x81, 0x35, 0x26, 0x57, 0x55, 0x23, + 0x00, 0x01, 0x00, 0x32, 0x00, 0x74, 0x02, 0x09, 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, 0x32, + 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, 0x05, 0x02, 0x09, 0xfe, 0x29, 0x01, 0xd7, 0xfe, 0x87, 0x01, 0x79, 0x74, + 0xcf, 0x32, 0xeb, 0x4e, 0xb2, 0x9e, 0x00, 0x02, 0x00, 0x38, 0x00, 0xd9, 0x02, 0x02, 0x01, 0xe7, 0x00, 0x03, 0x00, + 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, 0x03, 0x02, + 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, + 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, 0x35, 0x21, + 0x15, 0x38, 0x01, 0xca, 0xfe, 0x36, 0x01, 0xca, 0x01, 0xa0, 0x47, 0x47, 0xc7, 0x47, 0x47, 0x00, 0x00, 0x01, 0x00, + 0x32, 0x00, 0x74, 0x02, 0x09, 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, 0x25, + 0x25, 0x35, 0x05, 0x15, 0x05, 0x32, 0x01, 0x79, 0xfe, 0x87, 0x01, 0xd7, 0xfe, 0x29, 0xc2, 0x9d, 0xb3, 0x4e, 0xeb, + 0x32, 0xcf, 0x00, 0x00, 0x02, 0x00, 0x0c, 0xff, 0xf2, 0x01, 0x98, 0x02, 0xd4, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x32, + 0x40, 0x2f, 0x0f, 0x01, 0x00, 0x01, 0x0e, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, 0x03, + 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x04, 0x61, 0x00, 0x04, 0x04, + 0x71, 0x04, 0x4e, 0x24, 0x23, 0x1b, 0x25, 0x2a, 0x05, 0x0d, 0x1b, 0x2b, 0x37, 0x34, 0x36, 0x36, 0x37, 0x3e, 0x02, + 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x0e, + 0x02, 0x15, 0x15, 0x23, 0x07, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x8c, 0x0f, 0x25, + 0x20, 0x27, 0x2b, 0x12, 0x3e, 0x3b, 0x31, 0x4c, 0x23, 0x1f, 0x28, 0x61, 0x3c, 0x5f, 0x68, 0x1d, 0x35, 0x24, 0x21, + 0x23, 0x0c, 0x46, 0x17, 0x23, 0x1b, 0x19, 0x24, 0x24, 0x19, 0x1b, 0x23, 0xe4, 0x26, 0x37, 0x32, 0x1b, 0x21, 0x2c, + 0x2a, 0x1e, 0x30, 0x34, 0x19, 0x11, 0x46, 0x15, 0x1c, 0x5e, 0x51, 0x2d, 0x3f, 0x35, 0x1e, 0x1c, 0x2a, 0x29, 0x1d, + 0x11, 0x93, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x00, 0x02, 0x00, 0x3a, 0xff, 0xa7, 0x03, 0x49, 0x02, + 0xca, 0x00, 0x3f, 0x00, 0x4d, 0x00, 0x7b, 0x40, 0x13, 0x16, 0x01, 0x09, 0x02, 0x47, 0x08, 0x02, 0x03, 0x09, 0x2f, + 0x01, 0x05, 0x00, 0x30, 0x01, 0x06, 0x05, 0x04, 0x4c, 0x4b, 0xb0, 0x1e, 0x50, 0x58, 0x40, 0x26, 0x08, 0x01, 0x03, + 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, + 0x00, 0x07, 0x07, 0x6a, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x24, + 0x00, 0x02, 0x00, 0x09, 0x03, 0x02, 0x09, 0x69, 0x08, 0x01, 0x03, 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, + 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, 0x00, 0x07, 0x07, 0x6a, 0x04, 0x4e, 0x59, 0x40, + 0x0e, 0x4b, 0x49, 0x25, 0x27, 0x25, 0x25, 0x26, 0x28, 0x25, 0x25, 0x24, 0x0a, 0x0d, 0x1f, 0x2b, 0x01, 0x14, 0x0e, + 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x06, 0x14, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, + 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x03, 0x49, 0x15, + 0x2c, 0x40, 0x2c, 0x2e, 0x35, 0x06, 0x05, 0x12, 0x46, 0x35, 0x4c, 0x53, 0x34, 0x5f, 0x41, 0x2c, 0x55, 0x18, 0x0a, + 0x01, 0x25, 0x19, 0x1f, 0x2b, 0x17, 0x4b, 0x83, 0x53, 0x72, 0x9d, 0x51, 0x9c, 0x93, 0x3d, 0x6f, 0x2b, 0x2b, 0x6b, + 0x41, 0x76, 0xa8, 0x59, 0x3a, 0x6e, 0x9d, 0x63, 0x68, 0xa2, 0x5d, 0xfe, 0x07, 0x33, 0x2b, 0x38, 0x31, 0x04, 0x06, + 0x0d, 0x28, 0x15, 0x31, 0x3c, 0x1a, 0x01, 0x65, 0x2e, 0x58, 0x47, 0x2b, 0x35, 0x22, 0x25, 0x32, 0x66, 0x54, 0x42, + 0x65, 0x3a, 0x0f, 0x09, 0xcb, 0x12, 0x0f, 0x03, 0x34, 0x22, 0x33, 0x55, 0x33, 0x5d, 0x81, 0x44, 0x5e, 0xa5, 0x6a, + 0x94, 0x9e, 0x1b, 0x10, 0x44, 0x12, 0x17, 0x58, 0xa5, 0x74, 0x5d, 0x9f, 0x75, 0x41, 0x56, 0xa0, 0xaf, 0x40, 0x3a, + 0x54, 0x43, 0x7d, 0x04, 0x06, 0x30, 0x4b, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7e, 0x02, 0xcd, 0x00, + 0x07, 0x00, 0x11, 0x00, 0x2c, 0x40, 0x29, 0x0c, 0x01, 0x04, 0x02, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x00, 0x01, 0x04, + 0x00, 0x68, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x11, 0x10, + 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x21, 0x27, 0x21, 0x07, 0x23, 0x01, 0x33, 0x01, + 0x01, 0x2e, 0x02, 0x27, 0x06, 0x06, 0x07, 0x07, 0x33, 0x02, 0x21, 0x56, 0xfe, 0xe5, 0x55, 0x5b, 0x01, 0x17, 0x51, + 0x01, 0x16, 0xfe, 0xe2, 0x03, 0x0e, 0x0d, 0x04, 0x07, 0x12, 0x06, 0x51, 0xe2, 0xdd, 0xdd, 0x02, 0xcd, 0xfd, 0x33, + 0x02, 0x05, 0x08, 0x2a, 0x2d, 0x0c, 0x1f, 0x3b, 0x11, 0xd8, 0x00, 0x03, 0x00, 0x61, 0x00, 0x00, 0x02, 0x54, 0x02, + 0xca, 0x00, 0x10, 0x00, 0x19, 0x00, 0x22, 0x00, 0x44, 0x40, 0x41, 0x06, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, + 0x02, 0x08, 0x01, 0x05, 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, 0x6a, 0x4d, + 0x00, 0x04, 0x04, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1a, 0x1a, 0x12, 0x11, 0x01, 0x00, 0x1a, 0x22, + 0x1a, 0x21, 0x1d, 0x1b, 0x18, 0x16, 0x11, 0x19, 0x12, 0x19, 0x0f, 0x0d, 0x00, 0x10, 0x01, 0x10, 0x09, 0x0d, 0x16, + 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x23, 0x23, 0x11, 0x13, 0x32, + 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x15, 0x15, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x2d, 0x86, + 0x89, 0x46, 0x42, 0x2d, 0x49, 0x2a, 0x85, 0x73, 0xfb, 0xde, 0x5c, 0x44, 0x53, 0x5b, 0x76, 0x90, 0x5f, 0x4a, 0x4d, + 0x63, 0x02, 0xca, 0x4f, 0x62, 0x3f, 0x53, 0x0c, 0x05, 0x07, 0x26, 0x46, 0x38, 0x61, 0x6a, 0x02, 0xca, 0xfe, 0xd0, + 0x3b, 0x3a, 0x3b, 0x33, 0xe3, 0x4b, 0xfe, 0xfd, 0x4a, 0x3c, 0x38, 0x45, 0x00, 0x00, 0x01, 0x00, 0x3d, 0xff, 0xf6, + 0x02, 0x59, 0x02, 0xd4, 0x00, 0x1a, 0x00, 0x37, 0x40, 0x34, 0x17, 0x01, 0x00, 0x03, 0x18, 0x09, 0x02, 0x01, 0x00, + 0x0a, 0x01, 0x02, 0x01, 0x03, 0x4c, 0x04, 0x01, 0x00, 0x00, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, + 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x01, 0x00, 0x16, 0x14, 0x0e, 0x0c, 0x07, 0x05, 0x00, 0x1a, + 0x01, 0x1a, 0x05, 0x0d, 0x16, 0x2b, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, + 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x17, 0x07, 0x26, 0x26, 0x01, 0x93, 0x73, 0x84, 0x7b, + 0x7b, 0x2f, 0x54, 0x28, 0x28, 0x55, 0x3b, 0x6d, 0x92, 0x49, 0x4f, 0x9a, 0x6e, 0x71, 0x54, 0x24, 0x21, 0x51, 0x02, + 0x85, 0x9a, 0x86, 0x85, 0x9b, 0x10, 0x0c, 0x4e, 0x0f, 0x0e, 0x5a, 0xa6, 0x70, 0x6c, 0xa5, 0x5d, 0x2a, 0x4c, 0x0f, + 0x18, 0x00, 0x02, 0x00, 0x61, 0x00, 0x00, 0x02, 0x9d, 0x02, 0xca, 0x00, 0x09, 0x00, 0x11, 0x00, 0x1f, 0x40, 0x1c, + 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, + 0x00, 0x4e, 0x21, 0x25, 0x21, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x23, 0x23, 0x11, 0x33, 0x32, 0x16, + 0x16, 0x07, 0x34, 0x26, 0x23, 0x23, 0x11, 0x33, 0x20, 0x02, 0x9d, 0xc5, 0xb0, 0xc7, 0xdc, 0x6c, 0x9e, 0x56, 0x5f, + 0x8d, 0x81, 0x75, 0x61, 0x01, 0x22, 0x01, 0x6c, 0xb5, 0xb7, 0x02, 0xca, 0x50, 0x9b, 0x76, 0x8f, 0x85, 0xfd, 0xd0, + 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, 0xf0, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x29, 0x40, 0x26, 0x00, 0x03, 0x00, + 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x00, + 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x21, + 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0xf0, 0xfe, 0x71, 0x01, 0x8f, 0xfe, 0xcb, 0x01, + 0x23, 0xfe, 0xdd, 0x01, 0x35, 0x02, 0xca, 0x4f, 0xdf, 0x4e, 0xff, 0x00, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, + 0xf0, 0x02, 0xca, 0x00, 0x09, 0x00, 0x23, 0x40, 0x20, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x67, 0x00, 0x02, + 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x10, + 0x05, 0x0d, 0x1b, 0x2b, 0x33, 0x23, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0xbb, 0x5a, 0x01, 0x8f, 0xfe, + 0xcb, 0x01, 0x22, 0xfe, 0xde, 0x02, 0xca, 0x4f, 0xfd, 0x4f, 0x00, 0x01, 0x00, 0x3d, 0xff, 0xf6, 0x02, 0x8e, 0x02, + 0xd4, 0x00, 0x20, 0x00, 0x3b, 0x40, 0x38, 0x10, 0x01, 0x03, 0x02, 0x11, 0x01, 0x00, 0x03, 0x1e, 0x01, 0x04, 0x05, + 0x02, 0x01, 0x01, 0x04, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x67, 0x00, 0x03, 0x03, 0x02, 0x61, + 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x13, 0x25, 0x25, + 0x26, 0x23, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x11, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, + 0x35, 0x23, 0x01, 0x97, 0xf7, 0x3a, 0x76, 0x4b, 0x6f, 0x98, 0x4f, 0x58, 0xa5, 0x75, 0x3c, 0x6b, 0x2e, 0x22, 0x26, + 0x5f, 0x33, 0x80, 0x8f, 0x37, 0x76, 0x60, 0x2f, 0x42, 0x1b, 0x9d, 0x01, 0x79, 0xfe, 0xa2, 0x13, 0x12, 0x59, 0xa5, + 0x71, 0x70, 0xa4, 0x5b, 0x16, 0x14, 0x4e, 0x11, 0x18, 0x9a, 0x86, 0x55, 0x83, 0x49, 0x0a, 0x07, 0xd4, 0x00, 0x00, + 0x01, 0x00, 0x61, 0x00, 0x00, 0x02, 0x83, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x21, 0x40, 0x1e, 0x00, 0x04, 0x00, 0x01, + 0x00, 0x04, 0x01, 0x67, 0x05, 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, + 0x33, 0x02, 0x83, 0x5a, 0xfe, 0x92, 0x5a, 0x5a, 0x01, 0x6e, 0x5a, 0x01, 0x4d, 0xfe, 0xb3, 0x02, 0xca, 0xfe, 0xd2, + 0x01, 0x2e, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x01, 0x2a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, + 0x0b, 0x0a, 0x09, 0x08, 0x05, 0x04, 0x03, 0x02, 0x08, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x11, 0x27, 0x35, 0x21, + 0x15, 0x07, 0x11, 0x17, 0x01, 0x2a, 0xfe, 0xfe, 0x54, 0x54, 0x01, 0x02, 0x54, 0x54, 0x34, 0x13, 0x02, 0x3b, 0x14, + 0x34, 0x34, 0x14, 0xfd, 0xc5, 0x13, 0x00, 0x00, 0x01, 0xff, 0xb2, 0xff, 0x42, 0x00, 0xb6, 0x02, 0xca, 0x00, 0x10, + 0x00, 0x28, 0x40, 0x25, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, 0x00, + 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, 0x01, 0x00, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x10, 0x01, 0x10, + 0x04, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x11, 0x33, 0x11, + 0x14, 0x06, 0x04, 0x18, 0x24, 0x0e, 0x10, 0x24, 0x14, 0x19, 0x2d, 0x1c, 0x5a, 0x66, 0xbe, 0x07, 0x06, 0x4c, 0x04, + 0x06, 0x14, 0x32, 0x2d, 0x02, 0xc6, 0xfd, 0x41, 0x67, 0x62, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x02, 0x6b, 0x02, + 0xca, 0x00, 0x0e, 0x00, 0x20, 0x40, 0x1d, 0x0e, 0x08, 0x03, 0x02, 0x04, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, + 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x11, 0x13, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, + 0x23, 0x03, 0x07, 0x11, 0x23, 0x11, 0x33, 0x11, 0x36, 0x36, 0x37, 0x37, 0x33, 0x01, 0x02, 0x6b, 0x6a, 0xfd, 0x49, + 0x5a, 0x5a, 0x1e, 0x3e, 0x1f, 0xc1, 0x69, 0xfe, 0xe5, 0x01, 0x55, 0x40, 0xfe, 0xeb, 0x02, 0xca, 0xfe, 0xa0, 0x22, + 0x44, 0x22, 0xd8, 0xfe, 0xc9, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, 0xf3, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, + 0x40, 0x1c, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x61, + 0x5a, 0x01, 0x38, 0x02, 0xca, 0xfd, 0x86, 0x50, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x03, 0x2a, 0x02, 0xca, 0x00, + 0x15, 0x00, 0x27, 0x40, 0x24, 0x13, 0x0a, 0x01, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, + 0x05, 0x04, 0x03, 0x03, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x15, 0x00, 0x15, 0x11, 0x13, 0x11, 0x16, + 0x06, 0x0d, 0x1a, 0x2b, 0x21, 0x03, 0x23, 0x16, 0x16, 0x15, 0x11, 0x23, 0x11, 0x33, 0x13, 0x33, 0x13, 0x33, 0x11, + 0x23, 0x11, 0x34, 0x36, 0x37, 0x23, 0x03, 0x01, 0x9c, 0xeb, 0x04, 0x03, 0x04, 0x53, 0x85, 0xdc, 0x04, 0xe0, 0x84, + 0x59, 0x05, 0x02, 0x04, 0xee, 0x02, 0x72, 0x1f, 0x69, 0x39, 0xfe, 0x4f, 0x02, 0xca, 0xfd, 0xb7, 0x02, 0x49, 0xfd, + 0x36, 0x01, 0xb7, 0x34, 0x66, 0x20, 0xfd, 0x8f, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x02, 0x97, 0x02, 0xca, 0x00, + 0x12, 0x00, 0x1d, 0x40, 0x1a, 0x02, 0x01, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x17, 0x11, 0x16, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x01, 0x23, 0x16, 0x16, + 0x15, 0x11, 0x23, 0x11, 0x33, 0x01, 0x33, 0x2e, 0x02, 0x35, 0x11, 0x33, 0x02, 0x97, 0x69, 0xfe, 0x82, 0x04, 0x02, + 0x06, 0x53, 0x68, 0x01, 0x7d, 0x04, 0x01, 0x03, 0x03, 0x54, 0x02, 0x51, 0x23, 0x68, 0x37, 0xfe, 0x71, 0x02, 0xca, + 0xfd, 0xb1, 0x10, 0x40, 0x4c, 0x20, 0x01, 0x93, 0x00, 0x00, 0x02, 0x00, 0x3d, 0xff, 0xf6, 0x02, 0xd0, 0x02, 0xd5, + 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, + 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x25, 0x26, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, + 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, + 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xd0, 0x4b, 0x92, 0x6c, 0x6f, 0x93, 0x48, 0x48, 0x93, 0x70, + 0x6b, 0x92, 0x4b, 0xfd, 0xcc, 0x72, 0x79, 0x7a, 0x70, 0x70, 0x79, 0x79, 0x73, 0x01, 0x66, 0x6f, 0xa5, 0x5c, 0x5c, + 0xa6, 0x6f, 0x6e, 0xa4, 0x5c, 0x5b, 0xa5, 0x6f, 0x87, 0x9b, 0x9b, 0x87, 0x87, 0x99, 0x99, 0x00, 0x02, 0x00, 0x61, + 0x00, 0x00, 0x02, 0x2a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x32, 0x40, 0x2f, 0x00, 0x04, 0x00, 0x01, 0x02, + 0x04, 0x01, 0x67, 0x06, 0x01, 0x03, 0x03, 0x00, 0x5f, 0x05, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x6b, + 0x02, 0x4e, 0x0d, 0x0c, 0x01, 0x00, 0x10, 0x0e, 0x0c, 0x14, 0x0d, 0x14, 0x0a, 0x09, 0x08, 0x06, 0x00, 0x0b, 0x01, + 0x0b, 0x07, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x23, 0x11, 0x23, 0x11, 0x17, 0x23, + 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x1e, 0x8c, 0x80, 0x35, 0x7d, 0x6b, 0x52, 0x5a, 0xb5, 0x5b, 0x48, + 0x66, 0x64, 0x58, 0x02, 0xca, 0x6e, 0x64, 0x3b, 0x67, 0x40, 0xfe, 0xea, 0x02, 0xca, 0x4d, 0xfe, 0xe6, 0x42, 0x4f, + 0x45, 0x44, 0x00, 0x02, 0x00, 0x3d, 0xff, 0x56, 0x02, 0xd0, 0x02, 0xd5, 0x00, 0x14, 0x00, 0x20, 0x00, 0x2b, 0x40, + 0x28, 0x03, 0x01, 0x01, 0x03, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x86, 0x00, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, + 0x02, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x25, 0x26, 0x41, 0x14, + 0x05, 0x0d, 0x1b, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x17, 0x23, 0x27, 0x22, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, + 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, + 0xd0, 0x69, 0x67, 0xab, 0x81, 0x8a, 0x06, 0x0d, 0x06, 0x6f, 0x93, 0x48, 0x48, 0x93, 0x70, 0x6b, 0x92, 0x4b, 0xfd, + 0xcc, 0x72, 0x79, 0x7a, 0x70, 0x70, 0x79, 0x79, 0x73, 0x01, 0x66, 0x83, 0xb8, 0x23, 0xb2, 0xa1, 0x01, 0x5c, 0xa6, + 0x6f, 0x6e, 0xa4, 0x5c, 0x5b, 0xa5, 0x6f, 0x87, 0x9b, 0x9b, 0x87, 0x87, 0x99, 0x99, 0x00, 0x00, 0x02, 0x00, 0x61, + 0x00, 0x00, 0x02, 0x5f, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x17, 0x00, 0x3b, 0x40, 0x38, 0x07, 0x01, 0x02, 0x05, 0x01, + 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, + 0x6a, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x10, 0x0f, 0x01, 0x00, 0x13, 0x11, 0x0f, 0x17, 0x10, 0x17, + 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x00, 0x0e, 0x01, 0x0e, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, + 0x06, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x11, 0x23, 0x11, 0x17, 0x23, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, + 0x01, 0x26, 0x85, 0x7f, 0x2a, 0x41, 0x24, 0xc4, 0x69, 0xad, 0x8e, 0x5a, 0xc0, 0x66, 0x6b, 0x57, 0x50, 0x54, 0x02, + 0xca, 0x65, 0x66, 0x39, 0x4c, 0x2d, 0x0d, 0xfe, 0xc0, 0x01, 0x27, 0xfe, 0xd9, 0x02, 0xca, 0x4e, 0xfe, 0xf7, 0x45, + 0x43, 0x46, 0x3b, 0x00, 0x01, 0x00, 0x33, 0xff, 0xf6, 0x01, 0xf6, 0x02, 0xd4, 0x00, 0x29, 0x00, 0x2e, 0x40, 0x2b, + 0x1b, 0x01, 0x03, 0x02, 0x1c, 0x07, 0x02, 0x01, 0x03, 0x06, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, + 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, 0x2c, + 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, + 0x35, 0x34, 0x26, 0x26, 0x27, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, + 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xf6, 0x8a, 0x75, 0x3c, 0x66, 0x22, 0x24, 0x6b, 0x39, + 0x50, 0x51, 0x1e, 0x49, 0x41, 0x5b, 0x5d, 0x3a, 0x67, 0x43, 0x3b, 0x62, 0x28, 0x1c, 0x25, 0x57, 0x2f, 0x43, 0x44, + 0x1e, 0x44, 0x3a, 0x3f, 0x57, 0x2d, 0xbf, 0x5f, 0x6a, 0x12, 0x10, 0x56, 0x10, 0x1a, 0x3e, 0x35, 0x23, 0x30, 0x29, + 0x17, 0x21, 0x60, 0x53, 0x39, 0x51, 0x2c, 0x16, 0x12, 0x4d, 0x10, 0x16, 0x39, 0x2f, 0x24, 0x30, 0x26, 0x16, 0x17, + 0x35, 0x4a, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x02, 0x21, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1b, 0x40, 0x18, 0x03, + 0x01, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, + 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x11, 0x23, 0x35, 0x21, 0x15, 0x23, 0x01, 0x43, 0x5a, 0xdf, 0x02, 0x17, + 0xde, 0x02, 0x7b, 0x4f, 0x4f, 0x00, 0x01, 0x00, 0x5a, 0xff, 0xf6, 0x02, 0x80, 0x02, 0xca, 0x00, 0x12, 0x00, 0x1b, + 0x40, 0x18, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x13, 0x23, 0x13, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x02, 0x80, 0x3c, 0x7b, 0x5f, 0x85, 0x8b, 0x5a, 0x5d, 0x5e, 0x61, + 0x57, 0x59, 0xfc, 0x4a, 0x77, 0x45, 0x91, 0x77, 0x01, 0xcc, 0xfe, 0x31, 0x57, 0x60, 0x67, 0x51, 0x01, 0xce, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x58, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x21, 0x40, 0x1e, 0x08, 0x01, 0x00, + 0x01, 0x01, 0x4c, 0x03, 0x02, 0x02, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x0c, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x01, 0x03, 0x23, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x36, + 0x36, 0x37, 0x13, 0x02, 0x58, 0xff, 0x5a, 0xff, 0x5e, 0xa1, 0x10, 0x16, 0x07, 0x07, 0x16, 0x10, 0xa0, 0x02, 0xca, + 0xfd, 0x36, 0x02, 0xca, 0xfe, 0x36, 0x2c, 0x4d, 0x23, 0x23, 0x4e, 0x2d, 0x01, 0xc8, 0x00, 0x01, 0x00, 0x0c, 0x00, + 0x00, 0x03, 0x95, 0x02, 0xca, 0x00, 0x1f, 0x00, 0x27, 0x40, 0x24, 0x1b, 0x12, 0x07, 0x03, 0x00, 0x02, 0x01, 0x4c, + 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x1f, 0x18, 0x11, 0x19, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x01, 0x03, 0x23, 0x03, 0x2e, 0x02, 0x27, 0x06, 0x06, + 0x07, 0x03, 0x23, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x36, 0x36, 0x37, 0x13, 0x33, 0x13, 0x16, 0x16, 0x17, 0x36, + 0x36, 0x37, 0x13, 0x03, 0x95, 0xbe, 0x5b, 0x8b, 0x08, 0x10, 0x0a, 0x02, 0x01, 0x13, 0x0e, 0x87, 0x5b, 0xbd, 0x5e, + 0x6f, 0x0c, 0x11, 0x05, 0x05, 0x14, 0x0d, 0x7e, 0x5d, 0x83, 0x0e, 0x14, 0x05, 0x05, 0x12, 0x0c, 0x6e, 0x02, 0xca, + 0xfd, 0x36, 0x01, 0xd4, 0x1d, 0x3a, 0x2d, 0x09, 0x0d, 0x55, 0x2e, 0xfe, 0x2f, 0x02, 0xca, 0xfe, 0x4c, 0x2e, 0x56, + 0x26, 0x27, 0x5c, 0x2c, 0x01, 0xaf, 0xfe, 0x4e, 0x2e, 0x5b, 0x23, 0x25, 0x57, 0x2f, 0x01, 0xb3, 0x00, 0x01, 0x00, + 0x04, 0x00, 0x00, 0x02, 0x46, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x08, 0x05, 0x02, 0x04, 0x00, + 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x12, 0x12, + 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x03, 0x23, 0x13, 0x03, 0x33, 0x13, 0x13, 0x33, 0x03, 0x02, 0x46, + 0x66, 0xbd, 0xc0, 0x5f, 0xed, 0xde, 0x64, 0xaf, 0xb0, 0x5f, 0xdd, 0x01, 0x36, 0xfe, 0xca, 0x01, 0x74, 0x01, 0x56, + 0xfe, 0xe8, 0x01, 0x18, 0xfe, 0xac, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x36, 0x02, 0xca, 0x00, 0x08, + 0x00, 0x1c, 0x40, 0x19, 0x06, 0x03, 0x02, 0x01, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, + 0x01, 0x6b, 0x01, 0x4e, 0x12, 0x12, 0x11, 0x03, 0x0d, 0x19, 0x2b, 0x01, 0x13, 0x33, 0x03, 0x11, 0x23, 0x11, 0x03, + 0x33, 0x01, 0x1b, 0xba, 0x61, 0xee, 0x5a, 0xee, 0x62, 0x01, 0x6b, 0x01, 0x5f, 0xfe, 0x4b, 0xfe, 0xeb, 0x01, 0x11, + 0x01, 0xb9, 0x00, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x02, 0x15, 0x02, 0xca, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, + 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, + 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, + 0x2b, 0x21, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x21, 0x02, 0x15, 0xfe, 0x11, 0x01, 0x78, 0xfe, 0x94, + 0x01, 0xd9, 0xfe, 0x88, 0x01, 0x82, 0x44, 0x02, 0x36, 0x50, 0x44, 0xfd, 0xca, 0x00, 0x01, 0x00, 0x50, 0xff, 0x62, + 0x01, 0x30, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x63, 0x00, 0x02, + 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x02, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x05, 0x23, + 0x11, 0x33, 0x15, 0x23, 0x11, 0x33, 0x01, 0x30, 0xe0, 0xe0, 0x8a, 0x8a, 0x9e, 0x03, 0x68, 0x48, 0xfd, 0x28, 0x00, + 0x01, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x6b, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, + 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, + 0x13, 0x01, 0x23, 0x01, 0x60, 0x01, 0x0b, 0x57, 0xfe, 0xf6, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0x00, 0x00, 0x01, + 0x00, 0x19, 0xff, 0x62, 0x00, 0xf9, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x03, 0x63, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, + 0x1a, 0x2b, 0x17, 0x33, 0x11, 0x23, 0x35, 0x33, 0x11, 0x23, 0x19, 0x8a, 0x8a, 0xe0, 0xe0, 0x56, 0x02, 0xd8, 0x48, + 0xfc, 0x98, 0x00, 0x00, 0x01, 0x00, 0x26, 0x01, 0x0b, 0x02, 0x16, 0x02, 0xcf, 0x00, 0x06, 0x00, 0x27, 0xb1, 0x06, + 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x03, 0x02, 0x02, 0x01, + 0x01, 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x13, + 0x13, 0x33, 0x13, 0x23, 0x03, 0x03, 0x26, 0xd4, 0x32, 0xea, 0x4e, 0xb4, 0xa0, 0x01, 0x0b, 0x01, 0xc4, 0xfe, 0x3c, + 0x01, 0x67, 0xfe, 0x99, 0x00, 0x00, 0x01, 0xff, 0xfe, 0xff, 0x66, 0x01, 0xbe, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x20, + 0xb1, 0x06, 0x64, 0x44, 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, + 0x01, 0x00, 0x4f, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x05, 0x21, 0x35, 0x21, 0x01, 0xbe, + 0xfe, 0x40, 0x01, 0xc0, 0x9a, 0x40, 0x00, 0x01, 0x00, 0x28, 0x02, 0x5e, 0x00, 0xf1, 0x02, 0xfe, 0x00, 0x0b, 0x00, + 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x0a, 0x04, 0x02, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x00, 0x01, + 0x85, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, + 0x44, 0x13, 0x1e, 0x02, 0x17, 0x15, 0x23, 0x2e, 0x02, 0x27, 0x35, 0x91, 0x0b, 0x21, 0x25, 0x0f, 0x3b, 0x17, 0x3a, + 0x31, 0x0c, 0x02, 0xfe, 0x16, 0x37, 0x34, 0x13, 0x0c, 0x12, 0x39, 0x39, 0x12, 0x0a, 0x00, 0x02, 0x00, 0x2e, 0xff, + 0xf6, 0x01, 0xe0, 0x02, 0x21, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x7b, 0x40, 0x0e, 0x19, 0x01, 0x04, 0x00, 0x18, 0x01, + 0x03, 0x04, 0x06, 0x01, 0x06, 0x05, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x20, 0x00, 0x03, 0x08, 0x01, + 0x05, 0x06, 0x03, 0x05, 0x67, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, + 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x24, 0x00, 0x03, 0x08, 0x01, 0x05, 0x06, 0x03, + 0x05, 0x67, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x00, + 0x06, 0x06, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, + 0x1c, 0x26, 0x1d, 0x26, 0x16, 0x14, 0x11, 0x0f, 0x0b, 0x09, 0x05, 0x04, 0x00, 0x1b, 0x01, 0x1b, 0x09, 0x0d, 0x16, + 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, + 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x13, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, + 0x35, 0x35, 0x01, 0x20, 0x62, 0x5e, 0x40, 0x11, 0x04, 0x23, 0x4d, 0x44, 0x49, 0x60, 0x7e, 0x83, 0x5b, 0x3a, 0x35, + 0x2a, 0x4c, 0x21, 0x1b, 0x23, 0x60, 0x4e, 0x64, 0x4d, 0x37, 0x2b, 0x44, 0x5a, 0x02, 0x21, 0x56, 0x5e, 0xfe, 0x93, + 0x4c, 0x2c, 0x2a, 0x4d, 0x52, 0x50, 0x57, 0x04, 0x03, 0x20, 0x43, 0x34, 0x19, 0x10, 0x42, 0x13, 0x1b, 0xfe, 0xe2, + 0x04, 0x38, 0x33, 0x2d, 0x2a, 0x4b, 0x4e, 0x30, 0x00, 0x00, 0x02, 0x00, 0x55, 0xff, 0xf6, 0x02, 0x30, 0x02, 0xf8, + 0x00, 0x15, 0x00, 0x21, 0x00, 0x8a, 0xb6, 0x10, 0x03, 0x02, 0x05, 0x04, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x1c, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, + 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1b, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x20, + 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, + 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1b, 0x40, 0x20, 0x06, 0x01, 0x04, + 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6b, 0x4d, 0x00, + 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x59, 0x59, 0x40, 0x0f, 0x17, 0x16, 0x1e, 0x1c, 0x16, + 0x21, 0x17, 0x21, 0x11, 0x14, 0x24, 0x26, 0x07, 0x0d, 0x1a, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x07, 0x23, 0x11, 0x33, 0x13, 0x22, 0x06, 0x15, 0x15, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0xad, 0x03, 0x02, 0x05, 0x17, 0x50, 0x3f, 0x64, 0x79, 0x7a, 0x63, 0x3f, + 0x50, 0x17, 0x07, 0x12, 0x3f, 0x58, 0x97, 0x55, 0x42, 0x41, 0x58, 0x48, 0x47, 0x02, 0x3f, 0x22, 0x3b, 0x11, 0x22, + 0x2e, 0x8b, 0x8a, 0x8a, 0x8c, 0x2e, 0x20, 0x44, 0x02, 0xf8, 0xfe, 0xe0, 0x62, 0x67, 0x04, 0x63, 0x69, 0x6a, 0x64, + 0xcb, 0x00, 0x00, 0x01, 0x00, 0x37, 0xff, 0xf6, 0x01, 0xbf, 0x02, 0x22, 0x00, 0x1a, 0x00, 0x37, 0x40, 0x34, 0x0b, + 0x01, 0x02, 0x01, 0x17, 0x0c, 0x02, 0x03, 0x02, 0x18, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, + 0x15, 0x13, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1a, 0x01, 0x1a, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, + 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, + 0x15, 0x06, 0x06, 0x01, 0x2c, 0x47, 0x6f, 0x3f, 0x42, 0x71, 0x48, 0x29, 0x4c, 0x18, 0x1b, 0x18, 0x40, 0x1c, 0x9e, + 0x4d, 0x4c, 0x2c, 0x43, 0x1c, 0x1b, 0x41, 0x0a, 0x3a, 0x7a, 0x5f, 0x63, 0x7c, 0x3a, 0x11, 0x0c, 0x49, 0x09, 0x10, + 0xcb, 0x61, 0x67, 0x12, 0x0d, 0x4e, 0x0e, 0x0f, 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x12, 0x02, 0xf8, + 0x00, 0x15, 0x00, 0x22, 0x00, 0x95, 0xb6, 0x12, 0x09, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, + 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, + 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, + 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6b, 0x4d, + 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x17, 0x17, 0x16, + 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x22, 0x17, 0x22, 0x11, 0x10, 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, + 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x26, 0x26, 0x35, 0x35, 0x33, + 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x27, 0x32, 0x36, 0x35, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, + 0x01, 0x13, 0x64, 0x78, 0x79, 0x64, 0x3e, 0x4f, 0x19, 0x06, 0x01, 0x05, 0x58, 0x47, 0x0d, 0x04, 0x18, 0x50, 0x31, + 0x55, 0x45, 0x42, 0x59, 0x47, 0x47, 0x47, 0x0a, 0x8b, 0x8a, 0x8a, 0x8d, 0x2e, 0x21, 0x0d, 0x33, 0x0f, 0xd6, 0xfd, + 0x08, 0x48, 0x22, 0x30, 0x49, 0x5d, 0x5e, 0x10, 0x64, 0x6b, 0x71, 0x5f, 0x60, 0x6a, 0x00, 0x02, 0x00, 0x37, 0xff, + 0xf6, 0x02, 0x01, 0x02, 0x22, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x43, 0x40, 0x40, 0x0c, 0x01, 0x02, 0x01, 0x0d, 0x01, + 0x03, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x01, 0x02, 0x05, 0x01, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x19, 0x18, 0x01, + 0x00, 0x1c, 0x1b, 0x18, 0x1e, 0x19, 0x1e, 0x11, 0x0f, 0x0a, 0x08, 0x06, 0x05, 0x00, 0x17, 0x01, 0x17, 0x08, 0x0d, + 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x15, 0x21, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, + 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x07, 0x21, 0x26, 0x26, 0x01, 0x24, 0x45, 0x63, 0x35, + 0xfe, 0x91, 0x02, 0x59, 0x50, 0x33, 0x4f, 0x2a, 0x29, 0x50, 0x37, 0x4c, 0x75, 0x41, 0x3b, 0x6b, 0x46, 0x3f, 0x49, + 0x07, 0x01, 0x11, 0x01, 0x3e, 0x02, 0x22, 0x3c, 0x6d, 0x49, 0x35, 0x5b, 0x5f, 0x13, 0x12, 0x4d, 0x12, 0x11, 0x3e, + 0x7b, 0x59, 0x58, 0x7e, 0x44, 0x48, 0x51, 0x48, 0x44, 0x55, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x83, + 0x02, 0xfd, 0x00, 0x17, 0x00, 0x5c, 0x40, 0x0f, 0x0e, 0x01, 0x04, 0x03, 0x0f, 0x07, 0x02, 0x05, 0x04, 0x06, 0x01, + 0x00, 0x05, 0x03, 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, + 0x6c, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, + 0x1b, 0x40, 0x19, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x69, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, + 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x09, 0x13, 0x25, 0x25, 0x11, 0x11, 0x10, 0x06, + 0x0d, 0x1c, 0x2b, 0x01, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x37, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, + 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x15, 0x33, 0x01, 0x4c, 0x87, 0x58, 0x5e, 0x5e, 0x5c, 0x52, 0x20, 0x35, 0x13, + 0x17, 0x10, 0x2a, 0x16, 0x2c, 0x2b, 0x87, 0x01, 0xd4, 0xfe, 0x2c, 0x01, 0xd4, 0x29, 0x1e, 0x1f, 0x68, 0x5b, 0x0b, + 0x07, 0x45, 0x05, 0x0a, 0x3b, 0x3f, 0x23, 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0x10, 0x02, 0x12, 0x02, 0x22, 0x00, + 0x1e, 0x00, 0x2b, 0x00, 0x80, 0x40, 0x0f, 0x16, 0x03, 0x02, 0x06, 0x05, 0x0d, 0x01, 0x03, 0x04, 0x0c, 0x01, 0x02, + 0x03, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x08, 0x01, 0x05, 0x05, 0x00, 0x61, 0x01, 0x07, 0x02, + 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, + 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x00, + 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, + 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x20, 0x1f, 0x01, 0x00, 0x26, 0x24, 0x1f, + 0x2b, 0x20, 0x2b, 0x1a, 0x18, 0x10, 0x0e, 0x0b, 0x09, 0x06, 0x05, 0x00, 0x1e, 0x01, 0x1e, 0x09, 0x0d, 0x16, 0x2b, + 0x01, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x14, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x35, + 0x35, 0x34, 0x36, 0x37, 0x23, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, + 0x32, 0x36, 0x35, 0x35, 0x34, 0x26, 0x01, 0x13, 0x35, 0x55, 0x1e, 0x05, 0x0c, 0x46, 0x75, 0x7b, 0x76, 0x4b, 0x4f, + 0x77, 0x45, 0x4f, 0x02, 0x01, 0x04, 0x36, 0x70, 0x68, 0x75, 0x75, 0x73, 0x43, 0x4a, 0x49, 0x46, 0x51, 0x4a, 0x4c, + 0x02, 0x22, 0x28, 0x29, 0x47, 0xfd, 0xdf, 0x73, 0x74, 0x22, 0x51, 0x2a, 0x51, 0x46, 0x15, 0x0c, 0x2d, 0x09, 0x51, + 0x92, 0x83, 0x80, 0x97, 0x4a, 0x6b, 0x63, 0x63, 0x69, 0x57, 0x61, 0x15, 0x6e, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x55, + 0x00, 0x00, 0x02, 0x19, 0x02, 0xf8, 0x00, 0x15, 0x00, 0x48, 0xb5, 0x02, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x4b, 0xb0, + 0x29, 0x50, 0x58, 0x40, 0x16, 0x00, 0x04, 0x04, 0x6c, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, + 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x73, 0x4d, 0x00, 0x04, 0x04, 0x01, 0x5f, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0xb7, 0x11, 0x13, 0x22, + 0x13, 0x25, 0x05, 0x0d, 0x1b, 0x2b, 0x13, 0x14, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, + 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0xad, 0x05, 0x06, 0x1a, 0x59, 0x34, 0x62, 0x62, 0x57, 0x78, + 0x5a, 0x43, 0x58, 0x58, 0x02, 0x19, 0x28, 0x23, 0x29, 0x2a, 0x5d, 0x67, 0xfe, 0xa3, 0x01, 0x57, 0x81, 0x65, 0x5e, + 0xfe, 0xeb, 0x02, 0xf8, 0x00, 0x00, 0x02, 0x00, 0x4e, 0x00, 0x00, 0x00, 0xb5, 0x02, 0xe1, 0x00, 0x0b, 0x00, 0x0f, + 0x00, 0x8d, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x6c, + 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, + 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, + 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, + 0x04, 0x01, 0x00, 0x00, 0x6c, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, + 0x40, 0x15, 0x04, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x01, 0x69, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, + 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x13, 0x0c, 0x0c, 0x01, 0x00, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, + 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, + 0x35, 0x34, 0x36, 0x17, 0x11, 0x23, 0x11, 0x82, 0x14, 0x1f, 0x1f, 0x14, 0x16, 0x1e, 0x1e, 0x41, 0x58, 0x02, 0xe1, + 0x1b, 0x1d, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1b, 0xc9, 0xfd, 0xe8, 0x02, 0x18, 0x00, 0x02, 0xff, 0xc9, 0xff, 0x10, + 0x00, 0xb5, 0x02, 0xe1, 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xa5, 0x40, 0x0a, 0x10, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, + 0x03, 0x02, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x6c, + 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, + 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x04, + 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, + 0x50, 0x58, 0x40, 0x1b, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, + 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x19, 0x00, 0x00, 0x00, 0x01, + 0x04, 0x00, 0x01, 0x69, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, + 0x02, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x0f, 0x0d, 0x0c, 0x18, 0x17, 0x14, 0x12, 0x0c, 0x1b, 0x0d, 0x1b, 0x24, 0x22, + 0x06, 0x0d, 0x18, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x03, 0x22, 0x26, + 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x4e, 0x1e, 0x16, 0x14, 0x1f, 0x1f, + 0x14, 0x16, 0x1e, 0x38, 0x19, 0x26, 0x0e, 0x0f, 0x20, 0x13, 0x20, 0x2a, 0x58, 0x48, 0x02, 0xa9, 0x1d, 0x1b, 0x1b, + 0x1d, 0x1c, 0x1c, 0x1c, 0xfc, 0x83, 0x07, 0x05, 0x47, 0x04, 0x06, 0x23, 0x31, 0x02, 0x6b, 0xfd, 0x98, 0x4b, 0x55, + 0x00, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x02, 0x0d, 0x02, 0xf8, 0x00, 0x13, 0x00, 0x47, 0x40, 0x09, 0x0f, 0x0e, + 0x0b, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x11, 0x00, 0x03, 0x03, 0x6c, 0x4d, + 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x03, 0x03, 0x01, + 0x5f, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, + 0x59, 0xb6, 0x11, 0x13, 0x12, 0x19, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, 0x37, + 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x15, 0x23, 0x11, 0x33, 0xac, 0x03, 0x01, 0x04, 0x06, 0x18, 0x19, 0x09, 0xab, + 0x67, 0xd9, 0xe8, 0x6a, 0xba, 0x3d, 0x57, 0x57, 0x01, 0x6b, 0x10, 0x34, 0x13, 0x08, 0x1e, 0x1f, 0x0a, 0xb5, 0xe5, + 0xfe, 0xcd, 0xfa, 0x35, 0xc5, 0x02, 0xf8, 0x00, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x00, 0xad, 0x02, 0xf8, 0x00, + 0x03, 0x00, 0x28, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0b, 0x00, 0x01, 0x01, 0x6c, 0x4d, 0x00, 0x00, 0x00, 0x6b, + 0x00, 0x4e, 0x1b, 0x40, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x59, 0xb4, 0x11, + 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x33, 0x23, 0x11, 0x33, 0xad, 0x58, 0x58, 0x02, 0xf8, 0x00, 0x00, 0x01, 0x00, 0x55, + 0x00, 0x00, 0x03, 0x56, 0x02, 0x22, 0x00, 0x21, 0x00, 0x5d, 0xb6, 0x1e, 0x18, 0x02, 0x01, 0x02, 0x01, 0x4c, 0x4b, + 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x04, 0x01, 0x02, 0x02, 0x00, 0x61, 0x07, 0x06, 0x08, 0x03, 0x00, 0x00, 0x73, + 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x1a, 0x00, 0x06, 0x06, 0x6d, 0x4d, 0x04, 0x01, + 0x02, 0x02, 0x00, 0x61, 0x07, 0x08, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, + 0x59, 0x40, 0x17, 0x01, 0x00, 0x1d, 0x1b, 0x17, 0x16, 0x15, 0x14, 0x11, 0x0f, 0x0d, 0x0c, 0x09, 0x07, 0x05, 0x04, + 0x00, 0x21, 0x01, 0x21, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, + 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x33, 0x32, + 0x17, 0x33, 0x36, 0x36, 0x02, 0xa1, 0x5b, 0x5a, 0x57, 0x6d, 0x4e, 0x43, 0x57, 0x6e, 0x51, 0x3e, 0x58, 0x47, 0x0d, + 0x05, 0x19, 0x55, 0x30, 0x7e, 0x26, 0x05, 0x1b, 0x5d, 0x02, 0x22, 0x5d, 0x68, 0xfe, 0xa3, 0x01, 0x59, 0x7f, 0x5a, + 0x56, 0xfe, 0xd8, 0x01, 0x59, 0x7f, 0x64, 0x5e, 0xfe, 0xea, 0x02, 0x18, 0x49, 0x2a, 0x29, 0x5a, 0x2e, 0x2c, 0x00, + 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x02, 0x19, 0x02, 0x22, 0x00, 0x13, 0x00, 0x50, 0xb5, 0x10, 0x01, 0x01, 0x02, + 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x00, 0x02, 0x02, 0x00, 0x61, 0x04, 0x05, 0x02, 0x00, 0x00, + 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x02, + 0x02, 0x00, 0x61, 0x05, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x11, + 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x09, 0x07, 0x05, 0x04, 0x00, 0x13, 0x01, 0x13, 0x06, 0x0d, 0x16, 0x2b, 0x01, + 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, + 0x01, 0x57, 0x60, 0x62, 0x57, 0x78, 0x59, 0x44, 0x58, 0x47, 0x0d, 0x05, 0x1a, 0x5c, 0x02, 0x22, 0x5d, 0x68, 0xfe, + 0xa3, 0x01, 0x57, 0x81, 0x64, 0x5e, 0xfe, 0xea, 0x02, 0x18, 0x49, 0x2a, 0x29, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, + 0x02, 0x27, 0x02, 0x22, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x25, 0x25, 0x22, 0x04, + 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, + 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x27, 0x87, 0x73, 0x47, 0x6f, 0x40, 0x86, 0x73, + 0x49, 0x6f, 0x3f, 0xfe, 0x6b, 0x4b, 0x52, 0x51, 0x4c, 0x4c, 0x52, 0x52, 0x4a, 0x01, 0x0d, 0x85, 0x92, 0x41, 0x7d, + 0x59, 0x85, 0x90, 0x41, 0x7b, 0x59, 0x5f, 0x6f, 0x6f, 0x5f, 0x5f, 0x6c, 0x6c, 0x00, 0x02, 0x00, 0x55, 0xff, 0x10, + 0x02, 0x30, 0x02, 0x22, 0x00, 0x15, 0x00, 0x23, 0x00, 0x6b, 0xb6, 0x12, 0x09, 0x02, 0x05, 0x04, 0x01, 0x4c, 0x4b, + 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x73, 0x4d, + 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x21, + 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, + 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, + 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x23, 0x17, 0x23, 0x11, 0x10, 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, + 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x16, 0x16, 0x15, 0x15, 0x23, + 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x17, 0x22, 0x06, 0x07, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, + 0x26, 0x01, 0x54, 0x63, 0x79, 0x79, 0x64, 0x3e, 0x51, 0x17, 0x06, 0x02, 0x04, 0x58, 0x48, 0x0c, 0x04, 0x18, 0x4e, + 0x31, 0x52, 0x43, 0x02, 0x41, 0x58, 0x31, 0x3f, 0x1f, 0x47, 0x02, 0x22, 0x8a, 0x8b, 0x89, 0x8e, 0x2f, 0x1f, 0x11, + 0x34, 0x13, 0xdc, 0x03, 0x08, 0x49, 0x23, 0x30, 0x4a, 0x5c, 0x5e, 0x11, 0x63, 0x6b, 0x36, 0x5d, 0x3c, 0x5c, 0x6e, + 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0x10, 0x02, 0x12, 0x02, 0x22, 0x00, 0x15, 0x00, 0x22, 0x00, 0x61, 0xb6, 0x10, + 0x03, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, + 0x01, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, + 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, + 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, + 0x59, 0x40, 0x0f, 0x17, 0x16, 0x1e, 0x1c, 0x16, 0x22, 0x17, 0x22, 0x11, 0x14, 0x24, 0x26, 0x07, 0x0d, 0x1a, 0x2b, + 0x05, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, + 0x33, 0x11, 0x23, 0x03, 0x32, 0x36, 0x37, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x01, 0xba, 0x02, + 0x03, 0x06, 0x17, 0x51, 0x40, 0x61, 0x79, 0x7b, 0x62, 0x3f, 0x50, 0x18, 0x04, 0x0d, 0x46, 0x58, 0x98, 0x53, 0x45, + 0x01, 0x44, 0x57, 0x48, 0x46, 0x47, 0x0b, 0x12, 0x30, 0x11, 0x22, 0x30, 0x8b, 0x8a, 0x8a, 0x8d, 0x30, 0x23, 0x49, + 0xfc, 0xf8, 0x01, 0x2f, 0x5b, 0x5e, 0x12, 0x66, 0x69, 0x71, 0x5f, 0x5f, 0x6b, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, + 0x01, 0x8e, 0x02, 0x22, 0x00, 0x13, 0x00, 0x66, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0b, 0x03, 0x01, 0x01, 0x00, + 0x10, 0x04, 0x02, 0x02, 0x01, 0x02, 0x4c, 0x1b, 0x40, 0x0b, 0x03, 0x01, 0x03, 0x00, 0x10, 0x04, 0x02, 0x02, 0x01, + 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x01, 0x01, 0x00, 0x61, 0x03, 0x04, 0x02, 0x00, + 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0f, 0x01, + 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x13, 0x01, 0x13, 0x05, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x17, + 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x01, 0x4f, 0x0f, + 0x23, 0x0d, 0x0b, 0x0d, 0x1f, 0x0e, 0x29, 0x48, 0x2b, 0x58, 0x48, 0x0a, 0x04, 0x1a, 0x52, 0x02, 0x22, 0x03, 0x03, + 0x51, 0x03, 0x04, 0x2d, 0x51, 0x36, 0xfe, 0xe2, 0x02, 0x18, 0x62, 0x2c, 0x40, 0x00, 0x00, 0x01, 0x00, 0x33, 0xff, + 0xf6, 0x01, 0xb2, 0x02, 0x22, 0x00, 0x29, 0x00, 0x2e, 0x40, 0x2b, 0x1b, 0x01, 0x03, 0x02, 0x1c, 0x07, 0x02, 0x01, + 0x03, 0x06, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, 0x2c, 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, + 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x2e, 0x02, 0x35, + 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, + 0x01, 0xb2, 0x74, 0x62, 0x38, 0x51, 0x1f, 0x20, 0x5b, 0x2f, 0x43, 0x3c, 0x16, 0x39, 0x35, 0x34, 0x4a, 0x28, 0x6f, + 0x5a, 0x31, 0x55, 0x25, 0x1e, 0x22, 0x4a, 0x27, 0x36, 0x39, 0x1a, 0x3d, 0x33, 0x33, 0x48, 0x26, 0x94, 0x4e, 0x50, + 0x12, 0x10, 0x50, 0x10, 0x1b, 0x2b, 0x24, 0x14, 0x20, 0x20, 0x14, 0x14, 0x28, 0x38, 0x2c, 0x44, 0x4a, 0x13, 0x11, + 0x46, 0x0e, 0x14, 0x23, 0x1e, 0x16, 0x1f, 0x1d, 0x14, 0x13, 0x28, 0x39, 0x00, 0x00, 0x01, 0x00, 0x10, 0xff, 0xf6, + 0x01, 0x53, 0x02, 0x93, 0x00, 0x18, 0x00, 0x40, 0x40, 0x3d, 0x0e, 0x01, 0x02, 0x04, 0x03, 0x01, 0x00, 0x02, 0x04, + 0x01, 0x01, 0x00, 0x03, 0x4c, 0x00, 0x03, 0x04, 0x03, 0x85, 0x05, 0x01, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, 0x04, + 0x6d, 0x4d, 0x06, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x01, 0x00, 0x15, 0x14, 0x13, + 0x12, 0x11, 0x10, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x18, 0x01, 0x18, 0x07, 0x0d, 0x16, 0x2b, 0x25, 0x32, 0x36, 0x37, + 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x11, 0x23, 0x35, 0x37, 0x37, 0x33, 0x15, 0x33, 0x15, 0x23, 0x11, + 0x14, 0x16, 0x01, 0x08, 0x14, 0x2a, 0x0d, 0x0e, 0x34, 0x18, 0x2a, 0x47, 0x2c, 0x4c, 0x4d, 0x23, 0x34, 0x9b, 0x9b, + 0x2f, 0x3e, 0x07, 0x04, 0x43, 0x07, 0x09, 0x1d, 0x48, 0x41, 0x01, 0x38, 0x2a, 0x23, 0x72, 0x7b, 0x44, 0xfe, 0xca, + 0x31, 0x2f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0xff, 0xf6, 0x02, 0x15, 0x02, 0x18, 0x00, 0x13, 0x00, 0x4c, 0xb5, 0x03, + 0x01, 0x03, 0x02, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6d, 0x4d, + 0x00, 0x03, 0x03, 0x00, 0x61, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1b, 0x40, 0x17, 0x05, 0x04, 0x02, 0x02, + 0x02, 0x6d, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, + 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x13, 0x22, 0x13, 0x24, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x01, 0x11, + 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x33, 0x32, 0x36, 0x35, 0x11, 0x02, + 0x15, 0x48, 0x0d, 0x04, 0x1a, 0x5c, 0x34, 0x61, 0x62, 0x59, 0x77, 0x59, 0x45, 0x02, 0x18, 0xfd, 0xe8, 0x47, 0x2a, + 0x27, 0x5d, 0x66, 0x01, 0x5f, 0xfe, 0xa7, 0x80, 0x64, 0x5e, 0x01, 0x17, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xfc, 0x02, 0x18, 0x00, 0x0f, 0x00, 0x21, 0x40, 0x1e, 0x07, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, + 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x1b, 0x11, 0x04, 0x0d, + 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x17, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x03, 0xcb, 0xcb, 0x5e, + 0x72, 0x08, 0x12, 0x0e, 0x03, 0x04, 0x04, 0x0f, 0x13, 0x07, 0x72, 0x5e, 0xcc, 0x02, 0x18, 0xfe, 0xc4, 0x16, 0x36, + 0x31, 0x11, 0x11, 0x32, 0x36, 0x15, 0x01, 0x3c, 0xfd, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x01, 0x03, 0x07, + 0x02, 0x19, 0x00, 0x22, 0x00, 0x21, 0x40, 0x1e, 0x1a, 0x0f, 0x03, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x02, 0x02, + 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x19, 0x1a, 0x11, 0x18, 0x05, 0x0d, 0x1b, + 0x2b, 0x01, 0x26, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x03, 0x23, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, 0x3e, + 0x02, 0x37, 0x13, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0x23, 0x01, 0xaf, 0x0d, + 0x13, 0x05, 0x04, 0x04, 0x12, 0x0e, 0x60, 0x64, 0x93, 0x5b, 0x4a, 0x0b, 0x14, 0x04, 0x04, 0x04, 0x0b, 0x0e, 0x07, + 0x5f, 0x60, 0x5c, 0x0b, 0x15, 0x04, 0x04, 0x03, 0x15, 0x0c, 0x4b, 0x5a, 0x95, 0x67, 0x01, 0x2f, 0x29, 0x4f, 0x16, + 0x16, 0x4f, 0x2a, 0xfe, 0xd3, 0x02, 0x18, 0xfe, 0xe2, 0x2b, 0x58, 0x1d, 0x11, 0x32, 0x37, 0x16, 0x01, 0x2e, 0xfe, + 0xd2, 0x22, 0x50, 0x1d, 0x19, 0x58, 0x2e, 0x01, 0x1e, 0xfd, 0xe8, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x01, 0xff, + 0x02, 0x18, 0x00, 0x0b, 0x00, 0x1f, 0x40, 0x1c, 0x09, 0x06, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, + 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x12, 0x12, 0x12, 0x11, 0x04, 0x0d, 0x1a, 0x2b, 0x13, + 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x23, 0xd4, 0xb9, 0x64, 0x8a, 0x89, 0x63, 0xb9, 0xc3, + 0x64, 0x92, 0x94, 0x63, 0x01, 0x12, 0x01, 0x06, 0xca, 0xca, 0xfe, 0xfa, 0xfe, 0xee, 0xd6, 0xd6, 0x00, 0x00, 0x01, + 0x00, 0x01, 0xff, 0x10, 0x01, 0xfe, 0x02, 0x18, 0x00, 0x1a, 0x00, 0x27, 0x40, 0x24, 0x1a, 0x13, 0x05, 0x03, 0x03, + 0x00, 0x12, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, + 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x25, 0x23, 0x19, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x33, 0x13, 0x16, 0x16, 0x17, + 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x37, 0x01, 0x5e, 0x74, 0x0f, 0x18, 0x06, 0x04, 0x06, 0x1a, 0x0e, 0x6d, 0x5f, 0xe7, 0x1c, 0x59, 0x4e, 0x18, + 0x24, 0x0d, 0x0b, 0x1f, 0x11, 0x2e, 0x39, 0x10, 0x1c, 0x02, 0x18, 0xfe, 0xcf, 0x28, 0x49, 0x21, 0x19, 0x51, 0x29, + 0x01, 0x30, 0xfd, 0x9e, 0x4c, 0x5a, 0x05, 0x03, 0x46, 0x02, 0x04, 0x34, 0x2b, 0x47, 0x00, 0x01, 0x00, 0x27, 0x00, + 0x00, 0x01, 0xaf, 0x02, 0x18, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, + 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, + 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, + 0x15, 0x01, 0x21, 0x01, 0xaf, 0xfe, 0x78, 0x01, 0x20, 0xfe, 0xf1, 0x01, 0x70, 0xfe, 0xe4, 0x01, 0x23, 0x3a, 0x01, + 0x9a, 0x44, 0x42, 0xfe, 0x6e, 0x00, 0x01, 0x00, 0x1c, 0xff, 0x62, 0x01, 0x5c, 0x02, 0xca, 0x00, 0x1d, 0x00, 0x2c, + 0x40, 0x29, 0x16, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, 0x05, 0x00, + 0x00, 0x05, 0x00, 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, 0x4e, 0x1b, 0x11, 0x15, 0x11, + 0x15, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x05, 0x26, 0x26, 0x35, 0x35, 0x34, 0x26, 0x23, 0x35, 0x36, 0x36, 0x35, 0x35, + 0x34, 0x36, 0x33, 0x15, 0x06, 0x06, 0x15, 0x15, 0x14, 0x07, 0x15, 0x16, 0x15, 0x15, 0x14, 0x16, 0x17, 0x01, 0x5c, + 0x5c, 0x6a, 0x3f, 0x3b, 0x3b, 0x3f, 0x6e, 0x58, 0x34, 0x3b, 0x6d, 0x6d, 0x3a, 0x35, 0x9e, 0x01, 0x4e, 0x50, 0x93, + 0x33, 0x2b, 0x49, 0x01, 0x2a, 0x32, 0x94, 0x50, 0x4e, 0x48, 0x01, 0x2c, 0x31, 0x90, 0x67, 0x13, 0x06, 0x13, 0x67, + 0x93, 0x31, 0x2b, 0x01, 0x00, 0x01, 0x00, 0xef, 0xff, 0x0f, 0x01, 0x38, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x28, 0x4b, + 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x1b, 0x40, + 0x0b, 0x00, 0x00, 0x01, 0x00, 0x85, 0x00, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x59, 0xb4, 0x11, 0x10, 0x02, 0x0d, 0x18, + 0x2b, 0x13, 0x33, 0x11, 0x23, 0xef, 0x49, 0x49, 0x02, 0xf8, 0xfc, 0x17, 0x00, 0x00, 0x01, 0x00, 0x20, 0xff, 0x62, + 0x01, 0x60, 0x02, 0xca, 0x00, 0x1d, 0x00, 0x2c, 0x40, 0x29, 0x06, 0x01, 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, + 0x02, 0x6a, 0x01, 0x4e, 0x15, 0x11, 0x15, 0x11, 0x1b, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x17, 0x36, 0x36, 0x35, 0x35, + 0x34, 0x37, 0x35, 0x26, 0x35, 0x35, 0x34, 0x26, 0x27, 0x35, 0x16, 0x16, 0x15, 0x15, 0x14, 0x16, 0x33, 0x15, 0x06, + 0x06, 0x15, 0x15, 0x14, 0x06, 0x23, 0x20, 0x34, 0x3b, 0x6d, 0x6d, 0x3a, 0x35, 0x5c, 0x6a, 0x3f, 0x3b, 0x3b, 0x3f, + 0x6e, 0x58, 0x56, 0x02, 0x2b, 0x31, 0x91, 0x67, 0x13, 0x06, 0x13, 0x67, 0x92, 0x31, 0x2b, 0x01, 0x48, 0x01, 0x4e, + 0x50, 0x92, 0x33, 0x2b, 0x49, 0x01, 0x2a, 0x32, 0x95, 0x4f, 0x4f, 0x00, 0x00, 0x01, 0x00, 0x32, 0x01, 0x1f, 0x02, + 0x09, 0x01, 0xa2, 0x00, 0x17, 0x00, 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, 0x02, 0x01, 0x13, 0x01, + 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, 0x00, 0x02, 0x00, 0x03, 0x02, 0x59, 0x00, + 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, 0x03, 0x51, 0x24, 0x24, + 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, + 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x01, 0x0d, 0x24, 0x2f, + 0x16, 0x1c, 0x3e, 0x18, 0x30, 0x48, 0x1d, 0x39, 0x2e, 0x24, 0x2f, 0x15, 0x1d, 0x3e, 0x18, 0x31, 0x47, 0x1c, 0x3b, + 0x01, 0x3f, 0x10, 0x0b, 0x22, 0x19, 0x4e, 0x35, 0x0c, 0x14, 0x10, 0x0b, 0x22, 0x19, 0x4d, 0x36, 0x0d, 0x00, 0x01, + 0x00, 0x18, 0x01, 0xa0, 0x01, 0x33, 0x03, 0x55, 0x00, 0x19, 0x00, 0x30, 0x40, 0x2d, 0x0e, 0x01, 0x01, 0x02, 0x0d, + 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x03, 0x02, 0x01, 0x69, 0x00, 0x03, + 0x00, 0x00, 0x03, 0x57, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x00, 0x4f, 0x16, 0x25, 0x28, 0x10, 0x04, + 0x0c, 0x1a, 0x2b, 0x01, 0x21, 0x35, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, 0x33, 0x01, 0x32, 0xfe, 0xe6, 0x73, 0x29, 0x29, 0x0f, 0x25, 0x1e, + 0x1e, 0x31, 0x1a, 0x23, 0x1d, 0x45, 0x2b, 0x40, 0x49, 0x3b, 0x38, 0x51, 0xc3, 0x01, 0xa0, 0x36, 0x70, 0x27, 0x31, + 0x27, 0x16, 0x20, 0x20, 0x17, 0x14, 0x2e, 0x19, 0x1e, 0x3f, 0x37, 0x31, 0x4e, 0x35, 0x4d, 0x00, 0x00, 0x01, 0x00, + 0x11, 0x01, 0x98, 0x01, 0x41, 0x03, 0x55, 0x00, 0x28, 0x00, 0x4d, 0x40, 0x4a, 0x26, 0x01, 0x05, 0x00, 0x25, 0x01, + 0x04, 0x05, 0x06, 0x01, 0x03, 0x04, 0x11, 0x01, 0x02, 0x03, 0x10, 0x01, 0x01, 0x02, 0x05, 0x4c, 0x06, 0x01, 0x00, + 0x00, 0x05, 0x04, 0x00, 0x05, 0x69, 0x00, 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, + 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x01, 0x00, 0x23, 0x21, 0x1d, 0x1b, 0x1a, 0x18, + 0x14, 0x12, 0x0e, 0x0c, 0x00, 0x28, 0x01, 0x28, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, + 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, + 0x23, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0xa5, 0x47, 0x48, 0x2b, + 0x1e, 0x27, 0x2f, 0x54, 0x59, 0x25, 0x40, 0x1e, 0x46, 0x3e, 0x34, 0x30, 0x3a, 0x34, 0x39, 0x39, 0x32, 0x2f, 0x29, + 0x1d, 0x1f, 0x35, 0x1b, 0x24, 0x1f, 0x45, 0x03, 0x55, 0x3e, 0x30, 0x28, 0x34, 0x0a, 0x03, 0x07, 0x33, 0x29, 0x3a, + 0x49, 0x0d, 0x0f, 0x3f, 0x22, 0x29, 0x23, 0x24, 0x21, 0x37, 0x27, 0x1f, 0x20, 0x1d, 0x15, 0x11, 0x2e, 0x17, 0x1a, + 0x00, 0x00, 0x01, 0x00, 0x25, 0x01, 0xa0, 0x00, 0xf0, 0x03, 0x4c, 0x00, 0x0c, 0x00, 0x27, 0x40, 0x24, 0x0b, 0x0a, + 0x06, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x00, 0x00, 0x01, 0x57, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, + 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x11, 0x03, 0x0c, 0x17, 0x2b, 0x13, 0x11, 0x23, + 0x11, 0x34, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0xf0, 0x47, 0x03, 0x01, 0x0a, 0x18, 0x0d, 0x36, 0x23, + 0x82, 0x03, 0x4c, 0xfe, 0x54, 0x01, 0x14, 0x1a, 0x2a, 0x15, 0x09, 0x15, 0x09, 0x27, 0x31, 0x5c, 0x00, 0x00, 0x01, + 0xff, 0x41, 0x00, 0x00, 0x01, 0x40, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, + 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x01, + 0x01, 0x23, 0x01, 0x01, 0x40, 0xfe, 0x4c, 0x4b, 0x01, 0xb4, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0x00, 0x02, 0x00, + 0x0a, 0x01, 0xa0, 0x01, 0x55, 0x03, 0x4f, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x30, 0x40, 0x2d, 0x0e, 0x01, 0x04, 0x03, + 0x06, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x00, 0x03, 0x04, 0x01, 0x03, 0x57, 0x05, 0x01, 0x04, 0x02, 0x01, 0x00, 0x01, + 0x04, 0x00, 0x67, 0x00, 0x03, 0x03, 0x01, 0x5f, 0x00, 0x01, 0x03, 0x01, 0x4f, 0x18, 0x11, 0x12, 0x11, 0x11, 0x10, + 0x06, 0x0c, 0x1c, 0x2b, 0x01, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x13, 0x33, 0x11, 0x33, 0x27, 0x34, 0x36, 0x37, + 0x06, 0x06, 0x07, 0x07, 0x33, 0x01, 0x55, 0x3d, 0x4b, 0xc3, 0xc5, 0x49, 0x3d, 0x88, 0x02, 0x01, 0x05, 0x20, 0x0b, + 0x50, 0x7d, 0x02, 0x00, 0x60, 0x60, 0x34, 0x01, 0x1b, 0xfe, 0xed, 0x5d, 0x15, 0x38, 0x18, 0x0b, 0x31, 0x11, 0x75, + 0x00, 0x00, 0x01, 0x00, 0x1e, 0x01, 0x97, 0x01, 0x40, 0x03, 0x4c, 0x00, 0x1e, 0x00, 0x42, 0x40, 0x3f, 0x1d, 0x03, + 0x02, 0x04, 0x01, 0x1c, 0x10, 0x02, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x03, 0x4c, 0x06, 0x01, 0x05, 0x00, 0x00, + 0x01, 0x05, 0x00, 0x67, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x69, 0x00, 0x03, 0x02, 0x02, 0x03, 0x59, 0x00, + 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x03, 0x02, 0x51, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1e, 0x24, 0x25, 0x24, 0x23, + 0x11, 0x07, 0x0c, 0x1b, 0x2b, 0x01, 0x15, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, + 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x37, 0x01, 0x2b, + 0xb9, 0x09, 0x0c, 0x1d, 0x11, 0x43, 0x5a, 0x54, 0x52, 0x20, 0x46, 0x16, 0x1b, 0x45, 0x1a, 0x2d, 0x35, 0x35, 0x30, + 0x1a, 0x25, 0x0f, 0x1f, 0x10, 0x03, 0x4c, 0x37, 0x6d, 0x02, 0x04, 0x44, 0x40, 0x46, 0x4d, 0x0d, 0x0d, 0x43, 0x10, + 0x13, 0x28, 0x2b, 0x26, 0x2a, 0x08, 0x04, 0x14, 0xd0, 0x00, 0x01, 0x00, 0x1c, 0x01, 0xa0, 0x01, 0x43, 0x03, 0x4c, + 0x00, 0x06, 0x00, 0x2a, 0x40, 0x27, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, + 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x06, 0x11, 0x11, 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, 0x23, 0x35, 0x21, 0x15, 0x03, 0x4f, 0xaa, 0xdd, 0x01, + 0x27, 0xaa, 0x01, 0xa0, 0x01, 0x70, 0x3c, 0x31, 0xfe, 0x85, 0x00, 0x00, 0x03, 0x00, 0x19, 0x01, 0x98, 0x01, 0x45, + 0x03, 0x54, 0x00, 0x18, 0x00, 0x24, 0x00, 0x31, 0x00, 0x38, 0x40, 0x35, 0x1f, 0x12, 0x06, 0x03, 0x03, 0x02, 0x01, + 0x4c, 0x04, 0x01, 0x00, 0x05, 0x01, 0x02, 0x03, 0x00, 0x02, 0x69, 0x00, 0x03, 0x01, 0x01, 0x03, 0x59, 0x00, 0x03, + 0x03, 0x01, 0x61, 0x00, 0x01, 0x03, 0x01, 0x51, 0x1a, 0x19, 0x01, 0x00, 0x2c, 0x2a, 0x19, 0x24, 0x1a, 0x24, 0x0d, + 0x0b, 0x00, 0x18, 0x01, 0x18, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, + 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, + 0x14, 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x27, 0xb0, 0x37, 0x50, 0x2a, 0x1e, 0x27, 0x2f, 0x53, 0x42, 0x49, 0x4e, 0x2d, 0x20, 0x1f, 0x21, 0x26, 0x3f, + 0x24, 0x20, 0x24, 0x28, 0x1e, 0x1d, 0x25, 0x24, 0x2f, 0x21, 0x22, 0x28, 0x29, 0x2a, 0x28, 0x2d, 0x26, 0x03, 0x54, + 0x35, 0x37, 0x25, 0x30, 0x10, 0x10, 0x37, 0x29, 0x38, 0x43, 0x40, 0x38, 0x29, 0x36, 0x11, 0x14, 0x2b, 0x26, 0x24, + 0x31, 0x1a, 0x37, 0x1d, 0x1a, 0x1a, 0x22, 0x0c, 0x0b, 0x21, 0x1c, 0x1a, 0x1d, 0xb8, 0x10, 0x28, 0x1d, 0x1c, 0x24, + 0x24, 0x1c, 0x1d, 0x26, 0x0d, 0x00, 0x00, 0x02, 0x00, 0x13, 0x01, 0x98, 0x01, 0x4a, 0x03, 0x54, 0x00, 0x0b, 0x00, + 0x15, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, + 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x0d, 0x0c, 0x01, 0x00, 0x11, 0x0f, + 0x0c, 0x15, 0x0d, 0x15, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x27, 0x32, 0x35, 0x34, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0xae, 0x4d, + 0x4e, 0x4a, 0x51, 0x4d, 0x4f, 0x49, 0x53, 0x54, 0x54, 0x2b, 0x27, 0x27, 0x01, 0x98, 0x73, 0x6c, 0x6a, 0x73, 0x72, + 0x6b, 0x6a, 0x75, 0x3f, 0xa0, 0x9f, 0x4f, 0x51, 0x4f, 0x50, 0x00, 0x02, 0x00, 0x14, 0x01, 0x98, 0x01, 0x4c, 0x03, + 0x54, 0x00, 0x1c, 0x00, 0x29, 0x00, 0x4a, 0x40, 0x47, 0x03, 0x01, 0x01, 0x00, 0x04, 0x01, 0x02, 0x01, 0x0b, 0x01, + 0x04, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 0x69, 0x00, 0x02, 0x07, 0x01, 0x04, 0x05, + 0x02, 0x04, 0x69, 0x00, 0x05, 0x03, 0x03, 0x05, 0x59, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x05, 0x03, 0x51, + 0x1e, 0x1d, 0x01, 0x00, 0x25, 0x23, 0x1d, 0x29, 0x1e, 0x29, 0x16, 0x14, 0x10, 0x0e, 0x08, 0x06, 0x00, 0x1c, 0x01, + 0x1c, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x17, 0x15, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x33, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x17, 0x22, 0x06, 0x15, 0x14, + 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xec, 0x0e, 0x23, 0x0b, 0x0b, 0x22, 0x13, 0x36, 0x3e, 0x1b, 0x03, + 0x04, 0x0e, 0x36, 0x29, 0x3b, 0x4a, 0x52, 0x45, 0x44, 0x5d, 0x12, 0x2f, 0x54, 0x0d, 0x2b, 0x32, 0x14, 0x28, 0x1e, + 0x26, 0x2f, 0x29, 0x03, 0x54, 0x04, 0x03, 0x3b, 0x04, 0x05, 0x29, 0x46, 0x2a, 0x15, 0x1d, 0x46, 0x40, 0x46, 0x50, + 0x5f, 0x61, 0x2f, 0x5a, 0x48, 0x2b, 0xd7, 0x2d, 0x1a, 0x18, 0x2f, 0x1e, 0x2d, 0x2e, 0x26, 0x2b, 0x00, 0x02, 0x00, + 0x11, 0x01, 0x98, 0x01, 0x49, 0x03, 0x56, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x4a, 0x40, 0x47, 0x12, 0x01, 0x03, 0x05, + 0x0b, 0x01, 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x07, 0x01, 0x04, 0x05, 0x00, 0x04, + 0x69, 0x00, 0x05, 0x00, 0x03, 0x02, 0x05, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, + 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, 0x27, 0x1d, 0x27, 0x17, 0x15, 0x0f, + 0x0d, 0x09, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x23, + 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, + 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xa8, 0x44, 0x5d, 0x12, 0x2d, 0x54, 0x42, + 0x25, 0x1a, 0x0b, 0x20, 0x18, 0x37, 0x3c, 0x1b, 0x02, 0x05, 0x0d, 0x33, 0x28, 0x40, 0x4a, 0x52, 0x45, 0x24, 0x2f, + 0x27, 0x2a, 0x2b, 0x33, 0x2d, 0x03, 0x56, 0x5c, 0x63, 0x2f, 0x5b, 0x49, 0x2c, 0x07, 0x3c, 0x04, 0x06, 0x2c, 0x47, + 0x28, 0x13, 0x1f, 0x48, 0x40, 0x41, 0x53, 0x39, 0x2c, 0x2c, 0x26, 0x2e, 0x2d, 0x1a, 0x2a, 0x3b, 0xff, 0xff, 0x00, + 0x0f, 0x00, 0x00, 0x02, 0xdb, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x47, 0x01, 0x58, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x0d, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x4a, 0x01, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x05, 0x02, 0xfd, 0x00, 0x26, + 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x03, + 0x65, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x58, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x4a, 0x02, 0xb0, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x5d, 0x02, 0xfd, 0x00, 0x26, 0x00, + 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x58, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x02, 0xb0, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x13, 0xff, 0xf8, 0x01, 0x4a, 0x01, 0xb4, 0x03, 0x07, 0x00, 0x68, 0x00, 0x00, 0xfe, 0x60, 0x00, + 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x25, 0x00, 0x00, 0x00, 0xf0, + 0x01, 0xac, 0x03, 0x07, 0x00, 0x62, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, + 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x18, 0x00, 0x00, 0x01, 0x33, 0x01, 0xb5, 0x03, 0x07, 0x00, 0x60, 0x00, 0x00, + 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0xff, + 0xf8, 0x01, 0x41, 0x01, 0xb5, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, + 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x55, 0x01, 0xaf, 0x03, 0x07, 0x00, + 0x64, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x1e, 0xff, 0xf7, 0x01, 0x40, 0x01, 0xac, 0x03, 0x07, 0x00, 0x65, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, + 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x14, 0xff, 0xf8, 0x01, 0x4c, 0x01, 0xb4, + 0x03, 0x07, 0x00, 0x69, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, + 0x00, 0xff, 0xff, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x43, 0x01, 0xac, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xfe, 0x60, + 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x19, 0xff, 0xf8, 0x01, + 0x45, 0x01, 0xb4, 0x03, 0x07, 0x00, 0x67, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x60, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0xff, 0xf8, 0x01, 0x49, 0x01, 0xb6, 0x03, 0x07, 0x00, 0x6a, 0x00, + 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x13, + 0x01, 0x16, 0x01, 0x4a, 0x02, 0xd2, 0x03, 0x07, 0x00, 0x68, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, + 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x25, 0x01, 0x1e, 0x00, 0xf0, 0x02, 0xca, 0x03, 0x07, + 0x00, 0x62, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, + 0xff, 0x00, 0x18, 0x01, 0x1e, 0x01, 0x33, 0x02, 0xd3, 0x03, 0x07, 0x00, 0x60, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, + 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0x01, 0x16, 0x01, 0x41, 0x02, + 0xd3, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x01, 0x1e, 0x01, 0x55, 0x02, 0xcd, 0x03, 0x07, 0x00, 0x64, 0x00, 0x00, 0xff, + 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x01, 0x15, + 0x01, 0x40, 0x02, 0xca, 0x03, 0x07, 0x00, 0x65, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, + 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x14, 0x01, 0x16, 0x01, 0x4c, 0x02, 0xd2, 0x03, 0x07, 0x00, 0x69, + 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, + 0x1c, 0x01, 0x1e, 0x01, 0x43, 0x02, 0xca, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, + 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x19, 0x01, 0x16, 0x01, 0x45, 0x02, 0xd2, 0x03, + 0x07, 0x00, 0x67, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0x00, 0x11, 0x01, 0x16, 0x01, 0x49, 0x02, 0xd4, 0x03, 0x07, 0x00, 0x6a, 0x00, 0x00, 0xff, 0x7e, 0x00, + 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, + 0x01, 0x04, 0x00, 0x18, 0x00, 0x66, 0x00, 0x06, 0x00, 0x02, 0x00, 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, + 0x89, 0x0e, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x54, 0x00, 0xa8, + 0x01, 0x27, 0x01, 0xbc, 0x02, 0x4b, 0x02, 0x66, 0x02, 0x8a, 0x02, 0xae, 0x02, 0xe6, 0x03, 0x0e, 0x03, 0x2e, 0x03, + 0x49, 0x03, 0x68, 0x03, 0x84, 0x03, 0xbd, 0x03, 0xe4, 0x04, 0x25, 0x04, 0x83, 0x04, 0xbe, 0x05, 0x11, 0x05, 0x71, + 0x05, 0x96, 0x06, 0x02, 0x06, 0x63, 0x06, 0x98, 0x06, 0xcb, 0x06, 0xe1, 0x07, 0x0c, 0x07, 0x22, 0x07, 0x7b, 0x08, + 0x25, 0x08, 0x5f, 0x08, 0xb6, 0x08, 0xfc, 0x09, 0x2b, 0x09, 0x57, 0x09, 0x7c, 0x09, 0xcc, 0x09, 0xf4, 0x0a, 0x1c, + 0x0a, 0x4d, 0x0a, 0x7a, 0x0a, 0x98, 0x0a, 0xd1, 0x0b, 0x01, 0x0b, 0x3d, 0x0b, 0x79, 0x0b, 0xc2, 0x0c, 0x08, 0x0c, + 0x5d, 0x0c, 0x7b, 0x0c, 0xa8, 0x0c, 0xd5, 0x0d, 0x22, 0x0d, 0x4d, 0x0d, 0x71, 0x0d, 0x9c, 0x0d, 0xbb, 0x0d, 0xd7, + 0x0d, 0xf6, 0x0e, 0x1d, 0x0e, 0x3a, 0x0e, 0x64, 0x0e, 0xdd, 0x0f, 0x55, 0x0f, 0x9b, 0x10, 0x19, 0x10, 0x6d, 0x10, + 0xc1, 0x11, 0x40, 0x11, 0x87, 0x11, 0xea, 0x12, 0x69, 0x12, 0xaf, 0x12, 0xcf, 0x13, 0x30, 0x13, 0x79, 0x13, 0xb2, + 0x14, 0x1e, 0x14, 0x83, 0x14, 0xd9, 0x15, 0x2e, 0x15, 0x75, 0x15, 0xbc, 0x15, 0xeb, 0x16, 0x37, 0x16, 0x60, 0x16, + 0xa1, 0x16, 0xcc, 0x17, 0x0e, 0x17, 0x2f, 0x17, 0x71, 0x17, 0xb6, 0x17, 0xf8, 0x18, 0x59, 0x18, 0x87, 0x18, 0xa3, + 0x18, 0xde, 0x19, 0x2e, 0x19, 0x55, 0x19, 0xbb, 0x19, 0xf6, 0x1a, 0x58, 0x1a, 0xb7, 0x1a, 0xc3, 0x1a, 0xcf, 0x1a, + 0xdb, 0x1a, 0xeb, 0x1a, 0xfb, 0x1b, 0x0a, 0x1b, 0x19, 0x1b, 0x28, 0x1b, 0x37, 0x1b, 0x46, 0x1b, 0x55, 0x1b, 0x64, + 0x1b, 0x73, 0x1b, 0x82, 0x1b, 0x91, 0x1b, 0xa0, 0x1b, 0xaf, 0x1b, 0xbe, 0x1b, 0xcd, 0x1b, 0xdc, 0x1b, 0xeb, 0x1b, + 0xfa, 0x1c, 0x09, 0x1c, 0x18, 0x1c, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, 0xb1, 0xf9, + 0xad, 0x18, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xd3, 0xe7, 0x00, + 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc0, 0xb7, 0xfd, 0x93, 0xfe, 0x7b, 0x0a, 0xf0, 0x04, 0x2b, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x58, 0x00, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x01, 0x0d, 0x00, + 0x48, 0x01, 0x98, 0x00, 0x41, 0x02, 0x86, 0x00, 0x19, 0x02, 0x3c, 0x00, 0x3e, 0x03, 0x3f, 0x00, 0x31, 0x02, 0xdc, + 0x00, 0x35, 0x00, 0xe1, 0x00, 0x41, 0x01, 0x2c, 0x00, 0x28, 0x01, 0x2c, 0x00, 0x1e, 0x02, 0x27, 0x00, 0x29, 0x02, + 0x3c, 0x00, 0x32, 0x01, 0x0c, 0x00, 0x29, 0x01, 0x42, 0x00, 0x28, 0x01, 0x0c, 0x00, 0x48, 0x01, 0x74, 0x00, 0x0a, + 0x02, 0x3c, 0x00, 0x31, 0x02, 0x3c, 0x00, 0x59, 0x02, 0x3c, 0x00, 0x30, 0x02, 0x3c, 0x00, 0x2d, 0x02, 0x3c, 0x00, + 0x15, 0x02, 0x3c, 0x00, 0x3f, 0x02, 0x3c, 0x00, 0x37, 0x02, 0x3c, 0x00, 0x2c, 0x02, 0x3c, 0x00, 0x31, 0x02, 0x3c, + 0x00, 0x32, 0x01, 0x0c, 0x00, 0x48, 0x01, 0x0c, 0x00, 0x1f, 0x02, 0x3c, 0x00, 0x32, 0x02, 0x3c, 0x00, 0x38, 0x02, + 0x3c, 0x00, 0x32, 0x01, 0xb2, 0x00, 0x0c, 0x03, 0x83, 0x00, 0x3a, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x8a, 0x00, 0x61, + 0x02, 0x78, 0x00, 0x3d, 0x02, 0xda, 0x00, 0x61, 0x02, 0x2c, 0x00, 0x61, 0x02, 0x07, 0x00, 0x61, 0x02, 0xd8, 0x00, + 0x3d, 0x02, 0xe5, 0x00, 0x61, 0x01, 0x53, 0x00, 0x28, 0x01, 0x11, 0xff, 0xb2, 0x02, 0x6b, 0x00, 0x61, 0x02, 0x0c, + 0x00, 0x61, 0x03, 0x8b, 0x00, 0x61, 0x02, 0xf8, 0x00, 0x61, 0x03, 0x0d, 0x00, 0x3d, 0x02, 0x5d, 0x00, 0x61, 0x03, + 0x0d, 0x00, 0x3d, 0x02, 0x6e, 0x00, 0x61, 0x02, 0x25, 0x00, 0x33, 0x02, 0x2c, 0x00, 0x0a, 0x02, 0xdb, 0x00, 0x5a, + 0x02, 0x58, 0x00, 0x00, 0x03, 0xa2, 0x00, 0x0c, 0x02, 0x4a, 0x00, 0x04, 0x02, 0x36, 0x00, 0x00, 0x02, 0x3c, 0x00, + 0x26, 0x01, 0x49, 0x00, 0x50, 0x01, 0x74, 0x00, 0x0a, 0x01, 0x49, 0x00, 0x19, 0x02, 0x3c, 0x00, 0x26, 0x01, 0xbc, + 0xff, 0xfe, 0x01, 0x19, 0x00, 0x28, 0x02, 0x31, 0x00, 0x2e, 0x02, 0x67, 0x00, 0x55, 0x01, 0xe0, 0x00, 0x37, 0x02, + 0x67, 0x00, 0x37, 0x02, 0x34, 0x00, 0x37, 0x01, 0x58, 0x00, 0x0f, 0x02, 0x67, 0x00, 0x37, 0x02, 0x6a, 0x00, 0x55, + 0x01, 0x02, 0x00, 0x4e, 0x01, 0x02, 0xff, 0xc9, 0x02, 0x16, 0x00, 0x55, 0x01, 0x02, 0x00, 0x55, 0x03, 0xa7, 0x00, + 0x55, 0x02, 0x6a, 0x00, 0x55, 0x02, 0x5d, 0x00, 0x37, 0x02, 0x67, 0x00, 0x55, 0x02, 0x67, 0x00, 0x37, 0x01, 0x9d, + 0x00, 0x55, 0x01, 0xdf, 0x00, 0x33, 0x01, 0x69, 0x00, 0x10, 0x02, 0x6a, 0x00, 0x4f, 0x01, 0xfc, 0x00, 0x00, 0x03, + 0x12, 0x00, 0x0b, 0x02, 0x11, 0x00, 0x12, 0x01, 0xfe, 0x00, 0x01, 0x01, 0xd6, 0x00, 0x27, 0x01, 0x7c, 0x00, 0x1c, + 0x02, 0x27, 0x00, 0xef, 0x01, 0x7c, 0x00, 0x20, 0x02, 0x3c, 0x00, 0x32, 0x01, 0x5e, 0x00, 0x18, 0x01, 0x5e, 0x00, + 0x11, 0x01, 0x5e, 0x00, 0x25, 0x00, 0x82, 0xff, 0x41, 0x01, 0x5e, 0x00, 0x0a, 0x01, 0x5e, 0x00, 0x1e, 0x01, 0x5e, + 0x00, 0x1c, 0x01, 0x5e, 0x00, 0x19, 0x01, 0x5e, 0x00, 0x13, 0x01, 0x5e, 0x00, 0x14, 0x01, 0x5e, 0x00, 0x11, 0x02, + 0xb0, 0x00, 0x0f, 0x02, 0x5a, 0x00, 0x0f, 0x02, 0x5a, 0x00, 0x0f, 0x03, 0xb2, 0x00, 0x0f, 0x03, 0xb2, 0x00, 0x0f, + 0x01, 0x5e, 0x00, 0x13, 0x00, 0x25, 0x00, 0x18, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x1c, 0x00, + 0x19, 0x00, 0x11, 0x00, 0x13, 0x00, 0x25, 0x00, 0x18, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x1c, + 0x00, 0x19, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x0b, 0x18, 0xfd, + 0x93, 0xfd, 0x94, 0x0a, 0xf0, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x71, 0x00, 0x04, 0x02, 0x41, 0x01, 0x90, 0x00, 0x05, 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, 0x00, + 0x00, 0x00, 0x4b, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x32, 0x01, 0x42, 0x00, 0x00, 0x02, 0x0b, + 0x05, 0x02, 0x04, 0x05, 0x04, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0xc0, 0x00, 0x20, 0x00, 0x7e, 0x04, 0x2d, 0xfe, 0xdb, + 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x02, 0xca, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, + 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, + 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, 0x21, 0xb0, 0x00, 0x59, 0xb0, 0x00, 0x43, + 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, + 0x02, 0x2c, 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, + 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, 0x14, 0x43, 0x42, 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, + 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, 0x04, 0x50, 0x78, 0xb2, 0x02, 0x02, + 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, + 0x20, 0xb0, 0x02, 0x43, 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, + 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, 0x2c, 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, + 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x1b, 0x20, 0x64, 0x20, + 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, + 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, + 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, 0x38, 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, + 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x20, + 0xb0, 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, + 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, + 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x0c, + 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, + 0xb0, 0x1e, 0x50, 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, + 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, + 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, 0x20, 0x45, 0x20, 0xb0, 0x04, 0x25, + 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, + 0x59, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, + 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, + 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, 0xb0, 0x08, 0x43, 0x20, 0x8a, 0x20, + 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, + 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, + 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, 0x43, 0x2b, 0xb2, 0x00, 0x02, 0x00, 0x43, + 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, + 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, + 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, + 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, 0x0e, 0x00, 0x43, 0x45, 0x42, 0x2a, + 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, + 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, + 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, + 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, + 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, + 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, + 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, + 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, 0x0c, + 0x00, 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, + 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, 0x2c, 0xb0, 0x01, 0x60, 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, + 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, 0xb0, 0x00, 0x52, 0x58, 0x20, 0xb0, + 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, + 0x00, 0x63, 0x8a, 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, + 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x24, 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, + 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x1b, 0x21, 0x59, 0x24, 0xb0, 0x13, + 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, + 0x61, 0x42, 0xb0, 0x11, 0x2b, 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, + 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, + 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x23, 0xb0, 0x01, 0x61, 0x20, + 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, + 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, + 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, + 0x00, 0x13, 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, + 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, + 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, 0x13, 0x00, 0x42, + 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, + 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, + 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, 0x2c, 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, + 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, 0x06, + 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, + 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, + 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x5d, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, + 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, + 0x2e, 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, + 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, + 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, + 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, + 0x01, 0x00, 0x11, 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, + 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, 0x2c, 0xb1, 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, + 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, 0xb0, 0x25, 0x2c, 0xb1, 0x04, 0x20, + 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, + 0x28, 0x2c, 0xb1, 0x07, 0x20, 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, + 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, + 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x01, 0x60, 0xb0, 0x2e, 0x2a, + 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, + 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, + 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, + 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, + 0x23, 0x61, 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, + 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, + 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, + 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, + 0xb0, 0x34, 0x2c, 0x20, 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, + 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, + 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, + 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, + 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, + 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, 0x20, + 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0xb0, 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, + 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb0, 0x02, 0x25, 0x49, 0x8a, + 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, + 0x01, 0x15, 0x14, 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, + 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, + 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, + 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, + 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, + 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, + 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, + 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, + 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, + 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, + 0x02, 0x25, 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, + 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, + 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, + 0x60, 0x64, 0x23, 0xb0, 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, + 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, + 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x3c, 0x38, 0x2d, 0xb0, 0x3d, 0x2c, + 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, + 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, + 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, 0x2e, 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, + 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, + 0x47, 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, + 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x23, 0x21, + 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, + 0x23, 0x47, 0x23, 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, + 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, + 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, + 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, + 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, + 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, + 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, + 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, + 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, + 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, + 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, + 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x26, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, + 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, 0x20, 0x3c, 0x20, 0x2e, 0x23, 0x38, + 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, + 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, + 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, + 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, + 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, + 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, 0x23, + 0x38, 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, + 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, 0x3a, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, + 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x23, 0x38, 0xb1, 0x30, 0x01, + 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, + 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, + 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, + 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, 0xb0, 0x4c, 0x2c, 0xb0, 0x39, 0x2a, + 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, + 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, + 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, + 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x53, 0x2c, 0xb2, 0x00, 0x00, + 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, + 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, + 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x59, 0x2c, 0xb3, 0x01, 0x00, 0x00, + 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, + 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, + 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, + 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x61, 0x2c, 0xb2, 0x01, + 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, + 0x48, 0x2b, 0x2d, 0xb0, 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, + 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, + 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x69, 0x2c, 0xb3, 0x01, 0x00, 0x00, + 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, + 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, + 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, + 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x40, + 0x2b, 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, + 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x73, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, + 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x01, + 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, + 0x2d, 0xb0, 0x77, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, + 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, + 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, + 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, + 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, + 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, + 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, + 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, + 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, + 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x87, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, + 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, + 0x01, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, + 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, 0xb0, 0x06, 0x1b, 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, + 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, 0x50, 0x78, 0xb1, 0x05, 0x01, 0x15, + 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, + 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, 0x51, + 0x41, 0x00, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x14, 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, + 0x02, 0x56, 0x06, 0x46, 0x08, 0x3a, 0x06, 0x32, 0x04, 0x24, 0x07, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, + 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x4e, 0x06, 0x40, 0x04, 0x36, 0x02, 0x2b, 0x05, + 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, + 0x11, 0xc0, 0x0e, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, + 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, + 0x09, 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, + 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, 0x28, 0x01, 0x88, 0x51, 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, + 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, 0xba, 0x08, 0x80, 0x00, 0x01, 0x04, + 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, + 0x06, 0x7a, 0x06, 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x48, 0x06, 0x3c, 0x04, 0x34, 0x02, 0x26, 0x05, 0x09, 0x0e, + 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, 0x00, 0x44, 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x5d, 0x00, + 0x49, 0x00, 0x49, 0x02, 0xca, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0x22, + 0xff, 0xf6, 0xff, 0x10, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4b, 0x00, 0x4b, 0x02, 0x3c, 0x00, 0x00, 0x02, 0x45, 0xff, + 0xf8, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4b, 0x00, 0x4b, 0x02, 0x3c, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x45, + 0x02, 0x45, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0xff, 0xf6, 0x02, + 0xf8, 0x02, 0x18, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xfd, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, + 0x00, 0x48, 0x00, 0x48, 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, + 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x48, 0x00, 0x48, 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x5b, + 0x00, 0x5b, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0x00, 0x00, 0x02, 0xec, 0x02, 0x18, 0x00, 0x00, 0xff, 0x10, 0x02, + 0xd5, 0xff, 0xf6, 0x02, 0xec, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x2c, 0x00, 0x2c, + 0x01, 0x2a, 0xff, 0x7e, 0x01, 0x61, 0x00, 0xe2, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x32, 0xff, 0x76, 0x01, 0x61, 0x00, + 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x2c, 0x00, 0x2c, 0x02, 0xcb, 0x01, 0xa0, 0x02, 0xe0, + 0x02, 0x61, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe0, 0x01, 0x98, 0x02, 0xe0, 0x02, 0x67, 0x01, 0x19, 0x00, 0x8f, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, + 0x0e, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x36, 0x00, 0xd6, 0x00, 0x03, 0x00, 0x01, + 0x04, 0x09, 0x00, 0x04, 0x00, 0x22, 0x01, 0x0c, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, 0x01, + 0x2e, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x20, 0x01, 0x82, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, + 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, + 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, + 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, + 0x20, 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, + 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, + 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2f, + 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, + 0x2f, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, + 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, + 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, + 0x00, 0x6e, 0x00, 0x73, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, + 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, + 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, + 0x2d, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x4e, 0x00, 0x6f, + 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x52, 0x00, + 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, + 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, + 0x3b, 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x68, + 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, 0x00, + 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, 0x00, 0x29, + 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, + 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x9c, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x0c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x1f, 0x00, 0x01, 0x00, + 0x22, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x42, 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x0e, + 0x00, 0x05, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x20, 0x00, 0x20, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6b, 0x00, + 0x6f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x2d, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, + 0x01, 0x3b, 0x00, 0x01, 0x02, 0x77, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, + 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, + 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x6b, 0x65, 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, + 0x07, 0x2c, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0xf6, 0x00, 0x01, 0x00, 0x34, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x15, 0x00, 0x62, 0x00, 0xe2, 0x00, 0x74, 0x00, 0x7a, 0x00, 0xb2, 0x00, 0x84, 0x00, 0x8a, 0x00, 0xb2, + 0x00, 0xa8, 0x00, 0xb2, 0x00, 0xb8, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xc2, 0x00, 0xe2, 0x00, 0xcc, 0x00, 0xd2, 0x00, + 0xdc, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xe2, 0x00, 0x01, 0x00, 0x15, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, 0x00, 0x23, + 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, 0x00, 0x38, 0x00, + 0x3a, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, + 0xff, 0xc4, 0x00, 0x37, 0xff, 0xec, 0x00, 0x38, 0xff, 0xec, 0x00, 0x3a, 0xff, 0xe2, 0x00, 0x01, 0x00, 0x2b, 0x00, + 0x32, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xf6, 0x00, 0x0f, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x07, + 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, + 0xec, 0x00, 0x3e, 0x00, 0x14, 0x00, 0x5e, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x39, 0xff, 0xec, + 0x00, 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, + 0x07, 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x5f, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, + 0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, + 0x28, 0x00, 0x02, 0x04, 0x32, 0x00, 0x04, 0x00, 0x00, 0x04, 0x86, 0x05, 0x50, 0x00, 0x17, 0x00, 0x17, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, + 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xd8, 0x00, 0x00, + 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xce, 0xff, 0xec, 0xff, 0xe2, 0xff, 0xce, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xce, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xec, 0x00, 0x00, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xec, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, + 0xd8, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, + 0xff, 0xe2, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xba, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xff, 0xc4, 0xff, 0xba, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, + 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x60, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x03, 0x00, 0x08, + 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x2c, 0x00, + 0x2d, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, + 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, + 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6b, + 0x00, 0x02, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x09, 0x00, + 0x09, 0x00, 0x13, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, + 0x00, 0x0f, 0x00, 0x22, 0x00, 0x22, 0x00, 0x02, 0x00, 0x24, 0x00, 0x24, 0x00, 0x08, 0x00, 0x25, 0x00, 0x25, 0x00, + 0x03, 0x00, 0x26, 0x00, 0x26, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x09, + 0x00, 0x30, 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, + 0x35, 0x00, 0x35, 0x00, 0x0c, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x0a, 0x00, 0x39, + 0x00, 0x39, 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x07, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0e, 0x00, 0x3c, 0x00, + 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x49, 0x00, 0x49, + 0x00, 0x01, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, 0x55, 0x00, + 0x0d, 0x00, 0x57, 0x00, 0x58, 0x00, 0x05, 0x00, 0x59, 0x00, 0x59, 0x00, 0x16, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x05, + 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x15, 0x00, 0x01, 0x00, 0x03, 0x00, 0x6d, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0d, 0x00, 0x12, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, + 0x00, 0x07, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x36, 0x00, 0x6c, 0x00, 0x04, 0x44, 0x46, 0x4c, + 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, + 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x04, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x1a, 0x66, 0x72, 0x61, 0x63, 0x00, 0x20, 0x6c, 0x69, 0x67, 0x61, + 0x00, 0x2a, 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x32, 0x00, 0x10, 0x00, 0x1e, 0x00, 0x32, 0x00, 0x4a, 0x00, 0x88, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x5f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, + 0x00, 0x06, 0x00, 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x01, 0x00, 0x06, 0x00, 0x69, 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, + 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x70, 0x00, 0x79, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, + 0x00, 0x7a, 0x00, 0x83, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x36, 0x00, + 0x01, 0x00, 0x08, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6f, 0x00, 0x03, + 0x00, 0x47, 0x00, 0x4d, 0x00, 0x6e, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x4a, 0x00, + 0x6d, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6b, 0x00, 0x02, 0x00, 0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x47}; + + constexpr unsigned char ITALICS_DATA[] = { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x09, 0x76, 0x04, + 0x22, 0x00, 0x00, 0x59, 0xdc, 0x00, 0x00, 0x00, 0x7a, 0x47, 0x50, 0x4f, 0x53, 0x33, 0x4f, 0x0e, 0xa7, 0x00, 0x00, + 0x5a, 0x58, 0x00, 0x00, 0x07, 0x4e, 0x47, 0x53, 0x55, 0x42, 0xfc, 0xd3, 0xd8, 0xce, 0x00, 0x00, 0x61, 0xa8, 0x00, + 0x00, 0x01, 0xd4, 0x4f, 0x53, 0x2f, 0x32, 0x69, 0x50, 0x5f, 0x5f, 0x00, 0x00, 0x46, 0xec, 0x00, 0x00, 0x00, 0x60, + 0x63, 0x6d, 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x47, 0x4c, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, + 0x20, 0x3d, 0xa5, 0x1a, 0xce, 0x00, 0x00, 0x56, 0x94, 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, + 0x0b, 0x83, 0x00, 0x00, 0x47, 0x80, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x59, 0xd4, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0x07, 0xce, 0x9d, 0x67, 0x00, 0x00, 0x01, 0x1c, + 0x00, 0x00, 0x42, 0x36, 0x68, 0x65, 0x61, 0x64, 0x28, 0x38, 0xd8, 0x22, 0x00, 0x00, 0x44, 0x8c, 0x00, 0x00, 0x00, + 0x36, 0x68, 0x68, 0x65, 0x61, 0x0d, 0x3b, 0x0b, 0x91, 0x00, 0x00, 0x46, 0xc8, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, + 0x74, 0x78, 0xec, 0x2d, 0x0f, 0x0b, 0x00, 0x00, 0x44, 0xc4, 0x00, 0x00, 0x02, 0x02, 0x6c, 0x6f, 0x63, 0x61, 0xd3, + 0x44, 0xc2, 0xf3, 0x00, 0x00, 0x43, 0x74, 0x00, 0x00, 0x01, 0x16, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x5b, 0x10, 0x84, + 0x00, 0x00, 0x43, 0x54, 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x5c, 0x42, 0x2a, 0x00, 0x00, 0x57, + 0xc0, 0x00, 0x00, 0x01, 0xf4, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x93, 0x00, 0x32, 0x00, 0x00, 0x59, 0xb4, 0x00, 0x00, + 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0xff, 0x8d, 0x0b, 0xc2, 0x00, 0x00, 0x55, 0x8c, 0x00, 0x00, 0x01, 0x05, 0x00, + 0x02, 0x00, 0x14, 0xff, 0xf2, 0x01, 0x13, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x2f, 0x40, 0x2c, 0x04, 0x01, + 0x01, 0x00, 0x03, 0x00, 0x01, 0x03, 0x80, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, + 0x02, 0x02, 0x71, 0x02, 0x4e, 0x05, 0x04, 0x00, 0x00, 0x0a, 0x08, 0x04, 0x0e, 0x05, 0x0e, 0x00, 0x03, 0x00, 0x03, + 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x37, 0x13, 0x33, 0x03, 0x07, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, + 0x06, 0x4d, 0x5b, 0x6b, 0x7f, 0x4b, 0x35, 0x24, 0x27, 0x17, 0x1c, 0x23, 0xc9, 0x02, 0x01, 0xfd, 0xff, 0xd7, 0x36, + 0x20, 0x31, 0x1c, 0x1a, 0x1d, 0x34, 0x00, 0x02, 0x00, 0x6d, 0x01, 0xc8, 0x01, 0x9c, 0x02, 0xca, 0x00, 0x03, 0x00, + 0x07, 0x00, 0x24, 0x40, 0x21, 0x05, 0x03, 0x04, 0x03, 0x01, 0x01, 0x00, 0x5f, 0x02, 0x01, 0x00, 0x00, 0x6a, 0x01, + 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, + 0x2b, 0x01, 0x13, 0x33, 0x03, 0x23, 0x13, 0x33, 0x03, 0x01, 0x19, 0x23, 0x60, 0x4b, 0xe4, 0x23, 0x60, 0x4b, 0x01, + 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 0x02, 0x8e, 0x02, + 0xca, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, 0x40, 0x44, 0x07, 0x05, 0x02, 0x03, 0x0f, 0x08, 0x02, 0x02, 0x01, 0x03, + 0x02, 0x68, 0x0e, 0x09, 0x02, 0x01, 0x0c, 0x0a, 0x02, 0x00, 0x0b, 0x01, 0x00, 0x67, 0x06, 0x01, 0x04, 0x04, 0x6a, + 0x4d, 0x10, 0x0d, 0x02, 0x0b, 0x0b, 0x6b, 0x0b, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, 0x1c, 0x00, 0x1b, 0x00, 0x1b, + 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0d, + 0x1f, 0x2b, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, + 0x07, 0x23, 0x07, 0x33, 0x07, 0x23, 0x07, 0x23, 0x37, 0x23, 0x07, 0x13, 0x33, 0x37, 0x23, 0x61, 0x3b, 0x7e, 0x06, + 0x8b, 0x30, 0x86, 0x06, 0x92, 0x3c, 0x48, 0x3d, 0x90, 0x3e, 0x44, 0x3c, 0x80, 0x07, 0x8d, 0x2f, 0x8a, 0x06, 0x97, + 0x3c, 0x48, 0x3f, 0x90, 0x3d, 0x50, 0x90, 0x2d, 0x8f, 0xd1, 0x42, 0xa2, 0x41, 0xd4, 0xd4, 0xd4, 0xd4, 0x41, 0xa2, + 0x42, 0xd1, 0xd1, 0xd1, 0x01, 0x13, 0xa2, 0x00, 0x03, 0x00, 0x22, 0xff, 0xc6, 0x02, 0x0d, 0x02, 0xf6, 0x00, 0x23, + 0x00, 0x2a, 0x00, 0x31, 0x00, 0x82, 0x40, 0x14, 0x15, 0x12, 0x02, 0x03, 0x02, 0x31, 0x2a, 0x1a, 0x16, 0x08, 0x04, + 0x06, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x19, 0x00, 0x04, 0x00, + 0x00, 0x04, 0x71, 0x00, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x03, 0x03, 0x02, 0x5f, 0x00, 0x02, 0x02, + 0x6c, 0x03, 0x4e, 0x1b, 0x4b, 0xb0, 0x31, 0x50, 0x58, 0x40, 0x18, 0x00, 0x04, 0x00, 0x04, 0x86, 0x00, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x03, 0x03, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6c, 0x03, 0x4e, 0x1b, 0x40, 0x1d, + 0x00, 0x04, 0x00, 0x04, 0x86, 0x00, 0x02, 0x00, 0x03, 0x01, 0x02, 0x03, 0x69, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, + 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, 0x00, 0x51, 0x59, 0x59, 0xb7, 0x19, 0x17, 0x19, 0x15, 0x10, 0x05, + 0x0d, 0x1b, 0x2b, 0x37, 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x37, + 0x37, 0x33, 0x07, 0x16, 0x16, 0x17, 0x07, 0x26, 0x26, 0x27, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, + 0x23, 0x13, 0x06, 0x06, 0x15, 0x14, 0x16, 0x17, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0xbe, 0x29, 0x54, 0x1f, + 0x27, 0x5c, 0x27, 0x2f, 0x3d, 0x47, 0x35, 0x5c, 0x39, 0x13, 0x41, 0x12, 0x26, 0x46, 0x1e, 0x21, 0x17, 0x3e, 0x23, + 0x2d, 0x44, 0x45, 0x38, 0x5e, 0x3b, 0x18, 0x41, 0x8c, 0x2f, 0x3b, 0x21, 0x22, 0x03, 0x2e, 0x40, 0x1f, 0x26, 0x32, + 0x02, 0x13, 0x0f, 0x50, 0x14, 0x17, 0x01, 0xd7, 0x17, 0x45, 0x3f, 0x39, 0x4c, 0x2b, 0x05, 0x55, 0x56, 0x03, 0x12, + 0x10, 0x47, 0x0d, 0x15, 0x02, 0xd1, 0x19, 0x43, 0x3b, 0x3a, 0x4f, 0x2d, 0x07, 0x6d, 0x02, 0x92, 0x05, 0x34, 0x31, + 0x19, 0x2a, 0x0d, 0xfe, 0xdf, 0x06, 0x37, 0x2f, 0x1a, 0x28, 0x0f, 0x00, 0x00, 0x05, 0x00, 0x50, 0xff, 0xf6, 0x02, + 0xf3, 0x02, 0xd4, 0x00, 0x11, 0x00, 0x15, 0x00, 0x26, 0x00, 0x38, 0x00, 0x49, 0x00, 0x99, 0x4b, 0xb0, 0x19, 0x50, + 0x58, 0x40, 0x2c, 0x00, 0x07, 0x00, 0x09, 0x04, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, + 0x00, 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x70, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x03, 0x61, + 0x0d, 0x06, 0x0b, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x34, 0x00, 0x07, 0x00, 0x09, 0x04, 0x07, 0x09, + 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x05, 0x05, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x0b, 0x01, 0x03, 0x03, 0x6b, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x06, 0x61, + 0x0d, 0x01, 0x06, 0x06, 0x71, 0x06, 0x4e, 0x59, 0x40, 0x2b, 0x3a, 0x39, 0x28, 0x27, 0x17, 0x16, 0x12, 0x12, 0x01, + 0x00, 0x43, 0x41, 0x39, 0x49, 0x3a, 0x49, 0x31, 0x2f, 0x27, 0x38, 0x28, 0x38, 0x20, 0x1e, 0x16, 0x26, 0x17, 0x26, + 0x12, 0x15, 0x12, 0x15, 0x14, 0x13, 0x0a, 0x08, 0x00, 0x11, 0x01, 0x11, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, + 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x03, 0x03, 0x01, 0x33, 0x01, 0x13, 0x32, 0x3e, 0x03, + 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x14, 0x01, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, + 0x15, 0x14, 0x0e, 0x03, 0x27, 0x32, 0x3e, 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x14, 0xc3, 0x37, + 0x3c, 0x0a, 0x19, 0x2b, 0x42, 0x2e, 0x39, 0x3c, 0x0b, 0x1a, 0x2d, 0x41, 0x7f, 0x02, 0x12, 0x4e, 0xfd, 0xee, 0x0b, + 0x1a, 0x27, 0x1a, 0x0f, 0x07, 0x1a, 0x19, 0x1a, 0x26, 0x1a, 0x0f, 0x07, 0x01, 0x9a, 0x37, 0x3c, 0x0a, 0x19, 0x2c, + 0x41, 0x2e, 0x3a, 0x3c, 0x0c, 0x1a, 0x2c, 0x42, 0x26, 0x1a, 0x27, 0x1a, 0x0f, 0x07, 0x1a, 0x19, 0x1a, 0x26, 0x19, + 0x0f, 0x07, 0x01, 0x14, 0x4b, 0x46, 0x1d, 0x4e, 0x52, 0x47, 0x2b, 0x47, 0x42, 0x1b, 0x4f, 0x55, 0x4a, 0x2e, 0xfe, + 0xec, 0x02, 0xca, 0xfd, 0x36, 0x01, 0x56, 0x27, 0x3d, 0x42, 0x3a, 0x0f, 0x29, 0x25, 0x24, 0x38, 0x41, 0x3c, 0x14, + 0x50, 0xfe, 0xa0, 0x4a, 0x46, 0x1e, 0x4f, 0x52, 0x46, 0x2b, 0x47, 0x41, 0x1b, 0x4f, 0x55, 0x4b, 0x2e, 0x42, 0x27, + 0x3d, 0x43, 0x39, 0x0f, 0x29, 0x25, 0x24, 0x38, 0x41, 0x3c, 0x14, 0x50, 0x00, 0x00, 0x03, 0x00, 0x20, 0xff, 0xf6, + 0x02, 0x85, 0x02, 0xd5, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x38, 0x00, 0x7b, 0x40, 0x0f, 0x32, 0x14, 0x06, 0x03, 0x02, + 0x04, 0x31, 0x1f, 0x1c, 0x15, 0x04, 0x05, 0x02, 0x02, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x24, 0x00, 0x04, + 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, + 0x4d, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, + 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6b, 0x4d, + 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x2f, 0x2e, 0x01, + 0x00, 0x2e, 0x38, 0x2f, 0x38, 0x2a, 0x28, 0x1e, 0x1d, 0x19, 0x18, 0x0e, 0x0c, 0x00, 0x21, 0x01, 0x21, 0x08, 0x0d, + 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, 0x07, 0x17, 0x23, 0x27, 0x06, 0x06, 0x13, 0x3e, + 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x03, 0x32, 0x36, 0x37, 0x27, 0x0e, 0x02, 0x15, 0x14, 0x16, + 0xd8, 0x51, 0x67, 0x63, 0x5b, 0x13, 0x1e, 0x2d, 0x56, 0x3d, 0x49, 0x56, 0x35, 0x58, 0x35, 0x84, 0x21, 0x2e, 0x10, + 0x58, 0x19, 0x46, 0x2c, 0x63, 0x68, 0x37, 0x2f, 0x6a, 0x02, 0x20, 0x42, 0x2e, 0x28, 0x26, 0x31, 0x37, 0x18, 0x35, + 0x51, 0x25, 0x91, 0x24, 0x40, 0x28, 0x40, 0x0a, 0x5b, 0x57, 0x50, 0x69, 0x2b, 0x20, 0x4b, 0x2a, 0x33, 0x51, 0x30, + 0x4d, 0x42, 0x32, 0x48, 0x37, 0x1b, 0xb8, 0x1d, 0x4b, 0x28, 0x3d, 0x66, 0x2a, 0x85, 0x4e, 0x26, 0x32, 0x01, 0xbb, + 0x10, 0x27, 0x34, 0x23, 0x23, 0x2c, 0x3a, 0x33, 0x3b, 0xfe, 0x59, 0x2b, 0x1e, 0xce, 0x13, 0x2c, 0x3d, 0x2c, 0x33, + 0x3c, 0x00, 0x01, 0x00, 0x6d, 0x01, 0xc8, 0x00, 0xf0, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, + 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, + 0x17, 0x2b, 0x13, 0x13, 0x33, 0x03, 0x6d, 0x23, 0x60, 0x4b, 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x01, + 0x00, 0x28, 0xff, 0x62, 0x01, 0x6f, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x00, 0x01, + 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x16, 0x03, 0x0d, 0x17, 0x2b, 0x17, + 0x26, 0x26, 0x35, 0x34, 0x12, 0x37, 0x33, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x17, 0x70, 0x22, 0x26, 0x80, 0x76, 0x51, + 0x47, 0x6e, 0x3e, 0x1d, 0x1b, 0x9e, 0x3d, 0x94, 0x52, 0xb3, 0x01, 0x19, 0x79, 0x4e, 0xb5, 0xcd, 0x74, 0x57, 0x8f, + 0x3e, 0x00, 0x00, 0x01, 0xff, 0xb3, 0xff, 0x62, 0x00, 0xf9, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x19, 0x40, 0x16, 0x02, + 0x01, 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x17, 0x03, + 0x0d, 0x17, 0x2b, 0x07, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x15, 0x14, 0x02, 0x07, 0x4d, 0x47, + 0x6d, 0x3e, 0x1c, 0x1b, 0x44, 0x22, 0x25, 0x7f, 0x77, 0x9e, 0x4f, 0xb4, 0xce, 0x73, 0x56, 0x91, 0x3d, 0x3d, 0x94, + 0x53, 0xb2, 0xfe, 0xe7, 0x79, 0x00, 0x00, 0x01, 0x00, 0x67, 0x01, 0x2c, 0x02, 0x33, 0x02, 0xfb, 0x00, 0x0e, 0x00, + 0x1d, 0x40, 0x1a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x05, 0x00, 0x4a, 0x0e, 0x0d, 0x0c, 0x04, 0x03, 0x02, 0x01, 0x07, + 0x00, 0x49, 0x00, 0x00, 0x00, 0x76, 0x1a, 0x01, 0x0d, 0x17, 0x2b, 0x01, 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, + 0x37, 0x17, 0x07, 0x37, 0x07, 0x27, 0x17, 0x01, 0x74, 0x36, 0x7b, 0x3d, 0x95, 0xb4, 0x1c, 0xb4, 0x14, 0x57, 0x3b, + 0xcc, 0x04, 0xbe, 0x57, 0x01, 0x2c, 0xc3, 0xa5, 0x3d, 0x89, 0x35, 0x4e, 0x59, 0xc1, 0x11, 0xba, 0x0a, 0x52, 0x17, + 0xb9, 0x00, 0x01, 0x00, 0x46, 0x00, 0x6f, 0x02, 0x1c, 0x02, 0x53, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x00, 0x05, + 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, 0x05, 0x02, 0x5f, + 0x00, 0x02, 0x05, 0x02, 0x4f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x15, 0x23, + 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, 0x01, 0x55, 0xc7, 0xc7, 0x48, 0xc7, 0xc7, 0x48, 0x01, 0x84, 0x47, + 0xce, 0xce, 0x47, 0xcf, 0x00, 0x00, 0x01, 0xff, 0xd5, 0xff, 0x7f, 0x00, 0x9c, 0x00, 0x74, 0x00, 0x08, 0x00, 0x17, + 0x40, 0x14, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x13, + 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x36, 0x36, 0x37, 0x33, 0x17, 0x06, 0x06, 0x07, 0x2b, 0x1a, 0x36, 0x13, 0x60, 0x04, + 0x19, 0x48, 0x23, 0x81, 0x3b, 0x86, 0x34, 0x0b, 0x35, 0x7e, 0x37, 0x00, 0x00, 0x01, 0x00, 0x1a, 0x00, 0xe3, 0x01, + 0x18, 0x01, 0x34, 0x00, 0x03, 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, + 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, + 0x37, 0x33, 0x07, 0x1a, 0x12, 0xec, 0x12, 0xe3, 0x51, 0x51, 0x00, 0x00, 0x01, 0x00, 0x14, 0xff, 0xf2, 0x00, 0x92, + 0x00, 0x79, 0x00, 0x0a, 0x00, 0x1a, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x02, 0x01, 0x00, 0x00, 0x71, 0x00, + 0x4e, 0x01, 0x00, 0x06, 0x04, 0x00, 0x0a, 0x01, 0x0a, 0x03, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x35, 0x34, 0x36, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x48, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0x0e, 0x34, 0x21, 0x32, 0x1b, 0x1a, 0x1f, + 0x33, 0x00, 0x01, 0xff, 0xd2, 0x00, 0x00, 0x01, 0xb9, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, + 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, + 0x17, 0x2b, 0x23, 0x01, 0x33, 0x01, 0x2e, 0x01, 0x8d, 0x5a, 0xfe, 0x74, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x00, 0x02, + 0x00, 0x39, 0xff, 0xf6, 0x02, 0x16, 0x02, 0xd5, 0x00, 0x11, 0x00, 0x23, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, + 0x4e, 0x13, 0x12, 0x01, 0x00, 0x1c, 0x1a, 0x12, 0x23, 0x13, 0x23, 0x0a, 0x08, 0x00, 0x11, 0x01, 0x11, 0x06, 0x0d, + 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x03, 0x27, 0x32, 0x3e, + 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x14, 0x16, 0xec, 0x58, 0x5b, 0x14, 0x2b, 0x46, 0x63, 0x41, + 0x5c, 0x58, 0x16, 0x2d, 0x46, 0x62, 0x35, 0x28, 0x3f, 0x2f, 0x20, 0x10, 0x2f, 0x30, 0x26, 0x40, 0x31, 0x22, 0x12, + 0x30, 0x0a, 0x7e, 0x75, 0x3b, 0x86, 0x81, 0x6a, 0x40, 0x77, 0x6f, 0x48, 0x90, 0x82, 0x65, 0x3a, 0x4b, 0x34, 0x59, + 0x70, 0x79, 0x3a, 0x4a, 0x4f, 0x33, 0x57, 0x6c, 0x75, 0x36, 0x51, 0x57, 0x00, 0x00, 0x01, 0x00, 0x8f, 0x00, 0x00, + 0x01, 0xbc, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x1b, 0x40, 0x18, 0x08, 0x07, 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, + 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x11, 0x19, 0x02, 0x0d, 0x18, 0x2b, 0x01, 0x36, 0x36, + 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, 0x03, 0x23, 0x01, 0x29, 0x0a, 0x17, 0x09, 0x0f, 0x20, 0x14, 0x58, + 0x29, 0xe0, 0x4d, 0x99, 0x59, 0x01, 0xba, 0x2f, 0x60, 0x1d, 0x10, 0x18, 0x0d, 0x37, 0x42, 0x8e, 0xfd, 0x36, 0x00, + 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x10, 0x02, 0xd4, 0x00, 0x1b, 0x00, 0x2c, 0x40, 0x29, 0x0d, 0x0c, 0x02, + 0x02, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, + 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x1b, 0x27, 0x25, 0x28, 0x05, 0x0d, 0x19, + 0x2b, 0x33, 0x37, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x15, 0x21, 0x07, 0x03, 0x10, 0xe3, 0x42, 0x54, 0x28, 0x37, 0x33, 0x2c, 0x4a, + 0x23, 0x2a, 0x29, 0x64, 0x40, 0x5b, 0x61, 0x2c, 0x63, 0x53, 0xa8, 0x01, 0x46, 0x0f, 0x4b, 0xcd, 0x3c, 0x54, 0x4c, + 0x2f, 0x2d, 0x39, 0x24, 0x1a, 0x3c, 0x21, 0x2c, 0x5b, 0x48, 0x3a, 0x5f, 0x6a, 0x48, 0x92, 0x04, 0x50, 0x00, 0x00, + 0x01, 0x00, 0x16, 0xff, 0xf6, 0x02, 0x0d, 0x02, 0xd4, 0x00, 0x2b, 0x00, 0x4a, 0x40, 0x47, 0x1b, 0x01, 0x04, 0x05, + 0x1a, 0x01, 0x03, 0x04, 0x24, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, + 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1f, 0x1d, 0x18, 0x16, 0x11, 0x0f, 0x0e, + 0x0c, 0x08, 0x06, 0x00, 0x2b, 0x01, 0x2b, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, + 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, + 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xd2, 0x3a, + 0x5b, 0x27, 0x23, 0x66, 0x34, 0x50, 0x56, 0x4b, 0x45, 0x40, 0x0f, 0x41, 0x32, 0x55, 0x33, 0x39, 0x2d, 0x2e, 0x4c, + 0x26, 0x29, 0x29, 0x65, 0x43, 0x5a, 0x5e, 0x62, 0x57, 0x39, 0x49, 0x36, 0x72, 0x0a, 0x15, 0x12, 0x55, 0x13, 0x1f, + 0x4d, 0x41, 0x3e, 0x40, 0x49, 0x23, 0x44, 0x2f, 0x2e, 0x31, 0x20, 0x1a, 0x3e, 0x1e, 0x28, 0x57, 0x47, 0x4c, 0x6a, + 0x10, 0x04, 0x0a, 0x4f, 0x41, 0x38, 0x65, 0x3f, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x02, 0x18, 0x02, 0xca, + 0x00, 0x0a, 0x00, 0x16, 0x00, 0x2e, 0x40, 0x2b, 0x11, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x05, 0x01, 0x02, 0x03, 0x01, + 0x00, 0x04, 0x02, 0x00, 0x68, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x6b, 0x04, 0x4e, 0x00, 0x00, + 0x0c, 0x0b, 0x00, 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0d, 0x1a, 0x2b, 0x21, 0x37, 0x21, 0x37, 0x01, + 0x33, 0x03, 0x33, 0x07, 0x23, 0x07, 0x25, 0x33, 0x37, 0x3e, 0x02, 0x37, 0x23, 0x0e, 0x02, 0x07, 0x01, 0x20, 0x23, + 0xfe, 0xc3, 0x0f, 0x01, 0x93, 0x65, 0x63, 0x6e, 0x11, 0x6f, 0x23, 0xfe, 0xfa, 0xe5, 0x24, 0x08, 0x15, 0x15, 0x06, + 0x04, 0x08, 0x1a, 0x19, 0x09, 0xa2, 0x50, 0x01, 0xd8, 0xfe, 0x26, 0x4e, 0xa2, 0xf0, 0xab, 0x25, 0x51, 0x48, 0x17, + 0x0d, 0x24, 0x22, 0x0a, 0x00, 0x01, 0x00, 0x25, 0xff, 0xf6, 0x02, 0x18, 0x02, 0xca, 0x00, 0x20, 0x00, 0x44, 0x40, + 0x41, 0x16, 0x11, 0x02, 0x02, 0x05, 0x10, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, + 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, + 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1a, 0x18, 0x15, 0x14, 0x13, 0x12, 0x0e, 0x0c, + 0x07, 0x05, 0x00, 0x20, 0x01, 0x20, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, + 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x07, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x15, 0x14, 0x0e, 0x02, 0xc8, 0x61, 0x42, 0x24, 0x53, 0x2c, 0x46, 0x56, 0x27, 0x48, 0x3e, 0x1e, 0x34, 0x20, 0x25, + 0x61, 0x01, 0x49, 0x11, 0xfd, 0x3c, 0x12, 0x2a, 0x1b, 0x59, 0x69, 0x1d, 0x41, 0x6f, 0x0a, 0x27, 0x55, 0x16, 0x1c, + 0x30, 0x4f, 0x2e, 0x3e, 0x44, 0x0a, 0x08, 0x1d, 0x01, 0x50, 0x50, 0xcf, 0x04, 0x06, 0x65, 0x58, 0x2d, 0x5b, 0x4c, + 0x2e, 0x00, 0x02, 0x00, 0x3f, 0xff, 0xf6, 0x02, 0x22, 0x02, 0xd4, 0x00, 0x1e, 0x00, 0x30, 0x00, 0x47, 0x40, 0x44, + 0x0c, 0x01, 0x02, 0x01, 0x0d, 0x01, 0x03, 0x02, 0x13, 0x01, 0x04, 0x05, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x05, 0x04, + 0x03, 0x05, 0x69, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x20, 0x1f, 0x01, 0x00, 0x27, 0x25, 0x1f, 0x30, 0x20, 0x30, 0x18, 0x16, + 0x11, 0x0f, 0x0b, 0x09, 0x00, 0x1e, 0x01, 0x1e, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, + 0x37, 0x36, 0x36, 0x33, 0x32, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x06, 0x06, 0x15, + 0x14, 0x16, 0x16, 0xfb, 0x54, 0x68, 0x20, 0x44, 0x35, 0x2b, 0x76, 0x4d, 0x36, 0x26, 0x12, 0x10, 0x29, 0x1b, 0x5f, + 0x91, 0x23, 0x04, 0x1d, 0x54, 0x34, 0x4a, 0x58, 0x1e, 0x3d, 0x5e, 0x37, 0x31, 0x44, 0x24, 0x34, 0x35, 0x24, 0x3c, + 0x29, 0x09, 0x07, 0x05, 0x16, 0x30, 0x0a, 0x6b, 0x70, 0x46, 0x9d, 0x91, 0x33, 0x2c, 0x30, 0x0b, 0x4c, 0x05, 0x07, + 0x84, 0x97, 0x26, 0x2d, 0x5e, 0x56, 0x32, 0x63, 0x51, 0x31, 0x4a, 0x38, 0x5b, 0x32, 0x38, 0x3d, 0x20, 0x2e, 0x15, + 0x10, 0x28, 0x14, 0x24, 0x3f, 0x28, 0x00, 0x01, 0x00, 0x51, 0x00, 0x00, 0x02, 0x32, 0x02, 0xca, 0x00, 0x06, 0x00, + 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, + 0x4e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x37, 0x21, 0x07, + 0x01, 0x51, 0x01, 0x75, 0xfe, 0xa5, 0x10, 0x01, 0xb7, 0x0d, 0xfe, 0x8b, 0x02, 0x7c, 0x4e, 0x46, 0xfd, 0x7c, 0x00, + 0x00, 0x03, 0x00, 0x2d, 0xff, 0xf6, 0x02, 0x1f, 0x02, 0xd5, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x36, 0x00, 0x35, 0x40, + 0x32, 0x30, 0x16, 0x07, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, + 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x2a, 0x29, 0x01, 0x00, 0x29, 0x36, + 0x2a, 0x36, 0x24, 0x22, 0x0f, 0x0d, 0x00, 0x1c, 0x01, 0x1c, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, + 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x16, + 0x16, 0x15, 0x14, 0x06, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x03, 0x32, + 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x0e, 0x02, 0x15, 0x14, 0x16, 0xf6, 0x45, 0x59, 0x2b, 0x64, 0x59, 0x26, 0x2f, + 0x38, 0x61, 0x3b, 0x42, 0x50, 0x24, 0x2f, 0x4c, 0x2c, 0x34, 0x3d, 0x33, 0x6c, 0x0f, 0x44, 0x47, 0x36, 0x2e, 0x35, + 0x41, 0x2c, 0x19, 0x32, 0x40, 0x1e, 0x32, 0x35, 0x2d, 0x49, 0x2a, 0x43, 0x0a, 0x31, 0x51, 0x31, 0x4d, 0x68, 0x22, + 0x1c, 0x46, 0x37, 0x3b, 0x54, 0x2d, 0x2d, 0x48, 0x29, 0x35, 0x49, 0x32, 0x13, 0x1f, 0x53, 0x41, 0x35, 0x5d, 0x39, + 0x01, 0xa6, 0x1a, 0x43, 0x35, 0x2b, 0x32, 0x3d, 0x35, 0x2d, 0x3a, 0xfe, 0x8d, 0x25, 0x3b, 0x20, 0x30, 0x48, 0x1c, + 0x0e, 0x29, 0x3f, 0x2f, 0x34, 0x3b, 0x00, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x0a, 0x02, 0xd4, 0x00, 0x1f, + 0x00, 0x2e, 0x00, 0x47, 0x40, 0x44, 0x0a, 0x01, 0x04, 0x05, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x03, + 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, + 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x21, 0x20, 0x01, 0x00, 0x29, 0x27, + 0x20, 0x2e, 0x21, 0x2e, 0x16, 0x14, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x1f, 0x01, 0x1f, 0x08, 0x0d, 0x16, 0x2b, 0x17, + 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x07, 0x06, 0x06, 0x13, 0x32, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, + 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0xa5, 0x1e, 0x3e, 0x1a, 0x1b, 0x3b, 0x22, 0x64, 0x77, 0x1e, 0x05, 0x19, + 0x4f, 0x30, 0x52, 0x5a, 0x3c, 0x70, 0x4d, 0x58, 0x62, 0x12, 0x22, 0x31, 0x20, 0x2e, 0x71, 0x2f, 0x2f, 0x4c, 0x15, + 0x0e, 0x36, 0x32, 0x32, 0x46, 0x25, 0x34, 0x0a, 0x09, 0x08, 0x51, 0x09, 0x0d, 0x8a, 0x8b, 0x23, 0x2b, 0x62, 0x5b, + 0x48, 0x7b, 0x4b, 0x6f, 0x6d, 0x34, 0x75, 0x73, 0x64, 0x23, 0x33, 0x2c, 0x01, 0x5a, 0x32, 0x2e, 0x22, 0x32, 0x3b, + 0x4b, 0x34, 0x57, 0x35, 0x3a, 0x40, 0x00, 0x02, 0x00, 0x14, 0xff, 0xf2, 0x00, 0xe1, 0x02, 0x26, 0x00, 0x0a, 0x00, + 0x15, 0x00, 0x2d, 0x40, 0x2a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, + 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x0c, 0x0b, 0x01, 0x00, 0x11, 0x0f, 0x0b, 0x15, 0x0c, 0x15, + 0x06, 0x04, 0x00, 0x0a, 0x01, 0x0a, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x03, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x97, 0x34, 0x25, 0x28, 0x16, 0x1b, + 0x24, 0x75, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0x01, 0x9f, 0x33, 0x22, 0x32, 0x1a, 0x1b, 0x1f, 0x33, 0xfe, 0x53, + 0x34, 0x21, 0x32, 0x1b, 0x1a, 0x1f, 0x33, 0x00, 0x00, 0x02, 0xff, 0xcf, 0xff, 0x7f, 0x00, 0xe1, 0x02, 0x26, 0x00, + 0x0a, 0x00, 0x13, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, 0x03, 0x80, 0x05, 0x01, 0x03, 0x03, + 0x84, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x00, 0x4e, 0x0b, 0x0b, 0x01, 0x00, 0x0b, 0x13, + 0x0b, 0x13, 0x0f, 0x0e, 0x06, 0x04, 0x00, 0x0a, 0x01, 0x0a, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x35, 0x34, 0x36, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x03, 0x36, 0x36, 0x37, 0x33, 0x17, 0x06, 0x06, 0x07, 0x97, 0x34, 0x25, 0x28, + 0x16, 0x1b, 0x24, 0xee, 0x1a, 0x36, 0x13, 0x60, 0x04, 0x19, 0x48, 0x23, 0x01, 0x9f, 0x33, 0x22, 0x32, 0x1a, 0x1b, + 0x1f, 0x33, 0xfd, 0xe0, 0x3b, 0x86, 0x34, 0x0b, 0x35, 0x7e, 0x37, 0x00, 0x00, 0x01, 0x00, 0x46, 0x00, 0x74, 0x02, + 0x1d, 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, 0x32, 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, + 0x05, 0x02, 0x1d, 0xfe, 0x29, 0x01, 0xd7, 0xfe, 0x87, 0x01, 0x79, 0x74, 0xcf, 0x32, 0xeb, 0x4e, 0xb2, 0x9e, 0x00, + 0x02, 0x00, 0x4c, 0x00, 0xd9, 0x02, 0x16, 0x01, 0xe7, 0x00, 0x03, 0x00, 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, + 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x05, + 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, + 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, 0x35, 0x21, 0x15, 0x4c, 0x01, 0xca, 0xfe, 0x36, 0x01, + 0xca, 0x01, 0xa0, 0x47, 0x47, 0xc7, 0x47, 0x47, 0x00, 0x00, 0x01, 0x00, 0x46, 0x00, 0x74, 0x02, 0x1d, 0x02, 0x60, + 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, 0x25, 0x25, 0x35, 0x05, 0x15, 0x05, 0x46, 0x01, + 0x79, 0xfe, 0x87, 0x01, 0xd7, 0xfe, 0x29, 0xc2, 0x9d, 0xb3, 0x4e, 0xeb, 0x32, 0xcf, 0x00, 0x00, 0x02, 0x00, 0x4d, + 0xff, 0xf2, 0x01, 0xc6, 0x02, 0xd4, 0x00, 0x1c, 0x00, 0x27, 0x00, 0x3f, 0x40, 0x3c, 0x0f, 0x01, 0x00, 0x01, 0x0e, + 0x01, 0x02, 0x00, 0x02, 0x4c, 0x05, 0x01, 0x02, 0x00, 0x04, 0x00, 0x02, 0x04, 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x1e, 0x1d, + 0x00, 0x00, 0x23, 0x21, 0x1d, 0x27, 0x1e, 0x27, 0x00, 0x1c, 0x00, 0x1c, 0x25, 0x2a, 0x07, 0x0d, 0x18, 0x2b, 0x37, + 0x3e, 0x02, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x07, 0x0e, 0x02, 0x07, 0x07, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x7f, 0x07, + 0x1b, 0x2f, 0x24, 0x20, 0x37, 0x22, 0x30, 0x2e, 0x26, 0x49, 0x21, 0x20, 0x29, 0x62, 0x2f, 0x4f, 0x5e, 0x49, 0x46, + 0x27, 0x2b, 0x17, 0x08, 0x45, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0xc9, 0x2b, 0x40, 0x37, 0x1c, 0x19, 0x2e, 0x38, + 0x26, 0x2c, 0x30, 0x19, 0x10, 0x43, 0x16, 0x1c, 0x4e, 0x4f, 0x43, 0x64, 0x34, 0x1c, 0x28, 0x2c, 0x23, 0xd7, 0x34, + 0x21, 0x32, 0x1b, 0x1a, 0x1f, 0x33, 0x00, 0x00, 0x02, 0x00, 0x35, 0xff, 0xa5, 0x03, 0x36, 0x02, 0xc9, 0x00, 0x40, + 0x00, 0x4e, 0x00, 0x90, 0x40, 0x13, 0x22, 0x01, 0x09, 0x04, 0x45, 0x14, 0x02, 0x05, 0x09, 0x3d, 0x01, 0x07, 0x02, + 0x3e, 0x01, 0x00, 0x07, 0x04, 0x4c, 0x4b, 0xb0, 0x1b, 0x50, 0x58, 0x40, 0x28, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, + 0x02, 0x07, 0x05, 0x02, 0x69, 0x00, 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x09, 0x09, 0x04, 0x61, 0x00, 0x04, 0x04, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x26, 0x00, + 0x04, 0x00, 0x09, 0x05, 0x04, 0x09, 0x69, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, 0x07, 0x05, 0x02, 0x69, 0x00, + 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x06, 0x4e, 0x59, + 0x40, 0x1f, 0x42, 0x41, 0x01, 0x00, 0x49, 0x47, 0x41, 0x4e, 0x42, 0x4e, 0x3b, 0x39, 0x33, 0x31, 0x2a, 0x28, 0x20, + 0x1e, 0x19, 0x17, 0x12, 0x10, 0x0a, 0x08, 0x00, 0x40, 0x01, 0x40, 0x0c, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, + 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, + 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, + 0x3e, 0x02, 0x35, 0x34, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, + 0x06, 0x03, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x01, 0x81, 0x65, 0x95, + 0x52, 0x40, 0x7a, 0xad, 0x6c, 0x6a, 0x85, 0x3f, 0x37, 0x60, 0x3e, 0x38, 0x2d, 0x04, 0x04, 0x16, 0x44, 0x32, 0x37, + 0x42, 0x45, 0x73, 0x44, 0x30, 0x40, 0x1a, 0x2f, 0x08, 0x08, 0x1c, 0x14, 0x1f, 0x32, 0x23, 0x13, 0x2f, 0x6a, 0x59, + 0x56, 0x8b, 0x64, 0x36, 0x88, 0x84, 0x36, 0x6c, 0x2c, 0x34, 0x70, 0x3c, 0x30, 0x3f, 0x13, 0x21, 0x0a, 0x1e, 0x14, + 0x2e, 0x4c, 0x2c, 0x20, 0x5b, 0x50, 0x97, 0x6a, 0x5b, 0xa8, 0x83, 0x4d, 0x53, 0x87, 0x50, 0x59, 0x8c, 0x50, 0x36, + 0x23, 0x25, 0x34, 0x49, 0x43, 0x51, 0x7b, 0x44, 0x12, 0x0b, 0xb3, 0x1e, 0x27, 0x11, 0x1f, 0x18, 0x2a, 0x45, 0x55, + 0x2b, 0x42, 0x6c, 0x41, 0x3d, 0x6d, 0x90, 0x53, 0x7f, 0x93, 0x19, 0x11, 0x41, 0x15, 0x17, 0x01, 0x04, 0x55, 0x43, + 0x7c, 0x04, 0x07, 0x36, 0x5c, 0x39, 0x2c, 0x28, 0x00, 0x02, 0xff, 0xc7, 0x00, 0x00, 0x02, 0x01, 0x02, 0xca, 0x00, + 0x07, 0x00, 0x11, 0x00, 0x2c, 0x40, 0x29, 0x0d, 0x01, 0x04, 0x00, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x02, 0x01, 0x04, + 0x02, 0x68, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x09, 0x08, + 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x33, 0x13, 0x23, 0x27, 0x23, 0x07, + 0x13, 0x33, 0x27, 0x26, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x39, 0x01, 0x84, 0x5e, 0x58, 0x58, 0x1b, 0xf1, 0x74, + 0x9f, 0xbd, 0x10, 0x04, 0x07, 0x01, 0x03, 0x10, 0x2a, 0x17, 0x02, 0xca, 0xfd, 0x36, 0xde, 0xde, 0x01, 0x2e, 0x96, + 0x26, 0x5c, 0x23, 0x26, 0x57, 0x2c, 0x00, 0x03, 0x00, 0x29, 0x00, 0x00, 0x02, 0x4d, 0x02, 0xca, 0x00, 0x10, 0x00, + 0x1a, 0x00, 0x23, 0x00, 0x43, 0x40, 0x40, 0x08, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x00, 0x05, 0x04, + 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x08, 0x01, 0x04, 0x04, 0x01, 0x5f, + 0x06, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1c, 0x1b, 0x12, 0x11, 0x00, 0x00, 0x22, 0x20, 0x1b, 0x23, 0x1c, 0x23, + 0x19, 0x17, 0x11, 0x1a, 0x12, 0x1a, 0x00, 0x10, 0x00, 0x0f, 0x21, 0x09, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x13, 0x32, 0x36, 0x36, 0x35, 0x34, + 0x26, 0x23, 0x23, 0x07, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0xb9, 0x63, 0x71, 0x58, + 0x49, 0x31, 0x42, 0x47, 0x7b, 0x50, 0x41, 0x2d, 0x49, 0x2c, 0x3c, 0x46, 0x65, 0x30, 0x37, 0x55, 0x5c, 0x3e, 0x4a, + 0x70, 0x37, 0x02, 0xca, 0x4e, 0x56, 0x49, 0x5b, 0x0e, 0x05, 0x0d, 0x48, 0x3c, 0x49, 0x63, 0x32, 0x01, 0x9a, 0x1c, + 0x39, 0x2c, 0x2f, 0x33, 0xe3, 0xfe, 0xb2, 0x4c, 0x46, 0x30, 0x42, 0xfe, 0xfc, 0x00, 0x01, 0x00, 0x48, 0xff, 0xf6, + 0x02, 0x78, 0x02, 0xd4, 0x00, 0x1d, 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, 0x02, 0x01, 0x1a, 0x0c, 0x02, 0x03, 0x02, + 0x1b, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, + 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x18, 0x16, 0x10, 0x0e, 0x0a, 0x08, 0x00, 0x1d, + 0x01, 0x1d, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x17, 0x07, 0x26, 0x26, + 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x01, 0x46, 0x77, 0x87, 0x1e, + 0x3d, 0x5d, 0x7c, 0x4e, 0x64, 0x4a, 0x24, 0x1b, 0x43, 0x2c, 0x4b, 0x6d, 0x48, 0x23, 0x5d, 0x52, 0x29, 0x4f, 0x26, + 0x27, 0x4f, 0x0a, 0x92, 0x7f, 0x40, 0x84, 0x76, 0x5d, 0x36, 0x28, 0x4a, 0x0e, 0x15, 0x43, 0x6f, 0x86, 0x44, 0x5b, + 0x69, 0x10, 0x0d, 0x4e, 0x0e, 0x10, 0x00, 0x00, 0x02, 0x00, 0x29, 0x00, 0x00, 0x02, 0x7c, 0x02, 0xca, 0x00, 0x09, + 0x00, 0x13, 0x00, 0x2c, 0x40, 0x29, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, + 0x02, 0x01, 0x5f, 0x04, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x0b, 0x0a, 0x00, 0x00, 0x12, 0x10, 0x0a, 0x13, 0x0b, + 0x13, 0x00, 0x09, 0x00, 0x08, 0x21, 0x06, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, + 0x23, 0x37, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0xa9, 0x81, 0x92, 0x61, 0xbb, 0x87, + 0x05, 0x68, 0x8e, 0x4a, 0x69, 0x57, 0x55, 0x77, 0x02, 0xca, 0x8c, 0x91, 0x7c, 0xc2, 0x6f, 0x4d, 0x5e, 0xa0, 0x63, + 0x6e, 0x61, 0xfd, 0xd0, 0x00, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x02, 0x2a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x2f, + 0x40, 0x2c, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, + 0x4d, 0x00, 0x04, 0x04, 0x05, 0x5f, 0x06, 0x01, 0x05, 0x05, 0x6b, 0x05, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x33, 0x13, 0x21, 0x07, 0x21, 0x07, 0x33, 0x07, 0x21, 0x07, + 0x21, 0x07, 0x29, 0x97, 0x01, 0x6a, 0x11, 0xfe, 0xef, 0x2f, 0xff, 0x0f, 0xff, 0x00, 0x37, 0x01, 0x12, 0x11, 0x02, + 0xca, 0x4f, 0xdf, 0x4e, 0xff, 0x4f, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x02, 0x2a, 0x02, 0xca, 0x00, 0x09, 0x00, + 0x29, 0x40, 0x26, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, + 0x6a, 0x4d, 0x05, 0x01, 0x04, 0x04, 0x6b, 0x04, 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x11, 0x11, 0x11, 0x11, + 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x21, 0x07, 0x21, 0x07, 0x21, 0x07, 0x21, 0x03, 0x29, 0x97, 0x01, 0x6a, 0x10, + 0xfe, 0xee, 0x35, 0x01, 0x00, 0x11, 0xff, 0x00, 0x40, 0x02, 0xca, 0x4f, 0xfe, 0x4f, 0xfe, 0xd2, 0x00, 0x01, 0x00, + 0x48, 0xff, 0xf6, 0x02, 0x98, 0x02, 0xd4, 0x00, 0x21, 0x00, 0x3e, 0x40, 0x3b, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, + 0x05, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1e, 0x1d, + 0x1c, 0x1b, 0x18, 0x16, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x21, 0x01, 0x21, 0x07, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, + 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, + 0x33, 0x32, 0x36, 0x37, 0x37, 0x23, 0x37, 0x33, 0x03, 0x06, 0x06, 0x01, 0x57, 0x7f, 0x90, 0x37, 0x67, 0x8d, 0x56, + 0x41, 0x62, 0x2c, 0x22, 0x25, 0x56, 0x33, 0x52, 0x83, 0x4c, 0x27, 0x52, 0x40, 0x26, 0x3f, 0x16, 0x2e, 0x8c, 0x11, + 0xe5, 0x4c, 0x2d, 0x64, 0x0a, 0x8e, 0x7f, 0x62, 0xa9, 0x7f, 0x47, 0x16, 0x14, 0x4e, 0x11, 0x18, 0x62, 0xab, 0x6f, + 0x37, 0x59, 0x34, 0x0b, 0x07, 0xd3, 0x4e, 0xfe, 0xa3, 0x10, 0x15, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x02, 0xac, + 0x02, 0xca, 0x00, 0x0b, 0x00, 0x27, 0x40, 0x24, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x68, 0x02, 0x01, 0x00, + 0x00, 0x6a, 0x4d, 0x06, 0x05, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x21, 0x13, 0x33, 0x03, 0x23, 0x13, 0x21, 0x03, + 0x2a, 0x97, 0x59, 0x40, 0x01, 0x3a, 0x40, 0x58, 0x97, 0x58, 0x46, 0xfe, 0xc6, 0x46, 0x02, 0xca, 0xfe, 0xd2, 0x01, + 0x2e, 0xfd, 0x36, 0x01, 0x4d, 0xfe, 0xb3, 0x00, 0x00, 0x01, 0xff, 0xec, 0x00, 0x00, 0x01, 0x7d, 0x02, 0xca, 0x00, + 0x0b, 0x00, 0x22, 0x40, 0x1f, 0x0a, 0x09, 0x04, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6a, 0x4d, + 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0x23, + 0x37, 0x37, 0x13, 0x27, 0x37, 0x33, 0x07, 0x07, 0x03, 0x17, 0x07, 0x14, 0x0a, 0x55, 0x7a, 0x4c, 0x0a, 0xfa, 0x0a, + 0x56, 0x7a, 0x4d, 0x0a, 0x31, 0x14, 0x02, 0x40, 0x13, 0x32, 0x32, 0x13, 0xfd, 0xc0, 0x14, 0x31, 0x00, 0x01, 0xff, + 0x64, 0xff, 0x42, 0x01, 0x1a, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x28, 0x40, 0x25, 0x03, 0x01, 0x01, 0x02, 0x02, 0x01, + 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, 0x00, 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, 0x01, + 0x00, 0x0b, 0x0a, 0x07, 0x05, 0x00, 0x0e, 0x01, 0x0e, 0x04, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x27, 0x37, 0x16, 0x16, + 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x50, 0x32, 0x1a, 0x03, 0x0f, 0x24, 0x14, 0x2c, 0x44, 0x0d, + 0x96, 0x59, 0x97, 0x16, 0x6d, 0xbe, 0x0c, 0x4d, 0x04, 0x06, 0x38, 0x40, 0x02, 0xc1, 0xfd, 0x35, 0x65, 0x58, 0x00, + 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x02, 0x8b, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x25, 0x40, 0x22, 0x0a, 0x07, 0x03, + 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x12, 0x13, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x37, 0x01, + 0x33, 0x01, 0x13, 0x23, 0x03, 0x07, 0x03, 0x29, 0x97, 0x59, 0x4a, 0x3e, 0x01, 0x12, 0x6c, 0xfe, 0xca, 0xa9, 0x62, + 0x8b, 0x53, 0x3c, 0x02, 0xca, 0xfe, 0xa5, 0x42, 0x01, 0x19, 0xfe, 0xc6, 0xfe, 0x70, 0x01, 0x5a, 0x3d, 0xfe, 0xe3, + 0x00, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x01, 0xa4, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, + 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x21, 0x07, 0x29, 0x97, 0x59, 0x87, 0x01, + 0x12, 0x11, 0x02, 0xca, 0xfd, 0x86, 0x50, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x03, 0x4c, 0x02, 0xca, 0x00, + 0x16, 0x00, 0x27, 0x40, 0x24, 0x10, 0x0c, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, + 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x16, 0x00, 0x16, 0x16, 0x11, 0x13, 0x11, + 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x01, 0x33, 0x03, 0x23, 0x13, 0x36, 0x36, 0x37, 0x23, 0x01, + 0x23, 0x03, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x28, 0x97, 0x7e, 0x45, 0x04, 0x01, 0x3d, 0x89, 0x94, 0x5a, 0x5a, 0x0e, + 0x19, 0x09, 0x02, 0xfe, 0xa8, 0x47, 0x4c, 0x04, 0x02, 0x0a, 0x0d, 0x07, 0x5b, 0x02, 0xca, 0xfd, 0xb9, 0x02, 0x47, + 0xfd, 0x36, 0x01, 0xa8, 0x41, 0x6a, 0x20, 0xfd, 0x8d, 0x02, 0x72, 0x14, 0x43, 0x4b, 0x23, 0xfe, 0x53, 0x00, 0x00, + 0x01, 0x00, 0x28, 0x00, 0x00, 0x02, 0xc8, 0x02, 0xca, 0x00, 0x12, 0x00, 0x24, 0x40, 0x21, 0x0c, 0x03, 0x02, 0x02, + 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, + 0x00, 0x12, 0x00, 0x12, 0x11, 0x16, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x36, 0x36, 0x37, + 0x13, 0x33, 0x03, 0x23, 0x03, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x28, 0x97, 0x5f, 0xdb, 0x03, 0x05, 0x13, 0x0b, 0x54, + 0x55, 0x97, 0x5f, 0xdd, 0x03, 0x02, 0x0b, 0x0f, 0x08, 0x52, 0x02, 0xca, 0xfd, 0xb2, 0x24, 0x6f, 0x32, 0x01, 0x89, + 0xfd, 0x36, 0x02, 0x50, 0x15, 0x44, 0x4e, 0x25, 0xfe, 0x7c, 0x00, 0x02, 0x00, 0x48, 0xff, 0xf6, 0x02, 0xb2, 0x02, + 0xd5, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, + 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x11, 0x10, 0x01, 0x00, 0x19, 0x17, + 0x10, 0x1f, 0x11, 0x1f, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, + 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, + 0x02, 0x15, 0x14, 0x16, 0x01, 0x51, 0x80, 0x89, 0x31, 0x5e, 0x86, 0x54, 0x7a, 0x87, 0x2d, 0x59, 0x84, 0x54, 0x3c, + 0x5e, 0x42, 0x23, 0x5a, 0x4e, 0x3c, 0x60, 0x44, 0x24, 0x5c, 0x0a, 0x95, 0x80, 0x5c, 0xa6, 0x7f, 0x49, 0x96, 0x83, + 0x5d, 0xa4, 0x7d, 0x48, 0x4f, 0x3c, 0x69, 0x88, 0x4c, 0x5f, 0x69, 0x3b, 0x67, 0x89, 0x4e, 0x5e, 0x6a, 0x00, 0x02, + 0x00, 0x29, 0x00, 0x00, 0x02, 0x37, 0x02, 0xca, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x30, 0x40, 0x2d, 0x06, 0x01, 0x03, + 0x00, 0x01, 0x02, 0x03, 0x01, 0x69, 0x00, 0x04, 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, + 0x02, 0x6b, 0x02, 0x4e, 0x0c, 0x0b, 0x00, 0x00, 0x12, 0x10, 0x0b, 0x13, 0x0c, 0x13, 0x00, 0x0a, 0x00, 0x0a, 0x24, + 0x21, 0x07, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x23, 0x03, 0x13, 0x32, 0x36, + 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0xa1, 0x74, 0x62, 0xa0, 0x9a, 0x40, 0x3b, 0x89, 0x60, 0x71, 0x43, + 0x44, 0x4c, 0x3c, 0x02, 0xca, 0x67, 0x53, 0x79, 0x80, 0xfe, 0xe9, 0x01, 0x62, 0x53, 0x58, 0x3b, 0x35, 0xfe, 0xe5, + 0x00, 0x02, 0x00, 0x48, 0xff, 0x56, 0x02, 0xb2, 0x02, 0xd5, 0x00, 0x14, 0x00, 0x24, 0x00, 0x32, 0x40, 0x2f, 0x12, + 0x01, 0x00, 0x03, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x02, 0x86, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, + 0x4d, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x16, 0x15, 0x1e, 0x1c, 0x15, 0x24, + 0x16, 0x24, 0x17, 0x26, 0x22, 0x06, 0x0d, 0x19, 0x2b, 0x05, 0x06, 0x22, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x17, 0x23, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x61, 0x04, 0x08, 0x04, 0x80, 0x89, 0x31, 0x5e, 0x86, 0x54, 0x7a, 0x87, 0x3a, + 0x6f, 0x50, 0x86, 0x72, 0x79, 0x3d, 0x5f, 0x41, 0x22, 0x5a, 0x4e, 0x3c, 0x60, 0x44, 0x24, 0x5c, 0x09, 0x01, 0x95, + 0x80, 0x5c, 0xa6, 0x7f, 0x49, 0x96, 0x83, 0x67, 0xb3, 0x80, 0x1b, 0xb1, 0xef, 0x3c, 0x69, 0x88, 0x4c, 0x5f, 0x69, + 0x3b, 0x67, 0x89, 0x4e, 0x5e, 0x6a, 0x00, 0x02, 0x00, 0x29, 0x00, 0x00, 0x02, 0x39, 0x02, 0xca, 0x00, 0x0c, 0x00, + 0x15, 0x00, 0x38, 0x40, 0x35, 0x07, 0x01, 0x02, 0x04, 0x01, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, + 0x67, 0x00, 0x05, 0x05, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, + 0x0e, 0x0d, 0x00, 0x00, 0x14, 0x12, 0x0d, 0x15, 0x0e, 0x15, 0x00, 0x0c, 0x00, 0x0c, 0x11, 0x15, 0x21, 0x08, 0x0d, + 0x19, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x15, 0x14, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x03, 0x13, 0x32, 0x36, 0x35, + 0x34, 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0x9d, 0xdc, 0x51, 0x61, 0x76, 0x62, 0x66, 0x75, 0x3e, 0x9c, 0x64, 0x5b, + 0x44, 0x44, 0x4c, 0x39, 0x02, 0xca, 0xb5, 0x4d, 0x72, 0x1b, 0xfe, 0xc5, 0x01, 0x27, 0xfe, 0xd9, 0x01, 0x73, 0x57, + 0x45, 0x3d, 0x30, 0xfe, 0xf7, 0x00, 0x01, 0x00, 0x13, 0xff, 0xf6, 0x02, 0x07, 0x02, 0xd4, 0x00, 0x2a, 0x00, 0x37, + 0x40, 0x34, 0x19, 0x01, 0x03, 0x02, 0x1a, 0x04, 0x02, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, + 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, + 0x4e, 0x01, 0x00, 0x1e, 0x1c, 0x17, 0x15, 0x08, 0x06, 0x00, 0x2a, 0x01, 0x2a, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, + 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x15, 0x14, + 0x06, 0xb9, 0x34, 0x4f, 0x23, 0x1e, 0x53, 0x36, 0x2d, 0x4c, 0x2e, 0x35, 0x41, 0x26, 0x3b, 0x21, 0x40, 0x6b, 0x40, + 0x38, 0x55, 0x26, 0x22, 0x1a, 0x4e, 0x29, 0x3d, 0x4f, 0x16, 0x2e, 0x22, 0x2b, 0x41, 0x25, 0x8f, 0x0a, 0x10, 0x10, + 0x58, 0x10, 0x1a, 0x1c, 0x3a, 0x2e, 0x28, 0x39, 0x25, 0x17, 0x31, 0x41, 0x2e, 0x42, 0x5d, 0x30, 0x16, 0x14, 0x4c, + 0x0e, 0x19, 0x40, 0x3a, 0x1e, 0x29, 0x21, 0x15, 0x1a, 0x32, 0x42, 0x31, 0x6b, 0x6e, 0x00, 0x01, 0x00, 0x5a, 0x00, + 0x00, 0x02, 0x4d, 0x02, 0xca, 0x00, 0x07, 0x00, 0x21, 0x40, 0x1e, 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, + 0x01, 0x6a, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, + 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x23, 0x37, 0x21, 0x07, 0x23, 0x03, 0x98, 0x86, 0xc4, 0x11, 0x01, 0xe2, 0x10, + 0xc4, 0x87, 0x02, 0x7b, 0x4f, 0x4f, 0xfd, 0x85, 0x00, 0x01, 0x00, 0x4f, 0xff, 0xf6, 0x02, 0xb0, 0x02, 0xca, 0x00, + 0x18, 0x00, 0x24, 0x40, 0x21, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x01, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x14, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x00, 0x18, 0x01, 0x18, 0x05, 0x0d, 0x16, + 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x13, 0x33, 0x03, 0x0e, 0x02, 0x01, 0x2c, 0x70, 0x6d, 0x06, 0x06, 0x5c, 0x59, 0x5d, 0x05, 0x06, 0x45, 0x44, + 0x59, 0x57, 0x13, 0x63, 0x59, 0x64, 0x10, 0x45, 0x74, 0x0a, 0x67, 0x5f, 0x11, 0x32, 0x1c, 0x01, 0xaf, 0xfe, 0x4c, + 0x17, 0x32, 0x10, 0x38, 0x40, 0x5c, 0x59, 0x01, 0xd0, 0xfe, 0x29, 0x4e, 0x72, 0x3d, 0x00, 0x01, 0x00, 0x5c, 0x00, + 0x00, 0x02, 0x84, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, + 0x00, 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0d, 0x19, 0x11, + 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x16, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, 0xa9, + 0x4d, 0x58, 0x2d, 0x05, 0x05, 0x01, 0x02, 0x0f, 0x26, 0x18, 0xe8, 0x63, 0xfe, 0x84, 0x02, 0xca, 0xfe, 0x3c, 0x29, + 0x54, 0x24, 0x24, 0x4f, 0x2f, 0x01, 0xc3, 0xfd, 0x36, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x00, 0x03, 0xaf, 0x02, 0xca, + 0x00, 0x21, 0x00, 0x27, 0x40, 0x24, 0x1c, 0x10, 0x06, 0x03, 0x03, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x02, 0x00, 0x00, + 0x6a, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x21, 0x11, 0x19, 0x19, + 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x13, + 0x16, 0x16, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, 0x23, 0x03, 0x26, 0x26, 0x35, 0x23, 0x06, 0x06, 0x07, + 0x03, 0x89, 0x1e, 0x58, 0x0e, 0x02, 0x04, 0x02, 0x03, 0x0e, 0x28, 0x15, 0xc4, 0x5b, 0x14, 0x03, 0x02, 0x01, 0x03, + 0x0e, 0x1f, 0x13, 0xbb, 0x5f, 0xfe, 0xbc, 0x5b, 0x16, 0x02, 0x02, 0x03, 0x0a, 0x1a, 0x17, 0xd3, 0x02, 0xca, 0xfe, + 0x4d, 0x29, 0x58, 0x28, 0x27, 0x65, 0x2c, 0x01, 0xa4, 0xfe, 0x5e, 0x2f, 0x66, 0x25, 0x26, 0x5a, 0x2c, 0x01, 0xb0, + 0xfd, 0x36, 0x01, 0xcc, 0x21, 0x4b, 0x1f, 0x1e, 0x3e, 0x32, 0xfe, 0x37, 0x00, 0x00, 0x01, 0xff, 0xcc, 0x00, 0x00, + 0x02, 0x61, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, 0x04, 0x02, 0x00, 0x01, 0x4c, + 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, + 0x0b, 0x12, 0x12, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x03, 0x33, 0x13, 0x13, 0x33, 0x01, 0x13, 0x23, 0x03, + 0x03, 0x34, 0x01, 0x23, 0x7f, 0x5a, 0x61, 0xd4, 0x62, 0xfe, 0xf2, 0x87, 0x5e, 0x66, 0xe8, 0x01, 0x7a, 0x01, 0x50, + 0xfe, 0xef, 0x01, 0x11, 0xfe, 0xac, 0xfe, 0x8a, 0x01, 0x35, 0xfe, 0xcb, 0x00, 0x01, 0x00, 0x5c, 0x00, 0x00, 0x02, + 0x59, 0x02, 0xca, 0x00, 0x08, 0x00, 0x22, 0x40, 0x1f, 0x04, 0x01, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, + 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x12, 0x12, 0x04, + 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x03, 0x33, 0x13, 0x13, 0x33, 0x01, 0x03, 0x96, 0x3a, 0x74, 0x59, 0x55, 0xea, 0x65, + 0xfe, 0xce, 0x37, 0x01, 0x0c, 0x01, 0xbe, 0xfe, 0x9a, 0x01, 0x66, 0xfe, 0x3f, 0xfe, 0xf7, 0x00, 0x00, 0x01, 0xff, + 0xf6, 0x00, 0x00, 0x02, 0x3d, 0x02, 0xca, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, + 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x01, 0x21, 0x37, 0x21, 0x07, 0x01, 0x21, + 0x07, 0x0a, 0x0e, 0x01, 0xbd, 0xfe, 0xc5, 0x11, 0x01, 0xa6, 0x0d, 0xfe, 0x43, 0x01, 0x4f, 0x10, 0x46, 0x02, 0x34, + 0x50, 0x47, 0xfd, 0xcd, 0x50, 0x00, 0x01, 0xff, 0xf7, 0xff, 0x62, 0x01, 0x72, 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, + 0x40, 0x1f, 0x00, 0x02, 0x04, 0x01, 0x03, 0x02, 0x03, 0x63, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, + 0x01, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, + 0x23, 0x03, 0x33, 0x07, 0x09, 0xba, 0xc1, 0x10, 0x6e, 0x9a, 0x6e, 0x10, 0x9e, 0x03, 0x68, 0x48, 0xfd, 0x28, 0x48, + 0x00, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x00, 0x01, 0x26, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, + 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, + 0x17, 0x2b, 0x33, 0x03, 0x33, 0x13, 0xd6, 0x6a, 0x50, 0x6a, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x00, 0x01, 0xff, 0xb8, + 0xff, 0x62, 0x01, 0x32, 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x00, 0x04, 0x01, 0x03, 0x00, 0x03, + 0x63, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, + 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x07, 0x37, 0x33, 0x13, 0x23, 0x37, 0x33, 0x03, 0x48, 0x0f, 0x6e, 0x9a, 0x6e, + 0x10, 0xc1, 0xba, 0x9e, 0x48, 0x02, 0xd8, 0x48, 0xfc, 0x98, 0x00, 0x00, 0x01, 0x00, 0x26, 0x01, 0x0b, 0x02, 0x16, + 0x02, 0xcf, 0x00, 0x06, 0x00, 0x27, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, + 0x00, 0x01, 0x00, 0x85, 0x03, 0x02, 0x02, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, + 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x13, 0x13, 0x33, 0x13, 0x23, 0x03, 0x03, 0x26, 0xd4, 0x32, 0xea, 0x4e, + 0xb4, 0xa0, 0x01, 0x0b, 0x01, 0xc4, 0xfe, 0x3c, 0x01, 0x67, 0xfe, 0x99, 0x00, 0x00, 0x01, 0xff, 0xa4, 0xff, 0x62, + 0x01, 0x40, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, + 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x07, 0x37, 0x21, 0x07, 0x5c, 0x0f, 0x01, 0x8d, 0x0f, 0x9e, 0x44, + 0x44, 0x00, 0x01, 0x00, 0x92, 0x02, 0x5e, 0x01, 0x36, 0x02, 0xfe, 0x00, 0x0a, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, + 0x40, 0x1b, 0x09, 0x04, 0x02, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x76, + 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x2e, 0x02, 0x27, + 0x35, 0x33, 0x16, 0x16, 0x17, 0x15, 0x01, 0x00, 0x13, 0x2b, 0x26, 0x0a, 0x5e, 0x0b, 0x27, 0x14, 0x02, 0x5e, 0x13, + 0x36, 0x38, 0x15, 0x0a, 0x25, 0x4d, 0x22, 0x0c, 0x00, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf6, 0x02, 0x26, 0x02, 0x22, + 0x00, 0x14, 0x00, 0x26, 0x00, 0x67, 0xb6, 0x11, 0x0b, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x19, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x16, 0x15, 0x01, 0x00, 0x20, 0x1e, 0x15, 0x26, 0x16, 0x26, + 0x10, 0x0f, 0x0e, 0x0d, 0x09, 0x07, 0x00, 0x14, 0x01, 0x14, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, + 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0x27, 0x32, 0x36, 0x36, + 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0xc1, 0x40, 0x51, 0x27, 0x46, 0x60, + 0x3a, 0x35, 0x42, 0x10, 0x05, 0x20, 0x43, 0x72, 0x46, 0x0d, 0x04, 0x22, 0x5c, 0x1b, 0x25, 0x47, 0x3a, 0x0f, 0x08, + 0x05, 0x34, 0x2c, 0x27, 0x42, 0x32, 0x1b, 0x2c, 0x0a, 0x5d, 0x5a, 0x4b, 0x87, 0x67, 0x3c, 0x38, 0x25, 0x53, 0xfd, + 0xe8, 0x63, 0x2c, 0x41, 0x49, 0x36, 0x5c, 0x39, 0x1d, 0x31, 0x15, 0x2f, 0x3c, 0x31, 0x55, 0x6c, 0x3b, 0x36, 0x36, + 0x00, 0x00, 0x02, 0x00, 0x1c, 0xff, 0xf6, 0x02, 0x12, 0x02, 0xf8, 0x00, 0x18, 0x00, 0x27, 0x00, 0x94, 0xb5, 0x03, + 0x01, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, + 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x62, 0x01, 0x06, 0x02, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, + 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x62, 0x06, + 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x03, 0x02, 0x85, 0x00, 0x05, 0x05, 0x03, 0x61, + 0x00, 0x03, 0x03, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x62, 0x06, 0x01, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x17, 0x1a, 0x19, 0x01, 0x00, 0x21, 0x1f, 0x19, 0x27, 0x1a, 0x27, 0x12, + 0x10, 0x08, 0x07, 0x06, 0x05, 0x00, 0x18, 0x01, 0x18, 0x08, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x27, 0x23, 0x07, + 0x23, 0x13, 0x33, 0x07, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, + 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x0d, 0x36, 0x43, 0x10, 0x05, 0x21, 0x42, + 0xa1, 0x58, 0x26, 0x07, 0x11, 0x0c, 0x01, 0x04, 0x24, 0x55, 0x38, 0x42, 0x51, 0x24, 0x44, 0x60, 0x44, 0x28, 0x42, + 0x2f, 0x19, 0x55, 0x21, 0x45, 0x3a, 0x23, 0x32, 0x0a, 0x37, 0x25, 0x52, 0x02, 0xf8, 0xb4, 0x22, 0x41, 0x2b, 0x02, + 0x2c, 0x41, 0x5c, 0x5a, 0x49, 0x86, 0x69, 0x3d, 0x49, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x31, 0x55, 0x6c, 0x3b, 0x30, + 0x3c, 0x00, 0x01, 0x00, 0x30, 0xff, 0xf6, 0x01, 0xcd, 0x02, 0x22, 0x00, 0x1c, 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, + 0x02, 0x01, 0x19, 0x0c, 0x02, 0x03, 0x02, 0x1a, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x17, + 0x15, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1c, 0x01, 0x1c, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, + 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, + 0x15, 0x06, 0x06, 0xf7, 0x59, 0x6e, 0x27, 0x49, 0x68, 0x40, 0x23, 0x46, 0x1c, 0x19, 0x14, 0x37, 0x20, 0x39, 0x56, + 0x30, 0x3f, 0x37, 0x23, 0x3f, 0x1f, 0x1c, 0x45, 0x0a, 0x64, 0x64, 0x48, 0x81, 0x62, 0x39, 0x0e, 0x0c, 0x49, 0x09, + 0x10, 0x4d, 0x80, 0x4c, 0x3d, 0x43, 0x14, 0x0d, 0x4a, 0x0e, 0x12, 0x00, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf6, 0x02, + 0x55, 0x02, 0xf8, 0x00, 0x17, 0x00, 0x26, 0x00, 0x95, 0xb6, 0x14, 0x0b, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, + 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, + 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x29, + 0x50, 0x58, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, + 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, + 0x40, 0x21, 0x00, 0x02, 0x01, 0x02, 0x85, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, + 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x59, 0x40, + 0x17, 0x19, 0x18, 0x01, 0x00, 0x21, 0x1f, 0x18, 0x26, 0x19, 0x26, 0x13, 0x12, 0x11, 0x10, 0x09, 0x07, 0x00, 0x17, + 0x01, 0x17, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x36, + 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x0e, 0x02, 0x15, 0x14, 0xc1, 0x40, 0x51, 0x24, 0x45, 0x61, 0x3d, 0x36, 0x41, 0x10, 0x05, 0x05, 0x09, 0x08, 0x25, + 0x57, 0xa1, 0x48, 0x0b, 0x04, 0x24, 0x56, 0x1a, 0x21, 0x44, 0x3a, 0x23, 0x2f, 0x35, 0x28, 0x41, 0x30, 0x1a, 0x0a, + 0x5c, 0x5b, 0x4a, 0x85, 0x69, 0x3c, 0x37, 0x25, 0x22, 0x3e, 0x24, 0xaf, 0xfd, 0x08, 0x63, 0x2d, 0x40, 0x49, 0x31, + 0x54, 0x6c, 0x3c, 0x30, 0x3c, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf6, 0x01, 0xd5, 0x02, + 0x22, 0x00, 0x1c, 0x00, 0x27, 0x00, 0x43, 0x40, 0x40, 0x19, 0x01, 0x03, 0x02, 0x1a, 0x01, 0x00, 0x03, 0x02, 0x4c, + 0x07, 0x01, 0x04, 0x00, 0x02, 0x03, 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, + 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1e, 0x1d, 0x01, 0x00, 0x25, 0x23, 0x1d, + 0x27, 0x1e, 0x27, 0x17, 0x15, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1c, 0x01, 0x1c, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, + 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x23, 0x06, 0x06, 0x15, 0x14, 0x16, + 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x03, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0xf2, + 0x5d, 0x65, 0x25, 0x46, 0x63, 0x3e, 0x4c, 0x4d, 0x41, 0x8a, 0x6e, 0x11, 0x01, 0x01, 0x3c, 0x3d, 0x26, 0x44, 0x28, + 0x26, 0x49, 0x86, 0x3c, 0x66, 0x3e, 0x23, 0x25, 0x30, 0x59, 0x16, 0x0a, 0x6d, 0x5d, 0x40, 0x7d, 0x67, 0x3e, 0x42, + 0x3b, 0x34, 0x56, 0x33, 0x09, 0x14, 0x08, 0x3d, 0x47, 0x16, 0x13, 0x4b, 0x11, 0x16, 0x01, 0x39, 0x15, 0x31, 0x29, + 0x1a, 0x21, 0x59, 0x51, 0x00, 0x01, 0xff, 0x90, 0xff, 0x10, 0x01, 0xbb, 0x02, 0xfd, 0x00, 0x24, 0x00, 0x77, 0x40, + 0x12, 0x16, 0x01, 0x04, 0x03, 0x17, 0x01, 0x05, 0x04, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, + 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x21, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, + 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, + 0x00, 0x4e, 0x1b, 0x40, 0x1f, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x69, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, + 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, + 0x15, 0x01, 0x00, 0x21, 0x20, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x24, 0x01, 0x24, + 0x08, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, + 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, + 0x06, 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x24, 0x28, 0x0c, 0x6e, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, + 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0x73, 0x0d, 0x73, 0x70, 0x12, 0x4c, 0xf0, + 0x06, 0x04, 0x4a, 0x04, 0x07, 0x3b, 0x37, 0x02, 0x0a, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, + 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, 0x5e, 0x00, 0x00, 0x02, 0x00, 0x19, 0xff, 0x10, 0x02, 0x27, 0x02, + 0x22, 0x00, 0x23, 0x00, 0x32, 0x00, 0x80, 0x40, 0x0f, 0x1d, 0x0e, 0x02, 0x05, 0x06, 0x04, 0x01, 0x01, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x00, 0x06, 0x06, 0x03, 0x61, 0x04, 0x01, + 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x00, 0x01, 0x01, 0x00, + 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x06, 0x06, + 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x00, + 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, 0x19, 0x25, 0x24, 0x01, 0x00, 0x2d, + 0x2b, 0x24, 0x32, 0x25, 0x32, 0x20, 0x1f, 0x1b, 0x19, 0x13, 0x11, 0x08, 0x06, 0x00, 0x23, 0x01, 0x23, 0x09, 0x0d, + 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, 0x37, 0x23, 0x06, + 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x06, 0x06, 0x03, + 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xba, 0x31, 0x53, 0x1d, 0x1a, 0x59, 0x2b, + 0x3e, 0x50, 0x10, 0x09, 0x05, 0x0f, 0x05, 0x04, 0x22, 0x57, 0x38, 0x41, 0x51, 0x24, 0x45, 0x61, 0x3d, 0x36, 0x42, + 0x10, 0x04, 0x21, 0x43, 0x7a, 0x18, 0x7b, 0x3b, 0x22, 0x44, 0x39, 0x22, 0x2d, 0x35, 0x28, 0x42, 0x30, 0x1a, 0xf0, + 0x13, 0x0f, 0x51, 0x10, 0x1a, 0x3c, 0x46, 0x26, 0x17, 0x38, 0x13, 0x2c, 0x41, 0x5d, 0x5a, 0x49, 0x86, 0x69, 0x3d, + 0x38, 0x25, 0x53, 0xfd, 0xc9, 0x71, 0x60, 0x01, 0x2f, 0x32, 0x55, 0x6c, 0x3a, 0x30, 0x3c, 0x33, 0x56, 0x6c, 0x38, + 0x6c, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x02, 0x0b, 0x02, 0xf8, 0x00, 0x1e, 0x00, 0x50, 0xb5, 0x06, 0x01, 0x02, + 0x03, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x17, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x03, 0x03, 0x01, + 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x00, + 0x01, 0x00, 0x85, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, + 0x02, 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1e, 0x25, 0x16, 0x28, 0x11, 0x06, 0x0d, 0x1a, 0x2b, + 0x33, 0x13, 0x33, 0x07, 0x06, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x03, 0x23, + 0x13, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x1c, 0xa1, 0x58, 0x2b, 0x06, 0x12, 0x08, 0x05, + 0x13, 0x34, 0x43, 0x2b, 0x3e, 0x49, 0x06, 0x05, 0x46, 0x58, 0x47, 0x09, 0x21, 0x25, 0x22, 0x4f, 0x43, 0x13, 0x31, + 0x02, 0xf8, 0xc5, 0x1e, 0x41, 0x20, 0x19, 0x32, 0x22, 0x45, 0x44, 0x13, 0x28, 0x17, 0xfe, 0xba, 0x01, 0x50, 0x2d, + 0x15, 0x21, 0x25, 0x2f, 0x6a, 0x58, 0xe7, 0x00, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x0e, 0x02, 0xe0, 0x00, + 0x0a, 0x00, 0x0e, 0x00, 0x4d, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x17, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x15, + 0x00, 0x01, 0x04, 0x01, 0x00, 0x02, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6b, + 0x03, 0x4e, 0x59, 0x40, 0x13, 0x0b, 0x0b, 0x01, 0x00, 0x0b, 0x0e, 0x0b, 0x0e, 0x0d, 0x0c, 0x07, 0x05, 0x00, 0x0a, + 0x01, 0x0a, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x15, 0x14, 0x06, 0x03, 0x13, + 0x33, 0x03, 0xd5, 0x15, 0x1b, 0x1f, 0x1c, 0x2e, 0x24, 0xce, 0x72, 0x58, 0x72, 0x02, 0x71, 0x19, 0x16, 0x1a, 0x26, + 0x2d, 0x1f, 0x23, 0xfd, 0x8f, 0x02, 0x18, 0xfd, 0xe8, 0x00, 0x02, 0xff, 0x82, 0xff, 0x10, 0x01, 0x0d, 0x02, 0xe0, + 0x00, 0x0a, 0x00, 0x18, 0x00, 0x65, 0x40, 0x0a, 0x0e, 0x01, 0x03, 0x04, 0x0d, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x4b, + 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x1c, 0x05, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x04, + 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x06, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x1a, 0x00, + 0x01, 0x05, 0x01, 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x06, + 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x15, 0x0c, 0x0b, 0x01, 0x00, 0x15, 0x14, 0x12, 0x10, 0x0b, 0x18, + 0x0c, 0x18, 0x07, 0x05, 0x00, 0x0a, 0x01, 0x0a, 0x07, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, + 0x32, 0x15, 0x14, 0x06, 0x01, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0xd4, + 0x14, 0x1b, 0x1f, 0x1c, 0x2d, 0x24, 0xfe, 0xd7, 0x25, 0x19, 0x0c, 0x1e, 0x10, 0x3d, 0x15, 0x80, 0x57, 0x82, 0x10, + 0x49, 0x02, 0x71, 0x19, 0x16, 0x1a, 0x26, 0x2d, 0x1f, 0x23, 0xfc, 0x9f, 0x0a, 0x4a, 0x04, 0x07, 0x62, 0x02, 0x5d, + 0xfd, 0x9b, 0x4b, 0x58, 0x00, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x02, 0x0d, 0x02, 0xf8, 0x00, 0x0f, 0x00, 0x47, + 0xb7, 0x0d, 0x0a, 0x06, 0x03, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x12, 0x00, 0x00, 0x00, + 0x6c, 0x4d, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x12, 0x00, + 0x00, 0x01, 0x00, 0x85, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, + 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x12, 0x16, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x06, + 0x06, 0x07, 0x33, 0x13, 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x07, 0x1b, 0xa1, 0x59, 0x41, 0x11, 0x19, 0x05, 0x02, + 0xfe, 0x68, 0xe6, 0x8f, 0x61, 0x71, 0x48, 0x28, 0x02, 0xf8, 0xfe, 0xd2, 0x50, 0x57, 0x0e, 0x01, 0x03, 0xe6, 0xfe, + 0xce, 0xfb, 0x39, 0xc2, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x15, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x30, 0x4b, + 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, + 0x40, 0x0c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x0a, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x1b, 0xa2, 0x58, 0xa2, 0x02, 0xf8, + 0xfd, 0x08, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x03, 0x33, 0x02, 0x22, 0x00, 0x30, 0x00, 0x56, 0xb6, 0x0b, 0x03, + 0x02, 0x03, 0x04, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x02, + 0x01, 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x08, 0x07, 0x05, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x1a, 0x00, + 0x00, 0x00, 0x6d, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x08, 0x07, 0x05, + 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x59, 0x40, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x25, 0x14, 0x26, 0x16, + 0x26, 0x25, 0x11, 0x09, 0x0d, 0x1d, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, + 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x03, 0x23, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x06, 0x06, 0x07, 0x07, 0x23, 0x13, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x1c, 0x72, 0x48, + 0x0b, 0x05, 0x12, 0x31, 0x41, 0x29, 0x37, 0x3b, 0x06, 0x04, 0x14, 0x37, 0x44, 0x29, 0x3e, 0x44, 0x06, 0x05, 0x45, + 0x59, 0x48, 0x05, 0x04, 0x21, 0x23, 0x20, 0x49, 0x3f, 0x11, 0x33, 0x58, 0x47, 0x09, 0x1e, 0x23, 0x20, 0x4a, 0x40, + 0x13, 0x31, 0x02, 0x18, 0x63, 0x19, 0x32, 0x22, 0x3f, 0x38, 0x1e, 0x36, 0x23, 0x44, 0x40, 0x18, 0x29, 0x17, 0xfe, + 0xba, 0x01, 0x50, 0x17, 0x20, 0x0f, 0x1e, 0x24, 0x30, 0x65, 0x51, 0xf2, 0x01, 0x50, 0x2d, 0x15, 0x21, 0x25, 0x2f, + 0x6a, 0x58, 0xe7, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x02, 0x0e, 0x02, 0x25, 0x00, 0x1b, 0x00, 0x4c, 0xb5, + 0x03, 0x01, 0x02, 0x03, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x00, 0x03, 0x03, 0x00, 0x61, 0x01, + 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x00, 0x00, + 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, + 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x1b, 0x25, 0x16, 0x25, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, + 0x13, 0x33, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x03, 0x23, 0x13, 0x36, 0x36, 0x35, + 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x18, 0x73, 0x4e, 0x0b, 0x01, 0x13, 0x33, 0x44, 0x2b, 0x41, 0x49, 0x07, + 0x04, 0x47, 0x5e, 0x48, 0x05, 0x05, 0x44, 0x21, 0x4d, 0x43, 0x13, 0x32, 0x02, 0x1b, 0x63, 0x19, 0x32, 0x22, 0x47, + 0x40, 0x17, 0x30, 0x12, 0xfe, 0xbb, 0x01, 0x51, 0x17, 0x1f, 0x0e, 0x40, 0x2e, 0x68, 0x58, 0xe7, 0x00, 0x02, 0x00, + 0x30, 0xff, 0xf8, 0x02, 0x04, 0x02, 0x1f, 0x00, 0x0f, 0x00, 0x1e, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, + 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x11, 0x10, 0x01, 0x00, 0x19, 0x17, 0x10, 0x1e, 0x11, 0x1e, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, + 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, + 0x35, 0x34, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0xf8, 0x5d, 0x6b, 0x22, 0x43, 0x65, 0x42, 0x5e, + 0x6a, 0x22, 0x43, 0x64, 0x3e, 0x30, 0x4e, 0x2f, 0x15, 0x30, 0x28, 0x37, 0x51, 0x2c, 0x3d, 0x08, 0x6f, 0x5f, 0x3e, + 0x7a, 0x64, 0x3d, 0x6f, 0x60, 0x3d, 0x7a, 0x64, 0x3d, 0x49, 0x43, 0x7e, 0x58, 0x1e, 0x39, 0x25, 0x4b, 0x7d, 0x4b, + 0x3e, 0x44, 0x00, 0x02, 0xff, 0xea, 0xff, 0x10, 0x02, 0x12, 0x02, 0x21, 0x00, 0x17, 0x00, 0x26, 0x00, 0x68, 0xb6, + 0x12, 0x03, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x1b, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x05, 0x05, 0x00, 0x61, + 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, + 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, 0x03, 0x03, + 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x14, 0x19, 0x18, 0x00, 0x00, 0x20, 0x1e, 0x18, 0x26, 0x19, 0x26, 0x00, 0x17, 0x00, + 0x17, 0x26, 0x24, 0x11, 0x08, 0x0d, 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x07, 0x13, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, + 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x16, 0xa4, 0x48, 0x0c, 0x04, 0x23, 0x58, 0x38, 0x41, 0x50, 0x24, 0x44, 0x61, + 0x3c, 0x36, 0x42, 0x11, 0x05, 0x01, 0x08, 0x04, 0x31, 0xc5, 0x28, 0x42, 0x2f, 0x19, 0x55, 0x21, 0x45, 0x3a, 0x23, + 0x32, 0xf0, 0x03, 0x08, 0x64, 0x2c, 0x41, 0x5c, 0x5b, 0x49, 0x86, 0x69, 0x3c, 0x37, 0x25, 0x10, 0x39, 0x12, 0xe7, + 0x01, 0x2f, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x31, 0x54, 0x6c, 0x3c, 0x30, 0x3c, 0x00, 0x02, 0x00, 0x30, 0xff, 0x10, + 0x02, 0x26, 0x02, 0x22, 0x00, 0x17, 0x00, 0x26, 0x00, 0x61, 0xb6, 0x12, 0x03, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, + 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, + 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, + 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x19, 0x18, 0x21, 0x1f, + 0x18, 0x26, 0x19, 0x26, 0x11, 0x14, 0x26, 0x26, 0x07, 0x0d, 0x1a, 0x2b, 0x05, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, + 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x03, 0x32, 0x3e, + 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x01, 0x5a, 0x05, 0x11, 0x07, 0x04, 0x22, 0x57, 0x38, + 0x41, 0x51, 0x24, 0x45, 0x62, 0x3d, 0x35, 0x41, 0x10, 0x05, 0x21, 0x42, 0xa5, 0x57, 0x4b, 0x21, 0x44, 0x39, 0x23, + 0x2e, 0x34, 0x28, 0x42, 0x30, 0x1a, 0x0c, 0x13, 0x43, 0x19, 0x2c, 0x41, 0x5c, 0x5b, 0x49, 0x86, 0x69, 0x3d, 0x38, + 0x25, 0x53, 0xfc, 0xf8, 0x01, 0x2f, 0x32, 0x55, 0x6c, 0x3a, 0x2c, 0x40, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x00, 0x00, + 0x01, 0x00, 0x1c, 0x00, 0x00, 0x01, 0xad, 0x02, 0x22, 0x00, 0x13, 0x00, 0x63, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, + 0x0b, 0x0c, 0x03, 0x02, 0x03, 0x02, 0x01, 0x4c, 0x0b, 0x01, 0x00, 0x4a, 0x1b, 0x40, 0x0b, 0x0b, 0x01, 0x00, 0x01, + 0x0c, 0x03, 0x02, 0x03, 0x02, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x02, 0x02, 0x00, + 0x61, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x00, + 0x00, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, + 0x4e, 0x59, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x13, 0x00, 0x13, 0x24, 0x25, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, + 0x33, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x1c, 0x72, + 0x48, 0x0b, 0x05, 0x15, 0x2e, 0x3a, 0x26, 0x0e, 0x1f, 0x0d, 0x13, 0x1b, 0x18, 0x32, 0x4e, 0x34, 0x0b, 0x34, 0x02, + 0x18, 0x63, 0x1c, 0x31, 0x20, 0x03, 0x04, 0x4f, 0x06, 0x42, 0x66, 0x35, 0xf5, 0x00, 0x01, 0x00, 0x05, 0xff, 0xf6, + 0x01, 0x9c, 0x02, 0x22, 0x00, 0x26, 0x00, 0x37, 0x40, 0x34, 0x16, 0x01, 0x03, 0x02, 0x17, 0x04, 0x02, 0x01, 0x03, + 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, 0x01, + 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1b, 0x19, 0x14, 0x12, 0x08, 0x06, 0x00, 0x26, + 0x01, 0x26, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, + 0x27, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, + 0x17, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x9b, 0x31, 0x49, 0x1c, 0x1a, 0x4f, 0x2a, 0x3b, 0x3e, 0x26, 0x34, 0x39, 0x3a, + 0x63, 0x53, 0x31, 0x53, 0x1e, 0x1c, 0x1a, 0x40, 0x2c, 0x2b, 0x33, 0x23, 0x35, 0x22, 0x36, 0x1f, 0x71, 0x0a, 0x13, + 0x0f, 0x51, 0x10, 0x1b, 0x2f, 0x25, 0x1d, 0x27, 0x1d, 0x20, 0x44, 0x33, 0x44, 0x54, 0x17, 0x0e, 0x46, 0x0c, 0x15, + 0x29, 0x20, 0x1a, 0x27, 0x1d, 0x14, 0x28, 0x34, 0x26, 0x51, 0x54, 0x00, 0x00, 0x01, 0x00, 0x2c, 0xff, 0xf6, 0x01, + 0x6c, 0x02, 0x92, 0x00, 0x1c, 0x00, 0x66, 0x40, 0x0a, 0x19, 0x01, 0x05, 0x01, 0x1a, 0x01, 0x00, 0x05, 0x02, 0x4c, + 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x03, 0x03, 0x02, 0x70, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, + 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, + 0x1c, 0x00, 0x02, 0x03, 0x02, 0x85, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, + 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x13, 0x01, 0x00, 0x17, 0x15, 0x0f, 0x0e, + 0x0d, 0x0c, 0x0b, 0x0a, 0x07, 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, + 0x37, 0x13, 0x23, 0x3f, 0x02, 0x33, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x15, 0x06, 0x06, 0xb9, 0x36, 0x4a, 0x09, 0x3d, 0x53, 0x08, 0x5a, 0x3e, 0x34, 0x1b, 0x87, 0x0e, 0x86, 0x3e, + 0x03, 0x06, 0x19, 0x1c, 0x12, 0x22, 0x13, 0x0c, 0x32, 0x0a, 0x34, 0x41, 0x20, 0x27, 0x01, 0x23, 0x28, 0x26, 0x6f, + 0x7a, 0x43, 0xfe, 0xdc, 0x0d, 0x21, 0x0e, 0x17, 0x20, 0x07, 0x06, 0x43, 0x06, 0x0c, 0x00, 0x01, 0x00, 0x37, 0xff, + 0xf6, 0x02, 0x26, 0x02, 0x18, 0x00, 0x1b, 0x00, 0x50, 0xb5, 0x17, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x19, + 0x50, 0x58, 0x40, 0x13, 0x03, 0x01, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x05, 0x02, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x17, 0x03, 0x01, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x04, 0x04, 0x6b, 0x4d, 0x00, + 0x02, 0x02, 0x00, 0x62, 0x05, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, 0x16, 0x15, 0x14, + 0x13, 0x0f, 0x0d, 0x08, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, + 0x37, 0x13, 0x33, 0x03, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, + 0x0e, 0x02, 0xbd, 0x3d, 0x49, 0x07, 0x04, 0x46, 0x59, 0x48, 0x09, 0x21, 0x25, 0x22, 0x4f, 0x44, 0x13, 0x31, 0x57, + 0x72, 0x48, 0x0b, 0x05, 0x13, 0x33, 0x43, 0x0a, 0x44, 0x41, 0x17, 0x29, 0x16, 0x01, 0x47, 0xfe, 0xaf, 0x2b, 0x18, + 0x20, 0x25, 0x30, 0x6a, 0x58, 0xe7, 0xfd, 0xe8, 0x63, 0x18, 0x33, 0x22, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x00, + 0x02, 0x03, 0x02, 0x18, 0x00, 0x0f, 0x00, 0x21, 0x40, 0x1e, 0x07, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, + 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x1b, 0x11, 0x04, + 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x15, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x01, 0x6e, 0x3e, + 0x58, 0x1e, 0x03, 0x05, 0x03, 0x03, 0x0b, 0x1e, 0x1f, 0x0b, 0x9e, 0x5e, 0xfe, 0xde, 0x02, 0x18, 0xfe, 0xd6, 0x1a, + 0x46, 0x3d, 0x0e, 0x19, 0x40, 0x40, 0x15, 0x01, 0x27, 0xfd, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x39, 0x00, 0x00, 0x02, + 0xf9, 0x02, 0x18, 0x00, 0x22, 0x00, 0x27, 0x40, 0x24, 0x1d, 0x11, 0x06, 0x03, 0x03, 0x00, 0x01, 0x4c, 0x02, 0x01, + 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x22, + 0x11, 0x19, 0x1a, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, + 0x13, 0x33, 0x13, 0x16, 0x16, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0x23, 0x03, 0x26, 0x36, 0x35, 0x23, + 0x06, 0x06, 0x07, 0x03, 0x4f, 0x16, 0x56, 0x08, 0x02, 0x04, 0x02, 0x04, 0x08, 0x16, 0x19, 0x0a, 0x8d, 0x5f, 0x11, + 0x01, 0x02, 0x02, 0x04, 0x0d, 0x28, 0x18, 0x75, 0x5d, 0xf8, 0x6a, 0x0f, 0x02, 0x01, 0x04, 0x0d, 0x1b, 0x18, 0x8c, + 0x02, 0x18, 0xfe, 0xe2, 0x37, 0x59, 0x1d, 0x15, 0x39, 0x39, 0x15, 0x01, 0x2f, 0xfe, 0xe1, 0x25, 0x61, 0x26, 0x26, + 0x67, 0x37, 0x01, 0x07, 0xfd, 0xe8, 0x01, 0x22, 0x28, 0x4a, 0x2f, 0x25, 0x3f, 0x33, 0xfe, 0xd4, 0x00, 0x01, 0xff, + 0xdb, 0x00, 0x00, 0x01, 0xfe, 0x02, 0x18, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, 0x04, 0x02, + 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, + 0x00, 0x0b, 0x00, 0x0b, 0x12, 0x12, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, + 0x13, 0x23, 0x27, 0x07, 0x25, 0xe8, 0x74, 0x59, 0x53, 0x9d, 0x66, 0xdf, 0x7b, 0x59, 0x5b, 0xa5, 0x01, 0x14, 0x01, + 0x04, 0xc6, 0xc6, 0xfe, 0xf8, 0xfe, 0xf0, 0xd0, 0xd0, 0x00, 0x01, 0xff, 0xa2, 0xff, 0x10, 0x02, 0x03, 0x02, 0x18, + 0x00, 0x1c, 0x00, 0x30, 0x40, 0x2d, 0x12, 0x0b, 0x04, 0x03, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x03, + 0x01, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x01, 0x00, + 0x19, 0x18, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x05, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, + 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x15, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, + 0x01, 0x06, 0x06, 0x19, 0x18, 0x1f, 0x0e, 0x0e, 0x20, 0x12, 0x29, 0x39, 0x1a, 0x23, 0x51, 0x58, 0x23, 0x05, 0x05, + 0x03, 0x03, 0x07, 0x1b, 0x20, 0x0c, 0x9c, 0x5e, 0xfe, 0xac, 0x28, 0x59, 0xf0, 0x06, 0x04, 0x47, 0x04, 0x05, 0x32, + 0x30, 0x3e, 0x02, 0x20, 0xfe, 0xf7, 0x20, 0x4d, 0x45, 0x15, 0x10, 0x40, 0x44, 0x16, 0x01, 0x26, 0xfd, 0x8e, 0x4b, + 0x4b, 0x00, 0x01, 0xff, 0xf1, 0x00, 0x00, 0x01, 0xb7, 0x02, 0x18, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, + 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, + 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x01, 0x23, 0x37, + 0x21, 0x07, 0x01, 0x33, 0x07, 0x0f, 0x0c, 0x01, 0x4d, 0xe6, 0x0e, 0x01, 0x45, 0x0e, 0xfe, 0xb9, 0xff, 0x0d, 0x3c, + 0x01, 0x9a, 0x42, 0x47, 0xfe, 0x71, 0x42, 0x00, 0x01, 0x00, 0x0b, 0xff, 0x62, 0x01, 0x90, 0x02, 0xca, 0x00, 0x2c, + 0x00, 0x37, 0x40, 0x34, 0x1d, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, + 0x05, 0x06, 0x01, 0x00, 0x05, 0x00, 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, 0x4e, 0x01, + 0x00, 0x2b, 0x2a, 0x17, 0x16, 0x15, 0x13, 0x0e, 0x0d, 0x0c, 0x0b, 0x00, 0x2c, 0x01, 0x2c, 0x07, 0x0d, 0x16, 0x2b, + 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x23, 0x37, 0x32, 0x36, 0x37, 0x37, 0x36, + 0x36, 0x33, 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, + 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x15, 0xd9, 0x46, 0x4b, 0x06, 0x04, 0x18, 0x03, 0x04, 0x66, 0x11, 0x3a, 0x46, + 0x0a, 0x21, 0x11, 0x53, 0x53, 0x12, 0x0f, 0x2c, 0x32, 0x0b, 0x23, 0x0b, 0x39, 0x3b, 0x27, 0x24, 0x05, 0x04, 0x16, + 0x03, 0x04, 0x29, 0x22, 0x9e, 0x35, 0x39, 0x10, 0x21, 0x13, 0x69, 0x10, 0x1a, 0x0c, 0x46, 0x49, 0x2a, 0x33, 0x9d, + 0x4f, 0x3f, 0x49, 0x1e, 0x2f, 0x9c, 0x33, 0x42, 0x0a, 0x02, 0x0a, 0x37, 0x27, 0x0d, 0x22, 0x10, 0x66, 0x0d, 0x17, + 0x0a, 0x1d, 0x14, 0x49, 0x00, 0x00, 0x01, 0x01, 0x04, 0xff, 0x0f, 0x01, 0x4c, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x30, + 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6f, 0x01, 0x4e, + 0x1b, 0x40, 0x0c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x59, 0x40, 0x0a, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x05, 0x11, 0x33, 0x11, 0x01, 0x04, 0x48, 0xf1, 0x03, + 0xe9, 0xfc, 0x17, 0x00, 0x01, 0xff, 0xdb, 0xff, 0x62, 0x01, 0x59, 0x02, 0xca, 0x00, 0x2d, 0x00, 0x31, 0x40, 0x2e, + 0x07, 0x01, 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x05, 0x65, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x2c, 0x2b, 0x25, 0x24, 0x23, 0x22, + 0x18, 0x16, 0x15, 0x14, 0x10, 0x06, 0x0d, 0x17, 0x2b, 0x07, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, 0x37, 0x35, 0x26, + 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x37, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x07, 0x07, 0x06, 0x06, 0x15, 0x14, 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x0e, 0x02, 0x23, 0x23, 0x25, 0x30, 0x38, + 0x0a, 0x23, 0x0b, 0x3a, 0x3a, 0x27, 0x23, 0x05, 0x04, 0x17, 0x03, 0x04, 0x2e, 0x29, 0x0f, 0x06, 0x48, 0x4b, 0x05, + 0x05, 0x18, 0x03, 0x05, 0x66, 0x10, 0x3a, 0x45, 0x0b, 0x21, 0x0c, 0x2e, 0x4a, 0x38, 0x07, 0x55, 0x1e, 0x2f, 0x9c, + 0x33, 0x41, 0x0a, 0x03, 0x0b, 0x35, 0x27, 0x0e, 0x21, 0x10, 0x67, 0x0d, 0x17, 0x0a, 0x1d, 0x14, 0x49, 0x35, 0x39, + 0x10, 0x21, 0x13, 0x6a, 0x10, 0x19, 0x0c, 0x46, 0x49, 0x2a, 0x33, 0x9d, 0x38, 0x3e, 0x18, 0x00, 0x00, 0x01, 0x00, + 0x46, 0x01, 0x1f, 0x02, 0x1d, 0x01, 0xa2, 0x00, 0x17, 0x00, 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, + 0x02, 0x01, 0x13, 0x01, 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, 0x00, 0x02, 0x00, + 0x03, 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, + 0x03, 0x51, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, 0x22, + 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, + 0x01, 0x21, 0x24, 0x2f, 0x16, 0x1c, 0x3e, 0x18, 0x30, 0x48, 0x1d, 0x39, 0x2e, 0x24, 0x2f, 0x15, 0x1d, 0x3e, 0x18, + 0x31, 0x47, 0x1c, 0x3b, 0x01, 0x3f, 0x10, 0x0b, 0x22, 0x19, 0x4e, 0x35, 0x0c, 0x14, 0x10, 0x0b, 0x22, 0x19, 0x4d, + 0x36, 0x0d, 0x00, 0x01, 0x00, 0x47, 0x01, 0xa0, 0x01, 0x8e, 0x03, 0x55, 0x00, 0x19, 0x00, 0x32, 0x40, 0x2f, 0x0b, + 0x01, 0x00, 0x01, 0x0a, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x69, 0x00, 0x02, + 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x00, 0x00, 0x00, 0x19, + 0x00, 0x19, 0x18, 0x24, 0x27, 0x05, 0x0c, 0x19, 0x2b, 0x13, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x33, 0x07, 0x47, 0x0c, 0x81, + 0x3c, 0x38, 0x1d, 0x1c, 0x2f, 0x30, 0x1f, 0x1f, 0x43, 0x28, 0x2a, 0x32, 0x17, 0x17, 0x36, 0x2e, 0x68, 0xbf, 0x0d, + 0x01, 0xa0, 0x37, 0x6e, 0x34, 0x44, 0x27, 0x19, 0x1e, 0x27, 0x2f, 0x19, 0x19, 0x1e, 0x2f, 0x19, 0x21, 0x38, 0x3c, + 0x26, 0x57, 0x3d, 0x00, 0x01, 0x00, 0x51, 0x01, 0x99, 0x01, 0x8c, 0x03, 0x56, 0x00, 0x27, 0x00, 0x4d, 0x40, 0x4a, + 0x18, 0x01, 0x04, 0x05, 0x17, 0x01, 0x03, 0x04, 0x21, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x05, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x69, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x01, 0x00, 0x51, 0x01, 0x00, + 0x1c, 0x1a, 0x15, 0x13, 0x10, 0x0e, 0x0d, 0x0b, 0x08, 0x06, 0x00, 0x27, 0x01, 0x27, 0x07, 0x0c, 0x16, 0x2b, 0x13, + 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x35, 0x34, + 0x07, 0x06, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, + 0x06, 0xc4, 0x21, 0x3b, 0x17, 0x1a, 0x3e, 0x1d, 0x32, 0x31, 0x54, 0x2e, 0x0c, 0x2e, 0x2e, 0x38, 0x40, 0x1a, 0x2d, + 0x15, 0x1c, 0x17, 0x44, 0x2a, 0x3c, 0x3c, 0x36, 0x30, 0x23, 0x25, 0x53, 0x01, 0x99, 0x0f, 0x0c, 0x41, 0x0f, 0x14, + 0x2c, 0x25, 0x40, 0x37, 0x27, 0x22, 0x3b, 0x02, 0x01, 0x11, 0x0f, 0x30, 0x12, 0x19, 0x39, 0x2c, 0x2d, 0x37, 0x0d, + 0x04, 0x08, 0x31, 0x22, 0x3a, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x94, 0x01, 0x9f, 0x01, 0x60, 0x03, 0x4b, 0x00, 0x0c, + 0x00, 0x19, 0x40, 0x16, 0x08, 0x07, 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x00, 0x01, + 0x01, 0x76, 0x11, 0x19, 0x02, 0x0c, 0x18, 0x2b, 0x13, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, + 0x03, 0x23, 0xf3, 0x05, 0x11, 0x06, 0x08, 0x17, 0x0c, 0x34, 0x1c, 0x8e, 0x3e, 0x5b, 0x47, 0x02, 0x9a, 0x19, 0x3f, + 0x15, 0x07, 0x15, 0x09, 0x22, 0x2f, 0x5c, 0xfe, 0x54, 0x00, 0x01, 0xff, 0x10, 0x00, 0x00, 0x01, 0x71, 0x02, 0xca, + 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x23, 0x01, 0x33, 0x01, 0xf0, 0x02, 0x12, 0x4f, 0xfd, + 0xee, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x00, 0x02, 0x00, 0x4b, 0x01, 0xa0, 0x01, 0x8a, 0x03, 0x4f, 0x00, 0x0a, 0x00, + 0x14, 0x00, 0x61, 0xb5, 0x10, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x0d, 0x50, 0x58, 0x40, 0x1f, 0x00, 0x01, + 0x02, 0x01, 0x85, 0x06, 0x01, 0x04, 0x00, 0x00, 0x04, 0x71, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, + 0x02, 0x02, 0x00, 0x60, 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, 0x1b, 0x40, 0x1e, 0x00, 0x01, 0x02, 0x01, 0x85, 0x06, + 0x01, 0x04, 0x00, 0x04, 0x86, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, 0x02, 0x02, 0x00, 0x60, 0x03, + 0x01, 0x00, 0x02, 0x00, 0x50, 0x59, 0x40, 0x0f, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, + 0x11, 0x07, 0x0c, 0x1a, 0x2b, 0x13, 0x37, 0x23, 0x37, 0x13, 0x33, 0x03, 0x33, 0x07, 0x23, 0x07, 0x27, 0x33, 0x37, + 0x36, 0x36, 0x37, 0x0e, 0x02, 0x07, 0xe9, 0x14, 0xb2, 0x0b, 0xeb, 0x47, 0x3b, 0x3d, 0x0b, 0x3f, 0x14, 0x8e, 0x6c, + 0x14, 0x06, 0x0a, 0x07, 0x04, 0x13, 0x16, 0x08, 0x01, 0xa0, 0x61, 0x34, 0x01, 0x1a, 0xfe, 0xed, 0x3b, 0x61, 0x9c, + 0x5c, 0x1a, 0x2f, 0x18, 0x07, 0x1b, 0x1c, 0x09, 0x00, 0x00, 0x01, 0x00, 0x5f, 0x01, 0x99, 0x01, 0x98, 0x03, 0x4d, + 0x00, 0x1e, 0x00, 0x47, 0x40, 0x44, 0x15, 0x10, 0x02, 0x02, 0x05, 0x0f, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, + 0x01, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x01, 0x00, 0x51, 0x01, 0x00, + 0x19, 0x17, 0x14, 0x13, 0x12, 0x11, 0x0d, 0x0b, 0x07, 0x05, 0x00, 0x1e, 0x01, 0x1e, 0x07, 0x0c, 0x16, 0x2b, 0x13, + 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x37, 0x33, 0x07, + 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc6, 0x3b, 0x2c, 0x1a, 0x36, 0x1c, 0x32, 0x36, + 0x2e, 0x21, 0x10, 0x20, 0x11, 0x1b, 0x3c, 0xd4, 0x0c, 0x9b, 0x1f, 0x09, 0x17, 0x0d, 0x38, 0x3f, 0x22, 0x4d, 0x01, + 0x99, 0x19, 0x43, 0x10, 0x12, 0x33, 0x2a, 0x22, 0x22, 0x05, 0x06, 0x17, 0xcd, 0x3e, 0x69, 0x02, 0x04, 0x3e, 0x37, + 0x25, 0x49, 0x30, 0x00, 0x00, 0x01, 0x00, 0x71, 0x01, 0xa1, 0x01, 0xae, 0x03, 0x4d, 0x00, 0x06, 0x00, 0x24, 0x40, + 0x21, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, + 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, 0x23, + 0x37, 0x21, 0x07, 0x03, 0x71, 0xe4, 0xc0, 0x0d, 0x01, 0x0c, 0x0a, 0xe4, 0x01, 0xa1, 0x01, 0x71, 0x3b, 0x30, 0xfe, + 0x84, 0x00, 0x00, 0x03, 0x00, 0x58, 0x01, 0x99, 0x01, 0x94, 0x03, 0x55, 0x00, 0x16, 0x00, 0x22, 0x00, 0x2e, 0x00, + 0x39, 0x40, 0x36, 0x29, 0x11, 0x05, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, + 0x05, 0x01, 0x03, 0x00, 0x00, 0x03, 0x59, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x03, 0x00, 0x51, + 0x24, 0x23, 0x01, 0x00, 0x23, 0x2e, 0x24, 0x2e, 0x1e, 0x1c, 0x0c, 0x0a, 0x00, 0x16, 0x01, 0x16, 0x06, 0x0c, 0x16, + 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, + 0x16, 0x16, 0x15, 0x14, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x07, 0x16, + 0x36, 0x35, 0x34, 0x26, 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, 0xd7, 0x38, 0x47, 0x6e, 0x18, 0x1d, 0x4c, 0x43, 0x3a, + 0x3a, 0x35, 0x2e, 0x1e, 0x24, 0x55, 0x1b, 0x1b, 0x32, 0x1f, 0x18, 0x21, 0x24, 0x1c, 0x13, 0x26, 0x2a, 0x23, 0x17, + 0x25, 0x33, 0x25, 0x01, 0x99, 0x39, 0x32, 0x58, 0x29, 0x12, 0x29, 0x23, 0x32, 0x40, 0x3a, 0x28, 0x28, 0x3a, 0x10, + 0x13, 0x30, 0x25, 0x37, 0x49, 0x01, 0x04, 0x0a, 0x22, 0x24, 0x17, 0x1a, 0x22, 0x1a, 0x1a, 0x1f, 0xd9, 0x01, 0x29, + 0x1f, 0x1a, 0x28, 0x0c, 0x0d, 0x2a, 0x23, 0x1b, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x65, 0x01, 0x98, 0x01, 0x96, 0x03, + 0x59, 0x00, 0x0e, 0x00, 0x1d, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, + 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x10, 0x0f, + 0x01, 0x00, 0x17, 0x15, 0x0f, 0x1d, 0x10, 0x1d, 0x09, 0x07, 0x00, 0x0e, 0x01, 0x0e, 0x06, 0x0c, 0x16, 0x2b, 0x13, + 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, + 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0xdc, 0x39, 0x3e, 0x13, 0x2b, 0x47, 0x33, 0x79, 0x15, 0x2d, 0x47, 0x2c, 0x1d, + 0x2a, 0x1b, 0x0e, 0x38, 0x1a, 0x29, 0x1d, 0x0f, 0x1a, 0x01, 0x98, 0x4d, 0x4c, 0x2d, 0x67, 0x5a, 0x3a, 0x90, 0x37, + 0x6c, 0x59, 0x35, 0x3e, 0x2c, 0x49, 0x56, 0x29, 0x51, 0x2a, 0x45, 0x52, 0x29, 0x2c, 0x2f, 0x00, 0x02, 0x00, 0x6a, + 0x01, 0x99, 0x01, 0x9d, 0x03, 0x53, 0x00, 0x1a, 0x00, 0x27, 0x00, 0x4b, 0x40, 0x48, 0x09, 0x01, 0x02, 0x01, 0x0a, + 0x01, 0x03, 0x02, 0x10, 0x01, 0x05, 0x03, 0x03, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x00, 0x03, + 0x00, 0x05, 0x04, 0x03, 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x00, 0x04, 0x59, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x06, 0x01, 0x00, 0x04, 0x00, 0x51, 0x1c, 0x1b, 0x01, 0x00, 0x22, 0x20, 0x1b, 0x27, 0x1c, 0x27, 0x15, 0x13, 0x0e, + 0x0c, 0x08, 0x06, 0x00, 0x1a, 0x01, 0x1a, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, + 0x32, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, + 0x27, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0xe2, 0x35, 0x43, 0x33, 0x6c, 0x53, + 0x23, 0x1e, 0x0f, 0x0c, 0x21, 0x13, 0x3c, 0x4d, 0x0f, 0x04, 0x0b, 0x2f, 0x25, 0x2f, 0x38, 0x22, 0x46, 0x30, 0x29, + 0x2c, 0x1c, 0x1d, 0x23, 0x27, 0x0e, 0x1c, 0x01, 0x99, 0x44, 0x44, 0x52, 0x8b, 0x55, 0x08, 0x3b, 0x04, 0x05, 0x4e, + 0x45, 0x0e, 0x20, 0x3c, 0x35, 0x2a, 0x4e, 0x32, 0x3a, 0x41, 0x2a, 0x1d, 0x21, 0x24, 0x2d, 0x0d, 0x1d, 0x2e, 0x00, + 0x00, 0x02, 0x00, 0x5f, 0x01, 0x99, 0x01, 0x91, 0x03, 0x53, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x4a, 0x40, 0x47, 0x11, + 0x01, 0x03, 0x04, 0x0a, 0x01, 0x02, 0x03, 0x09, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x05, 0x04, + 0x00, 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, + 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, 0x26, 0x1d, 0x26, + 0x16, 0x14, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x1b, 0x01, 0x1b, 0x08, 0x0c, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, + 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, + 0x35, 0x34, 0x36, 0x36, 0x17, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x01, 0x18, 0x36, 0x43, + 0x37, 0x6c, 0x50, 0x22, 0x1d, 0x0c, 0x27, 0x13, 0x2f, 0x42, 0x28, 0x06, 0x02, 0x11, 0x34, 0x1c, 0x2e, 0x38, 0x22, + 0x46, 0x14, 0x26, 0x32, 0x1b, 0x21, 0x29, 0x2c, 0x03, 0x53, 0x43, 0x45, 0x52, 0x8b, 0x55, 0x08, 0x3f, 0x05, 0x08, + 0x2e, 0x46, 0x25, 0x1a, 0x19, 0x3c, 0x34, 0x2a, 0x4e, 0x32, 0xe2, 0x37, 0x27, 0x1d, 0x2d, 0x41, 0x2a, 0x3d, 0x00, + 0x00, 0x01, 0x00, 0x2b, 0x00, 0x00, 0x01, 0xbb, 0x02, 0xfd, 0x00, 0x18, 0x00, 0x35, 0x40, 0x32, 0x0c, 0x01, 0x02, + 0x01, 0x0d, 0x01, 0x03, 0x02, 0x02, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x04, 0x01, 0x00, 0x00, + 0x03, 0x5f, 0x00, 0x03, 0x03, 0x28, 0x4d, 0x06, 0x01, 0x05, 0x05, 0x27, 0x05, 0x4e, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x18, 0x11, 0x13, 0x25, 0x26, 0x11, 0x07, 0x07, 0x1b, 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, + 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x2b, 0x63, 0x5d, 0x07, 0x64, + 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0x73, 0x0d, 0x73, + 0x63, 0x01, 0xd5, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfe, + 0x2b, 0x00, 0x01, 0xff, 0x90, 0xff, 0x10, 0x02, 0xfb, 0x02, 0xfd, 0x00, 0x44, 0x00, 0x93, 0x40, 0x16, 0x27, 0x16, + 0x02, 0x04, 0x03, 0x28, 0x17, 0x02, 0x05, 0x04, 0x39, 0x04, 0x02, 0x01, 0x02, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, + 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x27, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x6c, + 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, + 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x25, 0x06, 0x01, 0x03, 0x07, 0x01, 0x04, 0x05, + 0x03, 0x04, 0x69, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, + 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, 0x21, 0x01, 0x00, 0x41, 0x40, 0x3d, + 0x3b, 0x37, 0x35, 0x32, 0x31, 0x30, 0x2f, 0x2c, 0x2a, 0x25, 0x23, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, + 0x08, 0x06, 0x00, 0x44, 0x01, 0x44, 0x0e, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, + 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, + 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, + 0x23, 0x03, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x06, 0x06, + 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x1e, 0x2d, 0x0d, 0x6e, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, + 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0c, 0x10, 0x2f, 0x46, 0x31, 0x1a, 0x35, + 0x10, 0x18, 0x0e, 0x21, 0x13, 0x28, 0x2d, 0x0e, 0x0c, 0x74, 0x0e, 0x73, 0x70, 0x12, 0x4b, 0x49, 0x26, 0x19, 0x0c, + 0x1c, 0x10, 0x1e, 0x2c, 0x0d, 0x6e, 0xe7, 0x70, 0x12, 0x4c, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x32, 0x40, 0x02, + 0x0a, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x34, 0x44, 0x4d, 0x20, + 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, 0x5e, 0x0a, 0x4a, 0x04, 0x07, 0x33, 0x3f, + 0x02, 0x0a, 0xfd, 0xec, 0x53, 0x5e, 0x00, 0x00, 0x03, 0xff, 0x90, 0xff, 0x10, 0x03, 0x8c, 0x02, 0xfd, 0x00, 0x44, + 0x00, 0x4f, 0x00, 0x53, 0x01, 0x05, 0x40, 0x16, 0x27, 0x16, 0x02, 0x0e, 0x03, 0x28, 0x17, 0x02, 0x0d, 0x04, 0x39, + 0x04, 0x02, 0x01, 0x10, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x39, 0x07, + 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x6c, 0x4d, 0x12, 0x01, 0x0d, 0x0d, 0x0e, 0x61, 0x00, 0x0e, + 0x0e, 0x70, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, + 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, + 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x37, 0x06, 0x01, 0x03, 0x07, 0x01, 0x04, 0x0d, 0x03, 0x04, 0x69, 0x12, 0x01, + 0x0d, 0x0d, 0x0e, 0x61, 0x00, 0x0e, 0x0e, 0x70, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, + 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, + 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x35, 0x06, 0x01, 0x03, 0x07, 0x01, 0x04, 0x0d, 0x03, 0x04, 0x69, 0x00, + 0x0e, 0x12, 0x01, 0x0d, 0x05, 0x0e, 0x0d, 0x69, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, + 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, + 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x31, 0x50, 0x50, 0x46, 0x45, 0x01, 0x00, 0x50, 0x53, 0x50, 0x53, 0x52, + 0x51, 0x4c, 0x4a, 0x45, 0x4f, 0x46, 0x4f, 0x41, 0x40, 0x3d, 0x3b, 0x37, 0x35, 0x32, 0x31, 0x30, 0x2f, 0x2c, 0x2a, + 0x25, 0x23, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x44, 0x01, 0x44, 0x14, 0x0d, 0x16, + 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, + 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, + 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x06, 0x06, 0x01, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x15, + 0x14, 0x06, 0x03, 0x13, 0x33, 0x03, 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x1e, 0x2d, 0x0d, 0x6e, 0x5d, 0x07, + 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0c, + 0x10, 0x2f, 0x46, 0x31, 0x1a, 0x35, 0x10, 0x18, 0x0e, 0x21, 0x13, 0x28, 0x2d, 0x0e, 0x0c, 0x74, 0x0e, 0x73, 0x70, + 0x12, 0x4b, 0x49, 0x26, 0x19, 0x0c, 0x1c, 0x10, 0x1e, 0x2c, 0x0d, 0x6e, 0xe7, 0x70, 0x12, 0x4c, 0x03, 0x3b, 0x13, + 0x1c, 0x1f, 0x1c, 0x2d, 0x24, 0xce, 0x73, 0x58, 0x73, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x32, 0x40, 0x02, 0x0a, + 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x34, 0x44, 0x4d, 0x20, 0x0b, + 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, 0x5e, 0x0a, 0x4a, 0x04, 0x07, 0x33, 0x3f, 0x02, + 0x0a, 0xfd, 0xec, 0x53, 0x5e, 0x03, 0x61, 0x19, 0x16, 0x1a, 0x26, 0x2d, 0x1f, 0x23, 0xfd, 0x8f, 0x02, 0x18, 0xfd, + 0xe8, 0x00, 0x00, 0x02, 0xff, 0x90, 0xff, 0x10, 0x03, 0x93, 0x02, 0xfd, 0x00, 0x44, 0x00, 0x48, 0x01, 0x04, 0x4b, + 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x16, 0x27, 0x16, 0x02, 0x04, 0x03, 0x28, 0x17, 0x02, 0x05, 0x04, 0x39, 0x04, 0x02, + 0x01, 0x0e, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x1b, 0x40, 0x16, 0x27, 0x16, 0x02, 0x04, 0x0d, 0x28, 0x17, + 0x02, 0x05, 0x04, 0x39, 0x04, 0x02, 0x01, 0x0e, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x1d, + 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, + 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, + 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, + 0x2c, 0x0d, 0x06, 0x02, 0x03, 0x07, 0x01, 0x04, 0x05, 0x03, 0x04, 0x69, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, + 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, + 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x33, 0x00, 0x0d, 0x03, 0x04, 0x03, 0x0d, 0x04, 0x80, 0x06, + 0x01, 0x03, 0x07, 0x01, 0x04, 0x05, 0x03, 0x04, 0x69, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, + 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, + 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x29, 0x45, 0x45, 0x01, 0x00, 0x45, 0x48, 0x45, 0x48, 0x47, 0x46, 0x41, + 0x40, 0x3d, 0x3b, 0x37, 0x35, 0x32, 0x31, 0x30, 0x2f, 0x2c, 0x2a, 0x25, 0x23, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, + 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x44, 0x01, 0x44, 0x11, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, + 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, + 0x06, 0x07, 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, + 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, + 0x06, 0x06, 0x25, 0x13, 0x33, 0x03, 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x1e, 0x2d, 0x0d, 0x6e, 0x5d, 0x07, + 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0c, + 0x10, 0x2f, 0x46, 0x31, 0x1a, 0x35, 0x10, 0x18, 0x0e, 0x21, 0x13, 0x28, 0x2d, 0x0e, 0x0c, 0x74, 0x0e, 0x73, 0x70, + 0x12, 0x4b, 0x49, 0x26, 0x19, 0x0c, 0x1c, 0x10, 0x1e, 0x2c, 0x0d, 0x6e, 0xe7, 0x70, 0x12, 0x4c, 0x02, 0x82, 0xa1, + 0x58, 0xa2, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x32, 0x40, 0x02, 0x0a, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, + 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x34, 0x44, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, + 0x43, 0xfd, 0xec, 0x53, 0x5e, 0x0a, 0x4a, 0x04, 0x07, 0x33, 0x3f, 0x02, 0x0a, 0xfd, 0xec, 0x53, 0x5e, 0xf0, 0x02, + 0xf8, 0xfd, 0x08, 0xff, 0xff, 0xff, 0x90, 0xff, 0x10, 0x02, 0x4c, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x4a, 0x01, 0x3e, 0x00, 0x00, 0xff, 0xff, 0xff, 0x90, 0xff, 0x10, 0x02, 0x53, 0x02, 0xfd, 0x00, + 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x3e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x00, + 0x02, 0xf9, 0x02, 0xfd, 0x00, 0x2d, 0x00, 0x42, 0x40, 0x3f, 0x1d, 0x0c, 0x02, 0x02, 0x01, 0x1e, 0x0d, 0x02, 0x03, + 0x02, 0x02, 0x4c, 0x04, 0x01, 0x01, 0x05, 0x01, 0x02, 0x03, 0x01, 0x02, 0x69, 0x09, 0x07, 0x02, 0x00, 0x00, 0x03, + 0x5f, 0x06, 0x01, 0x03, 0x03, 0x28, 0x4d, 0x0b, 0x0a, 0x02, 0x08, 0x08, 0x27, 0x08, 0x4e, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x2d, 0x2c, 0x2b, 0x11, 0x11, 0x13, 0x25, 0x24, 0x13, 0x25, 0x26, 0x11, 0x0c, 0x07, 0x1f, 0x2b, 0x33, 0x13, + 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, + 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x23, + 0x13, 0x23, 0x03, 0x2b, 0x63, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, + 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0b, 0x0f, 0x2f, 0x47, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, + 0x2d, 0x0e, 0x0c, 0x73, 0x0d, 0x73, 0x63, 0x58, 0x63, 0xe6, 0x63, 0x01, 0xd5, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, + 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x33, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, + 0x33, 0x43, 0xfe, 0x2b, 0x01, 0xd5, 0xfe, 0x2b, 0xff, 0xff, 0x00, 0x2b, 0x00, 0x00, 0x03, 0x8a, 0x02, 0xfd, 0x00, + 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x02, 0x7c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2b, 0x00, 0x00, + 0x03, 0x91, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x02, 0x7c, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x2b, 0x00, 0x00, 0x02, 0x4c, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, + 0x01, 0x3e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2b, 0x00, 0x00, 0x02, 0x53, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x3e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0d, 0xff, 0xf8, 0x01, 0x3e, 0x01, 0xb9, + 0x01, 0x07, 0x00, 0x68, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, + 0x00, 0xff, 0xff, 0x00, 0x40, 0x00, 0x00, 0x01, 0x0c, 0x01, 0xac, 0x01, 0x07, 0x00, 0x62, 0xff, 0xac, 0xfe, 0x61, + 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x61, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xef, 0x00, 0x00, 0x01, + 0x36, 0x01, 0xb5, 0x01, 0x07, 0x00, 0x60, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x04, 0xff, 0xf9, 0x01, 0x3f, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x61, 0xff, + 0xb3, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x01, 0x3e, 0x01, 0xaf, 0x01, 0x07, 0x00, 0x64, 0xff, 0xb4, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, + 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0d, 0xff, 0xf9, 0x01, 0x46, 0x01, 0xad, 0x01, 0x07, + 0x00, 0x65, 0xff, 0xae, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, + 0xff, 0x00, 0x11, 0xff, 0xf9, 0x01, 0x44, 0x01, 0xb3, 0x01, 0x07, 0x00, 0x69, 0xff, 0xa7, 0xfe, 0x60, 0x00, 0x09, + 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x5c, 0x01, + 0xac, 0x01, 0x07, 0x00, 0x66, 0xff, 0xae, 0xfe, 0x5f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x5f, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x01, 0x3b, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x67, 0xff, 0xa7, 0xfe, + 0x61, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x61, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x07, 0xff, 0xf9, + 0x01, 0x39, 0x01, 0xb3, 0x01, 0x07, 0x00, 0x6a, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, + 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x4a, 0x01, 0x17, 0x01, 0x7b, 0x02, 0xd8, 0x01, 0x07, 0x00, 0x68, + 0xff, 0xe5, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, + 0x75, 0x01, 0x1e, 0x01, 0x41, 0x02, 0xca, 0x01, 0x07, 0x00, 0x62, 0xff, 0xe1, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, + 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x2b, 0x01, 0x1f, 0x01, 0x72, 0x02, 0xd4, 0x01, + 0x07, 0x00, 0x60, 0xff, 0xe4, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0x00, 0x37, 0x01, 0x18, 0x01, 0x72, 0x02, 0xd5, 0x01, 0x07, 0x00, 0x61, 0xff, 0xe6, 0xff, 0x7f, 0x00, + 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x31, 0x01, 0x1f, 0x01, 0x70, + 0x02, 0xce, 0x01, 0x07, 0x00, 0x64, 0xff, 0xe6, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, + 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x45, 0x01, 0x18, 0x01, 0x7e, 0x02, 0xcc, 0x01, 0x07, 0x00, 0x65, 0xff, 0xe6, + 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x53, 0x01, + 0x18, 0x01, 0x86, 0x02, 0xd2, 0x01, 0x07, 0x00, 0x69, 0xff, 0xe9, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, + 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x5b, 0x01, 0x20, 0x01, 0x98, 0x02, 0xcc, 0x01, 0x07, 0x00, + 0x66, 0xff, 0xea, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x3b, 0x01, 0x18, 0x01, 0x77, 0x02, 0xd4, 0x01, 0x07, 0x00, 0x67, 0xff, 0xe3, 0xff, 0x7f, 0x00, 0x09, 0xb1, + 0x00, 0x03, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x49, 0x01, 0x18, 0x01, 0x7b, 0x02, 0xd2, + 0x01, 0x07, 0x00, 0x6a, 0xff, 0xea, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8a, 0x01, 0x08, 0x00, 0x18, 0x00, 0x71, 0x00, 0x06, 0x00, 0x02, + 0x00, 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x89, 0x0e, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x5b, 0x00, 0xaf, 0x01, 0x40, 0x01, 0xf5, 0x02, 0x87, 0x02, 0xa2, 0x02, 0xca, + 0x02, 0xf2, 0x03, 0x1f, 0x03, 0x47, 0x03, 0x67, 0x03, 0x83, 0x03, 0xa4, 0x03, 0xbf, 0x04, 0x09, 0x04, 0x32, 0x04, + 0x74, 0x04, 0xd8, 0x05, 0x18, 0x05, 0x6c, 0x05, 0xd7, 0x05, 0xfa, 0x06, 0x66, 0x06, 0xce, 0x07, 0x08, 0x07, 0x43, + 0x07, 0x59, 0x07, 0x84, 0x07, 0x9a, 0x07, 0xf5, 0x08, 0xaa, 0x08, 0xe2, 0x09, 0x3b, 0x09, 0x84, 0x09, 0xbc, 0x09, + 0xec, 0x0a, 0x17, 0x0a, 0x6a, 0x0a, 0x98, 0x0a, 0xc2, 0x0a, 0xf3, 0x0b, 0x23, 0x0b, 0x43, 0x0b, 0x81, 0x0b, 0xb6, + 0x0b, 0xfc, 0x0c, 0x36, 0x0c, 0x85, 0x0c, 0xc7, 0x0d, 0x21, 0x0d, 0x44, 0x0d, 0x80, 0x0d, 0xad, 0x0d, 0xfb, 0x0e, + 0x2a, 0x0e, 0x52, 0x0e, 0x7c, 0x0e, 0xa0, 0x0e, 0xba, 0x0e, 0xde, 0x0f, 0x05, 0x0f, 0x25, 0x0f, 0x4f, 0x0f, 0xbd, + 0x10, 0x42, 0x10, 0x8a, 0x11, 0x0e, 0x11, 0x6a, 0x11, 0xdf, 0x12, 0x69, 0x12, 0xc2, 0x13, 0x05, 0x13, 0x62, 0x13, + 0xa4, 0x13, 0xc9, 0x14, 0x3c, 0x14, 0x8e, 0x14, 0xd3, 0x15, 0x41, 0x15, 0xac, 0x15, 0xff, 0x16, 0x54, 0x16, 0xb4, + 0x17, 0x09, 0x17, 0x38, 0x17, 0x86, 0x17, 0xb2, 0x17, 0xfa, 0x18, 0x23, 0x18, 0x81, 0x18, 0xa6, 0x19, 0x02, 0x19, + 0x47, 0x19, 0x8a, 0x19, 0xeb, 0x1a, 0x12, 0x1a, 0x2d, 0x1a, 0x84, 0x1a, 0xd7, 0x1a, 0xfc, 0x1b, 0x5f, 0x1b, 0xa4, + 0x1c, 0x05, 0x1c, 0x64, 0x1c, 0xa7, 0x1d, 0x55, 0x1e, 0x53, 0x1f, 0x41, 0x1f, 0x4d, 0x1f, 0x59, 0x1f, 0xbf, 0x1f, + 0xcb, 0x1f, 0xd7, 0x1f, 0xe3, 0x1f, 0xef, 0x1f, 0xfe, 0x20, 0x0d, 0x20, 0x1c, 0x20, 0x2b, 0x20, 0x3a, 0x20, 0x49, + 0x20, 0x58, 0x20, 0x67, 0x20, 0x76, 0x20, 0x85, 0x20, 0x94, 0x20, 0xa3, 0x20, 0xb2, 0x20, 0xc1, 0x20, 0xd0, 0x20, + 0xdf, 0x20, 0xee, 0x20, 0xfd, 0x21, 0x0c, 0x21, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, + 0x57, 0x3e, 0x69, 0x66, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xcc, + 0xa2, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc4, 0x0f, 0xfd, 0x67, 0xfe, 0x7b, 0x0a, 0xcf, 0x04, 0x3c, 0x00, 0x02, + 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x58, 0x00, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x01, + 0x05, 0x00, 0x14, 0x01, 0x88, 0x00, 0x6d, 0x02, 0x86, 0x00, 0x1e, 0x02, 0x27, 0x00, 0x22, 0x03, 0x1f, 0x00, 0x50, + 0x02, 0xa1, 0x00, 0x20, 0x00, 0xdc, 0x00, 0x6d, 0x01, 0x22, 0x00, 0x28, 0x01, 0x22, 0xff, 0xb3, 0x02, 0x27, 0x00, + 0x67, 0x02, 0x3c, 0x00, 0x46, 0x01, 0x00, 0xff, 0xd5, 0x01, 0x39, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x14, 0x01, 0x64, + 0xff, 0xd2, 0x02, 0x27, 0x00, 0x39, 0x02, 0x27, 0x00, 0x8f, 0x02, 0x27, 0x00, 0x03, 0x02, 0x27, 0x00, 0x16, 0x02, + 0x27, 0x00, 0x06, 0x02, 0x27, 0x00, 0x25, 0x02, 0x27, 0x00, 0x3f, 0x02, 0x27, 0x00, 0x51, 0x02, 0x27, 0x00, 0x2d, + 0x02, 0x27, 0x00, 0x2f, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0xff, 0xcf, 0x02, 0x3c, 0x00, 0x46, 0x02, 0x3c, 0x00, + 0x4c, 0x02, 0x3c, 0x00, 0x46, 0x01, 0xae, 0x00, 0x4d, 0x03, 0x50, 0x00, 0x35, 0x02, 0x32, 0xff, 0xc7, 0x02, 0x58, + 0x00, 0x29, 0x02, 0x4b, 0x00, 0x48, 0x02, 0x9b, 0x00, 0x29, 0x02, 0x02, 0x00, 0x29, 0x01, 0xdd, 0x00, 0x29, 0x02, + 0xa6, 0x00, 0x48, 0x02, 0xa8, 0x00, 0x2a, 0x01, 0x44, 0xff, 0xec, 0x01, 0x11, 0xff, 0x64, 0x02, 0x32, 0x00, 0x29, + 0x01, 0xde, 0x00, 0x29, 0x03, 0x49, 0x00, 0x28, 0x02, 0xc3, 0x00, 0x28, 0x02, 0xd1, 0x00, 0x48, 0x02, 0x37, 0x00, + 0x29, 0x02, 0xd1, 0x00, 0x48, 0x02, 0x3d, 0x00, 0x29, 0x01, 0xf9, 0x00, 0x13, 0x01, 0xf5, 0x00, 0x5a, 0x02, 0xa5, + 0x00, 0x4f, 0x02, 0x28, 0x00, 0x5c, 0x03, 0x58, 0x00, 0x6b, 0x02, 0x0f, 0xff, 0xcc, 0x01, 0xfd, 0x00, 0x5c, 0x02, + 0x13, 0xff, 0xf6, 0x01, 0x22, 0xff, 0xf7, 0x01, 0x64, 0x00, 0x6c, 0x01, 0x22, 0xff, 0xb8, 0x02, 0x3c, 0x00, 0x26, + 0x01, 0x8b, 0xff, 0xa4, 0x01, 0x16, 0x00, 0x92, 0x02, 0x38, 0x00, 0x30, 0x02, 0x43, 0x00, 0x1c, 0x01, 0xc5, 0x00, + 0x30, 0x02, 0x43, 0x00, 0x30, 0x01, 0xf3, 0x00, 0x30, 0x01, 0x3e, 0xff, 0x90, 0x02, 0x43, 0x00, 0x19, 0x02, 0x43, + 0x00, 0x1c, 0x01, 0x02, 0x00, 0x1c, 0x01, 0x02, 0xff, 0x82, 0x01, 0xef, 0x00, 0x1b, 0x01, 0x02, 0x00, 0x1b, 0x03, + 0x6b, 0x00, 0x1c, 0x02, 0x43, 0x00, 0x18, 0x02, 0x33, 0x00, 0x30, 0x02, 0x43, 0xff, 0xea, 0x02, 0x43, 0x00, 0x30, + 0x01, 0x8e, 0x00, 0x1c, 0x01, 0xb0, 0x00, 0x05, 0x01, 0x4c, 0x00, 0x2c, 0x02, 0x43, 0x00, 0x37, 0x01, 0xd3, 0x00, + 0x30, 0x02, 0xd3, 0x00, 0x39, 0x01, 0xe3, 0xff, 0xdb, 0x01, 0xd3, 0xff, 0xa2, 0x01, 0xbd, 0xff, 0xf1, 0x01, 0x5e, + 0x00, 0x0b, 0x02, 0x27, 0x01, 0x04, 0x01, 0x5e, 0xff, 0xdb, 0x02, 0x3c, 0x00, 0x46, 0x01, 0x61, 0x00, 0x47, 0x01, + 0x61, 0x00, 0x51, 0x01, 0x61, 0x00, 0x94, 0x00, 0x82, 0xff, 0x10, 0x01, 0x61, 0x00, 0x4b, 0x01, 0x61, 0x00, 0x5f, + 0x01, 0x61, 0x00, 0x71, 0x01, 0x61, 0x00, 0x58, 0x01, 0x61, 0x00, 0x65, 0x01, 0x61, 0x00, 0x6a, 0x01, 0x61, 0x00, + 0x5f, 0x01, 0x3e, 0x00, 0x2b, 0x02, 0x7e, 0xff, 0x90, 0x03, 0x80, 0xff, 0x90, 0x03, 0x80, 0xff, 0x90, 0x02, 0x40, + 0xff, 0x90, 0x02, 0x40, 0xff, 0x90, 0x02, 0x7c, 0x00, 0x2b, 0x03, 0x7e, 0x00, 0x2b, 0x03, 0x7e, 0x00, 0x2b, 0x02, + 0x40, 0x00, 0x2b, 0x02, 0x40, 0x00, 0x2b, 0x01, 0x61, 0x00, 0x0d, 0x00, 0x40, 0xff, 0xef, 0x00, 0x04, 0xff, 0xff, + 0x00, 0x0d, 0x00, 0x11, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x07, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x2b, 0x00, 0x37, 0x00, + 0x31, 0x00, 0x45, 0x00, 0x53, 0x00, 0x5b, 0x00, 0x3b, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x2d, + 0xfe, 0xdb, 0x00, 0x00, 0x0a, 0xf0, 0xfd, 0x67, 0xfd, 0x67, 0x0a, 0xcf, 0x03, 0xe8, 0x00, 0xd5, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, 0x02, 0x26, 0x01, 0x90, 0x00, 0x05, + 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, 0xff, 0xf0, 0x00, 0x4b, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x4a, 0x01, 0x5e, 0x00, + 0x32, 0x01, 0x42, 0x00, 0x00, 0x02, 0x0b, 0x05, 0x02, 0x04, 0x05, 0x04, 0x09, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x01, 0x81, 0x00, + 0x20, 0x00, 0x7e, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x18, 0x02, 0xca, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, + 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, + 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, 0xb0, 0x28, 0x59, 0x60, 0x66, + 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, + 0x21, 0xb0, 0x00, 0x59, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, + 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, 0x02, 0x2c, 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, + 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, 0x14, 0x43, 0x42, + 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, + 0xb0, 0x04, 0x50, 0x78, 0xb2, 0x02, 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, + 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, 0x20, 0xb0, 0x02, 0x43, 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, + 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, 0x2c, + 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, + 0x58, 0x65, 0x59, 0x1b, 0x20, 0x64, 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, + 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, + 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, + 0x38, 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, + 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x20, 0xb0, 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, + 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, 0x20, 0xb0, 0x20, 0x50, + 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, + 0x59, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, + 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, 0xb0, 0x1e, 0x50, 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, + 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, 0x59, 0x59, + 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, + 0x2c, 0x20, 0x45, 0x20, 0xb0, 0x04, 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, + 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, 0x59, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, + 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, + 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, + 0x20, 0xb0, 0x08, 0x43, 0x20, 0x8a, 0x20, 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, + 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, 0x40, 0x53, 0x58, 0xb0, 0x01, + 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, + 0x43, 0x2b, 0xb2, 0x00, 0x02, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, + 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, + 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, + 0x09, 0x0e, 0x00, 0x43, 0x45, 0x42, 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, + 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, + 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, + 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, + 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, + 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, + 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, + 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, + 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, 0x0c, 0x00, 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, + 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, 0x2c, 0xb0, 0x01, 0x60, + 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, + 0x4a, 0xb0, 0x00, 0x52, 0x58, 0x20, 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, + 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, 0x00, 0x63, 0x8a, 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, + 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x24, + 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, + 0x59, 0x1b, 0x21, 0x59, 0x24, 0xb0, 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, + 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, 0x61, 0x42, 0xb0, 0x11, 0x2b, 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, + 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, + 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, + 0x2a, 0x21, 0x23, 0xb0, 0x01, 0x61, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, + 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, 0xb0, 0x0f, 0x43, 0x47, 0xb0, + 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, + 0x63, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, + 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, 0x00, 0x13, 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, + 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, 0x23, + 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, + 0x01, 0x00, 0x11, 0x00, 0x13, 0x00, 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, + 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, + 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, 0x2c, + 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, + 0x2b, 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, + 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, + 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, + 0x5d, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, + 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, + 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, + 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, + 0x58, 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, + 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, + 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, 0x2c, 0xb1, + 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, + 0x2d, 0xb0, 0x25, 0x2c, 0xb1, 0x04, 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, + 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, 0x28, 0x2c, 0xb1, 0x07, 0x20, 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, + 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, + 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, + 0x61, 0xb0, 0x01, 0x60, 0xb0, 0x2e, 0x2a, 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, + 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, + 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, + 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, + 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, + 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, + 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, + 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x34, 0x2c, 0x20, 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, + 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, + 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, + 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, + 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0xb0, + 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, + 0x23, 0x42, 0xb0, 0x02, 0x25, 0x49, 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, + 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, 0x01, 0x15, 0x14, 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, + 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, 0x42, 0xb0, + 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, + 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, + 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, + 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, + 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, + 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, + 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, + 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, 0x02, 0x25, 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, + 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, + 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, + 0x05, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, + 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, 0x60, 0x64, 0x23, 0xb0, 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, + 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, 0xb0, + 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, + 0x23, 0x3c, 0x38, 0x2d, 0xb0, 0x3d, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, + 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, + 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, + 0x2e, 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, + 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, + 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0x63, 0xb8, 0x04, + 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, + 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x23, 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, + 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, 0x3c, 0x8a, + 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, + 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, + 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, + 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, + 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, + 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, + 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, + 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, + 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, + 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, + 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x26, 0x20, 0x20, + 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, + 0x23, 0x20, 0x3c, 0x20, 0x2e, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, + 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, + 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, + 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, + 0x47, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, + 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, + 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, + 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, + 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, 0x23, 0x38, 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, + 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, 0x3a, 0x2b, 0x2e, 0xb1, + 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, + 0x23, 0x42, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, + 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, + 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, + 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, + 0x2d, 0xb0, 0x4c, 0x2c, 0xb0, 0x39, 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, + 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, + 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, + 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, + 0x2d, 0xb0, 0x53, 0x2c, 0xb2, 0x00, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, + 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, 0x01, 0x47, 0x2b, 0x2d, 0xb0, + 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, + 0xb0, 0x59, 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, + 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, + 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, 0x01, 0x01, 0x01, + 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, + 0x2b, 0x2d, 0xb0, 0x61, 0x2c, 0xb2, 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, + 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, + 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, 0xb0, + 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, + 0xb0, 0x69, 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, + 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, + 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, + 0x44, 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, + 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, + 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x73, 0x2c, 0xb1, + 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, + 0x75, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, + 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x77, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, + 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, + 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, + 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, + 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, + 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, + 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, + 0x82, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, + 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x85, 0x2c, + 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, + 0xb0, 0x87, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, + 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, + 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, 0xb0, 0x06, 0x1b, + 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, + 0x24, 0x50, 0x78, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, + 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, + 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, 0x00, 0x49, 0x39, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x14, + 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, 0x02, 0x56, 0x06, 0x4e, 0x04, 0x3e, 0x08, 0x32, 0x06, 0x24, 0x07, 0x09, + 0x0a, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x52, + 0x02, 0x46, 0x06, 0x38, 0x04, 0x2b, 0x05, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, + 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, 0x13, 0xc0, 0x0f, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, + 0x2a, 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, + 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, + 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, 0x28, 0x01, 0x88, 0x51, + 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, + 0x58, 0xba, 0x08, 0x80, 0x00, 0x01, 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, + 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, 0x06, 0x7a, 0x06, 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x50, 0x02, 0x40, + 0x06, 0x34, 0x04, 0x26, 0x05, 0x09, 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, 0x00, 0x44, + 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x48, 0x02, 0xca, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0xff, + 0x10, 0x02, 0xd6, 0xff, 0xf6, 0x02, 0x20, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4c, 0x00, 0x4c, + 0x02, 0x3b, 0x02, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x44, 0x02, 0x47, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x59, 0x00, + 0x59, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0xff, 0xf6, 0x02, 0xf8, 0x02, 0x18, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, + 0xff, 0xf6, 0x02, 0xfd, 0x02, 0x21, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4c, 0x00, 0x4c, 0x02, + 0x3b, 0x00, 0x00, 0x02, 0x44, 0xff, 0xf8, 0x00, 0x45, 0x00, 0x45, 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x68, 0x00, 0xe8, + 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x45, 0x00, 0x45, 0x00, 0x3e, 0x00, + 0x3e, 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x59, 0x00, 0x59, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0x00, 0x00, 0x02, 0xec, + 0x02, 0x18, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xec, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x00, + 0x3a, 0x00, 0x3a, 0x00, 0x2c, 0x00, 0x2c, 0x01, 0x2b, 0xff, 0x7e, 0x01, 0x61, 0x00, 0xe2, 0xff, 0xa0, 0xff, 0x10, + 0x01, 0x34, 0xff, 0x77, 0x01, 0x61, 0x00, 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x2c, 0x00, + 0x2c, 0x02, 0xcb, 0x01, 0x9f, 0x02, 0xe0, 0x02, 0x61, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe0, 0x01, 0x98, 0x02, 0xe0, + 0x02, 0x67, 0x01, 0x19, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, + 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, + 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x0c, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, + 0x34, 0x00, 0xd4, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x20, 0x01, 0x08, 0x00, 0x03, 0x00, 0x01, + 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, 0x01, 0x28, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x1e, 0x01, + 0x7c, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, + 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, + 0x20, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, + 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, + 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, 0x00, 0x3a, + 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, + 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, + 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, + 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, + 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, + 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, + 0x00, 0x69, 0x00, 0x63, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, 0x00, + 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, + 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, + 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, + 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, + 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, + 0x00, 0x3b, 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, + 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, + 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, 0x00, + 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, + 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x03, 0x00, 0x00, 0xff, 0xf4, 0x00, + 0x00, 0xff, 0x9c, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x22, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x42, + 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x02, 0x00, 0x18, 0x00, + 0x0a, 0x00, 0x22, 0x00, 0x32, 0x00, 0x3c, 0x00, 0x4a, 0x00, 0x4a, 0x00, 0x2a, 0x00, 0x32, 0x00, 0x3c, 0x00, 0x4a, + 0x00, 0x4a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, + 0xfa, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0xff, 0x00, 0x02, 0x00, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0xf7, + 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x00, 0xf9, 0x00, 0x01, 0x02, 0x2d, 0x00, 0x01, 0x00, 0x04, 0x00, + 0x01, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, 0x44, 0x46, + 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, + 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0x65, + 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x06, 0xc8, 0x00, + 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x01, 0x08, 0x00, 0x01, 0x00, 0x38, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x6a, 0x00, 0xf4, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x8c, 0x00, 0xb4, 0x00, 0x92, 0x00, 0x98, 0x00, 0xb4, 0x00, + 0xaa, 0x00, 0xb4, 0x00, 0xba, 0x00, 0xc4, 0x00, 0xc4, 0x00, 0xce, 0x00, 0xd8, 0x00, 0xf4, 0x00, 0xde, 0x00, 0xe4, + 0x00, 0xee, 0x00, 0xee, 0x00, 0xee, 0x00, 0xf4, 0x00, 0x01, 0x00, 0x17, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, 0x00, + 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, + 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, 0x00, 0x5a, 0x00, + 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, 0x37, 0xff, 0xd8, 0x00, 0x38, 0xff, 0xd8, 0x00, 0x3a, 0xff, 0xc4, + 0x00, 0x01, 0x00, 0x2b, 0x00, 0x4b, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xec, 0x00, 0x0f, 0xff, 0xec, 0x00, 0x01, 0x00, + 0x07, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x04, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, + 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x39, 0xff, 0xec, 0x00, + 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, + 0xff, 0xf6, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, 0x00, + 0x07, 0xff, 0xec, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, + 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, 0x03, + 0xd8, 0x00, 0x04, 0x00, 0x00, 0x04, 0x26, 0x04, 0xe4, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, 0xff, + 0xf6, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, 0xff, 0xe2, + 0xff, 0xce, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xc4, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, + 0x00, 0xff, 0xd8, 0xff, 0xec, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf6, 0xff, + 0xec, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xce, 0xff, 0xf6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0xff, 0xe2, + 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xce, 0x00, 0x00, 0xff, 0xec, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x0a, 0xff, 0xc4, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, + 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0xff, + 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x88, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x25, 0x00, 0x03, 0x00, + 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x2c, 0x00, 0x2d, + 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, + 0x3b, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x4c, 0x00, 0x50, 0x00, 0x51, 0x00, 0x53, + 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x1f, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x09, 0x00, 0x13, 0x00, 0x0d, + 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x22, 0x00, + 0x22, 0x00, 0x01, 0x00, 0x24, 0x00, 0x24, 0x00, 0x07, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x2c, 0x00, 0x2c, + 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x08, 0x00, 0x30, 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, + 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, 0x05, + 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x39, 0x00, 0x39, 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x06, 0x00, + 0x3b, 0x00, 0x3b, 0x00, 0x0d, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x02, 0x00, 0x47, + 0x00, 0x47, 0x00, 0x15, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x10, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, + 0x55, 0x00, 0x0c, 0x00, 0x57, 0x00, 0x58, 0x00, 0x04, 0x00, 0x59, 0x00, 0x59, 0x00, 0x10, 0x00, 0x5a, 0x00, 0x5a, + 0x00, 0x04, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x15, 0x00, 0x02, 0x00, 0x23, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x11, 0x00, 0x08, 0x00, 0x08, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x0d, + 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0c, 0x00, 0x1b, 0x00, + 0x1c, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x05, 0x00, 0x24, 0x00, 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x28, + 0x00, 0x02, 0x00, 0x30, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x32, 0x00, 0x02, 0x00, 0x35, 0x00, 0x35, 0x00, + 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x08, + 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x04, 0x00, + 0x44, 0x00, 0x46, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x48, 0x00, 0x48, 0x00, 0x0d, 0x00, 0x4e, + 0x00, 0x4f, 0x00, 0x03, 0x00, 0x50, 0x00, 0x50, 0x00, 0x01, 0x00, 0x51, 0x00, 0x51, 0x00, 0x03, 0x00, 0x52, 0x00, + 0x52, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x03, 0x00, 0x54, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x55, 0x00, 0x55, + 0x00, 0x0e, 0x00, 0x56, 0x00, 0x56, 0x00, 0x03, 0x00, 0x57, 0x00, 0x58, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x5a, 0x00, + 0x07, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x5e, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x15, + 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x00, + 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x08, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x02, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x0a, 0x00, 0x50, 0x00, 0x92, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, + 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x01, 0x45, 0x57, 0x45, 0x20, 0x00, 0x18, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x20, 0x66, 0x72, 0x61, 0x63, 0x00, 0x26, 0x6c, 0x69, 0x67, 0x61, 0x00, + 0x30, 0x6c, 0x6f, 0x63, 0x6c, 0x00, 0x36, 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x3c, 0x00, 0x4a, + 0x00, 0x5e, 0x00, 0x76, 0x00, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x12, 0x00, 0x06, 0x00, 0x6b, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x01, 0x00, 0x06, + 0x00, 0x47, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, + 0x00, 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x2a, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x01, 0x00, 0x76, 0x00, 0x7f, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, + 0x00, 0x89, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x66, 0x00, 0x02, 0x00, + 0x0a, 0x00, 0x38, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6e, 0x00, 0x03, + 0x00, 0x47, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x4a, 0x00, + 0x70, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x47, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, + 0x00, 0x22, 0x00, 0x28, 0x00, 0x73, 0x00, 0x03, 0x00, 0x6b, 0x00, 0x4d, 0x00, 0x72, 0x00, 0x03, 0x00, 0x6b, 0x00, + 0x4a, 0x00, 0x74, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x71, 0x00, 0x02, 0x00, 0x6b, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x47, 0x00, 0x6b}; + + constexpr unsigned char BOLD_DATA[] = { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x06, 0x75, 0x08, + 0xc3, 0x00, 0x00, 0x4f, 0x3c, 0x00, 0x00, 0x00, 0x6c, 0x47, 0x50, 0x4f, 0x53, 0x28, 0x98, 0x0a, 0xef, 0x00, 0x00, + 0x4f, 0xa8, 0x00, 0x00, 0x07, 0xb2, 0x47, 0x53, 0x55, 0x42, 0x39, 0x7a, 0x34, 0x30, 0x00, 0x00, 0x57, 0x5c, 0x00, + 0x00, 0x01, 0x50, 0x4f, 0x53, 0x2f, 0x32, 0x6a, 0x81, 0x61, 0x8b, 0x00, 0x00, 0x3c, 0x5c, 0x00, 0x00, 0x00, 0x60, + 0x63, 0x6d, 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x3c, 0xbc, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, + 0x20, 0x41, 0xb6, 0x1e, 0xcf, 0x00, 0x00, 0x4c, 0x04, 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, + 0x0b, 0x83, 0x00, 0x00, 0x3c, 0xf0, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x4f, 0x34, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0xea, 0xe8, 0x66, 0x13, 0x00, 0x00, 0x01, 0x1c, + 0x00, 0x00, 0x37, 0xca, 0x68, 0x65, 0x61, 0x64, 0x28, 0x6e, 0xdc, 0x4a, 0x00, 0x00, 0x3a, 0x14, 0x00, 0x00, 0x00, + 0x36, 0x68, 0x68, 0x65, 0x61, 0x0c, 0x9d, 0x0b, 0xd8, 0x00, 0x00, 0x3c, 0x38, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, + 0x74, 0x78, 0xf4, 0x22, 0x11, 0xe6, 0x00, 0x00, 0x3a, 0x4c, 0x00, 0x00, 0x01, 0xea, 0x6c, 0x6f, 0x63, 0x61, 0x08, + 0xbe, 0xfb, 0x1b, 0x00, 0x00, 0x39, 0x08, 0x00, 0x00, 0x01, 0x0a, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x55, 0x10, 0x44, + 0x00, 0x00, 0x38, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x27, 0x83, 0x40, 0x7b, 0x00, 0x00, 0x4d, + 0x30, 0x00, 0x00, 0x01, 0xe4, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x9f, 0x00, 0x32, 0x00, 0x00, 0x4f, 0x14, 0x00, 0x00, + 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0x44, 0x7e, 0xc6, 0xb9, 0x00, 0x00, 0x4a, 0xfc, 0x00, 0x00, 0x01, 0x05, 0x00, + 0x02, 0x00, 0x36, 0xff, 0xf3, 0x00, 0xe3, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, + 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, + 0x24, 0x23, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x37, 0x23, 0x03, 0x33, 0x03, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x23, 0x22, 0x26, 0xc9, 0x78, 0x19, 0xaa, 0xac, 0x33, 0x24, 0x23, 0x33, 0x33, 0x23, 0x24, 0x33, 0xe8, + 0x01, 0xe2, 0xfd, 0x7c, 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x02, 0x00, 0x3d, 0x01, 0xc8, 0x01, 0xa1, + 0x02, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x40, 0x21, 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x05, 0x03, 0x04, + 0x03, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, + 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0x21, 0x03, 0x23, 0x03, 0xcd, 0x14, 0x68, 0x14, 0x01, + 0x64, 0x14, 0x67, 0x14, 0x02, 0xca, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x00, 0x16, + 0x00, 0x00, 0x02, 0x70, 0x02, 0xc9, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, 0x40, 0x44, 0x0c, 0x0a, 0x02, 0x08, 0x0f, + 0x10, 0x0d, 0x03, 0x07, 0x00, 0x08, 0x07, 0x68, 0x0e, 0x06, 0x02, 0x00, 0x05, 0x03, 0x02, 0x01, 0x02, 0x00, 0x01, + 0x67, 0x0b, 0x01, 0x09, 0x09, 0x6a, 0x4d, 0x04, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, + 0x1c, 0x00, 0x1b, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x0d, 0x1f, 0x2b, 0x01, 0x07, 0x33, 0x15, 0x23, 0x07, 0x23, 0x37, 0x23, 0x07, 0x23, 0x37, + 0x23, 0x35, 0x33, 0x37, 0x23, 0x35, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, 0x15, 0x05, 0x33, 0x37, + 0x23, 0x01, 0xe8, 0x17, 0x7e, 0x91, 0x26, 0x6b, 0x26, 0x5f, 0x25, 0x69, 0x24, 0x74, 0x87, 0x17, 0x7b, 0x8d, 0x26, + 0x6b, 0x26, 0x61, 0x26, 0x69, 0x26, 0x75, 0xfe, 0x97, 0x60, 0x17, 0x60, 0x01, 0x9c, 0x71, 0x65, 0xc6, 0xc6, 0xc6, + 0xc6, 0x65, 0x71, 0x66, 0xc7, 0xc7, 0xc7, 0xc7, 0x66, 0x71, 0x71, 0x00, 0x00, 0x03, 0x00, 0x2b, 0xff, 0xc6, 0x02, + 0x15, 0x02, 0xf7, 0x00, 0x22, 0x00, 0x28, 0x00, 0x2e, 0x00, 0x3f, 0x40, 0x3c, 0x2e, 0x29, 0x28, 0x23, 0x19, 0x18, + 0x15, 0x14, 0x08, 0x04, 0x0a, 0x01, 0x03, 0x20, 0x03, 0x02, 0x00, 0x01, 0x02, 0x4c, 0x0f, 0x01, 0x03, 0x01, 0x4b, + 0x00, 0x03, 0x02, 0x01, 0x02, 0x03, 0x01, 0x80, 0x00, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x04, 0x04, + 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6c, 0x04, 0x4e, 0x1e, 0x11, 0x19, 0x15, 0x10, 0x05, 0x0d, 0x1b, 0x2b, 0x37, 0x26, + 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x35, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x37, 0x35, 0x33, 0x15, 0x16, 0x17, 0x07, + 0x26, 0x26, 0x27, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x15, 0x23, 0x11, 0x06, 0x15, 0x14, 0x16, 0x17, 0x13, + 0x36, 0x35, 0x34, 0x26, 0x27, 0xfd, 0x41, 0x66, 0x2a, 0x29, 0x74, 0x34, 0x4d, 0x5d, 0x28, 0x75, 0x5d, 0x43, 0x6f, + 0x5b, 0x2e, 0x28, 0x51, 0x23, 0x36, 0x62, 0x3d, 0x6a, 0x6b, 0x43, 0x3f, 0x1e, 0x21, 0x43, 0x42, 0x21, 0x21, 0x28, + 0x02, 0x15, 0x13, 0x81, 0x14, 0x21, 0x03, 0x97, 0x1e, 0x39, 0x46, 0x31, 0x4b, 0x59, 0x08, 0x4b, 0x49, 0x04, 0x29, + 0x72, 0x11, 0x12, 0x03, 0x90, 0x14, 0x2f, 0x48, 0x3b, 0x49, 0x62, 0x0a, 0x64, 0x02, 0x6d, 0x09, 0x2a, 0x15, 0x1c, + 0x0f, 0xfe, 0xde, 0x0c, 0x2e, 0x14, 0x1d, 0x0f, 0x00, 0x00, 0x05, 0x00, 0x1e, 0xff, 0xf7, 0x03, 0x68, 0x02, 0xd4, + 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x33, 0x00, 0xd2, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x2c, + 0x0d, 0x01, 0x06, 0x0e, 0x01, 0x08, 0x01, 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0c, + 0x01, 0x04, 0x04, 0x00, 0x61, 0x0b, 0x03, 0x0a, 0x03, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x07, + 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x1a, 0x50, 0x58, 0x40, 0x30, 0x0d, 0x01, 0x06, 0x0e, 0x01, + 0x08, 0x01, 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0b, 0x01, 0x03, 0x03, 0x6a, 0x4d, + 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, 0x0a, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x07, 0x01, + 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x34, 0x0d, 0x01, 0x06, 0x0e, 0x01, 0x08, 0x01, 0x06, 0x08, 0x6a, 0x00, + 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0b, 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x0a, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x09, 0x09, 0x07, 0x61, 0x00, 0x07, 0x07, + 0x71, 0x07, 0x4e, 0x59, 0x59, 0x40, 0x2b, 0x29, 0x28, 0x1d, 0x1c, 0x11, 0x10, 0x0c, 0x0c, 0x01, 0x00, 0x2f, 0x2d, + 0x28, 0x33, 0x29, 0x33, 0x23, 0x21, 0x1c, 0x27, 0x1d, 0x27, 0x17, 0x15, 0x10, 0x1b, 0x11, 0x1b, 0x0c, 0x0f, 0x0c, + 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x05, 0x01, 0x23, 0x01, 0x05, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, + 0x35, 0x34, 0x26, 0x05, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xc6, 0x50, 0x5c, 0x56, 0x56, 0x4e, 0x5a, 0x55, 0x02, 0x50, 0xfe, + 0x74, 0x77, 0x01, 0x8c, 0xfe, 0x7b, 0x1b, 0x18, 0x18, 0x1b, 0x1c, 0x19, 0x19, 0x01, 0xd9, 0x4f, 0x5d, 0x57, 0x55, + 0x4e, 0x5a, 0x55, 0x54, 0x1c, 0x17, 0x17, 0x1c, 0x1c, 0x19, 0x19, 0x02, 0xd4, 0x75, 0x6a, 0x6a, 0x77, 0x77, 0x6a, + 0x6a, 0x75, 0x0a, 0xfd, 0x36, 0x02, 0xca, 0x57, 0x42, 0x3d, 0x3d, 0x43, 0x42, 0x3e, 0x3d, 0x42, 0xbc, 0x75, 0x6a, + 0x6a, 0x77, 0x77, 0x6a, 0x6a, 0x75, 0x61, 0x42, 0x3d, 0x3d, 0x43, 0x42, 0x3e, 0x3e, 0x41, 0x00, 0x00, 0x03, 0x00, + 0x28, 0xff, 0xf6, 0x02, 0xee, 0x02, 0xd4, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x37, 0x00, 0x7d, 0x40, 0x12, 0x28, 0x1b, + 0x02, 0x01, 0x04, 0x37, 0x0f, 0x08, 0x07, 0x04, 0x05, 0x01, 0x12, 0x01, 0x02, 0x05, 0x03, 0x4c, 0x4b, 0xb0, 0x19, + 0x50, 0x58, 0x40, 0x23, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, + 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, + 0x4e, 0x1b, 0x40, 0x21, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, + 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x59, + 0x40, 0x17, 0x23, 0x22, 0x01, 0x00, 0x35, 0x33, 0x22, 0x2d, 0x23, 0x2d, 0x16, 0x14, 0x11, 0x10, 0x0c, 0x0b, 0x00, + 0x21, 0x01, 0x21, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, + 0x33, 0x06, 0x06, 0x07, 0x17, 0x23, 0x27, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, + 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x06, 0x06, 0x15, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x01, 0x36, 0x3a, 0x5a, 0x34, 0x52, 0x3d, 0x8b, 0x14, 0x1e, 0x0a, 0x9b, 0x0f, + 0x3a, 0x2d, 0x93, 0xb8, 0x38, 0x2b, 0x6a, 0x3e, 0x7a, 0x89, 0x46, 0x3d, 0x27, 0x1f, 0x35, 0x5f, 0x3c, 0x19, 0x2d, + 0x19, 0x15, 0x2a, 0x2d, 0x28, 0x4a, 0x1c, 0x21, 0x40, 0x30, 0x20, 0x38, 0x17, 0x02, 0xd4, 0x24, 0x45, 0x32, 0x45, + 0x5e, 0x23, 0x87, 0x22, 0x4b, 0x26, 0x38, 0x80, 0x38, 0x8f, 0x37, 0x1e, 0x23, 0x70, 0x5b, 0x4c, 0x5b, 0x23, 0x2d, + 0x4c, 0x2b, 0x33, 0x4a, 0x28, 0x73, 0x19, 0x23, 0x19, 0x2e, 0x18, 0x17, 0x2e, 0x1e, 0x1e, 0x1a, 0xfe, 0xd1, 0x15, + 0x2f, 0x1f, 0x2b, 0x31, 0x10, 0x0e, 0x00, 0x01, 0x00, 0x3d, 0x01, 0xc8, 0x00, 0xcd, 0x02, 0xca, 0x00, 0x03, 0x00, + 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0xcd, 0x14, 0x68, 0x14, 0x02, 0xca, 0xfe, 0xfe, + 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, 0x62, 0x01, 0x35, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, + 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x16, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x13, 0x34, + 0x36, 0x37, 0x33, 0x06, 0x06, 0x15, 0x14, 0x16, 0x17, 0x23, 0x26, 0x26, 0x28, 0x47, 0x4c, 0x7a, 0x44, 0x47, 0x47, + 0x43, 0x79, 0x4c, 0x47, 0x01, 0x12, 0x7a, 0xe3, 0x5b, 0x5e, 0xe2, 0x77, 0x74, 0xe1, 0x5c, 0x58, 0xdf, 0x00, 0x00, + 0x01, 0x00, 0x1e, 0xff, 0x62, 0x01, 0x2b, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x00, 0x01, + 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x16, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x23, 0x36, + 0x36, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x01, 0x2b, 0x47, 0x4c, 0x79, 0x44, 0x46, 0x47, 0x44, 0x7a, 0x4c, + 0x47, 0x01, 0x12, 0x79, 0xdf, 0x58, 0x5c, 0xe1, 0x74, 0x77, 0xe2, 0x5e, 0x5b, 0xe3, 0x00, 0x01, 0x00, 0x1d, 0x01, + 0x24, 0x02, 0x01, 0x02, 0xf8, 0x00, 0x0e, 0x00, 0x23, 0x40, 0x20, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, + 0x05, 0x04, 0x03, 0x02, 0x01, 0x0d, 0x00, 0x49, 0x01, 0x01, 0x00, 0x00, 0x6c, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x0e, 0x02, 0x0d, 0x16, 0x2b, 0x01, 0x07, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, + 0x17, 0x27, 0x01, 0x4f, 0x14, 0xb5, 0x11, 0xa5, 0x6c, 0x6f, 0x4c, 0x43, 0x74, 0x6c, 0xa5, 0x13, 0xb2, 0x14, 0x02, + 0xf8, 0xb4, 0x33, 0x7c, 0x0c, 0x90, 0x3b, 0x98, 0x98, 0x3b, 0x90, 0x0e, 0x7a, 0x33, 0xb4, 0x00, 0x01, 0x00, 0x2b, + 0x00, 0x6f, 0x02, 0x10, 0x02, 0x54, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x00, 0x05, 0x00, 0x02, 0x05, 0x57, 0x04, + 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, 0x05, 0x02, 0x5f, 0x00, 0x02, 0x05, 0x02, 0x4f, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, + 0x33, 0x35, 0x33, 0x01, 0x53, 0xbd, 0xbd, 0x6b, 0xbd, 0xbd, 0x6b, 0x01, 0x96, 0x6b, 0xbc, 0xbc, 0x6b, 0xbe, 0x00, + 0x00, 0x01, 0x00, 0x1f, 0xff, 0x7f, 0x00, 0xe0, 0x00, 0x74, 0x00, 0x08, 0x00, 0x18, 0x40, 0x15, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x13, 0x13, 0x02, 0x0d, 0x18, 0x2b, + 0x37, 0x06, 0x06, 0x07, 0x23, 0x36, 0x36, 0x37, 0x33, 0xe0, 0x0d, 0x30, 0x19, 0x6b, 0x0e, 0x1c, 0x07, 0x89, 0x69, + 0x35, 0x7e, 0x37, 0x3b, 0x86, 0x34, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0xce, 0x01, 0x23, 0x01, 0x4a, 0x00, 0x03, + 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, + 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, 0x35, 0x21, 0x15, 0x1c, 0x01, + 0x07, 0xce, 0x7c, 0x7c, 0x00, 0x01, 0x00, 0x36, 0xff, 0xf3, 0x00, 0xe3, 0x00, 0x9a, 0x00, 0x0b, 0x00, 0x13, 0x40, + 0x10, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x22, 0x02, 0x0d, 0x18, 0x2b, 0x37, + 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x36, 0x33, 0x24, 0x23, 0x33, 0x33, 0x23, 0x24, + 0x33, 0x46, 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x01, 0x00, 0x07, 0xff, 0xfa, 0x01, 0x9a, 0x02, 0xd0, + 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x01, 0x01, 0x23, 0x01, 0x01, 0x9a, 0xfe, 0xf6, 0x89, + 0x01, 0x0a, 0x02, 0xd0, 0xfd, 0x2a, 0x02, 0xd6, 0x00, 0x02, 0x00, 0x24, 0xff, 0xf6, 0x02, 0x17, 0x02, 0xd5, 0x00, + 0x0d, 0x00, 0x19, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, + 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x24, 0x25, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, + 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x17, 0x31, 0x6d, 0x5c, 0x81, 0x78, 0x30, 0x6e, 0x5b, 0x80, 0x7a, 0xfe, 0xa3, + 0x2a, 0x39, 0x38, 0x2c, 0x2c, 0x38, 0x39, 0x2a, 0x01, 0x65, 0x73, 0xa4, 0x58, 0xc3, 0xac, 0x74, 0xa4, 0x58, 0xc2, + 0xae, 0x7a, 0x7b, 0x7a, 0x7b, 0x7a, 0x7c, 0x7c, 0x00, 0x01, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x9d, 0x02, 0xca, 0x00, + 0x0c, 0x00, 0x1b, 0x40, 0x18, 0x0a, 0x09, 0x05, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1a, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x21, 0x23, 0x11, 0x34, 0x36, 0x37, 0x06, 0x06, + 0x07, 0x07, 0x27, 0x37, 0x33, 0x01, 0x9d, 0x97, 0x03, 0x01, 0x05, 0x21, 0x0e, 0x52, 0x49, 0xe6, 0x7c, 0x01, 0x9d, + 0x1a, 0x54, 0x20, 0x06, 0x1f, 0x0c, 0x42, 0x5b, 0xb7, 0x00, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x02, 0x1b, 0x02, + 0xd4, 0x00, 0x1d, 0x00, 0x2d, 0x40, 0x2a, 0x0e, 0x01, 0x01, 0x02, 0x0d, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, + 0x03, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, + 0x00, 0x6b, 0x00, 0x4e, 0x28, 0x26, 0x28, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x3e, 0x02, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, + 0x15, 0x21, 0x02, 0x1b, 0xfe, 0x0d, 0xb3, 0x36, 0x42, 0x1e, 0x2f, 0x28, 0x29, 0x4e, 0x2b, 0x52, 0x1f, 0x45, 0x5b, + 0x40, 0x46, 0x65, 0x37, 0x2f, 0x59, 0x3f, 0x5c, 0x01, 0x37, 0x69, 0xb5, 0x38, 0x4b, 0x3d, 0x23, 0x2b, 0x2a, 0x26, + 0x23, 0x61, 0x1b, 0x2e, 0x1d, 0x33, 0x57, 0x37, 0x3b, 0x62, 0x60, 0x3a, 0x56, 0x07, 0x00, 0x00, 0x01, 0x00, 0x26, + 0xff, 0xf6, 0x02, 0x14, 0x02, 0xd4, 0x00, 0x2b, 0x00, 0x3f, 0x40, 0x3c, 0x26, 0x01, 0x04, 0x05, 0x25, 0x01, 0x03, + 0x04, 0x03, 0x01, 0x02, 0x03, 0x0e, 0x01, 0x01, 0x02, 0x0d, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x03, 0x00, 0x02, + 0x01, 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, + 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, 0x25, 0x21, 0x25, 0x24, 0x2a, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x14, 0x06, + 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x26, 0x23, 0x23, 0x35, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x01, 0xff, 0x59, 0x41, 0x56, 0x59, 0x3d, 0x7f, 0x64, 0x74, 0x5a, 0x2e, 0x65, 0x2b, 0x51, 0x41, + 0x1e, 0x4b, 0x43, 0x36, 0x37, 0x42, 0x45, 0x19, 0x2f, 0x37, 0x33, 0x4b, 0x1a, 0x46, 0x2a, 0x71, 0x4e, 0x6e, 0x81, + 0x02, 0x2a, 0x4a, 0x58, 0x10, 0x03, 0x0a, 0x54, 0x47, 0x3e, 0x63, 0x39, 0x27, 0x80, 0x17, 0x18, 0x38, 0x33, 0x1e, + 0x29, 0x15, 0x74, 0x19, 0x2b, 0x1c, 0x26, 0x2b, 0x23, 0x11, 0x68, 0x1e, 0x28, 0x59, 0x00, 0x00, 0x02, 0x00, 0x11, + 0x00, 0x00, 0x02, 0x2b, 0x02, 0xca, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x27, 0x40, 0x24, 0x06, 0x01, 0x00, 0x04, 0x01, + 0x4c, 0x05, 0x01, 0x04, 0x02, 0x01, 0x00, 0x01, 0x04, 0x00, 0x67, 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, + 0x6b, 0x01, 0x4e, 0x1a, 0x11, 0x12, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x25, 0x23, 0x15, 0x23, 0x35, 0x21, + 0x35, 0x01, 0x33, 0x11, 0x33, 0x27, 0x34, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x07, 0x07, 0x33, 0x02, 0x2b, 0x56, + 0x93, 0xfe, 0xcf, 0x01, 0x39, 0x8b, 0x56, 0xe9, 0x02, 0x03, 0x01, 0x04, 0x09, 0x14, 0x0e, 0x83, 0xac, 0x94, 0x94, + 0x94, 0x69, 0x01, 0xcd, 0xfe, 0x3f, 0x79, 0x17, 0x42, 0x39, 0x09, 0x14, 0x26, 0x14, 0xc6, 0x00, 0x01, 0x00, 0x31, + 0xff, 0xf6, 0x02, 0x0e, 0x02, 0xca, 0x00, 0x1e, 0x00, 0x44, 0x40, 0x41, 0x1c, 0x17, 0x02, 0x03, 0x00, 0x16, 0x0b, + 0x02, 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x03, 0x02, 0x00, 0x03, 0x69, 0x00, + 0x05, 0x05, 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, + 0x4e, 0x01, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x14, 0x12, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x1e, 0x01, 0x1e, 0x07, 0x0d, + 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, + 0x35, 0x34, 0x23, 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x15, 0x23, 0x07, 0x36, 0x36, 0x01, 0x2c, 0x41, 0x66, 0x3b, + 0x90, 0x8d, 0x38, 0x63, 0x25, 0x25, 0x68, 0x2e, 0x43, 0x47, 0x8f, 0x1c, 0x3c, 0x14, 0x3c, 0x1b, 0x01, 0x83, 0xff, + 0x0d, 0x11, 0x27, 0x01, 0xc8, 0x32, 0x60, 0x47, 0x74, 0x85, 0x14, 0x13, 0x82, 0x13, 0x1b, 0x37, 0x3a, 0x6c, 0x0b, + 0x05, 0x20, 0x01, 0x6c, 0x80, 0x8c, 0x03, 0x07, 0x00, 0x02, 0x00, 0x23, 0xff, 0xf6, 0x02, 0x1b, 0x02, 0xd2, 0x00, + 0x1e, 0x00, 0x2c, 0x00, 0x69, 0x40, 0x0e, 0x09, 0x01, 0x01, 0x00, 0x0a, 0x01, 0x02, 0x01, 0x11, 0x01, 0x05, 0x02, + 0x03, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1e, 0x00, 0x02, 0x00, 0x05, 0x04, 0x02, 0x05, 0x69, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, + 0x4e, 0x1b, 0x40, 0x1e, 0x00, 0x02, 0x00, 0x05, 0x04, 0x02, 0x05, 0x69, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x70, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x20, + 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x24, 0x26, 0x24, 0x35, 0x07, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x3e, 0x03, + 0x33, 0x32, 0x16, 0x17, 0x15, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x23, 0x22, 0x26, 0x26, 0x05, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, + 0x16, 0x23, 0x12, 0x2d, 0x51, 0x7d, 0x59, 0x15, 0x38, 0x13, 0x13, 0x2d, 0x16, 0x59, 0x61, 0x28, 0x03, 0x06, 0x14, + 0x4b, 0x3c, 0x5e, 0x6e, 0x83, 0x70, 0x49, 0x76, 0x46, 0x01, 0x02, 0x2c, 0x38, 0x30, 0x31, 0x21, 0x32, 0x1c, 0x18, + 0x31, 0x01, 0x2f, 0x3e, 0x78, 0x6b, 0x53, 0x2f, 0x03, 0x04, 0x79, 0x05, 0x05, 0x38, 0x65, 0x42, 0x23, 0x30, 0x76, + 0x6c, 0x74, 0x84, 0x43, 0x8b, 0x55, 0x3d, 0x40, 0x34, 0x3c, 0x1d, 0x2e, 0x18, 0x21, 0x3f, 0x2a, 0x00, 0x01, 0x00, + 0x1b, 0x00, 0x00, 0x02, 0x1b, 0x02, 0xca, 0x00, 0x06, 0x00, 0x25, 0x40, 0x22, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, + 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x6f, 0x01, + 0x0c, 0xfe, 0xa0, 0x02, 0x00, 0xfe, 0xf2, 0x02, 0x4b, 0x7f, 0x5f, 0xfd, 0x95, 0x00, 0x00, 0x03, 0x00, 0x23, 0xff, + 0xf6, 0x02, 0x18, 0x02, 0xd3, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x35, 0x00, 0x36, 0x40, 0x33, 0x33, 0x22, 0x15, 0x07, + 0x04, 0x03, 0x02, 0x01, 0x4c, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x03, + 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1d, 0x1c, 0x01, 0x00, 0x2c, 0x2a, 0x1c, 0x27, 0x1d, 0x27, + 0x10, 0x0e, 0x00, 0x1b, 0x01, 0x1b, 0x06, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, + 0x02, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, + 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x26, 0x27, 0x27, 0x06, 0x06, 0x01, 0x1e, 0x3e, 0x67, 0x3f, 0x49, 0x37, 0x26, 0x45, 0x2b, 0x3f, 0x71, 0x4a, + 0x78, 0x83, 0x50, 0x39, 0x30, 0x43, 0x40, 0x69, 0x3b, 0x25, 0x31, 0x34, 0x23, 0x22, 0x34, 0x31, 0x94, 0x37, 0x36, + 0x38, 0x38, 0x20, 0x2f, 0x19, 0x0d, 0x2e, 0x3a, 0x02, 0xd3, 0x26, 0x4c, 0x3a, 0x40, 0x53, 0x1b, 0x14, 0x35, 0x47, + 0x30, 0x3b, 0x58, 0x30, 0x66, 0x59, 0x4a, 0x5a, 0x1c, 0x1e, 0x55, 0x40, 0x39, 0x4c, 0x26, 0x6e, 0x26, 0x23, 0x25, + 0x2e, 0x11, 0x10, 0x2d, 0x27, 0x23, 0x26, 0xfe, 0x59, 0x27, 0x32, 0x30, 0x28, 0x1b, 0x29, 0x21, 0x0e, 0x07, 0x16, + 0x3a, 0x00, 0x00, 0x02, 0x00, 0x20, 0xff, 0xf6, 0x02, 0x18, 0x02, 0xd2, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x3e, 0x40, + 0x3b, 0x11, 0x01, 0x02, 0x05, 0x0a, 0x01, 0x01, 0x02, 0x09, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, + 0x01, 0x05, 0x02, 0x69, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, + 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x20, 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x24, 0x26, 0x24, 0x35, + 0x07, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x0e, 0x03, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, + 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x16, 0x25, 0x22, 0x06, 0x15, 0x14, + 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x26, 0x02, 0x18, 0x12, 0x2d, 0x51, 0x7d, 0x59, 0x15, 0x38, 0x13, + 0x14, 0x2c, 0x16, 0x59, 0x61, 0x28, 0x03, 0x06, 0x15, 0x45, 0x44, 0x5b, 0x6e, 0x83, 0x70, 0x49, 0x76, 0x46, 0xfe, + 0xfe, 0x2c, 0x38, 0x30, 0x31, 0x22, 0x31, 0x1c, 0x18, 0x30, 0x01, 0x99, 0x3d, 0x79, 0x6b, 0x53, 0x2f, 0x03, 0x04, + 0x79, 0x04, 0x06, 0x39, 0x64, 0x42, 0x23, 0x30, 0x76, 0x6c, 0x74, 0x84, 0x43, 0x8b, 0x55, 0x3c, 0x41, 0x34, 0x3c, + 0x1e, 0x2d, 0x18, 0x21, 0x40, 0x29, 0x00, 0x02, 0x00, 0x36, 0xff, 0xf3, 0x00, 0xe3, 0x02, 0x2c, 0x00, 0x0b, 0x00, + 0x17, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, + 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x11, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, + 0x26, 0x36, 0x33, 0x24, 0x23, 0x33, 0x33, 0x23, 0x24, 0x33, 0x33, 0x24, 0x23, 0x33, 0x33, 0x23, 0x24, 0x33, 0x01, + 0xd9, 0x2e, 0x25, 0x25, 0x2e, 0x2d, 0x27, 0x27, 0xfe, 0x9a, 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x02, + 0x00, 0x1f, 0xff, 0x7f, 0x00, 0xe4, 0x02, 0x2c, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, + 0x02, 0x03, 0x02, 0x63, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x01, 0x4e, 0x13, 0x15, 0x24, 0x22, + 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x13, 0x06, 0x06, + 0x07, 0x23, 0x36, 0x36, 0x37, 0x33, 0x39, 0x32, 0x24, 0x23, 0x32, 0x32, 0x23, 0x24, 0x32, 0xa7, 0x0d, 0x30, 0x19, + 0x6b, 0x0e, 0x1c, 0x07, 0x89, 0x01, 0xd9, 0x2e, 0x25, 0x25, 0x2e, 0x2c, 0x27, 0x27, 0xfe, 0xbc, 0x35, 0x7e, 0x37, + 0x3b, 0x86, 0x34, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x63, 0x02, 0x10, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, + 0x00, 0x01, 0x32, 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, 0x05, 0x02, 0x10, 0xfe, 0x1b, 0x01, 0xe5, 0xfe, 0xb2, + 0x01, 0x4e, 0x63, 0xd6, 0x46, 0xf2, 0x75, 0x9b, 0x89, 0x00, 0x02, 0x00, 0x2b, 0x00, 0xcc, 0x02, 0x10, 0x01, 0xf4, + 0x00, 0x03, 0x00, 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, + 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, + 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, + 0x05, 0x35, 0x21, 0x15, 0x2b, 0x01, 0xe5, 0xfe, 0x1b, 0x01, 0xe5, 0x01, 0x8a, 0x6a, 0x6a, 0xbe, 0x6b, 0x6b, 0x00, + 0x00, 0x01, 0x00, 0x2b, 0x00, 0x63, 0x02, 0x10, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, + 0x2b, 0x37, 0x25, 0x25, 0x35, 0x05, 0x15, 0x05, 0x2b, 0x01, 0x4e, 0xfe, 0xb2, 0x01, 0xe5, 0xfe, 0x1b, 0xd8, 0x89, + 0x9b, 0x75, 0xf2, 0x46, 0xd6, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0xf3, 0x01, 0xc8, 0x02, 0xd4, 0x00, 0x1d, 0x00, + 0x29, 0x00, 0x32, 0x40, 0x2f, 0x0e, 0x01, 0x00, 0x01, 0x0d, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x02, 0x00, 0x03, + 0x00, 0x02, 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x04, 0x61, + 0x00, 0x04, 0x04, 0x71, 0x04, 0x4e, 0x24, 0x23, 0x1a, 0x25, 0x29, 0x05, 0x0d, 0x1b, 0x2b, 0x13, 0x34, 0x36, 0x37, + 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, + 0x0e, 0x02, 0x15, 0x15, 0x23, 0x07, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x8e, 0x24, + 0x33, 0x24, 0x24, 0x0d, 0x2f, 0x29, 0x2a, 0x53, 0x2b, 0x35, 0x31, 0x72, 0x44, 0x69, 0x73, 0x3a, 0x3b, 0x1f, 0x22, + 0x0d, 0x77, 0x15, 0x32, 0x25, 0x22, 0x33, 0x33, 0x22, 0x25, 0x32, 0x01, 0x0c, 0x32, 0x45, 0x24, 0x19, 0x24, 0x21, + 0x14, 0x1f, 0x22, 0x1a, 0x16, 0x6d, 0x1b, 0x22, 0x60, 0x51, 0x3d, 0x54, 0x2a, 0x16, 0x21, 0x1e, 0x15, 0x16, 0xa2, + 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xb0, 0x03, 0x53, 0x02, 0xcf, 0x00, 0x3e, + 0x00, 0x4c, 0x00, 0x7e, 0x40, 0x16, 0x16, 0x01, 0x09, 0x02, 0x46, 0x01, 0x03, 0x09, 0x08, 0x01, 0x00, 0x03, 0x2e, + 0x01, 0x05, 0x00, 0x2f, 0x01, 0x06, 0x05, 0x05, 0x4c, 0x4b, 0xb0, 0x2c, 0x50, 0x58, 0x40, 0x26, 0x08, 0x01, 0x03, + 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, + 0x00, 0x07, 0x07, 0x6a, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x24, + 0x00, 0x02, 0x00, 0x09, 0x03, 0x02, 0x09, 0x69, 0x08, 0x01, 0x03, 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, + 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, 0x00, 0x07, 0x07, 0x6a, 0x04, 0x4e, 0x59, 0x40, + 0x0e, 0x4a, 0x48, 0x25, 0x27, 0x25, 0x25, 0x25, 0x28, 0x25, 0x25, 0x24, 0x0a, 0x0d, 0x1f, 0x2b, 0x01, 0x14, 0x0e, + 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x14, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, + 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, + 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x03, 0x53, 0x17, 0x2e, + 0x43, 0x2d, 0x27, 0x3c, 0x0e, 0x06, 0x15, 0x42, 0x2e, 0x56, 0x59, 0x37, 0x69, 0x4c, 0x2f, 0x5a, 0x1c, 0x0a, 0x01, + 0x17, 0x10, 0x17, 0x21, 0x11, 0x8e, 0x7d, 0x69, 0x8f, 0x4a, 0x8e, 0x8b, 0x39, 0x7e, 0x36, 0x31, 0x76, 0x42, 0x7c, + 0xb0, 0x5e, 0x3c, 0x70, 0x9f, 0x63, 0x6f, 0xa8, 0x5f, 0xfe, 0x12, 0x2a, 0x23, 0x2e, 0x28, 0x04, 0x05, 0x0b, 0x18, + 0x0e, 0x2c, 0x36, 0x19, 0x01, 0x6c, 0x2e, 0x5a, 0x49, 0x2b, 0x27, 0x1e, 0x1d, 0x28, 0x6a, 0x57, 0x42, 0x68, 0x3c, + 0x12, 0x0a, 0xcd, 0x0a, 0x17, 0x09, 0x23, 0x18, 0x2d, 0x4b, 0x2c, 0x7b, 0x8b, 0x56, 0x98, 0x62, 0x82, 0x94, 0x1a, + 0x13, 0x5e, 0x15, 0x17, 0x59, 0xa6, 0x74, 0x5b, 0x9c, 0x75, 0x40, 0x56, 0x9f, 0xa9, 0x37, 0x31, 0x48, 0x47, 0x5f, + 0x02, 0x04, 0x28, 0x3f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0xb4, 0x02, 0xcd, 0x00, 0x07, 0x00, 0x12, + 0x00, 0x2c, 0x40, 0x29, 0x0c, 0x01, 0x04, 0x02, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x68, 0x00, + 0x02, 0x02, 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x12, 0x11, 0x00, 0x07, 0x00, + 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x21, 0x27, 0x23, 0x07, 0x23, 0x13, 0x33, 0x13, 0x01, 0x2e, 0x02, + 0x27, 0x0e, 0x02, 0x07, 0x07, 0x33, 0x02, 0x0f, 0x37, 0xfc, 0x37, 0xa5, 0xfb, 0xbc, 0xfd, 0xfe, 0xcf, 0x04, 0x11, + 0x10, 0x05, 0x04, 0x0f, 0x0e, 0x05, 0x33, 0xb5, 0xa8, 0xa8, 0x02, 0xcd, 0xfd, 0x33, 0x01, 0xc3, 0x0f, 0x3c, 0x3f, + 0x14, 0x17, 0x3b, 0x39, 0x13, 0x9b, 0x00, 0x00, 0x03, 0x00, 0x55, 0x00, 0x00, 0x02, 0x67, 0x02, 0xca, 0x00, 0x10, + 0x00, 0x19, 0x00, 0x22, 0x00, 0x44, 0x40, 0x41, 0x06, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x08, 0x01, + 0x05, 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x04, 0x04, + 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1a, 0x1a, 0x12, 0x11, 0x01, 0x00, 0x1a, 0x22, 0x1a, 0x21, 0x1d, + 0x1b, 0x18, 0x16, 0x11, 0x19, 0x12, 0x19, 0x0f, 0x0d, 0x00, 0x10, 0x01, 0x10, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x13, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x23, 0x23, 0x1d, 0x02, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x3c, 0x93, 0x86, 0x47, 0x32, 0x23, + 0x40, 0x28, 0x8d, 0x7a, 0xfe, 0xf5, 0xef, 0x41, 0x33, 0x3c, 0x3f, 0x4f, 0x61, 0x44, 0x35, 0x36, 0x48, 0x02, 0xca, + 0x57, 0x5b, 0x43, 0x4f, 0x0b, 0x05, 0x07, 0x24, 0x44, 0x38, 0x62, 0x6d, 0x02, 0xca, 0xfe, 0xe2, 0x30, 0x27, 0x29, + 0x27, 0xa7, 0x73, 0xc0, 0x37, 0x2b, 0x27, 0x37, 0x00, 0x01, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x63, 0x02, 0xd4, 0x00, + 0x1a, 0x00, 0x37, 0x40, 0x34, 0x17, 0x01, 0x00, 0x03, 0x18, 0x09, 0x02, 0x01, 0x00, 0x0a, 0x01, 0x02, 0x01, 0x03, + 0x4c, 0x04, 0x01, 0x00, 0x00, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, + 0x02, 0x71, 0x02, 0x4e, 0x01, 0x00, 0x15, 0x13, 0x0d, 0x0b, 0x07, 0x05, 0x00, 0x1a, 0x01, 0x1a, 0x05, 0x0d, 0x16, + 0x2b, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, + 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x01, 0x8e, 0x56, 0x63, 0x5f, 0x60, 0x2f, 0x57, 0x2c, 0x55, + 0x6e, 0x72, 0x93, 0x47, 0x50, 0x9a, 0x6f, 0x35, 0x6d, 0x31, 0x32, 0x24, 0x51, 0x02, 0x55, 0x81, 0x71, 0x71, 0x7d, + 0x16, 0x11, 0x82, 0x24, 0x5b, 0xa5, 0x6e, 0x6c, 0xa6, 0x5e, 0x17, 0x18, 0x7a, 0x11, 0x19, 0x00, 0x02, 0x00, 0x55, + 0x00, 0x00, 0x02, 0xa6, 0x02, 0xca, 0x00, 0x09, 0x00, 0x11, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x02, 0x02, 0x01, 0x5f, + 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x21, 0x24, 0x21, + 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, 0x23, 0x23, 0x11, 0x33, 0x32, 0x16, 0x07, 0x34, 0x26, 0x23, + 0x23, 0x11, 0x33, 0x32, 0x02, 0xa6, 0x5c, 0xa8, 0x73, 0xda, 0xec, 0xa8, 0xbd, 0xa0, 0x66, 0x63, 0x4f, 0x40, 0xd8, + 0x01, 0x71, 0x7b, 0xa4, 0x52, 0x02, 0xca, 0xb1, 0xae, 0x73, 0x6f, 0xfe, 0x31, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, + 0x00, 0x01, 0xf5, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x29, 0x40, 0x26, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, + 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, + 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x21, 0x11, 0x21, 0x15, 0x21, 0x15, + 0x33, 0x15, 0x23, 0x15, 0x21, 0x01, 0xf5, 0xfe, 0x65, 0x01, 0x9b, 0xfe, 0xfc, 0xf2, 0xf2, 0x01, 0x04, 0x02, 0xca, + 0x7c, 0x9d, 0x7c, 0xb8, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x01, 0xf3, 0x02, 0xca, 0x00, 0x09, 0x00, 0x23, + 0x40, 0x20, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, + 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x10, 0x05, 0x0d, 0x1b, 0x2b, 0x33, 0x23, 0x11, + 0x21, 0x15, 0x21, 0x15, 0x33, 0x15, 0x23, 0xef, 0x95, 0x01, 0x99, 0xfe, 0xfc, 0xf2, 0xf2, 0x02, 0xca, 0x7c, 0xb8, + 0x7c, 0x00, 0x01, 0x00, 0x3a, 0xff, 0xf6, 0x02, 0x84, 0x02, 0xd4, 0x00, 0x20, 0x00, 0x3b, 0x40, 0x38, 0x0f, 0x01, + 0x03, 0x02, 0x10, 0x01, 0x00, 0x03, 0x1e, 0x01, 0x04, 0x05, 0x02, 0x01, 0x01, 0x04, 0x04, 0x4c, 0x00, 0x00, 0x00, + 0x05, 0x04, 0x00, 0x05, 0x67, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x01, + 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x13, 0x26, 0x25, 0x25, 0x23, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x21, + 0x11, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, + 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x35, 0x23, 0x01, 0x69, 0x01, 0x1b, 0x38, 0x79, 0x4d, + 0xa0, 0xac, 0x57, 0xa6, 0x78, 0x39, 0x6e, 0x2d, 0x32, 0x21, 0x54, 0x2e, 0x42, 0x61, 0x35, 0x26, 0x52, 0x42, 0x20, + 0x2d, 0x13, 0x87, 0x01, 0x91, 0xfe, 0x8e, 0x13, 0x16, 0xbc, 0xb4, 0x70, 0xa4, 0x5a, 0x18, 0x14, 0x79, 0x11, 0x16, + 0x3c, 0x6d, 0x4a, 0x46, 0x6c, 0x3d, 0x06, 0x04, 0x95, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0xa3, 0x02, 0xca, + 0x00, 0x0b, 0x00, 0x21, 0x40, 0x1e, 0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x01, 0x67, 0x05, 0x01, 0x03, 0x03, 0x6a, + 0x4d, 0x02, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, + 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x02, 0xa3, 0x97, 0xfe, 0xe5, 0x97, 0x97, 0x01, + 0x1b, 0x97, 0x01, 0x34, 0xfe, 0xcc, 0x02, 0xca, 0xfe, 0xe8, 0x01, 0x18, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, + 0x01, 0x65, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x0a, 0x09, 0x08, 0x05, 0x04, 0x03, 0x02, 0x08, + 0x00, 0x01, 0x01, 0x4c, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x10, 0x02, 0x0d, + 0x18, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x11, 0x27, 0x35, 0x21, 0x15, 0x07, 0x11, 0x17, 0x01, 0x65, 0xfe, 0xbb, 0x57, + 0x57, 0x01, 0x45, 0x57, 0x57, 0x56, 0x28, 0x01, 0xce, 0x28, 0x56, 0x56, 0x28, 0xfe, 0x32, 0x28, 0x00, 0x00, 0x01, + 0xff, 0xb6, 0xff, 0x2e, 0x00, 0xf1, 0x02, 0xca, 0x00, 0x11, 0x00, 0x28, 0x40, 0x25, 0x04, 0x01, 0x01, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, 0x00, 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, + 0x01, 0x00, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x11, 0x01, 0x11, 0x04, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, + 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x06, 0x0f, 0x1d, 0x2c, 0x10, 0x10, 0x23, + 0x14, 0x1a, 0x2b, 0x18, 0x97, 0x39, 0x66, 0xd2, 0x07, 0x04, 0x7e, 0x04, 0x06, 0x14, 0x38, 0x34, 0x02, 0x9d, 0xfd, + 0x64, 0x5c, 0x71, 0x33, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0x98, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x20, + 0x40, 0x1d, 0x0e, 0x08, 0x03, 0x02, 0x04, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x11, 0x13, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x07, 0x15, 0x23, + 0x11, 0x33, 0x11, 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x02, 0x98, 0xac, 0xbb, 0x40, 0x97, 0x97, 0x0f, 0x1e, 0x0f, + 0xc1, 0xa8, 0xf9, 0x01, 0x2d, 0x2e, 0xff, 0x02, 0xca, 0xfe, 0xb9, 0x15, 0x2a, 0x15, 0xf3, 0xfe, 0xc4, 0x00, 0x01, + 0x00, 0x55, 0x00, 0x00, 0x02, 0x0f, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x6a, 0x4d, + 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x11, + 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x55, 0x99, 0x01, 0x21, 0x02, 0xca, 0xfd, 0xb4, + 0x7e, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x03, 0x55, 0x02, 0xca, 0x00, 0x17, 0x00, 0x26, 0x40, 0x23, 0x15, 0x0b, + 0x02, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x05, 0x04, 0x03, 0x03, 0x00, 0x00, 0x6b, 0x00, + 0x4e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x17, 0x11, 0x13, 0x11, 0x17, 0x06, 0x0d, 0x1a, 0x2b, 0x21, 0x03, 0x23, 0x1e, + 0x02, 0x15, 0x11, 0x23, 0x11, 0x33, 0x13, 0x33, 0x13, 0x33, 0x11, 0x23, 0x11, 0x34, 0x36, 0x36, 0x37, 0x23, 0x03, + 0x01, 0x88, 0xac, 0x04, 0x01, 0x04, 0x04, 0x87, 0xce, 0xa9, 0x03, 0xb3, 0xce, 0x8d, 0x03, 0x03, 0x01, 0x04, 0xb8, + 0x02, 0x30, 0x14, 0x50, 0x5b, 0x25, 0xfe, 0xb4, 0x02, 0xca, 0xfd, 0xde, 0x02, 0x22, 0xfd, 0x36, 0x01, 0x52, 0x22, + 0x58, 0x4f, 0x14, 0xfd, 0xd1, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0xd3, 0x02, 0xca, 0x00, 0x11, 0x00, 0x1e, + 0x40, 0x1b, 0x0b, 0x02, 0x02, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, + 0x6b, 0x00, 0x4e, 0x16, 0x11, 0x16, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x01, 0x23, 0x16, 0x16, 0x17, 0x11, + 0x23, 0x11, 0x33, 0x01, 0x33, 0x26, 0x26, 0x27, 0x11, 0x33, 0x02, 0xd3, 0xc0, 0xfe, 0xc9, 0x04, 0x02, 0x05, 0x02, + 0x87, 0xbf, 0x01, 0x36, 0x03, 0x01, 0x04, 0x02, 0x88, 0x02, 0x1c, 0x33, 0x66, 0x33, 0xfe, 0xb0, 0x02, 0xca, 0xfd, + 0xe9, 0x32, 0x62, 0x31, 0x01, 0x52, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0xdf, 0x02, 0xd5, 0x00, 0x0f, 0x00, + 0x1b, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, + 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x25, 0x26, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, + 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xdf, 0x49, 0x96, 0x75, 0x74, 0x97, 0x49, 0x49, 0x97, 0x75, 0x74, 0x97, 0x48, + 0xfd, 0xf9, 0x55, 0x5e, 0x60, 0x53, 0x53, 0x5f, 0x5f, 0x55, 0x01, 0x66, 0x6f, 0xa5, 0x5c, 0x5c, 0xa6, 0x6f, 0x6e, + 0xa5, 0x5b, 0x5b, 0xa5, 0x6f, 0x70, 0x7f, 0x7f, 0x70, 0x70, 0x80, 0x80, 0x00, 0x02, 0x00, 0x55, 0x00, 0x00, 0x02, + 0x43, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x32, 0x40, 0x2f, 0x00, 0x04, 0x00, 0x01, 0x02, 0x04, 0x01, 0x69, + 0x06, 0x01, 0x03, 0x03, 0x00, 0x5f, 0x05, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0d, + 0x0c, 0x01, 0x00, 0x10, 0x0e, 0x0c, 0x14, 0x0d, 0x14, 0x0a, 0x09, 0x08, 0x06, 0x00, 0x0b, 0x01, 0x0b, 0x07, 0x0d, + 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x23, 0x15, 0x23, 0x11, 0x17, 0x23, 0x15, 0x33, 0x32, + 0x36, 0x35, 0x34, 0x26, 0x01, 0x35, 0x8a, 0x84, 0x34, 0x79, 0x67, 0x41, 0x99, 0xdb, 0x42, 0x33, 0x3f, 0x49, 0x3b, + 0x02, 0xca, 0x73, 0x69, 0x3f, 0x6e, 0x44, 0xfd, 0x02, 0xca, 0x7d, 0xd2, 0x32, 0x3c, 0x30, 0x34, 0x00, 0x02, 0x00, + 0x37, 0xff, 0x56, 0x02, 0xdf, 0x02, 0xd5, 0x00, 0x14, 0x00, 0x20, 0x00, 0x2b, 0x40, 0x28, 0x03, 0x01, 0x01, 0x03, + 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x86, 0x00, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x03, + 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x25, 0x26, 0x41, 0x14, 0x05, 0x0d, 0x1b, 0x2b, 0x01, + 0x14, 0x06, 0x07, 0x17, 0x23, 0x27, 0x22, 0x22, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xdf, 0x55, 0x5a, 0xad, 0xc5, + 0x7f, 0x03, 0x08, 0x03, 0x74, 0x97, 0x49, 0x49, 0x97, 0x75, 0x74, 0x97, 0x48, 0xfd, 0xf9, 0x55, 0x5e, 0x60, 0x53, + 0x53, 0x5f, 0x5f, 0x55, 0x01, 0x66, 0x77, 0xb0, 0x29, 0xc0, 0xa0, 0x5c, 0xa6, 0x6f, 0x6e, 0xa5, 0x5b, 0x5b, 0xa5, + 0x6f, 0x70, 0x7f, 0x7f, 0x70, 0x70, 0x80, 0x80, 0x00, 0x02, 0x00, 0x55, 0x00, 0x00, 0x02, 0x91, 0x02, 0xca, 0x00, + 0x0c, 0x00, 0x15, 0x00, 0x3b, 0x40, 0x38, 0x05, 0x01, 0x02, 0x05, 0x01, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, + 0x02, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, + 0x01, 0x4e, 0x0e, 0x0d, 0x01, 0x00, 0x11, 0x0f, 0x0d, 0x15, 0x0e, 0x15, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x00, + 0x0c, 0x01, 0x0c, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x20, 0x15, 0x14, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x11, 0x23, + 0x11, 0x17, 0x23, 0x15, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x30, 0x01, 0x17, 0x4a, 0x37, 0xcb, 0xaf, 0x9f, + 0x55, 0x99, 0xd8, 0x3f, 0x3f, 0x3d, 0x42, 0x3d, 0x02, 0xca, 0xd0, 0x49, 0x5c, 0x1a, 0xfe, 0xc5, 0x01, 0x12, 0xfe, + 0xee, 0x02, 0xca, 0x77, 0xcb, 0x32, 0x39, 0x30, 0x30, 0x00, 0x01, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xff, 0x02, 0xd4, + 0x00, 0x28, 0x00, 0x2e, 0x40, 0x2b, 0x1b, 0x01, 0x03, 0x02, 0x1c, 0x06, 0x02, 0x01, 0x03, 0x05, 0x01, 0x00, 0x01, + 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x25, 0x2d, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, 0x22, 0x27, 0x35, + 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x2e, 0x03, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xff, 0x89, 0x7e, 0x71, 0x59, 0x33, + 0x6d, 0x36, 0x38, 0x2f, 0x25, 0x3e, 0x28, 0x19, 0x3a, 0x35, 0x22, 0x82, 0x70, 0x38, 0x65, 0x37, 0x31, 0x31, 0x4e, + 0x29, 0x2b, 0x2e, 0x44, 0x43, 0x37, 0x4d, 0x2a, 0xc6, 0x5f, 0x71, 0x2b, 0x8d, 0x16, 0x25, 0x2b, 0x21, 0x1b, 0x26, + 0x21, 0x13, 0x0c, 0x21, 0x31, 0x46, 0x31, 0x60, 0x6b, 0x1a, 0x18, 0x76, 0x14, 0x16, 0x28, 0x20, 0x26, 0x2c, 0x20, + 0x1a, 0x38, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x13, 0x00, 0x00, 0x02, 0x2e, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1b, 0x40, + 0x18, 0x03, 0x01, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, + 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x11, 0x23, 0x35, 0x21, 0x15, 0x23, 0x01, 0x6d, 0x99, 0xc1, + 0x02, 0x1b, 0xc1, 0x02, 0x4b, 0x7f, 0x7f, 0x00, 0x01, 0x00, 0x55, 0xff, 0xf6, 0x02, 0x9f, 0x02, 0xca, 0x00, 0x12, + 0x00, 0x1b, 0x40, 0x18, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x00, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x13, 0x23, 0x13, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, + 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x02, 0x9f, 0x41, 0x83, 0x64, 0x8e, 0x94, 0x97, 0x48, + 0x47, 0x4a, 0x43, 0x97, 0xfc, 0x4a, 0x77, 0x45, 0x91, 0x77, 0x01, 0xcc, 0xfe, 0x4b, 0x58, 0x48, 0x4e, 0x53, 0x01, + 0xb4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x8a, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x21, 0x40, 0x1e, 0x09, + 0x01, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x02, 0x02, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x01, 0x03, 0x23, 0x03, 0x33, 0x13, 0x1e, 0x02, + 0x17, 0x3e, 0x02, 0x37, 0x13, 0x02, 0x8a, 0xf3, 0xa5, 0xf2, 0x99, 0x86, 0x04, 0x0f, 0x10, 0x03, 0x03, 0x0f, 0x10, + 0x03, 0x87, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0xfe, 0x57, 0x0b, 0x3b, 0x41, 0x16, 0x16, 0x41, 0x3b, 0x0b, 0x01, + 0xa9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc7, 0x02, 0xca, 0x00, 0x26, 0x00, 0x27, 0x40, 0x24, 0x21, 0x16, + 0x08, 0x03, 0x00, 0x02, 0x01, 0x4c, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, + 0x00, 0x4e, 0x00, 0x00, 0x00, 0x26, 0x00, 0x26, 0x1a, 0x11, 0x1c, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x01, 0x03, 0x23, + 0x03, 0x2e, 0x03, 0x27, 0x0e, 0x03, 0x07, 0x03, 0x23, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x17, 0x3e, 0x02, 0x37, 0x13, + 0x33, 0x13, 0x1e, 0x02, 0x17, 0x3e, 0x02, 0x37, 0x13, 0x03, 0xc7, 0xb6, 0xac, 0x61, 0x03, 0x09, 0x0b, 0x08, 0x02, + 0x01, 0x09, 0x0a, 0x0a, 0x03, 0x60, 0xac, 0xb6, 0x95, 0x5b, 0x06, 0x0e, 0x0c, 0x03, 0x03, 0x0c, 0x0d, 0x05, 0x68, + 0x8f, 0x68, 0x05, 0x0d, 0x0c, 0x03, 0x03, 0x0c, 0x0f, 0x05, 0x5b, 0x02, 0xca, 0xfd, 0x36, 0x01, 0x77, 0x0b, 0x2c, + 0x34, 0x2f, 0x0d, 0x0d, 0x2f, 0x33, 0x2d, 0x0c, 0xfe, 0x8a, 0x02, 0xca, 0xfe, 0x7a, 0x17, 0x46, 0x46, 0x18, 0x19, + 0x45, 0x41, 0x12, 0x01, 0x90, 0xfe, 0x70, 0x11, 0x42, 0x46, 0x18, 0x19, 0x45, 0x46, 0x17, 0x01, 0x86, 0x00, 0x01, + 0x00, 0x03, 0x00, 0x00, 0x02, 0x9a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x08, 0x05, 0x02, 0x04, + 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x12, + 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x03, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x02, + 0x9a, 0xb0, 0x9e, 0x9f, 0xaa, 0xed, 0xdf, 0xaa, 0x93, 0x90, 0xab, 0xe0, 0x01, 0x01, 0xfe, 0xff, 0x01, 0x70, 0x01, + 0x5a, 0xf4, 0xf4, 0xfe, 0x9d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x72, 0x02, 0xca, 0x00, 0x08, 0x00, + 0x1c, 0x40, 0x19, 0x06, 0x03, 0x02, 0x01, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, + 0x6b, 0x01, 0x4e, 0x12, 0x12, 0x11, 0x03, 0x0d, 0x19, 0x2b, 0x01, 0x13, 0x33, 0x03, 0x11, 0x23, 0x11, 0x03, 0x33, + 0x01, 0x39, 0x93, 0xa6, 0xec, 0x9a, 0xec, 0xa6, 0x01, 0x9f, 0x01, 0x2b, 0xfe, 0x4c, 0xfe, 0xea, 0x01, 0x11, 0x01, + 0xb9, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x02, 0x2b, 0x02, 0xca, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x07, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x4d, + 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, + 0x21, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x21, 0x02, 0x2b, 0xfd, 0xed, 0x01, 0x56, 0xfe, 0xb3, 0x02, + 0x01, 0xfe, 0xaa, 0x01, 0x5f, 0x62, 0x01, 0xeb, 0x7d, 0x62, 0xfe, 0x15, 0x00, 0x01, 0x00, 0x46, 0xff, 0x62, 0x01, + 0x32, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x63, 0x00, 0x02, 0x02, + 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x02, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x05, 0x23, 0x11, + 0x33, 0x15, 0x23, 0x11, 0x33, 0x01, 0x32, 0xec, 0xec, 0x6d, 0x6d, 0x9e, 0x03, 0x68, 0x67, 0xfd, 0x66, 0x00, 0x01, + 0x00, 0x06, 0xff, 0xfa, 0x01, 0x99, 0x02, 0xd0, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, + 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, + 0x01, 0x23, 0x01, 0x8e, 0x01, 0x0b, 0x89, 0xfe, 0xf6, 0x02, 0xd0, 0xfd, 0x2a, 0x02, 0xd6, 0x00, 0x00, 0x01, 0x00, + 0x19, 0xff, 0x62, 0x01, 0x05, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, + 0x63, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, + 0x2b, 0x17, 0x33, 0x11, 0x23, 0x35, 0x33, 0x11, 0x23, 0x19, 0x6d, 0x6d, 0xec, 0xec, 0x37, 0x02, 0x9a, 0x67, 0xfc, + 0x98, 0x00, 0x00, 0x01, 0x00, 0x17, 0x00, 0xfe, 0x02, 0x25, 0x02, 0xce, 0x00, 0x06, 0x00, 0x27, 0xb1, 0x06, 0x64, + 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x03, 0x02, 0x02, 0x01, 0x01, + 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x37, 0x13, + 0x33, 0x13, 0x23, 0x03, 0x03, 0x17, 0xd6, 0x46, 0xf2, 0x75, 0x9d, 0x89, 0xfe, 0x01, 0xd0, 0xfe, 0x30, 0x01, 0x3a, + 0xfe, 0xc6, 0x00, 0x01, 0xff, 0xfe, 0xff, 0x62, 0x01, 0x9d, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x20, 0xb1, 0x06, 0x64, + 0x44, 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, + 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x05, 0x21, 0x35, 0x21, 0x01, 0x9d, 0xfe, 0x61, 0x01, + 0x9f, 0x9e, 0x44, 0x00, 0x01, 0x00, 0x28, 0x02, 0x5e, 0x01, 0x45, 0x02, 0xfe, 0x00, 0x0c, 0x00, 0x26, 0xb1, 0x06, + 0x64, 0x44, 0x40, 0x1b, 0x0b, 0x04, 0x02, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x00, 0x01, 0x85, 0x00, 0x00, + 0x00, 0x76, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x13, 0x1e, + 0x02, 0x17, 0x15, 0x23, 0x2e, 0x03, 0x27, 0x35, 0xd1, 0x0f, 0x2a, 0x2a, 0x11, 0x65, 0x13, 0x33, 0x35, 0x2f, 0x0e, + 0x02, 0xfe, 0x16, 0x37, 0x33, 0x13, 0x0d, 0x0d, 0x27, 0x2c, 0x28, 0x0e, 0x0a, 0x00, 0x02, 0x00, 0x28, 0xff, 0xf6, + 0x02, 0x10, 0x02, 0x2c, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x7b, 0x40, 0x0e, 0x19, 0x01, 0x04, 0x00, 0x18, 0x01, 0x03, + 0x04, 0x06, 0x01, 0x01, 0x06, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x20, 0x00, 0x03, 0x08, 0x01, 0x05, + 0x06, 0x03, 0x05, 0x69, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x01, + 0x61, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x24, 0x00, 0x03, 0x08, 0x01, 0x05, 0x06, 0x03, 0x05, + 0x69, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x00, 0x06, + 0x06, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, + 0x26, 0x1d, 0x26, 0x16, 0x14, 0x11, 0x0f, 0x0b, 0x09, 0x05, 0x04, 0x00, 0x1b, 0x01, 0x1b, 0x09, 0x0d, 0x16, 0x2b, + 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x13, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, + 0x35, 0x01, 0x3d, 0x66, 0x6d, 0x69, 0x1d, 0x04, 0x24, 0x4d, 0x45, 0x48, 0x60, 0x7c, 0x7b, 0x5b, 0x2d, 0x27, 0x25, + 0x4e, 0x26, 0x2c, 0x2b, 0x6f, 0x46, 0x48, 0x37, 0x27, 0x21, 0x2f, 0x41, 0x02, 0x2c, 0x61, 0x5f, 0xfe, 0x94, 0x4a, + 0x2c, 0x28, 0x54, 0x57, 0x55, 0x57, 0x05, 0x03, 0x11, 0x31, 0x27, 0x18, 0x11, 0x67, 0x16, 0x1a, 0xfe, 0xce, 0x02, + 0x2a, 0x26, 0x23, 0x21, 0x38, 0x34, 0x2d, 0x00, 0x00, 0x02, 0x00, 0x49, 0xff, 0xf6, 0x02, 0x48, 0x02, 0xf8, 0x00, + 0x15, 0x00, 0x21, 0x00, 0x6b, 0xb5, 0x03, 0x01, 0x05, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x21, + 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, 0x04, + 0x6c, 0x4d, 0x00, 0x06, 0x06, 0x01, 0x61, 0x03, 0x01, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1b, 0x40, 0x25, 0x07, 0x01, + 0x05, 0x05, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6c, 0x4d, + 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x59, 0x40, 0x10, + 0x17, 0x16, 0x1e, 0x1c, 0x16, 0x21, 0x17, 0x21, 0x11, 0x11, 0x12, 0x24, 0x26, 0x08, 0x0d, 0x1b, 0x2b, 0x13, 0x14, + 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x07, 0x23, 0x11, + 0x33, 0x13, 0x22, 0x06, 0x15, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0xe0, 0x04, 0x02, 0x06, 0x16, 0x4a, + 0x3b, 0x5b, 0x72, 0x73, 0x5e, 0x3c, 0x45, 0x16, 0x0a, 0x19, 0x74, 0x97, 0x6a, 0x39, 0x31, 0x2f, 0x3d, 0x31, 0x32, + 0x02, 0x47, 0x1f, 0x38, 0x15, 0x22, 0x2f, 0x8f, 0x8b, 0x8c, 0x90, 0x2b, 0x1a, 0x3b, 0x02, 0xf8, 0xfe, 0xbc, 0x48, + 0x4d, 0x12, 0x4e, 0x4f, 0x54, 0x50, 0xa0, 0x00, 0x01, 0x00, 0x2f, 0xff, 0xf6, 0x01, 0xe8, 0x02, 0x2c, 0x00, 0x1b, + 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, 0x02, 0x01, 0x18, 0x0c, 0x02, 0x03, 0x02, 0x19, 0x01, 0x00, 0x03, 0x03, 0x4c, + 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x01, 0x00, 0x16, 0x14, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x05, 0x0d, 0x16, 0x2b, + 0x05, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x01, 0x37, 0x4f, 0x77, 0x42, 0x48, 0x7c, 0x4f, 0x2f, 0x56, + 0x21, 0x2d, 0x1e, 0x3d, 0x1e, 0x3a, 0x3f, 0x3f, 0x38, 0x2a, 0x4e, 0x21, 0x20, 0x4d, 0x0a, 0x3b, 0x7c, 0x61, 0x64, + 0x7f, 0x3b, 0x14, 0x11, 0x72, 0x0d, 0x11, 0x52, 0x52, 0x51, 0x4e, 0x17, 0x13, 0x7b, 0x13, 0x16, 0x00, 0x02, 0x00, + 0x2f, 0xff, 0xf6, 0x02, 0x2f, 0x02, 0xf8, 0x00, 0x15, 0x00, 0x22, 0x00, 0x82, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, + 0x0a, 0x09, 0x01, 0x05, 0x01, 0x12, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x09, 0x01, 0x05, 0x01, 0x12, + 0x01, 0x03, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, + 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x22, 0x17, 0x22, 0x11, 0x10, 0x0f, 0x0e, + 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, + 0x17, 0x33, 0x26, 0x26, 0x35, 0x35, 0x33, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x27, 0x32, 0x36, 0x37, 0x35, 0x34, + 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0xfc, 0x5b, 0x72, 0x74, 0x5e, 0x3a, 0x48, 0x17, 0x05, 0x03, 0x05, 0x98, + 0x74, 0x1e, 0x06, 0x15, 0x4a, 0x07, 0x3d, 0x32, 0x01, 0x30, 0x41, 0x31, 0x37, 0x37, 0x0a, 0x8f, 0x8b, 0x8d, 0x8f, + 0x2e, 0x22, 0x12, 0x41, 0x1b, 0xae, 0xfd, 0x08, 0x47, 0x22, 0x2f, 0x79, 0x47, 0x49, 0x10, 0x4f, 0x54, 0x54, 0x50, + 0x50, 0x4f, 0x00, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x27, 0x02, 0x2c, 0x00, 0x15, 0x00, 0x1c, 0x00, 0x43, + 0x40, 0x40, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, 0x03, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x01, 0x02, 0x05, 0x01, + 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, + 0x03, 0x03, 0x71, 0x03, 0x4e, 0x17, 0x16, 0x01, 0x00, 0x1a, 0x19, 0x16, 0x1c, 0x17, 0x1c, 0x10, 0x0e, 0x09, 0x07, + 0x05, 0x04, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x15, 0x21, 0x16, 0x16, 0x33, + 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x07, 0x33, 0x26, + 0x26, 0x01, 0x32, 0x72, 0x83, 0xfe, 0xa1, 0x03, 0x47, 0x43, 0x33, 0x54, 0x2c, 0x28, 0x5a, 0x41, 0x51, 0x7d, 0x48, + 0x8f, 0x78, 0x2d, 0x39, 0x04, 0xce, 0x01, 0x31, 0x02, 0x2c, 0x80, 0x78, 0x49, 0x3e, 0x47, 0x14, 0x14, 0x71, 0x14, + 0x13, 0x3d, 0x7c, 0x5e, 0x8f, 0x90, 0x6b, 0x39, 0x38, 0x31, 0x40, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x01, 0xb0, + 0x02, 0xfd, 0x00, 0x18, 0x00, 0x86, 0x40, 0x13, 0x0f, 0x01, 0x04, 0x03, 0x10, 0x01, 0x05, 0x04, 0x06, 0x01, 0x00, + 0x05, 0x03, 0x4c, 0x07, 0x01, 0x05, 0x01, 0x4b, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, + 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, + 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, + 0x03, 0x6c, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, + 0x4e, 0x1b, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, + 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x59, 0x40, 0x09, 0x13, 0x25, 0x26, + 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x37, 0x35, 0x34, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x15, 0x33, 0x01, 0x7c, 0x81, 0x95, 0x52, 0x52, + 0x2f, 0x57, 0x3b, 0x2c, 0x47, 0x16, 0x26, 0x11, 0x28, 0x1a, 0x1f, 0x1d, 0x81, 0x01, 0xb2, 0xfe, 0x4e, 0x01, 0xb2, + 0x48, 0x28, 0x28, 0x46, 0x4d, 0x20, 0x0e, 0x09, 0x6d, 0x05, 0x09, 0x26, 0x1d, 0x22, 0x00, 0x02, 0x00, 0x2f, 0xff, + 0x10, 0x02, 0x2f, 0x02, 0x2c, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x9e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x03, + 0x01, 0x05, 0x00, 0x18, 0x01, 0x04, 0x06, 0x0e, 0x01, 0x03, 0x04, 0x0d, 0x01, 0x02, 0x03, 0x04, 0x4c, 0x1b, 0x40, + 0x12, 0x03, 0x01, 0x05, 0x01, 0x18, 0x01, 0x04, 0x06, 0x0e, 0x01, 0x03, 0x04, 0x0d, 0x01, 0x02, 0x03, 0x04, 0x4c, + 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x08, 0x01, 0x05, 0x05, 0x00, 0x61, 0x01, 0x07, 0x02, 0x00, 0x00, + 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, + 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x00, 0x61, 0x07, + 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, + 0x61, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x23, 0x22, 0x01, 0x00, 0x28, 0x26, 0x22, 0x2d, 0x23, + 0x2d, 0x1d, 0x1b, 0x12, 0x10, 0x0b, 0x09, 0x06, 0x05, 0x00, 0x21, 0x01, 0x21, 0x09, 0x0d, 0x16, 0x2b, 0x13, 0x32, + 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, + 0x35, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x33, + 0x32, 0x36, 0x35, 0x35, 0x34, 0x26, 0xff, 0x38, 0x4d, 0x19, 0x05, 0x0d, 0x80, 0x86, 0x8c, 0x3f, 0x64, 0x2c, 0x2e, + 0x5e, 0x3e, 0x3e, 0x42, 0x03, 0x02, 0x05, 0x17, 0x4b, 0x38, 0x5f, 0x70, 0x72, 0x8f, 0x32, 0x35, 0x6a, 0x3c, 0x33, + 0x33, 0x02, 0x2c, 0x2b, 0x24, 0x45, 0xfd, 0xda, 0x74, 0x78, 0x0f, 0x12, 0x80, 0x14, 0x16, 0x3a, 0x33, 0x0f, 0x0c, + 0x28, 0x0f, 0x24, 0x2c, 0x92, 0x88, 0x88, 0x94, 0x77, 0x56, 0x51, 0xa2, 0x46, 0x4a, 0x16, 0x52, 0x51, 0x00, 0x01, + 0x00, 0x49, 0x00, 0x00, 0x02, 0x43, 0x02, 0xf8, 0x00, 0x16, 0x00, 0x27, 0x40, 0x24, 0x03, 0x01, 0x02, 0x00, 0x01, + 0x4c, 0x00, 0x04, 0x04, 0x6c, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, + 0x01, 0x6b, 0x01, 0x4e, 0x11, 0x13, 0x22, 0x13, 0x26, 0x05, 0x0d, 0x1b, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0xe0, 0x04, + 0x03, 0x08, 0x1b, 0x51, 0x32, 0x58, 0x6c, 0x97, 0x57, 0x43, 0x32, 0x97, 0x97, 0x02, 0x5f, 0x2d, 0x43, 0x13, 0x2a, + 0x26, 0x5f, 0x69, 0xfe, 0x9c, 0x01, 0x3e, 0x76, 0x5d, 0x57, 0xff, 0x00, 0x02, 0xf8, 0x00, 0x00, 0x02, 0x00, 0x44, + 0x00, 0x00, 0x00, 0xe8, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x01, 0x01, 0x00, 0x61, + 0x04, 0x01, 0x00, 0x00, 0x72, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0c, + 0x0c, 0x01, 0x00, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, + 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x11, 0x23, 0x11, 0x96, 0x21, 0x31, + 0x31, 0x21, 0x22, 0x30, 0x30, 0x6d, 0x97, 0x02, 0xf9, 0x1f, 0x2b, 0x29, 0x20, 0x20, 0x29, 0x2b, 0x1f, 0xd7, 0xfd, + 0xde, 0x02, 0x22, 0x00, 0x02, 0xff, 0xcb, 0xff, 0x10, 0x00, 0xe8, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x1c, 0x00, 0x37, + 0x40, 0x34, 0x10, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x72, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x62, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, + 0x4e, 0x0d, 0x0c, 0x18, 0x17, 0x14, 0x12, 0x0c, 0x1c, 0x0d, 0x1c, 0x24, 0x22, 0x06, 0x0d, 0x18, 0x2b, 0x13, 0x34, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x03, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, + 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x06, 0x44, 0x2f, 0x23, 0x21, 0x31, 0x31, 0x21, 0x23, 0x2f, 0x1c, 0x18, + 0x33, 0x12, 0x10, 0x1c, 0x12, 0x1b, 0x25, 0x97, 0x24, 0x51, 0x02, 0xaf, 0x2b, 0x1f, 0x1f, 0x2b, 0x29, 0x20, 0x20, + 0xfc, 0x8a, 0x07, 0x05, 0x77, 0x05, 0x05, 0x22, 0x32, 0x02, 0x45, 0xfd, 0xa3, 0x32, 0x52, 0x31, 0x00, 0x01, 0x00, + 0x4e, 0x00, 0x00, 0x02, 0x6c, 0x02, 0xf8, 0x00, 0x12, 0x00, 0x24, 0x40, 0x21, 0x0e, 0x0d, 0x0a, 0x03, 0x04, 0x01, + 0x00, 0x01, 0x4c, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, + 0x4e, 0x11, 0x13, 0x12, 0x18, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x37, 0x33, + 0x07, 0x13, 0x23, 0x27, 0x07, 0x15, 0x23, 0x11, 0x33, 0xe3, 0x05, 0x03, 0x02, 0x0f, 0x20, 0x12, 0x99, 0xa8, 0xd9, + 0xe6, 0xac, 0x9d, 0x40, 0x95, 0x95, 0x01, 0xa4, 0x1f, 0x3d, 0x1f, 0x15, 0x2b, 0x13, 0xa6, 0xed, 0xfe, 0xcb, 0xdd, + 0x33, 0xaa, 0x02, 0xf8, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x00, 0xe0, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x13, 0x40, + 0x10, 0x00, 0x01, 0x01, 0x6c, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x33, + 0x23, 0x11, 0x33, 0xe0, 0x97, 0x97, 0x02, 0xf8, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x03, 0x88, 0x02, 0x2c, 0x00, + 0x24, 0x00, 0x6c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0xb6, 0x21, 0x1a, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x1b, 0xb6, 0x21, + 0x1a, 0x02, 0x02, 0x06, 0x01, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x04, 0x01, 0x02, 0x02, 0x00, + 0x61, 0x07, 0x06, 0x08, 0x03, 0x00, 0x00, 0x73, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, + 0x1a, 0x00, 0x06, 0x06, 0x6d, 0x4d, 0x04, 0x01, 0x02, 0x02, 0x00, 0x61, 0x07, 0x08, 0x02, 0x00, 0x00, 0x73, 0x4d, + 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x17, 0x01, 0x00, 0x1f, 0x1d, 0x19, 0x18, 0x17, 0x16, + 0x13, 0x11, 0x0e, 0x0d, 0x0a, 0x08, 0x05, 0x04, 0x00, 0x24, 0x01, 0x24, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, + 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, + 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x36, 0x36, 0x02, 0xca, 0x5e, 0x60, + 0x96, 0x2a, 0x2a, 0x3b, 0x2f, 0x97, 0x28, 0x2a, 0x3e, 0x2d, 0x97, 0x74, 0x16, 0x05, 0x17, 0x54, 0x38, 0x3d, 0x51, + 0x17, 0x05, 0x1b, 0x56, 0x02, 0x2c, 0x5f, 0x69, 0xfe, 0x9c, 0x01, 0x3e, 0x3f, 0x37, 0x55, 0x4e, 0xfe, 0xef, 0x01, + 0x3e, 0x3d, 0x39, 0x5d, 0x57, 0xff, 0x00, 0x02, 0x22, 0x46, 0x25, 0x2b, 0x2a, 0x28, 0x29, 0x29, 0x00, 0x00, 0x01, + 0x00, 0x49, 0x00, 0x00, 0x02, 0x43, 0x02, 0x2c, 0x00, 0x12, 0x00, 0x5e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0xb5, 0x10, + 0x01, 0x02, 0x00, 0x01, 0x4c, 0x1b, 0xb5, 0x10, 0x01, 0x02, 0x04, 0x01, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x13, 0x00, 0x02, 0x02, 0x00, 0x61, 0x04, 0x05, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, + 0x01, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x05, 0x01, 0x00, 0x00, + 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x09, + 0x07, 0x05, 0x04, 0x00, 0x12, 0x01, 0x12, 0x06, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, + 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x01, 0x81, 0x5a, 0x68, 0x96, 0x58, 0x44, 0x31, + 0x97, 0x74, 0x15, 0x06, 0x36, 0x02, 0x2c, 0x5f, 0x69, 0xfe, 0x9c, 0x01, 0x3e, 0x76, 0x5d, 0x57, 0xff, 0x00, 0x02, + 0x22, 0x49, 0x53, 0x00, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x41, 0x02, 0x2c, 0x00, 0x0d, 0x00, 0x19, 0x00, + 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x25, 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x23, 0x22, 0x26, + 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x06, 0x02, 0x41, 0x8f, 0x7b, 0x4d, 0x77, 0x44, 0x8f, 0x7c, 0x4d, 0x76, 0x44, 0xfe, 0x88, 0x34, 0x3c, 0x3a, 0x34, + 0x34, 0x3b, 0x3b, 0x34, 0x01, 0x12, 0x88, 0x94, 0x42, 0x7f, 0x5b, 0x88, 0x92, 0x41, 0x7e, 0x5b, 0x50, 0x59, 0x59, + 0x50, 0x51, 0x56, 0x56, 0x00, 0x02, 0x00, 0x49, 0xff, 0x10, 0x02, 0x48, 0x02, 0x2c, 0x00, 0x15, 0x00, 0x21, 0x00, + 0x82, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x12, 0x01, 0x04, 0x00, 0x09, 0x01, 0x01, 0x05, 0x02, 0x4c, 0x1b, + 0x40, 0x0a, 0x12, 0x01, 0x04, 0x03, 0x09, 0x01, 0x01, 0x05, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, + 0x1d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x03, 0x03, 0x6d, 0x4d, + 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, 0x1e, 0x1c, 0x16, + 0x21, 0x17, 0x21, 0x11, 0x10, 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x16, 0x16, 0x15, 0x15, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, + 0x36, 0x17, 0x22, 0x06, 0x07, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x01, 0x7b, 0x5e, 0x6f, 0x75, 0x5c, + 0x3c, 0x47, 0x14, 0x06, 0x02, 0x04, 0x97, 0x7b, 0x15, 0x07, 0x16, 0x48, 0x0b, 0x3a, 0x2d, 0x02, 0x2d, 0x3d, 0x33, + 0x32, 0x02, 0x2c, 0x8f, 0x8b, 0x8c, 0x90, 0x2b, 0x1a, 0x12, 0x2f, 0x19, 0xd1, 0x03, 0x12, 0x47, 0x21, 0x30, 0x78, + 0x48, 0x49, 0x10, 0x4f, 0x54, 0x54, 0x50, 0xa0, 0x00, 0x02, 0x00, 0x2f, 0xff, 0x10, 0x02, 0x2f, 0x02, 0x2c, 0x00, + 0x15, 0x00, 0x21, 0x00, 0x78, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x10, 0x01, 0x05, 0x01, 0x03, 0x01, 0x00, + 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x10, 0x01, 0x05, 0x02, 0x03, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, + 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, + 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x02, + 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x17, 0x16, 0x1e, 0x1c, 0x16, + 0x21, 0x17, 0x21, 0x11, 0x14, 0x24, 0x26, 0x07, 0x0d, 0x1a, 0x2b, 0x05, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x23, 0x03, 0x32, 0x36, 0x35, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x01, 0x98, 0x02, 0x03, 0x06, 0x15, 0x49, 0x3c, 0x5c, 0x72, 0x74, 0x5d, + 0x3c, 0x4a, 0x17, 0x04, 0x0e, 0x80, 0x97, 0x65, 0x3d, 0x31, 0x2f, 0x42, 0x34, 0x33, 0x0b, 0x13, 0x2c, 0x13, 0x22, + 0x2f, 0x8f, 0x8b, 0x8c, 0x90, 0x2e, 0x22, 0x46, 0xfc, 0xee, 0x01, 0x5d, 0x47, 0x49, 0x15, 0x4f, 0x55, 0x58, 0x50, + 0xa1, 0x00, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x01, 0xb3, 0x02, 0x2c, 0x00, 0x13, 0x00, 0x69, 0x4b, 0xb0, 0x19, + 0x50, 0x58, 0x40, 0x0b, 0x10, 0x03, 0x02, 0x01, 0x00, 0x04, 0x01, 0x02, 0x01, 0x02, 0x4c, 0x1b, 0x40, 0x0e, 0x03, + 0x01, 0x03, 0x00, 0x10, 0x01, 0x01, 0x03, 0x04, 0x01, 0x02, 0x01, 0x03, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x12, 0x00, 0x01, 0x01, 0x00, 0x61, 0x03, 0x04, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, + 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x73, + 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0f, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x08, 0x06, 0x00, + 0x13, 0x01, 0x13, 0x05, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, + 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x01, 0x77, 0x0f, 0x22, 0x0b, 0x0f, 0x0b, 0x1e, 0x15, 0x1f, 0x3e, + 0x29, 0x97, 0x73, 0x16, 0x07, 0x18, 0x53, 0x02, 0x2c, 0x04, 0x02, 0x8d, 0x03, 0x03, 0x1a, 0x3c, 0x34, 0xfe, 0xeb, + 0x02, 0x22, 0x5c, 0x2a, 0x3c, 0x00, 0x01, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xcc, 0x02, 0x2c, 0x00, 0x27, 0x00, 0x2e, + 0x40, 0x2b, 0x1a, 0x01, 0x03, 0x02, 0x1b, 0x07, 0x02, 0x01, 0x03, 0x06, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, + 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x25, 0x2b, 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, + 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, + 0x23, 0x22, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xcc, 0x6f, 0x73, 0x3a, 0x58, 0x29, 0x2c, 0x65, 0x26, + 0x2e, 0x29, 0x15, 0x35, 0x31, 0x49, 0x4b, 0x77, 0x62, 0x34, 0x5c, 0x2f, 0x2c, 0x26, 0x50, 0x1f, 0x48, 0x15, 0x35, + 0x30, 0x31, 0x43, 0x21, 0xa1, 0x4e, 0x5d, 0x0f, 0x11, 0x7d, 0x15, 0x18, 0x1a, 0x16, 0x0f, 0x18, 0x1a, 0x13, 0x1d, + 0x47, 0x44, 0x4c, 0x4e, 0x16, 0x14, 0x67, 0x11, 0x16, 0x28, 0x0f, 0x15, 0x18, 0x13, 0x14, 0x2a, 0x3d, 0x00, 0x01, + 0x00, 0x17, 0xff, 0xf6, 0x01, 0x92, 0x02, 0x96, 0x00, 0x18, 0x00, 0x40, 0x40, 0x3d, 0x0e, 0x01, 0x02, 0x04, 0x03, + 0x01, 0x00, 0x02, 0x04, 0x01, 0x01, 0x00, 0x03, 0x4c, 0x00, 0x03, 0x04, 0x03, 0x85, 0x05, 0x01, 0x02, 0x02, 0x04, + 0x5f, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x06, 0x01, 0x00, 0x00, 0x01, 0x62, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x01, + 0x00, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x18, 0x01, 0x18, 0x07, 0x0d, 0x16, 0x2b, + 0x25, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x11, 0x23, 0x35, 0x37, 0x37, 0x33, 0x15, + 0x33, 0x15, 0x23, 0x11, 0x14, 0x16, 0x01, 0x34, 0x19, 0x2e, 0x17, 0x18, 0x47, 0x2a, 0x31, 0x4d, 0x2d, 0x47, 0x52, + 0x2b, 0x5f, 0x99, 0x99, 0x24, 0x6d, 0x0a, 0x07, 0x6f, 0x0a, 0x0f, 0x20, 0x4f, 0x46, 0x01, 0x07, 0x3f, 0x32, 0x73, + 0x74, 0x70, 0xfe, 0xf9, 0x1f, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x46, 0xff, 0xf6, 0x02, 0x40, 0x02, 0x22, 0x00, 0x14, + 0x00, 0x50, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x18, 0x00, 0x01, 0x01, 0x03, 0x5f, 0x06, 0x05, 0x02, 0x03, 0x03, + 0x6d, 0x4d, 0x00, 0x04, 0x04, 0x00, 0x62, 0x02, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1b, 0x40, 0x1c, 0x00, 0x01, + 0x01, 0x03, 0x5f, 0x06, 0x05, 0x02, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0x00, 0x04, 0x04, 0x02, + 0x62, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x59, 0x40, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x23, 0x13, 0x22, + 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x01, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, + 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x02, 0x40, 0x74, 0x13, 0x09, 0x1a, 0x5a, 0x34, 0x57, 0x6b, 0x98, + 0x29, 0x2d, 0x44, 0x31, 0x02, 0x22, 0xfd, 0xde, 0x46, 0x2a, 0x26, 0x5f, 0x69, 0x01, 0x64, 0xfe, 0xc2, 0x3a, 0x3b, + 0x5c, 0x57, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3b, 0x02, 0x22, 0x00, 0x0d, 0x00, 0x21, + 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, + 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, + 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0xd0, 0xd0, 0x9e, 0x66, 0x05, 0x0f, 0x02, 0x04, 0x02, 0x0f, + 0x06, 0x68, 0x9e, 0xd0, 0x02, 0x22, 0xfe, 0xbe, 0x10, 0x37, 0x13, 0x14, 0x33, 0x12, 0x01, 0x43, 0xfd, 0xde, 0x00, + 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x03, 0x4e, 0x02, 0x22, 0x00, 0x2a, 0x00, 0x21, 0x40, 0x1e, 0x21, 0x14, 0x05, + 0x03, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x02, 0x02, 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, + 0x11, 0x1b, 0x1c, 0x11, 0x1c, 0x05, 0x0d, 0x1b, 0x2b, 0x25, 0x2e, 0x03, 0x27, 0x23, 0x0e, 0x03, 0x07, 0x07, 0x23, + 0x03, 0x33, 0x17, 0x1e, 0x02, 0x17, 0x33, 0x3e, 0x03, 0x37, 0x13, 0x33, 0x13, 0x1e, 0x02, 0x15, 0x33, 0x3e, 0x02, + 0x37, 0x37, 0x33, 0x03, 0x23, 0x01, 0xe5, 0x04, 0x0f, 0x12, 0x10, 0x03, 0x04, 0x03, 0x0f, 0x12, 0x10, 0x04, 0x2c, + 0xa0, 0x9b, 0x94, 0x3f, 0x07, 0x0b, 0x0a, 0x02, 0x04, 0x01, 0x06, 0x09, 0x07, 0x02, 0x43, 0xa4, 0x40, 0x04, 0x0b, + 0x09, 0x04, 0x02, 0x0a, 0x0d, 0x07, 0x41, 0x92, 0x9d, 0xa2, 0xbf, 0x11, 0x43, 0x4d, 0x41, 0x0f, 0x0f, 0x41, 0x4d, + 0x44, 0x12, 0xbd, 0x02, 0x22, 0xf2, 0x19, 0x46, 0x41, 0x13, 0x0e, 0x2f, 0x32, 0x29, 0x07, 0x01, 0x06, 0xfe, 0xfa, + 0x0e, 0x3e, 0x40, 0x13, 0x11, 0x41, 0x48, 0x19, 0xf2, 0xfd, 0xde, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x02, + 0x3d, 0x02, 0x22, 0x00, 0x0b, 0x00, 0x1f, 0x40, 0x1c, 0x09, 0x06, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, + 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x12, 0x12, 0x12, 0x11, 0x04, 0x0d, 0x1a, 0x2b, + 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x23, 0xbe, 0xb0, 0xa9, 0x6a, 0x6b, 0xa9, 0xb2, + 0xba, 0xa9, 0x73, 0x73, 0xa9, 0x01, 0x17, 0x01, 0x0b, 0xae, 0xae, 0xfe, 0xf5, 0xfe, 0xe9, 0xbb, 0xbb, 0x00, 0x00, + 0x01, 0x00, 0x00, 0xff, 0x10, 0x02, 0x3b, 0x02, 0x22, 0x00, 0x1a, 0x00, 0x27, 0x40, 0x24, 0x1a, 0x13, 0x05, 0x03, + 0x03, 0x00, 0x12, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x62, + 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x25, 0x23, 0x19, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x11, 0x33, 0x13, 0x16, 0x16, + 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, + 0x36, 0x37, 0x37, 0x9f, 0x67, 0x07, 0x0d, 0x03, 0x04, 0x03, 0x0f, 0x07, 0x65, 0x9c, 0xe0, 0x22, 0x69, 0x61, 0x1a, + 0x25, 0x0d, 0x0a, 0x20, 0x11, 0x2e, 0x32, 0x0f, 0x0c, 0x02, 0x22, 0xfe, 0xc8, 0x16, 0x31, 0x16, 0x15, 0x32, 0x16, + 0x01, 0x38, 0xfd, 0xac, 0x5c, 0x62, 0x05, 0x03, 0x77, 0x02, 0x04, 0x35, 0x27, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x1e, + 0x00, 0x00, 0x01, 0xce, 0x02, 0x22, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, + 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x13, 0x23, 0x35, + 0x21, 0x15, 0x03, 0x33, 0x01, 0xce, 0xfe, 0x50, 0xfc, 0xee, 0x01, 0x99, 0xf5, 0xfe, 0x59, 0x01, 0x56, 0x73, 0x61, + 0xfe, 0xb3, 0x00, 0x01, 0x00, 0x0f, 0xff, 0x62, 0x01, 0x62, 0x02, 0xca, 0x00, 0x1f, 0x00, 0x2c, 0x40, 0x29, 0x18, + 0x01, 0x01, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, + 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, 0x4e, 0x1b, 0x11, 0x16, 0x11, 0x16, 0x10, 0x06, + 0x0d, 0x1c, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, 0x35, 0x34, 0x26, 0x23, 0x35, 0x32, 0x36, 0x35, 0x35, 0x34, 0x36, + 0x36, 0x33, 0x15, 0x06, 0x06, 0x15, 0x15, 0x14, 0x07, 0x15, 0x16, 0x15, 0x15, 0x14, 0x16, 0x17, 0x01, 0x62, 0x55, + 0x5d, 0x24, 0x40, 0x3d, 0x3d, 0x40, 0x24, 0x5d, 0x55, 0x27, 0x2e, 0x72, 0x72, 0x2e, 0x27, 0x9e, 0x1c, 0x3c, 0x30, + 0x9a, 0x2f, 0x28, 0x75, 0x28, 0x2f, 0x9b, 0x30, 0x3c, 0x1c, 0x6e, 0x01, 0x1a, 0x2a, 0x92, 0x5b, 0x11, 0x06, 0x11, + 0x5b, 0x92, 0x2a, 0x1a, 0x01, 0x00, 0x01, 0x00, 0xde, 0xff, 0x1d, 0x01, 0x49, 0x02, 0xf5, 0x00, 0x03, 0x00, 0x28, + 0x4b, 0xb0, 0x27, 0x50, 0x58, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x1b, + 0x40, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x4e, 0x59, 0xb4, 0x11, 0x10, 0x02, 0x0d, + 0x18, 0x2b, 0x13, 0x33, 0x11, 0x23, 0xde, 0x6b, 0x6b, 0x02, 0xf5, 0xfc, 0x28, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, + 0x62, 0x01, 0x7b, 0x02, 0xca, 0x00, 0x1f, 0x00, 0x2c, 0x40, 0x29, 0x06, 0x01, 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, + 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, + 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x16, 0x11, 0x16, 0x11, 0x1b, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x17, 0x36, 0x36, 0x35, + 0x35, 0x34, 0x37, 0x35, 0x26, 0x35, 0x35, 0x34, 0x26, 0x27, 0x35, 0x32, 0x16, 0x16, 0x15, 0x15, 0x14, 0x16, 0x33, + 0x15, 0x22, 0x06, 0x15, 0x15, 0x14, 0x06, 0x06, 0x23, 0x28, 0x27, 0x2e, 0x72, 0x72, 0x2e, 0x27, 0x56, 0x5c, 0x24, + 0x40, 0x3d, 0x3d, 0x40, 0x24, 0x5c, 0x56, 0x30, 0x01, 0x1a, 0x2a, 0x92, 0x5b, 0x11, 0x06, 0x11, 0x5b, 0x92, 0x2a, + 0x1a, 0x01, 0x6e, 0x1c, 0x3c, 0x30, 0x9b, 0x2f, 0x28, 0x75, 0x28, 0x2f, 0x9a, 0x30, 0x3c, 0x1c, 0x00, 0x00, 0x01, + 0x00, 0x2b, 0x01, 0x0d, 0x02, 0x10, 0x01, 0xb4, 0x00, 0x17, 0x00, 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, + 0x01, 0x02, 0x01, 0x13, 0x01, 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, 0x00, 0x02, + 0x00, 0x03, 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, + 0x02, 0x03, 0x51, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, + 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, + 0x26, 0x01, 0x0c, 0x25, 0x33, 0x17, 0x1c, 0x3d, 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x2f, 0x25, 0x34, 0x16, 0x1d, 0x3c, + 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x01, 0x2d, 0x10, 0x0b, 0x22, 0x19, 0x71, 0x35, 0x0b, 0x14, 0x10, 0x0b, 0x22, 0x19, + 0x71, 0x35, 0x0c, 0x00, 0x01, 0x00, 0x17, 0x01, 0xa0, 0x01, 0x57, 0x03, 0x56, 0x00, 0x17, 0x00, 0x30, 0x40, 0x2d, + 0x0c, 0x01, 0x01, 0x02, 0x0b, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x03, + 0x02, 0x01, 0x69, 0x00, 0x03, 0x00, 0x00, 0x03, 0x57, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x00, 0x4f, + 0x16, 0x24, 0x27, 0x10, 0x04, 0x0c, 0x1a, 0x2b, 0x01, 0x21, 0x35, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, 0x33, 0x01, 0x57, 0xfe, 0xc4, 0x6d, 0x2d, + 0x21, 0x17, 0x14, 0x27, 0x31, 0x3c, 0x20, 0x4f, 0x35, 0x41, 0x4f, 0x32, 0x3b, 0x33, 0xac, 0x01, 0xa0, 0x52, 0x6b, + 0x2c, 0x2f, 0x1a, 0x12, 0x14, 0x2b, 0x4a, 0x1c, 0x23, 0x3f, 0x3b, 0x2d, 0x4a, 0x35, 0x2e, 0x00, 0x01, 0x00, 0x1a, + 0x01, 0x98, 0x01, 0x5e, 0x03, 0x55, 0x00, 0x26, 0x00, 0x4d, 0x40, 0x4a, 0x24, 0x01, 0x05, 0x00, 0x23, 0x01, 0x04, + 0x05, 0x05, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x0e, 0x01, 0x01, 0x02, 0x05, 0x4c, 0x06, 0x01, 0x00, 0x00, + 0x05, 0x04, 0x00, 0x05, 0x69, 0x00, 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, + 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x01, 0x00, 0x21, 0x1f, 0x1b, 0x19, 0x18, 0x16, 0x13, + 0x11, 0x0c, 0x0a, 0x00, 0x26, 0x01, 0x26, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x07, 0x15, 0x16, + 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x35, 0x34, 0x26, 0x23, 0x23, 0x35, 0x33, + 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0xb9, 0x49, 0x4e, 0x4d, 0x5b, 0x5d, 0x56, + 0x29, 0x49, 0x1e, 0x21, 0x48, 0x23, 0x4a, 0x24, 0x2f, 0x35, 0x2e, 0x2c, 0x23, 0x1c, 0x1b, 0x1a, 0x30, 0x1a, 0x31, + 0x1f, 0x4e, 0x03, 0x55, 0x3b, 0x30, 0x4e, 0x1b, 0x04, 0x15, 0x51, 0x3b, 0x44, 0x0f, 0x11, 0x5e, 0x14, 0x12, 0x32, + 0x16, 0x1a, 0x50, 0x1c, 0x16, 0x14, 0x18, 0x12, 0x13, 0x45, 0x17, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x20, 0x01, 0xa0, + 0x01, 0x15, 0x03, 0x4c, 0x00, 0x0d, 0x00, 0x27, 0x40, 0x24, 0x0c, 0x0b, 0x07, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x02, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x57, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, + 0x00, 0x0d, 0x00, 0x0d, 0x11, 0x03, 0x0c, 0x17, 0x2b, 0x01, 0x11, 0x23, 0x35, 0x34, 0x36, 0x36, 0x37, 0x06, 0x06, + 0x07, 0x07, 0x27, 0x37, 0x01, 0x15, 0x70, 0x02, 0x02, 0x01, 0x07, 0x14, 0x0a, 0x2d, 0x38, 0x97, 0x03, 0x4c, 0xfe, + 0x54, 0xd6, 0x0d, 0x27, 0x25, 0x0a, 0x09, 0x14, 0x07, 0x24, 0x45, 0x76, 0x00, 0x01, 0xff, 0x40, 0x00, 0x00, 0x01, + 0x41, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, + 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x01, 0x01, 0x23, 0x01, 0x01, 0x41, + 0xfe, 0x74, 0x75, 0x01, 0x8c, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0x00, 0x02, 0x00, 0x0c, 0x01, 0xa0, 0x01, 0x73, + 0x03, 0x4f, 0x00, 0x0a, 0x00, 0x12, 0x00, 0x5e, 0x40, 0x0a, 0x0d, 0x01, 0x04, 0x03, 0x06, 0x01, 0x00, 0x04, 0x02, + 0x4c, 0x4b, 0xb0, 0x10, 0x50, 0x58, 0x40, 0x1e, 0x00, 0x03, 0x04, 0x03, 0x85, 0x00, 0x01, 0x00, 0x00, 0x01, 0x71, + 0x05, 0x01, 0x04, 0x00, 0x00, 0x04, 0x57, 0x05, 0x01, 0x04, 0x04, 0x00, 0x60, 0x02, 0x01, 0x00, 0x04, 0x00, 0x50, + 0x1b, 0x40, 0x1d, 0x00, 0x03, 0x04, 0x03, 0x85, 0x00, 0x01, 0x00, 0x01, 0x86, 0x05, 0x01, 0x04, 0x00, 0x00, 0x04, + 0x57, 0x05, 0x01, 0x04, 0x04, 0x00, 0x60, 0x02, 0x01, 0x00, 0x04, 0x00, 0x50, 0x59, 0x40, 0x09, 0x17, 0x11, 0x12, + 0x11, 0x11, 0x10, 0x06, 0x0c, 0x1c, 0x2b, 0x01, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x13, 0x33, 0x11, 0x33, 0x27, + 0x34, 0x37, 0x06, 0x06, 0x07, 0x07, 0x33, 0x01, 0x73, 0x3d, 0x6f, 0xbb, 0xb6, 0x74, 0x3d, 0xac, 0x03, 0x05, 0x17, + 0x09, 0x3e, 0x60, 0x01, 0xef, 0x4f, 0x4f, 0x4c, 0x01, 0x14, 0xfe, 0xf3, 0x56, 0x26, 0x29, 0x0d, 0x2a, 0x0e, 0x60, + 0x00, 0x01, 0x00, 0x28, 0x01, 0x98, 0x01, 0x5d, 0x03, 0x4e, 0x00, 0x1d, 0x00, 0x42, 0x40, 0x3f, 0x1c, 0x03, 0x02, + 0x04, 0x01, 0x1b, 0x10, 0x02, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x03, 0x4c, 0x06, 0x01, 0x05, 0x00, 0x00, 0x01, + 0x05, 0x00, 0x67, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x69, 0x00, 0x03, 0x02, 0x02, 0x03, 0x59, 0x00, 0x03, + 0x03, 0x02, 0x61, 0x00, 0x02, 0x03, 0x02, 0x51, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x1d, 0x23, 0x25, 0x24, 0x23, 0x11, + 0x07, 0x0c, 0x1b, 0x2b, 0x01, 0x15, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, + 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x07, 0x27, 0x37, 0x01, 0x40, 0xae, 0x07, + 0x0a, 0x1c, 0x11, 0x41, 0x5a, 0x5e, 0x58, 0x23, 0x44, 0x18, 0x19, 0x42, 0x1a, 0x26, 0x2d, 0x51, 0x0c, 0x22, 0x0b, + 0x36, 0x12, 0x03, 0x4e, 0x55, 0x48, 0x01, 0x04, 0x46, 0x42, 0x47, 0x4f, 0x0c, 0x0d, 0x5f, 0x10, 0x14, 0x1d, 0x23, + 0x3e, 0x05, 0x04, 0x14, 0xd9, 0x00, 0x00, 0x01, 0x00, 0x1d, 0x01, 0xa0, 0x01, 0x64, 0x03, 0x4c, 0x00, 0x06, 0x00, + 0x2a, 0x40, 0x27, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, + 0x11, 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, 0x23, 0x35, 0x21, 0x15, 0x03, 0x4b, 0xa9, 0xd7, 0x01, 0x47, 0x9d, 0x01, + 0xa0, 0x01, 0x55, 0x57, 0x4a, 0xfe, 0x9e, 0x00, 0x00, 0x03, 0x00, 0x16, 0x01, 0x96, 0x01, 0x66, 0x03, 0x56, 0x00, + 0x17, 0x00, 0x22, 0x00, 0x2d, 0x00, 0x39, 0x40, 0x36, 0x23, 0x1d, 0x12, 0x06, 0x04, 0x03, 0x02, 0x01, 0x4c, 0x04, + 0x01, 0x00, 0x05, 0x01, 0x02, 0x03, 0x00, 0x02, 0x69, 0x00, 0x03, 0x01, 0x01, 0x03, 0x59, 0x00, 0x03, 0x03, 0x01, + 0x61, 0x00, 0x01, 0x03, 0x01, 0x51, 0x19, 0x18, 0x01, 0x00, 0x29, 0x27, 0x18, 0x22, 0x19, 0x22, 0x0d, 0x0b, 0x00, + 0x17, 0x01, 0x17, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, + 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x15, 0x14, 0x16, 0x17, 0x36, + 0x36, 0x35, 0x34, 0x26, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x35, 0x34, 0x26, 0x27, 0xbf, 0x3f, 0x58, 0x29, + 0x1d, 0x25, 0x31, 0x58, 0x4f, 0x58, 0x51, 0x2e, 0x1f, 0x1d, 0x21, 0x5a, 0x3f, 0x33, 0x1c, 0x18, 0x16, 0x1b, 0x17, + 0x24, 0x37, 0x1f, 0x20, 0x40, 0x20, 0x1f, 0x03, 0x56, 0x37, 0x37, 0x25, 0x2f, 0x11, 0x0f, 0x33, 0x2b, 0x36, 0x4a, + 0x49, 0x36, 0x2e, 0x2c, 0x10, 0x13, 0x32, 0x24, 0x36, 0x38, 0x4f, 0x27, 0x13, 0x1a, 0x0b, 0x0a, 0x19, 0x15, 0x0f, + 0x18, 0xb2, 0x17, 0x26, 0x18, 0x1b, 0x30, 0x16, 0x1c, 0x0a, 0x00, 0x02, 0x00, 0x14, 0x01, 0x96, 0x01, 0x67, 0x03, + 0x56, 0x00, 0x0b, 0x00, 0x13, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, + 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x0d, 0x0c, + 0x01, 0x00, 0x11, 0x0f, 0x0c, 0x13, 0x0d, 0x13, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0c, 0x16, 0x2b, 0x13, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x27, 0x32, 0x35, 0x34, 0x23, 0x22, 0x15, 0x14, + 0xbc, 0x52, 0x56, 0x50, 0x58, 0x54, 0x57, 0x52, 0x58, 0x2f, 0x2f, 0x2e, 0x01, 0x96, 0x77, 0x6a, 0x6a, 0x75, 0x75, + 0x6a, 0x6a, 0x77, 0x65, 0x7b, 0x7a, 0x7a, 0x7b, 0x00, 0x02, 0x00, 0x16, 0x01, 0x96, 0x01, 0x66, 0x03, 0x55, 0x00, + 0x1b, 0x00, 0x26, 0x00, 0x4a, 0x40, 0x47, 0x03, 0x01, 0x01, 0x00, 0x04, 0x01, 0x02, 0x01, 0x0a, 0x01, 0x04, 0x02, + 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 0x69, 0x00, 0x02, 0x07, 0x01, 0x04, 0x05, 0x02, 0x04, + 0x69, 0x00, 0x05, 0x03, 0x03, 0x05, 0x59, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x05, 0x03, 0x51, 0x1d, 0x1c, + 0x01, 0x00, 0x23, 0x21, 0x1c, 0x26, 0x1d, 0x26, 0x15, 0x13, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x1b, 0x01, 0x1b, 0x08, + 0x0c, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x17, 0x15, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, + 0x35, 0x34, 0x26, 0x01, 0x03, 0x0e, 0x27, 0x0d, 0x0c, 0x1f, 0x14, 0x46, 0x39, 0x03, 0x05, 0x0e, 0x2f, 0x26, 0x38, + 0x42, 0x56, 0x4b, 0x4c, 0x63, 0x13, 0x33, 0x5d, 0x08, 0x1f, 0x21, 0x1d, 0x1f, 0x3b, 0x1d, 0x03, 0x55, 0x03, 0x03, + 0x57, 0x02, 0x04, 0x42, 0x35, 0x14, 0x19, 0x44, 0x41, 0x47, 0x52, 0x60, 0x60, 0x2f, 0x5b, 0x49, 0x2c, 0xea, 0x22, + 0x14, 0x1a, 0x30, 0x43, 0x1d, 0x20, 0x00, 0x02, 0x00, 0x15, 0x01, 0x96, 0x01, 0x64, 0x03, 0x56, 0x00, 0x19, 0x00, + 0x24, 0x00, 0x4a, 0x40, 0x47, 0x10, 0x01, 0x03, 0x05, 0x0b, 0x01, 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, + 0x06, 0x01, 0x00, 0x07, 0x01, 0x04, 0x05, 0x00, 0x04, 0x69, 0x00, 0x05, 0x00, 0x03, 0x02, 0x05, 0x03, 0x69, 0x00, + 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1b, 0x1a, 0x01, 0x00, + 0x20, 0x1e, 0x1a, 0x24, 0x1b, 0x24, 0x15, 0x13, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x19, 0x01, 0x19, 0x08, 0x0c, 0x16, + 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x23, + 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, + 0xb8, 0x4a, 0x62, 0x28, 0x62, 0x58, 0x16, 0x2a, 0x0c, 0x19, 0x30, 0x3f, 0x35, 0x03, 0x05, 0x0e, 0x2d, 0x25, 0x3a, + 0x42, 0x57, 0x51, 0x3a, 0x1b, 0x1b, 0x1f, 0x22, 0x1e, 0x03, 0x56, 0x5f, 0x60, 0x46, 0x75, 0x46, 0x04, 0x04, 0x58, + 0x08, 0x43, 0x34, 0x14, 0x19, 0x45, 0x41, 0x46, 0x52, 0x54, 0x43, 0x1d, 0x21, 0x22, 0x14, 0x1d, 0x2e, 0xff, 0xff, + 0x00, 0x14, 0x00, 0x00, 0x03, 0x32, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x47, 0x01, + 0x82, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0x00, 0x00, 0x02, 0x6a, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x4a, 0x01, 0x82, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0x00, 0x00, 0x02, 0x63, 0x02, 0xfd, 0x00, + 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x83, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0x00, 0x00, + 0x03, 0xec, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x82, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x4a, 0x03, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0x00, 0x00, 0x03, 0xe6, 0x02, 0xfd, 0x00, 0x26, + 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x83, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x03, 0x06, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x14, 0xff, 0xf6, 0x01, 0x67, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x68, 0x00, 0x00, 0xfe, 0x60, + 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x20, 0x00, 0x00, 0x01, + 0x15, 0x01, 0xac, 0x03, 0x07, 0x00, 0x62, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0x00, 0x01, 0x57, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x60, 0x00, + 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1a, + 0xff, 0xf8, 0x01, 0x5e, 0x01, 0xb5, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, + 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x73, 0x01, 0xaf, 0x03, 0x07, + 0x00, 0x64, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, + 0xff, 0x00, 0x28, 0xff, 0xf8, 0x01, 0x5d, 0x01, 0xae, 0x03, 0x07, 0x00, 0x65, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, + 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0xff, 0xf6, 0x01, 0x66, 0x01, + 0xb5, 0x03, 0x07, 0x00, 0x69, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x64, 0x01, 0xac, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xfe, + 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0xff, 0xf6, + 0x01, 0x66, 0x01, 0xb6, 0x03, 0x07, 0x00, 0x67, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, + 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x15, 0xff, 0xf6, 0x01, 0x64, 0x01, 0xb6, 0x03, 0x07, 0x00, 0x6a, + 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, + 0x14, 0x01, 0x14, 0x01, 0x67, 0x02, 0xd4, 0x01, 0x07, 0x00, 0x68, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, + 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x20, 0x01, 0x1e, 0x01, 0x15, 0x02, 0xca, 0x03, + 0x07, 0x00, 0x62, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0x00, 0x17, 0x01, 0x1e, 0x01, 0x57, 0x02, 0xd4, 0x01, 0x07, 0x00, 0x60, 0x00, 0x00, 0xff, 0x7e, 0x00, + 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1a, 0x01, 0x16, 0x01, 0x5e, + 0x02, 0xd3, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, + 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x01, 0x1e, 0x01, 0x73, 0x02, 0xcd, 0x03, 0x07, 0x00, 0x64, 0x00, 0x00, + 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x28, 0x01, + 0x16, 0x01, 0x5d, 0x02, 0xcc, 0x03, 0x07, 0x00, 0x65, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, + 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0x01, 0x14, 0x01, 0x66, 0x02, 0xd3, 0x03, 0x07, 0x00, + 0x69, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x1d, 0x01, 0x1e, 0x01, 0x64, 0x02, 0xca, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, + 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0x01, 0x14, 0x01, 0x66, 0x02, 0xd4, + 0x03, 0x07, 0x00, 0x67, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, + 0x00, 0xff, 0xff, 0x00, 0x15, 0x01, 0x14, 0x01, 0x64, 0x02, 0xd4, 0x03, 0x07, 0x00, 0x6a, 0x00, 0x00, 0xff, 0x7e, + 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x84, 0x00, 0xd4, 0x00, 0x18, 0x00, 0x65, 0x00, 0x06, 0x00, 0x02, 0x00, 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, + 0x01, 0x89, 0x0e, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x54, 0x00, + 0xa8, 0x01, 0x0f, 0x01, 0xc7, 0x02, 0x5a, 0x02, 0x75, 0x02, 0x99, 0x02, 0xbd, 0x02, 0xed, 0x03, 0x15, 0x03, 0x35, + 0x03, 0x50, 0x03, 0x6f, 0x03, 0x8b, 0x03, 0xc4, 0x03, 0xeb, 0x04, 0x30, 0x04, 0x8f, 0x04, 0xc8, 0x05, 0x1a, 0x05, + 0x90, 0x05, 0xb5, 0x06, 0x21, 0x06, 0x82, 0x06, 0xb7, 0x06, 0xe9, 0x06, 0xff, 0x07, 0x2a, 0x07, 0x40, 0x07, 0x96, + 0x08, 0x40, 0x08, 0x7a, 0x08, 0xd0, 0x09, 0x16, 0x09, 0x45, 0x09, 0x70, 0x09, 0x94, 0x09, 0xe4, 0x0a, 0x0c, 0x0a, + 0x34, 0x0a, 0x67, 0x0a, 0x93, 0x0a, 0xb1, 0x0a, 0xec, 0x0b, 0x1c, 0x0b, 0x58, 0x0b, 0x93, 0x0b, 0xdb, 0x0c, 0x1e, + 0x0c, 0x71, 0x0c, 0x8f, 0x0c, 0xbc, 0x0c, 0xeb, 0x0d, 0x3f, 0x0d, 0x69, 0x0d, 0x8d, 0x0d, 0xb8, 0x0d, 0xd7, 0x0d, + 0xf3, 0x0e, 0x12, 0x0e, 0x38, 0x0e, 0x55, 0x0e, 0x80, 0x0e, 0xf9, 0x0f, 0x61, 0x0f, 0xa8, 0x10, 0x1d, 0x10, 0x6d, + 0x10, 0xd7, 0x11, 0x67, 0x11, 0x9f, 0x11, 0xd2, 0x12, 0x1b, 0x12, 0x4e, 0x12, 0x63, 0x12, 0xd0, 0x13, 0x1f, 0x13, + 0x58, 0x13, 0xcc, 0x14, 0x3b, 0x14, 0x92, 0x14, 0xe4, 0x15, 0x2b, 0x15, 0x76, 0x15, 0xa3, 0x15, 0xf5, 0x16, 0x1e, + 0x16, 0x5f, 0x16, 0x88, 0x16, 0xcc, 0x16, 0xed, 0x17, 0x31, 0x17, 0x76, 0x17, 0xb5, 0x18, 0x13, 0x18, 0x42, 0x18, + 0x5e, 0x18, 0xae, 0x18, 0xfd, 0x19, 0x24, 0x19, 0x84, 0x19, 0xbc, 0x1a, 0x1a, 0x1a, 0x75, 0x1a, 0x81, 0x1a, 0x8d, + 0x1a, 0x99, 0x1a, 0xa9, 0x1a, 0xb9, 0x1a, 0xc8, 0x1a, 0xd7, 0x1a, 0xe6, 0x1a, 0xf5, 0x1b, 0x04, 0x1b, 0x13, 0x1b, + 0x22, 0x1b, 0x31, 0x1b, 0x40, 0x1b, 0x4f, 0x1b, 0x5e, 0x1b, 0x6d, 0x1b, 0x7c, 0x1b, 0x8b, 0x1b, 0x9a, 0x1b, 0xa9, + 0x1b, 0xb8, 0x1b, 0xc7, 0x1b, 0xd6, 0x1b, 0xe5, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, 0x28, + 0x5e, 0xd5, 0x8c, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xd3, 0xe7, + 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc1, 0x01, 0xfd, 0x7c, 0xfe, 0x7b, 0x0a, 0xf1, 0x04, 0x2d, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x4d, 0x00, 0x59, 0x01, 0x04, 0x00, 0x00, 0x01, 0x1a, + 0x00, 0x36, 0x01, 0xdf, 0x00, 0x3d, 0x02, 0x86, 0x00, 0x16, 0x02, 0x3c, 0x00, 0x2b, 0x03, 0x86, 0x00, 0x1e, 0x02, + 0xee, 0x00, 0x28, 0x01, 0x0a, 0x00, 0x3d, 0x01, 0x53, 0x00, 0x28, 0x01, 0x53, 0x00, 0x1e, 0x02, 0x1e, 0x00, 0x1d, + 0x02, 0x3c, 0x00, 0x2b, 0x01, 0x1d, 0x00, 0x1f, 0x01, 0x40, 0x00, 0x1c, 0x01, 0x19, 0x00, 0x36, 0x01, 0x9f, 0x00, + 0x07, 0x02, 0x3c, 0x00, 0x24, 0x02, 0x3c, 0x00, 0x3b, 0x02, 0x3c, 0x00, 0x26, 0x02, 0x3c, 0x00, 0x26, 0x02, 0x3c, + 0x00, 0x11, 0x02, 0x3c, 0x00, 0x31, 0x02, 0x3c, 0x00, 0x23, 0x02, 0x3c, 0x00, 0x1b, 0x02, 0x3c, 0x00, 0x23, 0x02, + 0x3c, 0x00, 0x20, 0x01, 0x19, 0x00, 0x36, 0x01, 0x1d, 0x00, 0x1f, 0x02, 0x3c, 0x00, 0x2b, 0x02, 0x3c, 0x00, 0x2b, + 0x02, 0x3c, 0x00, 0x2b, 0x01, 0xdd, 0x00, 0x05, 0x03, 0x82, 0x00, 0x2f, 0x02, 0xb4, 0x00, 0x00, 0x02, 0x99, 0x00, + 0x55, 0x02, 0x82, 0x00, 0x37, 0x02, 0xdc, 0x00, 0x55, 0x02, 0x30, 0x00, 0x5a, 0x02, 0x25, 0x00, 0x5a, 0x02, 0xd4, + 0x00, 0x3a, 0x02, 0xfd, 0x00, 0x5a, 0x01, 0x85, 0x00, 0x20, 0x01, 0x4b, 0xff, 0xb6, 0x02, 0x98, 0x00, 0x5a, 0x02, + 0x2f, 0x00, 0x55, 0x03, 0xaf, 0x00, 0x5a, 0x03, 0x2d, 0x00, 0x5a, 0x03, 0x17, 0x00, 0x37, 0x02, 0x6d, 0x00, 0x55, + 0x03, 0x17, 0x00, 0x37, 0x02, 0x90, 0x00, 0x55, 0x02, 0x27, 0x00, 0x2e, 0x02, 0x41, 0x00, 0x13, 0x02, 0xf4, 0x00, + 0x55, 0x02, 0x8a, 0x00, 0x00, 0x03, 0xc7, 0x00, 0x00, 0x02, 0x9e, 0x00, 0x03, 0x02, 0x72, 0x00, 0x00, 0x02, 0x43, + 0x00, 0x18, 0x01, 0x4b, 0x00, 0x46, 0x01, 0x9f, 0x00, 0x06, 0x01, 0x4b, 0x00, 0x19, 0x02, 0x3c, 0x00, 0x17, 0x01, + 0x9b, 0xff, 0xfe, 0x01, 0x6d, 0x00, 0x28, 0x02, 0x57, 0x00, 0x28, 0x02, 0x78, 0x00, 0x49, 0x02, 0x04, 0x00, 0x2f, + 0x02, 0x78, 0x00, 0x2f, 0x02, 0x55, 0x00, 0x2f, 0x01, 0x83, 0x00, 0x14, 0x02, 0x78, 0x00, 0x2f, 0x02, 0x8a, 0x00, + 0x49, 0x01, 0x2b, 0x00, 0x44, 0x01, 0x2a, 0xff, 0xcb, 0x02, 0x6c, 0x00, 0x4e, 0x01, 0x2a, 0x00, 0x49, 0x03, 0xcf, + 0x00, 0x49, 0x02, 0x8a, 0x00, 0x49, 0x02, 0x71, 0x00, 0x2f, 0x02, 0x78, 0x00, 0x49, 0x02, 0x78, 0x00, 0x2f, 0x01, + 0xbf, 0x00, 0x49, 0x01, 0xf6, 0x00, 0x2e, 0x01, 0xb2, 0x00, 0x17, 0x02, 0x8a, 0x00, 0x46, 0x02, 0x3b, 0x00, 0x00, + 0x03, 0x58, 0x00, 0x0a, 0x02, 0x42, 0x00, 0x05, 0x02, 0x3b, 0x00, 0x00, 0x01, 0xed, 0x00, 0x1e, 0x01, 0x8a, 0x00, + 0x0f, 0x02, 0x27, 0x00, 0xde, 0x01, 0x8a, 0x00, 0x28, 0x02, 0x3c, 0x00, 0x2b, 0x01, 0x7b, 0x00, 0x17, 0x01, 0x7c, + 0x00, 0x1a, 0x01, 0x7c, 0x00, 0x20, 0x00, 0x82, 0xff, 0x40, 0x01, 0x7c, 0x00, 0x0c, 0x01, 0x7c, 0x00, 0x28, 0x01, + 0x7c, 0x00, 0x1d, 0x01, 0x7c, 0x00, 0x16, 0x01, 0x7b, 0x00, 0x14, 0x01, 0x7c, 0x00, 0x16, 0x01, 0x7c, 0x00, 0x15, + 0x03, 0x04, 0x00, 0x14, 0x02, 0xad, 0x00, 0x14, 0x02, 0xb4, 0x00, 0x14, 0x04, 0x2f, 0x00, 0x14, 0x04, 0x37, 0x00, + 0x14, 0x01, 0x7c, 0x00, 0x14, 0x00, 0x20, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x0c, 0x00, 0x28, 0x00, 0x16, 0x00, 0x1d, + 0x00, 0x16, 0x00, 0x15, 0x00, 0x14, 0x00, 0x20, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x0c, 0x00, 0x28, 0x00, 0x16, 0x00, + 0x1d, 0x00, 0x16, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x0b, 0x17, + 0xfd, 0x7c, 0xfd, 0x8d, 0x0a, 0xf1, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x04, 0x02, 0x6a, 0x02, 0xbc, 0x00, 0x05, 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, + 0x00, 0x00, 0x00, 0x4b, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x32, 0x01, 0x48, 0x00, 0x00, 0x02, + 0x0b, 0x08, 0x02, 0x04, 0x05, 0x04, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0xa0, 0x00, 0x20, 0x00, 0x7e, 0x04, 0x2d, 0xfe, + 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x22, 0x02, 0xca, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, + 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, + 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, 0x21, 0xb0, 0x00, 0x59, 0xb0, 0x00, + 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, + 0xb0, 0x02, 0x2c, 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, + 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, 0x14, 0x43, 0x42, 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, + 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, 0x04, 0x50, 0x78, 0xb2, 0x02, + 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, + 0x1c, 0x20, 0xb0, 0x02, 0x43, 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, + 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, 0x2c, 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, + 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x1b, 0x20, 0x64, + 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, + 0x58, 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, + 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, 0x38, 0x59, 0x59, 0x20, 0xb1, 0x01, + 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, + 0x20, 0xb0, 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, + 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, + 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, 0x1b, 0xb0, 0x02, 0x25, 0xb0, + 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, + 0x4b, 0xb0, 0x1e, 0x50, 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, + 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, + 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, 0x20, 0x45, 0x20, 0xb0, 0x04, + 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, + 0x21, 0x59, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, + 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, + 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, 0xb0, 0x08, 0x43, 0x20, 0x8a, + 0x20, 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, + 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, + 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, 0x43, 0x2b, 0xb2, 0x00, 0x02, 0x00, + 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, + 0x02, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, + 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, + 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, 0x0e, 0x00, 0x43, 0x45, 0x42, + 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, + 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, + 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, + 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, + 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, + 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, + 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, + 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, + 0x0c, 0x00, 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, + 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, 0x2c, 0xb0, 0x01, 0x60, 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, + 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, 0xb0, 0x00, 0x52, 0x58, 0x20, + 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, + 0x04, 0x00, 0x63, 0x8a, 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, + 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x24, 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, + 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x1b, 0x21, 0x59, 0x24, 0xb0, + 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, + 0x01, 0x61, 0x42, 0xb0, 0x11, 0x2b, 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, + 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, + 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x23, 0xb0, 0x01, 0x61, + 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, + 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb0, 0x0e, 0x43, 0x63, + 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, + 0x00, 0x00, 0x13, 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, + 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, + 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, 0x13, 0x00, + 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, + 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, + 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, 0x2c, 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, + 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, + 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, + 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, + 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x5d, 0x1b, 0x21, 0x21, 0x59, 0x2d, + 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, + 0x20, 0x2e, 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, + 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, + 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, 0x23, 0x42, 0x20, + 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, + 0x18, 0x01, 0x00, 0x11, 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, + 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, 0x2c, 0xb1, 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, + 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, 0xb0, 0x25, 0x2c, 0xb1, 0x04, + 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, + 0xb0, 0x28, 0x2c, 0xb1, 0x07, 0x20, 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, + 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, + 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x01, 0x60, 0xb0, 0x2e, + 0x2a, 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, + 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, + 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, + 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, + 0x60, 0x23, 0x61, 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, + 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, + 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, + 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, + 0x2d, 0xb0, 0x34, 0x2c, 0x20, 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, + 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, + 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, + 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, + 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, + 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0xb0, 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, + 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb0, 0x02, 0x25, 0x49, + 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, + 0x01, 0x01, 0x15, 0x14, 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, + 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, + 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, + 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, + 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, + 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, + 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, + 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, + 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, + 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, + 0xb0, 0x02, 0x25, 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, + 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, 0x25, 0xb0, 0x02, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, + 0x25, 0x60, 0x64, 0x23, 0xb0, 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, + 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, + 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x3c, 0x38, 0x2d, 0xb0, 0x3d, + 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, + 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, + 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, 0x2e, 0x20, 0x3c, 0x23, 0x21, 0x1b, + 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, + 0x23, 0x47, 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, + 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x23, + 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, + 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, + 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, + 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, + 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, + 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, + 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, + 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, + 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, + 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, + 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, + 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, + 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x26, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, + 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, 0x20, 0x3c, 0x20, 0x2e, 0x23, + 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, + 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, + 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, + 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, 0xb0, 0x06, 0x43, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, + 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, + 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, + 0x23, 0x38, 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, + 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, 0x3a, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, + 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x23, 0x38, 0xb1, 0x30, + 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, + 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, + 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, + 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, 0xb0, 0x4c, 0x2c, 0xb0, 0x39, + 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, + 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, + 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, + 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x53, 0x2c, 0xb2, 0x00, + 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, + 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, + 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x59, 0x2c, 0xb3, 0x01, 0x00, + 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, + 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, + 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, + 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x61, 0x2c, 0xb2, + 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, + 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, + 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, + 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x69, 0x2c, 0xb3, 0x01, 0x00, + 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, + 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, + 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, + 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, + 0x40, 0x2b, 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, + 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x73, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, + 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, 0x2c, 0xb0, 0x00, 0x16, 0xb1, + 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, + 0x2b, 0x2d, 0xb0, 0x77, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, + 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, + 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, + 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, + 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, + 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, + 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, + 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, + 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, + 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x87, 0x2c, 0xb1, 0x00, 0x3f, + 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, + 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, + 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, 0xb0, 0x06, 0x1b, 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, + 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, 0x50, 0x78, 0xb1, 0x05, 0x01, + 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, + 0x01, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, + 0x51, 0x41, 0x00, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x14, 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, + 0x62, 0x02, 0x56, 0x06, 0x46, 0x08, 0x3a, 0x06, 0x32, 0x04, 0x24, 0x07, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x07, 0x42, + 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x4e, 0x06, 0x40, 0x04, 0x36, 0x02, 0x2b, + 0x05, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, + 0xc0, 0x11, 0xc0, 0x0e, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, 0xb1, 0x00, 0x19, 0x42, 0x41, + 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, + 0x00, 0x09, 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, + 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, 0x28, 0x01, 0x88, 0x51, 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, + 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, 0xba, 0x08, 0x80, 0x00, 0x01, + 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, + 0x8a, 0x06, 0x7a, 0x06, 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x48, 0x06, 0x3c, 0x04, 0x34, 0x02, 0x26, 0x05, 0x09, + 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, 0x00, 0x44, 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, + 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x98, + 0x00, 0x72, 0x00, 0x72, 0x02, 0xca, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd4, 0xff, 0xf6, 0x02, + 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x95, 0x00, 0x95, 0x00, 0x73, 0x00, 0x73, 0x02, 0x48, 0x00, 0x00, 0x02, 0x50, + 0xff, 0xf8, 0x00, 0x95, 0x00, 0x95, 0x00, 0x73, 0x00, 0x73, 0x02, 0x48, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x50, 0x02, 0x50, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x73, 0x00, 0x73, 0x02, 0xca, 0xff, 0xf6, + 0x02, 0xf8, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xfd, 0x02, 0x2c, 0xff, 0xf6, 0xff, + 0x10, 0x00, 0x7b, 0x00, 0x7b, 0x00, 0x65, 0x00, 0x65, 0x01, 0x68, 0x00, 0xee, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, + 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x7b, 0x00, 0x7b, 0x00, 0x65, 0x00, 0x65, 0x01, 0x1f, 0x01, 0x1f, 0x00, + 0x9a, 0x00, 0x9a, 0x00, 0x73, 0x00, 0x73, 0x02, 0xca, 0x00, 0x00, 0x02, 0xf8, 0x02, 0x22, 0x00, 0x00, 0xff, 0x10, + 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xf9, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x64, 0x00, 0x64, 0x00, 0x45, 0x00, + 0x45, 0x01, 0x2c, 0xff, 0x7e, 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x34, 0xff, 0x74, 0x01, 0x68, + 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x64, 0x00, 0x64, 0x00, 0x45, 0x00, 0x45, 0x02, 0xcb, 0x01, 0xa0, 0x02, + 0xe7, 0x02, 0x67, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe7, 0x01, 0x96, 0x02, 0xe7, 0x02, 0x6d, 0x01, 0x19, 0x00, 0x8f, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, + 0x00, 0x08, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x30, 0x00, 0xd0, 0x00, 0x03, 0x00, + 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, + 0x01, 0x1c, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x1a, 0x01, 0x70, 0x00, 0x43, 0x00, 0x6f, 0x00, + 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, + 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x4e, 0x00, 0x6f, 0x00, + 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, + 0x00, 0x20, 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, + 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, + 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, + 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, + 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, + 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, + 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, + 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, + 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, + 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6f, + 0x00, 0x6c, 0x00, 0x64, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, + 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, + 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, + 0x35, 0x00, 0x3b, 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, + 0x00, 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, + 0x38, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, + 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, + 0x2d, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9c, + 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x1f, 0x00, 0x01, 0x00, 0x22, 0x00, 0x3b, 0x00, + 0x01, 0x00, 0x42, 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x05, 0x00, 0x18, + 0x00, 0x18, 0x00, 0x20, 0x00, 0x28, 0x00, 0x36, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x56, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x5a, 0x00, 0x02, 0x00, 0x06, + 0x00, 0x0a, 0x00, 0x01, 0x01, 0x65, 0x00, 0x01, 0x02, 0xca, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, + 0x68, 0x00, 0x01, 0x02, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, 0x44, 0x46, + 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, + 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0x65, + 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x07, 0x2c, 0x00, + 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0xf6, 0x00, 0x01, 0x00, 0x34, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, + 0x00, 0x62, 0x00, 0xe2, 0x00, 0x74, 0x00, 0x7a, 0x00, 0xb2, 0x00, 0x84, 0x00, 0x8a, 0x00, 0xb2, 0x00, 0xa8, 0x00, + 0xb2, 0x00, 0xb8, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xc2, 0x00, 0xe2, 0x00, 0xcc, 0x00, 0xd2, 0x00, 0xdc, 0x00, 0xdc, + 0x00, 0xdc, 0x00, 0xe2, 0x00, 0x01, 0x00, 0x15, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, 0x00, 0x23, 0x00, 0x25, 0x00, + 0x26, 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3c, + 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, + 0x37, 0xff, 0xec, 0x00, 0x38, 0xff, 0xec, 0x00, 0x3a, 0xff, 0xe2, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x32, 0x00, 0x02, + 0x00, 0x0d, 0xff, 0xf6, 0x00, 0x0f, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x07, 0x00, 0x0a, 0x00, + 0x14, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, 0xec, 0x00, 0x3e, + 0x00, 0x14, 0x00, 0x5e, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x39, 0xff, 0xec, 0x00, 0x01, 0x00, + 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xe2, + 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x5f, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, 0x00, + 0x14, 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, + 0x04, 0x32, 0x00, 0x04, 0x00, 0x00, 0x04, 0x86, 0x05, 0x50, 0x00, 0x17, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xba, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, + 0xff, 0xe2, 0xff, 0xce, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xc4, 0xff, 0xce, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xec, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xec, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, 0xff, + 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, + 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xba, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x14, 0xff, 0xc4, 0xff, 0xba, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xd8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x60, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x03, 0x00, 0x08, 0x00, 0x09, 0x00, + 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x30, + 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, + 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x51, + 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6b, 0x00, 0x02, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x09, 0x00, 0x13, + 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, + 0x22, 0x00, 0x22, 0x00, 0x02, 0x00, 0x24, 0x00, 0x24, 0x00, 0x08, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x26, + 0x00, 0x26, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x09, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, + 0x00, 0x0c, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x0a, 0x00, 0x39, 0x00, 0x39, 0x00, + 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x07, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0e, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, + 0x00, 0x42, 0x00, 0x42, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x49, 0x00, 0x49, 0x00, 0x01, 0x00, + 0x4e, 0x00, 0x4f, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0d, 0x00, 0x57, + 0x00, 0x58, 0x00, 0x05, 0x00, 0x59, 0x00, 0x59, 0x00, 0x16, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x05, 0x00, 0x5c, 0x00, + 0x5c, 0x00, 0x13, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x15, 0x00, 0x01, 0x00, 0x03, 0x00, 0x6d, 0x00, 0x13, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, + 0x12, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x0b, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, + 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x00, + 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x16, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, + 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x36, 0x00, 0x6c, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, + 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x1a, 0x66, 0x72, 0x61, 0x63, 0x00, 0x20, 0x6c, 0x69, 0x67, 0x61, 0x00, 0x2a, 0x6e, + 0x75, 0x6d, 0x72, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x32, 0x00, + 0x10, 0x00, 0x1e, 0x00, 0x32, 0x00, 0x4a, 0x00, 0x88, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, + 0x00, 0x01, 0x00, 0x28, 0x00, 0x5f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, + 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, + 0x00, 0x69, 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x2a, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x70, 0x00, 0x79, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, 0x7a, 0x00, + 0x83, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x36, 0x00, 0x01, 0x00, 0x08, + 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6f, 0x00, 0x03, 0x00, 0x47, 0x00, + 0x4d, 0x00, 0x6e, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x6d, 0x00, 0x02, + 0x00, 0x4d, 0x00, 0x6b, 0x00, 0x02, 0x00, 0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x47}; + + constexpr unsigned char BOLD_ITALICS_DATA[] = { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x0a, 0x6b, 0x06, + 0xbf, 0x00, 0x00, 0x5a, 0xd0, 0x00, 0x00, 0x00, 0x7e, 0x47, 0x50, 0x4f, 0x53, 0x33, 0x4f, 0x0e, 0xbf, 0x00, 0x00, + 0x5b, 0x50, 0x00, 0x00, 0x07, 0x4e, 0x47, 0x53, 0x55, 0x42, 0xfc, 0xd3, 0xd8, 0xce, 0x00, 0x00, 0x62, 0xa0, 0x00, + 0x00, 0x01, 0xd4, 0x4f, 0x53, 0x2f, 0x32, 0x6a, 0x82, 0x62, 0xb3, 0x00, 0x00, 0x47, 0xbc, 0x00, 0x00, 0x00, 0x60, + 0x63, 0x6d, 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, + 0x20, 0x41, 0x2b, 0x1e, 0x46, 0x00, 0x00, 0x57, 0x64, 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, + 0x0b, 0x83, 0x00, 0x00, 0x48, 0x50, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x5a, 0xc8, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0xb2, 0xab, 0x07, 0x57, 0x00, 0x00, 0x01, 0x1c, + 0x00, 0x00, 0x43, 0x06, 0x68, 0x65, 0x61, 0x64, 0x28, 0x3b, 0xd8, 0x55, 0x00, 0x00, 0x45, 0x5c, 0x00, 0x00, 0x00, + 0x36, 0x68, 0x68, 0x65, 0x61, 0x0d, 0x3d, 0x0b, 0xc5, 0x00, 0x00, 0x47, 0x98, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, + 0x74, 0x78, 0xfa, 0xcf, 0x0a, 0x08, 0x00, 0x00, 0x45, 0x94, 0x00, 0x00, 0x02, 0x02, 0x6c, 0x6f, 0x63, 0x61, 0xde, + 0x29, 0xcd, 0xbc, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x01, 0x16, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x5b, 0x10, 0x44, + 0x00, 0x00, 0x44, 0x24, 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x7e, 0x45, 0xc4, 0x00, 0x00, 0x58, + 0x90, 0x00, 0x00, 0x02, 0x18, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x93, 0x00, 0x32, 0x00, 0x00, 0x5a, 0xa8, 0x00, 0x00, + 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0xff, 0x8d, 0x0b, 0xc2, 0x00, 0x00, 0x56, 0x5c, 0x00, 0x00, 0x01, 0x05, 0x00, + 0x02, 0x00, 0x0b, 0xff, 0xf3, 0x01, 0x3e, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x2c, 0x40, 0x29, 0x04, 0x01, + 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, + 0x02, 0x4e, 0x05, 0x04, 0x00, 0x00, 0x0b, 0x09, 0x04, 0x0f, 0x05, 0x0f, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, + 0x17, 0x2b, 0x37, 0x13, 0x33, 0x03, 0x07, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x43, + 0x52, 0xa9, 0x7d, 0x69, 0x2a, 0x23, 0x32, 0x34, 0x23, 0x27, 0x36, 0xe8, 0x01, 0xe2, 0xfe, 0x1e, 0xf5, 0x27, 0x1b, + 0x2a, 0x3c, 0x24, 0x20, 0x2e, 0x36, 0x00, 0x02, 0x00, 0x62, 0x01, 0xc8, 0x01, 0xd2, 0x02, 0xca, 0x00, 0x03, 0x00, + 0x07, 0x00, 0x24, 0x40, 0x21, 0x05, 0x03, 0x04, 0x03, 0x01, 0x01, 0x00, 0x5f, 0x02, 0x01, 0x00, 0x00, 0x6a, 0x01, + 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, + 0x2b, 0x01, 0x13, 0x33, 0x03, 0x21, 0x13, 0x33, 0x03, 0x01, 0x27, 0x24, 0x87, 0x4a, 0xfe, 0xda, 0x23, 0x87, 0x4a, + 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x02, 0x8b, 0x02, + 0xca, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, 0x40, 0x44, 0x07, 0x05, 0x02, 0x03, 0x0f, 0x08, 0x02, 0x02, 0x01, 0x03, + 0x02, 0x68, 0x0e, 0x09, 0x02, 0x01, 0x0c, 0x0a, 0x02, 0x00, 0x0b, 0x01, 0x00, 0x67, 0x06, 0x01, 0x04, 0x04, 0x6a, + 0x4d, 0x10, 0x0d, 0x02, 0x0b, 0x0b, 0x6b, 0x0b, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, 0x1c, 0x00, 0x1b, 0x00, 0x1b, + 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0d, + 0x1f, 0x2b, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, + 0x07, 0x23, 0x07, 0x33, 0x07, 0x23, 0x07, 0x23, 0x37, 0x23, 0x07, 0x13, 0x33, 0x37, 0x23, 0x51, 0x37, 0x74, 0x09, + 0x87, 0x22, 0x7b, 0x09, 0x8d, 0x3a, 0x6a, 0x39, 0x61, 0x39, 0x69, 0x39, 0x75, 0x09, 0x88, 0x22, 0x7e, 0x09, 0x91, + 0x39, 0x6b, 0x39, 0x5f, 0x38, 0x54, 0x60, 0x22, 0x60, 0xc7, 0x65, 0x71, 0x66, 0xc7, 0xc7, 0xc7, 0xc7, 0x66, 0x71, + 0x65, 0xc7, 0xc7, 0xc7, 0x01, 0x2c, 0x71, 0x00, 0x03, 0x00, 0x19, 0xff, 0xc6, 0x02, 0x23, 0x02, 0xf8, 0x00, 0x24, + 0x00, 0x2a, 0x00, 0x31, 0x00, 0x70, 0x40, 0x17, 0x13, 0x01, 0x02, 0x03, 0x16, 0x01, 0x04, 0x02, 0x31, 0x2a, 0x1b, + 0x17, 0x08, 0x04, 0x06, 0x01, 0x04, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x20, + 0x00, 0x06, 0x00, 0x00, 0x06, 0x71, 0x00, 0x02, 0x04, 0x00, 0x02, 0x59, 0x00, 0x01, 0x05, 0x01, 0x00, 0x06, 0x01, + 0x00, 0x69, 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6c, 0x04, 0x4e, 0x1b, 0x40, 0x1f, 0x00, 0x06, 0x00, + 0x06, 0x86, 0x00, 0x02, 0x04, 0x00, 0x02, 0x59, 0x00, 0x01, 0x05, 0x01, 0x00, 0x06, 0x01, 0x00, 0x69, 0x00, 0x04, + 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6c, 0x04, 0x4e, 0x59, 0x40, 0x0a, 0x11, 0x17, 0x17, 0x11, 0x18, 0x15, 0x10, + 0x07, 0x0d, 0x1d, 0x2b, 0x37, 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x37, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x36, + 0x37, 0x37, 0x33, 0x07, 0x16, 0x16, 0x17, 0x07, 0x26, 0x26, 0x27, 0x07, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x07, + 0x23, 0x13, 0x06, 0x06, 0x15, 0x14, 0x17, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0xc6, 0x33, 0x56, 0x24, 0x26, + 0x65, 0x3a, 0x23, 0x2b, 0x47, 0x2a, 0x3c, 0x69, 0x44, 0x11, 0x44, 0x10, 0x29, 0x44, 0x23, 0x34, 0x1c, 0x3d, 0x1d, + 0x1f, 0x2d, 0x48, 0x2a, 0x71, 0x80, 0x13, 0x44, 0x84, 0x19, 0x27, 0x27, 0x06, 0x1f, 0x26, 0x18, 0x11, 0x28, 0x03, + 0x14, 0x13, 0x82, 0x15, 0x22, 0x02, 0x9d, 0x11, 0x2e, 0x43, 0x30, 0x3c, 0x54, 0x30, 0x04, 0x4a, 0x4a, 0x05, 0x14, + 0x13, 0x71, 0x0e, 0x14, 0x02, 0x92, 0x11, 0x2c, 0x41, 0x33, 0x52, 0x70, 0x09, 0x61, 0x02, 0x6f, 0x03, 0x1e, 0x21, + 0x26, 0x10, 0xfe, 0xe0, 0x05, 0x23, 0x1e, 0x17, 0x1c, 0x07, 0x00, 0x00, 0x05, 0x00, 0x38, 0xff, 0xf7, 0x03, 0x34, + 0x02, 0xd4, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x21, 0x00, 0x31, 0x00, 0x3f, 0x00, 0xd2, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x2c, 0x00, 0x07, 0x00, 0x09, 0x00, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, + 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x70, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x03, 0x61, 0x0d, + 0x06, 0x0b, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x4b, 0xb0, 0x1a, 0x50, 0x58, 0x40, 0x30, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6a, + 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x03, 0x61, 0x0d, 0x06, + 0x0b, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x34, 0x00, 0x07, 0x00, 0x09, 0x00, 0x07, 0x09, 0x6a, 0x0c, + 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x70, 0x4d, 0x0b, 0x01, 0x03, 0x03, 0x6b, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x06, 0x61, 0x0d, 0x01, + 0x06, 0x06, 0x71, 0x06, 0x4e, 0x59, 0x59, 0x40, 0x2b, 0x33, 0x32, 0x23, 0x22, 0x15, 0x14, 0x10, 0x10, 0x01, 0x00, + 0x3a, 0x38, 0x32, 0x3f, 0x33, 0x3f, 0x2b, 0x29, 0x22, 0x31, 0x23, 0x31, 0x1c, 0x1a, 0x14, 0x21, 0x15, 0x21, 0x10, + 0x13, 0x10, 0x13, 0x12, 0x11, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, + 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x03, 0x01, 0x33, 0x01, 0x03, 0x32, 0x3e, 0x02, 0x35, + 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x01, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, + 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xc2, 0x43, 0x47, 0x15, 0x2f, + 0x4f, 0x3a, 0x43, 0x49, 0x15, 0x30, 0x4f, 0x8c, 0x02, 0x13, 0x73, 0xfd, 0xef, 0x1b, 0x12, 0x1d, 0x14, 0x0b, 0x1c, + 0x10, 0x1d, 0x14, 0x0c, 0x01, 0xb8, 0x46, 0x47, 0x16, 0x31, 0x4e, 0x38, 0x43, 0x49, 0x15, 0x30, 0x4e, 0x33, 0x12, + 0x1d, 0x14, 0x0b, 0x1c, 0x10, 0x1d, 0x14, 0x0c, 0x01, 0x14, 0x52, 0x4a, 0x2c, 0x65, 0x5a, 0x39, 0x4e, 0x4d, 0x2b, + 0x65, 0x5b, 0x3a, 0xfe, 0xec, 0x02, 0xca, 0xfd, 0x36, 0x01, 0x79, 0x27, 0x3c, 0x45, 0x1e, 0x2f, 0x24, 0x3c, 0x45, + 0x21, 0x2f, 0xfe, 0x7e, 0x4d, 0x46, 0x35, 0x6a, 0x58, 0x36, 0x4d, 0x4a, 0x2d, 0x67, 0x5b, 0x3a, 0x65, 0x27, 0x3c, + 0x45, 0x1e, 0x2f, 0x24, 0x3c, 0x45, 0x21, 0x2f, 0x00, 0x03, 0x00, 0x21, 0xff, 0xf6, 0x02, 0xba, 0x02, 0xd5, 0x00, + 0x20, 0x00, 0x2c, 0x00, 0x36, 0x00, 0x99, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x06, 0x01, 0x02, 0x04, 0x31, + 0x30, 0x1b, 0x14, 0x13, 0x05, 0x05, 0x02, 0x1e, 0x01, 0x00, 0x05, 0x03, 0x4c, 0x1b, 0x40, 0x12, 0x06, 0x01, 0x02, + 0x04, 0x31, 0x30, 0x1b, 0x14, 0x13, 0x05, 0x05, 0x02, 0x1e, 0x01, 0x03, 0x05, 0x03, 0x4c, 0x59, 0x4b, 0xb0, 0x19, + 0x50, 0x58, 0x40, 0x24, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, + 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x4d, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, + 0x5f, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x59, 0x40, 0x17, 0x2e, 0x2d, 0x01, 0x00, 0x2d, 0x36, 0x2e, 0x36, 0x28, 0x26, 0x1d, 0x1c, 0x18, 0x17, 0x0d, 0x0b, + 0x00, 0x20, 0x01, 0x20, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x35, 0x34, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, 0x07, 0x17, 0x23, + 0x27, 0x06, 0x06, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x03, 0x32, 0x36, 0x37, + 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, 0xf4, 0x65, 0x6e, 0x54, 0x58, 0x25, 0x38, 0x60, 0x3c, 0x3f, 0x4e, 0x24, 0x5f, + 0x53, 0x5f, 0x1c, 0x22, 0x10, 0x92, 0x1e, 0x49, 0x30, 0x64, 0xab, 0x23, 0x27, 0x5f, 0x10, 0x28, 0x39, 0x1d, 0x14, + 0x22, 0x22, 0x0c, 0x31, 0x20, 0x36, 0x16, 0x6e, 0x23, 0x2a, 0x2a, 0x0a, 0x60, 0x59, 0x4b, 0x65, 0x2b, 0x3e, 0x40, + 0x44, 0x5b, 0x2e, 0x2a, 0x44, 0x28, 0x4a, 0x64, 0x22, 0x80, 0x23, 0x45, 0x28, 0x47, 0x7a, 0x32, 0x8c, 0x30, 0x1a, + 0x20, 0x01, 0xcb, 0x14, 0x33, 0x26, 0x1c, 0x19, 0x30, 0x21, 0x16, 0x2d, 0xfe, 0xa4, 0x11, 0x0c, 0xa0, 0x14, 0x33, + 0x2c, 0x1d, 0x2d, 0x00, 0x01, 0x00, 0x62, 0x01, 0xc8, 0x01, 0x0c, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, + 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, + 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x13, 0x33, 0x03, 0x62, 0x23, 0x87, 0x4a, 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x00, + 0x00, 0x01, 0x00, 0x24, 0xff, 0x62, 0x01, 0x9a, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, + 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x16, 0x03, 0x0d, 0x17, + 0x2b, 0x17, 0x26, 0x26, 0x35, 0x34, 0x12, 0x37, 0x33, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x17, 0x6d, 0x25, 0x24, 0x7e, + 0x78, 0x80, 0x47, 0x6e, 0x3f, 0x1e, 0x1b, 0x9e, 0x41, 0x96, 0x50, 0xad, 0x01, 0x18, 0x7c, 0x4d, 0xb3, 0xcf, 0x77, + 0x4c, 0x94, 0x42, 0x00, 0x00, 0x01, 0xff, 0xba, 0xff, 0x62, 0x01, 0x30, 0x02, 0xd6, 0x00, 0x0e, 0x00, 0x2e, 0x4b, + 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0c, 0x02, 0x01, 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x1b, + 0x40, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x76, 0x59, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x0e, 0x17, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x15, 0x14, + 0x02, 0x07, 0x46, 0x47, 0x6e, 0x3f, 0x1e, 0x1b, 0x72, 0x25, 0x24, 0x7d, 0x78, 0x9e, 0x4e, 0xb2, 0xcf, 0x77, 0x4c, + 0xa0, 0x42, 0x41, 0xa2, 0x50, 0xae, 0xfe, 0xe8, 0x7b, 0x00, 0x01, 0x00, 0x55, 0x01, 0x19, 0x02, 0x35, 0x02, 0xfd, + 0x00, 0x0e, 0x00, 0x1d, 0x40, 0x1a, 0x09, 0x08, 0x07, 0x06, 0x04, 0x00, 0x4a, 0x0e, 0x0d, 0x0c, 0x05, 0x04, 0x03, + 0x02, 0x01, 0x08, 0x00, 0x49, 0x00, 0x00, 0x00, 0x76, 0x1a, 0x01, 0x0d, 0x17, 0x2b, 0x01, 0x27, 0x07, 0x27, 0x37, + 0x27, 0x37, 0x17, 0x37, 0x17, 0x07, 0x37, 0x07, 0x27, 0x17, 0x01, 0x5f, 0x2d, 0x61, 0x62, 0x86, 0xa0, 0x29, 0xa5, + 0x11, 0x7e, 0x3a, 0xbd, 0x08, 0xa6, 0x4e, 0x01, 0x19, 0xa6, 0x89, 0x4f, 0x7a, 0x2e, 0x71, 0x54, 0xb3, 0x18, 0xac, + 0x0d, 0x79, 0x15, 0xa5, 0x00, 0x01, 0x00, 0x35, 0x00, 0x6f, 0x02, 0x1a, 0x02, 0x54, 0x00, 0x0b, 0x00, 0x26, 0x40, + 0x23, 0x00, 0x05, 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, + 0x05, 0x02, 0x5f, 0x00, 0x02, 0x05, 0x02, 0x4f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, + 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, 0x01, 0x5d, 0xbd, 0xbd, 0x6b, 0xbd, 0xbd, 0x6b, + 0x01, 0x96, 0x6b, 0xbc, 0xbc, 0x6b, 0xbe, 0x00, 0x00, 0x01, 0xff, 0xd0, 0xff, 0x7f, 0x00, 0xc0, 0x00, 0x74, 0x00, + 0x08, 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, + 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x13, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x36, 0x36, 0x37, 0x33, + 0x17, 0x06, 0x06, 0x07, 0x30, 0x1a, 0x32, 0x13, 0x8d, 0x04, 0x18, 0x44, 0x24, 0x81, 0x3b, 0x86, 0x34, 0x0b, 0x35, + 0x7e, 0x37, 0x00, 0x01, 0x00, 0x11, 0x00, 0xce, 0x01, 0x2c, 0x01, 0x4a, 0x00, 0x03, 0x00, 0x1e, 0x40, 0x1b, 0x00, + 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, 0x37, 0x21, 0x07, 0x11, 0x1a, 0x01, 0x01, 0x1a, 0xce, 0x7c, + 0x7c, 0x00, 0x01, 0x00, 0x08, 0xff, 0xf3, 0x00, 0xb7, 0x00, 0x9b, 0x00, 0x0b, 0x00, 0x1a, 0x40, 0x17, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x02, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x03, + 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x50, 0x21, 0x27, 0x3a, + 0x2c, 0x21, 0x28, 0x37, 0x0d, 0x21, 0x21, 0x31, 0x35, 0x21, 0x22, 0x34, 0x31, 0x00, 0x00, 0x01, 0xff, 0xd3, 0xff, + 0xfa, 0x01, 0xf1, 0x02, 0xd0, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, + 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x01, 0x33, 0x01, + 0x2d, 0x01, 0x95, 0x89, 0xfe, 0x6c, 0x06, 0x02, 0xd6, 0xfd, 0x2a, 0x00, 0x02, 0x00, 0x20, 0xff, 0xf6, 0x02, 0x1e, + 0x02, 0xd5, 0x00, 0x0f, 0x00, 0x21, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, + 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x11, 0x10, 0x01, 0x00, 0x1a, + 0x18, 0x10, 0x21, 0x11, 0x21, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, + 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x0e, 0x03, 0x15, 0x14, 0x16, 0xe5, 0x65, 0x60, 0x28, 0x50, 0x76, 0x4d, 0x5c, 0x67, 0x24, 0x4b, 0x77, 0x47, 0x1c, + 0x30, 0x26, 0x19, 0x0e, 0x1e, 0x1e, 0x1e, 0x31, 0x25, 0x19, 0x0d, 0x1b, 0x0a, 0x7c, 0x72, 0x62, 0xb3, 0x8b, 0x51, + 0x6e, 0x79, 0x5f, 0xb4, 0x90, 0x55, 0x7a, 0x31, 0x53, 0x65, 0x6b, 0x2f, 0x36, 0x32, 0x36, 0x57, 0x65, 0x63, 0x25, + 0x37, 0x3a, 0x00, 0x00, 0x01, 0x00, 0x59, 0x00, 0x00, 0x01, 0xe7, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x1b, 0x40, 0x18, + 0x08, 0x07, 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, + 0x11, 0x19, 0x02, 0x0d, 0x18, 0x2b, 0x01, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x25, 0x33, 0x03, 0x23, + 0x01, 0x13, 0x05, 0x16, 0x0a, 0x09, 0x26, 0x10, 0x5f, 0x41, 0x01, 0x14, 0x7a, 0x97, 0x95, 0x01, 0x95, 0x1a, 0x52, + 0x20, 0x07, 0x1d, 0x0a, 0x3c, 0x69, 0xaa, 0xfd, 0x36, 0x00, 0x01, 0xff, 0xe8, 0x00, 0x00, 0x02, 0x18, 0x02, 0xd4, + 0x00, 0x1c, 0x00, 0x2f, 0x40, 0x2c, 0x0d, 0x01, 0x00, 0x01, 0x0c, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x00, 0x00, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1c, 0x28, 0x25, 0x28, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x37, 0x3e, 0x02, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, + 0x15, 0x21, 0x07, 0x18, 0x15, 0xe9, 0x3a, 0x44, 0x1d, 0x28, 0x22, 0x24, 0x44, 0x2e, 0x47, 0x32, 0x77, 0x4c, 0x46, + 0x59, 0x2a, 0x37, 0x5e, 0x3d, 0x83, 0x01, 0x15, 0x1a, 0x68, 0xcf, 0x34, 0x4a, 0x3b, 0x1b, 0x25, 0x26, 0x24, 0x26, + 0x63, 0x2b, 0x3a, 0x32, 0x4f, 0x2d, 0x3f, 0x68, 0x5d, 0x32, 0x6c, 0x05, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x07, 0xff, + 0xf6, 0x02, 0x1b, 0x02, 0xd4, 0x00, 0x2b, 0x00, 0x4a, 0x40, 0x47, 0x1b, 0x01, 0x04, 0x05, 0x1a, 0x01, 0x03, 0x04, + 0x24, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x03, 0x00, 0x02, 0x01, + 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1f, 0x1d, 0x18, 0x16, 0x11, 0x0f, 0x0e, 0x0c, 0x08, 0x06, 0x00, + 0x2b, 0x01, 0x2b, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc4, 0x37, 0x62, 0x24, 0x29, 0x60, + 0x2d, 0x47, 0x59, 0x35, 0x49, 0x43, 0x16, 0x24, 0x2b, 0x50, 0x34, 0x26, 0x2a, 0x2c, 0x46, 0x1a, 0x3e, 0x30, 0x6b, + 0x4f, 0x63, 0x63, 0x5a, 0x54, 0x36, 0x4c, 0x3e, 0x84, 0x0a, 0x14, 0x13, 0x82, 0x18, 0x19, 0x3a, 0x3b, 0x24, 0x30, + 0x6c, 0x16, 0x32, 0x2a, 0x1d, 0x28, 0x20, 0x11, 0x64, 0x20, 0x27, 0x5d, 0x46, 0x4a, 0x67, 0x0f, 0x04, 0x0a, 0x48, + 0x44, 0x38, 0x68, 0x41, 0x00, 0x00, 0x02, 0xff, 0xf4, 0x00, 0x00, 0x02, 0x1b, 0x02, 0xca, 0x00, 0x0a, 0x00, 0x15, + 0x00, 0x2e, 0x40, 0x2b, 0x11, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x05, 0x01, 0x02, 0x03, 0x01, 0x00, 0x04, 0x02, 0x00, + 0x68, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x6b, 0x04, 0x4e, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x0a, + 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0d, 0x1a, 0x2b, 0x33, 0x37, 0x21, 0x37, 0x01, 0x33, 0x03, 0x33, 0x07, + 0x23, 0x07, 0x03, 0x33, 0x37, 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x07, 0xf5, 0x1f, 0xfe, 0xe0, 0x17, 0x01, 0x78, + 0x98, 0x5f, 0x53, 0x19, 0x53, 0x1f, 0xef, 0x98, 0x1c, 0x06, 0x0f, 0x0f, 0x04, 0x05, 0x0b, 0x22, 0x11, 0x94, 0x72, + 0x01, 0xc4, 0xfe, 0x3f, 0x75, 0x94, 0x01, 0x09, 0x79, 0x1a, 0x3c, 0x33, 0x0c, 0x13, 0x30, 0x15, 0x00, 0x00, 0x01, + 0x00, 0x0d, 0xff, 0xf6, 0x02, 0x27, 0x02, 0xca, 0x00, 0x21, 0x00, 0x44, 0x40, 0x41, 0x17, 0x12, 0x02, 0x02, 0x05, + 0x11, 0x04, 0x02, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, + 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1b, 0x19, 0x16, 0x15, 0x14, 0x13, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x21, 0x01, 0x21, + 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, + 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x07, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, + 0xc7, 0x3a, 0x61, 0x1f, 0x24, 0x58, 0x30, 0x3c, 0x46, 0x1e, 0x2f, 0x3e, 0x1e, 0x38, 0x12, 0x33, 0x65, 0x01, 0x71, + 0x1b, 0xef, 0x2b, 0x0c, 0x1f, 0x13, 0x36, 0x58, 0x33, 0x3f, 0x83, 0x0a, 0x17, 0x11, 0x83, 0x14, 0x1c, 0x27, 0x3b, + 0x1f, 0x26, 0x36, 0x0b, 0x05, 0x26, 0x01, 0x66, 0x80, 0x8f, 0x02, 0x05, 0x29, 0x54, 0x41, 0x4a, 0x7b, 0x49, 0x00, + 0x02, 0x00, 0x2b, 0xff, 0xf6, 0x02, 0x33, 0x02, 0xd5, 0x00, 0x1f, 0x00, 0x30, 0x00, 0x47, 0x40, 0x44, 0x0d, 0x01, + 0x02, 0x01, 0x0e, 0x01, 0x03, 0x02, 0x14, 0x01, 0x05, 0x03, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x05, 0x04, 0x03, 0x05, + 0x69, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x21, 0x20, 0x01, 0x00, 0x28, 0x26, 0x20, 0x30, 0x21, 0x30, 0x19, 0x17, 0x12, 0x10, + 0x0b, 0x09, 0x00, 0x1f, 0x01, 0x1f, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x37, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x06, 0x06, 0x15, 0x14, + 0x16, 0xfc, 0x67, 0x6a, 0x26, 0x47, 0x31, 0x31, 0x7a, 0x52, 0x1f, 0x3b, 0x13, 0x19, 0x12, 0x33, 0x18, 0x64, 0x74, + 0x1e, 0x04, 0x19, 0x4a, 0x35, 0x4a, 0x56, 0x19, 0x3c, 0x65, 0x46, 0x25, 0x30, 0x18, 0x21, 0x21, 0x1c, 0x30, 0x1f, + 0x04, 0x02, 0x02, 0x26, 0x0a, 0x7c, 0x73, 0x4e, 0x99, 0x84, 0x2d, 0x2c, 0x2c, 0x08, 0x05, 0x78, 0x05, 0x07, 0x6f, + 0x6e, 0x23, 0x2e, 0x5c, 0x59, 0x2a, 0x65, 0x5b, 0x3b, 0x79, 0x30, 0x4a, 0x27, 0x23, 0x29, 0x1e, 0x2c, 0x17, 0x0b, + 0x17, 0x0b, 0x29, 0x36, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x02, 0x52, 0x02, 0xca, 0x00, 0x06, 0x00, 0x1f, 0x40, + 0x1c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x37, 0x21, 0x07, 0x01, 0x26, + 0x01, 0x68, 0xfe, 0xcd, 0x1b, 0x01, 0xdc, 0x14, 0xfe, 0x91, 0x02, 0x4b, 0x7f, 0x5f, 0xfd, 0x95, 0x00, 0x00, 0x03, + 0x00, 0x1b, 0xff, 0xf6, 0x02, 0x26, 0x02, 0xd5, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x34, 0x00, 0x35, 0x40, 0x32, 0x2f, + 0x15, 0x06, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, + 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x2a, 0x29, 0x01, 0x00, 0x29, 0x34, 0x2a, 0x34, + 0x24, 0x22, 0x0e, 0x0c, 0x00, 0x1c, 0x01, 0x1c, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, + 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x1e, 0x02, 0x15, 0x14, + 0x06, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x03, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, 0xfb, 0x70, 0x70, 0x58, 0x52, 0x1e, 0x33, 0x36, 0x69, 0x4d, 0x43, 0x57, + 0x2c, 0x2b, 0x45, 0x28, 0x1a, 0x31, 0x1f, 0x36, 0x70, 0x14, 0x2a, 0x30, 0x26, 0x1f, 0x27, 0x2a, 0x21, 0x1d, 0x33, + 0x30, 0x2b, 0x22, 0x38, 0x38, 0x31, 0x0a, 0x68, 0x4d, 0x4d, 0x65, 0x1e, 0x17, 0x49, 0x32, 0x37, 0x5b, 0x36, 0x2d, + 0x4a, 0x2c, 0x34, 0x49, 0x31, 0x0e, 0x11, 0x30, 0x43, 0x2e, 0x34, 0x5f, 0x3b, 0x01, 0xbe, 0x11, 0x34, 0x27, 0x21, + 0x26, 0x2f, 0x22, 0x23, 0x30, 0xfe, 0xa2, 0x3a, 0x24, 0x29, 0x38, 0x16, 0x16, 0x3d, 0x2c, 0x27, 0x2f, 0x00, 0x00, + 0x02, 0x00, 0x2a, 0xff, 0xf6, 0x02, 0x15, 0x02, 0xd5, 0x00, 0x21, 0x00, 0x32, 0x00, 0x47, 0x40, 0x44, 0x0c, 0x01, + 0x02, 0x04, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, 0x04, + 0x02, 0x69, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x23, 0x22, 0x01, 0x00, 0x2d, 0x2b, 0x22, 0x32, 0x23, 0x32, 0x19, 0x17, 0x11, 0x0f, + 0x08, 0x06, 0x00, 0x21, 0x01, 0x21, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, + 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x06, 0x07, 0x06, 0x06, 0x13, 0x32, 0x36, 0x36, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, + 0x14, 0x16, 0x9f, 0x21, 0x40, 0x14, 0x13, 0x3b, 0x21, 0x36, 0x4c, 0x32, 0x20, 0x0a, 0x04, 0x18, 0x46, 0x32, 0x55, + 0x52, 0x19, 0x3c, 0x6a, 0x50, 0x5c, 0x6e, 0x1e, 0x3c, 0x2e, 0x2a, 0x74, 0x26, 0x1d, 0x2c, 0x1c, 0x04, 0x02, 0x02, + 0x22, 0x25, 0x24, 0x30, 0x18, 0x25, 0x0a, 0x0a, 0x06, 0x7d, 0x07, 0x0d, 0x25, 0x3e, 0x4e, 0x28, 0x22, 0x2b, 0x6c, + 0x52, 0x28, 0x61, 0x59, 0x3a, 0x6f, 0x7d, 0x46, 0x98, 0x88, 0x30, 0x2b, 0x32, 0x01, 0x79, 0x1f, 0x2e, 0x16, 0x0b, + 0x17, 0x0b, 0x29, 0x34, 0x2f, 0x45, 0x23, 0x2a, 0x2c, 0x00, 0x00, 0x02, 0x00, 0x08, 0xff, 0xf3, 0x01, 0x10, 0x02, + 0x2c, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x2d, 0x40, 0x2a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, + 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x0d, 0x0c, 0x01, 0x00, 0x13, 0x11, + 0x0c, 0x17, 0x0d, 0x17, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x03, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0xa9, 0x21, 0x27, 0x39, 0x2d, 0x20, 0x29, 0x37, 0x89, 0x21, 0x27, 0x3a, 0x2c, 0x21, 0x28, 0x37, 0x01, 0x85, 0x21, + 0x20, 0x32, 0x34, 0x20, 0x22, 0x34, 0x31, 0xfe, 0x6e, 0x21, 0x21, 0x31, 0x35, 0x21, 0x22, 0x34, 0x31, 0x00, 0x00, + 0x02, 0xff, 0xca, 0xff, 0x7f, 0x01, 0x10, 0x02, 0x2c, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x2a, 0x40, 0x27, 0x00, 0x02, + 0x05, 0x01, 0x03, 0x02, 0x03, 0x63, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x00, 0x4e, 0x0c, + 0x0c, 0x01, 0x00, 0x0c, 0x14, 0x0c, 0x14, 0x10, 0x0f, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, + 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x36, 0x36, 0x37, 0x33, 0x17, 0x06, + 0x06, 0x07, 0xa9, 0x21, 0x27, 0x39, 0x2d, 0x20, 0x29, 0x37, 0xfe, 0xf1, 0x1a, 0x32, 0x13, 0x8d, 0x04, 0x18, 0x44, + 0x24, 0x01, 0x85, 0x21, 0x20, 0x32, 0x34, 0x20, 0x22, 0x34, 0x31, 0xfd, 0xfa, 0x3b, 0x86, 0x34, 0x0b, 0x35, 0x7e, + 0x37, 0x00, 0x01, 0x00, 0x35, 0x00, 0x63, 0x02, 0x1a, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, + 0x32, 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, 0x05, 0x02, 0x1a, 0xfe, 0x1b, 0x01, 0xe5, 0xfe, 0xb2, 0x01, 0x4e, + 0x63, 0xd6, 0x46, 0xf2, 0x75, 0x9b, 0x89, 0x00, 0x02, 0x00, 0x35, 0x00, 0xcc, 0x02, 0x1a, 0x01, 0xf4, 0x00, 0x03, + 0x00, 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, 0x03, + 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, + 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, 0x35, + 0x21, 0x15, 0x35, 0x01, 0xe5, 0xfe, 0x1b, 0x01, 0xe5, 0x01, 0x8a, 0x6a, 0x6a, 0xbe, 0x6b, 0x6b, 0x00, 0x00, 0x01, + 0x00, 0x35, 0x00, 0x63, 0x02, 0x1a, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, + 0x25, 0x25, 0x35, 0x05, 0x15, 0x05, 0x35, 0x01, 0x4e, 0xfe, 0xb2, 0x01, 0xe5, 0xfe, 0x1b, 0xd8, 0x89, 0x9b, 0x75, + 0xf2, 0x46, 0xd6, 0x00, 0x00, 0x02, 0x00, 0x4d, 0xff, 0xf3, 0x01, 0xeb, 0x02, 0xd4, 0x00, 0x1b, 0x00, 0x27, 0x00, + 0x3f, 0x40, 0x3c, 0x0d, 0x01, 0x00, 0x01, 0x0c, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x05, 0x01, 0x02, 0x00, 0x04, 0x00, + 0x02, 0x04, 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x03, 0x61, 0x06, + 0x01, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x1d, 0x1c, 0x00, 0x00, 0x23, 0x21, 0x1c, 0x27, 0x1d, 0x27, 0x00, 0x1b, 0x00, + 0x1b, 0x25, 0x28, 0x07, 0x0d, 0x18, 0x2b, 0x37, 0x36, 0x36, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, + 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x0e, 0x02, 0x07, 0x07, 0x22, 0x26, 0x35, + 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x7f, 0x0d, 0x36, 0x3c, 0x31, 0x2c, 0x1e, 0x23, 0x23, 0x47, 0x2c, + 0x2d, 0x2d, 0x6d, 0x3f, 0x58, 0x63, 0x26, 0x43, 0x2a, 0x1d, 0x23, 0x14, 0x07, 0x64, 0x2a, 0x22, 0x2d, 0x37, 0x21, + 0x28, 0x35, 0xed, 0x45, 0x5b, 0x28, 0x21, 0x2d, 0x1f, 0x1b, 0x1f, 0x1c, 0x15, 0x6c, 0x19, 0x24, 0x56, 0x4c, 0x32, + 0x47, 0x38, 0x1c, 0x13, 0x21, 0x27, 0x1d, 0xfa, 0x2b, 0x1a, 0x24, 0x3d, 0x25, 0x22, 0x29, 0x36, 0x00, 0x00, 0x02, + 0x00, 0x2d, 0xff, 0xa5, 0x03, 0x4e, 0x02, 0xca, 0x00, 0x40, 0x00, 0x4f, 0x00, 0x93, 0x40, 0x16, 0x23, 0x01, 0x09, + 0x04, 0x45, 0x01, 0x05, 0x09, 0x14, 0x01, 0x02, 0x05, 0x3d, 0x01, 0x07, 0x02, 0x3e, 0x01, 0x00, 0x07, 0x05, 0x4c, + 0x4b, 0xb0, 0x15, 0x50, 0x58, 0x40, 0x28, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, 0x07, 0x05, 0x02, 0x69, 0x00, + 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x09, + 0x09, 0x04, 0x61, 0x00, 0x04, 0x04, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x04, 0x00, 0x09, 0x05, 0x04, 0x09, + 0x69, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, 0x07, 0x05, 0x02, 0x69, 0x00, 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, + 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x06, 0x4e, 0x59, 0x40, 0x1f, 0x42, 0x41, 0x01, 0x00, + 0x49, 0x47, 0x41, 0x4f, 0x42, 0x4f, 0x3b, 0x39, 0x33, 0x31, 0x2b, 0x29, 0x21, 0x1f, 0x19, 0x17, 0x12, 0x10, 0x0a, + 0x08, 0x00, 0x40, 0x01, 0x40, 0x0c, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, + 0x16, 0x15, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x03, 0x32, 0x36, 0x37, 0x37, 0x26, + 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x87, 0x72, 0x9a, 0x4e, 0x4c, 0x83, 0xa9, 0x5d, 0x9b, 0xb1, + 0x20, 0x3f, 0x5a, 0x39, 0x27, 0x3a, 0x09, 0x05, 0x15, 0x39, 0x2f, 0x37, 0x4c, 0x23, 0x42, 0x5f, 0x3b, 0x36, 0x4c, + 0x1e, 0x34, 0x05, 0x08, 0x10, 0x0c, 0x1b, 0x2d, 0x21, 0x12, 0x73, 0x79, 0x63, 0x9d, 0x5c, 0x32, 0x6e, 0x59, 0x3e, + 0x65, 0x34, 0x2f, 0x71, 0x40, 0x27, 0x31, 0x10, 0x1c, 0x09, 0x12, 0x0d, 0x23, 0x34, 0x22, 0x11, 0x1c, 0x5b, 0x59, + 0x98, 0x5e, 0x72, 0xaf, 0x78, 0x3d, 0xa0, 0x90, 0x3b, 0x6f, 0x58, 0x34, 0x23, 0x25, 0x21, 0x27, 0x47, 0x50, 0x33, + 0x61, 0x4e, 0x2e, 0x10, 0x0b, 0xcd, 0x16, 0x1f, 0x10, 0x12, 0x0f, 0x27, 0x40, 0x4d, 0x27, 0x63, 0x73, 0x5a, 0xa5, + 0x70, 0x44, 0x74, 0x45, 0x16, 0x14, 0x5b, 0x13, 0x19, 0x01, 0x18, 0x49, 0x3b, 0x6c, 0x02, 0x03, 0x23, 0x37, 0x3d, + 0x1a, 0x26, 0x1e, 0x00, 0x02, 0xff, 0xc4, 0x00, 0x00, 0x02, 0x38, 0x02, 0xca, 0x00, 0x07, 0x00, 0x11, 0x00, 0x2c, + 0x40, 0x29, 0x0d, 0x01, 0x04, 0x00, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, 0x68, 0x00, 0x00, 0x00, + 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x09, 0x08, 0x00, 0x07, 0x00, 0x07, 0x11, + 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x33, 0x13, 0x23, 0x27, 0x23, 0x07, 0x13, 0x33, 0x27, 0x26, 0x26, + 0x37, 0x23, 0x06, 0x06, 0x07, 0x3c, 0x01, 0x76, 0xb6, 0x48, 0x91, 0x0c, 0xe7, 0x54, 0x91, 0xa3, 0x0d, 0x02, 0x04, + 0x01, 0x02, 0x0a, 0x18, 0x0f, 0x02, 0xca, 0xfd, 0x36, 0xaa, 0xaa, 0x01, 0x29, 0xb8, 0x1d, 0x3c, 0x1f, 0x1b, 0x35, + 0x1f, 0x00, 0x03, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x63, 0x02, 0xca, 0x00, 0x10, 0x00, 0x18, 0x00, 0x21, 0x00, 0x43, + 0x40, 0x40, 0x08, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x00, 0x05, 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, + 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x08, 0x01, 0x04, 0x04, 0x01, 0x5f, 0x06, 0x01, 0x01, 0x01, 0x6b, + 0x01, 0x4e, 0x1a, 0x19, 0x12, 0x11, 0x00, 0x00, 0x20, 0x1e, 0x19, 0x21, 0x1a, 0x21, 0x17, 0x15, 0x11, 0x18, 0x12, + 0x18, 0x00, 0x10, 0x00, 0x0f, 0x21, 0x09, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, + 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x13, 0x32, 0x36, 0x35, 0x34, 0x23, 0x23, 0x07, 0x13, 0x32, 0x36, + 0x35, 0x34, 0x26, 0x23, 0x23, 0x07, 0x1a, 0x97, 0xd0, 0x66, 0x7c, 0x52, 0x4a, 0x31, 0x3a, 0x4a, 0x7f, 0x50, 0x3a, + 0x35, 0x41, 0x53, 0x4a, 0x22, 0x17, 0x37, 0x43, 0x2c, 0x2d, 0x51, 0x28, 0x02, 0xca, 0x49, 0x56, 0x49, 0x5e, 0x10, + 0x04, 0x0d, 0x45, 0x35, 0x51, 0x67, 0x31, 0x01, 0xaf, 0x2b, 0x31, 0x43, 0x9f, 0xfe, 0xce, 0x37, 0x34, 0x26, 0x29, + 0xba, 0x00, 0x00, 0x01, 0x00, 0x3b, 0xff, 0xf6, 0x02, 0x8c, 0x02, 0xd5, 0x00, 0x1d, 0x00, 0x37, 0x40, 0x34, 0x0c, + 0x01, 0x02, 0x01, 0x1b, 0x0d, 0x02, 0x03, 0x02, 0x1c, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, + 0x19, 0x17, 0x11, 0x0f, 0x0a, 0x08, 0x00, 0x1d, 0x01, 0x1d, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, + 0x3e, 0x03, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x15, 0x06, 0x01, 0x3f, 0x80, 0x84, 0x1d, 0x3b, 0x5a, 0x7c, 0x50, 0x3f, 0x67, 0x2d, 0x3a, 0x26, 0x49, 0x2a, + 0x38, 0x55, 0x39, 0x1d, 0x46, 0x3f, 0x2b, 0x51, 0x2f, 0x5c, 0x0a, 0x97, 0x7d, 0x40, 0x83, 0x76, 0x5c, 0x36, 0x1d, + 0x1a, 0x78, 0x16, 0x19, 0x38, 0x5d, 0x73, 0x3c, 0x4b, 0x51, 0x14, 0x12, 0x7e, 0x27, 0x00, 0x00, 0x02, 0x00, 0x1a, + 0x00, 0x00, 0x02, 0x86, 0x02, 0xca, 0x00, 0x09, 0x00, 0x13, 0x00, 0x2c, 0x40, 0x29, 0x00, 0x03, 0x03, 0x00, 0x5f, + 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x01, 0x5f, 0x04, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x0b, + 0x0a, 0x00, 0x00, 0x12, 0x10, 0x0a, 0x13, 0x0b, 0x13, 0x00, 0x09, 0x00, 0x08, 0x21, 0x06, 0x0d, 0x17, 0x2b, 0x33, + 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x37, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, + 0x1a, 0x97, 0xbd, 0x83, 0x95, 0x61, 0xb8, 0x82, 0x13, 0x4a, 0x6b, 0x39, 0x49, 0x3f, 0x36, 0x62, 0x02, 0xca, 0x8b, + 0x89, 0x85, 0xc5, 0x6c, 0x7e, 0x4f, 0x8a, 0x59, 0x50, 0x4d, 0xfe, 0x31, 0x00, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, + 0x02, 0x41, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, + 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x04, 0x04, 0x05, 0x5f, 0x06, 0x01, 0x05, 0x05, 0x6b, + 0x05, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x33, 0x13, + 0x21, 0x07, 0x23, 0x07, 0x33, 0x07, 0x23, 0x07, 0x33, 0x07, 0x1a, 0x97, 0x01, 0x90, 0x1b, 0xf8, 0x21, 0xe8, 0x1b, + 0xe8, 0x27, 0xf9, 0x1a, 0x02, 0xca, 0x7d, 0x9c, 0x7d, 0xb5, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x02, + 0x3f, 0x02, 0xca, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, + 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x04, 0x04, 0x6b, 0x04, 0x4e, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x09, 0x11, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x21, 0x07, 0x23, 0x07, 0x33, 0x07, 0x23, + 0x03, 0x1a, 0x97, 0x01, 0x8e, 0x1b, 0xf7, 0x26, 0xe6, 0x1b, 0xe7, 0x3a, 0x02, 0xca, 0x7d, 0xb6, 0x7e, 0xfe, 0xe7, + 0x00, 0x00, 0x01, 0x00, 0x3b, 0xff, 0xf6, 0x02, 0xa7, 0x02, 0xd5, 0x00, 0x21, 0x00, 0x3e, 0x40, 0x3b, 0x0b, 0x01, + 0x02, 0x01, 0x0c, 0x01, 0x05, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x67, 0x00, 0x02, 0x02, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x01, 0x00, 0x1e, 0x1d, 0x1c, 0x1b, 0x18, 0x16, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x21, 0x01, 0x21, 0x07, 0x0d, 0x16, + 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, + 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x23, 0x37, 0x21, 0x03, 0x06, 0x06, 0x01, 0x48, 0x7b, 0x92, 0x35, + 0x67, 0x97, 0x62, 0x40, 0x6b, 0x2c, 0x3a, 0x21, 0x4f, 0x2e, 0x3f, 0x5d, 0x3e, 0x1f, 0x43, 0x43, 0x1b, 0x29, 0x14, + 0x21, 0x7b, 0x1b, 0x01, 0x0f, 0x50, 0x30, 0x72, 0x0a, 0x8f, 0x88, 0x5a, 0xa4, 0x80, 0x4a, 0x19, 0x17, 0x7b, 0x11, + 0x1a, 0x39, 0x5e, 0x73, 0x3a, 0x4a, 0x51, 0x06, 0x05, 0x97, 0x7a, 0xfe, 0x8b, 0x10, 0x17, 0x00, 0x01, 0x00, 0x1a, + 0x00, 0x00, 0x02, 0xc1, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x27, 0x40, 0x24, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, + 0x68, 0x02, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x05, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x0b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x33, 0x13, 0x33, 0x03, + 0x23, 0x13, 0x23, 0x03, 0x1a, 0x97, 0x97, 0x3a, 0xe2, 0x3b, 0x96, 0x97, 0x96, 0x40, 0xe2, 0x41, 0x02, 0xca, 0xfe, + 0xe9, 0x01, 0x17, 0xfd, 0x36, 0x01, 0x33, 0xfe, 0xcd, 0x00, 0x00, 0x01, 0xff, 0xe3, 0x00, 0x00, 0x01, 0xb6, 0x02, + 0xca, 0x00, 0x0b, 0x00, 0x22, 0x40, 0x1f, 0x0a, 0x09, 0x04, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, + 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x15, 0x03, 0x0d, 0x17, + 0x2b, 0x23, 0x37, 0x37, 0x13, 0x27, 0x37, 0x21, 0x07, 0x07, 0x03, 0x17, 0x07, 0x1d, 0x12, 0x5b, 0x62, 0x4a, 0x12, + 0x01, 0x3c, 0x12, 0x5d, 0x62, 0x4c, 0x12, 0x56, 0x28, 0x01, 0xce, 0x28, 0x56, 0x56, 0x28, 0xfe, 0x32, 0x28, 0x56, + 0x00, 0x00, 0x01, 0xff, 0x62, 0xff, 0x2d, 0x01, 0x54, 0x02, 0xca, 0x00, 0x0f, 0x00, 0x28, 0x40, 0x25, 0x04, 0x01, + 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, 0x00, 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, + 0x6a, 0x02, 0x4e, 0x01, 0x00, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x0f, 0x01, 0x0f, 0x04, 0x0d, 0x16, 0x2b, 0x07, 0x22, + 0x26, 0x27, 0x37, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x41, 0x19, 0x32, 0x12, 0x01, + 0x11, 0x26, 0x18, 0x2d, 0x3e, 0x0f, 0x91, 0x97, 0x94, 0x1b, 0x78, 0xd3, 0x07, 0x06, 0x7d, 0x04, 0x07, 0x34, 0x46, + 0x02, 0xa4, 0xfd, 0x4a, 0x7e, 0x69, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x02, 0xc1, 0x02, 0xca, 0x00, 0x0c, 0x00, + 0x25, 0x40, 0x22, 0x0a, 0x07, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, + 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x12, 0x13, 0x11, 0x05, 0x0d, 0x19, 0x2b, + 0x33, 0x13, 0x33, 0x03, 0x37, 0x37, 0x33, 0x01, 0x13, 0x23, 0x03, 0x07, 0x07, 0x1a, 0x97, 0x95, 0x4b, 0x4c, 0xca, + 0xb0, 0xfe, 0xde, 0x8e, 0xa5, 0x67, 0x3d, 0x35, 0x02, 0xca, 0xfe, 0xa7, 0x66, 0xf3, 0xfe, 0xaa, 0xfe, 0x8c, 0x01, + 0x21, 0x22, 0xff, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x01, 0xc3, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, + 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x33, 0x07, 0x1a, 0x97, 0x95, + 0x7d, 0xfa, 0x1a, 0x02, 0xca, 0xfd, 0xb3, 0x7d, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x03, 0x75, 0x02, 0xca, 0x00, + 0x17, 0x00, 0x27, 0x40, 0x24, 0x11, 0x0d, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, + 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x17, 0x17, 0x11, 0x13, 0x11, + 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x01, 0x33, 0x03, 0x23, 0x13, 0x3e, 0x02, 0x37, 0x23, 0x01, + 0x23, 0x03, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x1a, 0x97, 0xc5, 0x20, 0x04, 0x01, 0x0c, 0xcf, 0x97, 0x89, 0x47, 0x07, + 0x13, 0x13, 0x08, 0x04, 0xfe, 0xea, 0x89, 0x1e, 0x04, 0x02, 0x0c, 0x0f, 0x09, 0x46, 0x02, 0xca, 0xfd, 0xea, 0x02, + 0x16, 0xfd, 0x36, 0x01, 0x52, 0x22, 0x4d, 0x4b, 0x1d, 0xfd, 0xd7, 0x02, 0x29, 0x15, 0x49, 0x56, 0x29, 0xfe, 0xb4, + 0x00, 0x00, 0x01, 0x00, 0x19, 0x00, 0x00, 0x02, 0xfb, 0x02, 0xca, 0x00, 0x13, 0x00, 0x24, 0x40, 0x21, 0x0d, 0x03, + 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, + 0x00, 0x00, 0x00, 0x13, 0x00, 0x13, 0x11, 0x17, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x3e, + 0x02, 0x37, 0x13, 0x33, 0x03, 0x23, 0x03, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x19, 0x97, 0xad, 0xab, 0x03, 0x03, 0x0a, + 0x0c, 0x06, 0x48, 0x89, 0x97, 0xad, 0xac, 0x04, 0x01, 0x09, 0x0d, 0x08, 0x46, 0x02, 0xca, 0xfd, 0xf5, 0x17, 0x42, + 0x46, 0x1c, 0x01, 0x50, 0xfd, 0x36, 0x02, 0x19, 0x10, 0x47, 0x53, 0x22, 0xfe, 0xb3, 0x00, 0x02, 0x00, 0x3b, 0xff, + 0xf6, 0x02, 0xbc, 0x02, 0xd5, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x11, 0x10, + 0x01, 0x00, 0x19, 0x17, 0x10, 0x1f, 0x11, 0x1f, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, 0x2b, 0x05, + 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, + 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x4a, 0x86, 0x89, 0x30, 0x5e, 0x8e, 0x5d, 0x80, 0x88, 0x2d, + 0x5c, 0x8b, 0x53, 0x2d, 0x4b, 0x36, 0x1e, 0x40, 0x39, 0x30, 0x4d, 0x38, 0x1d, 0x42, 0x0a, 0x96, 0x7e, 0x57, 0xa4, + 0x83, 0x4d, 0x96, 0x7f, 0x57, 0xa4, 0x82, 0x4d, 0x7f, 0x34, 0x5c, 0x77, 0x43, 0x47, 0x50, 0x37, 0x5e, 0x76, 0x40, + 0x48, 0x4e, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x67, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x30, 0x40, + 0x2d, 0x06, 0x01, 0x03, 0x00, 0x01, 0x02, 0x03, 0x01, 0x67, 0x00, 0x04, 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, + 0x4d, 0x05, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0e, 0x0d, 0x00, 0x00, 0x13, 0x11, 0x0d, 0x14, 0x0e, 0x14, 0x00, + 0x0c, 0x00, 0x0c, 0x26, 0x21, 0x07, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, + 0x23, 0x23, 0x07, 0x13, 0x32, 0x36, 0x35, 0x34, 0x23, 0x23, 0x07, 0x1a, 0x97, 0xc7, 0x57, 0x69, 0x2f, 0x52, 0x8c, + 0x59, 0x4c, 0x35, 0x8d, 0x43, 0x52, 0x5f, 0x46, 0x2d, 0x02, 0xca, 0x34, 0x5e, 0x3e, 0x55, 0x70, 0x37, 0xfe, 0x01, + 0x7a, 0x42, 0x3a, 0x58, 0xd4, 0x00, 0x00, 0x02, 0x00, 0x3b, 0xff, 0x56, 0x02, 0xbc, 0x02, 0xd5, 0x00, 0x14, 0x00, + 0x23, 0x00, 0x32, 0x40, 0x2f, 0x12, 0x01, 0x00, 0x03, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x02, 0x86, 0x00, 0x04, 0x04, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x16, 0x15, 0x1e, 0x1c, 0x15, 0x23, 0x16, 0x23, 0x17, 0x26, 0x40, 0x06, 0x0d, 0x19, 0x2b, 0x05, 0x22, 0x22, 0x23, + 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x17, 0x23, 0x03, 0x32, 0x3e, + 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x01, 0x4e, 0x03, 0x07, 0x03, 0x7f, 0x87, 0x30, + 0x5f, 0x8e, 0x5e, 0x7e, 0x88, 0x32, 0x64, 0x4a, 0x7b, 0xaf, 0x58, 0x30, 0x4d, 0x37, 0x1d, 0x3f, 0x38, 0x3f, 0x60, + 0x35, 0x41, 0x0a, 0x96, 0x7e, 0x57, 0xa4, 0x83, 0x4d, 0x96, 0x7f, 0x5a, 0xa8, 0x83, 0x22, 0xc3, 0x01, 0x21, 0x34, + 0x5c, 0x76, 0x43, 0x48, 0x4d, 0x5b, 0x96, 0x5b, 0x46, 0x4c, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x52, 0x02, + 0xca, 0x00, 0x0d, 0x00, 0x16, 0x00, 0x38, 0x40, 0x35, 0x08, 0x01, 0x02, 0x04, 0x01, 0x4c, 0x07, 0x01, 0x04, 0x00, + 0x02, 0x01, 0x04, 0x02, 0x67, 0x00, 0x05, 0x05, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x03, 0x02, 0x01, + 0x01, 0x6b, 0x01, 0x4e, 0x0f, 0x0e, 0x00, 0x00, 0x15, 0x13, 0x0e, 0x16, 0x0f, 0x16, 0x00, 0x0d, 0x00, 0x0d, 0x11, + 0x16, 0x21, 0x08, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, + 0x03, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x07, 0x1a, 0x97, 0xb0, 0x76, 0x7b, 0x57, 0x43, 0x7d, 0xa5, + 0x62, 0x43, 0x3a, 0x81, 0x3e, 0x4a, 0x2d, 0x31, 0x2d, 0x2b, 0x02, 0xca, 0x5f, 0x5f, 0x5a, 0x6a, 0x17, 0xfe, 0xcf, + 0x01, 0x12, 0xfe, 0xee, 0x01, 0x88, 0x3e, 0x3c, 0x27, 0x2a, 0xcb, 0x00, 0x01, 0x00, 0x14, 0xff, 0xf6, 0x02, 0x1e, + 0x02, 0xd4, 0x00, 0x27, 0x00, 0x37, 0x40, 0x34, 0x18, 0x01, 0x03, 0x02, 0x19, 0x04, 0x02, 0x01, 0x03, 0x03, 0x01, + 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, + 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1c, 0x1a, 0x16, 0x14, 0x08, 0x06, 0x00, 0x27, 0x01, 0x27, + 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x2e, + 0x02, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, + 0x16, 0x15, 0x14, 0x06, 0x06, 0xc2, 0x36, 0x59, 0x1f, 0x2c, 0x56, 0x2d, 0x32, 0x42, 0x30, 0x26, 0x1e, 0x38, 0x24, + 0x3c, 0x6f, 0x4a, 0x38, 0x5e, 0x2c, 0x35, 0x4c, 0x41, 0x28, 0x34, 0x2e, 0x2a, 0x3b, 0x3b, 0x49, 0x79, 0x0a, 0x18, + 0x14, 0x86, 0x19, 0x1c, 0x26, 0x28, 0x29, 0x2f, 0x1c, 0x16, 0x36, 0x49, 0x31, 0x40, 0x61, 0x38, 0x18, 0x18, 0x72, + 0x24, 0x2b, 0x25, 0x26, 0x2d, 0x1c, 0x27, 0x5e, 0x3f, 0x4b, 0x62, 0x30, 0x00, 0x01, 0x00, 0x51, 0x00, 0x00, 0x02, + 0x5b, 0x02, 0xca, 0x00, 0x07, 0x00, 0x21, 0x40, 0x1e, 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, + 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, + 0x19, 0x2b, 0x33, 0x13, 0x23, 0x37, 0x21, 0x07, 0x23, 0x03, 0x81, 0x7b, 0xab, 0x1c, 0x01, 0xee, 0x1c, 0xab, 0x7b, + 0x02, 0x4b, 0x7f, 0x7f, 0xfd, 0xb5, 0x00, 0x01, 0x00, 0x44, 0xff, 0xf6, 0x02, 0xbc, 0x02, 0xca, 0x00, 0x17, 0x00, + 0x24, 0x40, 0x21, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x01, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x01, 0x00, 0x13, 0x12, 0x0f, 0x0d, 0x08, 0x07, 0x00, 0x17, 0x01, 0x17, 0x05, 0x0d, 0x16, 0x2b, 0x05, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, + 0x03, 0x0e, 0x02, 0x01, 0x2b, 0x70, 0x77, 0x04, 0x04, 0x5f, 0x98, 0x5f, 0x08, 0x2e, 0x2e, 0x3c, 0x41, 0x11, 0x5f, + 0x97, 0x62, 0x12, 0x48, 0x79, 0x0a, 0x6f, 0x5c, 0x10, 0x29, 0x15, 0x01, 0xbb, 0xfe, 0x46, 0x27, 0x1e, 0x28, 0x2d, + 0x48, 0x4d, 0x01, 0xbf, 0xfe, 0x33, 0x54, 0x75, 0x3e, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0xa8, 0x02, + 0xca, 0x00, 0x0d, 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, + 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, + 0x33, 0x03, 0x33, 0x13, 0x16, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, 0x98, 0x3e, 0x90, 0x19, 0x02, + 0x01, 0x02, 0x04, 0x0b, 0x1b, 0x10, 0xd2, 0x9a, 0xfe, 0x93, 0x02, 0xca, 0xfe, 0x52, 0x1f, 0x4e, 0x1d, 0x21, 0x47, + 0x22, 0x01, 0xae, 0xfd, 0x36, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x03, 0xdc, 0x02, 0xca, 0x00, 0x22, 0x00, 0x27, + 0x40, 0x24, 0x1e, 0x11, 0x06, 0x03, 0x03, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x02, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x04, + 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x22, 0x11, 0x1a, 0x19, 0x11, 0x06, 0x0d, 0x1a, + 0x2b, 0x33, 0x03, 0x33, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x13, 0x16, 0x06, 0x06, 0x07, + 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, 0x23, 0x03, 0x26, 0x26, 0x34, 0x37, 0x23, 0x06, 0x07, 0x03, 0x70, 0x16, + 0x8c, 0x03, 0x03, 0x04, 0x04, 0x0e, 0x22, 0x0d, 0xb4, 0x84, 0x0a, 0x01, 0x01, 0x02, 0x02, 0x04, 0x0e, 0x23, 0x0e, + 0xa1, 0x97, 0xfe, 0xc4, 0xa9, 0x08, 0x01, 0x01, 0x01, 0x04, 0x1a, 0x1d, 0x9e, 0x02, 0xca, 0xfe, 0x7a, 0x25, 0x5d, + 0x27, 0x27, 0x59, 0x1f, 0x01, 0x90, 0xfe, 0x70, 0x11, 0x36, 0x3d, 0x1b, 0x29, 0x5f, 0x22, 0x01, 0x85, 0xfd, 0x36, + 0x01, 0x45, 0x2c, 0x39, 0x2e, 0x19, 0x50, 0x42, 0xfe, 0xa1, 0x00, 0x00, 0x01, 0xff, 0xc7, 0x00, 0x00, 0x02, 0xb0, + 0x02, 0xca, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, 0x04, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, + 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x12, + 0x12, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x03, 0x33, 0x17, 0x37, 0x33, 0x01, 0x13, 0x23, 0x03, 0x03, 0x39, + 0x01, 0x19, 0x74, 0x9f, 0x4a, 0xaf, 0xac, 0xfe, 0xf6, 0x83, 0xa6, 0x53, 0xbf, 0x01, 0x7b, 0x01, 0x4f, 0xf6, 0xf6, + 0xfe, 0xa3, 0xfe, 0x93, 0x01, 0x0d, 0xfe, 0xf3, 0x00, 0x01, 0x00, 0x5b, 0x00, 0x00, 0x02, 0x90, 0x02, 0xca, 0x00, + 0x08, 0x00, 0x22, 0x40, 0x1f, 0x04, 0x01, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x03, + 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x12, 0x12, 0x04, 0x0d, 0x18, 0x2b, 0x33, + 0x13, 0x03, 0x33, 0x13, 0x13, 0x33, 0x01, 0x03, 0x94, 0x3a, 0x73, 0x98, 0x3f, 0xb7, 0xa7, 0xfe, 0xd2, 0x3a, 0x01, + 0x11, 0x01, 0xb9, 0xfe, 0xdf, 0x01, 0x21, 0xfe, 0x47, 0xfe, 0xef, 0x00, 0x00, 0x01, 0xff, 0xe2, 0x00, 0x00, 0x02, + 0x4a, 0x02, 0xca, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, + 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, + 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x01, 0x21, 0x37, 0x21, 0x07, 0x01, 0x21, 0x07, 0x1e, 0x13, 0x01, + 0x7b, 0xfe, 0xf7, 0x1a, 0x01, 0xc9, 0x14, 0xfe, 0x82, 0x01, 0x23, 0x1a, 0x62, 0x01, 0xeb, 0x7d, 0x63, 0xfe, 0x16, + 0x7d, 0x00, 0x01, 0xff, 0xee, 0xff, 0x62, 0x01, 0x8f, 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x02, + 0x04, 0x01, 0x03, 0x02, 0x03, 0x63, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, 0x23, 0x03, 0x33, 0x07, + 0x12, 0xba, 0xe7, 0x16, 0x69, 0x8e, 0x69, 0x16, 0x9e, 0x03, 0x68, 0x67, 0xfd, 0x66, 0x67, 0x00, 0x00, 0x01, 0x00, + 0x6c, 0xff, 0xfa, 0x01, 0x5a, 0x02, 0xd0, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, + 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x17, 0x03, + 0x33, 0x13, 0xdc, 0x70, 0x7b, 0x73, 0x06, 0x02, 0xd6, 0xfd, 0x2a, 0x00, 0x01, 0xff, 0xbd, 0xff, 0x62, 0x01, 0x5d, + 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x00, 0x04, 0x01, 0x03, 0x00, 0x03, 0x63, 0x00, 0x01, 0x01, + 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, + 0x19, 0x2b, 0x07, 0x37, 0x33, 0x13, 0x23, 0x37, 0x33, 0x03, 0x43, 0x16, 0x68, 0x8e, 0x69, 0x16, 0xe7, 0xba, 0x9e, + 0x67, 0x02, 0x9a, 0x67, 0xfc, 0x98, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0xfe, 0x02, 0x0e, 0x02, 0xce, 0x00, 0x06, + 0x00, 0x27, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, + 0x03, 0x02, 0x02, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, + 0x06, 0x00, 0x44, 0x37, 0x01, 0x33, 0x13, 0x23, 0x03, 0x03, 0x11, 0x01, 0x2e, 0x48, 0x87, 0x6d, 0x55, 0xc4, 0xfe, + 0x01, 0xd0, 0xfe, 0x30, 0x01, 0x35, 0xfe, 0xcb, 0x00, 0x00, 0x01, 0xff, 0xa5, 0xff, 0x62, 0x01, 0x45, 0xff, 0xa6, + 0x00, 0x03, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, + 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, + 0xb1, 0x06, 0x00, 0x44, 0x07, 0x37, 0x21, 0x07, 0x5b, 0x0f, 0x01, 0x91, 0x0f, 0x9e, 0x44, 0x44, 0x00, 0x01, 0x00, + 0x91, 0x02, 0x5e, 0x01, 0x63, 0x02, 0xfe, 0x00, 0x09, 0x00, 0x2d, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x22, 0x08, 0x04, + 0x02, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, + 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, + 0x2e, 0x02, 0x27, 0x35, 0x33, 0x16, 0x17, 0x15, 0x01, 0x07, 0x15, 0x2e, 0x28, 0x0b, 0x9a, 0x11, 0x27, 0x02, 0x5e, + 0x14, 0x34, 0x37, 0x17, 0x0a, 0x48, 0x4c, 0x0c, 0x00, 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x42, 0x02, 0x2c, + 0x00, 0x15, 0x00, 0x24, 0x00, 0x7e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x01, 0x12, 0x01, + 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x02, 0x12, 0x01, 0x03, 0x04, 0x02, 0x4c, 0x59, 0x4b, + 0xb0, 0x19, 0x50, 0x58, 0x40, 0x19, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6d, + 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, + 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, 0x20, 0x1e, + 0x16, 0x24, 0x17, 0x24, 0x11, 0x10, 0x0f, 0x0e, 0x0a, 0x08, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x17, + 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, + 0x06, 0x37, 0x32, 0x36, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0xc4, 0x2b, 0x45, + 0x28, 0x21, 0x40, 0x5e, 0x3d, 0x32, 0x3e, 0x13, 0x04, 0x1d, 0x76, 0x74, 0x77, 0x08, 0x04, 0x1b, 0x48, 0x07, 0x1b, + 0x32, 0x26, 0x0a, 0x09, 0x21, 0x1d, 0x24, 0x3b, 0x23, 0x0a, 0x29, 0x58, 0x47, 0x3c, 0x80, 0x6e, 0x44, 0x30, 0x23, + 0x49, 0xfd, 0xde, 0x4b, 0x24, 0x31, 0x79, 0x2d, 0x4a, 0x2d, 0x29, 0x22, 0x26, 0x2f, 0x46, 0x6d, 0x3c, 0x55, 0x00, + 0x00, 0x02, 0x00, 0x12, 0xff, 0xf6, 0x02, 0x27, 0x02, 0xf8, 0x00, 0x19, 0x00, 0x28, 0x00, 0x82, 0x4b, 0xb0, 0x19, + 0x50, 0x58, 0x40, 0x0a, 0x0d, 0x01, 0x05, 0x03, 0x03, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x0d, 0x01, + 0x05, 0x03, 0x03, 0x01, 0x01, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, + 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x01, + 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x03, + 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x1b, 0x1a, 0x01, 0x00, 0x22, 0x20, 0x1a, 0x28, 0x1b, 0x28, 0x12, + 0x10, 0x08, 0x07, 0x06, 0x05, 0x00, 0x19, 0x01, 0x19, 0x08, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x27, 0x23, 0x07, + 0x23, 0x13, 0x33, 0x07, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, + 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x2a, 0x34, 0x41, 0x12, 0x04, 0x1c, + 0x71, 0xa1, 0x93, 0x1e, 0x04, 0x0e, 0x10, 0x07, 0x04, 0x1a, 0x3e, 0x32, 0x28, 0x46, 0x2c, 0x24, 0x42, 0x5d, 0x53, + 0x1b, 0x2f, 0x23, 0x14, 0x40, 0x24, 0x32, 0x20, 0x0f, 0x25, 0x0a, 0x2c, 0x24, 0x46, 0x02, 0xf8, 0x8d, 0x14, 0x35, + 0x35, 0x14, 0x21, 0x32, 0x27, 0x57, 0x48, 0x43, 0x82, 0x6b, 0x40, 0x77, 0x2b, 0x46, 0x56, 0x2b, 0x56, 0x34, 0x4f, + 0x52, 0x1d, 0x27, 0x2f, 0x00, 0x00, 0x01, 0x00, 0x2c, 0xff, 0xf6, 0x01, 0xef, 0x02, 0x2c, 0x00, 0x1e, 0x00, 0x37, + 0x40, 0x34, 0x0c, 0x01, 0x02, 0x01, 0x1b, 0x0d, 0x02, 0x03, 0x02, 0x1c, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, + 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, + 0x4e, 0x01, 0x00, 0x19, 0x17, 0x11, 0x0f, 0x0a, 0x08, 0x00, 0x1e, 0x01, 0x1e, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, + 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, + 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0xf7, 0x39, 0x5c, 0x36, 0x28, 0x4c, 0x6b, 0x42, 0x2e, 0x4f, 0x25, + 0x2f, 0x17, 0x39, 0x1d, 0x22, 0x36, 0x25, 0x13, 0x2c, 0x27, 0x23, 0x41, 0x22, 0x22, 0x50, 0x0a, 0x2d, 0x60, 0x4b, + 0x49, 0x7f, 0x60, 0x36, 0x11, 0x11, 0x71, 0x0a, 0x11, 0x28, 0x41, 0x4f, 0x26, 0x36, 0x31, 0x16, 0x11, 0x79, 0x12, + 0x15, 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x6e, 0x02, 0xf8, 0x00, 0x19, 0x00, 0x28, 0x00, 0x82, 0x4b, 0xb0, + 0x19, 0x50, 0x58, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x01, 0x16, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x0c, + 0x01, 0x05, 0x01, 0x16, 0x01, 0x03, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, + 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x1b, 0x1a, 0x01, 0x00, 0x23, 0x21, 0x1a, 0x28, 0x1b, 0x28, + 0x15, 0x14, 0x13, 0x12, 0x0a, 0x08, 0x00, 0x19, 0x01, 0x19, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, + 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x34, 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, + 0x06, 0x37, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xc6, 0x27, 0x47, 0x2c, 0x24, + 0x42, 0x5d, 0x3a, 0x31, 0x38, 0x13, 0x04, 0x03, 0x06, 0x04, 0x25, 0x93, 0xa1, 0x70, 0x09, 0x04, 0x1d, 0x4a, 0x09, + 0x23, 0x31, 0x1f, 0x0f, 0x24, 0x20, 0x1b, 0x2f, 0x23, 0x14, 0x0a, 0x27, 0x57, 0x49, 0x42, 0x83, 0x6a, 0x40, 0x2e, + 0x22, 0x03, 0x25, 0x31, 0x14, 0xaf, 0xfd, 0x08, 0x47, 0x24, 0x2d, 0x77, 0x35, 0x4f, 0x51, 0x1d, 0x27, 0x2f, 0x2b, + 0x46, 0x56, 0x2b, 0x56, 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x14, 0x02, 0x2c, 0x00, 0x1b, 0x00, 0x25, 0x00, + 0x43, 0x40, 0x40, 0x18, 0x01, 0x03, 0x02, 0x19, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x03, + 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1d, 0x1c, 0x01, 0x00, 0x22, 0x20, 0x1c, 0x25, 0x1d, 0x25, 0x16, 0x14, 0x0f, + 0x0d, 0x09, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x08, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x23, 0x06, 0x14, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, + 0x03, 0x32, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x01, 0x04, 0x60, 0x78, 0x27, 0x4d, 0x72, 0x4b, 0x5c, + 0x5b, 0x9b, 0x9f, 0x19, 0x01, 0x33, 0x2e, 0x2b, 0x46, 0x30, 0x2b, 0x58, 0x58, 0x55, 0x4b, 0x33, 0x1b, 0x36, 0x29, + 0x09, 0x0a, 0x69, 0x6a, 0x45, 0x7f, 0x64, 0x3b, 0x54, 0x41, 0x56, 0x68, 0x06, 0x09, 0x05, 0x2c, 0x34, 0x14, 0x16, + 0x6f, 0x15, 0x15, 0x01, 0x46, 0x35, 0x23, 0x2e, 0x22, 0x3c, 0x28, 0x00, 0x01, 0xff, 0x96, 0xff, 0x10, 0x01, 0xe5, + 0x02, 0xfd, 0x00, 0x23, 0x00, 0xa3, 0x40, 0x12, 0x15, 0x01, 0x04, 0x03, 0x16, 0x01, 0x05, 0x04, 0x04, 0x01, 0x01, + 0x02, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x21, 0x00, 0x04, 0x04, 0x03, 0x61, + 0x00, 0x03, 0x03, 0x72, 0x4d, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, + 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x21, 0x00, 0x04, + 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, + 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x04, 0x04, 0x03, + 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x15, 0x01, 0x00, 0x20, 0x1f, 0x1e, + 0x1d, 0x1a, 0x18, 0x13, 0x11, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x23, 0x01, 0x23, 0x08, 0x0d, 0x16, 0x2b, 0x07, 0x22, + 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x13, 0x18, 0x2f, 0x10, 0x0e, + 0x1c, 0x0f, 0x24, 0x26, 0x09, 0x63, 0x55, 0x0f, 0x5f, 0x0a, 0x15, 0x5f, 0x50, 0x22, 0x41, 0x16, 0x26, 0x0e, 0x22, + 0x11, 0x19, 0x21, 0x07, 0x0a, 0x6c, 0x19, 0x6b, 0x69, 0x11, 0x5a, 0xf0, 0x07, 0x05, 0x77, 0x04, 0x06, 0x29, 0x29, + 0x01, 0xd7, 0x47, 0x29, 0x29, 0x61, 0x51, 0x0e, 0x0a, 0x69, 0x06, 0x08, 0x1c, 0x22, 0x2a, 0x70, 0xfe, 0x13, 0x51, + 0x64, 0x00, 0x00, 0x02, 0x00, 0x12, 0xff, 0x10, 0x02, 0x42, 0x02, 0x2c, 0x00, 0x23, 0x00, 0x32, 0x00, 0x9e, 0x4b, + 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x1c, 0x01, 0x06, 0x03, 0x0d, 0x01, 0x02, 0x05, 0x04, 0x01, 0x01, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x04, 0x4c, 0x1b, 0x40, 0x12, 0x1c, 0x01, 0x06, 0x04, 0x0d, 0x01, 0x02, 0x05, 0x04, 0x01, 0x01, + 0x02, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x00, 0x06, 0x06, 0x03, + 0x61, 0x04, 0x01, 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x00, + 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x04, 0x04, 0x6d, 0x4d, + 0x00, 0x06, 0x06, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, + 0x71, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, 0x19, 0x25, 0x24, + 0x01, 0x00, 0x2d, 0x2b, 0x24, 0x32, 0x25, 0x32, 0x1f, 0x1e, 0x1a, 0x18, 0x12, 0x10, 0x08, 0x06, 0x00, 0x23, 0x01, + 0x23, 0x09, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x37, 0x37, 0x36, 0x36, 0x37, + 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x0e, + 0x02, 0x11, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xbd, 0x38, 0x53, 0x20, 0x21, + 0x58, 0x2e, 0x67, 0x18, 0x07, 0x03, 0x0a, 0x05, 0x04, 0x1a, 0x43, 0x32, 0x40, 0x52, 0x20, 0x3f, 0x5e, 0x3f, 0x32, + 0x3b, 0x16, 0x04, 0x1d, 0x76, 0x78, 0x12, 0x4c, 0x6d, 0x1b, 0x30, 0x25, 0x16, 0x1d, 0x21, 0x1c, 0x2f, 0x24, 0x13, + 0xf0, 0x13, 0x0d, 0x7e, 0x12, 0x18, 0x63, 0x1c, 0x0f, 0x27, 0x0f, 0x21, 0x2e, 0x5c, 0x68, 0x3c, 0x80, 0x6f, 0x44, + 0x2c, 0x27, 0x49, 0xfd, 0xca, 0x52, 0x60, 0x2a, 0x01, 0x5f, 0x2b, 0x47, 0x54, 0x29, 0x26, 0x2f, 0x29, 0x45, 0x55, + 0x2c, 0x55, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x02, 0x29, 0x02, 0xf8, 0x00, 0x1c, 0x00, 0x2d, 0x40, 0x2a, 0x07, + 0x01, 0x03, 0x01, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, + 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1c, 0x24, 0x15, 0x28, 0x11, + 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, + 0x07, 0x03, 0x23, 0x13, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x12, 0xa1, 0x93, 0x1c, 0x04, 0x10, + 0x10, 0x07, 0x04, 0x1e, 0x4a, 0x31, 0x47, 0x46, 0x0b, 0x41, 0x93, 0x43, 0x08, 0x35, 0x21, 0x36, 0x27, 0x0d, 0x30, + 0x02, 0xf8, 0x84, 0x16, 0x3a, 0x37, 0x14, 0x26, 0x2d, 0x55, 0x48, 0x24, 0x34, 0xfe, 0xc9, 0x01, 0x3f, 0x23, 0x17, + 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0x00, 0x02, 0x00, 0x12, 0x00, 0x00, 0x01, 0x41, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x0f, + 0x00, 0x2d, 0x40, 0x2a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x72, 0x4d, 0x00, 0x02, 0x02, 0x6d, + 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x0c, 0x0c, 0x01, 0x00, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, + 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x01, 0x13, 0x33, 0x03, 0xe8, 0x21, 0x2b, 0x30, 0x2b, 0x20, 0x2a, 0x2f, 0xff, 0x00, 0x73, 0x97, 0x75, + 0x02, 0x65, 0x1d, 0x20, 0x28, 0x2f, 0x1c, 0x20, 0x28, 0x30, 0xfd, 0x9b, 0x02, 0x22, 0xfd, 0xde, 0x00, 0x02, 0xff, + 0x80, 0xff, 0x10, 0x01, 0x43, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x1b, 0x00, 0x3e, 0x40, 0x3b, 0x10, 0x01, 0x03, 0x04, + 0x0f, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x05, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x72, 0x4d, 0x00, 0x04, + 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x06, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x0d, 0x0c, 0x01, 0x00, + 0x17, 0x16, 0x13, 0x11, 0x0c, 0x1b, 0x0d, 0x1b, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x07, 0x0d, 0x16, 0x2b, 0x13, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, + 0x36, 0x37, 0x13, 0x33, 0x03, 0x0e, 0x02, 0xea, 0x20, 0x2b, 0x2f, 0x2b, 0x20, 0x2a, 0x2f, 0xfe, 0xc2, 0x17, 0x30, + 0x0f, 0x1c, 0x1c, 0x1e, 0x2d, 0x09, 0x7c, 0x95, 0x80, 0x0b, 0x2e, 0x50, 0x02, 0x65, 0x1d, 0x20, 0x28, 0x2f, 0x1c, + 0x20, 0x28, 0x30, 0xfc, 0xab, 0x07, 0x05, 0x77, 0x0a, 0x27, 0x2b, 0x02, 0x47, 0xfd, 0xa4, 0x32, 0x53, 0x31, 0x00, + 0x01, 0x00, 0x12, 0x00, 0x00, 0x02, 0x69, 0x02, 0xf8, 0x00, 0x0f, 0x00, 0x29, 0x40, 0x26, 0x0d, 0x0a, 0x06, 0x03, + 0x02, 0x01, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, + 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x12, 0x16, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, + 0x03, 0x06, 0x06, 0x07, 0x33, 0x37, 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x07, 0x12, 0xa1, 0x93, 0x48, 0x05, 0x14, + 0x05, 0x04, 0xdd, 0xa8, 0xf3, 0x8b, 0xa4, 0x59, 0x3b, 0x24, 0x02, 0xf8, 0xfe, 0xad, 0x19, 0x41, 0x11, 0xe8, 0xf6, + 0xfe, 0xd4, 0xcd, 0x23, 0xaa, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x01, 0x48, 0x02, 0xf8, 0x00, 0x03, 0x00, + 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x11, 0xa2, 0x95, 0xa1, 0x02, 0xf8, 0xfd, 0x08, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x03, 0x56, 0x02, 0x2c, 0x00, 0x2a, 0x00, 0x56, 0xb6, 0x0a, 0x03, 0x02, + 0x04, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x02, 0x01, + 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x08, 0x07, 0x05, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x1a, 0x00, 0x00, + 0x00, 0x6d, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x08, 0x07, 0x05, 0x03, + 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x59, 0x40, 0x10, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x2a, 0x24, 0x14, 0x24, 0x15, 0x25, + 0x24, 0x11, 0x09, 0x0d, 0x1d, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x03, 0x23, 0x13, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, + 0x23, 0x13, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x12, 0x74, 0x70, 0x0a, 0x04, 0x20, 0x53, 0x39, + 0x38, 0x3e, 0x0a, 0x04, 0x1f, 0x56, 0x39, 0x44, 0x44, 0x0b, 0x41, 0x93, 0x43, 0x08, 0x30, 0x21, 0x36, 0x28, 0x0c, + 0x2f, 0x93, 0x43, 0x08, 0x30, 0x21, 0x36, 0x27, 0x0d, 0x30, 0x02, 0x22, 0x65, 0x31, 0x3e, 0x3b, 0x34, 0x31, 0x3e, + 0x55, 0x48, 0x24, 0x34, 0xfe, 0xc9, 0x01, 0x3f, 0x23, 0x17, 0x3c, 0x38, 0x5f, 0x3b, 0xe3, 0x01, 0x3f, 0x23, 0x17, + 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x02, 0x29, 0x02, 0x2c, 0x00, 0x18, 0x00, + 0x4c, 0xb5, 0x03, 0x01, 0x03, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x00, 0x03, 0x03, 0x00, + 0x61, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x17, 0x00, + 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, + 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x24, 0x15, 0x24, 0x11, 0x06, 0x0d, 0x1a, + 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x03, 0x23, 0x13, 0x36, 0x35, + 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x12, 0x74, 0x70, 0x0a, 0x04, 0x20, 0x53, 0x39, 0x47, 0x46, 0x0b, 0x41, + 0x93, 0x43, 0x08, 0x35, 0x21, 0x36, 0x27, 0x0d, 0x30, 0x02, 0x22, 0x65, 0x31, 0x3e, 0x55, 0x48, 0x24, 0x34, 0xfe, + 0xc9, 0x01, 0x3f, 0x23, 0x17, 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x1d, 0x02, + 0x2c, 0x00, 0x10, 0x00, 0x1e, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, + 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x12, 0x11, 0x01, 0x00, 0x19, 0x17, + 0x11, 0x1e, 0x12, 0x1e, 0x0a, 0x08, 0x00, 0x10, 0x01, 0x10, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, + 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x0e, 0x02, 0x15, 0x14, 0xfd, 0x3d, 0x5f, 0x35, 0x24, 0x48, 0x6d, 0x49, 0x5f, 0x70, 0x22, 0x47, 0x6d, 0x3e, 0x29, + 0x39, 0x1e, 0x1f, 0x27, 0x21, 0x32, 0x20, 0x10, 0x0a, 0x33, 0x5e, 0x41, 0x48, 0x81, 0x63, 0x38, 0x72, 0x66, 0x45, + 0x7e, 0x62, 0x39, 0x78, 0x42, 0x69, 0x3b, 0x29, 0x37, 0x2d, 0x48, 0x52, 0x25, 0x5a, 0x00, 0x00, 0x02, 0xff, 0xdf, + 0xff, 0x10, 0x02, 0x27, 0x02, 0x2c, 0x00, 0x18, 0x00, 0x27, 0x00, 0x6c, 0x40, 0x0a, 0x03, 0x01, 0x05, 0x00, 0x13, + 0x01, 0x02, 0x04, 0x02, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x01, 0x01, + 0x00, 0x00, 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, 0x03, 0x03, + 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, + 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, 0x03, 0x03, 0x6f, 0x03, + 0x4e, 0x59, 0x40, 0x14, 0x1a, 0x19, 0x00, 0x00, 0x21, 0x1f, 0x19, 0x27, 0x1a, 0x27, 0x00, 0x18, 0x00, 0x18, 0x27, + 0x24, 0x11, 0x08, 0x0d, 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, + 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x07, 0x13, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, + 0x0e, 0x02, 0x15, 0x14, 0x16, 0x21, 0xa7, 0x70, 0x08, 0x04, 0x1a, 0x4c, 0x35, 0x28, 0x46, 0x2c, 0x24, 0x42, 0x5d, + 0x3a, 0x32, 0x36, 0x14, 0x04, 0x03, 0x0a, 0x08, 0x23, 0x9f, 0x1b, 0x2f, 0x23, 0x14, 0x40, 0x24, 0x32, 0x20, 0x0f, + 0x25, 0xf0, 0x03, 0x12, 0x53, 0x23, 0x3a, 0x27, 0x57, 0x49, 0x42, 0x83, 0x6a, 0x40, 0x2e, 0x22, 0x28, 0x42, 0x26, + 0xa6, 0x01, 0x5d, 0x2b, 0x46, 0x56, 0x2b, 0x56, 0x34, 0x4e, 0x52, 0x1e, 0x27, 0x2f, 0x00, 0x00, 0x02, 0x00, 0x2c, + 0xff, 0x10, 0x02, 0x41, 0x02, 0x2c, 0x00, 0x19, 0x00, 0x29, 0x00, 0x78, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, + 0x14, 0x01, 0x05, 0x01, 0x04, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x14, 0x01, 0x05, 0x02, 0x04, 0x01, + 0x00, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, + 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, + 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, + 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, + 0x40, 0x0f, 0x1b, 0x1a, 0x23, 0x21, 0x1a, 0x29, 0x1b, 0x29, 0x11, 0x14, 0x27, 0x27, 0x07, 0x0d, 0x1a, 0x2b, 0x05, + 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, + 0x37, 0x33, 0x03, 0x23, 0x03, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, + 0x2b, 0x04, 0x0e, 0x11, 0x06, 0x04, 0x1a, 0x44, 0x33, 0x24, 0x43, 0x2c, 0x24, 0x42, 0x5d, 0x3a, 0x31, 0x3e, 0x18, + 0x04, 0x1c, 0x71, 0xa7, 0x93, 0x02, 0x23, 0x31, 0x1e, 0x0f, 0x24, 0x20, 0x1b, 0x2f, 0x23, 0x14, 0x24, 0x4b, 0x12, + 0x35, 0x38, 0x15, 0x22, 0x31, 0x27, 0x57, 0x48, 0x43, 0x82, 0x6b, 0x40, 0x2a, 0x26, 0x46, 0xfc, 0xee, 0x01, 0x5d, + 0x35, 0x4f, 0x51, 0x1d, 0x27, 0x2f, 0x2b, 0x46, 0x56, 0x2b, 0x2b, 0x2b, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x01, + 0xcc, 0x02, 0x2c, 0x00, 0x12, 0x00, 0x69, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0e, 0x03, 0x01, 0x02, 0x00, 0x0b, + 0x01, 0x03, 0x02, 0x02, 0x4c, 0x0a, 0x01, 0x00, 0x4a, 0x1b, 0x40, 0x0e, 0x0a, 0x01, 0x00, 0x01, 0x03, 0x01, 0x02, + 0x00, 0x0b, 0x01, 0x03, 0x02, 0x03, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x02, 0x02, 0x00, + 0x61, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x00, + 0x00, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, + 0x4e, 0x59, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x12, 0x25, 0x24, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, + 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x12, 0x73, + 0x79, 0x0a, 0x04, 0x22, 0x4b, 0x38, 0x0c, 0x1a, 0x09, 0x21, 0x0c, 0x1c, 0x10, 0x39, 0x4e, 0x11, 0x34, 0x02, 0x22, + 0x5e, 0x33, 0x35, 0x02, 0x03, 0x91, 0x04, 0x05, 0x5c, 0x4f, 0xf4, 0x00, 0x01, 0x00, 0x0b, 0xff, 0xf6, 0x01, 0xc7, + 0x02, 0x2c, 0x00, 0x26, 0x00, 0x37, 0x40, 0x34, 0x17, 0x01, 0x03, 0x02, 0x18, 0x04, 0x02, 0x01, 0x03, 0x03, 0x01, + 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, + 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1c, 0x1a, 0x15, 0x13, 0x08, 0x06, 0x00, 0x26, 0x01, 0x26, + 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, + 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, + 0x16, 0x16, 0x15, 0x14, 0x06, 0xb0, 0x35, 0x51, 0x1f, 0x25, 0x4f, 0x28, 0x22, 0x36, 0x0d, 0x23, 0x22, 0x36, 0x33, + 0x6a, 0x67, 0x34, 0x58, 0x26, 0x2f, 0x1b, 0x44, 0x22, 0x1c, 0x20, 0x21, 0x29, 0x37, 0x3b, 0x7e, 0x0a, 0x11, 0x0f, + 0x7c, 0x15, 0x16, 0x19, 0x1c, 0x0f, 0x16, 0x1a, 0x13, 0x1d, 0x47, 0x34, 0x4b, 0x5b, 0x18, 0x16, 0x66, 0x10, 0x19, + 0x1a, 0x17, 0x13, 0x1c, 0x16, 0x1c, 0x48, 0x35, 0x5f, 0x5d, 0x00, 0x01, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xad, 0x02, + 0x96, 0x00, 0x1b, 0x00, 0x66, 0x40, 0x0a, 0x18, 0x01, 0x05, 0x01, 0x19, 0x01, 0x00, 0x05, 0x02, 0x4c, 0x4b, 0xb0, + 0x0a, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x03, 0x03, 0x02, 0x70, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, + 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x1c, 0x00, + 0x02, 0x03, 0x02, 0x85, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, + 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x13, 0x01, 0x00, 0x16, 0x14, 0x0f, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x07, 0x06, 0x00, 0x1b, 0x01, 0x1b, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x37, 0x13, + 0x23, 0x3f, 0x02, 0x33, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, + 0x06, 0xc8, 0x40, 0x4e, 0x06, 0x38, 0x4a, 0x0e, 0x60, 0x40, 0x5f, 0x18, 0x8a, 0x18, 0x8a, 0x38, 0x03, 0x18, 0x13, + 0x14, 0x25, 0x16, 0x17, 0x42, 0x0a, 0x37, 0x47, 0x19, 0x1e, 0x01, 0x07, 0x48, 0x29, 0x73, 0x74, 0x70, 0xfe, 0xf9, + 0x0f, 0x0b, 0x13, 0x11, 0x09, 0x08, 0x6e, 0x0b, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x36, 0xff, 0xf6, 0x02, 0x4b, 0x02, + 0x22, 0x00, 0x19, 0x00, 0x5e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0xb5, 0x16, 0x01, 0x00, 0x02, 0x01, 0x4c, 0x1b, 0xb5, + 0x16, 0x01, 0x04, 0x02, 0x01, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x03, 0x01, 0x01, 0x01, 0x6d, + 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x05, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x17, 0x03, 0x01, + 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x04, 0x04, 0x6b, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x05, 0x01, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, 0x15, 0x14, 0x13, 0x12, 0x0e, 0x0c, 0x08, 0x07, 0x00, 0x19, 0x01, 0x19, + 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x15, 0x14, 0x33, 0x32, + 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0xc1, 0x46, 0x45, 0x06, 0x06, 0x3e, 0x93, 0x43, + 0x08, 0x35, 0x22, 0x35, 0x28, 0x0c, 0x30, 0x93, 0x74, 0x70, 0x0a, 0x05, 0x1f, 0x53, 0x0a, 0x55, 0x48, 0x12, 0x39, + 0x1d, 0x01, 0x27, 0xfe, 0xc1, 0x23, 0x17, 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0xfd, 0xde, 0x65, 0x31, 0x3e, 0x00, 0x01, + 0x00, 0x32, 0x00, 0x00, 0x02, 0x3a, 0x02, 0x22, 0x00, 0x0d, 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, + 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0d, 0x00, + 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x16, 0x15, 0x33, 0x36, 0x36, 0x37, 0x13, + 0x33, 0x01, 0x75, 0x43, 0x90, 0x16, 0x02, 0x01, 0x05, 0x09, 0x18, 0x0a, 0x91, 0x9e, 0xfe, 0xd9, 0x02, 0x22, 0xfe, + 0xe2, 0x13, 0x43, 0x1b, 0x19, 0x41, 0x13, 0x01, 0x22, 0xfd, 0xde, 0x00, 0x00, 0x01, 0x00, 0x3d, 0x00, 0x00, 0x03, + 0x47, 0x02, 0x22, 0x00, 0x25, 0x00, 0x27, 0x40, 0x24, 0x1f, 0x11, 0x06, 0x03, 0x03, 0x00, 0x01, 0x4c, 0x02, 0x01, + 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x25, 0x00, 0x25, + 0x11, 0x1a, 0x1a, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x03, 0x33, 0x17, 0x14, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, + 0x13, 0x33, 0x11, 0x14, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, 0x37, 0x33, 0x01, 0x23, 0x27, 0x34, 0x36, 0x36, 0x37, + 0x23, 0x0e, 0x02, 0x07, 0x03, 0x56, 0x19, 0x89, 0x02, 0x01, 0x04, 0x04, 0x07, 0x16, 0x13, 0x04, 0x71, 0xa0, 0x01, + 0x04, 0x05, 0x07, 0x15, 0x16, 0x08, 0x6b, 0x96, 0xfe, 0xfd, 0xa1, 0x03, 0x01, 0x03, 0x01, 0x06, 0x08, 0x15, 0x14, + 0x08, 0x72, 0x02, 0x22, 0xf2, 0x28, 0x4f, 0x2e, 0x19, 0x3d, 0x32, 0x09, 0x01, 0x06, 0xfe, 0xfa, 0x22, 0x46, 0x29, + 0x17, 0x3e, 0x3d, 0x13, 0xf2, 0xfd, 0xde, 0xfe, 0x15, 0x3b, 0x3e, 0x18, 0x18, 0x3b, 0x36, 0x13, 0xfe, 0xf8, 0x00, + 0x01, 0xff, 0xce, 0x00, 0x00, 0x02, 0x47, 0x02, 0x22, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, + 0x04, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x12, 0x12, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, + 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x32, 0xe8, 0x6b, 0xa0, 0x37, 0x75, 0xb0, 0xe1, 0x73, 0xa2, 0x3b, 0x7f, 0x01, + 0x18, 0x01, 0x0a, 0xaa, 0xaa, 0xfe, 0xee, 0xfe, 0xf0, 0xb3, 0xb3, 0x00, 0x01, 0xff, 0xbb, 0xff, 0x10, 0x02, 0x3b, + 0x02, 0x22, 0x00, 0x1a, 0x00, 0x30, 0x40, 0x2d, 0x11, 0x0b, 0x04, 0x03, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, + 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x62, 0x04, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, + 0x01, 0x00, 0x17, 0x16, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x1a, 0x01, 0x1a, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, + 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x03, 0x33, 0x17, 0x16, 0x16, 0x15, 0x33, 0x36, 0x36, 0x37, + 0x13, 0x33, 0x01, 0x06, 0x06, 0x03, 0x1a, 0x22, 0x0c, 0x0d, 0x1b, 0x11, 0x2f, 0x3c, 0x16, 0x0d, 0x50, 0x90, 0x1b, + 0x04, 0x02, 0x04, 0x0a, 0x18, 0x13, 0x7f, 0xa0, 0xfe, 0xb4, 0x2c, 0x77, 0xf0, 0x05, 0x04, 0x75, 0x02, 0x04, 0x36, + 0x2a, 0x18, 0x02, 0x22, 0xfd, 0x22, 0x50, 0x1d, 0x19, 0x43, 0x29, 0x01, 0x07, 0xfd, 0x90, 0x53, 0x4f, 0x00, 0x00, + 0x01, 0xff, 0xee, 0x00, 0x00, 0x01, 0xdf, 0x02, 0x22, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, + 0x5f, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, + 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x01, 0x23, 0x37, 0x21, 0x07, + 0x01, 0x33, 0x07, 0x12, 0x11, 0x01, 0x18, 0xc2, 0x1a, 0x01, 0x70, 0x15, 0xfe, 0xed, 0xd5, 0x18, 0x59, 0x01, 0x57, + 0x72, 0x63, 0xfe, 0xb4, 0x73, 0x00, 0x01, 0xff, 0xff, 0xff, 0x62, 0x01, 0xa3, 0x02, 0xca, 0x00, 0x2c, 0x00, 0x37, + 0x40, 0x34, 0x1d, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, 0x05, 0x06, + 0x01, 0x00, 0x05, 0x00, 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, 0x4e, 0x01, 0x00, 0x2b, + 0x2a, 0x17, 0x16, 0x15, 0x13, 0x0e, 0x0d, 0x0c, 0x0b, 0x00, 0x2c, 0x01, 0x2c, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, + 0x26, 0x35, 0x34, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x37, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, 0x33, + 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, 0x06, 0x06, + 0x15, 0x14, 0x16, 0x33, 0x15, 0xde, 0x56, 0x4d, 0x08, 0x14, 0x02, 0x03, 0x2a, 0x33, 0x17, 0x3b, 0x3c, 0x0a, 0x1d, + 0x11, 0x53, 0x5d, 0x2e, 0x18, 0x27, 0x2e, 0x09, 0x1d, 0x0c, 0x43, 0x36, 0x2a, 0x26, 0x04, 0x02, 0x13, 0x02, 0x03, + 0x21, 0x1e, 0x9e, 0x41, 0x3c, 0x1d, 0x24, 0x5c, 0x0a, 0x11, 0x07, 0x22, 0x22, 0x72, 0x28, 0x30, 0x86, 0x4c, 0x4c, + 0x70, 0x1b, 0x29, 0x8a, 0x36, 0x37, 0x07, 0x03, 0x0d, 0x38, 0x29, 0x0b, 0x18, 0x0b, 0x59, 0x0a, 0x10, 0x07, 0x19, + 0x14, 0x70, 0x00, 0x00, 0x01, 0x00, 0xde, 0xff, 0x1d, 0x01, 0x49, 0x02, 0xf5, 0x00, 0x03, 0x00, 0x30, 0x4b, 0xb0, + 0x27, 0x50, 0x58, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x1b, 0x40, + 0x0c, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x4e, 0x59, 0x40, 0x0a, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x17, 0x11, 0x33, 0x11, 0xde, 0x6b, 0xe3, 0x03, 0xd8, 0xfc, 0x28, + 0x00, 0x00, 0x01, 0xff, 0xcd, 0xff, 0x62, 0x01, 0x65, 0x02, 0xca, 0x00, 0x2a, 0x00, 0x31, 0x40, 0x2e, 0x07, 0x01, + 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, + 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x2a, 0x28, 0x23, 0x22, 0x21, 0x20, 0x17, 0x15, + 0x14, 0x13, 0x10, 0x06, 0x0d, 0x17, 0x2b, 0x07, 0x36, 0x36, 0x37, 0x37, 0x36, 0x36, 0x37, 0x35, 0x26, 0x26, 0x35, + 0x34, 0x36, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x23, 0x37, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x07, 0x06, 0x06, + 0x15, 0x14, 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x06, 0x06, 0x23, 0x23, 0x33, 0x33, 0x2a, 0x09, 0x1d, 0x0c, 0x43, + 0x36, 0x2a, 0x26, 0x04, 0x03, 0x13, 0x02, 0x03, 0x4a, 0x15, 0x15, 0x56, 0x4c, 0x09, 0x14, 0x02, 0x03, 0x61, 0x17, + 0x3b, 0x40, 0x0a, 0x1d, 0x11, 0x58, 0x5d, 0x19, 0x2e, 0x01, 0x1b, 0x29, 0x89, 0x36, 0x36, 0x07, 0x04, 0x0d, 0x37, + 0x2a, 0x0a, 0x19, 0x0b, 0x59, 0x0a, 0x10, 0x07, 0x2d, 0x70, 0x45, 0x38, 0x1d, 0x24, 0x5d, 0x0a, 0x10, 0x07, 0x44, + 0x72, 0x28, 0x30, 0x86, 0x4e, 0x4a, 0x00, 0x01, 0x00, 0x35, 0x01, 0x0d, 0x02, 0x1a, 0x01, 0xb4, 0x00, 0x17, 0x00, + 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, 0x02, 0x01, 0x13, 0x01, 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, + 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, 0x00, 0x02, 0x00, 0x03, 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, + 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, 0x03, 0x51, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, + 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, + 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x01, 0x16, 0x25, 0x33, 0x17, 0x1c, 0x3d, 0x19, 0x32, 0x4b, + 0x1d, 0x3b, 0x2f, 0x25, 0x34, 0x16, 0x1d, 0x3c, 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x01, 0x2d, 0x10, 0x0b, 0x22, 0x19, + 0x71, 0x35, 0x0b, 0x14, 0x10, 0x0b, 0x22, 0x19, 0x71, 0x35, 0x0c, 0x00, 0x01, 0x00, 0x38, 0x01, 0x9f, 0x01, 0xa7, + 0x03, 0x55, 0x00, 0x18, 0x00, 0x32, 0x40, 0x2f, 0x0b, 0x01, 0x00, 0x01, 0x0a, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x69, 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, + 0x01, 0x03, 0x02, 0x03, 0x4f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x17, 0x24, 0x27, 0x05, 0x0c, 0x19, 0x2b, 0x13, + 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x06, 0x07, 0x07, 0x33, 0x07, 0x38, 0x11, 0x85, 0x30, 0x32, 0x19, 0x11, 0x2a, 0x32, 0x31, 0x24, 0x51, 0x35, 0x3d, + 0x47, 0x1f, 0x3d, 0x2d, 0x3f, 0xa9, 0x14, 0x01, 0x9f, 0x51, 0x6b, 0x27, 0x31, 0x1c, 0x14, 0x14, 0x28, 0x4d, 0x1c, + 0x1d, 0x3e, 0x2f, 0x29, 0x3b, 0x34, 0x21, 0x2e, 0x62, 0x00, 0x00, 0x01, 0x00, 0x48, 0x01, 0x97, 0x01, 0xa8, 0x03, + 0x54, 0x00, 0x2b, 0x00, 0x4d, 0x40, 0x4a, 0x1a, 0x01, 0x04, 0x05, 0x19, 0x01, 0x03, 0x04, 0x24, 0x01, 0x02, 0x03, + 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x69, 0x00, + 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x01, 0x00, 0x51, 0x01, 0x00, 0x1e, 0x1c, 0x17, 0x15, 0x11, 0x0f, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x2b, + 0x01, 0x2b, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, + 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xca, 0x25, 0x45, 0x18, 0x1d, 0x3d, 0x22, + 0x23, 0x32, 0x19, 0x1f, 0x3e, 0x11, 0x2c, 0x29, 0x2f, 0x19, 0x16, 0x16, 0x2f, 0x17, 0x28, 0x23, 0x4a, 0x2c, 0x33, + 0x3c, 0x1b, 0x3e, 0x2c, 0x29, 0x22, 0x37, 0x58, 0x01, 0x97, 0x0f, 0x0c, 0x5e, 0x10, 0x13, 0x1d, 0x1d, 0x12, 0x19, + 0x4e, 0x1b, 0x1c, 0x14, 0x13, 0x11, 0x0f, 0x49, 0x17, 0x16, 0x1d, 0x2f, 0x1b, 0x33, 0x33, 0x0b, 0x04, 0x09, 0x2c, + 0x20, 0x31, 0x3e, 0x1d, 0x00, 0x00, 0x01, 0x00, 0x5b, 0x01, 0x9f, 0x01, 0x83, 0x03, 0x4b, 0x00, 0x0c, 0x00, 0x20, + 0x40, 0x1d, 0x08, 0x07, 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, + 0x01, 0x5f, 0x00, 0x01, 0x00, 0x01, 0x4f, 0x11, 0x19, 0x02, 0x0c, 0x18, 0x2b, 0x13, 0x36, 0x36, 0x37, 0x06, 0x06, + 0x07, 0x07, 0x27, 0x37, 0x33, 0x03, 0x23, 0xd9, 0x07, 0x0f, 0x05, 0x09, 0x17, 0x07, 0x40, 0x32, 0xc3, 0x65, 0x5b, + 0x78, 0x02, 0x61, 0x1f, 0x35, 0x11, 0x07, 0x11, 0x05, 0x28, 0x51, 0x79, 0xfe, 0x54, 0x00, 0x00, 0x01, 0xfe, 0xfb, + 0x00, 0x00, 0x01, 0x83, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, + 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x21, 0x01, 0x33, + 0x01, 0xfe, 0xfb, 0x02, 0x13, 0x75, 0xfd, 0xef, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x02, 0x00, 0x32, 0x01, 0x9f, 0x01, + 0xa8, 0x03, 0x4e, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x61, 0xb5, 0x10, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x11, + 0x50, 0x58, 0x40, 0x1f, 0x00, 0x01, 0x02, 0x01, 0x85, 0x06, 0x01, 0x04, 0x00, 0x00, 0x04, 0x71, 0x05, 0x01, 0x02, + 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, 0x02, 0x02, 0x00, 0x60, 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, 0x1b, 0x40, 0x1e, + 0x00, 0x01, 0x02, 0x01, 0x85, 0x06, 0x01, 0x04, 0x00, 0x04, 0x86, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, + 0x01, 0x02, 0x02, 0x00, 0x60, 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, 0x59, 0x40, 0x0f, 0x00, 0x00, 0x0c, 0x0b, 0x00, + 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0c, 0x1a, 0x2b, 0x13, 0x37, 0x23, 0x37, 0x13, 0x33, 0x03, 0x33, + 0x07, 0x23, 0x07, 0x27, 0x33, 0x37, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0xd8, 0x10, 0xb6, 0x0f, 0xe8, 0x7f, 0x3b, + 0x3a, 0x11, 0x3a, 0x10, 0xa8, 0x55, 0x14, 0x05, 0x07, 0x07, 0x09, 0x19, 0x08, 0x01, 0x9f, 0x4a, 0x55, 0x01, 0x10, + 0xfe, 0xed, 0x52, 0x4a, 0x9c, 0x50, 0x14, 0x19, 0x18, 0x0d, 0x1f, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x49, 0x01, 0x97, + 0x01, 0xac, 0x03, 0x4b, 0x00, 0x1e, 0x00, 0x47, 0x40, 0x44, 0x15, 0x10, 0x02, 0x02, 0x05, 0x0f, 0x04, 0x02, 0x01, + 0x02, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x05, 0x00, 0x02, + 0x01, 0x05, 0x02, 0x69, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x01, + 0x00, 0x51, 0x01, 0x00, 0x19, 0x17, 0x14, 0x13, 0x12, 0x11, 0x0d, 0x0b, 0x08, 0x06, 0x00, 0x1e, 0x01, 0x1e, 0x07, + 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x07, + 0x27, 0x37, 0x21, 0x07, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc5, 0x22, 0x43, 0x17, + 0x19, 0x3c, 0x1c, 0x32, 0x2a, 0x40, 0x10, 0x23, 0x0e, 0x25, 0x3a, 0x01, 0x02, 0x14, 0xad, 0x15, 0x08, 0x19, 0x13, + 0x38, 0x45, 0x33, 0x58, 0x01, 0x97, 0x0d, 0x0d, 0x59, 0x0f, 0x11, 0x2b, 0x1d, 0x36, 0x06, 0x04, 0x21, 0xcc, 0x5a, + 0x44, 0x02, 0x04, 0x40, 0x35, 0x35, 0x4b, 0x27, 0x00, 0x01, 0x00, 0x62, 0x01, 0x9f, 0x01, 0xd2, 0x03, 0x4b, 0x00, + 0x06, 0x00, 0x24, 0x40, 0x21, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, + 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0c, 0x18, + 0x2b, 0x13, 0x13, 0x23, 0x37, 0x21, 0x07, 0x03, 0x62, 0xe2, 0xc6, 0x13, 0x01, 0x41, 0x0f, 0xe3, 0x01, 0x9f, 0x01, + 0x52, 0x5a, 0x49, 0xfe, 0x9d, 0x00, 0x00, 0x03, 0x00, 0x4c, 0x01, 0x95, 0x01, 0xae, 0x03, 0x55, 0x00, 0x18, 0x00, + 0x24, 0x00, 0x30, 0x00, 0x39, 0x40, 0x36, 0x2b, 0x13, 0x06, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x01, 0x00, 0x02, + 0x03, 0x01, 0x02, 0x69, 0x05, 0x01, 0x03, 0x00, 0x00, 0x03, 0x59, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, + 0x00, 0x03, 0x00, 0x51, 0x26, 0x25, 0x01, 0x00, 0x25, 0x30, 0x26, 0x30, 0x20, 0x1e, 0x0e, 0x0c, 0x00, 0x18, 0x01, + 0x18, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x06, 0x15, 0x14, 0x16, 0x07, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, 0xe4, 0x49, 0x4f, + 0x3b, 0x35, 0x19, 0x1c, 0x2b, 0x46, 0x28, 0x48, 0x46, 0x30, 0x2c, 0x20, 0x26, 0x66, 0x1d, 0x14, 0x1a, 0x10, 0x14, + 0x11, 0x18, 0x12, 0x1c, 0x1a, 0x1d, 0x15, 0x13, 0x16, 0x28, 0x1a, 0x01, 0x95, 0x42, 0x30, 0x2e, 0x3b, 0x12, 0x11, + 0x2b, 0x1e, 0x27, 0x36, 0x1c, 0x3a, 0x2c, 0x2b, 0x33, 0x10, 0x11, 0x30, 0x24, 0x43, 0x44, 0x01, 0x17, 0x09, 0x1a, + 0x16, 0x0d, 0x16, 0x18, 0x14, 0x10, 0x18, 0xd2, 0x1f, 0x15, 0x15, 0x1c, 0x0b, 0x07, 0x21, 0x1b, 0x14, 0x19, 0x00, + 0x02, 0x00, 0x5d, 0x01, 0x95, 0x01, 0xb6, 0x03, 0x55, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, + 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, + 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x10, 0x0f, 0x01, 0x00, 0x17, 0x15, 0x0f, 0x1c, 0x10, 0x1c, 0x09, 0x07, 0x00, + 0x0e, 0x01, 0x0e, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, + 0x06, 0x06, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xe7, 0x40, 0x4a, 0x13, 0x2f, + 0x4f, 0x3c, 0x43, 0x49, 0x30, 0x5c, 0x3a, 0x12, 0x1d, 0x14, 0x0b, 0x1c, 0x10, 0x1d, 0x14, 0x0c, 0x01, 0x95, 0x4d, + 0x46, 0x30, 0x68, 0x5c, 0x39, 0x4d, 0x4a, 0x52, 0x87, 0x50, 0x65, 0x27, 0x3c, 0x45, 0x1e, 0x2f, 0x24, 0x3c, 0x45, + 0x21, 0x2f, 0x00, 0x02, 0x00, 0x5b, 0x01, 0x97, 0x01, 0xb7, 0x03, 0x54, 0x00, 0x1d, 0x00, 0x2a, 0x00, 0x4b, 0x40, + 0x48, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, 0x03, 0x02, 0x13, 0x01, 0x05, 0x03, 0x03, 0x4c, 0x00, 0x01, 0x00, 0x02, + 0x03, 0x01, 0x02, 0x69, 0x00, 0x03, 0x00, 0x05, 0x04, 0x03, 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x00, 0x04, 0x59, + 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x04, 0x00, 0x51, 0x1f, 0x1e, 0x01, 0x00, 0x25, 0x23, 0x1e, + 0x2a, 0x1f, 0x2a, 0x18, 0x16, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1d, 0x01, 0x1d, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x22, + 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x33, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x27, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, + 0x14, 0x16, 0xf0, 0x43, 0x52, 0x16, 0x39, 0x66, 0x4f, 0x14, 0x39, 0x0b, 0x15, 0x0a, 0x29, 0x1c, 0x2d, 0x36, 0x1b, + 0x07, 0x04, 0x0e, 0x30, 0x21, 0x37, 0x37, 0x2b, 0x4e, 0x34, 0x20, 0x22, 0x19, 0x14, 0x19, 0x1c, 0x0c, 0x16, 0x01, + 0x97, 0x57, 0x55, 0x26, 0x5e, 0x56, 0x37, 0x06, 0x04, 0x5c, 0x05, 0x09, 0x23, 0x34, 0x1a, 0x11, 0x1a, 0x40, 0x32, + 0x31, 0x4f, 0x2d, 0x55, 0x2f, 0x1f, 0x17, 0x1b, 0x1b, 0x23, 0x0d, 0x17, 0x1e, 0x00, 0x00, 0x02, 0x00, 0x5b, 0x01, + 0x97, 0x01, 0xb1, 0x03, 0x54, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x4a, 0x40, 0x47, 0x12, 0x01, 0x03, 0x04, 0x0b, 0x01, + 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x69, 0x07, 0x01, + 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, + 0x01, 0x02, 0x01, 0x51, 0x1e, 0x1d, 0x01, 0x00, 0x24, 0x22, 0x1d, 0x28, 0x1e, 0x28, 0x17, 0x15, 0x0f, 0x0d, 0x08, + 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x08, 0x0c, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, + 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, + 0x17, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x01, 0x1c, 0x4b, 0x4a, 0x40, 0x79, 0x56, + 0x13, 0x29, 0x0b, 0x0d, 0x2d, 0x10, 0x31, 0x3c, 0x23, 0x09, 0x03, 0x10, 0x2f, 0x21, 0x37, 0x37, 0x2b, 0x4f, 0x1f, + 0x1f, 0x22, 0x16, 0x17, 0x1e, 0x23, 0x19, 0x03, 0x54, 0x52, 0x46, 0x58, 0x84, 0x49, 0x05, 0x04, 0x5b, 0x05, 0x07, + 0x1e, 0x33, 0x1d, 0x10, 0x18, 0x41, 0x31, 0x32, 0x4e, 0x2d, 0xd3, 0x2b, 0x1f, 0x17, 0x1e, 0x2d, 0x20, 0x17, 0x1b, + 0x00, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x01, 0xe5, 0x02, 0xfd, 0x00, 0x17, 0x00, 0x35, 0x40, 0x32, 0x0b, 0x01, + 0x02, 0x01, 0x0c, 0x01, 0x03, 0x02, 0x02, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x04, 0x01, 0x00, + 0x00, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x28, 0x4d, 0x06, 0x01, 0x05, 0x05, 0x27, 0x05, 0x4e, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x17, 0x11, 0x13, 0x25, 0x25, 0x11, 0x07, 0x07, 0x1b, 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, + 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x2a, 0x5b, 0x55, 0x0f, + 0x5f, 0x0a, 0x15, 0x5f, 0x50, 0x22, 0x41, 0x16, 0x26, 0x0e, 0x22, 0x11, 0x19, 0x21, 0x07, 0x0a, 0x6c, 0x19, 0x6b, + 0x5c, 0x01, 0xb2, 0x47, 0x29, 0x29, 0x61, 0x51, 0x0e, 0x0a, 0x69, 0x06, 0x08, 0x1c, 0x22, 0x2a, 0x70, 0xfe, 0x4e, + 0x00, 0x01, 0xff, 0x95, 0xff, 0x10, 0x03, 0x36, 0x02, 0xfd, 0x00, 0x41, 0x00, 0xc5, 0x40, 0x16, 0x23, 0x13, 0x02, + 0x04, 0x03, 0x24, 0x14, 0x02, 0x05, 0x04, 0x36, 0x03, 0x02, 0x01, 0x02, 0x35, 0x02, 0x02, 0x00, 0x01, 0x04, 0x4c, + 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x27, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, 0x4d, + 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, + 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x27, 0x07, 0x01, 0x04, + 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, + 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, + 0x27, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, + 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, + 0x00, 0x4e, 0x59, 0x59, 0x40, 0x21, 0x01, 0x00, 0x3d, 0x3c, 0x39, 0x37, 0x34, 0x32, 0x2e, 0x2d, 0x2c, 0x2b, 0x28, + 0x26, 0x21, 0x1f, 0x1c, 0x1b, 0x18, 0x16, 0x11, 0x0f, 0x0a, 0x09, 0x06, 0x04, 0x00, 0x41, 0x01, 0x41, 0x0e, 0x0d, + 0x16, 0x2b, 0x07, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, + 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, + 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, + 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x0e, 0x02, 0x16, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0x50, 0x0f, + 0x59, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, + 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0x6b, 0x18, 0x6b, 0x69, 0x0a, 0x2e, + 0x4f, 0x3e, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0xc1, 0x69, 0x0a, 0x2e, 0x4f, 0xf0, 0x0c, 0x76, 0x0a, + 0x28, 0x2b, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, + 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x70, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x0c, 0x76, 0x0a, 0x28, + 0x2b, 0x01, 0xd7, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x00, 0x03, 0xff, 0x95, 0xff, 0x10, 0x03, 0xfe, 0x02, 0xfd, 0x00, + 0x41, 0x00, 0x4d, 0x00, 0x51, 0x01, 0x75, 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x03, + 0x24, 0x14, 0x02, 0x0d, 0x04, 0x36, 0x03, 0x02, 0x01, 0x10, 0x35, 0x02, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x1b, 0x40, + 0x16, 0x23, 0x13, 0x02, 0x04, 0x0e, 0x24, 0x14, 0x02, 0x0d, 0x04, 0x36, 0x03, 0x02, 0x01, 0x10, 0x35, 0x02, 0x02, + 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x3c, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0e, + 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x12, 0x01, 0x0d, 0x0d, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, + 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, + 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, + 0x50, 0x58, 0x40, 0x3c, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x12, 0x01, + 0x0d, 0x0d, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, + 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, + 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x3c, 0x07, 0x01, 0x04, 0x04, + 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x12, 0x01, 0x0d, 0x0d, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, + 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, + 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, + 0x40, 0x39, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, 0x4d, 0x12, 0x01, 0x0d, 0x0d, 0x0e, + 0x61, 0x00, 0x0e, 0x0e, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, + 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, + 0x00, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x31, 0x4e, 0x4e, 0x43, 0x42, 0x01, 0x00, 0x4e, 0x51, 0x4e, 0x51, 0x50, 0x4f, + 0x49, 0x47, 0x42, 0x4d, 0x43, 0x4d, 0x3d, 0x3c, 0x39, 0x37, 0x34, 0x32, 0x2e, 0x2d, 0x2c, 0x2b, 0x28, 0x26, 0x21, + 0x1f, 0x1c, 0x1b, 0x18, 0x16, 0x11, 0x0f, 0x0a, 0x09, 0x06, 0x04, 0x00, 0x41, 0x01, 0x41, 0x14, 0x0d, 0x16, 0x2b, + 0x07, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, + 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x13, 0x23, 0x03, 0x0e, 0x02, 0x01, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, + 0x13, 0x33, 0x03, 0x16, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, + 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, + 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0x6b, 0x18, 0x6b, 0x69, 0x0a, 0x2e, 0x4f, 0x3e, 0x33, 0x22, 0x1e, + 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0xc1, 0x69, 0x0a, 0x2e, 0x4f, 0x03, 0x7e, 0x1f, 0x2b, 0x2f, 0x2a, 0x1d, 0x2c, 0x2b, + 0xfe, 0xfe, 0x74, 0x93, 0x74, 0xf0, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x63, 0x4f, 0x0d, + 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x70, + 0xfe, 0x13, 0x32, 0x52, 0x31, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x03, 0x56, + 0x1b, 0x21, 0x2a, 0x2c, 0x1a, 0x21, 0x27, 0x30, 0xfd, 0x9a, 0x02, 0x22, 0xfd, 0xde, 0x00, 0x02, 0xff, 0x95, 0xff, + 0x10, 0x04, 0x05, 0x02, 0xfd, 0x00, 0x41, 0x00, 0x45, 0x01, 0x3c, 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x16, 0x23, + 0x13, 0x02, 0x04, 0x03, 0x24, 0x14, 0x02, 0x05, 0x04, 0x36, 0x03, 0x02, 0x01, 0x0e, 0x35, 0x02, 0x02, 0x00, 0x01, + 0x04, 0x4c, 0x1b, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x0d, 0x24, 0x14, 0x02, 0x05, 0x04, 0x36, 0x03, 0x02, 0x01, + 0x0e, 0x35, 0x02, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, + 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, + 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, + 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, + 0x0d, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, + 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, + 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, + 0x03, 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, + 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, + 0x40, 0x32, 0x00, 0x0d, 0x0d, 0x6c, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, 0x4d, + 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, + 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x29, + 0x42, 0x42, 0x01, 0x00, 0x42, 0x45, 0x42, 0x45, 0x44, 0x43, 0x3d, 0x3c, 0x39, 0x37, 0x34, 0x32, 0x2e, 0x2d, 0x2c, + 0x2b, 0x28, 0x26, 0x21, 0x1f, 0x1c, 0x1b, 0x18, 0x16, 0x11, 0x0f, 0x0a, 0x09, 0x06, 0x04, 0x00, 0x41, 0x01, 0x41, + 0x11, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x35, + 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x0e, 0x02, 0x25, 0x13, 0x33, 0x03, 0x16, 0x33, 0x22, 0x1e, 0x1a, + 0x1e, 0x2d, 0x09, 0x64, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, + 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, + 0x6b, 0x18, 0x6b, 0x69, 0x0a, 0x2e, 0x4f, 0x3e, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0xc1, 0x69, 0x0a, + 0x2e, 0x4f, 0x02, 0xa9, 0xa1, 0x93, 0xa1, 0xf0, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x63, + 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, + 0x1e, 0x70, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0xfe, 0x13, 0x32, 0x52, 0x31, + 0xf0, 0x02, 0xf8, 0xfd, 0x08, 0x00, 0xff, 0xff, 0xff, 0x96, 0xff, 0x10, 0x02, 0xb6, 0x02, 0xfd, 0x00, 0x26, 0x00, + 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0xff, 0x96, 0xff, 0x10, 0x02, 0xbd, + 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x29, 0x00, 0x00, 0x03, 0x36, 0x02, 0xfd, 0x00, 0x2b, 0x00, 0x42, 0x40, 0x3f, 0x1b, 0x0b, 0x02, 0x02, 0x01, 0x1c, + 0x0c, 0x02, 0x03, 0x02, 0x02, 0x4c, 0x04, 0x01, 0x01, 0x05, 0x01, 0x02, 0x03, 0x01, 0x02, 0x69, 0x09, 0x07, 0x02, + 0x00, 0x00, 0x03, 0x5f, 0x06, 0x01, 0x03, 0x03, 0x28, 0x4d, 0x0b, 0x0a, 0x02, 0x08, 0x08, 0x27, 0x08, 0x4e, 0x00, + 0x00, 0x00, 0x2b, 0x00, 0x2b, 0x2a, 0x29, 0x11, 0x11, 0x13, 0x25, 0x23, 0x13, 0x25, 0x25, 0x11, 0x0c, 0x07, 0x1f, + 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, + 0x07, 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, + 0x23, 0x03, 0x23, 0x13, 0x23, 0x03, 0x29, 0x5c, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, + 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, + 0x1c, 0x22, 0x06, 0x06, 0x6b, 0x18, 0x6b, 0x5c, 0x93, 0x5c, 0xc1, 0x5c, 0x01, 0xb2, 0x47, 0x29, 0x29, 0x63, 0x4f, + 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, + 0x70, 0xfe, 0x4e, 0x01, 0xb2, 0xfe, 0x4e, 0xff, 0xff, 0x00, 0x29, 0x00, 0x00, 0x04, 0x0a, 0x02, 0xfd, 0x00, 0x26, + 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x02, 0xc9, 0x00, 0x00, 0xff, 0xff, 0x00, 0x29, 0x00, 0x00, 0x04, + 0x11, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x02, 0xc9, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x2a, 0x00, 0x00, 0x02, 0xb6, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, + 0x75, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2a, 0x00, 0x00, 0x02, 0xbd, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x4d, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0xff, 0xf5, 0x01, 0x5c, 0x01, 0xb5, 0x01, + 0x07, 0x00, 0x68, 0xff, 0xa6, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0xff, 0xff, 0x01, 0x36, 0x01, 0xab, 0x01, 0x07, 0x00, 0x62, 0xff, 0xb3, 0xfe, 0x60, 0x00, + 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xe2, 0xff, 0xff, 0x01, 0x51, + 0x01, 0xb5, 0x01, 0x07, 0x00, 0x60, 0xff, 0xaa, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, + 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xf7, 0x01, 0x58, 0x01, 0xb4, 0x01, 0x07, 0x00, 0x61, 0xff, 0xb0, + 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xe1, 0xff, + 0xff, 0x01, 0x57, 0x01, 0xae, 0x01, 0x07, 0x00, 0x64, 0xff, 0xaf, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, + 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xf7, 0x01, 0x5e, 0x01, 0xab, 0x01, 0x07, 0x00, + 0x65, 0xff, 0xb2, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x04, 0xff, 0xf7, 0x01, 0x60, 0x01, 0xb4, 0x01, 0x07, 0x00, 0x69, 0xff, 0xa9, 0xfe, 0x60, 0x00, 0x09, 0xb1, + 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0b, 0xff, 0xff, 0x01, 0x7b, 0x01, 0xab, + 0x01, 0x07, 0x00, 0x66, 0xff, 0xa9, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, + 0x00, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xf5, 0x01, 0x58, 0x01, 0xb5, 0x01, 0x07, 0x00, 0x67, 0xff, 0xaa, 0xfe, 0x60, + 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x03, 0xff, 0xf7, 0x01, + 0x59, 0x01, 0xb4, 0x01, 0x07, 0x00, 0x6a, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x3f, 0x01, 0x13, 0x01, 0x98, 0x02, 0xd3, 0x01, 0x07, 0x00, 0x68, 0xff, + 0xe2, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x47, + 0x01, 0x1d, 0x01, 0x6f, 0x02, 0xc9, 0x01, 0x07, 0x00, 0x62, 0xff, 0xec, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, + 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1b, 0x01, 0x1d, 0x01, 0x8a, 0x02, 0xd3, 0x01, 0x07, + 0x00, 0x60, 0xff, 0xe3, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, + 0xff, 0x00, 0x2f, 0x01, 0x15, 0x01, 0x8f, 0x02, 0xd2, 0x01, 0x07, 0x00, 0x61, 0xff, 0xe7, 0xff, 0x7e, 0x00, 0x09, + 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1c, 0x01, 0x1d, 0x01, 0x92, 0x02, + 0xcc, 0x01, 0x07, 0x00, 0x64, 0xff, 0xea, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0x00, 0x37, 0x01, 0x15, 0x01, 0x9a, 0x02, 0xc9, 0x01, 0x07, 0x00, 0x65, 0xff, 0xee, 0xff, + 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x44, 0x01, 0x15, + 0x01, 0xa0, 0x02, 0xd2, 0x01, 0x07, 0x00, 0x69, 0xff, 0xe9, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, + 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x01, 0x1d, 0x01, 0xbd, 0x02, 0xc9, 0x01, 0x07, 0x00, 0x66, + 0xff, 0xeb, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, + 0x33, 0x01, 0x13, 0x01, 0x95, 0x02, 0xd3, 0x01, 0x07, 0x00, 0x67, 0xff, 0xe7, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, + 0x03, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x41, 0x01, 0x15, 0x01, 0x97, 0x02, 0xd2, 0x01, + 0x07, 0x00, 0x6a, 0xff, 0xe6, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8a, 0x00, 0xd3, 0x00, 0x18, 0x00, 0x66, 0x00, 0x06, 0x00, 0x02, 0x00, + 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x89, 0x0e, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x33, 0x00, 0x5b, 0x00, 0xaf, 0x01, 0x36, 0x01, 0xfc, 0x02, 0x9b, 0x02, 0xb6, 0x02, 0xde, 0x03, + 0x10, 0x03, 0x3d, 0x03, 0x65, 0x03, 0x88, 0x03, 0xa4, 0x03, 0xc7, 0x03, 0xe2, 0x04, 0x2a, 0x04, 0x53, 0x04, 0x98, + 0x04, 0xfc, 0x05, 0x3b, 0x05, 0x91, 0x05, 0xfc, 0x06, 0x1f, 0x06, 0x88, 0x06, 0xf6, 0x07, 0x33, 0x07, 0x6d, 0x07, + 0x83, 0x07, 0xae, 0x07, 0xc4, 0x08, 0x20, 0x08, 0xd7, 0x09, 0x0f, 0x09, 0x65, 0x09, 0xae, 0x09, 0xe6, 0x0a, 0x15, + 0x0a, 0x3f, 0x0a, 0x92, 0x0a, 0xbf, 0x0a, 0xea, 0x0b, 0x1c, 0x0b, 0x4a, 0x0b, 0x69, 0x0b, 0xa8, 0x0b, 0xde, 0x0c, + 0x24, 0x0c, 0x5f, 0x0c, 0xad, 0x0c, 0xf0, 0x0d, 0x46, 0x0d, 0x69, 0x0d, 0xa4, 0x0d, 0xd1, 0x0e, 0x20, 0x0e, 0x4e, + 0x0e, 0x76, 0x0e, 0xa0, 0x0e, 0xc4, 0x0e, 0xde, 0x0f, 0x02, 0x0f, 0x29, 0x0f, 0x49, 0x0f, 0x75, 0x0f, 0xec, 0x10, + 0x6a, 0x10, 0xb4, 0x11, 0x31, 0x11, 0x8a, 0x12, 0x14, 0x12, 0xac, 0x12, 0xf0, 0x13, 0x25, 0x13, 0x72, 0x13, 0xa5, + 0x13, 0xbf, 0x14, 0x2a, 0x14, 0x78, 0x14, 0xbd, 0x15, 0x2f, 0x15, 0xa9, 0x15, 0xfe, 0x16, 0x53, 0x16, 0xb2, 0x17, + 0x0b, 0x17, 0x38, 0x17, 0x87, 0x17, 0xb3, 0x17, 0xf9, 0x18, 0x22, 0x18, 0x80, 0x18, 0xa5, 0x18, 0xfd, 0x19, 0x42, + 0x19, 0x84, 0x19, 0xea, 0x1a, 0x15, 0x1a, 0x30, 0x1a, 0x86, 0x1a, 0xd9, 0x1a, 0xfe, 0x1b, 0x63, 0x1b, 0xa7, 0x1c, + 0x0c, 0x1c, 0x6e, 0x1c, 0xb0, 0x1d, 0x72, 0x1e, 0xa5, 0x1f, 0xab, 0x1f, 0xb7, 0x1f, 0xc3, 0x20, 0x27, 0x20, 0x33, + 0x20, 0x3f, 0x20, 0x4b, 0x20, 0x57, 0x20, 0x66, 0x20, 0x75, 0x20, 0x84, 0x20, 0x93, 0x20, 0xa2, 0x20, 0xb1, 0x20, + 0xc0, 0x20, 0xcf, 0x20, 0xde, 0x20, 0xed, 0x20, 0xfc, 0x21, 0x0b, 0x21, 0x1a, 0x21, 0x29, 0x21, 0x38, 0x21, 0x47, + 0x21, 0x56, 0x21, 0x65, 0x21, 0x74, 0x21, 0x83, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, 0xbc, + 0xcf, 0x60, 0xc2, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xcc, 0xa2, + 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc4, 0x58, 0xfd, 0x5c, 0xfe, 0x7b, 0x0a, 0xdc, 0x04, 0x26, 0x00, 0x03, 0x00, + 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x58, 0x00, 0x5f, 0x01, 0x04, 0x00, 0x00, 0x01, 0x1f, + 0x00, 0x0b, 0x01, 0xc5, 0x00, 0x62, 0x02, 0x86, 0x00, 0x14, 0x02, 0x27, 0x00, 0x19, 0x03, 0x58, 0x00, 0x38, 0x02, + 0xc4, 0x00, 0x21, 0x00, 0xff, 0x00, 0x62, 0x01, 0x53, 0x00, 0x24, 0x01, 0x55, 0xff, 0xba, 0x02, 0x22, 0x00, 0x55, + 0x02, 0x3c, 0x00, 0x35, 0x01, 0x1f, 0xff, 0xd0, 0x01, 0x43, 0x00, 0x11, 0x01, 0x1f, 0x00, 0x08, 0x01, 0xa8, 0xff, + 0xd3, 0x02, 0x27, 0x00, 0x20, 0x02, 0x27, 0x00, 0x59, 0x02, 0x27, 0xff, 0xe8, 0x02, 0x27, 0x00, 0x07, 0x02, 0x27, + 0xff, 0xf4, 0x02, 0x27, 0x00, 0x0d, 0x02, 0x27, 0x00, 0x2b, 0x02, 0x27, 0x00, 0x26, 0x02, 0x27, 0x00, 0x1b, 0x02, + 0x27, 0x00, 0x2a, 0x01, 0x1f, 0x00, 0x08, 0x01, 0x1f, 0xff, 0xca, 0x02, 0x3c, 0x00, 0x35, 0x02, 0x3c, 0x00, 0x35, + 0x02, 0x3c, 0x00, 0x35, 0x01, 0xcb, 0x00, 0x4d, 0x03, 0x58, 0x00, 0x2d, 0x02, 0x74, 0xff, 0xc4, 0x02, 0x6c, 0x00, + 0x1a, 0x02, 0x65, 0x00, 0x3b, 0x02, 0xa5, 0x00, 0x1a, 0x02, 0x1f, 0x00, 0x1a, 0x02, 0x15, 0x00, 0x1a, 0x02, 0xb2, + 0x00, 0x3b, 0x02, 0xbd, 0x00, 0x1a, 0x01, 0x7f, 0xff, 0xe3, 0x01, 0x4e, 0xff, 0x62, 0x02, 0x65, 0x00, 0x1a, 0x02, + 0x06, 0x00, 0x1a, 0x03, 0x70, 0x00, 0x1a, 0x02, 0xf6, 0x00, 0x19, 0x02, 0xdb, 0x00, 0x3b, 0x02, 0x62, 0x00, 0x1a, + 0x02, 0xdb, 0x00, 0x3b, 0x02, 0x6c, 0x00, 0x1a, 0x02, 0x12, 0x00, 0x14, 0x02, 0x14, 0x00, 0x51, 0x02, 0xb4, 0x00, + 0x44, 0x02, 0x4e, 0x00, 0x5a, 0x03, 0x7e, 0x00, 0x5a, 0x02, 0x62, 0xff, 0xc7, 0x02, 0x34, 0x00, 0x5b, 0x02, 0x18, + 0xff, 0xe2, 0x01, 0x4b, 0xff, 0xee, 0x01, 0xa8, 0x00, 0x6c, 0x01, 0x4b, 0xff, 0xbd, 0x02, 0x27, 0x00, 0x11, 0x01, + 0x90, 0xff, 0xa5, 0x01, 0x44, 0x00, 0x91, 0x02, 0x50, 0x00, 0x2c, 0x02, 0x53, 0x00, 0x12, 0x01, 0xe4, 0x00, 0x2c, + 0x02, 0x52, 0x00, 0x2c, 0x02, 0x2d, 0x00, 0x2c, 0x01, 0x76, 0xff, 0x96, 0x02, 0x54, 0x00, 0x12, 0x02, 0x5c, 0x00, + 0x12, 0x01, 0x2b, 0x00, 0x12, 0x01, 0x2b, 0xff, 0x80, 0x02, 0x38, 0x00, 0x12, 0x01, 0x2b, 0x00, 0x11, 0x03, 0x89, + 0x00, 0x12, 0x02, 0x5c, 0x00, 0x12, 0x02, 0x49, 0x00, 0x2c, 0x02, 0x53, 0xff, 0xdf, 0x02, 0x52, 0x00, 0x2c, 0x01, + 0xa6, 0x00, 0x12, 0x01, 0xdb, 0x00, 0x0b, 0x01, 0x9a, 0x00, 0x2e, 0x02, 0x5c, 0x00, 0x36, 0x02, 0x00, 0x00, 0x32, + 0x03, 0x14, 0x00, 0x3d, 0x02, 0x16, 0xff, 0xce, 0x02, 0x07, 0xff, 0xbb, 0x01, 0xd5, 0xff, 0xee, 0x01, 0x63, 0xff, + 0xff, 0x02, 0x27, 0x00, 0xde, 0x01, 0x63, 0xff, 0xcd, 0x02, 0x3c, 0x00, 0x35, 0x01, 0x7b, 0x00, 0x38, 0x01, 0x7b, + 0x00, 0x48, 0x01, 0x7b, 0x00, 0x5b, 0x00, 0x7d, 0xfe, 0xfb, 0x01, 0x7b, 0x00, 0x32, 0x01, 0x7b, 0x00, 0x49, 0x01, + 0x7b, 0x00, 0x62, 0x01, 0x7b, 0x00, 0x4c, 0x01, 0x7b, 0x00, 0x5d, 0x01, 0x7b, 0x00, 0x5b, 0x01, 0x7b, 0x00, 0x5b, + 0x01, 0x76, 0x00, 0x2a, 0x02, 0xc9, 0xff, 0x95, 0x03, 0xe8, 0xff, 0x95, 0x03, 0xe8, 0xff, 0x95, 0x02, 0x9e, 0xff, + 0x96, 0x02, 0x9e, 0xff, 0x96, 0x02, 0xc9, 0x00, 0x29, 0x03, 0xf2, 0x00, 0x29, 0x03, 0xf2, 0x00, 0x29, 0x02, 0x9e, + 0x00, 0x2a, 0x02, 0x9e, 0x00, 0x2a, 0x01, 0x7b, 0x00, 0x03, 0x00, 0x0e, 0xff, 0xe2, 0xff, 0xf8, 0xff, 0xe1, 0xff, + 0xfb, 0x00, 0x04, 0x00, 0x0b, 0xff, 0xf6, 0x00, 0x03, 0x00, 0x3f, 0x00, 0x47, 0x00, 0x1b, 0x00, 0x2f, 0x00, 0x1c, + 0x00, 0x37, 0x00, 0x44, 0x00, 0x4d, 0x00, 0x33, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x2d, 0xfe, + 0xdb, 0x00, 0x00, 0x0a, 0xf0, 0xfd, 0x5c, 0xfd, 0x9b, 0x0a, 0xdc, 0x03, 0xe8, 0x00, 0xd5, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, 0x02, 0x50, 0x02, 0xbc, 0x00, 0x05, 0x00, + 0x00, 0x02, 0x8a, 0x02, 0x58, 0xff, 0xf0, 0x00, 0x4b, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x4a, 0x01, 0x5e, 0x00, 0x32, + 0x01, 0x48, 0x00, 0x00, 0x02, 0x0b, 0x08, 0x02, 0x04, 0x05, 0x04, 0x09, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x01, 0xa1, 0x00, 0x20, + 0x00, 0x7e, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x22, 0x02, 0xca, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, + 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, + 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, 0x21, + 0xb0, 0x00, 0x59, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, + 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, 0x02, 0x2c, 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, + 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, 0x14, 0x43, 0x42, 0xb1, + 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, + 0x04, 0x50, 0x78, 0xb2, 0x02, 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, + 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, 0x20, 0xb0, 0x02, 0x43, 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, + 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, 0x2c, 0xb0, + 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, + 0x65, 0x59, 0x1b, 0x20, 0x64, 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, + 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, + 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, 0x38, + 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, + 0x0d, 0x43, 0x45, 0x63, 0x45, 0x20, 0xb0, 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, + 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, 0x20, 0xb0, 0x20, 0x50, 0x58, + 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, + 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, + 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, 0xb0, 0x1e, 0x50, 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, + 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, 0x59, 0x59, 0x23, + 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, + 0x20, 0x45, 0x20, 0xb0, 0x04, 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, + 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, 0x59, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, + 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, 0xb1, + 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, + 0xb0, 0x08, 0x43, 0x20, 0x8a, 0x20, 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, + 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, + 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, 0x43, + 0x2b, 0xb2, 0x00, 0x02, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, + 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, + 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, + 0x0e, 0x00, 0x43, 0x45, 0x42, 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, + 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, + 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0x20, + 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, + 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, + 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, + 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, + 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, + 0x00, 0x23, 0x42, 0xb3, 0x0d, 0x0c, 0x00, 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, + 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, 0x2c, 0xb0, 0x01, 0x60, 0x20, + 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, + 0xb0, 0x00, 0x52, 0x58, 0x20, 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, + 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, 0x00, 0x63, 0x8a, 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, + 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x24, 0xb0, + 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, + 0x1b, 0x21, 0x59, 0x24, 0xb0, 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, + 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, 0x61, 0x42, 0xb0, 0x11, 0x2b, 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, + 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, 0x50, + 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, + 0x21, 0x23, 0xb0, 0x01, 0x61, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, + 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, + 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, + 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, + 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, 0x00, 0x13, 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, + 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, 0x23, 0x42, + 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, + 0x00, 0x11, 0x00, 0x13, 0x00, 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, + 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, + 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, 0x2c, 0xb1, + 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, + 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, + 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, + 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x5d, + 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, + 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, + 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, + 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, + 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, + 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, + 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, 0x2c, 0xb1, 0x01, + 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, + 0xb0, 0x25, 0x2c, 0xb1, 0x04, 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, + 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, 0x28, 0x2c, 0xb1, 0x07, 0x20, 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, + 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, 0x2d, + 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, + 0xb0, 0x01, 0x60, 0xb0, 0x2e, 0x2a, 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, + 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, 0x20, + 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, + 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, + 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, + 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, + 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, + 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x34, 0x2c, 0x20, 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, + 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, + 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, + 0x3c, 0x2d, 0xb0, 0x38, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0xb0, 0x01, + 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, + 0x42, 0xb0, 0x02, 0x25, 0x49, 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, + 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, 0x01, 0x15, 0x14, 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, + 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, + 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, + 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, + 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, + 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, 0x0a, + 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, + 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, + 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, + 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, 0x02, 0x25, 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, + 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, + 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, + 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, + 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, 0x60, 0x64, 0x23, 0xb0, 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, + 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, 0xb0, 0x00, + 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, + 0x3c, 0x38, 0x2d, 0xb0, 0x3d, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, + 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, + 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, 0x2e, + 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, + 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, + 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0x63, 0xb8, 0x04, 0x00, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, + 0x20, 0x3c, 0x8a, 0x38, 0x23, 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, + 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, + 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, + 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, + 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, + 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, + 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, + 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, + 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, + 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, 0x20, + 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, + 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, + 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x26, 0x20, 0x20, 0x20, + 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, + 0x20, 0x3c, 0x20, 0x2e, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, + 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, + 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, + 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, + 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, + 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, + 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, + 0x61, 0x38, 0x23, 0x20, 0x3c, 0x23, 0x38, 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, + 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, 0x3a, 0x2b, 0x2e, 0xb1, 0x30, + 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, + 0x42, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, + 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, + 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, + 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, + 0xb0, 0x4c, 0x2c, 0xb0, 0x39, 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, + 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, + 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, 0x2b, + 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, + 0xb0, 0x53, 0x2c, 0xb2, 0x00, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, + 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, + 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, + 0x59, 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, + 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, + 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x43, + 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, + 0x2d, 0xb0, 0x61, 0x2c, 0xb2, 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, + 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, + 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x67, + 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, + 0x69, 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, + 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, + 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x44, + 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, + 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, + 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x73, 0x2c, 0xb1, 0x01, + 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, + 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, + 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x77, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, + 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x42, + 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, + 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, + 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, + 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, 0x00, + 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, + 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, + 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, + 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, + 0x87, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, + 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, + 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, 0xb0, 0x06, 0x1b, 0xb2, + 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, + 0x50, 0x78, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, + 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, + 0x93, 0x83, 0x73, 0x00, 0x5d, 0x00, 0x49, 0x39, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x14, 0x88, + 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, 0x02, 0x56, 0x06, 0x4e, 0x04, 0x3e, 0x08, 0x32, 0x06, 0x24, 0x07, 0x09, 0x0a, + 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x52, 0x02, + 0x46, 0x06, 0x38, 0x04, 0x2b, 0x05, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, + 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, 0x13, 0xc0, 0x0f, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, + 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, + 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, + 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, 0x28, 0x01, 0x88, 0x51, 0x58, + 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, + 0xba, 0x08, 0x80, 0x00, 0x01, 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, + 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, 0x06, 0x7a, 0x06, 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x50, 0x02, 0x40, 0x06, + 0x34, 0x04, 0x26, 0x05, 0x09, 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, 0x00, 0x44, 0xb3, + 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x73, 0x02, 0xca, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0xff, 0x10, + 0x02, 0xd6, 0xff, 0xf6, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x99, 0x00, 0x99, 0x00, 0x7d, 0x00, 0x7d, 0x02, + 0x46, 0x02, 0x46, 0x00, 0x00, 0x00, 0x00, 0x02, 0x4f, 0x02, 0x50, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x94, 0x00, 0x94, + 0x00, 0x78, 0x00, 0x78, 0x02, 0xca, 0xff, 0xf6, 0x02, 0xf8, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, + 0xf6, 0x02, 0xfd, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x99, 0x00, 0x99, 0x00, 0x7d, 0x00, 0x7d, 0x02, 0x46, + 0x00, 0x00, 0x02, 0x50, 0xff, 0xf8, 0x00, 0x78, 0x00, 0x78, 0x00, 0x65, 0x00, 0x65, 0x01, 0x68, 0x00, 0xee, 0xff, + 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x78, 0x00, 0x78, 0x00, 0x65, 0x00, 0x65, + 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x94, 0x00, 0x94, 0x00, 0x78, 0x00, 0x78, 0x02, 0xca, 0x00, 0x00, 0x02, 0xf8, 0x02, + 0x22, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xf9, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x60, + 0x00, 0x60, 0x00, 0x48, 0x00, 0x48, 0x01, 0x29, 0xff, 0x7d, 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, + 0x33, 0xff, 0x73, 0x01, 0x69, 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x60, 0x00, 0x60, 0x00, 0x48, 0x00, 0x48, + 0x02, 0xcb, 0x01, 0x9f, 0x02, 0xe7, 0x02, 0x67, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe8, 0x01, 0x95, 0x02, 0xe8, 0x02, + 0x6d, 0x01, 0x19, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, + 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, + 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x16, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x3c, + 0x00, 0xde, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x2a, 0x01, 0x1a, 0x00, 0x03, 0x00, 0x01, 0x04, + 0x09, 0x00, 0x05, 0x00, 0x54, 0x01, 0x44, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x26, 0x01, 0x98, + 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, + 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, + 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, + 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, + 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, 0x00, 0x3a, 0x00, + 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, + 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, + 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, + 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, 0x00, + 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, + 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, + 0x20, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, + 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, + 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6f, + 0x00, 0x6c, 0x00, 0x64, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x4e, 0x00, + 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x42, + 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x20, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, + 0x63, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, + 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, + 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, + 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, + 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, + 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x49, 0x00, + 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x03, 0x00, 0x00, 0xff, 0xf4, 0x00, 0x00, 0xff, 0x9c, + 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x22, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x42, 0x00, 0x5b, 0x00, + 0x01, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x02, 0x00, 0x18, 0x00, 0x0a, 0x00, 0x22, + 0x00, 0x32, 0x00, 0x40, 0x00, 0x4e, 0x00, 0x4e, 0x00, 0x2a, 0x00, 0x32, 0x00, 0x40, 0x00, 0x4e, 0x00, 0x4e, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x21, 0x00, 0x01, + 0x00, 0x04, 0x00, 0x01, 0x01, 0x15, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x1f, 0x00, 0x01, 0x02, + 0x73, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x25, 0x00, 0x01, 0x02, 0x7d, 0x00, 0x01, 0x00, 0x04, + 0x00, 0x01, 0x01, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, 0x44, + 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, + 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, + 0x65, 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x06, 0xc8, + 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x01, 0x08, 0x00, 0x01, 0x00, 0x38, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x6a, 0x00, 0xf4, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x8c, 0x00, 0xb4, 0x00, 0x92, 0x00, 0x98, 0x00, 0xb4, + 0x00, 0xaa, 0x00, 0xb4, 0x00, 0xba, 0x00, 0xc4, 0x00, 0xc4, 0x00, 0xce, 0x00, 0xd8, 0x00, 0xf4, 0x00, 0xde, 0x00, + 0xe4, 0x00, 0xee, 0x00, 0xee, 0x00, 0xee, 0x00, 0xf4, 0x00, 0x01, 0x00, 0x17, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, + 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, + 0x37, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, 0x00, 0x5a, + 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, 0x37, 0xff, 0xd8, 0x00, 0x38, 0xff, 0xd8, 0x00, 0x3a, 0xff, + 0xc4, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x4b, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xec, 0x00, 0x0f, 0xff, 0xec, 0x00, 0x01, + 0x00, 0x07, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x04, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, + 0xc4, 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x39, 0xff, 0xec, + 0x00, 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, + 0x07, 0xff, 0xf6, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, + 0x00, 0x07, 0xff, 0xec, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, 0x00, + 0x14, 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, + 0x03, 0xd8, 0x00, 0x04, 0x00, 0x00, 0x04, 0x26, 0x04, 0xe4, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, + 0xff, 0xf6, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, + 0xd8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, 0xff, + 0xe2, 0xff, 0xce, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xc4, + 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, + 0x00, 0x00, 0xff, 0xd8, 0xff, 0xec, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf6, + 0xff, 0xec, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xce, 0xff, + 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0xff, + 0xe2, 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xce, 0x00, 0x00, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x0a, 0xff, 0xc4, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, + 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0xff, 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x8e, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x25, 0x00, 0x03, + 0x00, 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x2c, 0x00, + 0x2d, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, + 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x4c, 0x00, 0x50, 0x00, 0x51, 0x00, + 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x1f, + 0x00, 0x03, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x09, 0x00, 0x13, 0x00, + 0x0d, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x22, + 0x00, 0x22, 0x00, 0x01, 0x00, 0x24, 0x00, 0x24, 0x00, 0x07, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x2c, 0x00, + 0x2c, 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x08, 0x00, 0x30, 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, + 0x00, 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, + 0x05, 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x39, 0x00, 0x39, 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x06, + 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0d, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x02, 0x00, + 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x10, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, + 0x00, 0x55, 0x00, 0x0c, 0x00, 0x57, 0x00, 0x58, 0x00, 0x04, 0x00, 0x59, 0x00, 0x59, 0x00, 0x10, 0x00, 0x5a, 0x00, + 0x5a, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x15, 0x00, 0x02, 0x00, 0x23, + 0x00, 0x03, 0x00, 0x03, 0x00, 0x11, 0x00, 0x08, 0x00, 0x08, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x13, 0x00, + 0x0d, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0c, 0x00, 0x1b, + 0x00, 0x1c, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x05, 0x00, 0x24, 0x00, 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x02, 0x00, 0x30, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x32, 0x00, 0x02, 0x00, 0x35, 0x00, 0x35, + 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x3a, 0x00, 0x3a, 0x00, + 0x08, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x04, + 0x00, 0x44, 0x00, 0x46, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x48, 0x00, 0x48, 0x00, 0x0d, 0x00, + 0x4e, 0x00, 0x4f, 0x00, 0x03, 0x00, 0x50, 0x00, 0x50, 0x00, 0x01, 0x00, 0x51, 0x00, 0x51, 0x00, 0x03, 0x00, 0x52, + 0x00, 0x52, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x03, 0x00, 0x54, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x55, 0x00, + 0x55, 0x00, 0x0e, 0x00, 0x56, 0x00, 0x56, 0x00, 0x03, 0x00, 0x57, 0x00, 0x58, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x5a, + 0x00, 0x07, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x5e, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, + 0x15, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, + 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x50, 0x00, 0x92, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, + 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x01, 0x45, 0x57, 0x45, 0x20, 0x00, 0x18, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x05, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x20, 0x66, 0x72, 0x61, 0x63, 0x00, 0x26, 0x6c, 0x69, 0x67, 0x61, + 0x00, 0x30, 0x6c, 0x6f, 0x63, 0x6c, 0x00, 0x36, 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x3c, 0x00, + 0x4a, 0x00, 0x5e, 0x00, 0x76, 0x00, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, + 0x00, 0x12, 0x00, 0x06, 0x00, 0x6b, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x47, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, + 0x00, 0x06, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, + 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x01, 0x00, 0x76, 0x00, 0x7f, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x80, 0x00, 0x89, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x66, 0x00, 0x02, + 0x00, 0x0a, 0x00, 0x38, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6e, 0x00, + 0x03, 0x00, 0x47, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x4a, + 0x00, 0x70, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x47, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, + 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x73, 0x00, 0x03, 0x00, 0x6b, 0x00, 0x4d, 0x00, 0x72, 0x00, 0x03, 0x00, 0x6b, + 0x00, 0x4a, 0x00, 0x74, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x71, 0x00, 0x02, 0x00, + 0x6b, 0x00, 0x01, 0x00, 0x02, 0x00, 0x47, 0x00, 0x6b}; + + constexpr Info FONTS[COUNT] = {{.data = REGULAR_DATA, .length = std::size(REGULAR_DATA)}, + {.data = ITALICS_DATA, .length = std::size(ITALICS_DATA)}, + {.data = BOLD_DATA, .length = std::size(BOLD_DATA)}, + {.data = BOLD_ITALICS_DATA, .length = std::size(BOLD_ITALICS_DATA)}}; + + class Font + { + ImFont* pointer{}; + + public: + Font(); + Font(void* data, size_t length, int size); + ~Font(); + ImFont* get(); + Font& operator=(Font&& other) noexcept; + }; +}; \ No newline at end of file diff --git a/src/frame_properties.cpp b/src/frame_properties.cpp new file mode 100644 index 0000000..4b57cbf --- /dev/null +++ b/src/frame_properties.cpp @@ -0,0 +1,124 @@ +#include "frame_properties.h" + +#include + +#include + +#include "imgui.h" +#include "math.h" +#include "types.h" + +using namespace anm2ed::settings; +using namespace anm2ed::document_manager; +using namespace anm2ed::math; +using namespace anm2ed::types; +using namespace glm; + +namespace anm2ed::frame_properties +{ + + void FrameProperties::update(DocumentManager& manager, Settings& settings) + { + if (ImGui::Begin("Frame Properties", &settings.windowIsFrameProperties)) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& reference = document.reference; + auto& type = reference.itemType; + auto& isRound = settings.propertiesIsRound; + auto frame = document.frame_get(); + + ImGui::BeginDisabled(!frame); + { + if (type == anm2::TRIGGER) + { + std::vector eventNames{}; + for (auto& event : anm2.content.events | std::views::values) + eventNames.emplace_back(event.name); + + imgui::combo_strings("Event", frame ? &frame->eventID : &dummy_value(), eventNames); + ImGui::SetItemTooltip("%s", "Change the event this trigger uses."); + ImGui::InputInt("At Frame", frame ? &frame->atFrame : &dummy_value(), step::NORMAL, step::FAST, + !frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); + ImGui::SetItemTooltip("%s", "Change the frame the trigger will be activated at."); + } + else + { + + ImGui::BeginDisabled(type == anm2::ROOT || type == anm2::NULL_); + { + if (ImGui::InputFloat2("Crop", frame ? value_ptr(frame->crop) : &dummy_value(), + frame ? vec2_format_get(frame->crop) : "")) + if (isRound) frame->crop = ivec2(frame->crop); + ImGui::SetItemTooltip("%s", "Change the crop position the frame uses."); + + if (ImGui::InputFloat2("Size", frame ? value_ptr(frame->size) : &dummy_value(), + frame ? vec2_format_get(frame->size) : "")) + if (isRound) frame->crop = ivec2(frame->size); + ImGui::SetItemTooltip("%s", "Change the size of the crop the frame uses."); + } + ImGui::EndDisabled(); + + if (ImGui::InputFloat2("Position", frame ? value_ptr(frame->position) : &dummy_value(), + frame ? vec2_format_get(frame->position) : "")) + if (isRound) frame->position = ivec2(frame->position); + ImGui::SetItemTooltip("%s", "Change the position of the frame."); + + ImGui::BeginDisabled(type == anm2::ROOT || type == anm2::NULL_); + { + if (ImGui::InputFloat2("Pivot", frame ? value_ptr(frame->pivot) : &dummy_value(), + frame ? vec2_format_get(frame->pivot) : "")) + if (isRound) frame->position = ivec2(frame->position); + ImGui::SetItemTooltip("%s", "Change the pivot of the frame; i.e., where it is centered."); + } + ImGui::EndDisabled(); + + if (ImGui::InputFloat2("Scale", frame ? value_ptr(frame->scale) : &dummy_value(), + frame ? vec2_format_get(frame->scale) : "")) + if (isRound) frame->position = ivec2(frame->position); + ImGui::SetItemTooltip("%s", "Change the scale of the frame, in percent."); + + if (ImGui::InputFloat("Rotation", frame ? &frame->rotation : &dummy_value(), step::NORMAL, step::FAST, + frame ? float_format_get(frame->rotation) : "")) + if (isRound) frame->rotation = (int)frame->rotation; + ImGui::SetItemTooltip("%s", "Change the rotation of the frame."); + + ImGui::InputInt("Duration", frame ? &frame->delay : &dummy_value(), step::NORMAL, step::FAST, + !frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); + ImGui::SetItemTooltip("%s", "Change how long the frame lasts."); + + ImGui::ColorEdit4("Tint", frame ? value_ptr(frame->tint) : &dummy_value()); + ImGui::SetItemTooltip("%s", "Change the tint of the frame."); + ImGui::ColorEdit3("Color Offset", frame ? value_ptr(frame->offset) : &dummy_value()); + ImGui::SetItemTooltip("%s", "Change the color added onto the frame."); + + ImGui::Checkbox("Visible", frame ? &frame->isVisible : &dummy_value()); + ImGui::SetItemTooltip("%s", "Toggle the frame's visibility."); + ImGui::SameLine(); + ImGui::Checkbox("Interpolated", frame ? &frame->isInterpolated : &dummy_value()); + ImGui::SetItemTooltip( + "%s", "Toggle the frame interpolating; i.e., blending its values into the next frame based on the time."); + + ImGui::SameLine(); + ImGui::Checkbox("Round", &settings.propertiesIsRound); + ImGui::SetItemTooltip( + "%s", "When toggled, decimal values will be snapped to their nearest whole value when changed."); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + if (ImGui::Button("Flip X", widgetSize)) + if (frame) frame->scale.x = -frame->scale.x; + ImGui::SetItemTooltip("%s", "Flip the horizontal scale of the frame, to cheat mirroring the frame " + "horizontally.\n(Note: the format does not support mirroring.)"); + ImGui::SameLine(); + if (ImGui::Button("Flip Y", widgetSize)) + if (frame) frame->scale.y = -frame->scale.y; + ImGui::SetItemTooltip("%s", "Flip the vertical scale of the frame, to cheat mirroring the frame " + "vertically.\n(Note: the format does not support mirroring.)"); + } + } + ImGui::EndDisabled(); + } + ImGui::End(); + } +} \ No newline at end of file diff --git a/src/frame_properties.h b/src/frame_properties.h new file mode 100644 index 0000000..27ea5ee --- /dev/null +++ b/src/frame_properties.h @@ -0,0 +1,13 @@ +#pragma once + +#include "document_manager.h" +#include "settings.h" + +namespace anm2ed::frame_properties +{ + class FrameProperties + { + public: + void update(document_manager::DocumentManager& manager, settings::Settings& settings); + }; +} \ No newline at end of file diff --git a/src/generate_preview.cpp b/src/generate_preview.cpp deleted file mode 100644 index 0d2ffe7..0000000 --- a/src/generate_preview.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "generate_preview.h" - -void generate_preview_init(GeneratePreview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings) { - self->anm2 = anm2; - self->reference = reference; - self->resources = resources; - self->settings = settings; - - canvas_init(&self->canvas, GENERATE_PREVIEW_SIZE); -} - -void generate_preview_draw(GeneratePreview* self) { - static auto& columns = self->settings->generateColumns; - static auto& count = self->settings->generateCount; - static GLuint& shaderTexture = self->resources->shaders[SHADER_TEXTURE]; - const mat4 transform = canvas_transform_get(&self->canvas, {}, CANVAS_ZOOM_DEFAULT, ORIGIN_CENTER); - - vec2 startPosition = {self->settings->generateStartPosition.x, self->settings->generateStartPosition.y}; - vec2 size = {self->settings->generateSize.x, self->settings->generateSize.y}; - vec2 pivot = {self->settings->generatePivot.x, self->settings->generatePivot.y}; - - canvas_bind(&self->canvas); - canvas_viewport_set(&self->canvas); - canvas_clear(self->settings->previewBackgroundColor); - - Anm2Item* item = anm2_item_from_reference(self->anm2, *self->reference); - - if (item) { - if (Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->anm2->layers[self->reference->itemID].spritesheetID)) { - Texture& texture = spritesheet->texture; - - const int index = std::clamp((int)(self->time * count), 0, count); - const int row = index / columns; - const int column = index % columns; - vec2 crop = startPosition + vec2(size.x * column, size.y * row); - - vec2 textureSize = vec2(texture.size); - vec2 uvMin = (crop + vec2(0.5f)) / textureSize; - vec2 uvMax = (crop + size - vec2(0.5f)) / textureSize; - float vertices[] = UV_VERTICES(uvMin, uvMax); - - mat4 generateTransform = transform * quad_model_get(size, {}, pivot); - canvas_texture_draw(&self->canvas, shaderTexture, texture.id, generateTransform, vertices, COLOR_OPAQUE, COLOR_OFFSET_NONE); - } - } - - canvas_unbind(); -} - -void generate_preview_free(GeneratePreview* self) { canvas_free(&self->canvas); } \ No newline at end of file diff --git a/src/generate_preview.h b/src/generate_preview.h deleted file mode 100644 index 6539991..0000000 --- a/src/generate_preview.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "anm2.h" -#include "canvas.h" -#include "resources.h" -#include "settings.h" - -#define GENERATE_PREVIEW_TIME_MIN 0.0f -#define GENERATE_PREVIEW_TIME_MAX 1.0f - -const vec2 GENERATE_PREVIEW_SIZE = {325, 215}; - -struct GeneratePreview { - Anm2* anm2 = nullptr; - Anm2Reference* reference = nullptr; - Resources* resources = nullptr; - Settings* settings = nullptr; - Canvas canvas; - float time{}; -}; - -void generate_preview_init(GeneratePreview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings); -void generate_preview_draw(GeneratePreview* self); -void generate_preview_free(GeneratePreview* self); \ No newline at end of file diff --git a/src/icon.h b/src/icon.h new file mode 100644 index 0000000..737a2c3 --- /dev/null +++ b/src/icon.h @@ -0,0 +1,200 @@ +#pragma once +#include +#include + +namespace icon +{ + constexpr auto SIZE_SMALL = glm::ivec2(64, 64); + constexpr auto SIZE_NORMAL = glm::ivec2(128, 128); + constexpr auto SIZE_LARGE = glm::ivec2(256, 256); + constexpr auto SIZE_HUGE = glm::ivec2(512, 512); + + constexpr auto NONE_DATA = R"( + + )"; + + constexpr auto FILE_DATA = R"( + + )"; + + constexpr auto FOLDER_DATA = R"( + + )"; + + constexpr auto CLOSE_DATA = R"( + + )"; + + constexpr auto ROOT_DATA = R"( + + )"; + + constexpr auto LAYER_DATA = R"( + + )"; + + constexpr auto NULL_DATA = R"( + + )"; + + constexpr auto TRIGGERS_DATA = R"( + + )"; + + constexpr auto VISIBLE_DATA = R"( + + )"; + + constexpr auto INVISIBLE_DATA = R"( + + )"; + + constexpr auto SHOW_UNUSED_DATA = R"( + +)"; + + constexpr auto HIDE_UNUSED_DATA = R"( + +)"; + + constexpr auto SHOW_RECT_DATA = R"( + + )"; + + constexpr auto HIDE_RECT_DATA = R"( + + )"; + + constexpr auto ANIMATION_DATA = R"( + + )"; + + constexpr auto SPRITESHEET_DATA = R"( + + )"; + + constexpr auto EVENT_DATA = R"( + + )"; + + constexpr auto PAN_DATA = R"( + + )"; + + constexpr auto MOVE_DATA = R"( + + )"; + + constexpr auto ROTATE_DATA = R"( + + )"; + + constexpr auto SCALE_DATA = R"( + + )"; + + constexpr auto CROP_DATA = R"( + + )"; + + constexpr auto DRAW_DATA = R"( + + )"; + + constexpr auto ERASE_DATA = R"( + + )"; + + constexpr auto COLOR_PICKER_DATA = R"( + + )"; + + constexpr auto UNDO_DATA = R"( + + )"; + + constexpr auto REDO_DATA = R"( + + )"; + + constexpr auto TARGET_DATA = R"( + + )"; + + constexpr auto INTERPOLATED_DATA = R"( + + )"; + + constexpr auto UNINTERPOLATED_DATA = R"( + + )"; + + constexpr auto PIVOT_DATA = R"( + + )"; + + constexpr auto TRIGGER_DATA = R"( + + )"; + + constexpr auto PLAYHEAD_DATA = R"( + + )"; + +#define LIST \ + X(NONE, NONE_DATA, SIZE_NORMAL) \ + X(FILE, FILE_DATA, SIZE_NORMAL) \ + X(FOLDER, FOLDER_DATA, SIZE_NORMAL) \ + X(CLOSE, CLOSE_DATA, SIZE_NORMAL) \ + X(ROOT, ROOT_DATA, SIZE_NORMAL) \ + X(LAYER, LAYER_DATA, SIZE_NORMAL) \ + X(NULL_, NULL_DATA, SIZE_NORMAL) \ + X(TRIGGERS, TRIGGERS_DATA, SIZE_NORMAL) \ + X(VISIBLE, VISIBLE_DATA, SIZE_NORMAL) \ + X(INVISIBLE, INVISIBLE_DATA, SIZE_NORMAL) \ + X(SHOW_RECT, SHOW_RECT_DATA, SIZE_NORMAL) \ + X(HIDE_RECT, HIDE_RECT_DATA, SIZE_NORMAL) \ + X(SHOW_UNUSED, SHOW_UNUSED_DATA, SIZE_NORMAL) \ + X(HIDE_UNUSED, HIDE_UNUSED_DATA, SIZE_NORMAL) \ + X(PAN, PAN_DATA, SIZE_NORMAL) \ + X(MOVE, MOVE_DATA, SIZE_NORMAL) \ + X(ROTATE, ROTATE_DATA, SIZE_NORMAL) \ + X(SCALE, SCALE_DATA, SIZE_NORMAL) \ + X(CROP, CROP_DATA, SIZE_NORMAL) \ + X(DRAW, DRAW_DATA, SIZE_NORMAL) \ + X(ERASE, ERASE_DATA, SIZE_NORMAL) \ + X(COLOR_PICKER, COLOR_PICKER_DATA, SIZE_NORMAL) \ + X(UNDO, UNDO_DATA, SIZE_NORMAL) \ + X(REDO, REDO_DATA, SIZE_NORMAL) \ + X(ANIMATION, ANIMATION_DATA, SIZE_NORMAL) \ + X(SPRITESHEET, SPRITESHEET_DATA, SIZE_NORMAL) \ + X(EVENT, EVENT_DATA, SIZE_NORMAL) \ + X(INTERPOLATED, INTERPOLATED_DATA, SIZE_NORMAL) \ + X(UNINTERPOLATED, UNINTERPOLATED_DATA, SIZE_NORMAL) \ + X(TRIGGER, TRIGGER_DATA, SIZE_NORMAL) \ + X(PLAYHEAD, PLAYHEAD_DATA, SIZE_NORMAL) \ + X(PIVOT, PIVOT_DATA, SIZE_NORMAL) \ + X(POINT, UNINTERPOLATED_DATA, SIZE_NORMAL) \ + X(TARGET, TARGET_DATA, SIZE_HUGE) + + enum Type + { +#define X(name, data, size) name, + LIST +#undef X + COUNT + }; + + struct Info + { + const char* data{}; + size_t length{}; + glm::ivec2 size{}; + }; + + const Info ICONS[COUNT] = { +#define X(name, data, size) {data, std::strlen(data) - 1, size}, + LIST +#undef X + }; +} \ No newline at end of file diff --git a/src/imgui.cpp b/src/imgui.cpp index ae2ab3d..3b6d13d 100644 --- a/src/imgui.cpp +++ b/src/imgui.cpp @@ -1,3096 +1,235 @@ #include "imgui.h" -#include "COMMON.h" -#include "anm2.h" -static void _imgui_anm2_open(Imgui* self, const std::string& path) { - imgui_anm2_new(self); +#include - if (anm2_deserialize(self->anm2, path)) { - window_title_from_path_set(self->window, path); - imgui_log_push(self, std::format(IMGUI_LOG_FILE_OPEN_FORMAT, path)); - } else - imgui_log_push(self, std::format(IMGUI_LOG_FILE_OPEN_FORMAT, path)); -} +#include +#include +#include -static void _imgui_spritesheet_add(Imgui* self, const std::string& path) { - imgui_snapshot(self, IMGUI_ACTION_ADD_SPRITESHEET); - WorkingDirectory workingDirectory(self->anm2->path); - std::string spritesheetPath = path; - std::string anm2WorkingPath = working_directory_from_file_set(self->anm2->path); - spritesheetPath = std::filesystem::relative(path, anm2WorkingPath).string(); - Texture texture; - if (texture_from_path_init(&texture, spritesheetPath)) { - int id = map_next_id_get(self->anm2->spritesheets); - self->anm2->spritesheets[id] = Anm2Spritesheet{}; - self->anm2->spritesheets[id].path = spritesheetPath; - self->anm2->spritesheets[id].texture = texture; - imgui_log_push(self, std::format(IMGUI_LOG_ADD_SPRITESHEET, id, path)); - } else - imgui_log_push(self, std::format(IMGUI_LOG_ADD_SPRITESHEET_ERROR, path)); -} +namespace anm2ed::imgui +{ + std::string chord_to_string(ImGuiKeyChord chord) + { + std::string result; -static bool _imgui_is_window_hovered(void) { return ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } -static bool _imgui_is_window_hovered_and_click(void) { return _imgui_is_window_hovered() && ImGui::IsMouseClicked(0); } -static bool _imgui_is_no_click_on_item(void) { return ImGui::IsMouseClicked(0) && !ImGui::IsItemHovered(); } + if (chord & ImGuiMod_Ctrl) result += "Ctrl+"; + if (chord & ImGuiMod_Shift) result += "Shift+"; + if (chord & ImGuiMod_Alt) result += "Alt+"; + if (chord & ImGuiMod_Super) result += "Super+"; -static bool _imgui_is_input_begin(void) { - return ImGui::IsItemHovered() && (ImGui::IsKeyPressed(IMGUI_INPUT_RENAME) || ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)); -} - -static bool _imgui_is_input_default(void) { - return ImGui::IsItemHovered() && (ImGui::IsKeyPressed(IMGUI_INPUT_DEFAULT) || ImGui::IsMouseClicked(IMGUI_MOUSE_DEFAULT)); -} - -static bool _imgui_chord_pressed(ImGuiKeyChord chord) { - if (chord == IMGUI_CHORD_NONE) - return false; - ImGuiKey key = (ImGuiKey)(chord & ~ImGuiMod_Mask_); - if (key == ImGuiKey_None) - return false; - if (key < ImGuiKey_NamedKey_BEGIN || key >= ImGuiKey_NamedKey_END) - return false; - - return ImGui::IsKeyChordPressed(chord); -} - -static bool _imgui_is_focus_window(const std::string& focus) { - ImGuiContext* context = ImGui::GetCurrentContext(); - if (!context) - return false; - - ImGuiWindow* window = context->NavWindow; - if (!window || !window->Name) - return false; - - std::string_view name(window->Name); - return name.find(focus) != std::string_view::npos; -} - -static vec2 _imgui_item_spacing_get(const ImguiItem& self) { return self.itemSpacing.has_value() ? *self.itemSpacing : vec2(ImGui::GetStyle().ItemSpacing); } -static vec2 _imgui_window_padding_get(const ImguiItem& self) { - return self.windowPadding.has_value() ? *self.windowPadding : vec2(ImGui::GetStyle().WindowPadding); -} -static vec2 _imgui_frame_padding_get(const ImguiItem& self) { - return self.framePadding.has_value() ? *self.framePadding : vec2(ImGui::GetStyle().WindowPadding); -} - -static vec2 _imgui_cursor_position_get(const ImguiItem& self) { return self.cursorPosition.has_value() ? *self.cursorPosition : vec2(ImGui::GetCursorPos()); } - -static vec2 _imgui_item_size_get(const ImguiItem& self, ImguiItemType type) { - vec2 size{}; - - if (!self.size.has_value()) { - switch (type) { - case IMGUI_ATLAS_BUTTON: - size = self.size.has_value() ? *self.size : vec2(ATLAS_SIZE(self.atlas)); - break; - default: - if (self.rowCount.has_value()) - size.x = (ImGui::GetWindowSize().x - (_imgui_item_spacing_get(self).x * (*self.rowCount + 1))) / *self.rowCount; - else if (self.isWidthToText) - size.x = (ImGui::CalcTextSize(self.label_get().c_str()).x + ImGui::GetStyle().FramePadding.x); - else if (self.isWidthToRegion) - size.x = ImGui::GetContentRegionAvail().x; + if (auto key = (ImGuiKey)(chord & ~ImGuiMod_Mask_); key != ImGuiKey_None) + { + if (const char* name = ImGui::GetKeyName(key); name && *name) + result += name; else - size.x = ImGui::CalcItemWidth(); - - if (self.isHeightToRegion) - size.y = ImGui::GetContentRegionAvail().y; - else if (type != IMGUI_BUTTON) - size.y = ImGui::GetTextLineHeight() + ImGui::GetStyle().FramePadding.y; - break; + result += "Unknown"; } - } else - size = *self.size; - size *= self.scale; + if (!result.empty() && result.back() == '+') result.pop_back(); - return size; -} - -static void _imgui_item_style_push(const ImguiItem& self) { - if (self.windowPadding.has_value()) - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, *self.windowPadding); - if (self.itemSpacing.has_value()) - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, *self.itemSpacing); - if (self.font.has_value()) - ImGui::PushFont(*self.font, FONT_SIZE); -} - -static void _imgui_item_style_pop(const ImguiItem& self) { - if (self.windowPadding.has_value()) - ImGui::PopStyleVar(); - if (self.itemSpacing.has_value()) - ImGui::PopStyleVar(); - if (self.font.has_value()) - ImGui::PopFont(); -} - -static const char* _imgui_float_format_get(const ImguiItem& item, float& value) { - if (item.isEmptyFormat) - return ""; - return float_format_get(value); -} - -static const char* _imgui_vec2_format_get(const ImguiItem& item, vec2& value) { - if (item.isEmptyFormat) - return ""; - return vec2_format_get(value); -} - -static void _imgui_item_pre(const ImguiItem& self, ImguiItemType type) { - switch (type) { - case IMGUI_ITEM: - case IMGUI_TEXT: - case IMGUI_BEGIN_WINDOW: - case IMGUI_END_WINDOW: - case IMGUI_DOCKSPACE: - case IMGUI_BEGIN_CHILD: - case IMGUI_END_CHILD: - case IMGUI_CONFIRM_POPUP: - case IMGUI_TABLE: - break; - default: - ImGui::BeginDisabled(self.isDisabled); - break; + return result; } - switch (type) { - case IMGUI_SELECTABLE: - case IMGUI_INPUT_INT: - case IMGUI_INPUT_TEXT: - case IMGUI_INPUT_FLOAT: - case IMGUI_DRAG_FLOAT: - case IMGUI_SLIDER_FLOAT: - case IMGUI_COLOR_EDIT: - ImGui::SetNextItemWidth(_imgui_item_size_get(self, type).x); - break; - default: - break; - } + ImGuiKeyChord string_to_chord(const std::string& string) + { + ImGuiKeyChord chord = 0; + ImGuiKey baseKey = ImGuiKey_None; - switch (type) { - case IMGUI_BUTTON: - case IMGUI_ATLAS_BUTTON: - if (self.border.has_value()) { - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, *self.border); - if (self.color.border.has_value()) - ImGui::PushStyleColor(ImGuiCol_Border, *self.color.border); + std::stringstream ss(string); + std::string token; + while (std::getline(ss, token, '+')) + { + token.erase(0, token.find_first_not_of(" \t\r\n")); + token.erase(token.find_last_not_of(" \t\r\n") + 1); + + if (token.empty()) continue; + + if (auto it = MOD_MAP.find(token); it != MOD_MAP.end()) + chord |= it->second; + else if (baseKey == ImGuiKey_None) + if (auto it2 = KEY_MAP.find(token); it2 != KEY_MAP.end()) baseKey = it2->second; } - break; - default: - break; + + if (baseKey != ImGuiKey_None) chord |= baseKey; + + return chord; } - switch (type) { - case IMGUI_BEGIN_CHILD: - if (self.color.normal.has_value()) - ImGui::PushStyleColor(ImGuiCol_ChildBg, *self.color.normal); - break; - case IMGUI_SELECTABLE: - if (self.isSelected && self.color.normal.has_value()) - ImGui::PushStyleColor(ImGuiCol_Header, *self.color.normal); - break; - case IMGUI_BUTTON: - case IMGUI_ATLAS_BUTTON: - if (self.color.normal.has_value()) - ImGui::PushStyleColor(ImGuiCol_Button, *self.color.normal); - if (self.color.active.has_value()) - ImGui::PushStyleColor(ImGuiCol_ButtonActive, *self.color.active); - if (self.color.hovered.has_value()) - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, *self.color.hovered); - if (self.isSelected) { - if (self.color.active.has_value()) - ImGui::PushStyleColor(ImGuiCol_Button, *self.color.active); - else - ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]); + float row_widget_width_get(int count, float width) + { + return (width - (ImGui::GetStyle().ItemSpacing.x * (float)(count - 1))) / (float)count; + } + + ImVec2 widget_size_with_row_get(int count, float width) + { + return ImVec2(row_widget_width_get(count, width), 0); + } + + float footer_height_get(int itemCount) + { + return ImGui::GetTextLineHeightWithSpacing() * itemCount + ImGui::GetStyle().WindowPadding.y + + ImGui::GetStyle().ItemSpacing.y * (itemCount); + } + + ImVec2 size_with_footer_get(int rowCount) + { + return ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - footer_height_get(rowCount)); + } + + ImVec2 child_size_get(int rowCount, bool isContentRegionAvail) + { + return ImVec2(isContentRegionAvail ? ImGui::GetContentRegionAvail().x : 0, + (ImGui::GetFrameHeightWithSpacing() * rowCount) + (ImGui::GetStyle().WindowPadding.y * 2.0f)); + } + + int input_text_callback(ImGuiInputTextCallbackData* data) + { + if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) + { + auto* string = (std::string*)(data->UserData); + string->resize(data->BufTextLen); + data->Buf = string->data(); } - break; - default: - break; + return 0; } - switch (type) { - case IMGUI_END_WINDOW: - _imgui_item_style_pop(self); - break; - case IMGUI_END_CHILD: - break; - default: - _imgui_item_style_push(self); - break; + bool input_text_string(const char* label, std::string* string, ImGuiInputTextFlags flags) + { + flags |= ImGuiInputTextFlags_CallbackResize; + return ImGui::InputText(label, string->data(), string->capacity() + 1, flags, input_text_callback, string); } - switch (type) { - case IMGUI_BEGIN_WINDOW: - case IMGUI_END_WINDOW: - case IMGUI_BEGIN_CHILD: - case IMGUI_END_CHILD: - break; - default: - ImGui::SetCursorPos(self.cursorPosition.value_or(vec2(ImGui::GetCursorPos())) + self.cursorOffset); - break; + void combo_strings(const std::string& label, int* index, std::vector& strings) + { + std::vector items{}; + for (auto& string : strings) + items.push_back(string.c_str()); + ImGui::Combo(label.c_str(), index, items.data(), (int)items.size()); } - switch (type) { - case IMGUI_BEGIN_WINDOW: - if (self.position.has_value()) - ImGui::SetNextWindowPos(*self.position); - if (self.size.has_value()) - ImGui::SetNextWindowSize(*self.size); - break; - default: - break; - } -} + bool selectable_input_text(const std::string& label, const std::string& id, std::string& text, bool isSelected, + ImGuiSelectableFlags flags) + { + static std::string editID{}; + static bool isJustEdit{}; + const bool isEditing = editID == id; + bool isActivated{}; -static void _imgui_item_post(const ImguiItem& self, Imgui* imgui, ImguiItemType type, bool& isActivated) { + if (isEditing) + { + if (isJustEdit) + { + ImGui::SetKeyboardFocusHere(); + isJustEdit = false; + } - if (self.is_mnemonic() && !self.isMnemonicDisabled) { - ImVec2 position = ImGui::GetItemRectMin(); - ImFont* font = ImGui::GetFont(); - float fontSize = ImGui::GetFontSize(); - const char* start = self.label.c_str(); - const char* charPointer = start + self.mnemonicIndex; - - position.x += ImGui::GetStyle().FramePadding.x; - - float offset = font->CalcTextSizeA(fontSize, FLT_MAX, 0.0f, start, charPointer).x; - float charWidth = font->CalcTextSizeA(fontSize, FLT_MAX, 0.0f, charPointer, charPointer + 1).x; - - ImVec2 lineStart = ImVec2(position.x + offset, position.y + fontSize + 1.0f); - ImVec2 lineEnd = ImVec2(lineStart.x + charWidth, lineStart.y); - - ImU32 color = ImGui::GetColorU32(ImGuiCol_Text); - ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, color, 1.0f); - - if (_imgui_chord_pressed(ImGuiMod_Alt | self.mnemonicKey)) { - if (!self.isDisabled) + ImGui::SetNextItemWidth(-FLT_MIN); + if (input_text_string("##Edit", &text, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) + { + editID.clear(); isActivated = true; - imgui_close_current_popup(imgui); + } + if (ImGui::IsItemDeactivatedAfterEdit() || ImGui::IsKeyPressed(ImGuiKey_Escape)) editID.clear(); } - } + else + { + if (ImGui::Selectable(label.c_str(), isSelected, flags)) isActivated = true; - if (self.isUseItemActivated && !self.isDisabled) - isActivated = ImGui::IsItemActivated(); - - if (imgui->isContextualActionsEnabled && _imgui_chord_pressed(self.chord_get()) && - (self.focusWindow.has_value() && _imgui_is_focus_window(*self.focusWindow))) - if (!self.isDisabled) - isActivated = true; - - if (!self.tooltip.empty() && ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) { - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, imgui->style.WindowPadding); - ImGui::SetTooltip("%s", self.tooltip_get().c_str()); - ImGui::PopStyleVar(); - } - - if (isActivated) { - if (self.snapshotAction.has_value()) - imgui_snapshot(imgui, *self.snapshotAction); - if (self.function) - self.function(imgui); - - if (!self.popup.empty()) { - imgui->pendingPopup = self.popup; - imgui->pendingPopupType = self.popupType; - imgui->pendingPopupPosition = ImVec2(ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y + ImGui::GetItemRectSize().y); + if ((ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGuiKey_F2) && isSelected) || + (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))) + { + editID = id; + isJustEdit = true; + } } + + return isActivated; } - switch (type) { - case IMGUI_END_CHILD: - if (self.color.normal.has_value()) - ImGui::PopStyleColor(); - break; - case IMGUI_SELECTABLE: - if (self.isSelected && self.color.normal.has_value()) - ImGui::PopStyleColor(); - break; - case IMGUI_BUTTON: - case IMGUI_ATLAS_BUTTON: - if (self.color.normal.has_value()) - ImGui::PopStyleColor(); - if (self.color.active.has_value()) - ImGui::PopStyleColor(); - if (self.color.hovered.has_value()) - ImGui::PopStyleColor(); - if (self.isSelected) - ImGui::PopStyleColor(); - break; - default: - break; + void set_item_tooltip_shortcut(const std::string& tooltip, const std::string& shortcut) + { + auto text = shortcut.empty() ? tooltip : std::format("{}\n(Shortcut: {})", tooltip, shortcut); + ImGui::SetItemTooltip("%s", text.c_str()); } - switch (type) { - case IMGUI_BUTTON: - case IMGUI_ATLAS_BUTTON: - if (self.border.has_value()) { - ImGui::PopStyleVar(); - if (self.color.border.has_value()) - ImGui::PopStyleColor(); + void external_storage_set(ImGuiSelectionExternalStorage* self, int id, bool isSelected) + { + auto* set = (std::set*)self->UserData; + if (isSelected) + set->insert(id); + else + set->erase(id); + }; + + ImVec2 icon_size_get() + { + return ImVec2(ImGui::GetTextLineHeightWithSpacing(), ImGui::GetTextLineHeightWithSpacing()); + } + + bool chord_held(ImGuiKeyChord chord) + { + auto& io = ImGui::GetIO(); + + for (constexpr ImGuiKey mods[] = {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiMod_Alt, ImGuiMod_Super}; ImGuiKey mod : mods) + { + bool required = (chord & mod) != 0; + if (bool held = io.KeyMods & mod; required && !held) return false; } - default: - break; + + auto main_key = (ImGuiKey)(chord & ~ImGuiMod_Mask_); + if (main_key == ImGuiKey_None) return false; + + return ImGui::IsKeyDown(main_key); } - switch (type) { - case IMGUI_ITEM: - case IMGUI_TEXT: - case IMGUI_BEGIN_WINDOW: - case IMGUI_END_WINDOW: - case IMGUI_DOCKSPACE: - case IMGUI_BEGIN_CHILD: - case IMGUI_END_CHILD: - case IMGUI_CONFIRM_POPUP: - case IMGUI_TABLE: - break; - default: - ImGui::EndDisabled(); - } + bool chord_repeating(ImGuiKeyChord chord, float delay, float rate) + { + struct State + { + float timeHeld = 0.f; + float nextRepeat = 0.f; + }; + static std::unordered_map stateMap; - if (self.isSameLine) - ImGui::SameLine(); - if (self.isSeparator) - ImGui::Separator(); + auto& io = ImGui::GetIO(); + auto& state = stateMap[chord]; - switch (type) { - case IMGUI_BEGIN_CHILD: - break; - case IMGUI_BEGIN_WINDOW: - _imgui_item_style_push(self); - break; - default: - _imgui_item_style_pop(self); - break; - } -} + if (chord_held(chord)) + { + state.timeHeld += io.DeltaTime; -#define IMGUI_ITEM_BASE(NAME, TYPE, BODY) \ - static bool NAME(const ImguiItem& self, Imgui* imgui) { \ - ImguiItemType type = TYPE; \ - _imgui_item_pre(self, type); \ - bool isActivated = false; \ - do { \ - BODY \ - } while (0); \ - _imgui_item_post(self, imgui, type, isActivated); \ - return isActivated; \ - } + if (state.timeHeld <= io.DeltaTime) + { + state.nextRepeat = delay; + return true; + } -#define IMGUI_ITEM_VALUE_BASE(NAME, TYPE, VALUE_TYPE, BODY) \ - static bool NAME(const ImguiItem& self, Imgui* imgui, VALUE_TYPE& inValue) { \ - ImguiItemType type = TYPE; \ - _imgui_item_pre(self, type); \ - bool isActivated = false; \ - do { \ - VALUE_TYPE value = inValue; \ - BODY {} \ - inValue = value; \ - } while (0); \ - _imgui_item_post(self, imgui, type, isActivated); \ - return isActivated; \ - } - -#define IMGUI_ITEM_VOID_FUNCTION(NAME, TYPE, BODY) IMGUI_ITEM_BASE(NAME, TYPE, { ([&] { BODY; })(); }) -#define IMGUI_ITEM_BOOL_FUNCTION(NAME, TYPE, BODY) IMGUI_ITEM_BASE(NAME, TYPE, { isActivated = ([&] { return BODY; })(); }) -#define IMGUI_ITEM_VALUE_FUNCTION(NAME, TYPE, VALUE_TYPE, BODY) IMGUI_ITEM_VALUE_BASE(NAME, TYPE, VALUE_TYPE, { isActivated = ([&] { return BODY; })(); }) - -#define IMGUI_ITEM_VALUE_CLAMP_FUNCTION(NAME, TYPE, VALUE_TYPE, BODY) \ - IMGUI_ITEM_VALUE_BASE(NAME, TYPE, VALUE_TYPE, { \ - isActivated = ([&] { return BODY; })(); \ - if (self.is_range()) \ - value = glm::clamp(value, VALUE_TYPE(*self.min), VALUE_TYPE(*self.max)); \ - }) - -#define IMGUI_ITEM_STRING_FUNCTION(NAME, TYPE, BODY) \ - static bool NAME(const ImguiItem& self, Imgui* imgui, std::string& inValue) { \ - ImguiItemType type = TYPE; \ - _imgui_item_pre(self, type); \ - bool isActivated = false; \ - do { \ - std::string value = inValue; \ - isActivated = ([&] { return BODY; })(); \ - /* no VALUE_TYPE(self.value) here, strings don’t come from self.value */ \ - inValue = value; \ - } while (0); \ - _imgui_item_post(self, imgui, type, isActivated); \ - return isActivated; \ - } - -#define IMGUI_ITEM_CUSTOM_FUNCTION(NAME, TYPE, BODY) IMGUI_ITEM_BASE(NAME, TYPE, BODY) -#define IMGUI_ITEM_CUSTOM_VALUE_FUNCTION(NAME, TYPE, VALUE_TYPE, BODY) IMGUI_ITEM_VALUE_BASE(NAME, TYPE, VALUE_TYPE, {BODY}) - -IMGUI_ITEM_VOID_FUNCTION(_imgui_dockspace, IMGUI_DOCKSPACE, ImGui::DockSpace(ImGui::GetID(self.label_get().c_str()), *self.size, self.flags)); -IMGUI_ITEM_VOID_FUNCTION(_imgui_begin_child, IMGUI_BEGIN_CHILD, ImGui::BeginChild(self.label_get().c_str(), *self.size, self.flags, self.windowFlags)); -IMGUI_ITEM_VOID_FUNCTION(_imgui_end_child, IMGUI_END_CHILD, ImGui::EndChild()); -IMGUI_ITEM_VOID_FUNCTION(_imgui_text, IMGUI_TEXT, ImGui::Text("%s", self.label_get().c_str())); -IMGUI_ITEM_BOOL_FUNCTION(_imgui_button, IMGUI_BUTTON, ImGui::Button(self.label_get().c_str(), _imgui_item_size_get(self, type))); -IMGUI_ITEM_BOOL_FUNCTION(_imgui_begin_table, IMGUI_TABLE, ImGui::BeginTable(self.label_get().c_str(), self.value, self.flags)); -IMGUI_ITEM_BOOL_FUNCTION(_imgui_selectable, IMGUI_SELECTABLE, - ImGui::Selectable(self.label_get().c_str(), self.isSelected, self.flags, _imgui_item_size_get(self, type))); -IMGUI_ITEM_VOID_FUNCTION(_imgui_image, IMGUI_IMAGE, ImGui::Image(self.textureID, _imgui_item_size_get(self, IMGUI_IMAGE), self.uvMin, self.uvMax)); - -IMGUI_ITEM_VALUE_CLAMP_FUNCTION(_imgui_input_int, IMGUI_INPUT_INT, int, - ImGui::InputInt(self.label_get().c_str(), &value, self.step, self.stepFast, self.flags)); -IMGUI_ITEM_VALUE_CLAMP_FUNCTION(_imgui_input_int2, IMGUI_INPUT_INT, ivec2, ImGui::InputInt2(self.label_get().c_str(), value_ptr(value), self.flags)); -IMGUI_ITEM_VALUE_CLAMP_FUNCTION(_imgui_input_float, IMGUI_INPUT_FLOAT, float, - ImGui::InputFloat(self.label_get().c_str(), &value, self.step, self.stepFast, _imgui_float_format_get(self, value), - self.flags)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_checkbox, IMGUI_CHECKBOX, bool, ImGui::Checkbox(self.label_get().c_str(), &value)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_slider_float, IMGUI_SLIDER_FLOAT, float, - ImGui::SliderFloat(self.label_get().c_str(), &value, *self.min, *self.max, _imgui_float_format_get(self, value), self.flags)); - -IMGUI_ITEM_STRING_FUNCTION(_imgui_input_text, IMGUI_INPUT_TEXT, - (value.resize(*self.max), ImGui::InputText(self.label_get().c_str(), value.data(), *self.max, self.flags))); - -IMGUI_ITEM_BOOL_FUNCTION(_imgui_begin, IMGUI_BEGIN_WINDOW, ImGui::Begin(self.label_get().c_str(), nullptr, self.flags)); -IMGUI_ITEM_VOID_FUNCTION(_imgui_end, IMGUI_END_WINDOW, ImGui::End()); - -IMGUI_ITEM_VALUE_FUNCTION(_imgui_radio_button, IMGUI_RADIO_BUTTON, int, ImGui::RadioButton(self.label_get().c_str(), &value, self.value)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_button, IMGUI_COLOR_BUTTON, vec4, ImGui::ColorButton(self.label_get().c_str(), ImVec4(value), self.flags)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_drag_float, IMGUI_DRAG_FLOAT, float, - ImGui::DragFloat(self.label_get().c_str(), &value, self.speed, *self.min, *self.max, _imgui_float_format_get(self, value))); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_drag_float2, IMGUI_DRAG_FLOAT, vec2, - ImGui::DragFloat2(self.label_get().c_str(), value_ptr(value), self.speed, *self.min, *self.max, _imgui_vec2_format_get(self, value))); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_edit3, IMGUI_COLOR_EDIT, vec3, ImGui::ColorEdit3(self.label_get().c_str(), value_ptr(value), self.flags)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_edit4, IMGUI_COLOR_EDIT, vec4, ImGui::ColorEdit4(self.label_get().c_str(), value_ptr(value), self.flags)); - -/* -IMGUI_ITEM_CHECKBOX_FUNCTION(_imgui_checkbox_selectable, _imgui_selectable(self, imgui)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_checkbox, bool, _imgui_checkbox(self, imgui, value)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_input_int, int, _imgui_input_int(self, imgui, value)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_drag_float, float, _imgui_drag_float(self, imgui, value)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_drag_float2, vec2, _imgui_drag_float2(self, imgui, value)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_color_edit3, vec3, _imgui_color_edit3(self, imgui, value)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_color_edit4, vec4, _imgui_color_edit4(self, imgui, value)); -*/ - -IMGUI_ITEM_CUSTOM_VALUE_FUNCTION(_imgui_combo, IMGUI_COMBO, int, { - std::vector cStrings; - cStrings.reserve(self.items.size()); - for (auto& [id, string] : self.items) - cStrings.emplace_back(string.c_str()); - - isActivated = ImGui::Combo(self.label_get().c_str(), &value, cStrings.data(), (int)self.items.size()); -}); - -IMGUI_ITEM_CUSTOM_VALUE_FUNCTION(_imgui_selectable_input_text, IMGUI_SELECTABLE, std::string, { - static std::string buffer{}; - static int id = ID_NONE; - ImguiItem selectable = self; - ImVec2 size = _imgui_item_size_get(selectable, IMGUI_SELECTABLE); - - if (id == self.id) { - isActivated = _imgui_input_text(IMGUI_CHANGE_INPUT_TEXT.copy({.size = size}), imgui, buffer); - imgui_contextual_actions_disable(imgui); - - if (isActivated || _imgui_is_no_click_on_item()) { - value = buffer; - buffer.clear(); - id = ID_NONE; - imgui_contextual_actions_enable(imgui); + if (state.timeHeld >= state.nextRepeat) + { + state.nextRepeat += rate; + return true; + } } - } else { - isActivated = _imgui_selectable(selectable, imgui); - - if (_imgui_is_input_begin()) { - buffer = value; - buffer.resize(*IMGUI_CHANGE_INPUT_TEXT.max); - id = self.id; - ImGui::SetKeyboardFocusHere(-1); + else + { + state.timeHeld = 0.f; + state.nextRepeat = 0.f; } - } -}); -#define IMGUI_ATLAS_VOID_FUNCTION(NAME, FUNCTION) \ - static void NAME(const ImguiItem& self, Imgui* imgui) { \ - vec2 cursorPosition = _imgui_cursor_position_get(self); \ - _imgui_image(self.copy({.textureID = imgui->resources->atlas.id, \ - .size = ATLAS_SIZE(self.atlas) * imgui->settings->displayScale, \ - .uvMin = ATLAS_UV_MIN(self.atlas), \ - .uvMax = ATLAS_UV_MAX(self.atlas), \ - .cursorPosition = cursorPosition}), \ - imgui); \ - \ - FUNCTION(self.copy({.cursorPosition = \ - cursorPosition + vec2(ATLAS_SIZE(self.atlas).x + (((_imgui_item_spacing_get(self).x + _imgui_frame_padding_get(self).x * 0.5f) * \ - imgui->settings->displayScale)), \ - 0.0f)}), \ - imgui); \ + return false; } -#define IMGUI_ATLAS_BOOL_FUNCTION(NAME, FUNCTION) \ - static bool NAME(const ImguiItem& self, Imgui* imgui) { \ - vec2 cursorPosition = _imgui_cursor_position_get(self); \ - _imgui_image(self.copy({.textureID = imgui->resources->atlas.id, \ - .size = ATLAS_SIZE(self.atlas) * imgui->settings->displayScale, \ - .uvMin = ATLAS_UV_MIN(self.atlas), \ - .uvMax = ATLAS_UV_MAX(self.atlas), \ - .cursorPosition = cursorPosition}), \ - imgui); \ - \ - return FUNCTION(self.copy({.cursorPosition = cursorPosition + vec2(ATLAS_SIZE(self.atlas).x + \ - (((_imgui_item_spacing_get(self).x + _imgui_frame_padding_get(self).x * 0.5f) * \ - imgui->settings->displayScale)), \ - 0.0f)}), \ - imgui); \ - } + bool shortcut(std::string string, bool isSet, bool isGlobal, bool isPopupBlock) + { + if (isPopupBlock && ImGui::GetTopMostPopupModal() != nullptr) return false; + auto flags = isGlobal ? ImGuiInputFlags_RouteGlobal : ImGuiInputFlags_RouteFocused; -#define IMGUI_ATLAS_VALUE_BOOL_FUNCTION(NAME, FUNCTION, TYPE) \ - static bool NAME(const ImguiItem& self, Imgui* imgui, TYPE& value) { \ - vec2 cursorPosition = _imgui_cursor_position_get(self); \ - _imgui_image(self.copy({.textureID = imgui->resources->atlas.id, \ - .size = ATLAS_SIZE(self.atlas) * imgui->settings->displayScale, \ - .uvMin = ATLAS_UV_MIN(self.atlas), \ - .uvMax = ATLAS_UV_MAX(self.atlas), \ - .cursorPosition = cursorPosition}), \ - imgui); \ - \ - return FUNCTION(self.copy({.cursorPosition = cursorPosition + vec2(ATLAS_SIZE(self.atlas).x + \ - (((_imgui_item_spacing_get(self).x + _imgui_frame_padding_get(self).x * 0.5f) * \ - imgui->settings->displayScale)), \ - 0.0f)}), \ - imgui, value); \ - } - -IMGUI_ATLAS_VOID_FUNCTION(_imgui_atlas_text, _imgui_text); -IMGUI_ATLAS_BOOL_FUNCTION(_imgui_atlas_selectable, _imgui_selectable); -IMGUI_ATLAS_VALUE_BOOL_FUNCTION(_imgui_atlas_selectable_input_text, _imgui_selectable_input_text, std::string); - -#define IMGUI_BEGIN_OR_RETURN(item, imgui) \ - if (!_imgui_begin(item, imgui)) { \ - _imgui_end(item, imgui); \ - return; \ - } - -static void _imgui_end_table(void) { ImGui::EndTable(); } -static void _imgui_table_setup_column(const char* text) { ImGui::TableSetupColumn(text); } -static void _imgui_table_headers_row(void) { ImGui::TableHeadersRow(); } -static void _imgui_table_next_row(void) { ImGui::TableNextRow(); } -static void _imgui_table_set_column_index(int index) { ImGui::TableSetColumnIndex(index); } - -IMGUI_ITEM_CUSTOM_FUNCTION(_imgui_atlas_button, IMGUI_ATLAS_BUTTON, { - ImVec2 size = _imgui_item_size_get(self, type); - - if (self.size.has_value()) { - isActivated = ImGui::Button(self.label_get().c_str(), size); - vec2 framePadding = _imgui_frame_padding_get(self) * self.scale; - - vec2 atlasOffset = self.atlasOffset.has_value() ? *self.atlasOffset * self.scale : framePadding; - vec2 start = ImGui::GetItemRectMin() + atlasOffset; - vec2 atlasSize = self.isAtlasStretch ? *self.size - framePadding : ATLAS_SIZE(self.atlas); - vec2 end = start + atlasSize; - - ImGui::GetWindowDrawList()->AddImage(imgui->resources->atlas.id, start, end, ATLAS_UV_ARGS(self.atlas)); - } else - isActivated = ImGui::ImageButton(self.label_get().c_str(), imgui->resources->atlas.id, size, ATLAS_UV_ARGS(self.atlas)); -}); - -/* -static bool _imgui_selectable_input_int(const ImguiItem& self, Imgui* imgui, int& value) { - static int temp; - static int id = ID_NONE; - ImguiItem selectable = self.copy({.label = std::format(IMGUI_SELECTABLE_INPUT_INT_FORMAT, value)}); - ImVec2 size = _imgui_item_size_get(selectable, IMGUI_SELECTABLE); - bool isActivated = false; - - if (id == self.id) { - isActivated = _imgui_input_int(IMGUI_CHANGE_INPUT_INT.copy({.size = size}), imgui, temp); - imgui_contextual_actions_disable(imgui); - - if (isActivated || _imgui_is_no_click_on_item()) { - value = temp; - id = ID_NONE; - imgui_contextual_actions_enable(imgui); - } - } else { - isActivated = _imgui_selectable(selectable, imgui); - - if (_imgui_is_input_begin()) { - temp = value; - id = self.id; - ImGui::SetKeyboardFocusHere(-1); - } - } - - return isActivated; -}; -*/ - -static bool _imgui_confirm_popup(ImguiItem self, Imgui* imgui, ImguiPopupState* state = nullptr, bool isOnlyConfirm = false) { - ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); - - if (state) - *state = IMGUI_POPUP_STATE_CLOSED; - - if (imgui_begin_popup_modal(self.label_get().c_str(), imgui)) { - if (state) - *state = IMGUI_POPUP_STATE_OPEN; - - ImGui::Text("%s", self.text_get()); - ImGui::Separator(); - - if (_imgui_button(IMGUI_POPUP_OK.copy({.rowCount = isOnlyConfirm ? 1 : IMGUI_CONFIRM_POPUP_ROW_COUNT}), imgui)) { - imgui_close_current_popup(imgui); - imgui_end_popup(imgui); - if (state) - *state = isOnlyConfirm ? IMGUI_POPUP_STATE_CANCEL : IMGUI_POPUP_STATE_CONFIRM; + if (isSet) + { + ImGui::SetNextItemShortcut(string_to_chord(string), flags); return true; } - ImGui::SameLine(); - - if (!isOnlyConfirm) { - if (_imgui_button(IMGUI_POPUP_CANCEL, imgui)) { - imgui_close_current_popup(imgui); - if (state) - *state = IMGUI_POPUP_STATE_CANCEL; - } - } - - imgui_end_popup(imgui); - } - - return false; -} - -static void _imgui_no_anm2_path_check(Imgui* self) { - if (self->anm2->path.empty()) - imgui_open_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION.label); -} - -static void _imgui_no_anm2_path_click_check(Imgui* self) { - if (_imgui_is_window_hovered_and_click() && self->anm2->path.empty() && !imgui_is_any_popup_open()) - imgui_open_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION.label); - _imgui_confirm_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION, self, nullptr, true); -} - -static void _imgui_context_menu(Imgui* self) { - if (!self->isContextualActionsEnabled) - return; - - if (_imgui_is_window_hovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) - imgui_open_popup(IMGUI_CONTEXT_MENU.label_get()); - - if (imgui_begin_popup(IMGUI_CONTEXT_MENU.label_get(), self)) { - if (_imgui_selectable(IMGUI_CUT, self)) { - if (self->clipboard->type == CLIPBOARD_ANIMATION) - self->selectedAnimationIndices = {}; - } - _imgui_selectable(IMGUI_COPY, self); - _imgui_selectable(IMGUI_PASTE.copy({.isDisabled = !clipboard_is_value()}), self); - - imgui_end_popup(self); + return ImGui::Shortcut(string_to_chord(string), flags); } } - -/* -static void _imgui_timeline(Imgui* self) { - static const ImU32 frameColor = ImGui::GetColorU32(IMGUI_TIMELINE_FRAME_COLOR); - static const ImU32 frameMultipleColor = ImGui::GetColorU32(IMGUI_TIMELINE_FRAME_MULTIPLE_COLOR); - static const ImU32 headerFrameColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_COLOR); - static const ImU32 headerFrameMultipleColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_COLOR); - static const ImU32 headerFrameInactiveColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_INACTIVE_COLOR); - static const ImU32 headerFrameMultipleInactiveColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_INACTIVE_COLOR); - static const ImU32 textColor = ImGui::GetColorU32(ImGuiCol_Text); - static Anm2Reference hoverReference; - static Anm2Reference swapItemReference; - static Anm2Type& itemType = self->reference->itemType; - static ImVec2 itemMin{}; - static ImVec2 localMousePos{}; - static ImVec2 mousePos{}; - static ImVec2 playheadPos{}; - static ImVec2 scroll{}; - static bool isItemSwap = false; - static const ImVec2& frameSize = IMGUI_TIMELINE_FRAME_SIZE; - static float& time = self->preview->time; - static int frameTime{}; - static int& itemID = self->reference->itemID; - - IMGUI_BEGIN_OR_RETURN(IMGUI_TIMELINE); - _imgui_no_anm2_path_click_check(self); - - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); - - if (!animation) { - ImGui::Text(IMGUI_TIMELINE_ANIMATION_NONE); - _imgui_end(); // IMGUI_TIMELINE - return; - } - - int length = animation->frameNum; - int actualLength = anm2_animation_length_get(animation); - - ImVec2 actualFramesSize = {actualLength * frameSize.x, frameSize.y}; - ImVec2 framesSize = {length * frameSize.x, frameSize.y}; - - ImVec2 defaultItemSpacing = ImGui::GetStyle().ItemSpacing; - ImVec2 defaultWindowPadding = ImGui::GetStyle().WindowPadding; - ImVec2 defaultFramePadding = ImGui::GetStyle().FramePadding; - - vec2 windowSize = ImGui::GetContentRegionAvail(); - vec2 childSize = {windowSize.x, windowSize.y - IMGUI_FOOTER_CHILD.size->y}; - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); - - _imgui_begin_child(IMGUI_TIMELINE_CHILD.copy({.size = childSize}), self); - ImVec2 clipRectMin = ImGui::GetWindowDrawList()->GetClipRectMin(); - ImVec2 clipRectMax = ImGui::GetWindowDrawList()->GetClipRectMax(); - clipRectMin.x += IMGUI_TIMELINE_ITEM_SIZE.x; - - ImVec2 scrollDelta{}; - - if (_imgui_is_window_hovered() && !imgui_is_any_popup_open()) { - ImGuiIO& io = ImGui::GetIO(); - float lineHeight = ImGui::GetTextLineHeight(); - - scrollDelta.x -= io.MouseWheelH * lineHeight; - scrollDelta.y -= io.MouseWheel * lineHeight; - } - - std::function timeline_header = [&]() { - static bool isPlayheadDrag = false; - _imgui_begin_child(IMGUI_TIMELINE_HEADER_CHILD, self); - - ImGui::SetScrollX(scroll.x); - - itemMin = ImGui::GetItemRectMin(); - mousePos = ImGui::GetMousePos(); - localMousePos = ImVec2(mousePos.x - itemMin.x + scroll.x, mousePos.y - itemMin.y); - frameTime = (int)(localMousePos.x / frameSize.x); - - if (ImGui::IsMouseDown(0) && _imgui_is_window_hovered()) - isPlayheadDrag = true; - - if (isPlayheadDrag) { - if (self->settings->playbackIsClampPlayhead) - time = std::clamp(frameTime, 0, std::max(0, length - 1)); - else - time = std::max(frameTime, 0); - - if (ImGui::IsMouseReleased(0)) - isPlayheadDrag = false; - } - - ImVec2 cursorPos = ImGui::GetCursorScreenPos(); - playheadPos = {cursorPos.x + (time * frameSize.x), cursorPos.y}; - - ImDrawList* drawList = ImGui::GetWindowDrawList(); - - ImVec2 dummySize = actualFramesSize.x > framesSize.x ? actualFramesSize : framesSize; - ImGui::Dummy(dummySize); - - float viewWidth = ImGui::GetContentRegionAvail().x; - int start = (int)std::floor(scroll.x / frameSize.x) - 1; - start = (start < 0) ? 0 : start; - - int end = (int)std::ceil((scroll.x + viewWidth) / frameSize.x) + 1; - end = (end > ANM2_FRAME_NUM_MAX) ? ANM2_FRAME_NUM_MAX : end; - - playheadPos = ImVec2(cursorPos.x + time * frameSize.x, cursorPos.y); - - for (int i = start; i < end; i++) { - bool isMultiple = (i % IMGUI_TIMELINE_FRAME_MULTIPLE) == 0; - bool isInactive = i >= length; - - float startX = cursorPos.x + i * frameSize.x; - float endX = startX + frameSize.x; - ImVec2 positionStart(startX, cursorPos.y); - ImVec2 positionEnd(endX, cursorPos.y + frameSize.y); - - ImU32 bgColor = - isInactive ? (isMultiple ? headerFrameMultipleInactiveColor : headerFrameInactiveColor) : (isMultiple ? headerFrameMultipleColor : headerFrameColor); - - drawList->AddRectFilled(positionStart, positionEnd, bgColor); - - if (isMultiple) { - std::string buffer = std::to_string(i); - ImVec2 textSize = ImGui::CalcTextSize(buffer.c_str()); - ImVec2 textPosition(startX + (frameSize.x - textSize.x) * 0.5f, cursorPos.y + (frameSize.y - textSize.y) * 0.5f); - drawList->AddText(textPosition, textColor, buffer.c_str()); - } - - drawList->AddImage(self->resources->atlas.id, positionStart, positionEnd, ATLAS_UV_ARGS(ATLAS_FRAME_ALT)); - } - - _imgui_end_child(); // IMGUI_TIMELINE_HEADER_CHILD - - ImGui::SetNextWindowPos(ImGui::GetWindowPos()); - ImGui::SetNextWindowSize(ImGui::GetWindowSize()); - _imgui_begin(IMGUI_PLAYHEAD); - - ImVec2& pos = playheadPos; - - ImVec2 lineStart = {pos.x + (frameSize.x * 0.5f) - (IMGUI_PLAYHEAD_LINE_WIDTH * 0.5f), pos.y + frameSize.y}; - ImVec2 lineEnd = {lineStart.x + IMGUI_PLAYHEAD_LINE_WIDTH, lineStart.y + childSize.y - frameSize.y}; - - drawList = ImGui::GetWindowDrawList(); - - drawList->PushClipRect(clipRectMin, clipRectMax, true); - drawList->AddImage(self->resources->atlas.id, pos, ImVec2(pos.x + frameSize.x, pos.y + frameSize.y), ATLAS_UV_ARGS(ATLAS_PICKER)); - drawList->AddRectFilled(lineStart, lineEnd, IMGUI_PLAYHEAD_LINE_COLOR); - drawList->PopClipRect(); - - _imgui_end(); // IMGUI_PLAYHEAD - }; - - std::function timeline_item_child = [&](Anm2Reference reference, int& index) { - Anm2Item* item = anm2_item_from_reference(self->anm2, reference); - Anm2Type& type = reference.itemType; - if (!item) - return; - if (!self->settings->timelineIsShowUnused && item->frames.empty() && (type == ANM2_LAYER || type == ANM2_NULL)) - return; - - ImVec2 buttonSize = ImVec2(ATLAS_SIZE_NORMAL) + (defaultFramePadding * ImVec2(2, 2)); - - Anm2Layer* layer = nullptr; - Anm2Null* null = nullptr; - int buttonCount = type == ANM2_NULL ? 2 : 1; - float buttonAreaWidth = buttonCount * buttonSize.x + (buttonCount - 1) * defaultItemSpacing.x; - bool isSelected = (self->reference->itemID == reference.itemID && self->reference->itemType == type); - - ImGui::PushID(reference.itemID); - - ImVec2 childPos = ImGui::GetCursorScreenPos(); - _imgui_begin_child(*IMGUI_TIMELINE_ITEM_CHILDS[type], self); - ImVec2 childSize = ImGui::GetContentRegionAvail(); - - const ImguiItem* selectable = IMGUI_TIMELINE_ITEM_SELECTABLES[type]; - - std::string dragDrop = selectable->drag_drop_get(); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, defaultItemSpacing); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, defaultWindowPadding); - - _imgui_selectable(selectable->copy({.isSelected = isSelected}), self); - - if (imgui_begin_popup_modal(IMGUI_POPUP_ITEM_PROPERTIES, self, IMGUI_POPUP_ITEM_PROPERTIES_SIZE)) { - static int selectedLayerID = ID_NONE; - static int selectedNullID = ID_NONE; - Anm2Type& type = reference.itemType; - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, self); - - _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER.copy({.isDisabled = true}), self, (int&)type); - _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL.copy({.isDisabled = true}), self, (int&)type); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, self); - - switch (type) { - case ANM2_LAYER: - default: { - for (auto& [id, layer] : self->anm2->layers) { - if (id == reference.itemID) - continue; - - ImGui::PushID(id); - - ImguiItem layerItem = IMGUI_LAYER.copy({.label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), .isSelected = selectedLayerID = id, .id = id}); - if (_imgui_atlas_selectable(layerItem, self)) - selectedLayerID = id; - - ImGui::PopID(); - }; - break; - } - case ANM2_NULL: { - for (auto& [id, null] : self->anm2->nulls) { - if (id == reference.itemID) - continue; - - ImGui::PushID(id); - - ImguiItem nullItem = IMGUI_NULL.copy({.label = std::format(IMGUI_NULL_FORMAT, id, null.name), .isSelected = selectedNullID == id, .id = id}); - if (_imgui_atlas_selectable(nullItem, self)) - selectedNullID = id; - - ImGui::PopID(); - }; - break; - } - } - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD, self); - - if (self->anm2->layers.size() == 0) - selectedLayerID = ID_NONE; - if (self->anm2->nulls.size() == 0) - selectedNullID = ID_NONE; - - bool isDisabled = type == ANM2_NONE || (type == ANM2_LAYER && selectedLayerID == ID_NONE) || (type == ANM2_NULL && selectedNullID == ID_NONE); - - if (_imgui_button(IMGUI_TIMELINE_ITEM_PROPERTIES_CONFIRM.copy({.isDisabled = isDisabled}), self)) { - switch (type) { - case ANM2_LAYER: - if (!map_find(animation->layerAnimations, selectedLayerID)) { - anm2_animation_layer_animation_add(animation, selectedLayerID); - anm2_animation_layer_animation_remove(animation, reference.itemID); - } else - map_swap(animation->layerAnimations, selectedLayerID, reference.itemID); - - *self->reference = {self->reference->animationID, ANM2_LAYER, selectedLayerID}; - selectedLayerID = ID_NONE; - break; - case ANM2_NULL: - if (!map_find(animation->nullAnimations, selectedNullID)) { - anm2_animation_null_animation_add(animation, selectedNullID); - anm2_animation_null_animation_remove(animation, reference.itemID); - - } else - map_swap(animation->nullAnimations, selectedNullID, reference.itemID); - - *self->reference = {self->reference->animationID, ANM2_NULL, selectedNullID}; - selectedNullID = ID_NONE; - break; - default: - break; - } - - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) - imgui_close_current_popup(self); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD - - imgui_end_popup(self); - } - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None) && !dragDrop.empty()) { - *self->reference = reference; - - ImGui::SetDragDropPayload(dragDrop.c_str(), &reference, sizeof(Anm2Reference)); - timeline_item_child(reference, index); - ImGui::EndDragDropSource(); - } - ImGui::PopStyleVar(); - - if (ImGui::BeginDragDropTarget()) { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(dragDrop.c_str())) { - Anm2Reference checkReference = *(Anm2Reference*)payload->Data; - if (checkReference != reference) { - swapItemReference = reference; - isItemSwap = true; - } - } - - ImGui::EndDragDropTarget(); - } - - ImGui::SetCursorScreenPos({childPos.x + childSize.x - buttonAreaWidth, childPos.y + defaultWindowPadding.y}); - - if (type == ANM2_NULL && null) { - const ImguiItem& rectItem = null->isShowRect ? IMGUI_TIMELINE_ITEM_SHOW_RECT : IMGUI_TIMELINE_ITEM_HIDE_RECT; - if (_imgui_atlas_button(rectItem, self)) - null->isShowRect = !null->isShowRect; - ImGui::SameLine(0.0f, defaultItemSpacing.x); - } - - const ImguiItem& visibleItem = item->isVisible ? IMGUI_TIMELINE_ITEM_VISIBLE : IMGUI_TIMELINE_ITEM_INVISIBLE; - if (_imgui_atlas_button(visibleItem, self)) - item->isVisible = !item->isVisible; - - ImGui::PopStyleVar(2); - - _imgui_end_child(); // itemChild - - ImGui::PopID(); - - index++; - }; - - std::function timeline_items_child = [&]() { - static int& animationID = self->reference->animationID; - int index = 0; - - _imgui_begin_child(IMGUI_TIMELINE_ITEMS_CHILD, self); - ImGui::SetScrollY(scroll.y); - - timeline_item_child({animationID, ANM2_ROOT}, index); - - for (auto& id : std::ranges::reverse_view(animation->layerOrder)) - timeline_item_child({animationID, ANM2_LAYER, id}, index); - - for (auto& [id, null] : animation->nullAnimations) - timeline_item_child({animationID, ANM2_NULL, id}, index); - - timeline_item_child({animationID, ANM2_TRIGGER}, index); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEMS_CHILD - - if (isItemSwap) { - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); - - imgui_snapshot(self, IMGUI_ACTION_ITEM_SWAP); - - switch (swapItemReference.itemType) { - case ANM2_LAYER: - vector_value_swap(animation->layerOrder, self->reference->itemID, swapItemReference.itemID); - break; - case ANM2_NULL: - map_swap(animation->nullAnimations, self->reference->itemID, swapItemReference.itemID); - break; - default: - break; - } - - self->reference->itemID = swapItemReference.itemID; - swapItemReference = Anm2Reference(); - isItemSwap = false; - } - }; - - std::function timeline_item_frames = [&](Anm2Reference reference, int& index) { - Anm2Item* item = anm2_item_from_reference(self->anm2, reference); - if (!item) - return; - Anm2Type& type = reference.itemType; - if (!self->settings->timelineIsShowUnused && item->frames.empty() && (type == ANM2_LAYER || type == ANM2_NULL)) - return; - - ImGui::PushID(index); - - ImDrawList* drawList = ImGui::GetWindowDrawList(); - - float viewWidth = ImGui::GetContentRegionAvail().x; - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_FRAMES_CHILD.copy({.size = actualFramesSize.x > framesSize.x ? actualFramesSize : framesSize}), self); - - ImVec2 startPos = ImGui::GetCursorPos(); - ImVec2 cursorPos = ImGui::GetCursorScreenPos(); - - if (_imgui_is_window_hovered()) { - hoverReference = reference; - hoverReference.frameIndex = anm2_frame_index_from_time(self->anm2, reference, frameTime); - self->clipboard->destination = hoverReference; - self->clipboard->type = CLIPBOARD_FRAME; - - if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) { - *self->reference = reference; - if (reference.itemType == ANM2_LAYER && reference.itemID != ID_NONE) - self->editor->spritesheetID = self->anm2->layers[self->reference->itemID].spritesheetID; - } - } - - int start = (int)std::floor(scroll.x / frameSize.x) - 1; - if (start < 0) - start = 0; - - int end = (int)std::ceil((scroll.x + viewWidth) / frameSize.x) + 1; - if (end > ANM2_FRAME_NUM_MAX) - end = ANM2_FRAME_NUM_MAX; - - for (int i = start; i < end; i++) { - bool isMultiple = (i % IMGUI_TIMELINE_FRAME_MULTIPLE) == 0; - ImU32 bgColor = isMultiple ? frameMultipleColor : frameColor; - - float startX = cursorPos.x + i * frameSize.x; - float endX = startX + frameSize.x; - ImVec2 startPosition(startX, cursorPos.y); - ImVec2 endPosition(endX, cursorPos.y + frameSize.y); - - drawList->AddRectFilled(startPosition, endPosition, bgColor); - drawList->AddImage(self->resources->atlas.id, startPosition, endPosition, ATLAS_UV_ARGS(ATLAS_FRAME)); - } - - ImGui::SetCursorPos(startPos); - - std::function timeline_item_frame = [&](int i, Anm2Frame& frame) { - static int frameDelayStart{}; - static float frameDelayTimeStart{}; - const bool isModCtrl = ImGui::IsKeyDown(IMGUI_INPUT_CTRL); - const bool isModAlt = ImGui::IsKeyDown(IMGUI_INPUT_ALT); - static bool isDrag = false; - - ImGui::PushID(i); - reference.frameIndex = i; - ImVec2 framePos = ImGui::GetCursorPos(); - AtlasType atlas = frame.isInterpolated ? ATLAS_CIRCLE : ATLAS_SQUARE; - - if (type == ANM2_TRIGGER) { - framePos.x = startPos.x + (frameSize.x * frame.atFrame); - atlas = ATLAS_TRIGGER; - } - - ImguiItem frameButton = IMGUI_TIMELINE_FRAMES[type]->copy( - {.atlas = atlas, .size = vec2(frameSize.x * frame.delay, frameSize.y), .isSelected = reference == *self->reference, .id = i}); - - ImGui::SetCursorPos(framePos); - - if (_imgui_atlas_button(frameButton, self)) { - if (isModAlt) - frame.isInterpolated = !frame.isInterpolated; - else { - *self->reference = reference; - frameDelayStart = frame.delay; - frameDelayTimeStart = frameTime; - self->preview->time = frameTime; - } - } - - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoPreviewTooltip)) { - if (!isDrag) { - *self->reference = reference; - frameDelayStart = frame.delay; - frameDelayTimeStart = frameTime; - isDrag = true; - } - - ImGui::SetDragDropPayload(frameButton.drag_drop_get(), &reference, sizeof(Anm2Reference)); - if (!isModCtrl && type != ANM2_TRIGGER) { - ImGui::BeginTooltip(); - _imgui_atlas_button(frameButton, self); - ImGui::EndTooltip(); - } - ImGui::EndDragDropSource(); - } - - if (isDrag) { - self->pendingCursor = SDL_SYSTEM_CURSOR_POINTER; - - if (Anm2Frame* referenceFrame = anm2_frame_from_reference(self->anm2, *self->reference)) { - switch (self->reference->itemType) { - case ANM2_TRIGGER: { - referenceFrame->atFrame = std::max(frameTime, 0); - for (auto& trigger : animation->triggers.frames) { - if (&trigger == referenceFrame) - continue; - if (trigger.atFrame == referenceFrame->atFrame) { - referenceFrame->atFrame++; - break; - } - } - break; - } - case ANM2_ROOT: - case ANM2_LAYER: - case ANM2_NULL: { - if (isModCtrl) - referenceFrame->delay = std::max(frameDelayStart + (int)(frameTime - frameDelayTimeStart), ANM2_FRAME_NUM_MIN); - break; - } - default: - break; - } - } - } - - if (ImGui::BeginDragDropTarget()) { - ImGui::AcceptDragDropPayload(frameButton.drag_drop_get()); - ImGui::EndDragDropTarget(); - } - - if (isDrag && ImGui::IsMouseReleased(0)) { - if (!isModCtrl && *self->reference != hoverReference && self->reference->itemType == hoverReference.itemType) { - imgui_snapshot(self, IMGUI_ACTION_FRAME_MOVE); - if (Anm2Frame* referenceFrame = anm2_frame_from_reference(self->anm2, *self->reference)) { - Anm2Reference addReference = hoverReference; - addReference.frameIndex = - hoverReference.frameIndex < self->reference->frameIndex ? std::min(0, addReference.frameIndex - 2) : std::min(0, addReference.frameIndex - 1); - Anm2Frame addFrame = *referenceFrame; - anm2_frame_remove(self->anm2, *self->reference); - anm2_frame_add(self->anm2, &addFrame, hoverReference); - *self->reference = hoverReference; - hoverReference = Anm2Reference(); - } - } - - isDrag = false; - } - - if (i < (int)item->frames.size() - 1) - ImGui::SameLine(); - - ImGui::PopID(); - }; - - for (auto [i, frame] : std::views::enumerate(item->frames)) - timeline_item_frame(i, frame); - - _imgui_end_child(); // itemFramesChild - - ImGui::PopID(); - - index++; - }; - - std::function timeline_frames_child = [&]() { - int& animationID = self->reference->animationID; - int index = 0; - - _imgui_begin_child(IMGUI_TIMELINE_FRAMES_CHILD, self); - scroll.x = ImGui::GetScrollX() + scrollDelta.x; - scroll.y = ImGui::GetScrollY() + scrollDelta.y; - ImGui::SetScrollX(scroll.x); - ImGui::SetScrollY(scroll.y); - - timeline_item_frames(Anm2Reference(animationID, ANM2_ROOT), index); - - for (auto& id : std::ranges::reverse_view(animation->layerOrder)) - timeline_item_frames(Anm2Reference(animationID, ANM2_LAYER, id), index); - - for (auto& [id, null] : animation->nullAnimations) - timeline_item_frames(Anm2Reference(animationID, ANM2_NULL, id), index); - - timeline_item_frames(Anm2Reference(animationID, ANM2_TRIGGER), index); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, defaultItemSpacing); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, defaultWindowPadding); - _imgui_context_menu(self); - ImGui::PopStyleVar(2); - - _imgui_end_child(); // IMGUI_TIMELINE_FRAMES_CHILD - }; - - // In order to set scroll properly timeline_frames_child must be called first - ImGui::SetCursorPos(ImVec2(IMGUI_TIMELINE_ITEM_SIZE)); - timeline_frames_child(); - ImGui::SetCursorPos(ImVec2()); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, defaultItemSpacing); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, defaultWindowPadding); - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_CHILD, self); - - const ImguiItem& unusedItem = self->settings->timelineIsShowUnused ? IMGUI_TIMELINE_SHOW_UNUSED : IMGUI_TIMELINE_HIDE_UNUSED; - if (_imgui_atlas_button(unusedItem, self)) - self->settings->timelineIsShowUnused = !self->settings->timelineIsShowUnused; - ImGui::PopStyleVar(2); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_CHILD - ImGui::SameLine(); - timeline_header(); - - timeline_items_child(); - - ImGui::PopStyleVar(2); - - _imgui_end_child(); // IMGUI_TIMELINE_CHILD - - Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *self->reference); - Anm2Item* item = anm2_item_from_reference(self->anm2, *self->reference); - _imgui_begin_child(IMGUI_TIMELINE_ITEM_FOOTER_CHILD, self); - - _imgui_button(IMGUI_TIMELINE_ADD_ITEM, self); - - if (imgui_begin_popup_modal(IMGUI_TIMELINE_ADD_ITEM.popup, self, IMGUI_TIMELINE_ADD_ITEM.popupSize)) { - static int selectedLayerID = ID_NONE; - static int selectedNullID = ID_NONE; - int& type = self->settings->timelineAddItemType; - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, self); - - _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER, self, type); - _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL, self, type); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, self); - - switch (type) { - case ANM2_LAYER: - default: { - for (auto& [id, layer] : self->anm2->layers) { - ImGui::PushID(id); - - ImguiItem layerItem = IMGUI_LAYER.copy({.label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), .isSelected = selectedLayerID == id, .id = id}); - if (_imgui_atlas_selectable(layerItem, self)) - selectedLayerID = id; - - ImGui::PopID(); - }; - break; - } - case ANM2_NULL: { - for (auto& [id, null] : self->anm2->nulls) { - ImGui::PushID(id); - - ImguiItem nullItem = IMGUI_NULL.copy({.label = std::format(IMGUI_NULL_FORMAT, id, null.name), .isSelected = selectedNullID == id, .id = id}); - if (_imgui_atlas_selectable(nullItem, self)) - selectedNullID = id; - - ImGui::PopID(); - }; - break; - } - } - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD, self); - - if (self->anm2->layers.size() == 0) - selectedLayerID = ID_NONE; - if (self->anm2->nulls.size() == 0) - selectedNullID = ID_NONE; - - bool isDisabled = type == ANM2_NONE || (type == ANM2_LAYER && selectedLayerID == ID_NONE) || (type == ANM2_NULL && selectedNullID == ID_NONE); - - if (_imgui_button(IMGUI_TIMELINE_ITEM_PROPERTIES_CONFIRM.copy({.isDisabled = isDisabled}), self)) { - switch (type) { - case ANM2_LAYER: - anm2_animation_layer_animation_add(animation, selectedLayerID); - *self->reference = {self->reference->animationID, ANM2_LAYER, selectedLayerID}; - selectedLayerID = ID_NONE; - break; - case ANM2_NULL: - anm2_animation_null_animation_add(animation, selectedNullID); - *self->reference = {self->reference->animationID, ANM2_NULL, selectedNullID}; - selectedNullID = ID_NONE; - break; - default: - break; - } - - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) - imgui_close_current_popup(self); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD - - imgui_end_popup(self); - } - - if (_imgui_button(IMGUI_TIMELINE_REMOVE_ITEM.copy({.isDisabled = !item || itemType == ANM2_ROOT || itemType == ANM2_TRIGGER}), self)) { - switch (itemType) { - case ANM2_LAYER: - anm2_animation_layer_animation_remove(animation, itemID); - break; - case ANM2_NULL: - anm2_animation_null_animation_remove(animation, itemID); - break; - default: - break; - } - - *self->reference = {self->reference->animationID}; - } - - _imgui_end_child(); // IMGUI_TIMELINE_FOOTER_ITEM_CHILD - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - ImGui::SameLine(); - ImGui::PopStyleVar(); - - _imgui_begin_child(IMGUI_TIMELINE_OPTIONS_FOOTER_CHILD, self); - - if (_imgui_button(self->preview->isPlaying ? IMGUI_PAUSE : IMGUI_PLAY, self)) { - if (!self->preview->isPlaying && time >= animation->frameNum - 1) - time = 0.0f; - self->preview->isPlaying = !self->preview->isPlaying; - } - - if (_imgui_button(IMGUI_INSERT_FRAME.copy({.isDisabled = !item}), self)) { - Anm2Reference frameReference = *self->reference; - Anm2Frame addFrame = Anm2Frame(); - - switch (self->reference->itemType) { - case ANM2_ROOT: - case ANM2_LAYER: - case ANM2_NULL: - frameReference.frameIndex = item->frames.empty() ? 0 : std::clamp(frameReference.frameIndex, 0, (int)(item->frames.size() - 1)); - - addFrame = *anm2_frame_from_reference(self->anm2, frameReference); - break; - case ANM2_TRIGGER: - addFrame.atFrame = (int)self->preview->time; - break; - default: - break; - } - - anm2_frame_add(self->anm2, &addFrame, frameReference); - } - - if (_imgui_button(IMGUI_REMOVE_FRAME.copy({.isDisabled = !frame}), self)) { - anm2_frame_remove(self->anm2, *self->reference); - self->reference->frameIndex = ID_NONE; - } - - _imgui_button(IMGUI_BAKE.copy({.isDisabled = !frame || itemType == ANM2_TRIGGER}), self); - - if (imgui_begin_popup_modal(IMGUI_BAKE.popup, self, IMGUI_BAKE.popupSize)) { - static int& interval = self->settings->bakeInterval; - static bool& isRoundScale = self->settings->bakeIsRoundScale; - static bool& isRoundRotation = self->settings->bakeIsRoundRotation; - - _imgui_begin_child(IMGUI_BAKE_CHILD, self); - - _imgui_input_int(IMGUI_BAKE_INTERVAL.copy({.max = frame->delay}), self, interval); - _imgui_checkbox(IMGUI_BAKE_ROUND_SCALE, self, isRoundScale); - _imgui_checkbox(IMGUI_BAKE_ROUND_ROTATION, self, isRoundRotation); - - if (_imgui_button(IMGUI_BAKE_CONFIRM, self)) { - anm2_frame_bake(self->anm2, *self->reference, interval, isRoundScale, isRoundRotation); - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) - imgui_close_current_popup(self); - - _imgui_end_child(); // IMGUI_BAKE_CHILD) - - imgui_end_popup(self); - } - - if (_imgui_button(IMGUI_FIT_ANIMATION_LENGTH, self)) - anm2_animation_length_set(animation); - - _imgui_input_int(IMGUI_ANIMATION_LENGTH, self, animation->frameNum); - _imgui_input_int(IMGUI_FPS, self, self->anm2->fps); - _imgui_checkbox(IMGUI_LOOP, self, animation->isLoop); - _imgui_selectable_input_text(IMGUI_CREATED_BY.copy({.label = self->anm2->createdBy}), self, self->anm2->createdBy); - - _imgui_end_child(); // IMGUI_TIMELINE_FOOTER_OPTIONS_CHILD - - _imgui_end(); // IMGUI_TIMELINE -} - */ - -static void _imgui_onionskin(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_ONIONSKIN, self); - - bool isEnabled = self->settings->onionskinIsEnabled; - int drawOrder = self->settings->onionskinDrawOrder; - - _imgui_checkbox(IMGUI_ONIONSKIN_ENABLED, self, isEnabled); - - auto onionskin_section = [&](auto& text, auto& count, auto& colorOffset) { - ImGui::PushID(text.label.c_str()); - _imgui_text(text, self); - _imgui_input_int(IMGUI_ONIONSKIN_COUNT.copy({.isDisabled = !isEnabled}), self, count); - _imgui_color_edit3(IMGUI_ONIONSKIN_COLOR_OFFSET.copy({.isDisabled = !isEnabled}), self, colorOffset); - ImGui::PopID(); - }; - - onionskin_section(IMGUI_ONIONSKIN_BEFORE, self->settings->onionskinBeforeCount, self->settings->onionskinBeforeColorOffset); - onionskin_section(IMGUI_ONIONSKIN_AFTER, self->settings->onionskinAfterCount, self->settings->onionskinAfterColorOffset); - - ImGui::Separator(); - - _imgui_text(IMGUI_ONIONSKIN_DRAW_ORDER, self); - _imgui_radio_button(IMGUI_ONIONSKIN_BELOW.copy({.isDisabled = !isEnabled}), self, drawOrder); - _imgui_radio_button(IMGUI_ONIONSKIN_ABOVE.copy({.isDisabled = !isEnabled}), self, drawOrder); - - _imgui_end(IMGUI_ONIONSKIN, self); -} - -static void _imgui_taskbar(Imgui* self) { - static ImguiPopupState exitConfirmState = IMGUI_POPUP_STATE_CLOSED; - static float displayScale = self->settings->displayScale; - ImGuiViewport* viewport = ImGui::GetMainViewport(); - - ImguiItem taskbar = IMGUI_TASKBAR.copy({.position = viewport->Pos, .size = vec2(viewport->Size.x, IMGUI_TASKBAR.size->y * displayScale)}); - _imgui_begin(taskbar, self); - - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); - Anm2Item* item = anm2_item_from_reference(self->anm2, *self->reference); - - _imgui_selectable(IMGUI_FILE.copy({.isSelected = imgui_is_popup_open(IMGUI_FILE.popup)}), self); - - if (imgui_begin_popup(IMGUI_FILE.popup, self)) { - _imgui_selectable(IMGUI_NEW, self); - _imgui_selectable(IMGUI_OPEN, self); - _imgui_selectable(IMGUI_SAVE.copy({.isDisabled = self->anm2->path.empty()}), self); - _imgui_selectable(IMGUI_SAVE_AS.copy({.isDisabled = self->anm2->path.empty()}), self); - _imgui_selectable(IMGUI_EXPLORE_ANM2_LOCATION.copy({.isDisabled = self->anm2->path.empty()}), self); - _imgui_selectable(IMGUI_EXIT, self); - imgui_end_popup(self); - } - - if (self->dialog->isSelected && self->dialog->type == DIALOG_ANM2_OPEN) { - _imgui_anm2_open(self, self->dialog->path); - dialog_reset(self->dialog); - } - - if (self->dialog->isSelected && self->dialog->type == DIALOG_ANM2_SAVE) { - anm2_serialize(self->anm2, self->dialog->path); - window_title_from_path_set(self->window, self->dialog->path); - imgui_log_push(self, std::format(IMGUI_LOG_FILE_SAVE_FORMAT, self->dialog->path)); - dialog_reset(self->dialog); - } - - if (self->isTryQuit && !imgui_is_popup_open(IMGUI_EXIT_CONFIRMATION.label)) - imgui_open_popup(IMGUI_EXIT_CONFIRMATION.label); - - _imgui_confirm_popup(IMGUI_EXIT_CONFIRMATION, self, &exitConfirmState); - - switch (exitConfirmState) { - case IMGUI_POPUP_STATE_CONFIRM: - self->isQuit = true; - break; - case IMGUI_POPUP_STATE_CANCEL: - self->isTryQuit = false; - break; - default: - break; - } - - _imgui_selectable(IMGUI_WIZARD.copy({.isSelected = imgui_is_popup_open(IMGUI_WIZARD.popup)}), self); - - if (imgui_begin_popup(IMGUI_WIZARD.popup, self)) { - _imgui_selectable(IMGUI_GENERATE_ANIMATION_FROM_GRID.copy({.isDisabled = !item || (self->reference->itemType != ANM2_LAYER)}), self); - _imgui_selectable(IMGUI_CHANGE_ALL_FRAME_PROPERTIES.copy({.isDisabled = !item}), self); - _imgui_selectable(IMGUI_SCALE_ANM2.copy({.isDisabled = self->anm2->animations.empty()}), self); - _imgui_selectable(IMGUI_RENDER_ANIMATION.copy({.isDisabled = !animation}), self); - - imgui_end_popup(self); - } - - if (imgui_begin_popup_modal(IMGUI_GENERATE_ANIMATION_FROM_GRID.popup, self, IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize)) { - static auto& startPosition = self->settings->generateStartPosition; - static auto& size = self->settings->generateSize; - static auto& pivot = self->settings->generatePivot; - static auto& rows = self->settings->generateRows; - static auto& columns = self->settings->generateColumns; - static auto& count = self->settings->generateCount; - static auto& delay = self->settings->generateDelay; - static float& time = self->generatePreview->time; - - _imgui_begin_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_OPTIONS_CHILD, self); - _imgui_input_int2(IMGUI_GENERATE_ANIMATION_FROM_GRID_START_POSITION, self, startPosition); - _imgui_input_int2(IMGUI_GENERATE_ANIMATION_FROM_GRID_SIZE, self, size); - _imgui_input_int2(IMGUI_GENERATE_ANIMATION_FROM_GRID_PIVOT, self, pivot); - _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_ROWS, self, rows); - _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_COLUMNS, self, columns); - _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_COUNT.copy({.max = rows * columns}), self, count); - _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_DELAY, self, delay); - _imgui_end_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_OPTIONS_CHILD, self); - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_PREVIEW_CHILD, self); - - generate_preview_draw(self->generatePreview); - ImGui::Image(self->generatePreview->canvas.framebuffer, GENERATE_PREVIEW_SIZE); - - _imgui_begin_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER_CHILD, self); - _imgui_slider_float(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER, self, time); - _imgui_end_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER_CHILD, self); - _imgui_end_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_PREVIEW_CHILD, self); - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - if (_imgui_button(IMGUI_GENERATE_ANIMATION_FROM_GRID_GENERATE, self)) { - anm2_generate_from_grid(self->anm2, *self->reference, startPosition, size, pivot, columns, count, delay); - imgui_close_current_popup(self); - } - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) - imgui_close_current_popup(self); - _imgui_end_child(IMGUI_FOOTER_CHILD, self); - - imgui_end_popup(self); - } - - if (imgui_begin_popup_modal(IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popup, self, IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popupSize)) { - static auto& isCrop = self->settings->changeIsCrop; - static auto& isSize = self->settings->changeIsSize; - static auto& isPosition = self->settings->changeIsPosition; - static auto& isPivot = self->settings->changeIsPivot; - static auto& isScale = self->settings->changeIsScale; - static auto& isRotation = self->settings->changeIsRotation; - static auto& isColorOffset = self->settings->changeIsColorOffset; - static auto& isTint = self->settings->changeIsTint; - static auto& isVisibleSet = self->settings->changeIsVisibleSet; - static auto& isInterpolatedSet = self->settings->changeIsInterpolatedSet; - static auto& crop = self->settings->changeCrop; - static auto& size = self->settings->changeSize; - static auto& position = self->settings->changePosition; - static auto& pivot = self->settings->changePivot; - static auto& scale = self->settings->changeScale; - static auto& rotation = self->settings->changeRotation; - static auto& isDelay = self->settings->changeIsDelay; - static auto& delay = self->settings->changeDelay; - static auto& tint = self->settings->changeTint; - static auto& colorOffset = self->settings->changeColorOffset; - static auto& isVisible = self->settings->changeIsVisible; - static auto& isInterpolated = self->settings->changeIsInterpolated; - static auto& isFromSelectedFrame = self->settings->changeIsFromSelectedFrame; - static auto& numberFrames = self->settings->changeNumberFrames; - int start = std::max(self->reference->frameIndex, 0); - int max = isFromSelectedFrame ? std::max(ANM2_FRAME_NUM_MIN, (int)item->frames.size() - start) : (int)item->frames.size(); - - auto change_frames = [&](Anm2ChangeType type) { - Anm2FrameChange frameChange = { - .isVisible = isVisibleSet ? std::optional{isVisible} : std::nullopt, - .isInterpolated = isInterpolatedSet ? std::optional{isInterpolated} : std::nullopt, - .rotation = isRotation ? std::optional{rotation} : std::nullopt, - .delay = isDelay ? std::optional{delay} : std::nullopt, - .crop = isCrop ? std::optional{crop} : std::nullopt, - .pivot = isPivot ? std::optional{pivot} : std::nullopt, - .position = isPosition ? std::optional{position} : std::nullopt, - .size = isSize ? std::optional{size} : std::nullopt, - .scale = isScale ? std::optional{scale} : std::nullopt, - .offsetRGB = isColorOffset ? std::optional{colorOffset} : std::nullopt, - .tintRGBA = isTint ? std::optional{tint} : std::nullopt, - }; - anm2_item_frame_set(self->anm2, *self->reference, frameChange, type, start, numberFrames); - - imgui_close_current_popup(self); - }; - - _imgui_begin_child(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CHILD, self); - /* - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_CROP.copy({.isDisabled = !isCrop}), self, crop, isCrop); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_SIZE.copy({.isDisabled = !isSize}), self, size, isSize); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_POSITION.copy({.isDisabled = !isPosition}), self, position, isPosition); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_PIVOT.copy({.isDisabled = !isPivot}), self, pivot, isPivot); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_SCALE.copy({.isDisabled = !isScale}), self, scale, isScale); - _imgui_checkbox_drag_float(IMGUI_FRAME_PROPERTIES_ROTATION.copy({.isDisabled = !isRotation}), self, rotation, isRotation); - _imgui_checkbox_input_int(IMGUI_FRAME_PROPERTIES_DELAY.copy({.isDisabled = !isDelay}), self, delay, isDelay); - _imgui_checkbox_color_edit4(IMGUI_FRAME_PROPERTIES_TINT.copy({.isDisabled = !isTint}), self, tint, isTint); - _imgui_checkbox_color_edit3(IMGUI_FRAME_PROPERTIES_COLOR_OFFSET.copy({.isDisabled = !isColorOffset}), self, colorOffset, isColorOffset); - _imgui_checkbox_checkbox(IMGUI_FRAME_PROPERTIES_VISIBLE.copy({.isDisabled = !isVisibleSet}), self, isVisible, isVisibleSet); - ImGui::NewLine(); - _imgui_checkbox_checkbox(IMGUI_FRAME_PROPERTIES_INTERPOLATED.copy({.isDisabled = !isInterpolatedSet}), self, isInterpolated, isInterpolatedSet); - */ - _imgui_end_child(IMGUI_FOOTER_CHILD, self); - - _imgui_begin_child(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS_CHILD, self); - _imgui_text(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS, self); - _imgui_checkbox(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_FROM_SELECTED_FRAME, self, isFromSelectedFrame); - _imgui_input_int(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_NUMBER_FRAMES.copy({.max = max, .value = max}), self, numberFrames); - _imgui_end_child(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS_CHILD, self); - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_ADD, self)) - change_frames(ANM2_CHANGE_ADD); - if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SUBTRACT, self)) - change_frames(ANM2_CHANGE_SUBTRACT); - if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SET, self)) - change_frames(ANM2_CHANGE_SET); - if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CANCEL, self)) - imgui_close_current_popup(self); - _imgui_end_child(IMGUI_FOOTER_CHILD, self); - - imgui_end_popup(self); - } - - if (imgui_begin_popup_modal(IMGUI_SCALE_ANM2.popup, self, IMGUI_SCALE_ANM2.popupSize)) { - _imgui_begin_child(IMGUI_SCALE_ANM2_OPTIONS_CHILD, self); - _imgui_input_float(IMGUI_SCALE_ANM2_VALUE, self, self->settings->scaleValue); - _imgui_end_child(IMGUI_SCALE_ANM2_OPTIONS_CHILD, self); - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - if (_imgui_button(IMGUI_SCALE_ANM2_SCALE, self)) { - anm2_scale(self->anm2, self->settings->scaleValue); - imgui_close_current_popup(self); - } - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) - imgui_close_current_popup(self); - _imgui_end_child(IMGUI_FOOTER_CHILD, self); - - imgui_end_popup(self); - } - - if (imgui_begin_popup_modal(IMGUI_RENDER_ANIMATION.popup, self, IMGUI_RENDER_ANIMATION.popupSize)) { - static DialogType& dialogType = self->dialog->type; - static bool& dialogIsSelected = self->dialog->isSelected; - static int& type = self->settings->renderType; - static float& scale = self->settings->renderScale; - static bool& isUseAnimationBounds = self->settings->renderIsUseAnimationBounds; - static std::string& dialogPath = self->dialog->path; - static std::string& ffmpegPath = self->settings->renderFFmpegPath; - static std::string& format = self->settings->renderFormat; - static std::string& path = self->settings->renderPath; - - _imgui_begin_child(IMGUI_RENDER_ANIMATION_CHILD, self); - - /* - if (_imgui_atlas_button(IMGUI_RENDER_ANIMATION_LOCATION_BROWSE, self)) - dialog_render_path_set(self->dialog, (RenderType)type); - */ - - if (dialogIsSelected && (dialogType == DIALOG_RENDER_PATH_SET)) { - path = path_extension_change(dialogPath, RENDER_EXTENSIONS[type]); - dialog_reset(self->dialog); - } - - _imgui_input_text(IMGUI_RENDER_ANIMATION_LOCATION, self, path); - - /* - if (_imgui_atlas_button(IMGUI_RENDER_ANIMATION_FFMPEG_BROWSE, self)) - dialog_ffmpeg_path_set(self->dialog); - */ - - if (dialogIsSelected && dialogType == DIALOG_FFMPEG_PATH_SET) { - ffmpegPath = self->dialog->path; - dialog_reset(self->dialog); - } - - _imgui_input_text(IMGUI_RENDER_ANIMATION_FFMPEG_PATH, self, ffmpegPath); - _imgui_combo(IMGUI_RENDER_ANIMATION_OUTPUT, self, type); - _imgui_input_text(IMGUI_RENDER_ANIMATION_FORMAT.copy({.isDisabled = type != RENDER_PNG}), self, format); - _imgui_checkbox(IMGUI_RENDER_ANIMATION_IS_USE_ANIMATION_BOUNDS, self, isUseAnimationBounds); - _imgui_input_float(IMGUI_RENDER_ANIMATION_SCALE.copy({.isDisabled = !isUseAnimationBounds}), self, scale); - - _imgui_end_child(IMGUI_RENDER_ANIMATION_CHILD, self); - - _imgui_begin_child(IMGUI_RENDER_ANIMATION_FOOTER_CHILD, self); - - if (_imgui_button(IMGUI_RENDER_ANIMATION_CONFIRM, self)) { - bool isRenderStart = true; - - if (!std::filesystem::exists(ffmpegPath)) { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_FFMPEG_PATH_ERROR); - isRenderStart = false; - } - - if (isRenderStart) { - switch (self->settings->renderType) { - case RENDER_PNG: - if (!std::filesystem::is_directory(path)) { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_DIRECTORY_ERROR); - isRenderStart = false; - } - break; - case RENDER_GIF: - case RENDER_WEBM: - case RENDER_MP4: - if (!path_is_valid(path)) { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_PATH_ERROR); - isRenderStart = false; - } - default: - break; - } - } - - if (isRenderStart) - preview_render_start(self->preview); - else - self->preview->isRenderCancelled = true; - - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) - imgui_close_current_popup(self); - - _imgui_end_child(IMGUI_RENDER_ANIMATION_FOOTER_CHILD, self); - - imgui_end_popup(self); - } - - if (imgui_begin_popup_modal(IMGUI_RENDER_ANIMATION_CONFIRM.popup, self, IMGUI_RENDER_ANIMATION_CONFIRM.popupSize)) { - static int& type = self->settings->renderType; - static std::string& format = self->settings->renderFormat; - - auto rendering_end = [&]() { - preview_render_end(self->preview); - imgui_close_current_popup(self); - }; - - std::vector& frames = self->preview->renderFrames; - std::string path = std::string(self->settings->renderPath.c_str()); - - if (self->preview->isRenderCancelled) { - rendering_end(); - self->preview->isRenderCancelled = false; - } - - if (!animation) { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_NO_ANIMATION_ERROR); - rendering_end(); - } - - _imgui_begin_child(IMGUI_RENDERING_ANIMATION_CHILD, self); - - float progress = self->preview->time / (animation->frameNum - 1); - ImGui::ProgressBar(progress); - - _imgui_text(IMGUI_RENDERING_ANIMATION_INFO, self); - - _imgui_end_child(IMGUI_RENDERING_ANIMATION_CHILD, self); - - if (_imgui_button(IMGUI_RENDERING_ANIMATION_CANCEL, self)) - self->preview->isRenderCancelled = true; - - if (self->preview->isRenderFinished && frames.empty()) { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_NO_FRAMES_ERROR); - rendering_end(); - } - - if (self->preview->isRenderFinished) { - switch (type) { - case RENDER_PNG: { - std::filesystem::path workingPath = std::filesystem::current_path(); - std::filesystem::current_path(path); - - for (auto [i, frame] : std::views::enumerate(frames)) { - std::string framePath = std::vformat(format, std::make_format_args(i)); - framePath = path_extension_change(framePath, RENDER_EXTENSIONS[type]); - if (!frame.isInvalid) - texture_from_gl_write(&frame, framePath); - } - - std::filesystem::current_path(workingPath); - imgui_log_push(self, std::format(IMGUI_LOG_RENDER_ANIMATION_FRAMES_SAVE_FORMAT, path)); - break; - } - case RENDER_GIF: - case RENDER_WEBM: - case RENDER_MP4: { - std::string ffmpegPath = std::string(self->settings->renderFFmpegPath.c_str()); - path = path_extension_change(path, RENDER_EXTENSIONS[self->settings->renderType]); - - if (ffmpeg_render(ffmpegPath, path, frames, self->preview->canvas.size, self->anm2->fps, (RenderType)type)) - imgui_log_push(self, std::format(IMGUI_LOG_RENDER_ANIMATION_SAVE_FORMAT, path)); - else - imgui_log_push(self, std::format(IMGUI_LOG_RENDER_ANIMATION_FFMPEG_ERROR, path)); - break; - } - default: - break; - } - - rendering_end(); - } - - imgui_end_popup(self); - } - - _imgui_selectable(IMGUI_PLAYBACK.copy({.isSelected = imgui_is_popup_open(IMGUI_PLAYBACK.popup)}), self); - - if (imgui_begin_popup(IMGUI_PLAYBACK.popup, self, IMGUI_PLAYBACK.popupSize)) { - /* - _imgui_checkbox_selectable(IMGUI_ALWAYS_LOOP, self, self->settings->playbackIsLoop); - _imgui_checkbox_selectable(IMGUI_CLAMP_PLAYHEAD, self, self->settings->playbackIsClampPlayhead); - */ - imgui_end_popup(self); - } - - _imgui_selectable(IMGUI_SETTINGS.copy({.isSelected = imgui_is_popup_open(IMGUI_SETTINGS.popup)}), self); - - /* - if (imgui_begin_popup(IMGUI_SETTINGS.popup, self, IMGUI_SETTINGS.popupSize)) { - if (_imgui_checkbox_selectable(IMGUI_VSYNC, self, self->settings->isVsync)) - window_vsync_set(self->settings->isVsync); - _imgui_selectable(IMGUI_HOTKEYS, self); - if (_imgui_selectable(IMGUI_DEFAULT_SETTINGS, self)) - *self->settings = Settings(); - imgui_end_popup(self); - } - */ - - if (imgui_begin_popup_modal(IMGUI_HOTKEYS.popup, self, IMGUI_HOTKEYS.popupSize)) { - _imgui_begin_child(IMGUI_HOTKEYS_CHILD, self); - - if (_imgui_begin_table(IMGUI_HOTKEYS_TABLE, self)) { - static int selectedIndex = INDEX_NONE; - - ImGui::TableSetupScrollFreeze(0, 1); - _imgui_table_setup_column(IMGUI_HOTKEYS_FUNCTION); - _imgui_table_setup_column(IMGUI_HOTKEYS_HOTKEY); - _imgui_table_headers_row(); - - for (int i = 0; i < HOTKEY_COUNT; i++) { - if (!SETTINGS_HOTKEY_MEMBERS[i]) - continue; - - bool isSelected = selectedIndex == i; - const char* string = HOTKEY_STRINGS[i]; - std::string* settingString = &(self->settings->*SETTINGS_HOTKEY_MEMBERS[i]); - std::string chordString = isSelected ? IMGUI_HOTKEY_CHANGE : *settingString; - - ImGui::PushID(i); - _imgui_table_next_row(); - _imgui_table_set_column_index(0); - ImGui::TextUnformatted(string); - _imgui_table_set_column_index(1); - - if (ImGui::Selectable(chordString.c_str(), isSelected)) - selectedIndex = i; - ImGui::PopID(); - - if (isSelected) { - ImGuiKeyChord chord = IMGUI_CHORD_NONE; - - if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) - chord |= ImGuiMod_Ctrl; - if (ImGui::IsKeyDown(ImGuiMod_Shift)) - chord |= ImGuiMod_Shift; - if (ImGui::IsKeyDown(ImGuiMod_Alt)) - chord |= ImGuiMod_Alt; - if (ImGui::IsKeyDown(ImGuiMod_Super)) - chord |= ImGuiMod_Super; - - for (auto& [_, key] : IMGUI_KEY_MAP) { - if (ImGui::IsKeyPressed(key)) { - chord |= key; - imgui_hotkey_chord_registry()[i] = chord; - *settingString = imgui_string_from_chord_get(chord); - selectedIndex = INDEX_NONE; - break; - } - } - } - } - - _imgui_end_table(); - } - - _imgui_end_child(IMGUI_HOTKEYS_CHILD, self); - - _imgui_begin_child(IMGUI_HOTKEYS_OPTIONS_CHILD, self); - if (_imgui_button(IMGUI_HOTKEYS_CONFIRM, self)) - imgui_close_current_popup(self); - _imgui_end_child(IMGUI_HOTKEYS_OPTIONS_CHILD, self); - - imgui_end_popup(self); - } - - _imgui_end(taskbar, self); -} - -static void _imgui_tools(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_TOOLS, self); - - float displayScale = self->settings->displayScale; - float availableWidth = ImGui::GetContentRegionAvail().x; - float usedWidth = ImGui::GetStyle().FramePadding.x; - - for (int i = 0; i < TOOL_COUNT; i++) { - - ImguiItem item = IMGUI_TOOL_ITEMS[i]->copy( - {.scale = displayScale, - .isDisabled = (i == TOOL_UNDO && self->snapshots->undoStack.empty()) || (i == TOOL_REDO && self->snapshots->redoStack.empty()), - .isSelected = self->settings->tool == (ToolType)i}); - - if (i > 0 && usedWidth + ImGui::GetItemRectSize().x < availableWidth) - ImGui::SameLine(); - else - usedWidth = 0; - - if (i == TOOL_COLOR) - _imgui_color_edit4(item, self, self->settings->toolColor); - else - _imgui_atlas_button(item, self); - - usedWidth += ImGui::GetItemRectSize().x + ImGui::GetStyle().ItemSpacing.x; - } - - _imgui_end(IMGUI_TOOLS, self); -} - -static void _imgui_layers(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_LAYERS, self); - _imgui_no_anm2_path_click_check(self); - - vec2 footerSize = {0, (ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f)}; - vec2 childSize = ImGui::GetContentRegionAvail() - footerSize; - - ImguiItem layersChild = IMGUI_LAYERS_CHILD.copy({.size = childSize}); - _imgui_begin_child(layersChild, self); - - for (auto& [id, layer] : self->anm2->layers) { - ImGui::PushID(id); - - ImguiItem layerItem = IMGUI_LAYER.copy({.label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), .isSelected = self->selectedLayerID == id, .id = id}); - if (_imgui_atlas_selectable_input_text(layerItem, self, layer.name)) - self->selectedLayerID = id; - - /* - ImguiItem spritesheetItem = - IMGUI_LAYER_SPRITESHEET_ID.copy({.label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), .isSelected = self->selectedLayerID == id, .id = id}); - _imgui_atlas_selectable_input_int(spritesheetItem, self, layer.spritesheetID); - */ - - ImGui::PopID(); - }; - - _imgui_end_child(layersChild, self); - - ImguiItem footerChild = IMGUI_FOOTER_CHILD.copy({.size = footerSize}); - _imgui_begin_child(footerChild, self); - - if (_imgui_button(IMGUI_LAYER_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) - self->selectedLayerID = anm2_layer_add(self->anm2); - - if (_imgui_button(IMGUI_LAYER_REMOVE.copy({.isDisabled = self->selectedLayerID == ID_NONE}), self)) { - anm2_layer_remove(self->anm2, self->selectedLayerID); - self->selectedLayerID = ID_NONE; - } - - _imgui_end_child(footerChild, self); - _imgui_end(IMGUI_LAYERS, self); -} - -static void _imgui_nulls(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_NULLS, self); - _imgui_no_anm2_path_click_check(self); - - vec2 footerSize = {0, (ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f)}; - vec2 childSize = ImGui::GetContentRegionAvail() - footerSize; - - ImguiItem nullsChild = IMGUI_NULLS_CHILD.copy({.size = childSize}); - _imgui_begin_child(nullsChild, self); - - for (auto& [id, null] : self->anm2->nulls) { - ImGui::PushID(id); - - ImguiItem nullItem = IMGUI_NULL.copy({.label = std::format(IMGUI_NULL_FORMAT, id, null.name), .isSelected = self->selectedNullID == id, .id = id}); - - if (_imgui_atlas_selectable_input_text(nullItem, self, null.name)) - self->selectedNullID = id; - - ImGui::PopID(); - }; - - _imgui_end_child(nullsChild, self); // nullsChild - - ImguiItem footerChild = IMGUI_FOOTER_CHILD.copy({.size = footerSize}); - _imgui_begin_child(footerChild, self); - - if (_imgui_button(IMGUI_NULL_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) - self->selectedNullID = anm2_null_add(self->anm2); - - if (_imgui_button(IMGUI_NULL_REMOVE.copy({.isDisabled = self->selectedNullID == ID_NONE}), self)) { - anm2_null_remove(self->anm2, self->selectedNullID); - self->selectedNullID = ID_NONE; - } - - _imgui_end_child(footerChild, self); - _imgui_end(IMGUI_NULLS, self); -} - -static void _imgui_animations(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATIONS, self); - _imgui_no_anm2_path_click_check(self); - - vec2 footerSize = {0, (ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f)}; - vec2 childSize = ImGui::GetContentRegionAvail() - footerSize; - ImguiItem animationsChild = IMGUI_ANIMATIONS_CHILD.copy({.size = childSize}); - - _imgui_begin_child(animationsChild, self); - - for (auto [i, animation] : std::views::enumerate(self->anm2->animations)) { - ImGui::PushID(i); - - bool isDefaultAnimation = self->anm2->defaultAnimation == animation.name; - bool isReferenceAnimation = self->reference->animationIndex == i; - - ImguiItem animationItem = IMGUI_ANIMATION.copy({.label = animation.name, - .tooltip = animation.name, - .size = vec2(childSize.x, 0), - .isSelected = self->selectedAnimationIndices.contains(i), - .id = i, - .font = isDefaultAnimation && isReferenceAnimation ? self->fonts[FONT_BOLD_ITALICS] - : isDefaultAnimation ? self->fonts[FONT_BOLD] - : isReferenceAnimation ? self->fonts[FONT_ITALICS] - : self->fonts[FONT_REGULAR]}); - - if (_imgui_atlas_selectable_input_text(animationItem, self, animation.name)) { - set_list(self->selectedAnimationIndices, (int)i, ImGui::IsKeyDown(ImGuiMod_Ctrl), ImGui::IsKeyDown(ImGuiMod_Shift), &self->lastAnimationIndex); - if (!ImGui::IsKeyDown(ImGuiMod_Ctrl) && !ImGui::IsKeyDown(ImGuiMod_Shift)) - *self->reference = {(int)i}; - } - - if (ImGui::IsItemHovered()) { - self->clipboard->type = CLIPBOARD_ANIMATION; - self->clipboard->destination = (int)i; - self->clipboard->source = self->selectedAnimationIndices; - } - - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - ImGui::SetDragDropPayload(animationItem.drag_drop_get(), &i, sizeof(int)); - _imgui_atlas_selectable(animationItem.copy({.size = vec2(childSize.x, 0)}), self); - ImGui::EndDragDropSource(); - } - - if (ImGui::BeginDragDropTarget()) { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(animationItem.drag_drop_get())) { - int sourceIndex = *(int*)payload->Data; - if (sourceIndex != i) { - imgui_snapshot(self, IMGUI_ACTION_ANIMATION_MOVE); - vector_move(self->anm2->animations, sourceIndex, i); - } - } - - ImGui::EndDragDropTarget(); - } - - ImGui::PopID(); - } - - _imgui_context_menu(self); - - _imgui_end_child(animationsChild, self); - - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); - - ImguiItem footerChild = IMGUI_FOOTER_CHILD.copy({.size = footerSize}); - _imgui_begin_child(footerChild, self); - - if (_imgui_button(IMGUI_ANIMATION_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) - self->reference->animationIndex = anm2_animation_add(self->anm2); - - if (_imgui_button(IMGUI_ANIMATION_DUPLICATE.copy({.isDisabled = !animation}), self)) - self->reference->animationIndex = anm2_animation_add(self->anm2, animation, self->reference->animationIndex); - - _imgui_button(IMGUI_ANIMATION_MERGE.copy({.isDisabled = !animation || self->reference->animationIndex == INDEX_NONE}), self); - - if (imgui_begin_popup_modal(IMGUI_ANIMATION_MERGE.popup, self, IMGUI_ANIMATION_MERGE.popupSize)) { - static bool& isDeleteAnimationsAfter = self->settings->mergeIsDeleteAnimationsAfter; - static int& mergeType = self->settings->mergeType; - static std::set selectedMergeIndices; - static int lastMergeAnimationIndex = INDEX_NONE; - - _imgui_begin_child(IMGUI_MERGE_ANIMATIONS_CHILD, self); - - for (auto [i, animation] : std::views::enumerate(self->anm2->animations)) { - ImGui::PushID(i); - - if (_imgui_atlas_selectable(IMGUI_ANIMATION.copy({.label = animation.name, .isSelected = selectedMergeIndices.contains(i)}), self)) { - set_list(selectedMergeIndices, (int)i, ImGui::IsKeyDown(ImGuiMod_Ctrl), ImGui::IsKeyDown(ImGuiMod_Shift), &lastMergeAnimationIndex); - } - - ImGui::PopID(); - } - - _imgui_end_child(IMGUI_MERGE_ANIMATIONS_CHILD, self); - - _imgui_begin_child(IMGUI_MERGE_ON_CONFLICT_CHILD, self); - _imgui_text(IMGUI_MERGE_ON_CONFLICT, self); - _imgui_radio_button(IMGUI_MERGE_APPEND_FRAMES, self, mergeType); - _imgui_radio_button(IMGUI_MERGE_REPLACE_FRAMES, self, mergeType); - _imgui_radio_button(IMGUI_MERGE_PREPEND_FRAMES, self, mergeType); - _imgui_radio_button(IMGUI_MERGE_IGNORE, self, mergeType); - _imgui_end_child(IMGUI_MERGE_ON_CONFLICT_CHILD, self); - - _imgui_begin_child(IMGUI_MERGE_OPTIONS_CHILD, self); - - _imgui_checkbox(IMGUI_MERGE_DELETE_ANIMATIONS_AFTER, self, isDeleteAnimationsAfter); - - _imgui_end_child(IMGUI_MERGE_OPTIONS_CHILD, self); - - if (_imgui_button(IMGUI_MERGE_CONFIRM.copy({.isDisabled = selectedMergeIndices.empty()}), self)) { - anm2_animation_merge(self->anm2, self->reference->animationIndex, self->selectedAnimationIndices, (Anm2MergeType)mergeType); - - if (isDeleteAnimationsAfter) - anm2_animations_remove(self->anm2, selectedMergeIndices); - - selectedMergeIndices.clear(); - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) { - selectedMergeIndices.clear(); - imgui_close_current_popup(self); - } - - imgui_end_popup(self); - } - - if (_imgui_button(IMGUI_ANIMATION_REMOVE.copy({.isDisabled = !animation}), self)) { - anm2_animations_remove(self->anm2, self->selectedAnimationIndices); - *self->reference = Anm2Reference(); - self->selectedAnimationIndices = {}; - } - - if (_imgui_button(IMGUI_ANIMATION_DEFAULT.copy({.isDisabled = !animation}), self)) - self->anm2->defaultAnimation = animation->name; - - _imgui_end_child(footerChild, self); - _imgui_end(IMGUI_ANIMATIONS, self); -} - -static void _imgui_events(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_EVENTS, self); - _imgui_no_anm2_path_click_check(self); - - vec2 footerSize = {0, (ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f)}; - vec2 childSize = ImGui::GetContentRegionAvail() - footerSize; - ImguiItem eventsChild = IMGUI_EVENTS_CHILD.copy({.size = childSize}); - _imgui_begin_child(eventsChild, self); - - for (auto [id, event] : self->anm2->events) { - ImGui::PushID(id); - - ImguiItem eventItem = IMGUI_EVENT.copy({.label = event.name, .isSelected = id == self->selectedEventID, .id = id}); - - if (_imgui_atlas_selectable_input_text(eventItem, self, event.name)) - self->selectedEventID = id; - - ImGui::PopID(); - } - - _imgui_end_child(eventsChild, self); - - ImguiItem footerChild = IMGUI_FOOTER_CHILD.copy({.size = footerSize}); - _imgui_begin_child(footerChild, self); - - if (_imgui_button(IMGUI_EVENTS_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) { - int id = map_next_id_get(self->anm2->events); - self->anm2->events[id] = Anm2Event{}; - self->selectedEventID = id; - } - - std::unordered_set eventIDs = map_keys_to_set(self->anm2->events); - - std::unordered_set usedEventIDs; - for (auto& animation : self->anm2->animations) - for (auto& frame : animation.triggers.frames) - if (frame.eventID != ID_NONE) - usedEventIDs.insert(frame.eventID); - - std::unordered_set unusedEventIDs = set_symmetric_difference(eventIDs, usedEventIDs); - - if (_imgui_button(IMGUI_EVENTS_REMOVE_UNUSED.copy({.isDisabled = unusedEventIDs.empty()}), self)) { - for (auto& id : unusedEventIDs) - self->anm2->events.erase(id); - imgui_log_push(self, IMGUI_LOG_REMOVE_UNUSED_EVENTS); - } - - _imgui_end_child(footerChild, self); - _imgui_end(IMGUI_EVENTS, self); -} - -static void _imgui_spritesheets(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEETS, self); - _imgui_no_anm2_path_click_check(self); - - float displayScale = self->settings->displayScale; - vec2 footerSize = {0, ((ImGui::GetTextLineHeightWithSpacing() * 2.0f) + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f + - ImGui::GetStyle().ItemSpacing.y)}; - vec2 childSize = ImGui::GetContentRegionAvail() - footerSize; - vec2 spritesheetSize = *IMGUI_SPRITESHEET_PREVIEW.size * displayScale; - - _imgui_begin_child(IMGUI_SPRITESHEETS_CHILD.copy({.size = childSize}), self); - - std::function spritesheet_draw = [&](int id, Anm2Spritesheet& spritesheet) { - ImGui::PushID(id); - vec2 itemSize = {childSize.x, spritesheetSize.y}; - _imgui_begin_child(IMGUI_SPRITESHEET_CHILD.copy({.size = itemSize}), self); - - Texture& texture = spritesheet.texture; - bool& isInvalid = texture.isInvalid; - - ImVec2 cursorPos = ImGui::GetCursorPos(); - - if (_imgui_selectable(IMGUI_SPRITESHEET.copy({.tooltip = spritesheet.path, .size = itemSize, .isSelected = self->selectedSpritesheetIDs.contains(id)}), - self)) - set_list(self->selectedSpritesheetIDs, id, ImGui::IsKeyDown(ImGuiMod_Ctrl), ImGui::IsKeyDown(ImGuiMod_Shift), &self->lastSpritesheetID); - - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { - ImGui::SetDragDropPayload(IMGUI_SPRITESHEET.drag_drop_get(), &id, sizeof(int)); - spritesheet_draw(id, spritesheet); - ImGui::EndDragDropSource(); - } - - if (ImGui::BeginDragDropTarget()) { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_SPRITESHEET.drag_drop_get())) { - int sourceID = *(int*)payload->Data; - if (sourceID != id) { - imgui_snapshot(self, IMGUI_ACTION_SPRITESHEET_SWAP); - map_swap(self->anm2->spritesheets, sourceID, id); - } - } - ImGui::EndDragDropTarget(); - } - - vec2 spritesheetPreviewSize = spritesheetSize; - float spritesheetAspect = (float)texture.size.x / texture.size.y; - - if ((spritesheetSize.x / spritesheetSize.y) > spritesheetAspect) - spritesheetPreviewSize.x = spritesheetSize.y * spritesheetAspect; - else - spritesheetPreviewSize.y = spritesheetSize.x / spritesheetAspect; - - _imgui_image(IMGUI_SPRITESHEET_PREVIEW.copy({.textureID = isInvalid ? self->resources->atlas.id : spritesheet.texture.id, - .size = spritesheetPreviewSize, - .uvMin = isInvalid ? ATLAS_UV_MIN(ATLAS_NONE) : vec2(), - .uvMax = isInvalid ? ATLAS_UV_MAX(ATLAS_NONE) : vec2(1.0f), - .cursorPosition = cursorPos}), - self); - - _imgui_atlas_text( - IMGUI_SPRITESHEET_TEXT.copy({.label = std::format(IMGUI_SPRITESHEET_FORMAT, id, spritesheet.path), - .cursorPosition = vec2(spritesheetSize.x, (spritesheetSize.y * 0.5f) - (ImGui::GetTextLineHeight() * 0.5f))}), - self); - - _imgui_end_child(IMGUI_SPRITESHEET_CHILD, self); - ImGui::PopID(); - }; - - for (auto& [id, spritesheet] : self->anm2->spritesheets) - spritesheet_draw(id, spritesheet); - - _imgui_end_child(IMGUI_SPRITESHEETS_CHILD, self); - - _imgui_begin_child(IMGUI_SPRITESHEETS_FOOTER_CHILD.copy({.size = footerSize}), self); - - if (_imgui_button(IMGUI_SPRITESHEET_ADD.copy({.isDisabled = self->anm2->path.empty()}), self)) - dialog_spritesheet_add(self->dialog); - - if (self->dialog->isSelected && self->dialog->type == DIALOG_SPRITESHEET_ADD) { - _imgui_spritesheet_add(self, self->dialog->path); - dialog_reset(self->dialog); - } - - if (_imgui_button(IMGUI_SPRITESHEETS_RELOAD.copy({.isDisabled = self->selectedSpritesheetIDs.empty()}), self)) { - for (auto& id : self->selectedSpritesheetIDs) { - WorkingDirectory workingDirectory(self->anm2->path); - Texture texture; - texture_from_path_init(&texture, self->anm2->spritesheets[id].path); - self->anm2->spritesheets[id].texture = texture; - } - imgui_log_push(self, IMGUI_LOG_RELOAD_SPRITESHEET); - } - - if (_imgui_button(IMGUI_SPRITESHEETS_REPLACE.copy({.isDisabled = self->selectedSpritesheetIDs.size() != 1}), self)) - dialog_spritesheet_replace(self->dialog, *self->selectedSpritesheetIDs.begin()); - - if (self->dialog->isSelected && self->dialog->type == DIALOG_SPRITESHEET_REPLACE) { - - imgui_snapshot(self, IMGUI_ACTION_REPLACE_SPRITESHEET); - - WorkingDirectory workingDirectory(self->anm2->path); - std::string anm2WorkingPath = working_directory_from_file_set(self->anm2->path); - std::string spritesheetPath = std::filesystem::relative(self->dialog->path, anm2WorkingPath).string(); - self->anm2->spritesheets[self->dialog->replaceID].path = spritesheetPath; - Texture texture; - texture_from_path_init(&texture, spritesheetPath); - self->anm2->spritesheets[self->dialog->replaceID].texture = texture; - imgui_log_push(self, std::format(IMGUI_LOG_REPLACE_SPRITESHEET, self->dialog->replaceID, spritesheetPath)); - dialog_reset(self->dialog); - } - - std::unordered_set spritesheetIDs = map_keys_to_set(self->anm2->spritesheets); - - std::unordered_set usedSpritesheetIDs; - for (auto& [layerID, layer] : self->anm2->layers) - usedSpritesheetIDs.insert(layer.spritesheetID); - - std::unordered_set unusedSpritesheetIDs = set_symmetric_difference(spritesheetIDs, usedSpritesheetIDs); - - if (_imgui_button(IMGUI_SPRITESHEETS_REMOVE_UNUSED.copy({.isDisabled = unusedSpritesheetIDs.empty()}), self)) { - for (auto& id : unusedSpritesheetIDs) { - texture_free(&self->anm2->spritesheets[id].texture); - self->anm2->spritesheets.erase(id); - } - imgui_log_push(self, IMGUI_LOG_REMOVE_UNUSED_SPRITESHEETS); - } - - if (_imgui_button(IMGUI_SPRITESHEETS_SELECT_ALL.copy({.isDisabled = self->selectedSpritesheetIDs.size() == self->anm2->spritesheets.size()}), self)) - for (auto [id, _] : self->anm2->spritesheets) - self->selectedSpritesheetIDs.insert(id); - - if (_imgui_button(IMGUI_SPRITESHEETS_SELECT_NONE.copy({.isDisabled = self->selectedSpritesheetIDs.empty()}), self)) - self->selectedSpritesheetIDs.clear(); - - if (_imgui_button(IMGUI_SPRITESHEET_SAVE.copy({.isDisabled = self->selectedSpritesheetIDs.empty()}), self)) { - for (auto& id : self->selectedSpritesheetIDs) { - WorkingDirectory workingDirectory(self->anm2->path); - Anm2Spritesheet& spritesheet = self->anm2->spritesheets[id]; - texture_from_gl_write(&spritesheet.texture, spritesheet.path); - imgui_log_push(self, std::format(IMGUI_LOG_SPRITESHEET_SAVE_FORMAT, id, spritesheet.path)); - } - } - - _imgui_end_child(IMGUI_SPRITESHEETS_FOOTER_CHILD, self); - _imgui_end(IMGUI_SPRITESHEETS, self); -} - -/* -static void _imgui_animation_preview(Imgui* self) { - static int& tool = self->settings->tool; - static float& zoom = self->settings->previewZoom; - static vec2& pan = self->settings->previewPan; - static ivec2& size = self->preview->canvas.size; - static vec2 mousePos{}; - - std::string mousePositionString = std::format(IMGUI_POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y); - - IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATION_PREVIEW); - - _imgui_begin_child(IMGUI_CANVAS_GRID_CHILD, self); - _imgui_checkbox(IMGUI_CANVAS_GRID, self, self->settings->previewIsGrid); - ImGui::SameLine(); - _imgui_color_edit4(IMGUI_CANVAS_GRID_COLOR, self, self->settings->previewGridColor); - _imgui_input_int2(IMGUI_CANVAS_GRID_SIZE, self, self->settings->previewGridSize); - _imgui_input_int2(IMGUI_CANVAS_GRID_OFFSET, self, self->settings->previewGridOffset); - _imgui_end_child(); // IMGUI_CANVAS_GRID_CHILD - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_VIEW_CHILD, self); - _imgui_drag_float(IMGUI_CANVAS_ZOOM, self, zoom); - if (_imgui_button(IMGUI_ANIMATION_PREVIEW_CENTER_VIEW.copy({.isDisabled = pan == vec2()}), self)) - pan = vec2(); - if (_imgui_button(IMGUI_ANIMATION_PREVIEW_FIT.copy({.isDisabled = self->reference->animationID == ID_NONE}), self)) { - vec4 rect = anm2_animation_rect_get(self->anm2, *self->reference, self->settings->previewIsRootTransform); - - if (rect != vec4(-1.0f) && (rect.z > 0 && rect.w > 0)) { - float scaleX = self->preview->canvas.size.x / rect.z; - float scaleY = self->preview->canvas.size.y / rect.w; - float fitScale = std::min(scaleX, scaleY); - - zoom = UNIT_TO_PERCENT(fitScale); - - vec2 rectCenter = {rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f}; - pan = -rectCenter * fitScale; - } - } - ImGui::Text("%s", mousePositionString.c_str()); - _imgui_end_child(); // IMGUI_CANVAS_VIEW_CHILD - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_VISUAL_CHILD, self); - _imgui_color_edit4(IMGUI_CANVAS_BACKGROUND_COLOR, self, self->settings->previewBackgroundColor); - - std::vector animationIndices; - ImguiItem animationOverlayItem = IMGUI_CANVAS_ANIMATION_OVERLAY; - - animationIndices.emplace_back(ID_NONE); - animationOverlayItem.items.emplace_back(IMGUI_NONE); - - for (auto& [id, animation] : self->anm2->animations) { - animationIndices.emplace_back(id); - animationOverlayItem.items.emplace_back(animation.name); - } - - int animationIndex = 0; - - if (self->preview->animationOverlayID != ID_NONE) - animationIndex = std::find(animationIndices.begin(), animationIndices.end(), self->preview->animationOverlayID) - animationIndices.begin(); - - if (_imgui_combo(animationOverlayItem, self, &animationIndex)) - self->preview->animationOverlayID = animationIndices[animationIndex]; - - _imgui_drag_float(IMGUI_CANVAS_ANIMATION_OVERLAY_TRANSPARENCY, self, self->settings->previewOverlayTransparency); - _imgui_end_child(); // IMGUI_CANVAS_VISUAL_CHILD - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_HELPER_CHILD, self); - _imgui_checkbox(IMGUI_CANVAS_AXES, self, self->settings->previewIsAxes); - ImGui::SameLine(); - _imgui_color_edit4(IMGUI_CANVAS_AXES_COLOR, self, self->settings->previewAxesColor); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_ALT_ICONS, self, self->settings->previewIsAltIcons); - _imgui_checkbox(IMGUI_CANVAS_ROOT_TRANSFORM, self, self->settings->previewIsRootTransform); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_TRIGGERS, self, self->settings->previewIsTriggers); - _imgui_checkbox(IMGUI_CANVAS_PIVOTS, self, self->settings->previewIsPivots); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_ICONS, self, self->settings->previewIsIcons); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_BORDER, self, self->settings->previewIsBorder); - _imgui_end_child(); // IMGUI_CANVAS_HELPER_CHILD - - ImVec2 previewCursorScreenPos = ImGui::GetCursorScreenPos(); - - if (!self->preview->isRender) - size = ivec2(vec2(ImGui::GetContentRegionAvail())); - - preview_draw(self->preview); - ImGui::Image(self->preview->canvas.framebuffer, vec2(size)); - - if (self->settings->previewIsTriggers) { - Anm2Frame trigger; - anm2_frame_from_time(self->anm2, &trigger, {self->reference->animationID, ANM2_TRIGGER}, self->preview->time); - - if (trigger.eventID != ID_NONE) { - ImVec2 textPos = previewCursorScreenPos + ImGui::GetStyle().ItemSpacing; - ImGui::PushFont(NULL, ImGui::GetStyle().FontSizeBase * IMGUI_TRIGGERS_FONT_SCALE); - ImGui::GetWindowDrawList()->AddText(textPos, IMGUI_TRIGGERS_EVENT_COLOR, self->anm2->events[trigger.eventID].name.c_str()); - ImGui::PopFont(); - } - } - - if (ImGui::IsItemHovered()) { - self->pendingCursor = TOOL_CURSORS[tool]; - imgui_keyboard_nav_disable(); - } else { - _imgui_end(); // IMGUI_ANIMATION_EDITOR - imgui_keyboard_nav_enable(); - return; - } - - _imgui_end(); // IMGUI_ANIMATION_PREVIEW - - mousePos = vec2(ImGui::GetMousePos() - previewCursorScreenPos - pan - (vec2(size) * 0.5f)) / PERCENT_TO_UNIT(zoom); - - const bool isLeft = ImGui::IsKeyPressed(IMGUI_INPUT_LEFT); - const bool isRight = ImGui::IsKeyPressed(IMGUI_INPUT_RIGHT); - const bool isUp = ImGui::IsKeyPressed(IMGUI_INPUT_UP); - const bool isDown = ImGui::IsKeyPressed(IMGUI_INPUT_DOWN); - const bool isMod = ImGui::IsKeyDown(IMGUI_INPUT_SHIFT); - const bool isZoomIn = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_IN]); - const bool isZoomOut = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_OUT]); - const bool isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); - const bool isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); - const bool isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); - const ImVec2 mouseDelta = ImGui::GetIO().MouseDelta; - const float mouseWheel = ImGui::GetIO().MouseWheel; - - Anm2Frame* frame = nullptr; - - if (self->reference->itemType != ANM2_TRIGGER) - frame = anm2_frame_from_reference(self->anm2, *self->reference); - - float step = isMod ? TOOL_STEP_MOD : TOOL_STEP; - - if ((tool == TOOL_PAN && isMouseDown) || isMouseMiddleDown) - pan += vec2(mouseDelta.x, mouseDelta.y); - - switch (tool) { - case TOOL_MOVE: - if (!frame) - break; - - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_MOVE); - - if (isMouseDown) - frame->position = vec2(mousePos); - else { - if (isLeft) - frame->position.x -= step; - if (isRight) - frame->position.x += step; - if (isUp) - frame->position.y -= step; - if (isDown) - frame->position.y += step; - } - break; - case TOOL_ROTATE: - if (!frame) - break; - - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_ROTATE); - - if (isMouseDown) - frame->rotation += mouseDelta.x; - else { - if (isLeft || isUp) - frame->rotation -= step; - if (isRight || isDown) - frame->rotation += step; - } - break; - case TOOL_SCALE: - if (!frame) - break; - - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_SCALE); - - if (isMouseDown) - frame->scale += vec2(mouseDelta.x, mouseDelta.y); - else { - if (isLeft) - frame->scale.x -= step; - if (isRight) - frame->scale.x += step; - if (isUp) - frame->scale.y -= step; - if (isDown) - frame->scale.y += step; - } - break; - default: - break; - } - - if (mouseWheel != 0 || isZoomIn || isZoomOut) { - float delta = (mouseWheel > 0 || isZoomIn) ? CANVAS_ZOOM_STEP : -CANVAS_ZOOM_STEP; - zoom = std::clamp(ROUND_NEAREST_MULTIPLE(zoom + delta, CANVAS_ZOOM_STEP), CANVAS_ZOOM_MIN, CANVAS_ZOOM_MAX); - } -} - -static void _imgui_spritesheet_editor(Imgui* self) { - static vec2 mousePos = {0, 0}; - static int& tool = self->settings->tool; - static vec4& toolColor = self->settings->toolColor; - static ivec2& gridSize = self->settings->editorGridSize; - static ivec2& gridOffset = self->settings->editorGridOffset; - static vec2& pan = self->settings->editorPan; - static float& zoom = self->settings->editorZoom; - static ivec2& size = self->editor->canvas.size; - - std::string mousePositionString = std::format(IMGUI_POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y); - - IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEET_EDITOR); - - _imgui_begin_child(IMGUI_CANVAS_GRID_CHILD, self); - _imgui_checkbox(IMGUI_CANVAS_GRID, self, self->settings->editorIsGrid); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_GRID_SNAP, self, self->settings->editorIsGridSnap); - ImGui::SameLine(); - _imgui_color_edit4(IMGUI_CANVAS_GRID_COLOR, self, self->settings->editorGridColor); - _imgui_input_int2(IMGUI_CANVAS_GRID_SIZE, self, gridSize); - _imgui_input_int2(IMGUI_CANVAS_GRID_OFFSET, self, gridOffset); - _imgui_end_child(); - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_VIEW_CHILD, self); - _imgui_drag_float(IMGUI_CANVAS_ZOOM, self, zoom); - if (_imgui_button(IMGUI_SPRITESHEET_EDITOR_CENTER_VIEW.copy({.isDisabled = pan == vec2()}), self)) - pan = vec2(); - if (_imgui_button(IMGUI_SPRITESHEET_EDITOR_FIT.copy({.isDisabled = self->editor->spritesheetID == ID_NONE}), self)) { - vec4 rect = {0, 0, self->anm2->spritesheets[self->editor->spritesheetID].texture.size.x, - self->anm2->spritesheets[self->editor->spritesheetID].texture.size.y}; - - if ((rect.z > 0 && rect.w > 0)) { - float scaleX = self->editor->canvas.size.x / rect.z; - float scaleY = self->editor->canvas.size.y / rect.w; - float fitScale = std::min(scaleX, scaleY); - - zoom = UNIT_TO_PERCENT(fitScale); - pan = {}; - } - } - ImGui::Text("%s", mousePositionString.c_str()); - _imgui_end_child(); // IMGUI_CANVAS_VIEW_CHILD - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_VISUAL_CHILD, self); - _imgui_color_edit4(IMGUI_CANVAS_BACKGROUND_COLOR, self, self->settings->editorBackgroundColor); - _imgui_checkbox(IMGUI_CANVAS_BORDER, self, self->settings->editorIsBorder); - _imgui_end_child(); // IMGUI_CANVAS_VISUAL_CHILD - - ImVec2 editorCursorScreenPos = ImGui::GetCursorScreenPos(); - size = ivec2(vec2(ImGui::GetContentRegionAvail())); - editor_draw(self->editor); - ImGui::Image(self->editor->canvas.framebuffer, vec2(size)); - - if (ImGui::IsItemHovered()) { - self->pendingCursor = TOOL_CURSORS[tool]; - imgui_keyboard_nav_disable(); - } else { - _imgui_end(); // IMGUI_SPRITESHEET_EDITOR - imgui_keyboard_nav_enable(); - return; - } - - _imgui_end(); // IMGUI_SPRITESHEET_EDITOR - - mousePos = vec2(ImGui::GetMousePos() - editorCursorScreenPos - pan) / PERCENT_TO_UNIT(zoom); - - const bool isLeft = ImGui::IsKeyPressed(IMGUI_INPUT_LEFT); - const bool isRight = ImGui::IsKeyPressed(IMGUI_INPUT_RIGHT); - const bool isUp = ImGui::IsKeyPressed(IMGUI_INPUT_UP); - const bool isDown = ImGui::IsKeyPressed(IMGUI_INPUT_DOWN); - const bool isShift = ImGui::IsKeyDown(IMGUI_INPUT_SHIFT); - const bool isCtrl = ImGui::IsKeyDown(IMGUI_INPUT_CTRL); - const bool isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); - const bool isMouseRightClick = ImGui::IsMouseClicked(ImGuiMouseButton_Right); - const bool isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); - const bool isMouseRightDown = ImGui::IsMouseDown(ImGuiMouseButton_Right); - const bool isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); - const bool isZoomIn = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_IN]); - const bool isZoomOut = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_OUT]); - const float mouseWheel = ImGui::GetIO().MouseWheel; - const ImVec2 mouseDelta = ImGui::GetIO().MouseDelta; - - Anm2Frame* frame = nullptr; - if (self->reference->itemType == ANM2_LAYER) - frame = anm2_frame_from_reference(self->anm2, *self->reference); - - Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->editor->spritesheetID); - Texture* texture = spritesheet ? &spritesheet->texture : nullptr; - - vec2 position = mousePos; - float step = isShift ? TOOL_STEP_MOD : TOOL_STEP; - - if ((tool == TOOL_PAN && isMouseDown) || isMouseMiddleDown) - pan += vec2(mouseDelta.x, mouseDelta.y); - - auto spritesheet_editor_move = [&](bool isPrimary = true) { - bool isActivated = isPrimary ? isMouseClick || isLeft || isRight || isUp || isDown : isMouseRightClick; - bool isUseMouseDown = isPrimary ? isMouseDown : isMouseRightDown; - - if (isActivated) - imgui_snapshot(self, IMGUI_ACTION_MOVE); - - if (isUseMouseDown) - frame->pivot = position - frame->crop; - else if (isPrimary) { - if (isLeft) - frame->pivot.x -= step; - if (isRight) - frame->pivot.x += step; - if (isUp) - frame->pivot.y -= step; - if (isDown) - frame->pivot.y += step; - } - }; - - auto spritesheet_editor_crop = [&](bool isPrimary = true) { - bool isActivated = isPrimary ? isMouseClick || isLeft || isRight || isUp || isDown : isMouseRightClick; - bool isUseMouseClick = isPrimary ? isMouseClick : isMouseRightClick; - bool isUseMouseDown = isPrimary ? isMouseDown : isMouseRightDown; - - vec2 cropPosition = self->settings->editorIsGridSnap ? vec2(roundf(position.x / gridSize.x) * gridSize.x + gridOffset.x - (gridSize.x * 0.5f), - roundf(position.y / gridSize.y) * gridSize.y + gridOffset.y - (gridSize.y * 0.5f)) - : position; - - if (isActivated) - imgui_snapshot(self, IMGUI_ACTION_MOVE); - - if (isUseMouseClick) { - frame->crop = cropPosition; - frame->size = ivec2(); - } else if (isUseMouseDown) - frame->size = position - frame->crop; - else if (isPrimary) { - if (isCtrl) { - if (isLeft) - frame->crop.x -= step; - if (isRight) - frame->crop.x += step; - if (isUp) - frame->crop.y -= step; - if (isDown) - frame->crop.y += step; - } else { - if (isLeft) - frame->size.x -= step; - if (isRight) - frame->size.x += step; - if (isUp) - frame->size.y -= step; - if (isDown) - frame->size.y += step; - } - - frame->size.x = std::max({}, frame->size.x); - frame->size.y = std::max({}, frame->size.y); - } - }; - - auto spritesheet_editor_draw = [&](vec4 color) { - if (isMouseClick || isMouseRightClick) - imgui_snapshot(self, color != vec4() ? IMGUI_ACTION_DRAW : IMGUI_ACTION_ERASE); - - if (isMouseDown || isMouseRightDown) - texture_pixel_set(texture, position, color); - }; - - switch (tool) { - case TOOL_MOVE: - if (!texture || !frame) - break; - spritesheet_editor_move(true); - spritesheet_editor_crop(false); - break; - case TOOL_CROP: - if (!texture || !frame) - break; - spritesheet_editor_crop(true); - spritesheet_editor_move(false); - break; - case TOOL_DRAW: - case TOOL_ERASE: - if (!texture) - break; - spritesheet_editor_draw(tool == TOOL_DRAW && !isMouseRightDown ? self->settings->toolColor : vec4()); - break; - case TOOL_COLOR_PICKER: - if (isMouseDown) { - SDL_GetMouseState(&mousePos.x, &mousePos.y); - - ImGuiIO& io = ImGui::GetIO(); - ivec2 fbPosition = {(int)(position.x * io.DisplayFramebufferScale.x), (int)(position.y * io.DisplayFramebufferScale.y)}; - ivec2 size{}; - SDL_GetWindowSizeInPixels(self, &size.x, &size.y); - - if (fbPosition.x < 0 || fbPosition.y < 0 || fbPosition.x >= size.x || fbPosition.y >= size.y) - return false; - - uint8_t rgba[4]; - - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(fbPosition.x, size.y - 1 - fbPosition.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba); - - color = vec4(UINT8_TO_FLOAT(rgba[0]), UINT8_TO_FLOAT(rgba[1]), UINT8_TO_FLOAT(rgba[2]), UINT8_TO_FLOAT(rgba[3])); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); - ImGui::BeginTooltip(); - _imgui_color_button(IMGUI_COLOR_PICKER_BUTTON, self, toolColor); - ImGui::EndTooltip(); - ImGui::PopStyleVar(); - } - break; - default: - break; - } - - if (mouseWheel != 0 || isZoomIn || isZoomOut) { - float delta = (mouseWheel > 0 || isZoomIn) ? CANVAS_ZOOM_STEP : -CANVAS_ZOOM_STEP; - zoom = std::clamp(ROUND_NEAREST_MULTIPLE(zoom + delta, CANVAS_ZOOM_STEP), CANVAS_ZOOM_MIN, CANVAS_ZOOM_MAX); - } -} -*/ - -static void _imgui_frame_properties(Imgui* self) { - IMGUI_BEGIN_OR_RETURN(IMGUI_FRAME_PROPERTIES, self); - _imgui_no_anm2_path_click_check(self); - - Anm2Type type = self->reference->itemType; - Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *self->reference); - - bool isLayerFrame = frame && type == ANM2_LAYER; - - if (!frame || type != ANM2_TRIGGER) { - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_CROP.copy({.isDisabled = !isLayerFrame}), self, !isLayerFrame ? dummy_value() : frame->crop); - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_SIZE.copy({.isDisabled = !isLayerFrame}), self, !isLayerFrame ? dummy_value() : frame->size); - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_POSITION.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->position); - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_PIVOT.copy({.isDisabled = !isLayerFrame}), self, !isLayerFrame ? dummy_value() : frame->pivot); - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_SCALE.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->scale); - _imgui_drag_float(IMGUI_FRAME_PROPERTIES_ROTATION.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->rotation); - _imgui_input_int(IMGUI_FRAME_PROPERTIES_DELAY.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->delay); - _imgui_color_edit4(IMGUI_FRAME_PROPERTIES_TINT.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->tintRGBA); - _imgui_color_edit3(IMGUI_FRAME_PROPERTIES_COLOR_OFFSET.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->offsetRGB); - _imgui_checkbox(IMGUI_FRAME_PROPERTIES_VISIBLE.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->isVisible); - _imgui_checkbox(IMGUI_FRAME_PROPERTIES_INTERPOLATED.copy({.isDisabled = !frame}), self, !frame ? dummy_value() : frame->isInterpolated); - _imgui_checkbox(IMGUI_FRAME_PROPERTIES_ROUND.copy({.isDisabled = !frame}), self, self->settings->propertiesIsRound); - if (_imgui_button(IMGUI_FRAME_PROPERTIES_FLIP_X.copy({.isDisabled = !frame}), self)) - frame->scale.x = -frame->scale.x; - if (_imgui_button(IMGUI_FRAME_PROPERTIES_FLIP_Y.copy({.isDisabled = !frame}), self)) - frame->scale.y = -frame->scale.y; - - if (self->settings->propertiesIsRound && frame) { - frame->position = glm::trunc(frame->position); - frame->pivot = glm::trunc(frame->pivot); - frame->crop = glm::trunc(frame->crop); - frame->scale = glm::trunc(frame->scale); - frame->rotation = glm::trunc(frame->rotation); - } - } else { - ImguiItem eventItem = IMGUI_FRAME_PROPERTIES_EVENT.copy({.isDisabled = !frame}); - - eventItem.items[ID_NONE] = IMGUI_NONE; - - for (auto& [id, event] : self->anm2->events) - eventItem.items[id] = event.name; - - _imgui_combo(eventItem, self, frame->eventID); - _imgui_input_int(IMGUI_FRAME_PROPERTIES_AT_FRAME.copy({.isDisabled = !frame}), self, frame->atFrame); - } - - _imgui_end(IMGUI_FRAME_PROPERTIES, self); -} - -static void _imgui_log(Imgui* self) { - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle& style = ImGui::GetStyle(); - ImVec4 borderColor = style.Colors[ImGuiCol_Border]; - ImVec4 textColor = style.Colors[ImGuiCol_Text]; - float itemSpacingHeight = ImGui::GetStyle().ItemSpacing.y; - - ImVec2 position = {io.DisplaySize.x - itemSpacingHeight, io.DisplaySize.y - itemSpacingHeight}; - - for (int i = (int)self->log.size() - 1; i >= 0; --i) { - ImguiLogItem& item = self->log[i]; - float lifetime = item.timeRemaining / IMGUI_LOG_DURATION; - borderColor.w = lifetime; - textColor.w = lifetime; - - item.timeRemaining -= io.DeltaTime; - - if (item.timeRemaining <= 0.0f) { - self->log.erase(self->log.begin() + i); - continue; - } - - ImGui::SetNextWindowPos(position, ImGuiCond_Always, {1.0f, 1.0f}); - ImGui::PushStyleColor(ImGuiCol_Border, borderColor); - ImGui::PushStyleColor(ImGuiCol_Text, textColor); - ImGui::SetNextWindowBgAlpha(lifetime); - - ImguiItem logItem = IMGUI_LOG_WINDOW.copy({.label = std::format(IMGUI_LOG_FORMAT, i)}); - _imgui_begin(logItem, self); - ImGui::TextUnformatted(item.text.c_str()); - ImVec2 windowSize = ImGui::GetWindowSize(); - _imgui_end(logItem, self); // IMGUI_LOG_WINDOW - - ImGui::PopStyleColor(2); - - position.y -= windowSize.y + ImGui::GetStyle().ItemSpacing.y; - } -} - -static void _imgui_dock(Imgui* self) { - ImGuiViewport* viewport = ImGui::GetMainViewport(); - - float windowOffset = IMGUI_TASKBAR.size->y * self->settings->displayScale; - vec2 windowPosition = {viewport->Pos.x, viewport->Pos.y + windowOffset}; - vec2 windowSize = {viewport->Size.x, viewport->Size.y - windowOffset}; - - ImGui::SetNextWindowPos(windowPosition); - ImGui::SetNextWindowSize(windowSize); - ImGui::SetNextWindowViewport(viewport->ID); - - _imgui_begin(IMGUI_WINDOW_MAIN, self); - _imgui_dockspace(IMGUI_DOCKSPACE_MAIN, self); - - _imgui_tools(self); - _imgui_animations(self); - _imgui_events(self); - _imgui_spritesheets(self); - //_imgui_animation_preview(self); - //_imgui_spritesheet_editor(self); - _imgui_layers(self); - _imgui_nulls(self); - //_imgui_timeline(self); - _imgui_onionskin(self); - _imgui_frame_properties(self); - - _imgui_end(IMGUI_WINDOW_MAIN, self); -} - -void imgui_init(Imgui* self, Dialog* dialog, Resources* resources, Anm2* anm2, Anm2Reference* reference, Editor* editor, Preview* preview, - GeneratePreview* generatePreview, Settings* settings, Snapshots* snapshots, Clipboard* clipboard, SDL_Window* window, - SDL_GLContext* glContext) { - - self->dialog = dialog; - self->resources = resources; - self->anm2 = anm2; - self->reference = reference; - self->editor = editor; - self->preview = preview; - self->generatePreview = generatePreview; - self->settings = settings; - self->snapshots = snapshots; - self->clipboard = clipboard; - self->window = window; - self->glContext = glContext; - - self->saveAnm2 = *anm2; - - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGui::StyleColorsDark(); - - log_info(std::format(IMGUI_LOG_INIT, ImGui::GetVersion())); - - ImGui_ImplSDL3_InitForOpenGL(self->window, *self->glContext); - ImGui_ImplOpenGL3_Init(IMGUI_OPENGL_VERSION); - - ImGuiIO& io = ImGui::GetIO(); - io.IniFilename = nullptr; - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; - io.ConfigWindowsMoveFromTitleBarOnly = true; - - ImGui::GetStyle().FontScaleMain = self->settings->displayScale; - ImFontConfig config; - config.FontDataOwnedByAtlas = false; - - for (auto [i, font] : std::views::enumerate(FONTS)) - self->fonts[i] = io.Fonts->AddFontFromMemoryTTF((void*)font.data, font.length, FONT_SIZE, &config); - - imgui_keyboard_nav_enable(); - - ImGui::LoadIniSettingsFromDisk(settings_path_get().c_str()); - - for (int i = 0; i < HOTKEY_COUNT; i++) { - if (!SETTINGS_HOTKEY_MEMBERS[i]) - continue; - imgui_hotkey_chord_registry()[i] = imgui_chord_from_string_get(*&(self->settings->*SETTINGS_HOTKEY_MEMBERS[i])); - } - - self->style = ImGui::GetStyle(); -} - -void imgui_update(Imgui* self) { - ImGui_ImplSDL3_NewFrame(); - ImGui_ImplOpenGL3_NewFrame(); - ImGui::NewFrame(); - - _imgui_taskbar(self); - _imgui_dock(self); - _imgui_log(self); - - if (self->isContextualActionsEnabled) { - for (const auto& item : imgui_item_registry()) { - if (!item->is_chord() || !_imgui_chord_pressed(item->chord_get())) - continue; - if (item->isAllowHotkeyWhenFocusWindow && !_imgui_is_focus_window(*item->focusWindow)) - continue; - if (!item->isAllowHotkeyWhenFocusWindow && item->focusWindow.has_value()) - continue; - if (item->snapshotAction) - imgui_snapshot(self, *item->snapshotAction); - if (item->function) - item->function(self); - } - } - - imgui_contextual_actions_enable(self); - - if (self->pendingCursor != self->cursor) { - SDL_SetCursor(SDL_CreateSystemCursor(self->pendingCursor)); - self->cursor = self->pendingCursor; - } - - self->pendingCursor = CURSOR_DEFAULT; - - SDL_Event event; - - while (SDL_PollEvent(&event)) { - ImGui_ImplSDL3_ProcessEvent(&event); - - switch (event.type) { - case SDL_EVENT_DROP_FILE: { - const char* droppedFile = event.drop.data; - - if (path_is_extension(droppedFile, ANM2_EXTENSION)) - _imgui_anm2_open(self, droppedFile); - else if (path_is_extension(droppedFile, ANM2_SPRITESHEET_EXTENSION)) { - if (self->anm2->path.empty()) { - _imgui_no_anm2_path_check(self); - break; - } - _imgui_spritesheet_add(self, droppedFile); - } else - imgui_log_push(self, IMGUI_LOG_DRAG_DROP_ERROR); - - break; - } - case SDL_EVENT_QUIT: - if (self->isTryQuit) - self->isQuit = true; - else - imgui_quit(self); - break; - default: - break; - } - } - - _imgui_confirm_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION, self, nullptr, true); -} - -void imgui_draw(void) { - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); -} - -void imgui_free(void) { - if (!ImGui::GetCurrentContext()) - return; - - log_info(IMGUI_LOG_FREE); - ImGui_ImplSDL3_Shutdown(); - ImGui_ImplOpenGL3_Shutdown(); - ImGui::SaveIniSettingsToDisk(settings_path_get().c_str()); - ImGui::DestroyContext(); -} \ No newline at end of file diff --git a/src/imgui.h b/src/imgui.h index fe07d95..11f9d71 100644 --- a/src/imgui.h +++ b/src/imgui.h @@ -1,1684 +1,138 @@ #pragma once -#include "canvas.h" -#include "clipboard.h" -#include "dialog.h" -#include "editor.h" -#include "ffmpeg.h" -#include "generate_preview.h" -#include "preview.h" -#include "resources.h" -#include "settings.h" -#include "snapshots.h" -#include "tool.h" -#include "window.h" -#include - -#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM -#define IM_VEC2_CLASS_EXTRA \ - inline bool operator==(const ImVec2& rhs) const { return x == rhs.x && y == rhs.y; } \ - inline bool operator!=(const ImVec2& rhs) const { return !(*this == rhs); } \ - inline ImVec2 operator+(const ImVec2& rhs) const { return ImVec2(x + rhs.x, y + rhs.y); } \ - inline ImVec2 operator-(const ImVec2& rhs) const { return ImVec2(x - rhs.x, y - rhs.y); } \ - inline ImVec2 operator*(const ImVec2& rhs) const { return ImVec2(x * rhs.x, y * rhs.y); } \ - inline ImVec2 operator*(float s) const { return ImVec2(x * s, y * s); } \ - friend inline ImVec2 operator*(float s, const ImVec2& v) { return ImVec2(v.x * s, v.y * s); } \ - inline ImVec2& operator+=(const ImVec2& rhs) { \ - x += rhs.x; \ - y += rhs.y; \ - return *this; \ - } \ - inline ImVec2& operator-=(const ImVec2& rhs) { \ - x -= rhs.x; \ - y -= rhs.y; \ - return *this; \ - } \ - inline ImVec2& operator*=(float s) { \ - x *= s; \ - y *= s; \ - return *this; \ - } \ - inline ImVec2(const vec2& v) : x(v.x), y(v.y) {} \ - inline operator vec2() const { return vec2(x, y); } - -#define IM_VEC4_CLASS_EXTRA \ - inline bool operator==(const ImVec4& rhs) const { return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; } \ - inline bool operator!=(const ImVec4& rhs) const { return !(*this == rhs); } \ - inline ImVec4 operator+(const ImVec4& rhs) const { return ImVec4(x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w); } \ - inline ImVec4 operator-(const ImVec4& rhs) const { return ImVec4(x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w); } \ - inline ImVec4 operator*(const ImVec4& rhs) const { return ImVec4(x * rhs.x, y * rhs.y, z * rhs.z, w * rhs.w); } \ - inline ImVec4 operator*(float s) const { return ImVec4(x * s, y * s, z * s, w * s); } \ - friend inline ImVec4 operator*(float s, const ImVec4& v) { return ImVec4(v.x * s, v.y * s, v.z * s, v.w * s); } \ - inline ImVec4& operator+=(const ImVec4& rhs) { \ - x += rhs.x; \ - y += rhs.y; \ - z += rhs.z; \ - w += rhs.w; \ - return *this; \ - } \ - inline ImVec4& operator-=(const ImVec4& rhs) { \ - x -= rhs.x; \ - y -= rhs.y; \ - z -= rhs.z; \ - w -= rhs.w; \ - return *this; \ - } \ - inline ImVec4& operator*=(float s) { \ - x *= s; \ - y *= s; \ - z *= s; \ - w *= s; \ - return *this; \ - } \ - inline ImVec4(const vec4& v) : x(v.x), y(v.y), z(v.z), w(v.w) {} \ - inline operator vec4() const { return vec4(x, y, z, w); } - -#include -#include #include -#include - -#define IMGUI_CHORD_NONE (ImGuiMod_None) -#define IMGUI_FRAME_BORDER 2.0f -#define IMGUI_LOG_DURATION 3.0f -#define IMGUI_TEXT_HEIGHT_PADDING 4.0f -#define IMGUI_PLAYHEAD_LINE_COLOR IM_COL32(UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX) -#define IMGUI_TRIGGERS_EVENT_COLOR IM_COL32(UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, 128) -#define IMGUI_PLAYHEAD_LINE_WIDTH 2.0f -#define IMGUI_TIMELINE_FRAME_MULTIPLE 5 -#define IMGUI_TIMELINE_MERGE -#define IMGUI_TOOL_COLOR_PICKER_DURATION 0.25f -#define IMGUI_CONFIRM_POPUP_ROW_COUNT 2 -#define IMGUI_CHORD_REPEAT_TIME 0.25f - -#define IMGUI_ACTION_FRAME_CROP "Frame Crop" -#define IMGUI_ACTION_FRAME_MOVE "Frame Move" - -#define IMGUI_ACTION_ANIMATION_MOVE "Move Animation" -#define IMGUI_ACTION_TRIGGER_MOVE "Trigger At Frame" -#define IMGUI_ACTION_ITEM_SWAP "Item Swap" -#define IMGUI_ACTION_FRAME_DELAY "Frame Delay" -#define IMGUI_ACTION_DRAW "Draw" -#define IMGUI_ACTION_ERASE "Erase" -#define IMGUI_ACTION_MOVE "Move" -#define IMGUI_ACTION_SCALE "Scale" -#define IMGUI_ACTION_ROTATE "Rotate" -#define IMGUI_ACTION_CROP "Crop" -#define IMGUI_ACTION_ADD_SPRITESHEET "Add Spritesheet" -#define IMGUI_ACTION_REPLACE_SPRITESHEET "Replace Spritesheet" -#define IMGUI_ACTION_SPRITESHEET_SWAP "Spritesheet Swap" -#define IMGUI_ACTION_OPEN_FILE "Open File" - -#define IMGUI_SET_ITEM_PROPERTIES_POPUP "Item Properties" -#define IMGUI_POPUP_FLAGS ImGuiWindowFlags_NoMove -#define IMGUI_POPUP_MODAL_FLAGS ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize - -#define IMGUI_LOG_INIT "Initialized ImGui {}" -#define IMGUI_LOG_FREE "Freed ImGui" - -#define IMGUI_LOG_NO_ANM2_PATH "Please save the .anm2 to a path first!" -#define IMGUI_LOG_FILE_OPEN_FORMAT "Opened anm2: {}" -#define IMGUI_LOG_FILE_SAVE_FORMAT "Saved anm2 to: {}" -#define IMGUI_LOG_SPRITESHEET_RELOAD "Reloaded selected spritesheets" -#define IMGUI_LOG_RENDER_ANIMATION_FRAMES_SAVE_FORMAT "Saved rendered frames to: {}" -#define IMGUI_LOG_RENDER_ANIMATION_SAVE_FORMAT "Saved rendered animation to: {}" -#define IMGUI_LOG_RENDER_ANIMATION_NO_ANIMATION_ERROR "No animation selected; rendering cancelled." -#define IMGUI_LOG_RENDER_ANIMATION_NO_FRAMES_ERROR "No frames to render; rendering cancelled." -#define IMGUI_LOG_RENDER_ANIMATION_DIRECTORY_ERROR "Invalid directory! Make sure it exists and you have write permissions." -#define IMGUI_LOG_RENDER_ANIMATION_PATH_ERROR "Invalid path! Make sure it's valid and you have write permissions." -#define IMGUI_LOG_RENDER_ANIMATION_FFMPEG_PATH_ERROR \ - "Invalid FFmpeg path! Make sure you have it installed and the path is " \ - "correct." -#define IMGUI_LOG_RENDER_ANIMATION_FFMPEG_ERROR \ - "FFmpeg could not render animation! Check paths or your FFmpeg " \ - "installation." -#define IMGUI_LOG_SPRITESHEET_SAVE_FORMAT "Saved spritesheet #{} to: {}" -#define IMGUI_LOG_DRAG_DROP_ERROR "Invalid file for dragging/dropping!" -#define IMGUI_LOG_ANIMATION_PASTE_ERROR "Failed to parse clipboard text as an animation." -#define IMGUI_LOG_FRAME_PASTE_ERROR "Failed to parse clipboard text as a frame." -#define IMGUI_LOG_RELOAD_SPRITESHEET "Reloaded spritesheet(s)." -#define IMGUI_LOG_REMOVE_UNUSED_SPRITESHEETS "Removed unused spritesheet(s)." -#define IMGUI_LOG_REMOVE_UNUSED_EVENTS "Removed unused event(s)." -#define IMGUI_LOG_ADD_SPRITESHEET_ERROR "Failed to add spritesheet: {}. Make sure it's a valid PNG file." -#define IMGUI_LOG_ADD_SPRITESHEET "Added spritesheet #{}: {}" -#define IMGUI_LOG_REPLACE_SPRITESHEET "Replaced spritesheet #{}: {}" - -#define IMGUI_NONE "None" -#define IMGUI_ANIMATION_DEFAULT_FORMAT "(*) {}" -#define IMGUI_BUFFER_MAX UCHAR_MAX -#define IMGUI_INVISIBLE_LABEL_MARKER "##" -#define IMGUI_ITEM_SELECTABLE_EDITABLE_LABEL "## Editing" -#define IMGUI_LOG_FORMAT "## Log {}" -#define IMGUI_LOG_REDO_FORMAT "Redo: {}" -#define IMGUI_LOG_UNDO_FORMAT "Undo: {}" -#define IMGUI_OPENGL_VERSION "#version 330" -#define IMGUI_POSITION_FORMAT "Position: ({:8}, {:8})" -#define IMGUI_SPRITESHEET_FORMAT "#{} {}" -#define IMGUI_SPRITESHEET_ID_FORMAT "#{}" -#define IMGUI_TIMELINE_ITEM_CHILD_FORMAT "#{} {}" -#define IMGUI_LAYER_FORMAT "#{} {}" -#define IMGUI_NULL_FORMAT "#{} {}" -#define IMGUI_TIMELINE_FRAME_LABEL_FORMAT "## {}" -#define IMGUI_SELECTABLE_INPUT_INT_FORMAT "#{}" -#define IMGUI_TIMELINE_ANIMATION_NONE "Select an animation to show timeline..." -#define IMGUI_HOTKEY_CHANGE "Input new hotkey..." -#define IMGUI_LABEL_HOTKEY_FORMAT " ({})" -#define IMGUI_TOOLTIP_HOTKEY_FORMAT "\n(Hotkey: {})" -#define IMGUI_INVISIBLE_FORMAT "## {}" -#define IMGUI_RENDERING_FFMPEG_INFO_THRESHOLD 0.95f - -#define IMGUI_TRIGGERS_FONT_SCALE 2.0 - -const ImVec2 IMGUI_TOOL_BUTTON_SIZE = {24, 24}; -const ImVec2 IMGUI_TOOL_COLOR_SIZE = {24, 24}; -const ImVec2 IMGUI_TIMELINE_FRAME_SIZE = {12, 36}; -const ImVec2 IMGUI_TIMELINE_FRAME_ATLAS_OFFSET = {ATLAS_SIZE_SMALL.x * 0.25f, (IMGUI_TIMELINE_FRAME_SIZE.y * 0.5f) - (ATLAS_SIZE_SMALL.y * 0.5f)}; -const ImVec2 IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE = {150, 0}; -const ImVec2 IMGUI_TIMELINE_ITEM_SIZE = {300, IMGUI_TIMELINE_FRAME_SIZE.y}; - -const ImVec4 IMGUI_TIMELINE_FRAME_COLOR = {0.0f, 0.0f, 0.0f, 0.125}; -const ImVec4 IMGUI_TIMELINE_FRAME_MULTIPLE_COLOR = {0.113, 0.184, 0.286, 0.125}; -const ImVec4 IMGUI_TIMELINE_HEADER_FRAME_COLOR = {0.113, 0.184, 0.286, 0.5}; -const ImVec4 IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_COLOR = {0.113, 0.184, 0.286, 1.0}; -const ImVec4 IMGUI_TIMELINE_HEADER_FRAME_INACTIVE_COLOR = {0.113, 0.184, 0.286, 0.125}; -const ImVec4 IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_INACTIVE_COLOR = {0.113, 0.184, 0.286, 0.25}; -const ImVec4 IMGUI_ACTIVE_COLOR = {1.0, 1.0, 1.0, 1.0}; -const ImVec4 IMGUI_INACTIVE_COLOR = {1.0, 1.0, 1.0, 0.25}; - -const ImVec2 IMGUI_TOOLTIP_OFFSET = {16, 8}; -const vec2 IMGUI_SPRITESHEET_EDITOR_CROP_FORGIVENESS = {1, 1}; - -const ImGuiKey IMGUI_INPUT_DELETE = ImGuiKey_Delete; -const ImGuiKey IMGUI_INPUT_LEFT = ImGuiKey_LeftArrow; -const ImGuiKey IMGUI_INPUT_RIGHT = ImGuiKey_RightArrow; -const ImGuiKey IMGUI_INPUT_UP = ImGuiKey_UpArrow; -const ImGuiKey IMGUI_INPUT_DOWN = ImGuiKey_DownArrow; -const ImGuiKey IMGUI_INPUT_SHIFT = ImGuiMod_Shift; -const ImGuiKey IMGUI_INPUT_CTRL = ImGuiMod_Ctrl; -const ImGuiKey IMGUI_INPUT_ALT = ImGuiMod_Alt; -const ImGuiKey IMGUI_INPUT_ZOOM_IN = ImGuiKey_1; -const ImGuiKey IMGUI_INPUT_ZOOM_OUT = ImGuiKey_2; -const ImGuiKey IMGUI_INPUT_ENTER = ImGuiKey_Enter; -const ImGuiKey IMGUI_INPUT_RENAME = ImGuiKey_F2; -const ImGuiKey IMGUI_INPUT_DEFAULT = ImGuiKey_Home; -const ImGuiKeyChord IMGUI_CHORD_SELECT_ALL = ImGuiMod_Ctrl | ImGuiKey_A; -const ImGuiKeyChord IMGUI_CHORD_SELECT_NONE = ImGuiKey_Escape; -const ImGuiMouseButton IMGUI_MOUSE_DEFAULT = ImGuiMouseButton_Middle; - -enum ImguiPopupType { IMGUI_POPUP_NONE, IMGUI_POPUP_BY_ITEM, IMGUI_POPUP_CENTER_WINDOW }; -enum ImguiPopupState { IMGUI_POPUP_STATE_CLOSED, IMGUI_POPUP_STATE_OPEN, IMGUI_POPUP_STATE_CONFIRM, IMGUI_POPUP_STATE_CANCEL }; - -struct ImguiColorSet { - std::optional normal = {}; - std::optional active = {}; - std::optional hovered = {}; - std::optional border = {}; -}; - -struct ImguiLogItem { - std::string text; - float timeRemaining; -}; - -struct Imgui { - Dialog* dialog = nullptr; - Resources* resources = nullptr; - Anm2* anm2 = nullptr; - Anm2Reference* reference = nullptr; - Editor* editor = nullptr; - Preview* preview = nullptr; - GeneratePreview* generatePreview = nullptr; - Settings* settings = nullptr; - Snapshots* snapshots = nullptr; - Clipboard* clipboard = nullptr; - SDL_Window* window = nullptr; - SDL_GLContext* glContext = nullptr; - Anm2 saveAnm2 = Anm2(); - ImFont* fonts[FONT_COUNT] = {}; - ImGuiStyle style; - std::vector log{}; - std::string pendingPopup{}; - ImguiPopupType pendingPopupType = IMGUI_POPUP_NONE; - ImVec2 pendingPopupPosition{}; - std::set selectedAnimationIndices{}; - int lastAnimationIndex = ID_NONE; - std::set selectedSpritesheetIDs{}; - int lastSpritesheetID = ID_NONE; - int selectedEventID = ID_NONE; - int selectedLayerID = ID_NONE; - int selectedNullID = ID_NONE; - SDL_SystemCursor cursor = SDL_SYSTEM_CURSOR_DEFAULT; - SDL_SystemCursor pendingCursor = SDL_SYSTEM_CURSOR_DEFAULT; - bool isCursorSet = false; - bool isContextualActionsEnabled = true; - bool isQuit = false; - bool isTryQuit = false; -}; - -static inline void imgui_snapshot(Imgui* self, const std::string& action = SNAPSHOT_ACTION) { - self->snapshots->action = action; - Snapshot snapshot = snapshot_get(self->snapshots); - snapshots_undo_push(self->snapshots, &snapshot); -} - -static void imgui_log_push(Imgui* self, const std::string& text) { - self->log.push_back({text, IMGUI_LOG_DURATION}); - log_imgui(text); -} - -static inline void imgui_anm2_new(Imgui* self) { - anm2_free(self->anm2); - anm2_new(self->anm2); - - *self->reference = Anm2Reference(); - self->selectedAnimationIndices = {}; - self->selectedSpritesheetIDs = {}; -} - -static inline void imgui_file_open(Imgui* self) { dialog_anm2_open(self->dialog); } - -static inline void imgui_file_save(Imgui* self) { - if (self->anm2->path.empty()) - dialog_anm2_save(self->dialog); - else { - anm2_serialize(self->anm2, self->anm2->path); - imgui_log_push(self, std::format(IMGUI_LOG_FILE_SAVE_FORMAT, self->anm2->path)); - } - - self->saveAnm2 = *self->anm2; -} - -static inline void imgui_file_new(Imgui* self) { - std::string path = self->anm2->path; - imgui_anm2_new(self); - self->anm2->path = path; - imgui_file_save(self); -} - -static inline void imgui_file_save_as(Imgui* self) { dialog_anm2_save(self->dialog); } - -static inline void imgui_quit(Imgui* self) { - if (self->saveAnm2 != *self->anm2) - self->isTryQuit = true; - else - self->isQuit = true; -} - -static inline void imgui_explore(Imgui* self) { - std::filesystem::path filePath = self->anm2->path; - std::filesystem::path parentPath = filePath.parent_path(); - dialog_explorer_open(parentPath.string()); -} - -static inline void imgui_tool_pan_set(Imgui* self) { self->settings->tool = TOOL_PAN; } -static inline void imgui_tool_move_set(Imgui* self) { self->settings->tool = TOOL_MOVE; } -static inline void imgui_tool_rotate_set(Imgui* self) { self->settings->tool = TOOL_ROTATE; } -static inline void imgui_tool_scale_set(Imgui* self) { self->settings->tool = TOOL_SCALE; } -static inline void imgui_tool_crop_set(Imgui* self) { self->settings->tool = TOOL_CROP; } -static inline void imgui_tool_draw_set(Imgui* self) { self->settings->tool = TOOL_DRAW; } -static inline void imgui_tool_erase_set(Imgui* self) { self->settings->tool = TOOL_ERASE; } -static inline void imgui_tool_color_picker_set(Imgui* self) { self->settings->tool = TOOL_COLOR_PICKER; } - -static inline void imgui_undo(Imgui* self) { - if (self->snapshots->undoStack.top == 0) - return; - - snapshots_undo(self->snapshots); - imgui_log_push(self, std::format(IMGUI_LOG_UNDO_FORMAT, self->snapshots->action)); -} - -static inline void imgui_redo(Imgui* self) { - if (self->snapshots->redoStack.top == 0) - return; - - std::string action = self->snapshots->action; - snapshots_redo(self->snapshots); - imgui_log_push(self, std::format(IMGUI_LOG_REDO_FORMAT, action)); -} - -static inline void imgui_cut(Imgui* self) { clipboard_cut(self->clipboard); } - -static inline void imgui_copy(Imgui* self) { clipboard_copy(self->clipboard); } - -static inline void imgui_paste(Imgui* self) { - if (!clipboard_paste(self->clipboard)) { - switch (self->clipboard->type) { - case CLIPBOARD_FRAME: - imgui_log_push(self, IMGUI_LOG_FRAME_PASTE_ERROR); - break; - case CLIPBOARD_ANIMATION: - imgui_log_push(self, IMGUI_LOG_ANIMATION_PASTE_ERROR); - break; - default: - break; - } - } -} - -static inline void imgui_onionskin_toggle(Imgui* self) { self->settings->onionskinIsEnabled = !self->settings->onionskinIsEnabled; } - -static std::unordered_map IMGUI_KEY_MAP = {{"A", ImGuiKey_A}, - {"B", ImGuiKey_B}, - {"C", ImGuiKey_C}, - {"D", ImGuiKey_D}, - {"E", ImGuiKey_E}, - {"F", ImGuiKey_F}, - {"G", ImGuiKey_G}, - {"H", ImGuiKey_H}, - {"I", ImGuiKey_I}, - {"J", ImGuiKey_J}, - {"K", ImGuiKey_K}, - {"L", ImGuiKey_L}, - {"M", ImGuiKey_M}, - {"N", ImGuiKey_N}, - {"O", ImGuiKey_O}, - {"P", ImGuiKey_P}, - {"Q", ImGuiKey_Q}, - {"R", ImGuiKey_R}, - {"S", ImGuiKey_S}, - {"T", ImGuiKey_T}, - {"U", ImGuiKey_U}, - {"V", ImGuiKey_V}, - {"W", ImGuiKey_W}, - {"X", ImGuiKey_X}, - {"Y", ImGuiKey_Y}, - {"Z", ImGuiKey_Z}, - - {"0", ImGuiKey_0}, - {"1", ImGuiKey_1}, - {"2", ImGuiKey_2}, - {"3", ImGuiKey_3}, - {"4", ImGuiKey_4}, - {"5", ImGuiKey_5}, - {"6", ImGuiKey_6}, - {"7", ImGuiKey_7}, - {"8", ImGuiKey_8}, - {"9", ImGuiKey_9}, - - {"Num0", ImGuiKey_Keypad0}, - {"Num1", ImGuiKey_Keypad1}, - {"Num2", ImGuiKey_Keypad2}, - {"Num3", ImGuiKey_Keypad3}, - {"Num4", ImGuiKey_Keypad4}, - {"Num5", ImGuiKey_Keypad5}, - {"Num6", ImGuiKey_Keypad6}, - {"Num7", ImGuiKey_Keypad7}, - {"Num8", ImGuiKey_Keypad8}, - {"Num9", ImGuiKey_Keypad9}, - {"NumAdd", ImGuiKey_KeypadAdd}, - {"NumSubtract", ImGuiKey_KeypadSubtract}, - {"NumMultiply", ImGuiKey_KeypadMultiply}, - {"NumDivide", ImGuiKey_KeypadDivide}, - {"NumEnter", ImGuiKey_KeypadEnter}, - {"NumDecimal", ImGuiKey_KeypadDecimal}, - - {"F1", ImGuiKey_F1}, - {"F2", ImGuiKey_F2}, - {"F3", ImGuiKey_F3}, - {"F4", ImGuiKey_F4}, - {"F5", ImGuiKey_F5}, - {"F6", ImGuiKey_F6}, - {"F7", ImGuiKey_F7}, - {"F8", ImGuiKey_F8}, - {"F9", ImGuiKey_F9}, - {"F10", ImGuiKey_F10}, - {"F11", ImGuiKey_F11}, - {"F12", ImGuiKey_F12}, - - {"Up", ImGuiKey_UpArrow}, - {"Down", ImGuiKey_DownArrow}, - {"Left", ImGuiKey_LeftArrow}, - {"Right", ImGuiKey_RightArrow}, - - {"Space", ImGuiKey_Space}, - {"Enter", ImGuiKey_Enter}, - {"Escape", ImGuiKey_Escape}, - {"Tab", ImGuiKey_Tab}, - {"Backspace", ImGuiKey_Backspace}, - {"Delete", ImGuiKey_Delete}, - {"Insert", ImGuiKey_Insert}, - {"Home", ImGuiKey_Home}, - {"End", ImGuiKey_End}, - {"PageUp", ImGuiKey_PageUp}, - {"PageDown", ImGuiKey_PageDown}, - - {"Minus", ImGuiKey_Minus}, - {"Equal", ImGuiKey_Equal}, - {"LeftBracket", ImGuiKey_LeftBracket}, - {"RightBracket", ImGuiKey_RightBracket}, - {"Semicolon", ImGuiKey_Semicolon}, - {"Apostrophe", ImGuiKey_Apostrophe}, - {"Comma", ImGuiKey_Comma}, - {"Period", ImGuiKey_Period}, - {"Slash", ImGuiKey_Slash}, - {"Backslash", ImGuiKey_Backslash}, - {"GraveAccent", ImGuiKey_GraveAccent}, - - {"MouseLeft", ImGuiKey_MouseLeft}, - {"MouseRight", ImGuiKey_MouseRight}, - {"MouseMiddle", ImGuiKey_MouseMiddle}, - {"MouseX1", ImGuiKey_MouseX1}, - {"MouseX2", ImGuiKey_MouseX2}}; - -static std::unordered_map IMGUI_MOD_MAP = { - {"Ctrl", ImGuiMod_Ctrl}, - {"Shift", ImGuiMod_Shift}, - {"Alt", ImGuiMod_Alt}, - {"Super", ImGuiMod_Super}, -}; - -static inline ImGuiKey imgui_key_from_char_get(char c) { - if (c >= 'a' && c <= 'z') - c -= 'a' - 'A'; - if (c >= 'A' && c <= 'Z') - return (ImGuiKey)(ImGuiKey_A + (c - 'A')); - return ImGuiKey_None; -} - -static inline std::string imgui_string_from_chord_get(ImGuiKeyChord chord) { - std::string result; - - if (chord & ImGuiMod_Ctrl) - result += "Ctrl+"; - if (chord & ImGuiMod_Shift) - result += "Shift+"; - if (chord & ImGuiMod_Alt) - result += "Alt+"; - if (chord & ImGuiMod_Super) - result += "Super+"; - - ImGuiKey key = (ImGuiKey)(chord & ~ImGuiMod_Mask_); - - if (key != ImGuiKey_None) { - const char* name = ImGui::GetKeyName(key); - if (name && *name) - result += name; - else - result += "Unknown"; - } - - if (!result.empty() && result.back() == '+') - result.pop_back(); - - return result; -} - -static inline ImGuiKeyChord imgui_chord_from_string_get(const std::string& str) { - ImGuiKeyChord chord = 0; - ImGuiKey baseKey = ImGuiKey_None; - - std::stringstream ss(str); - std::string token; - while (std::getline(ss, token, '+')) { - // trim - token.erase(0, token.find_first_not_of(" \t\r\n")); - token.erase(token.find_last_not_of(" \t\r\n") + 1); - - if (token.empty()) - continue; - - if (auto it = IMGUI_MOD_MAP.find(token); it != IMGUI_MOD_MAP.end()) { - chord |= it->second; - } else if (baseKey == ImGuiKey_None) { - if (auto it2 = IMGUI_KEY_MAP.find(token); it2 != IMGUI_KEY_MAP.end()) - baseKey = it2->second; - } - } - - if (baseKey != ImGuiKey_None) - chord |= baseKey; - - return chord; -} - -static inline void imgui_keyboard_nav_enable(void) { ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; } -static inline void imgui_keyboard_nav_disable(void) { ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NavEnableKeyboard; } -static inline void imgui_contextual_actions_enable(Imgui* self) { self->isContextualActionsEnabled = true; } -static inline void imgui_contextual_actions_disable(Imgui* self) { self->isContextualActionsEnabled = false; } -static inline bool imgui_is_popup_open(const std::string& label) { return ImGui::IsPopupOpen(label.c_str()); } -static inline bool imgui_is_any_popup_open(void) { return ImGui::IsPopupOpen(nullptr, ImGuiPopupFlags_AnyPopupId); } -static inline void imgui_open_popup(const std::string& label) { ImGui::OpenPopup(label.c_str()); } -static inline void imgui_pending_popup_process(Imgui* self) { - if (self->pendingPopup.empty()) - return; - - switch (self->pendingPopupType) { - case IMGUI_POPUP_CENTER_WINDOW: - ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); - break; - case IMGUI_POPUP_BY_ITEM: - default: - ImGui::SetNextWindowPos(self->pendingPopupPosition); - break; - } - - if (!imgui_is_any_popup_open()) - imgui_open_popup(self->pendingPopup.c_str()); - - self->pendingPopup.clear(); - self->pendingPopupType = IMGUI_POPUP_NONE; - self->pendingPopupPosition = ImVec2(); -} - -static inline bool imgui_begin_popup(const std::string& label, Imgui* imgui, ImVec2 size = ImVec2()) { - imgui_pending_popup_process(imgui); - if (size != ImVec2()) - ImGui::SetNextWindowSizeConstraints(size, ImVec2(FLT_MAX, FLT_MAX)); - bool isActivated = ImGui::BeginPopup(label.c_str(), IMGUI_POPUP_FLAGS); - return isActivated; -} - -static inline bool imgui_begin_popup_modal(const std::string& label, Imgui* imgui, ImVec2 size = ImVec2()) { - imgui_pending_popup_process(imgui); - if (size != ImVec2()) - ImGui::SetNextWindowSizeConstraints(size, ImVec2(FLT_MAX, FLT_MAX)); - bool isActivated = ImGui::BeginPopupModal(label.c_str(), nullptr, IMGUI_POPUP_MODAL_FLAGS); - if (isActivated) - imgui_contextual_actions_disable(imgui); - return isActivated; -} - -static inline void imgui_close_current_popup(Imgui* imgui) { - imgui_contextual_actions_enable(imgui); - ImGui::CloseCurrentPopup(); -} - -static inline void imgui_end_popup(Imgui* imgui) { - ImGui::EndPopup(); - imgui_pending_popup_process(imgui); -} - -enum ImguiItemType { - IMGUI_ITEM, - IMGUI_TEXT, - IMGUI_IMAGE, - IMGUI_BEGIN_WINDOW, - IMGUI_END_WINDOW, - IMGUI_DOCKSPACE, - IMGUI_BEGIN_CHILD, - IMGUI_END_CHILD, - IMGUI_TABLE, - IMGUI_CONFIRM_POPUP, - IMGUI_SELECTABLE, - IMGUI_BUTTON, - IMGUI_RADIO_BUTTON, - IMGUI_COLOR_BUTTON, - IMGUI_CHECKBOX, - IMGUI_INPUT_INT, - IMGUI_INPUT_TEXT, - IMGUI_INPUT_FLOAT, - IMGUI_SLIDER_FLOAT, - IMGUI_DRAG_FLOAT, - IMGUI_COLOR_EDIT, - IMGUI_COMBO, - IMGUI_ATLAS_TEXT, - IMGUI_ATLAS_BUTTON -}; - -struct ImguiItem; - -static std::vector& imgui_item_registry(void) { - static std::vector registry; - return registry; -} - -static ImGuiKeyChord* imgui_hotkey_chord_registry(void) { - static ImGuiKeyChord registry[HOTKEY_COUNT]; - return registry; -} - -typedef void (*ImguiFunction)(Imgui*); -using IntStringMap = std::map; - -#define IMGUI_ITEM_MEMBERS \ - X(label, std::string, false, {}) \ - X(tooltip, std::string, false, {}) \ - X(snapshotAction, std::string, true, {}) \ - X(popup, std::string, false, {}) \ - X(dragDrop, std::string, true, {}) \ - X(focusWindow, std::string, true, {}) \ - X(items, IntStringMap, false, {}) \ - X(atlas, AtlasType, false, ATLAS_NONE) \ - X(textureID, int, false, ID_NONE) \ - X(chord, ImGuiKeyChord, true, {}) \ - X(hotkey, HotkeyType, true, {}) \ - X(mnemonicKey, ImGuiKey, false, ImGuiKey_None) \ - X(mnemonicIndex, int, false, INDEX_NONE) \ - X(position, vec2, true, {}) \ - X(size, vec2, true, {}) \ - X(scale, float, false, 1.0f) \ - X(uvMin, vec2, false, vec2()) \ - X(uvMax, vec2, false, vec2(1.0f)) \ - X(popupSize, vec2, false, {}) \ - X(color, ImguiColorSet, false, {}) \ - X(function, ImguiFunction, false, {}) \ - X(popupType, ImguiPopupType, false, IMGUI_POPUP_CENTER_WINDOW) \ - X(isDisabled, bool, false, false) \ - X(isSelected, bool, false, false) \ - X(isMnemonicDisabled, bool, false, false) \ - X(isEmptyFormat, bool, false, false) \ - X(isUseItemActivated, bool, false, false) \ - X(isWidthToText, bool, false, false) \ - X(isWidthToRegion, bool, false, false) \ - X(isHeightToRegion, bool, false, false) \ - X(isHotkeyInLabel, bool, false, false) \ - X(isAllowHotkeyWhenFocusWindow, bool, false, false) \ - X(isAtlasStretch, bool, false, false) \ - X(isSameLine, bool, false, false) \ - X(isSeparator, bool, false, false) \ - X(id, int, false, 0) \ - X(idOffset, int, false, {}) \ - X(speed, float, false, 0.25f) \ - X(step, float, false, 1.0f) \ - X(stepFast, float, false, 10.0f) \ - X(min, int, true, {}) \ - X(max, int, true, {}) \ - X(value, int, false, {}) \ - X(atlasOffset, vec2, true, {}) \ - X(cursorPosition, vec2, true, {}) \ - X(cursorOffset, vec2, false, {}) \ - X(textPosition, vec2, true, {}) \ - X(textOffset, vec2, false, {}) \ - X(itemSpacing, vec2, true, {}) \ - X(windowPadding, vec2, true, {}) \ - X(framePadding, vec2, true, {}) \ - X(border, int, true, {}) \ - X(flags, int, false, {}) \ - X(windowFlags, int, false, {}) \ - X(rowCount, int, true, {}) \ - X(font, ImFont*, true, {}) - -struct ImguiItemOverride { -#define X(name, type, isOptional, ...) std::optional name = {}; - IMGUI_ITEM_MEMBERS -#undef X -}; - -struct ImguiItem { -#define X(name, type, isOptional, ...) std::conditional_t, type> name = __VA_ARGS__; - IMGUI_ITEM_MEMBERS -#undef X - - bool is_chord() const { return chord.has_value() || hotkey.has_value(); } - bool is_mnemonic() const { return mnemonicKey != ImGuiKey_None; } - bool is_range() const { return min != 0 || max != 0; } - const char* drag_drop_get() const { return dragDrop->c_str(); } - const char* text_get() const { return tooltip.c_str(); } - - void construct() { - static int idNew = 0; - id = idNew++; - - imgui_item_registry().push_back(this); - - std::string labelNew{}; - - for (int i = 0; i < (int)label.size(); i++) { - if (label[i] == '&') { - if (label[i + 1] == '&') { - labelNew += '&'; - i++; - } else if (label[i + 1] != '\0') { - mnemonicKey = imgui_key_from_char_get(label[i + 1]); - mnemonicIndex = (int)labelNew.size(); - labelNew += label[i + 1]; - i++; - } - } else - labelNew += label[i]; - } - - label = labelNew; - } - - ImguiItem copy(const ImguiItemOverride& override) const { - ImguiItem out = *this; - -#define X(name, type, value, isOptional) \ - if (override.name.has_value()) \ - out.name = *override.name; - IMGUI_ITEM_MEMBERS -#undef X - - out.id += out.idOffset; - - return out; - } - - ImGuiKeyChord chord_get() const { - if (hotkey.has_value()) - return imgui_hotkey_chord_registry()[*hotkey]; - if (chord.has_value()) - return *chord; - return ImGuiKey_None; - } - - std::string label_get() const { - std::string newLabel = label; - if (isHotkeyInLabel) - newLabel += std::format(IMGUI_LABEL_HOTKEY_FORMAT, imgui_string_from_chord_get(chord_get())); - return newLabel; - } - - std::string tooltip_get() const { - std::string newTooltip = tooltip; - if (is_chord()) - newTooltip += std::format(IMGUI_TOOLTIP_HOTKEY_FORMAT, imgui_string_from_chord_get(chord_get())); - return newTooltip; - } -}; - -#define IMGUI_ITEM(NAME, ...) \ - const inline ImguiItem NAME = [] { \ - ImguiItem self; \ - __VA_ARGS__; \ - self.construct(); \ - return self; \ - }() - -IMGUI_ITEM(IMGUI_WINDOW_MAIN, self.label = "## Window", - self.flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus); - -IMGUI_ITEM(IMGUI_DOCKSPACE_MAIN, self.label = "## Dockspace", self.flags = ImGuiDockNodeFlags_PassthruCentralNode); - -IMGUI_ITEM(IMGUI_FOOTER_CHILD, self.label = "## Footer Child", self.size = {0, 42}, self.flags = true); - -IMGUI_ITEM(IMGUI_TASKBAR, self.label = "Taskbar", self.size = {0, 32}, - self.flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoSavedSettings); - -IMGUI_ITEM(IMGUI_FILE, self.label = "&File", self.tooltip = "Opens the file menu, for reading/writing anm2 files.", self.popup = "## File Popup", - self.popupType = IMGUI_POPUP_BY_ITEM, self.isWidthToText = true, self.isHeightToRegion = true, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_NEW, self.label = "&New", self.tooltip = "Load a blank .anm2 file to edit.", self.function = imgui_file_new, self.hotkey = HOTKEY_NEW, - self.isWidthToRegion = true, self.isHotkeyInLabel = true); - -IMGUI_ITEM(IMGUI_OPEN, self.label = "&Open", self.tooltip = "Open an existing .anm2 file to edit.", self.function = imgui_file_open, self.hotkey = HOTKEY_OPEN, - self.isWidthToRegion = true, self.isHotkeyInLabel = true); - -IMGUI_ITEM(IMGUI_SAVE, self.label = "&Save", - self.tooltip = "Saves the current .anm2 file to its path.\nIf no " - "path exists, one can be chosen.", - self.function = imgui_file_save, self.hotkey = HOTKEY_SAVE, self.isWidthToText = true, self.isHotkeyInLabel = true); - -IMGUI_ITEM(IMGUI_SAVE_AS, self.label = "S&ave As", self.tooltip = "Saves the current .anm2 file to a chosen path.", self.function = imgui_file_save_as, - self.hotkey = HOTKEY_SAVE_AS, self.isWidthToText = true, self.isHotkeyInLabel = true); - -IMGUI_ITEM(IMGUI_EXPLORE_ANM2_LOCATION, self.label = "E&xplore Anm2 Location", self.tooltip = "Open the system's file explorer in the anm2's path.", - self.function = imgui_explore, self.isWidthToText = true, self.isSeparator = true); - -IMGUI_ITEM(IMGUI_EXIT, self.label = "&Exit", self.tooltip = "Exits the program.", self.function = imgui_quit, self.hotkey = HOTKEY_EXIT, - self.isWidthToText = true, self.isHotkeyInLabel = true); - -IMGUI_ITEM(IMGUI_EXIT_CONFIRMATION, self.label = "Exit Confirmation", self.tooltip = "Unsaved changes will be lost!\nAre you sure you want to exit?"); - -IMGUI_ITEM(IMGUI_OPEN_CONFIRMATION, self.label = "Open Confirmation", self.tooltip = "Unsaved changes will be lost!\nAre you sure you open a new file?"); - -IMGUI_ITEM(IMGUI_NO_ANM2_PATH_CONFIRMATION, self.label = "No Anm2 Path", self.tooltip = "You will need to load or make a new .anm2 file first!\n"); - -IMGUI_ITEM(IMGUI_WIZARD, self.label = "&Wizard", self.tooltip = "Opens the wizard menu, for neat functions related to the .anm2.", - self.popup = "## Wizard Popup", self.popupType = IMGUI_POPUP_BY_ITEM, self.isHeightToRegion = true, self.isWidthToText = true, - self.isSameLine = true); - -#define IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING 40 -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID, self.label = "&Generate Animation from Grid", self.tooltip = "Generate a new animation from grid values.", - self.popup = "Generate Animation from Grid", self.popupType = IMGUI_POPUP_CENTER_WINDOW, - self.popupSize = {(GENERATE_PREVIEW_SIZE.x * 2) + IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING, - GENERATE_PREVIEW_SIZE.y + (IMGUI_FOOTER_CHILD.size->y * 2) + (IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING * 0.5f)}); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_OPTIONS_CHILD, self.label = "## Generate Animation From Grid Options Child", - self.size = {IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.x * 0.5f, IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.y - IMGUI_FOOTER_CHILD.size->y}, - self.flags = true); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_START_POSITION, self.label = "Start Position", - self.tooltip = "Set the starting position on the layer's " - "spritesheet for the generated animation."); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_SIZE, self.label = "Size", self.tooltip = "Set the size of each frame in the generated animation."); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_PIVOT, self.label = "Pivot", self.tooltip = "Set the pivot of each frame in the generated animation."); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_ROWS, self.label = "Rows", self.tooltip = "Set how many rows will be used in the generated animation.", - self.min = 1, self.max = 1000); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_COLUMNS, self.label = "Columns", self.tooltip = "Set how many columns will be used in the generated animation.", - self.min = 1, self.max = 1000); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_COUNT, self.label = "Count", self.tooltip = "Set how many frames will be made for the generated animation.", - self.value = ANM2_FRAME_NUM_MIN); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_DELAY, self.label = "Delay", self.tooltip = "Set the delay of each frame in the generated animation.", - self.max = 1000); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_PREVIEW_CHILD, self.label = "## Generate Animation From Grid Preview Child", - self.size = {IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.x * 0.5f, IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.y - IMGUI_FOOTER_CHILD.size->y}, - self.flags = true); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER_CHILD, self.label = "## Generate Animation From Grid Slider Child", - self.size = {(IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.x * 0.5f) - (IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING * 0.5f), - IMGUI_FOOTER_CHILD.size->y}, - self.flags = true); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER, self.label = "## Generate Animation From Grid Slider", - self.tooltip = "Change the time of the generated animation preview.", self.min = GENERATE_PREVIEW_TIME_MIN, self.max = GENERATE_PREVIEW_TIME_MAX, - self.value = GENERATE_PREVIEW_TIME_MIN, self.rowCount = 1, self.isEmptyFormat = true, self.flags = ImGuiSliderFlags_NoInput); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_GENERATE, self.label = "Generate", self.tooltip = "Generate an animation with the used settings.", - self.snapshotAction = "Generate Animation from Grid", self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES, self.label = "&Change All Frame Properties", - self.tooltip = "Change all frame properties in the selected " - "animation item (or selected frame).", - self.popup = "Change All Frame Properties", self.popupType = IMGUI_POPUP_CENTER_WINDOW, self.popupSize = {500, 405}); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CHILD, self.label = "## Change All Frame Properties Child", - self.size = {IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popupSize.x, 275}, self.flags = true); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS_CHILD, self.label = "## Change All Frame Properties Settings Child", - self.size = {IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popupSize.x, 55}, self.flags = true); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS, self.label = "Settings"); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_FROM_SELECTED_FRAME, self.label = "From Selected Frames", - self.tooltip = "The set frame properties will start from the selected frame.", self.isSameLine = true); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_NUMBER_FRAMES, self.label = "# of Frames", - self.tooltip = "Set the amount of frames that the set frame properties will apply to.", self.size = {200, 0}, self.value = ANM2_FRAME_NUM_MIN, - self.max = 1000); - -#define IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT 4 -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_ADD, self.label = "Add", self.tooltip = "The specified values will be added to all specified frames.", - self.snapshotAction = "Add Frame Properties", self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SUBTRACT, self.label = "Subtract", - self.tooltip = "The specified values will be subtracted from all selected frames.", self.snapshotAction = "Subtract Frame Properties", - self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SET, self.label = "Set", - self.tooltip = "The specified values will be set to the specified " - "value in selected frames.", - self.snapshotAction = "Set Frame Properties", self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CANCEL, self.label = "Cancel", self.tooltip = "Cancel changing all frame properties.", - self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT); - -IMGUI_ITEM(IMGUI_SCALE_ANM2, self.label = "S&cale Anm2", self.tooltip = "Scale up all size and position-related frame properties in the anm2.", - self.popup = "Scale Anm2", self.popupType = IMGUI_POPUP_CENTER_WINDOW, self.popupSize = {260, 75}, self.isWidthToText = true, - self.isSeparator = true); - -IMGUI_ITEM(IMGUI_SCALE_ANM2_OPTIONS_CHILD, self.label = "## Scale Anm2 Options Child", self.flags = true); - -IMGUI_ITEM(IMGUI_SCALE_ANM2_VALUE, self.label = "Value", - self.tooltip = "The size and position-related frame properties in " - "the anm2 will be scaled by this value.", - self.value = 1, self.step = 0.25, self.stepFast = 1); - -IMGUI_ITEM(IMGUI_SCALE_ANM2_SCALE, self.label = "Scale", self.tooltip = "Scale the anm2 with the value specified.", self.snapshotAction = "Scale Anm2", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION, self.label = "&Render Animation", - self.tooltip = "Renders the current animation preview; output " - "options can be customized.", - self.popup = "Render Animation", self.popupSize = {500, 170}, self.popupType = IMGUI_POPUP_CENTER_WINDOW); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_CHILD, self.label = "## Render Animation Child", self.flags = true); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FOOTER_CHILD, self.label = "## Render Animation Footer Child", self.flags = true); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_LOCATION_BROWSE, self.label = "## Location Browse", self.tooltip = "Open file explorer to pick rendered animation location.", - self.atlas = ATLAS_FOLDER, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_LOCATION, self.label = "Location", - self.tooltip = "Select the location of the rendered animation.\nFor PNG " - "images, this should be a directory, otherwise, a filepath.", - self.max = 1024); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FFMPEG_BROWSE, self.label = "## FFMpeg Browse", self.tooltip = "Open file explorer to pick the path of FFmpeg", - self.atlas = ATLAS_FOLDER, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FFMPEG_PATH, self.label = "FFmpeg Path", - self.tooltip = "Sets the path FFmpeg currently resides in.\nFFmpeg is required " - "for rendering animations.\nDownload it from " - "https://ffmpeg.org/, your package manager, or wherever else.", - self.max = 1024); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_OUTPUT, self.label = "Output", - self.tooltip = "Select the rendered animation output.\nIt can either be " - "one animated image or a sequence of frames.", - self.items = {{RENDER_PNG, RENDER_TYPE_STRINGS[RENDER_PNG]}, - {RENDER_GIF, RENDER_TYPE_STRINGS[RENDER_GIF]}, - {RENDER_WEBM, RENDER_TYPE_STRINGS[RENDER_WEBM]}, - {RENDER_MP4, RENDER_TYPE_STRINGS[RENDER_MP4]}}, - self.value = RENDER_PNG); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FORMAT, self.label = "Format", - self.tooltip = "(PNG images only).\nSet the format of each output frame; i.e., " - "its filename.\nThe format will only take one argument; that " - "being the frame's index.\nFor example, a format like " - "\"{}.png\" will export a frame of index 0 as \"0.png\".", - self.max = UCHAR_MAX); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_IS_USE_ANIMATION_BOUNDS, self.label = "Use Animation Bounds", - self.tooltip = "Instead of using the animation preview's bounds, the rendered " - "animation will use the animation's bounds.\nNOTE: If you're looking " - "to make a transparent animation, set the preview background to be " - "transparent\nand toggle off other drawn things.", - self.value = SETTINGS_RENDER_IS_USE_ANIMATION_BOUNDS_DEFAULT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_SCALE, self.label = "Scale", self.tooltip = "Change the scale the animation will be rendered at.", - self.value = SETTINGS_RENDER_SCALE_DEFAULT, self.size = {125, 0}); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_CONFIRM, self.label = "Render", self.tooltip = "Render the animation, with the used settings.", - self.popup = "Rendering Animation...", self.popupType = IMGUI_POPUP_CENTER_WINDOW, self.popupSize = {300, 60}, self.isSameLine = true, - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT); - -IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_CHILD, self.label = "##Rendering Child", self.size = {400.0f, 65.0f}, self.flags = true); - -IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_INFO, self.label = "Recording frames. Once done, the program may halt\nas " - "FFmpeg renders the animation. Please be patient!"); -IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_CANCEL, self.label = "Cancel", self.tooltip = "Cancel rendering the animation.", self.rowCount = 1); - -IMGUI_ITEM(IMGUI_PLAYBACK, self.label = "&Playback", self.tooltip = "Opens the playback menu, for configuring playback settings.", - self.popup = "## Playback Popup", self.popupType = IMGUI_POPUP_BY_ITEM, self.isWidthToText = true, self.isHeightToRegion = true, - self.isSameLine = true); - -IMGUI_ITEM(IMGUI_ALWAYS_LOOP, self.label = "&Always Loop", - self.tooltip = "Sets the animation playback to always loop, " - "regardless of the animation's loop setting.", - self.isWidthToText = true); - -IMGUI_ITEM(IMGUI_CLAMP_PLAYHEAD, self.label = "&Clamp Playhead", - self.tooltip = "The playhead (draggable icon on timeline) won't be " - "able to exceed the animation length.", - self.isWidthToText = true); - -IMGUI_ITEM(IMGUI_SETTINGS, self.label = "&Settings", self.tooltip = "Opens the setting menu, for configuring general program settings.", - self.popup = "## Settings Popup", self.popupType = IMGUI_POPUP_BY_ITEM, self.isWidthToText = true, self.isHeightToRegion = true); - -IMGUI_ITEM(IMGUI_VSYNC, self.label = "&Vsync", - self.tooltip = "Toggle vertical sync; synchronizes program " - "framerate with your monitor's refresh rate.", - self.isWidthToText = true, self.isSeparator = true); - -IMGUI_ITEM(IMGUI_HOTKEYS, self.label = "&Hotkeys", self.tooltip = "Change the program's hotkeys.", self.popup = "Hotkeys", self.popupSize = {500, 405}, - self.isWidthToText = true, self.isSeparator = true); - -IMGUI_ITEM(IMGUI_HOTKEYS_CHILD, self.label = "## Hotkeys Child", self.size = {IMGUI_HOTKEYS.popupSize.x, IMGUI_HOTKEYS.popupSize.y - 35}, self.flags = true); - -#define IMGUI_HOTKEYS_FUNCTION "Function" -#define IMGUI_HOTKEYS_HOTKEY "Hotkey" -IMGUI_ITEM(IMGUI_HOTKEYS_TABLE, self.label = "## Hotkeys Table", self.value = 2, self.flags = ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY); - -IMGUI_ITEM(IMGUI_HOTKEYS_OPTIONS_CHILD, self.label = "## Merge Options Child", self.size = {IMGUI_HOTKEYS.popupSize.x, 35}, self.flags = true); - -IMGUI_ITEM(IMGUI_HOTKEYS_CONFIRM, self.label = "Confirm", self.tooltip = "Use these hotkeys.", self.rowCount = 1); - -IMGUI_ITEM(IMGUI_DEFAULT_SETTINGS, self.label = "&Reset to Default Settings", self.tooltip = "Reset the program's settings to their default state.", - self.isWidthToText = true); - -IMGUI_ITEM(IMGUI_ANM2S, self.label = "## Anm2s", self.size = {0, 32}, - self.flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoSavedSettings); - -IMGUI_ITEM(IMGUI_ANM2, self.label = "## Anm2"); - -IMGUI_ITEM(IMGUI_LAYERS, self.label = "Layers", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_LAYERS_CHILD, self.label = "## Layers Child", self.flags = true); - -IMGUI_ITEM(IMGUI_LAYER, self.label = "## Layer Item", self.dragDrop = "## Layer Drag Drop", self.atlas = ATLAS_LAYER, self.isWidthToRegion = true, - self.idOffset = 3000); - -IMGUI_ITEM(IMGUI_LAYER_SPRITESHEET_ID, self.label = "## Spritesheet ID", self.tooltip = "Change the spritesheet ID this layer uses.", - self.atlas = ATLAS_SPRITESHEET, self.size = {50, 0}); - -#define IMGUI_LAYERS_OPTIONS_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_LAYER_ADD, self.label = "Add", self.tooltip = "Adds a new layer.", self.snapshotAction = "Add Layer", - self.rowCount = IMGUI_LAYERS_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_LAYER_REMOVE, self.label = "Remove", - self.tooltip = "Removes the selected layer.\nThis will remove all layer " - "animations that use this layer from all animations.", - self.snapshotAction = "Remove Layer", self.chord = ImGuiKey_Delete, self.focusWindow = IMGUI_LAYERS.label, - self.rowCount = IMGUI_LAYERS_OPTIONS_ROW_COUNT); - -IMGUI_ITEM(IMGUI_NULLS, self.label = "Nulls", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_NULLS_CHILD, self.label = "## Nulls Child", self.flags = true); - -IMGUI_ITEM(IMGUI_NULL, self.label = "## Null Item", self.dragDrop = "## Null Drag Drop", self.atlas = ATLAS_NULL, self.idOffset = 4000); - -#define IMGUI_NULLS_OPTIONS_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_NULL_ADD, self.label = "Add", self.tooltip = "Adds a null layer.", self.snapshotAction = "Add Null", - self.rowCount = IMGUI_NULLS_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_NULL_REMOVE, self.label = "Remove", - self.tooltip = "Removes the selected null.\nThis will remove all null " - "animations that use this null from all animations.", - self.snapshotAction = "Remove Null", self.chord = ImGuiKey_Delete, self.focusWindow = IMGUI_NULLS.label, - self.rowCount = IMGUI_NULLS_OPTIONS_ROW_COUNT); - -IMGUI_ITEM(IMGUI_ANIMATIONS, self.label = "Animations", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_ANIMATIONS_CHILD, self.label = "## Animations Child", self.flags = true); - -IMGUI_ITEM(IMGUI_ANIMATION, self.label = "## Animation Item", self.dragDrop = "## Animation Drag Drop", self.atlas = ATLAS_ANIMATION, - self.isWidthToRegion = true, self.idOffset = 2000); - -#define IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT 5 -IMGUI_ITEM(IMGUI_ANIMATION_ADD, self.label = "Add", self.tooltip = "Adds a new animation.", self.snapshotAction = "Add Animation", - self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_ANIMATION_DUPLICATE, self.label = "Duplicate", self.tooltip = "Duplicates the selected animation, placing it after.", - self.snapshotAction = "Duplicate Animation", self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_ANIMATION_MERGE, self.label = "Merge", self.tooltip = "Open the animation merge popup, to merge animations together.", - self.popup = "Merge Animations", self.popupSize = {300, 400}, self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_MERGE_ANIMATIONS_CHILD, self.label = "## Merge Animations", self.size = {IMGUI_ANIMATION_MERGE.popupSize.x, 250}, self.flags = true); - -IMGUI_ITEM(IMGUI_MERGE_ON_CONFLICT_CHILD, self.label = "## Merge On Conflict Child", self.size = {IMGUI_ANIMATION_MERGE.popupSize.x, 75}, self.flags = true); - -IMGUI_ITEM(IMGUI_MERGE_ON_CONFLICT, self.label = "On Conflict"); - -IMGUI_ITEM(IMGUI_MERGE_APPEND_FRAMES, self.label = "Append Frames ", - self.tooltip = "On frame conflict, the merged animation will have " - "the selected animations' frames appended.", - self.value = ANM2_MERGE_APPEND, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_MERGE_REPLACE_FRAMES, self.label = "Replace Frames", - self.tooltip = "On frame conflict, the merged animation will have " - "the latest selected animations' frames.", - self.value = ANM2_MERGE_REPLACE); - -IMGUI_ITEM(IMGUI_MERGE_PREPEND_FRAMES, self.label = "Prepend Frames", - self.tooltip = "On frame conflict, the merged animation will have " - "the selected animations' frames prepended.", - self.value = ANM2_MERGE_PREPEND, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_MERGE_IGNORE, self.label = "Ignore ", - self.tooltip = "On frame conflict, the merged animation will ignore " - "the other selected animations' frames.", - self.value = ANM2_MERGE_IGNORE); - -IMGUI_ITEM(IMGUI_MERGE_OPTIONS_CHILD, self.label = "## Merge Options Child", self.size = {IMGUI_ANIMATION_MERGE.popupSize.x, 35}, self.flags = true); - -IMGUI_ITEM(IMGUI_MERGE_DELETE_ANIMATIONS_AFTER, self.label = "Delete Animations After Merging", - self.tooltip = "After merging, the selected animations (besides the " - "original) will be deleted."); - -IMGUI_ITEM(IMGUI_MERGE_CONFIRM, self.label = "Merge", self.tooltip = "Merge the selected animations with the options set.", - self.snapshotAction = "Merge Animations", self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_ANIMATION_REMOVE, self.label = "Remove", self.tooltip = "Remove the selected animation(s).", self.snapshotAction = "Remove Animation(s)", - self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, self.chord = ImGuiKey_Delete, self.focusWindow = IMGUI_ANIMATIONS.label, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_ANIMATION_DEFAULT, self.label = "Default", self.tooltip = "Set the referenced animation as the default one.", - self.snapshotAction = "Default Animation", self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, self.isSameLine = true); - -static inline void imgui_animations_select_all(Imgui* self) { - for (int i = 0; i < (int)self->anm2->animations.size(); i++) - self->selectedAnimationIndices.insert(i); -} - -IMGUI_ITEM(IMGUI_ANIMATION_SELECT_ALL, self.label = "## Select None", self.hotkey = HOTKEY_SELECT_ALL, self.focusWindow = IMGUI_ANIMATIONS.label, - self.function = imgui_animations_select_all, self.isAllowHotkeyWhenFocusWindow = true); - -static inline void imgui_animations_select_none(Imgui* self) { - self->selectedAnimationIndices.clear(); - *self->reference = Anm2Reference(); -} - -IMGUI_ITEM(IMGUI_ANIMATION_SELECT_NONE, self.label = "## Select None", self.hotkey = HOTKEY_SELECT_NONE, self.focusWindow = IMGUI_ANIMATIONS.label, - self.function = imgui_animations_select_none, self.isAllowHotkeyWhenFocusWindow = true); - -IMGUI_ITEM(IMGUI_EVENTS, self.label = "Events", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -IMGUI_ITEM(IMGUI_EVENTS_CHILD, self.label = "## Events Child", self.flags = true); - -IMGUI_ITEM(IMGUI_EVENT, self.label = "## Event", self.atlas = ATLAS_EVENT, self.idOffset = 1000); - -#define IMGUI_EVENTS_OPTIONS_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_EVENTS_ADD, self.label = "Add", self.tooltip = "Adds a new event.", self.snapshotAction = "Add Event", - self.rowCount = IMGUI_EVENTS_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_EVENTS_REMOVE_UNUSED, self.label = "Remove Unused", - self.tooltip = "Removes all unused events (i.e., not being used in " - "any triggers in any animation).", - self.snapshotAction = "Remove Unused Events", self.rowCount = IMGUI_EVENTS_OPTIONS_ROW_COUNT); - -// Spritesheets -IMGUI_ITEM(IMGUI_SPRITESHEET_PREVIEW, self.label = "## Spritesheet Preview", self.size = {65, 65}); -IMGUI_ITEM(IMGUI_SPRITESHEETS, self.label = "Spritesheets", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_SPRITESHEETS_CHILD, self.label = "## Spritesheets Child", self.flags = true, self.windowPadding = vec2()); -IMGUI_ITEM(IMGUI_SPRITESHEET_CHILD, self.label = "## Spritesheet Child", self.flags = true, self.itemSpacing = vec2(), self.windowPadding = vec2()); -IMGUI_ITEM(IMGUI_SPRITESHEET, self.label = "## Spritesheet", self.dragDrop = "## Spritesheet Drag Drop"); -IMGUI_ITEM(IMGUI_SPRITESHEET_TEXT, self.label = "## Spritesheet Text", self.atlas = ATLAS_SPRITESHEET, self.itemSpacing = vec2(8, 0)); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_FOOTER_CHILD, self.label = "## Spritesheets Footer Child", self.flags = true); - -#define IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT 4 -#define IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT 3 -IMGUI_ITEM(IMGUI_SPRITESHEET_ADD, self.label = "Add", self.tooltip = "Select a .png image to add as a spritesheet.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_RELOAD, self.label = "Reload", self.tooltip = "Reload the selected spritesheet(s).", - self.snapshotAction = "Reload Spritesheet(s)", self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_REPLACE, self.label = "Replace", self.tooltip = "Replace the highlighted spritesheet with another.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_REMOVE_UNUSED, self.label = "Remove Unused", - self.tooltip = "Remove all unused spritesheets in the anm2 (i.e., " - "the spritesheet isn't used in any layer animations).", - self.snapshotAction = "Remove Unused Spritesheets", self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_SELECT_ALL, self.label = "Select All", self.tooltip = "Select all spritesheets.", self.hotkey = HOTKEY_SELECT_ALL, - self.focusWindow = IMGUI_SPRITESHEETS.label, self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_SELECT_NONE, self.label = "Select None", self.tooltip = "Unselect all spritesheets.", self.hotkey = HOTKEY_SELECT_NONE, - self.focusWindow = IMGUI_SPRITESHEETS.label, self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_SPRITESHEET_SAVE, self.label = "Save", self.tooltip = "Save the selected spritesheets to their original locations.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT); - -const ImVec2 IMGUI_CANVAS_CHILD_SIZE = {230, 85}; -IMGUI_ITEM(IMGUI_CANVAS_GRID_CHILD, self.label = "## Canvas Grid Child", self.size = IMGUI_CANVAS_CHILD_SIZE, self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -IMGUI_ITEM(IMGUI_CANVAS_GRID, self.label = "Grid", self.tooltip = "Toggles the visiblity of the canvas' grid."); - -IMGUI_ITEM(IMGUI_CANVAS_GRID_SNAP, self.label = "Snap", self.tooltip = "Using the crop tool will snap the points to the nearest grid point."); - -IMGUI_ITEM(IMGUI_CANVAS_GRID_COLOR, self.label = "Color", self.tooltip = "Change the color of the canvas' grid.", self.flags = ImGuiColorEditFlags_NoInputs); - -IMGUI_ITEM(IMGUI_CANVAS_GRID_SIZE, self.label = "Size", self.tooltip = "Change the size of the canvas' grid.", self.min = CANVAS_GRID_MIN, - self.max = CANVAS_GRID_MAX, self.value = CANVAS_GRID_DEFAULT); - -IMGUI_ITEM(IMGUI_CANVAS_GRID_OFFSET, self.label = "Offset", self.tooltip = "Change the offset of the canvas' grid, in pixels."); - -IMGUI_ITEM(IMGUI_CANVAS_VIEW_CHILD, self.label = "## View Child", self.size = IMGUI_CANVAS_CHILD_SIZE, self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -IMGUI_ITEM(IMGUI_CANVAS_ZOOM, self.label = "Zoom", self.tooltip = "Change the zoom of the canvas.", self.min = CANVAS_ZOOM_MIN, self.max = CANVAS_ZOOM_MAX, - self.speed = 1.0f, self.value = CANVAS_ZOOM_DEFAULT); - -IMGUI_ITEM(IMGUI_CANVAS_VISUAL_CHILD, self.label = "## Animation Preview Visual Child", self.size = IMGUI_CANVAS_CHILD_SIZE, self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -IMGUI_ITEM(IMGUI_CANVAS_BACKGROUND_COLOR, self.label = "Background Color", self.tooltip = "Change the background color of the canvas.", - self.flags = ImGuiColorEditFlags_NoInputs); - -IMGUI_ITEM(IMGUI_CANVAS_ANIMATION_OVERLAY, self.label = "Overlay", - self.tooltip = "Choose an animation to overlay over the previewed " - "animation, for reference."); - -IMGUI_ITEM(IMGUI_CANVAS_ANIMATION_OVERLAY_TRANSPARENCY, self.label = "Alpha", self.tooltip = "Set the transparency of the animation overlay.", - self.value = SETTINGS_PREVIEW_OVERLAY_TRANSPARENCY_DEFAULT, self.max = UCHAR_MAX); - -IMGUI_ITEM(IMGUI_CANVAS_HELPER_CHILD, self.label = "## Animation Preview Helper Child", self.size = IMGUI_CANVAS_CHILD_SIZE, self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -IMGUI_ITEM(IMGUI_CANVAS_AXES, self.label = "Axes", self.tooltip = "Toggle the display of the X/Y axes."); - -IMGUI_ITEM(IMGUI_CANVAS_AXES_COLOR, self.label = "Color", self.tooltip = "Change the color of the axes.", self.flags = ImGuiColorEditFlags_NoInputs); - -IMGUI_ITEM(IMGUI_CANVAS_ROOT_TRANSFORM, self.label = "Root Transform", - self.tooltip = "Toggles the root frames's attributes transforming " - "the other items in an animation.", - self.value = SETTINGS_PREVIEW_IS_ROOT_TRANSFORM_DEFAULT); - -IMGUI_ITEM(IMGUI_CANVAS_TRIGGERS, self.label = "Triggers", self.tooltip = "Toggles activated triggers drawing their event name.", - self.value = SETTINGS_PREVIEW_IS_TRIGGERS_DEFAULT); - -IMGUI_ITEM(IMGUI_CANVAS_PIVOTS, self.label = "Pivots", self.tooltip = "Toggles drawing each layer's pivot.", self.value = SETTINGS_PREVIEW_IS_PIVOTS_DEFAULT); - -IMGUI_ITEM(IMGUI_CANVAS_ICONS, self.label = "Icons", self.tooltip = "Toggles drawing the the colored root/null icons.", - self.value = SETTINGS_PREVIEW_IS_ICONS_DEFAULT); - -IMGUI_ITEM(IMGUI_CANVAS_ALT_ICONS, self.label = "Alt Icons", - self.tooltip = "Toggles the use of alternate icons for the targets " - "(the colored root/null icons).", - self.value = SETTINGS_PREVIEW_IS_ALT_ICONS_DEFAULT); - -IMGUI_ITEM(IMGUI_CANVAS_BORDER, self.label = "Border", self.tooltip = "Toggles the appearance of a border around the items.", - self.value = SETTINGS_PREVIEW_IS_BORDER_DEFAULT); - -IMGUI_ITEM(IMGUI_ANIMATION_PREVIEW, self.label = "Animation Preview", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -#define IMGUI_ANIMATION_PREVIEW_VIEW_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_ANIMATION_PREVIEW_CENTER_VIEW, self.label = "Center View", self.tooltip = "Centers the current view on the animation preview.", - self.hotkey = HOTKEY_CENTER_VIEW, self.focusWindow = IMGUI_ANIMATION_PREVIEW.label, self.rowCount = IMGUI_ANIMATION_PREVIEW_VIEW_ROW_COUNT, - self.isSameLine = true); - -IMGUI_ITEM(IMGUI_ANIMATION_PREVIEW_FIT, self.label = "Fit", - self.tooltip = "Adjust the view/pan based on the size of the " - "animation, to fit the canvas' size.", - self.hotkey = HOTKEY_FIT, self.focusWindow = IMGUI_ANIMATION_PREVIEW.label, self.rowCount = IMGUI_ANIMATION_PREVIEW_VIEW_ROW_COUNT); - -IMGUI_ITEM(IMGUI_SPRITESHEET_EDITOR, self.label = "Spritesheet Editor", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -#define IMGUI_SPRITESHEET_EDITOR_VIEW_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_SPRITESHEET_EDITOR_CENTER_VIEW, self.label = "Center View", self.tooltip = "Centers the current view on the spritesheet editor.", - self.hotkey = HOTKEY_CENTER_VIEW, self.focusWindow = IMGUI_SPRITESHEET_EDITOR.label, self.rowCount = IMGUI_SPRITESHEET_EDITOR_VIEW_ROW_COUNT, - self.isSameLine = true); - -IMGUI_ITEM(IMGUI_SPRITESHEET_EDITOR_FIT, self.label = "Fit", - self.tooltip = "Adjust the view/pan based on the size of the " - "spritesheet, to fit the canvas' size.", - self.hotkey = HOTKEY_FIT, self.focusWindow = IMGUI_SPRITESHEET_EDITOR.label, self.rowCount = IMGUI_SPRITESHEET_EDITOR_VIEW_ROW_COUNT); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES, self.label = "Frame Properties"); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_POSITION, self.label = "Position", self.tooltip = "Change the position of the selected frame.", - self.snapshotAction = "Frame Position", self.isUseItemActivated = true); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_CROP, self.label = "Crop", self.tooltip = "Change the crop position of the selected frame.", - self.snapshotAction = "Frame Crop", self.isUseItemActivated = true); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_SIZE, self.label = "Size", self.tooltip = "Change the size of the crop of the selected frame.", - self.snapshotAction = "Frame Size", self.isUseItemActivated = true); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_PIVOT, self.label = "Pivot", self.tooltip = "Change the pivot of the selected frame.", self.snapshotAction = "Frame Pivot", - self.isUseItemActivated = true); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_SCALE, self.label = "Scale", self.tooltip = "Change the scale of the selected frame.", self.snapshotAction = "Frame Scale", - self.isUseItemActivated = true); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_ROTATION, self.label = "Rotation", self.tooltip = "Change the rotation of the selected frame.", - self.snapshotAction = "Frame Rotation", self.isUseItemActivated = true); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_DELAY, self.label = "Duration", self.tooltip = "Change the duration of the selected frame.", - self.snapshotAction = "Frame Duration", self.isUseItemActivated = true, self.min = ANM2_FRAME_NUM_MIN, self.max = ANM2_FRAME_NUM_MAX, - self.value = ANM2_FRAME_NUM_MIN); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_TINT, self.label = "Tint", self.tooltip = "Change the tint of the selected frame.", self.snapshotAction = "Frame Tint", - self.isUseItemActivated = true, self.value = 1); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_COLOR_OFFSET, self.label = "Color Offset", self.tooltip = "Change the color offset of the selected frame.", - self.snapshotAction = "Frame Color Offset", self.isUseItemActivated = true, self.value = 0); - -#define IMGUI_FRAME_PROPERTIES_FLIP_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_FLIP_X, self.label = "Flip X", - self.tooltip = "Change the sign of the X scale, to cheat flipping the layer " - "horizontally.\n(Anm2 doesn't support flipping directly.)", - self.snapshotAction = "Frame Flip X", self.rowCount = IMGUI_FRAME_PROPERTIES_FLIP_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_FLIP_Y, self.label = "Flip Y", - self.tooltip = "Change the sign of the Y scale, to cheat flipping the layer " - "vertically.\n(Anm2 doesn't support flipping directly.)", - self.snapshotAction = "Frame Flip Y", self.rowCount = IMGUI_FRAME_PROPERTIES_FLIP_ROW_COUNT); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_VISIBLE, self.label = "Visible", self.tooltip = "Toggles the visibility of the selected frame.", - self.snapshotAction = "Frame Visibility", self.isSameLine = true, self.value = true); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_INTERPOLATED, self.label = "Interpolation", self.tooltip = "Toggles the interpolation of the selected frame.", - self.snapshotAction = "Frame Interpolation", self.isSameLine = true, self.value = true); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_ROUND, self.label = "Round", self.tooltip = "Values will be rounded to the nearest integer.", - self.value = SETTINGS_PROPERTIES_IS_ROUND_DEFAULT); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_EVENT, self.label = "Event", self.tooltip = "Change the event the trigger uses.", self.snapshotAction = "Trigger Event"); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_AT_FRAME, self.label = "At Frame", self.tooltip = "Change the frame where the trigger occurs.", - self.snapshotAction = "Trigger At Frame"); - -IMGUI_ITEM(IMGUI_TOOLS, self.label = "Tools"); - -IMGUI_ITEM(IMGUI_TOOL_PAN, self.label = "## Pan", - self.tooltip = "Use the pan tool.\nWill shift the view as the cursor is dragged.\nYou " - "can also use the middle mouse button to pan at any time.", - self.function = imgui_tool_pan_set, self.hotkey = HOTKEY_PAN, self.atlas = ATLAS_PAN, self.isAtlasStretch = true); - -IMGUI_ITEM(IMGUI_TOOL_MOVE, self.label = "## Move", - self.tooltip = "Use the move tool.\nAnimation Preview: Will move the position " - "of the frame." - "\nSpritesheet Editor: Will move the pivot, and holding right " - "click will use the Crop functionality instead." - "\nUse mouse or directional keys to change the value.", - self.function = imgui_tool_move_set, self.hotkey = HOTKEY_MOVE, self.atlas = ATLAS_MOVE); - -IMGUI_ITEM(IMGUI_TOOL_ROTATE, self.label = "## Rotate", - self.tooltip = "Use the rotate tool.\nWill rotate the selected item as the cursor is " - "dragged, or directional keys are pressed.\n(Animation Preview only.)", - self.function = imgui_tool_rotate_set, self.hotkey = HOTKEY_ROTATE, self.atlas = ATLAS_ROTATE); - -IMGUI_ITEM(IMGUI_TOOL_SCALE, self.label = "## Scale", - self.tooltip = "Use the scale tool.\nWill scale the selected item as the cursor is " - "dragged, or directional keys are pressed.\n(Animation Preview only.)", - self.function = imgui_tool_scale_set, self.hotkey = HOTKEY_SCALE, self.atlas = ATLAS_SCALE); - -IMGUI_ITEM(IMGUI_TOOL_CROP, self.label = "## Crop", - self.tooltip = "Use the crop tool.\nWill produce a crop rectangle based on how " - "the cursor is dragged." - "\nAlternatively, you can use the arrow keys and Ctrl/Shift to " - "move the size/position, respectively." - "\nHolding right click will use the Move tool's functionality." - "\n(Spritesheet Editor only.)", - self.function = imgui_tool_crop_set, self.hotkey = HOTKEY_CROP, self.atlas = ATLAS_CROP); - -IMGUI_ITEM(IMGUI_TOOL_DRAW, self.label = "## Draw", - self.tooltip = "Draws pixels onto the selected spritesheet, with " - "the current color.\n(Spritesheet Editor only.)", - self.function = imgui_tool_draw_set, self.hotkey = HOTKEY_DRAW, self.atlas = ATLAS_DRAW); - -IMGUI_ITEM(IMGUI_TOOL_ERASE, self.label = "## Erase", - self.tooltip = "Erases pixels from the selected " - "spritesheet.\n(Spritesheet Editor only.)", - self.function = imgui_tool_erase_set, self.hotkey = HOTKEY_ERASE, self.atlas = ATLAS_ERASE); - -IMGUI_ITEM(IMGUI_TOOL_COLOR_PICKER, self.label = "## Color Picker", - self.tooltip = "Selects a color from the canvas, to be used for " - "drawing.\n(Spritesheet Editor only).", - self.function = imgui_tool_color_picker_set, self.hotkey = HOTKEY_COLOR_PICKER, self.atlas = ATLAS_COLOR_PICKER); - -IMGUI_ITEM(IMGUI_TOOL_UNDO, self.label = "## Undo", self.tooltip = "Undo the last action.", self.function = imgui_undo, self.hotkey = HOTKEY_UNDO, - self.atlas = ATLAS_UNDO); - -IMGUI_ITEM(IMGUI_TOOL_REDO, self.label = "## Redo", self.tooltip = "Redo the last action.", self.function = imgui_redo, self.hotkey = HOTKEY_REDO, - self.atlas = ATLAS_REDO); - -IMGUI_ITEM(IMGUI_TOOL_COLOR, self.label = "## Color", self.tooltip = "Set the color, to be used by the draw tool.", self.flags = ImGuiColorEditFlags_NoInputs); - -const inline ImguiItem* IMGUI_TOOL_ITEMS[TOOL_COUNT] = {&IMGUI_TOOL_PAN, &IMGUI_TOOL_MOVE, &IMGUI_TOOL_ROTATE, &IMGUI_TOOL_SCALE, - &IMGUI_TOOL_CROP, &IMGUI_TOOL_DRAW, &IMGUI_TOOL_ERASE, &IMGUI_TOOL_COLOR_PICKER, - &IMGUI_TOOL_UNDO, &IMGUI_TOOL_REDO, &IMGUI_TOOL_COLOR}; - -IMGUI_ITEM(IMGUI_COLOR_PICKER_BUTTON, self.label = "## Color Picker Button"); - -IMGUI_ITEM(IMGUI_TIMELINE, self.label = "Timeline", self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -IMGUI_ITEM(IMGUI_TIMELINE_CHILD, self.label = "## Timeline Child", self.flags = true); - -IMGUI_ITEM(IMGUI_TIMELINE_HEADER_CHILD, self.label = "## Timeline Header Child", self.size = {0, IMGUI_TIMELINE_FRAME_SIZE.y}, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -IMGUI_ITEM(IMGUI_PLAYHEAD, self.label = "## Playhead", - self.flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground | - ImGuiWindowFlags_NoInputs); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEMS_CHILD, self.label = "## Timeline Items", self.size = {IMGUI_TIMELINE_ITEM_SIZE.x, 0}, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_CHILD, self.label = "## Timeline Item Child", self.size = IMGUI_TIMELINE_ITEM_SIZE, self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_ROOT_CHILD, self.label = "## Root Item Child", self.color.normal = {0.045f, 0.08f, 0.11f, 1.0f}, - self.size = IMGUI_TIMELINE_ITEM_SIZE, self.flags = true, self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_LAYER_CHILD, self.label = "## Layer Item Child", self.color.normal = {0.0875f, 0.05f, 0.015f, 1.0f}, - self.size = IMGUI_TIMELINE_ITEM_SIZE, self.flags = true, self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_NULL_CHILD, self.label = "## Null Item Child", self.color.normal = {0.055f, 0.10f, 0.055f, 1.0f}, - self.size = IMGUI_TIMELINE_ITEM_SIZE, self.flags = true, self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_TRIGGERS_CHILD, self.label = "## Triggers Item Child", self.color.normal = {0.10f, 0.0375f, 0.07f, 1.0f}, - self.size = IMGUI_TIMELINE_ITEM_SIZE, self.flags = true, self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -const inline ImguiItem* IMGUI_TIMELINE_ITEM_CHILDS[ANM2_COUNT]{&IMGUI_TIMELINE_ITEM_CHILD, &IMGUI_TIMELINE_ITEM_ROOT_CHILD, &IMGUI_TIMELINE_ITEM_LAYER_CHILD, - &IMGUI_TIMELINE_ITEM_NULL_CHILD, &IMGUI_TIMELINE_ITEM_TRIGGERS_CHILD}; - -#define IMGUI_POPUP_ITEM_PROPERTIES "Item Properties" -#define IMGUI_POPUP_ITEM_PROPERTIES_TYPE IMGUI_POPUP_CENTER_WINDOW -const ImVec2 IMGUI_POPUP_ITEM_PROPERTIES_SIZE = {300, 350}; - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, self.label = "## Item Properties Type Child", self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 35}, - self.flags = true); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER, self.label = "Layer", - self.tooltip = "The item will be a layer item.\nA layer item is a " - "primary graphical item, using a spritesheet.", - self.isWidthToText = true, self.value = ANM2_LAYER, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL, self.label = "Null", - self.tooltip = "The item will be a null item.\nA null item is an " - "invisible item, often accessed by a game engine.", - self.isWidthToText = true, self.value = ANM2_NULL); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, self.label = "## Item Properties Items", self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 250}, - self.flags = true); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD, self.label = "## Item Properties Options Child", self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 35}, - self.flags = true); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_CONFIRM, self.label = "Confirm", self.tooltip = "Set the timeline item's properties.", - self.snapshotAction = "Timeline Item Change", self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_SELECTABLE, self.label = "## Selectable", self.size = IMGUI_TIMELINE_ITEM_SIZE); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_ROOT_SELECTABLE, self.label = "Root", - self.tooltip = "The root item of an animation.\nChanging its properties " - "will transform the rest of the animation.", - self.size = IMGUI_TIMELINE_ITEM_SIZE); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_LAYER_SELECTABLE, self.label = "## Layer Selectable", self.tooltip = "A layer item.\nA graphical item within the animation.", - self.dragDrop = "## Layer Drag Drop", self.color.active = {0.45f, 0.18f, 0.07f, 1.0f}, self.popup = IMGUI_POPUP_ITEM_PROPERTIES, - self.popupType = IMGUI_POPUP_ITEM_PROPERTIES_TYPE, self.size = IMGUI_TIMELINE_ITEM_SIZE); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_NULL_SELECTABLE, self.label = "## Null Selectable", - self.tooltip = "A null item.\nAn invisible item within the " - "animation that is accessible via a game engine.", - self.dragDrop = "## Null Drag Drop", self.popup = IMGUI_POPUP_ITEM_PROPERTIES, self.popupType = IMGUI_POPUP_ITEM_PROPERTIES_TYPE, - self.size = IMGUI_TIMELINE_ITEM_SIZE); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_TRIGGERS_SELECTABLE, self.label = "Triggers", self.tooltip = "The animation's triggers.\nWill fire based on an event.", - self.size = IMGUI_TIMELINE_ITEM_SIZE); - -const inline ImguiItem* IMGUI_TIMELINE_ITEM_SELECTABLES[ANM2_COUNT]{&IMGUI_TIMELINE_ITEM_SELECTABLE, &IMGUI_TIMELINE_ITEM_ROOT_SELECTABLE, - &IMGUI_TIMELINE_ITEM_LAYER_SELECTABLE, &IMGUI_TIMELINE_ITEM_NULL_SELECTABLE, - &IMGUI_TIMELINE_ITEM_TRIGGERS_SELECTABLE}; - -IMGUI_ITEM(IMGUI_TIMELINE_SHOW_UNUSED, self.label = "## Show Unused", self.tooltip = "Layers/nulls without any frames will be hidden.", - self.snapshotAction = "Hide Unused", self.atlas = ATLAS_SHOW_UNUSED); - -IMGUI_ITEM(IMGUI_TIMELINE_HIDE_UNUSED, self.label = "## Hide Unused", self.tooltip = "Layers/nulls without any frames will be shown.", - self.snapshotAction = "Show Unused", self.atlas = ATLAS_HIDE_UNUSED); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_VISIBLE, self.label = "## Visible", self.tooltip = "The item is visible.\nPress to set to invisible.", - self.snapshotAction = "Item Invisible", self.atlas = ATLAS_VISIBLE); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_INVISIBLE, self.label = "## Invisible", self.tooltip = "The item is invisible.\nPress to set to visible.", - self.snapshotAction = "Item Visible", self.atlas = ATLAS_INVISIBLE); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_SHOW_RECT, self.label = "## Show Rect", self.tooltip = "The rect is shown.\nPress to hide rect.", - self.snapshotAction = "Hide Rect", self.atlas = ATLAS_SHOW_RECT); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_HIDE_RECT, self.label = "## Hide Rect", self.tooltip = "The rect is hidden.\nPress to show rect.", - self.snapshotAction = "Show Rect", self.atlas = ATLAS_HIDE_RECT); - -IMGUI_ITEM(IMGUI_TIMELINE_FRAMES_CHILD, self.label = "## Timeline Frames Child", - self.windowFlags = ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_HorizontalScrollbar); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_FRAMES_CHILD, self.label = "## Timeline Item Frames Child", self.size = {0, IMGUI_TIMELINE_FRAME_SIZE.y}); - -IMGUI_ITEM(IMGUI_TIMELINE_FRAME, self.label = "## Frame"); - -#define IMGUI_TIMELINE_FRAME_BORDER 5 -static const vec4 IMGUI_FRAME_BORDER_COLOR = {1.0f, 1.0f, 1.0f, 0.25f}; -IMGUI_ITEM(IMGUI_TIMELINE_ROOT_FRAME, self.label = "## Root Frame", self.snapshotAction = "Root Frame", - self.color = {vec4(0.14f, 0.27f, 0.39f, 1.0f), vec4(0.28f, 0.54f, 0.78f, 1.0f), vec4(0.36f, 0.70f, 0.95f, 1.0f), IMGUI_FRAME_BORDER_COLOR}, - self.size = IMGUI_TIMELINE_FRAME_SIZE, self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, self.border = IMGUI_FRAME_BORDER); - -IMGUI_ITEM(IMGUI_TIMELINE_LAYER_FRAME, self.label = "## Layer Frame", self.dragDrop = "## Layer Frame Drag Drop", self.snapshotAction = "Layer Frame", - self.color = {vec4(0.45f, 0.18f, 0.07f, 1.0f), vec4(0.78f, 0.32f, 0.12f, 1.0f), vec4(0.95f, 0.40f, 0.15f, 1.0f), IMGUI_FRAME_BORDER_COLOR}, - self.size = IMGUI_TIMELINE_FRAME_SIZE, self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, self.border = IMGUI_FRAME_BORDER); - -IMGUI_ITEM(IMGUI_TIMELINE_NULL_FRAME, self.label = "## Null Frame", self.dragDrop = "## Null Frame Drag Drop", self.snapshotAction = "Null Frame", - self.color = {vec4(0.17f, 0.33f, 0.17f, 1.0f), vec4(0.34f, 0.68f, 0.34f, 1.0f), vec4(0.44f, 0.88f, 0.44f, 1.0f), IMGUI_FRAME_BORDER_COLOR}, - self.size = IMGUI_TIMELINE_FRAME_SIZE, self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, self.border = IMGUI_FRAME_BORDER); - -IMGUI_ITEM(IMGUI_TIMELINE_TRIGGERS_FRAME, self.label = "## Triggers Frame", self.snapshotAction = "Trigger", - self.color = {vec4(0.36f, 0.14f, 0.24f, 1.0f), vec4(0.72f, 0.28f, 0.48f, 1.0f), vec4(0.92f, 0.36f, 0.60f, 1.0f), IMGUI_FRAME_BORDER_COLOR}, - self.size = IMGUI_TIMELINE_FRAME_SIZE, self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, self.border = IMGUI_FRAME_BORDER); - -const inline ImguiItem* IMGUI_TIMELINE_FRAMES[ANM2_COUNT]{&IMGUI_TIMELINE_FRAME, &IMGUI_TIMELINE_ROOT_FRAME, &IMGUI_TIMELINE_LAYER_FRAME, - &IMGUI_TIMELINE_NULL_FRAME, &IMGUI_TIMELINE_TRIGGERS_FRAME}; - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_FOOTER_CHILD, self.label = "## Item Footer Child", self.size = {IMGUI_TIMELINE_ITEM_CHILD.size->x, IMGUI_FOOTER_CHILD.size->y}, - self.flags = true, self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); -IMGUI_ITEM(IMGUI_TIMELINE_OPTIONS_FOOTER_CHILD, self.label = "## Options Footer Child", self.size = {0, IMGUI_FOOTER_CHILD.size->y}, self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - -#define IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT 2 -IMGUI_ITEM(IMGUI_TIMELINE_ADD_ITEM, self.label = "Add", - self.tooltip = "Adds an item (layer or null) to the animation.\nMake sure " - "to add a Layer/Null first in the Layers or Nulls windows.", - self.popup = "Add Item", self.popupType = IMGUI_POPUP_ITEM_PROPERTIES_TYPE, self.popupSize = {300, 350}, - self.rowCount = IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_TIMELINE_REMOVE_ITEM, self.label = "Remove", self.tooltip = "Removes the selected item (layer or null) from the animation.", - self.snapshotAction = "Remove Item", self.chord = ImGuiKey_Delete, self.focusWindow = IMGUI_TIMELINE_ITEMS_CHILD.label, - self.rowCount = IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT); - -#define IMGUI_TIMELINE_OPTIONS_ROW_COUNT 10 -IMGUI_ITEM(IMGUI_PLAY, self.label = "|> Play", self.tooltip = "Play the current animation, if paused.", self.focusWindow = IMGUI_TIMELINE.label, - self.hotkey = HOTKEY_PLAY_PAUSE, self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_PAUSE, self.label = "|| Pause", self.tooltip = "Pause the current animation, if playing.", self.focusWindow = IMGUI_TIMELINE.label, - self.hotkey = HOTKEY_PLAY_PAUSE, self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_INSERT_FRAME, self.label = "+ Insert Frame", - self.tooltip = "Inserts a frame in the selected animation item, " - "based on the preview time.", - self.snapshotAction = "Insert Frame", self.hotkey = HOTKEY_INSERT_FRAME, self.focusWindow = IMGUI_TIMELINE.label, - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_REMOVE_FRAME, self.label = "- Delete Frame", self.tooltip = "Removes the selected frame from the selected animation item.", - self.snapshotAction = "Delete Frame", self.focusWindow = IMGUI_TIMELINE.label, self.chord = ImGuiKey_Delete, - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.isSameLine = true); - -static inline void imgui_shorten_frame(Imgui* self) { - if (self->reference->itemType == ANM2_TRIGGER) - return; - if (Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *self->reference)) - frame->delay = std::max(ANM2_FRAME_DELAY_MIN, frame->delay - 1); -} - -IMGUI_ITEM(IMGUI_SHORTEN_FRAME, self.label = "## Shorten Frame", self.snapshotAction = "Shorten Frame", self.hotkey = HOTKEY_SHORTEN_FRAME, - self.function = imgui_shorten_frame); - -static inline void imgui_extend_frame(Imgui* self) { - if (self->reference->itemType == ANM2_TRIGGER) - return; - if (Anm2Frame* frame = anm2_frame_from_reference(self->anm2, *self->reference)) - frame->delay++; -} - -IMGUI_ITEM(IMGUI_EXTEND_FRAME, self.label = "## Extend Frame", self.snapshotAction = "Extend Frame", self.hotkey = HOTKEY_EXTEND_FRAME, - self.function = imgui_extend_frame); - -static inline void imgui_next_frame(Imgui* self) { - if (Anm2Item* item = anm2_item_from_reference(self->anm2, *self->reference)) { - self->reference->frameIndex = std::min((int)(item->frames.size() - 1), self->reference->frameIndex + 1); - self->preview->time = anm2_time_from_reference(self->anm2, *self->reference); - } -} - -IMGUI_ITEM(IMGUI_NEXT_FRAME, self.label = "## Next Frame", self.hotkey = HOTKEY_NEXT_FRAME, self.function = imgui_next_frame); - -static inline void imgui_previous_frame(Imgui* self) { - if (anm2_item_from_reference(self->anm2, *self->reference)) { - self->reference->frameIndex = std::max(0, self->reference->frameIndex - 1); - self->preview->time = anm2_time_from_reference(self->anm2, *self->reference); - } -} - -IMGUI_ITEM(IMGUI_PREVIOUS_FRAME, self.label = "## Previous Frame", self.hotkey = HOTKEY_PREVIOUS_FRAME, self.function = imgui_previous_frame); - -IMGUI_ITEM(IMGUI_BAKE, self.label = "Bake", - self.tooltip = "Opens the bake popup menu, if a frame is selected.\nBaking a frame " - "takes the currently interpolated values at the time between it and " - "the next frame and separates them based on the interval.", - self.popup = "Bake Frames", self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.popupSize = {260, 145}, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_BAKE_CHILD, self.label = "## Bake Child", self.flags = true); - -IMGUI_ITEM(IMGUI_BAKE_INTERVAL, self.label = "Interval", - self.tooltip = "Sets the delay of the baked frames the selected " - "frame will be separated out into.", - self.min = ANM2_FRAME_DELAY_MIN, self.value = ANM2_FRAME_DELAY_MIN); - -IMGUI_ITEM(IMGUI_BAKE_ROUND_SCALE, self.label = "Round Scale", self.tooltip = "The scale of the baked frames will be rounded to the nearest integer.", - self.value = true); - -IMGUI_ITEM(IMGUI_BAKE_ROUND_ROTATION, self.label = "Round Rotation", - self.tooltip = "The rotation of the baked frames will be rounded to " - "the nearest integer.", - self.value = true, self.isSeparator = true); - -IMGUI_ITEM(IMGUI_BAKE_CONFIRM, self.label = "Bake", self.tooltip = "Bake the selected frame with the options selected.", self.snapshotAction = "Bake Frames", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_FIT_ANIMATION_LENGTH, self.label = "Fit Animation Length", self.tooltip = "Sets the animation's length to the latest frame.", - self.snapshotAction = "Fit Animation Length", self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_ANIMATION_LENGTH, self.label = "Length", self.tooltip = "Sets the animation length.\n(Will not change frames.)", - self.snapshotAction = "Set Animation Length", self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.min = ANM2_FRAME_NUM_MIN, - self.max = ANM2_FRAME_NUM_MAX, self.value = ANM2_FRAME_NUM_MIN, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_FPS, self.label = "FPS", self.tooltip = "Sets the animation's frames per second (its speed).", self.snapshotAction = "Set FPS", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.min = ANM2_FPS_MIN, self.max = ANM2_FPS_MAX, self.value = ANM2_FPS_DEFAULT, - self.isSameLine = true); - -IMGUI_ITEM(IMGUI_LOOP, self.label = "Loop", self.tooltip = "Toggles the animation looping.", self.snapshotAction = "Set Loop", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, self.value = true, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_CREATED_BY, self.label = "Author", self.tooltip = "Sets the author of the animation.", self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.max = UCHAR_MAX); - -#define IMGUI_ONIONSKIN_ROW_COUNT 3 -IMGUI_ITEM(IMGUI_ONIONSKIN, self.label = "Onionskin"); -IMGUI_ITEM(IMGUI_ONIONSKIN_ENABLED, self.label = "Enabled", self.tooltip = "Toggle onionskin (previews of frames before/after the current one.)", - self.function = imgui_onionskin_toggle, self.hotkey = HOTKEY_ONIONSKIN, self.isSeparator = true); - -IMGUI_ITEM(IMGUI_ONIONSKIN_BEFORE, self.label = "-- Before -- "); -IMGUI_ITEM(IMGUI_ONIONSKIN_AFTER, self.label = "-- After -- "); - -IMGUI_ITEM(IMGUI_ONIONSKIN_COUNT, self.label = "Count", self.tooltip = "Set the number of previewed frames appearing.", self.min = 0, self.max = 100, - self.value = SETTINGS_ONIONSKIN_BEFORE_COUNT_DEFAULT, self.rowCount = IMGUI_ONIONSKIN_ROW_COUNT, self.isSameLine = true); - -IMGUI_ITEM(IMGUI_ONIONSKIN_COLOR_OFFSET, self.label = "Color Offset", self.tooltip = "Set the color offset of the previewed frames.", - self.flags = ImGuiColorEditFlags_NoInputs, self.rowCount = IMGUI_ONIONSKIN_ROW_COUNT); - -IMGUI_ITEM(IMGUI_ONIONSKIN_DRAW_ORDER, self.label = "Draw Order", self.isSameLine = true); - -IMGUI_ITEM(IMGUI_ONIONSKIN_BELOW, self.label = "Below", self.tooltip = "The onionskin frames will draw below the base frame.", self.value = ONIONSKIN_BELOW, - self.isSameLine = true); - -IMGUI_ITEM(IMGUI_ONIONSKIN_ABOVE, self.label = "Above", self.tooltip = "The onionskin frames will draw above the base frame.", self.value = ONIONSKIN_ABOVE); - -IMGUI_ITEM(IMGUI_CONTEXT_MENU, self.label = "## Context Menu"); - -IMGUI_ITEM(IMGUI_CUT, self.label = "Cut", - self.tooltip = "Cuts the currently selected contextual element; " - "removing it and putting it to the clipboard.", - self.snapshotAction = "Cut", self.function = imgui_cut, self.hotkey = HOTKEY_CUT, self.isWidthToText = true); - -IMGUI_ITEM(IMGUI_COPY, self.label = "Copy", self.tooltip = "Copies the currently selected contextual element to the clipboard.", self.function = imgui_copy, - self.hotkey = HOTKEY_COPY, self.isWidthToText = true); - -IMGUI_ITEM(IMGUI_PASTE, self.label = "Paste", self.tooltip = "Pastes the currently selection contextual element from the clipboard.", - self.snapshotAction = "Paste", self.function = imgui_paste, self.hotkey = HOTKEY_PASTE, self.isWidthToText = true); - -IMGUI_ITEM(IMGUI_CHANGE_INPUT_TEXT, self.label = "## Input Text", self.tooltip = "Rename the selected item.", self.snapshotAction = "Rename", - self.flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue, self.max = 0xFFFF); - -IMGUI_ITEM(IMGUI_CHANGE_INPUT_INT, self.label = "## Input Int", self.tooltip = "Change the selected item's value.", self.snapshotAction = "Change Value", - self.step = 0); - -#define IMGUI_CONFIRM_POPUP_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_POPUP_OK, self.label = "OK", self.tooltip = "Confirm the action.", self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT); - -IMGUI_ITEM(IMGUI_POPUP_CANCEL, self.label = "Cancel", self.tooltip = "Cancel the action.", self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT); - -IMGUI_ITEM(IMGUI_LOG_WINDOW, self.label = "## Log Window", - self.flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | - ImGuiWindowFlags_NoInputs); - -IMGUI_ITEM(IMGUI_ATLAS, self.label = "## Atlas Image", self.atlas = ATLAS_NONE); - -void imgui_init(Imgui* self, Dialog* dialog, Resources* resources, Anm2* anm2, Anm2Reference* reference, Editor* editor, Preview* preview, - GeneratePreview* generatePreview, Settings* settings, Snapshots* snapshots, Clipboard* clipboard, SDL_Window* window, SDL_GLContext* glContext); - -void imgui_update(Imgui* self); -void imgui_draw(); -void imgui_free(); \ No newline at end of file +#include +#include +#include + +namespace anm2ed::imgui +{ + const std::unordered_map KEY_MAP = {{"A", ImGuiKey_A}, + {"B", ImGuiKey_B}, + {"C", ImGuiKey_C}, + {"D", ImGuiKey_D}, + {"E", ImGuiKey_E}, + {"F", ImGuiKey_F}, + {"G", ImGuiKey_G}, + {"H", ImGuiKey_H}, + {"I", ImGuiKey_I}, + {"J", ImGuiKey_J}, + {"K", ImGuiKey_K}, + {"L", ImGuiKey_L}, + {"M", ImGuiKey_M}, + {"N", ImGuiKey_N}, + {"O", ImGuiKey_O}, + {"P", ImGuiKey_P}, + {"Q", ImGuiKey_Q}, + {"R", ImGuiKey_R}, + {"S", ImGuiKey_S}, + {"T", ImGuiKey_T}, + {"U", ImGuiKey_U}, + {"V", ImGuiKey_V}, + {"W", ImGuiKey_W}, + {"X", ImGuiKey_X}, + {"Y", ImGuiKey_Y}, + {"Z", ImGuiKey_Z}, + + {"0", ImGuiKey_0}, + {"1", ImGuiKey_1}, + {"2", ImGuiKey_2}, + {"3", ImGuiKey_3}, + {"4", ImGuiKey_4}, + {"5", ImGuiKey_5}, + {"6", ImGuiKey_6}, + {"7", ImGuiKey_7}, + {"8", ImGuiKey_8}, + {"9", ImGuiKey_9}, + + {"Num0", ImGuiKey_Keypad0}, + {"Num1", ImGuiKey_Keypad1}, + {"Num2", ImGuiKey_Keypad2}, + {"Num3", ImGuiKey_Keypad3}, + {"Num4", ImGuiKey_Keypad4}, + {"Num5", ImGuiKey_Keypad5}, + {"Num6", ImGuiKey_Keypad6}, + {"Num7", ImGuiKey_Keypad7}, + {"Num8", ImGuiKey_Keypad8}, + {"Num9", ImGuiKey_Keypad9}, + {"NumAdd", ImGuiKey_KeypadAdd}, + {"NumSubtract", ImGuiKey_KeypadSubtract}, + {"NumMultiply", ImGuiKey_KeypadMultiply}, + {"NumDivide", ImGuiKey_KeypadDivide}, + {"NumEnter", ImGuiKey_KeypadEnter}, + {"NumDecimal", ImGuiKey_KeypadDecimal}, + + {"F1", ImGuiKey_F1}, + {"F2", ImGuiKey_F2}, + {"F3", ImGuiKey_F3}, + {"F4", ImGuiKey_F4}, + {"F5", ImGuiKey_F5}, + {"F6", ImGuiKey_F6}, + {"F7", ImGuiKey_F7}, + {"F8", ImGuiKey_F8}, + {"F9", ImGuiKey_F9}, + {"F10", ImGuiKey_F10}, + {"F11", ImGuiKey_F11}, + {"F12", ImGuiKey_F12}, + + {"Up", ImGuiKey_UpArrow}, + {"Down", ImGuiKey_DownArrow}, + {"Left", ImGuiKey_LeftArrow}, + {"Right", ImGuiKey_RightArrow}, + + {"Space", ImGuiKey_Space}, + {"Enter", ImGuiKey_Enter}, + {"Escape", ImGuiKey_Escape}, + {"Tab", ImGuiKey_Tab}, + {"Backspace", ImGuiKey_Backspace}, + {"Delete", ImGuiKey_Delete}, + {"Insert", ImGuiKey_Insert}, + {"Home", ImGuiKey_Home}, + {"End", ImGuiKey_End}, + {"PageUp", ImGuiKey_PageUp}, + {"PageDown", ImGuiKey_PageDown}, + + {"Minus", ImGuiKey_Minus}, + {"Equal", ImGuiKey_Equal}, + {"LeftBracket", ImGuiKey_LeftBracket}, + {"RightBracket", ImGuiKey_RightBracket}, + {"Semicolon", ImGuiKey_Semicolon}, + {"Apostrophe", ImGuiKey_Apostrophe}, + {"Comma", ImGuiKey_Comma}, + {"Period", ImGuiKey_Period}, + {"Slash", ImGuiKey_Slash}, + {"Backslash", ImGuiKey_Backslash}, + {"GraveAccent", ImGuiKey_GraveAccent}, + + {"MouseLeft", ImGuiKey_MouseLeft}, + {"MouseRight", ImGuiKey_MouseRight}, + {"MouseMiddle", ImGuiKey_MouseMiddle}, + {"MouseX1", ImGuiKey_MouseX1}, + {"MouseX2", ImGuiKey_MouseX2}}; + + const std::unordered_map MOD_MAP = { + {"Ctrl", ImGuiMod_Ctrl}, + {"Shift", ImGuiMod_Shift}, + {"Alt", ImGuiMod_Alt}, + {"Super", ImGuiMod_Super}, + }; + + std::string chord_to_string(ImGuiKeyChord chord); + ImGuiKeyChord string_to_chord(const std::string& string); + float row_widget_width_get(int count, float width = ImGui::GetContentRegionAvail().x); + ImVec2 widget_size_with_row_get(int count, float width = ImGui::GetContentRegionAvail().x); + float footer_height_get(int itemCount = 1); + ImVec2 size_with_footer_get(int rowCount = 1); + ImVec2 child_size_get(int rowCount = 1, bool isContentRegionAvail = false); + int input_text_callback(ImGuiInputTextCallbackData* data); + bool input_text_string(const char* label, std::string* string, ImGuiInputTextFlags flags = 0); + void combo_strings(const std::string& label, int* index, std::vector& strings); + bool selectable_input_text(const std::string& label, const std::string& id, std::string& text, + bool isSelected = false, ImGuiSelectableFlags flags = 0); + void set_item_tooltip_shortcut(const std::string& tooltip, const std::string& shortcut = {}); + void external_storage_set(ImGuiSelectionExternalStorage* self, int id, bool isSelected); + ImVec2 icon_size_get(); + bool chord_held(ImGuiKeyChord chord); + bool chord_repeating(ImGuiKeyChord chord, float delay = 0.125f, float rate = 0.025f); + bool shortcut(std::string string, bool isSet = false, bool isGlobal = false, bool isPopupBlock = true); +} \ No newline at end of file diff --git a/src/layers.cpp b/src/layers.cpp new file mode 100644 index 0000000..07536d9 --- /dev/null +++ b/src/layers.cpp @@ -0,0 +1,81 @@ +#include "layers.h" + +#include + +#include "imgui.h" + +using namespace anm2ed::document_manager; +using namespace anm2ed::settings; +using namespace anm2ed::resources; +using namespace anm2ed::types; + +namespace anm2ed::layers +{ + void Layers::update(DocumentManager& manager, Settings& settings, Resources& resources) + { + if (ImGui::Begin("Layers", &settings.windowIsLayers)) + { + auto document = manager.get(); + anm2::Anm2& anm2 = document->anm2; + + auto& selection = document->selectedLayers; + storage.UserData = &selection; + storage.AdapterSetItemSelected = imgui::external_storage_set; + + auto childSize = imgui::size_with_footer_get(); + + if (ImGui::BeginChild("##Layers Child", childSize, true)) + { + ImGuiMultiSelectIO* io = + ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, selection.size(), anm2.content.layers.size()); + storage.ApplyRequests(io); + + for (auto& [id, layer] : anm2.content.layers) + { + auto isSelected = selection.contains(id); + + ImGui::PushID(id); + ImGui::SetNextItemSelectionUserData(id); + imgui::selectable_input_text(std::format("#{} {}", id, layer.name), + std::format("###Document #{} Layer #{}", manager.selected, id), layer.name, + isSelected); + if (ImGui::BeginItemTooltip()) + { + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); + ImGui::TextUnformatted(layer.name.c_str()); + ImGui::TextUnformatted(std::format("ID: {}", id).c_str()); + ImGui::TextUnformatted(std::format("Spritesheet ID: {}", layer.spritesheetID).c_str()); + ImGui::PopFont(); + ImGui::EndTooltip(); + } + ImGui::PopID(); + } + + io = ImGui::EndMultiSelect(); + storage.ApplyRequests(io); + } + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + imgui::shortcut(settings.shortcutAdd, true); + ImGui::Button("Add", widgetSize); + imgui::set_item_tooltip_shortcut("Add a layer.", settings.shortcutAdd); + ImGui::SameLine(); + + std::set unusedLayersIDs = anm2.layers_unused(); + + imgui::shortcut(settings.shortcutRemove, true); + ImGui::BeginDisabled(unusedLayersIDs.empty()); + { + if (ImGui::Button("Remove Unused", widgetSize)) + for (auto& id : unusedLayersIDs) + anm2.content.layers.erase(id); + } + ImGui::EndDisabled(); + imgui::set_item_tooltip_shortcut("Remove unused layers (i.e., ones not used in any animation.)", + settings.shortcutRemove); + } + ImGui::End(); + } +} diff --git a/src/layers.h b/src/layers.h new file mode 100644 index 0000000..5007e68 --- /dev/null +++ b/src/layers.h @@ -0,0 +1,17 @@ +#pragma once + +#include "document_manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::layers +{ + class Layers + { + ImGuiSelectionExternalStorage storage{}; + + public: + void update(document_manager::DocumentManager& manager, settings::Settings& settings, + resources::Resources& resources); + }; +} \ No newline at end of file diff --git a/src/loader.cpp b/src/loader.cpp new file mode 100644 index 0000000..034c126 --- /dev/null +++ b/src/loader.cpp @@ -0,0 +1,93 @@ +#include "loader.h" + +#include +#include + +#include "filesystem.h" +#include "log.h" + +using namespace anm2ed::log; +using namespace anm2ed::settings; +using namespace anm2ed::types; + +namespace anm2ed::loader +{ + std::string settings_path() + { + return filesystem::path_preferences_get() + "settings.ini"; + } + + Loader::Loader(int argc, const char** argv) + { + for (int i = 1; i < argc; i++) + arguments.emplace_back(argv[i]); + + if (!SDL_Init(SDL_INIT_VIDEO)) + { + logger.fatal(std::format("Could not initialize SDL! {}", SDL_GetError())); + isError = true; + return; + } + + settings = Settings(settings_path()); + + window = SDL_CreateWindow("Anm2Ed", settings.windowSize.x, settings.windowSize.y, + SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_HIGH_PIXEL_DENSITY); + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + + glContext = SDL_GL_CreateContext(window); + + if (!glContext) + { + logger.fatal(std::format("Could not initialize OpenGL context! {}", SDL_GetError())); + isError = true; + return; + } + + if (!gladLoadGLLoader((GLADloadproc)(SDL_GL_GetProcAddress))) + { + logger.fatal(std::format("Could not initialize OpenGL!")); + isError = true; + return; + } + + logger.info(std::format("OpenGL {}", (const char*)glGetString(GL_VERSION))); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glLineWidth(2.0f); + glDisable(GL_MULTISAMPLE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LINE_SMOOTH); + glClearColor(color::BLACK.r, color::BLACK.g, color::BLACK.b, color::BLACK.a); + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGui::StyleColorsDark(); + + ImGui_ImplSDL3_InitForOpenGL(window, glContext); + ImGui_ImplOpenGL3_Init("#version 330"); + + ImGuiIO& io = ImGui::GetIO(); + io.IniFilename = nullptr; + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigWindowsMoveFromTitleBarOnly = true; + + ImGui::LoadIniSettingsFromDisk(settings_path().c_str()); + } + + Loader::~Loader() + { + settings.save(settings_path(), ImGui::SaveIniSettingsToMemory(nullptr)); + + ImGui_ImplSDL3_Shutdown(); + ImGui_ImplOpenGL3_Shutdown(); + ImGui::DestroyContext(); + SDL_GL_DestroyContext(glContext); + SDL_DestroyWindow(window); + SDL_Quit(); + } +} \ No newline at end of file diff --git a/src/loader.h b/src/loader.h new file mode 100644 index 0000000..fda6a20 --- /dev/null +++ b/src/loader.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +#include + +#include "settings.h" + +namespace anm2ed::loader +{ + class Loader + { + public: + SDL_Window* window{}; + SDL_GLContext glContext{}; + settings::Settings settings; + std::vector arguments; + bool isError{}; + + Loader(int argc, const char** argv); + ~Loader(); + }; +} diff --git a/src/log.cpp b/src/log.cpp index 537d166..3cdfba3 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -1,56 +1,58 @@ #include "log.h" -inline std::ofstream logFile; +#include -std::string log_path_get(void) +#include "filesystem.h" +#include "util.h" + +using namespace anm2ed::filesystem; +using namespace anm2ed::util; + +namespace anm2ed::log { - return preferences_path_get() + LOG_PATH; + void Logger::write(const Level level, const std::string& message) + { + std::string formatted = std::format("{} {} {}", time::get("(%d-%B-%Y %I:%M:%S)"), LEVEL_STRINGS[level], message); + std::println("{}", formatted); + if (file.is_open()) file << formatted << '\n' << std::flush; + } + + void Logger::info(const std::string& message) + { + write(INFO, message); + } + + void Logger::warning(const std::string& message) + { + write(WARNING, message); + } + + void Logger::error(const std::string& message) + { + write(ERROR, message); + } + + void Logger::fatal(const std::string& message) + { + write(FATAL, message); + } + + void Logger::open(const std::filesystem::path& path) + { + file.open(path, std::ios::out | std::ios::app); + } + + Logger::Logger() + { + open(path_preferences_get() + "log.txt"); + info("Initializing Anm2Ed"); + } + + Logger::~Logger() + { + info("Exiting Anm2Ed"); + if (file.is_open()) file.close(); + } + + Logger logger; } - -void log_write(const std::string& string) -{ - std::println("{}", string); - - if (logFile.is_open()) - { - logFile << string << '\n'; - logFile.flush(); - } -} - -void log_init(void) -{ - std::string logFilepath = log_path_get(); - logFile.open(logFilepath, std::ios::out | std::ios::trunc); - if (!logFile) std::println("{}", std::format(LOG_INIT_ERROR, logFilepath)); -} - -void log_error(const std::string& error) -{ - log_write(LOG_ERROR_FORMAT + error); -} - -void log_info(const std::string& info) -{ - log_write(LOG_INFO_FORMAT + info); -} - -void log_warning(const std::string& warning) -{ - log_write(LOG_WARNING_FORMAT + warning); -} - -void log_imgui(const std::string& imgui) -{ - log_write(LOG_IMGUI_FORMAT + imgui); -} - -void log_command(const std::string& command) -{ - log_write(LOG_COMMAND_FORMAT + command); -} - -void log_free(void) -{ - logFile.close(); -} \ No newline at end of file diff --git a/src/log.h b/src/log.h index 3ac20d9..84b61f5 100644 --- a/src/log.h +++ b/src/log.h @@ -1,21 +1,44 @@ #pragma once -#include "COMMON.h" +#include +#include -#define LOG_WARNING_FORMAT "[WARNING] " -#define LOG_ERROR_FORMAT "[ERROR] " -#define LOG_INFO_FORMAT "[INFO] " -#define LOG_IMGUI_FORMAT "[IMGUI] " -#define LOG_INIT_ERROR "[ERROR] Failed to open log file: {}" -#define LOG_COMMAND_FORMAT "[COMMAND] " -#define LOG_PATH "log.txt" +namespace anm2ed::log +{ +#define LEVELS \ + X(INFO, "[INFO]") \ + X(WARNING, "[WARNING]") \ + X(ERROR, "[ERROR]") \ + X(FATAL, "[FATAL]") -std::string log_path_get(void); -void log_init(void); -void log_write(const std::string& file); -void log_error(const std::string& error); -void log_info(const std::string& info); -void log_warning(const std::string& warning); -void log_imgui(const std::string& imgui); -void log_command(const std::string& command); -void log_free(void); \ No newline at end of file + enum Level + { +#define X(symbol, string) symbol, + LEVELS +#undef X + }; + + constexpr std::string_view LEVEL_STRINGS[] = { +#define X(symbol, string) string, + LEVELS +#undef X + }; +#undef LEVELS + + class Logger + { + std::ofstream file{}; + + public: + void write(const Level level, const std::string& message); + void info(const std::string& message); + void warning(const std::string& message); + void error(const std::string& message); + void fatal(const std::string& message); + void open(const std::filesystem::path& path); + Logger(); + ~Logger(); + }; + + extern Logger logger; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 0970bdf..ea5ef6a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,51 +1,19 @@ -#include "main.h" +#include "loader.h" +#include "state.h" -static bool _anm2_rescale(const std::string& file, float scale) { - Anm2 anm2; +using namespace anm2ed::loader; +using namespace anm2ed::state; - if (!anm2_deserialize(&anm2, file, false)) - return false; - anm2_scale(&anm2, scale); - return anm2_serialize(&anm2, file); -} +int main(int argc, const char** argv) +{ + Loader loader(argc, argv); -int main(int argc, char* argv[]) { - State state; + if (loader.isError) return EXIT_FAILURE; - log_init(); + State state(loader.window, loader.arguments); - if (argc > 0 && argv[1]) { - if (std::string(argv[1]) == ARGUMENT_RESCALE) { - if (argv[2] && argv[3]) { - if (_anm2_rescale(std::string(argv[2]), atof(argv[3]))) { - log_info(std::format(ARGUMENT_RESCALE_ANM2_INFO, argv[2], argv[3])); - return EXIT_SUCCESS; - } else - log_error(ARGUMENT_RESCALE_ANM2_ERROR); - } else - log_error(ARGUMENT_RESCALE_ARGUMENT_ERROR); - - return EXIT_FAILURE; - } else if (std::string(argv[1]) == ARGUMENT_TEST && argv[2]) { - if (anm2_deserialize(&state.anm2, std::string(argv[2]), false)) - return EXIT_SUCCESS; - return EXIT_FAILURE; - } else if (std::string(argv[1]) == ARGUMENT_TEST_GL && argv[2]) { - if (!sdl_init(&state, true)) - return EXIT_FAILURE; - if (anm2_deserialize(&state.anm2, std::string(argv[2]))) - return EXIT_SUCCESS; - return EXIT_FAILURE; - } else if (argv[1]) - state.argument = argv[1]; - } - - init(&state); - - while (state.isRunning) - loop(&state); - - quit(&state); + while (!state.isQuit) + state.loop(loader.window, loader.settings); return EXIT_SUCCESS; -} \ No newline at end of file +} diff --git a/src/main.h b/src/main.h deleted file mode 100644 index 2e53307..0000000 --- a/src/main.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -#define ARGUMENT_TEST "--test" -#define ARGUMENT_TEST_GL "--test-gl" - -#define ARGUMENT_RESCALE "--rescale" -#define ARGUMENT_RESCALE_ARGUMENT_ERROR "--rescale: specify both anm2 and scale arguments" -#define ARGUMENT_RESCALE_ANM2_ERROR "Unable to rescale anm2 {} by value {}. Make sure the file is valid." -#define ARGUMENT_RESCALE_ANM2_INFO "Scaled anm2 {} by {}" - -#include "state.h" \ No newline at end of file diff --git a/src/math.cpp b/src/math.cpp new file mode 100644 index 0000000..edeca35 --- /dev/null +++ b/src/math.cpp @@ -0,0 +1,81 @@ +#include "math.h" + +#include +#include + +using namespace glm; + +namespace anm2ed::math +{ + constexpr auto FLOAT_FORMAT_MAX_DECIMALS = 7; + constexpr auto FLOAT_FORMAT_EPSILON = 1e-7f; + constexpr float FLOAT_FORMAT_POW10[] = {1.f, 10.f, 100.f, 1000.f, 10000.f, 100000.f, 1000000.f, 10000000.f}; + + float round_nearest_multiple(float value, float multiple) + { + return (roundf((value) / (multiple)) * (multiple)); + } + + int float_decimals_needed(float value) + { + for (int decimalCount = 0; decimalCount <= FLOAT_FORMAT_MAX_DECIMALS; ++decimalCount) + { + auto scale = FLOAT_FORMAT_POW10[decimalCount]; + auto rounded = roundf(value * scale) / scale; + if (fabsf(value - rounded) < FLOAT_FORMAT_EPSILON) return decimalCount; + } + return FLOAT_FORMAT_MAX_DECIMALS; + } + + const char* float_format_get(float value) + { + static std::string formatString{}; + int decimalCount = float_decimals_needed(value); + formatString = (decimalCount == 0) ? "%.0f" : ("%." + std::to_string(decimalCount) + "f"); + return formatString.c_str(); + } + + const char* vec2_format_get(vec2& value) + { + static std::string formatString{}; + int decimalCountX = float_decimals_needed(value.x); + int decimalCountY = float_decimals_needed(value.y); + int decimalCount = (decimalCountX > decimalCountY) ? decimalCountX : decimalCountY; + formatString = (decimalCount == 0) ? "%.0f" : ("%." + std::to_string(decimalCount) + "f"); + return formatString.c_str(); + } + + mat4 quad_model_get(vec2 size, vec2 position, vec2 pivot, vec2 scale, float rotation) + { + vec2 scaleAbsolute = glm::abs(scale); + vec2 scaleSign = glm::sign(scale); + vec2 pivotScaled = pivot * scaleAbsolute; + vec2 sizeScaled = size * scaleAbsolute; + + mat4 model(1.0f); + model = glm::translate(model, vec3(position - pivotScaled, 0.0f)); + model = glm::translate(model, vec3(pivotScaled, 0.0f)); + model = glm::scale(model, vec3(scaleSign, 1.0f)); + model = glm::rotate(model, glm::radians(rotation), vec3(0, 0, 1)); + model = glm::translate(model, vec3(-pivotScaled, 0.0f)); + model = glm::scale(model, vec3(sizeScaled, 1.0f)); + return model; + } + + mat4 quad_model_parent_get(vec2 position, vec2 pivot, vec2 scale, float rotation) + { + vec2 scaleSign = glm::sign(scale); + vec2 scaleAbsolute = glm::abs(scale); + float handedness = (scaleSign.x * scaleSign.y) < 0.0f ? -1.0f : 1.0f; + + mat4 local(1.0f); + local = glm::translate(local, vec3(pivot, 0.0f)); + local = glm::scale(local, vec3(scaleSign, 1.0f)); + local = glm::rotate(local, glm::radians(rotation) * handedness, vec3(0, 0, 1)); + local = glm::translate(local, vec3(-pivot, 0.0f)); + local = glm::scale(local, vec3(scaleAbsolute, 1.0f)); + + return glm::translate(mat4(1.0f), vec3(position, 0.0f)) * local; + } + +} diff --git a/src/math.h b/src/math.h new file mode 100644 index 0000000..c058de3 --- /dev/null +++ b/src/math.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include + +namespace anm2ed::math +{ + template constexpr T percent_to_unit(T value) + { + return value / 100.0f; + } + + template constexpr T unit_to_percent(T value) + { + return value * 100.0f; + } + + constexpr float uint8_to_float(int value) + { + return (float)(value / 255.0f); + } + + constexpr int float_to_uint8(float value) + { + return (int)(value * 255); + } + + constexpr std::array uv_vertices_get(glm::vec2 uvMin, glm::vec2 uvMax) + { + return {0.0f, 0.0f, uvMin.x, uvMin.y, 1.0f, 0.0f, uvMax.x, uvMin.y, + 1.0f, 1.0f, uvMax.x, uvMax.y, 0.0f, 1.0f, uvMin.x, uvMax.y}; + } + + float round_nearest_multiple(float value, float multiple); + + int float_decimals_needed(float value); + + const char* float_format_get(float value); + + const char* vec2_format_get(glm::vec2& value); + + glm::mat4 quad_model_get(glm::vec2 size = {}, glm::vec2 position = {}, glm::vec2 pivot = {}, + glm::vec2 scale = glm::vec2(1.0f), float rotation = {}); + glm::mat4 quad_model_parent_get(glm::vec2 position = {}, glm::vec2 pivot = {}, glm::vec2 scale = glm::vec2(1.0f), + float rotation = {}); +} \ No newline at end of file diff --git a/src/nulls.cpp b/src/nulls.cpp new file mode 100644 index 0000000..2d9f9a5 --- /dev/null +++ b/src/nulls.cpp @@ -0,0 +1,80 @@ +#include "nulls.h" + +#include + +#include "imgui.h" + +using namespace anm2ed::document_manager; +using namespace anm2ed::settings; +using namespace anm2ed::resources; +using namespace anm2ed::types; + +namespace anm2ed::nulls +{ + void Nulls::update(DocumentManager& manager, Settings& settings, Resources& resources) + { + if (ImGui::Begin("Nulls", &settings.windowIsNulls)) + { + auto document = manager.get(); + anm2::Anm2& anm2 = document->anm2; + + auto& selection = document->selectedNulls; + storage.UserData = &selection; + storage.AdapterSetItemSelected = imgui::external_storage_set; + + auto childSize = imgui::size_with_footer_get(); + + if (ImGui::BeginChild("##Nulls Child", childSize, true)) + { + ImGuiMultiSelectIO* io = + ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, selection.size(), anm2.content.nulls.size()); + storage.ApplyRequests(io); + + for (auto& [id, null] : anm2.content.nulls) + { + const bool isSelected = selection.contains(id); + + ImGui::PushID(id); + ImGui::SetNextItemSelectionUserData(id); + imgui::selectable_input_text(std::format("#{} {}", id, null.name), + std::format("###Document #{} Null #{}", manager.selected, id), null.name, + isSelected); + if (ImGui::BeginItemTooltip()) + { + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); + ImGui::TextUnformatted(null.name.c_str()); + ImGui::TextUnformatted(std::format("ID: {}", id).c_str()); + ImGui::PopFont(); + ImGui::EndTooltip(); + } + ImGui::PopID(); + } + + io = ImGui::EndMultiSelect(); + storage.ApplyRequests(io); + } + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + imgui::shortcut(settings.shortcutAdd, true); + ImGui::Button("Add", widgetSize); + imgui::set_item_tooltip_shortcut("Add a null.", settings.shortcutAdd); + ImGui::SameLine(); + + std::set unusedNullsIDs = anm2.nulls_unused(); + + imgui::shortcut(settings.shortcutRemove, true); + ImGui::BeginDisabled(unusedNullsIDs.empty()); + { + if (ImGui::Button("Remove Unused", widgetSize)) + for (auto& id : unusedNullsIDs) + anm2.content.nulls.erase(id); + } + ImGui::EndDisabled(); + imgui::set_item_tooltip_shortcut("Remove unused nulls (i.e., ones not used in any animation.)", + settings.shortcutRemove); + } + ImGui::End(); + } +} \ No newline at end of file diff --git a/src/nulls.h b/src/nulls.h new file mode 100644 index 0000000..a85bb6f --- /dev/null +++ b/src/nulls.h @@ -0,0 +1,17 @@ +#pragma once + +#include "document_manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::nulls +{ + class Nulls + { + ImGuiSelectionExternalStorage storage{}; + + public: + void update(document_manager::DocumentManager& manager, settings::Settings& settings, + resources::Resources& resources); + }; +} \ No newline at end of file diff --git a/src/onionskin.cpp b/src/onionskin.cpp new file mode 100644 index 0000000..7064d6c --- /dev/null +++ b/src/onionskin.cpp @@ -0,0 +1,43 @@ +#include "onionskin.h" + +#include + +#include "imgui.h" + +using namespace anm2ed::settings; +using namespace glm; + +namespace anm2ed::onionskin +{ + void Onionskin::update(Settings& settings) + { + if (ImGui::Begin("Onionskin", &settings.windowIsOnionskin)) + { + auto order_configure = [&](const std::string& separator, int& frames, vec3& color) + { + ImGui::PushID(separator.c_str()); + ImGui::SeparatorText(separator.c_str()); + ImGui::InputInt("Frames", &frames, 1, 5); + frames = glm::clamp(frames, 0, 100); + ImGui::ColorEdit3("Color", value_ptr(color)); + ImGui::PopID(); + }; + + imgui::shortcut(settings.shortcutOnionskin, true, true); + ImGui::Checkbox("Enabled", &settings.onionskinIsEnabled); + + order_configure("Before", settings.onionskinBeforeCount, settings.onionskinBeforeColor); + order_configure("After", settings.onionskinAfterCount, settings.onionskinAfterColor); + + ImGui::Text("Order"); + ImGui::SameLine(); + ImGui::RadioButton("Before", &settings.onionskinDrawOrder, BELOW); + ImGui::SameLine(); + ImGui::RadioButton("After", &settings.onionskinDrawOrder, ABOVE); + } + + if (imgui::shortcut(settings.shortcutOnionskin)) settings.onionskinIsEnabled = !settings.onionskinIsEnabled; + + ImGui::End(); + } +} diff --git a/src/onionskin.h b/src/onionskin.h new file mode 100644 index 0000000..2157670 --- /dev/null +++ b/src/onionskin.h @@ -0,0 +1,18 @@ +#pragma once + +#include "settings.h" + +namespace anm2ed::onionskin +{ + enum Type + { + BELOW, + ABOVE + }; + + class Onionskin + { + public: + void update(settings::Settings& settings); + }; +} diff --git a/src/playback.cpp b/src/playback.cpp new file mode 100644 index 0000000..30c2413 --- /dev/null +++ b/src/playback.cpp @@ -0,0 +1,48 @@ +#include "playback.h" + +#include + +namespace anm2ed::playback +{ + void Playback::toggle() + { + if (isFinished) time = 0.0f; + isFinished = false; + isPlaying = !isPlaying; + } + + void Playback::clamp(int length) + { + time = glm::clamp(time, 0.0f, (float)length - 1.0f); + } + + void Playback::tick(int fps, int length, bool isLoop) + { + if (isFinished) return; + + time += (float)fps / 30.0f; + + if (time >= (float)length) + { + if (isLoop) + time = 0.0f; + else + { + isPlaying = false; + isFinished = true; + } + } + } + + void Playback::decrement(int length) + { + --time; + clamp(length); + } + + void Playback::increment(int length) + { + ++time; + clamp(length); + } +} \ No newline at end of file diff --git a/src/playback.h b/src/playback.h new file mode 100644 index 0000000..edbd7f3 --- /dev/null +++ b/src/playback.h @@ -0,0 +1,18 @@ +#pragma once + +namespace anm2ed::playback +{ + class Playback + { + public: + float time{}; + bool isPlaying{}; + bool isFinished{}; + + void toggle(); + void clamp(int length); + void tick(int fps, int length, bool isLoop); + void decrement(int length); + void increment(int length); + }; +} \ No newline at end of file diff --git a/src/preview.cpp b/src/preview.cpp deleted file mode 100644 index 6d86e06..0000000 --- a/src/preview.cpp +++ /dev/null @@ -1,259 +0,0 @@ -#include "preview.h" - -static void _preview_render_textures_free(Preview* self) { - for (auto& texture : self->renderFrames) - texture_free(&texture); - - self->renderFrames.clear(); -} - -void preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings) { - self->anm2 = anm2; - self->reference = reference; - self->resources = resources; - self->settings = settings; - - canvas_init(&self->canvas, vec2()); -} - -void preview_tick(Preview* self) { - float& time = self->time; - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, *self->reference); - - if (animation) { - if (self->isPlaying) { - if (self->isRender) { - ivec2& size = self->canvas.size; - u32 framebufferPixelCount = size.x * size.y * TEXTURE_CHANNELS; - std::vector framebufferPixels(framebufferPixelCount); - Texture frameTexture; - - glBindFramebuffer(GL_READ_FRAMEBUFFER, self->canvas.fbo); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ROW_LENGTH, 0); - glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, framebufferPixels.data()); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - - texture_from_rgba_init(&frameTexture, size, framebufferPixels.data()); - self->renderFrames.push_back(frameTexture); - } - - time += (float)self->anm2->fps / TICK_DELAY; - - if (time >= (float)animation->frameNum - 1) { - if (self->isRender) { - self->isRender = false; - self->isRenderFinished = true; - time = 0.0f; - self->isPlaying = false; - } else { - if (self->settings->playbackIsLoop) - time = 0.0f; - else { - time = std::clamp(time, 0.0f, std::max(0.0f, (float)animation->frameNum - 1)); - self->isPlaying = false; - } - } - } - } - - if (self->settings->playbackIsClampPlayhead) - time = std::clamp(time, 0.0f, std::max(0.0f, (float)animation->frameNum - 1)); - else - time = std::max(time, 0.0f); - } -} - -void preview_draw(Preview* self) { - ivec2& gridSize = self->settings->previewGridSize; - ivec2& gridOffset = self->settings->previewGridOffset; - vec4& gridColor = self->settings->previewGridColor; - GLuint& shaderLine = self->resources->shaders[SHADER_LINE]; - GLuint& shaderAxis = self->resources->shaders[SHADER_AXIS]; - GLuint& shaderTexture = self->resources->shaders[SHADER_TEXTURE]; - GLuint& shaderGrid = self->resources->shaders[SHADER_GRID]; - mat4 transform = canvas_transform_get(&self->canvas, self->settings->previewPan, self->settings->previewZoom, ORIGIN_CENTER); - - canvas_framebuffer_resize_check(&self->canvas); - - canvas_bind(&self->canvas); - canvas_viewport_set(&self->canvas); - canvas_clear(self->settings->previewBackgroundColor); - - if (self->settings->previewIsGrid) - canvas_grid_draw(&self->canvas, shaderGrid, transform, gridSize, gridOffset, gridColor); - - if (self->settings->previewIsAxes) - canvas_axes_draw(&self->canvas, shaderAxis, transform, self->settings->previewAxesColor); - - auto animation_draw = [&](int animationIndex) { - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, {animationIndex}); - if (!animation) - return; - - auto root_draw = [&](Anm2Frame root, vec3 colorOffset = {}, float alphaOffset = {}, bool isOnionskin = {}) { - mat4 model = quad_model_get(PREVIEW_TARGET_SIZE, root.position, PREVIEW_TARGET_SIZE * 0.5f, PERCENT_TO_UNIT(root.scale), root.rotation); - mat4 rootTransform = transform * model; - vec4 color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : PREVIEW_ROOT_COLOR; - AtlasType atlas = self->settings->previewIsAltIcons ? ATLAS_TARGET_ALT : ATLAS_TARGET; - float vertices[] = ATLAS_UV_VERTICES(atlas); - canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, rootTransform, vertices, color); - }; - - auto layer_draw = [&](mat4 rootModel, int id, float time, vec3 colorOffset = {}, float alphaOffset = {}, bool isOnionskin = {}) { - Anm2Item& layerAnimation = animation->layerAnimations[id]; - if (!layerAnimation.isVisible || layerAnimation.frames.size() <= 0) - return; - - Anm2Frame frame; - anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationIndex, ANM2_LAYER, id}, time); - if (!frame.isVisible) - return; - - mat4 model = quad_model_get(frame.size, frame.position, frame.pivot, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 layerTransform = transform * (rootModel * model); - vec3 frameColorOffset = frame.offsetRGB + colorOffset; - vec4 frameTint = frame.tintRGBA; - frameTint.a = std::max(0.0f, frameTint.a - alphaOffset); - - Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->anm2->layers[id].spritesheetID); - if (!spritesheet) - return; - - Texture& texture = spritesheet->texture; - if (texture.isInvalid) - return; - - vec2 inset = 0.5f / vec2(texture.size); - vec2 uvMin = frame.crop / vec2(texture.size) + inset; - vec2 uvMax = (frame.crop + frame.size) / vec2(texture.size) - inset; - float vertices[] = UV_VERTICES(uvMin, uvMax); - canvas_texture_draw(&self->canvas, shaderTexture, texture.id, layerTransform, vertices, frameTint, frameColorOffset); - - if (self->settings->previewIsBorder) { - vec4 borderColor = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : PREVIEW_BORDER_COLOR; - canvas_rect_draw(&self->canvas, shaderLine, layerTransform, borderColor); - } - - if (self->settings->previewIsPivots) { - vec4 pivotColor = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : PREVIEW_PIVOT_COLOR; - float vertices[] = ATLAS_UV_VERTICES(ATLAS_PIVOT); - mat4 pivotModel = quad_model_get(CANVAS_PIVOT_SIZE, frame.position, CANVAS_PIVOT_SIZE * 0.5f, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 pivotTransform = transform * (rootModel * pivotModel); - canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, pivotTransform, vertices, pivotColor); - } - }; - - auto null_draw = [&](mat4 rootModel, int id, float time, vec3 colorOffset = {}, float alphaOffset = {}, bool isOnionskin = {}) { - Anm2Item& nullAnimation = animation->nullAnimations[id]; - if (!nullAnimation.isVisible || nullAnimation.frames.size() <= 0) - return; - - Anm2Frame frame; - anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationIndex, ANM2_NULL, id}, time); - if (!frame.isVisible) - return; - - Anm2Null null = self->anm2->nulls[id]; - - vec4 color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) - : (self->reference->itemType == ANM2_NULL && self->reference->itemID == id) ? PREVIEW_NULL_SELECTED_COLOR - : PREVIEW_NULL_COLOR; - - vec2 size = null.isShowRect ? CANVAS_PIVOT_SIZE : PREVIEW_TARGET_SIZE; - AtlasType atlas = null.isShowRect ? ATLAS_SQUARE : self->settings->previewIsAltIcons ? ATLAS_TARGET_ALT : ATLAS_TARGET; - - mat4 model = quad_model_get(size, frame.position, size * 0.5f, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 nullTransform = transform * (rootModel * model); - - float vertices[] = ATLAS_UV_VERTICES(atlas); - - canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, nullTransform, vertices, color); - - if (null.isShowRect) { - mat4 rectModel = quad_model_get(PREVIEW_NULL_RECT_SIZE, frame.position, PREVIEW_NULL_RECT_SIZE * 0.5f, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 rectTransform = transform * (rootModel * rectModel); - canvas_rect_draw(&self->canvas, shaderLine, rectTransform, color); - } - }; - - auto base_draw = [&](float time, vec3 colorOffset = {}, float alphaOffset = {}, bool isOnionskin = {}) { - Anm2Frame root; - anm2_frame_from_time(self->anm2, &root, Anm2Reference{animationIndex, ANM2_ROOT}, time); - - mat4 rootModel = - self->settings->previewIsRootTransform ? quad_model_parent_get(root.position, {}, PERCENT_TO_UNIT(root.scale), root.rotation) : mat4(1.0f); - - if (self->settings->previewIsIcons && animation->rootAnimation.isVisible && root.isVisible) - root_draw(root, colorOffset, alphaOffset, isOnionskin); - - for (auto id : animation->layerOrder) - layer_draw(rootModel, id, time, colorOffset, alphaOffset, isOnionskin); - - if (self->settings->previewIsIcons) - for (auto& [id, _] : animation->nullAnimations) - null_draw(rootModel, id, time, colorOffset, alphaOffset, isOnionskin); - }; - - auto onionskin_draw = [&](int count, int direction, vec3 colorOffset) { - for (int i = 1; i <= count; i++) { - float time = self->time + (float)(direction * i); - float alphaOffset = (1.0f / (count + 1)) * i; - base_draw(time, colorOffset, alphaOffset, true); - } - }; - - auto onionskins_draw = [&]() { - if (!self->settings->onionskinIsEnabled) - return; - onionskin_draw(self->settings->onionskinBeforeCount, -1, self->settings->onionskinBeforeColorOffset); - onionskin_draw(self->settings->onionskinAfterCount, 1, self->settings->onionskinAfterColorOffset); - }; - - if (self->settings->onionskinDrawOrder == ONIONSKIN_BELOW) - onionskins_draw(); - base_draw(self->time); - if (self->settings->onionskinDrawOrder == ONIONSKIN_ABOVE) - onionskins_draw(); - }; - - animation_draw(self->reference->animationIndex); - animation_draw(self->animationOverlayID); - - canvas_unbind(); -} - -void preview_render_start(Preview* self) { - self->isRender = true; - self->isPlaying = true; - self->time = 0.0f; - _preview_render_textures_free(self); - - self->normalCanvasSize = self->canvas.size; - self->normalCanvasPan = self->settings->previewPan; - self->normalCanvasZoom = self->settings->previewZoom; - - if (self->settings->renderIsUseAnimationBounds) { - vec4 rect = anm2_animation_rect_get(self->anm2, *self->reference, self->settings->previewIsRootTransform); - - self->canvas.size = ivec2(ceilf(rect.z * self->settings->renderScale), ceilf(rect.w * self->settings->renderScale)); - - vec2 rectCenter = vec2(rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f); - self->settings->previewPan = -rectCenter * self->settings->renderScale; - self->settings->previewZoom = UNIT_TO_PERCENT(self->settings->renderScale); - } -} - -void preview_render_end(Preview* self) { - self->isRender = false; - self->isPlaying = false; - self->isRenderFinished = false; - _preview_render_textures_free(self); - - self->canvas.size = self->normalCanvasSize; - self->settings->previewPan = self->normalCanvasPan; - self->settings->previewZoom = self->normalCanvasZoom; -} - -void preview_free(Preview* self) { canvas_free(&self->canvas); } \ No newline at end of file diff --git a/src/preview.h b/src/preview.h deleted file mode 100644 index de54696..0000000 --- a/src/preview.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include "anm2.h" -#include "canvas.h" -#include "resources.h" -#include "settings.h" - -const vec2 PREVIEW_SIZE = {2000, 2000}; -const vec2 PREVIEW_CANVAS_SIZE = {2000, 2000}; -const vec2 PREVIEW_CENTER = {0, 0}; - -#define PREVIEW_ZOOM_MIN 1 -#define PREVIEW_ZOOM_MAX 1000 -#define PREVIEW_ZOOM_STEP 25 -#define PREVIEW_GRID_MIN 1 -#define PREVIEW_GRID_MAX 1000 -#define PREVIEW_GRID_OFFSET_MIN 0 -#define PREVIEW_GRID_OFFSET_MAX 100 - -const vec2 PREVIEW_NULL_RECT_SIZE = {100, 100}; -const vec2 PREVIEW_POINT_SIZE = {2, 2}; -const vec2 PREVIEW_TARGET_SIZE = {16, 16}; -const vec4 PREVIEW_BORDER_COLOR = COLOR_RED; -const vec4 PREVIEW_ROOT_COLOR = COLOR_GREEN; -const vec4 PREVIEW_NULL_COLOR = COLOR_BLUE; -const vec4 PREVIEW_NULL_SELECTED_COLOR = COLOR_RED; -const vec4 PREVIEW_PIVOT_COLOR = COLOR_RED; - -struct Preview { - Anm2* anm2 = nullptr; - Anm2Reference* reference = nullptr; - Resources* resources = nullptr; - Settings* settings = nullptr; - int animationOverlayID = ID_NONE; - Canvas canvas; - vec2 normalCanvasSize{}; - vec2 normalCanvasPan{}; - float normalCanvasZoom{}; - bool isPlaying = false; - bool isRender = false; - bool isRenderFinished = false; - bool isRenderCancelled = false; - std::vector renderFrames; - float time{}; -}; - -void preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings); -void preview_draw(Preview* self); -void preview_tick(Preview* self); -void preview_free(Preview* self); -void preview_render_start(Preview* self); -void preview_render_end(Preview* self); \ No newline at end of file diff --git a/src/render.h b/src/render.h deleted file mode 100644 index ac4dc5d..0000000 --- a/src/render.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "COMMON.h" - -enum RenderType { RENDER_PNG, RENDER_GIF, RENDER_WEBM, RENDER_MP4, RENDER_COUNT }; - -const inline std::string RENDER_TYPE_STRINGS[] = { - "PNG Images", - "GIF image", - "WebM video", - "MP4 video", -}; - -const inline std::string RENDER_EXTENSIONS[RENDER_COUNT] = { - ".png", - ".gif", - ".webm", - ".mp4", -}; \ No newline at end of file diff --git a/src/resources.cpp b/src/resources.cpp index 2f3280a..eec7ecf 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -1,16 +1,21 @@ #include "resources.h" -#include "RESOURCE.h" +#include -void resources_init(Resources* self) { - texture_from_memory_init(&self->atlas, TEXTURE_ATLAS_SIZE, TEXTURE_ATLAS, TEXTURE_ATLAS_LENGTH); +using namespace anm2ed::texture; +using namespace anm2ed::shader; +using namespace anm2ed::font; - for (int i = 0; i < SHADER_COUNT; i++) - shader_init(&self->shaders[i], SHADER_DATA[i].vertex, SHADER_DATA[i].fragment); -} +namespace anm2ed::resources +{ + Resources::Resources() + { + for (auto [i, font] : std::views::enumerate(font::FONTS)) + fonts[i] = Font((void*)font.data, font.length, font::SIZE); -void resources_free(Resources* self) { - for (auto& shader : self->shaders) - shader_free(&shader); + for (auto [i, icon] : std::views::enumerate(icon::ICONS)) + icons[i] = Texture(icon.data, icon.length, icon.size); - texture_free(&self->atlas); + for (auto [i, shader] : std::views::enumerate(shader::SHADERS)) + shaders[i] = Shader(shader.vertex, shader.fragment); + }; } \ No newline at end of file diff --git a/src/resources.h b/src/resources.h index af0dbcb..3554be5 100644 --- a/src/resources.h +++ b/src/resources.h @@ -1,15 +1,21 @@ #pragma once -#include "RESOURCE.h" +#include + +#include "font.h" +#include "icon.h" #include "shader.h" #include "texture.h" -#define RESOURCES_TEXTURES_FREE_INFO "Freed texture resources" +namespace anm2ed::resources +{ + class Resources + { + public: + font::Font fonts[font::COUNT]{}; + texture::Texture icons[icon::COUNT]{}; + shader::Shader shaders[shader::COUNT]{}; -struct Resources { - GLuint shaders[SHADER_COUNT]; - Texture atlas; -}; - -void resources_init(Resources* self); -void resources_free(Resources* self); + Resources(); + }; +} \ No newline at end of file diff --git a/src/settings.cpp b/src/settings.cpp index d1b31e2..d801dab 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1,305 +1,314 @@ #include "settings.h" -static void _settings_setting_load(Settings* self, const std::string& line) { - for (int i = 0; i < SETTINGS_COUNT; i++) { - const auto& entry = SETTINGS_ENTRIES[i]; - const std::string& key = entry.key; - void* target = (u8*)self + entry.offset; +#include "filesystem.h" +#include "log.h" - auto match_key = [&](const std::string& full) -> const char* { - if (!line.starts_with(full)) - return nullptr; +using namespace anm2ed::filesystem; +using namespace anm2ed::log; +using namespace glm; - size_t p = full.size(); - while (p < line.size() && std::isspace((u8)line[p])) - ++p; - if (p < line.size() && line[p] == '=') - return line.c_str() + p + 1; - return nullptr; - }; +namespace anm2ed::settings +{ + constexpr auto IMGUI_DEFAULT = R"( +# Dear ImGui +[Window][## Window] +Pos=0,32 +Size=1600,868 +Collapsed=0 - const char* value = nullptr; +[Window][Debug##Default] +Pos=60,60 +Size=400,400 +Collapsed=0 - switch (entry.type) { - case TYPE_INT: - if ((value = match_key(key))) { - *(int*)target = std::atoi(value); - return; - } - break; - case TYPE_BOOL: - if ((value = match_key(key))) { - *(bool*)target = string_to_bool(value); - return; - } - break; - case TYPE_FLOAT: - if ((value = match_key(key))) { - *(f32*)target = std::atof(value); - return; - } - break; - case TYPE_STRING: - if ((value = match_key(key))) { - *(std::string*)target = value; - return; - } - break; - case TYPE_IVEC2: { - ivec2* v = (ivec2*)target; - if ((value = match_key(key + "X"))) { - v->x = std::atoi(value); - return; - } - if ((value = match_key(key + "Y"))) { - v->y = std::atoi(value); - return; - } - break; +[Window][Tools] +Pos=8,40 +Size=38,516 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][Animations] +Pos=1289,307 +Size=303,249 +Collapsed=0 +DockId=0x0000000A,0 + +[Window][Events] +Pos=957,264 +Size=330,292 +Collapsed=0 +DockId=0x00000008,2 + +[Window][Spritesheets] +Pos=1289,40 +Size=303,265 +Collapsed=0 +DockId=0x00000009,0 + +[Window][Animation Preview] +Pos=48,40 +Size=907,516 +Collapsed=0 +DockId=0x0000000C,0 + +[Window][Spritesheet Editor] +Pos=48,40 +Size=907,516 +Collapsed=0 +DockId=0x0000000C,1 + +[Window][Timeline] +Pos=8,558 +Size=1584,334 +Collapsed=0 +DockId=0x00000004,0 + +[Window][Frame Properties] +Pos=957,40 +Size=330,222 +Collapsed=0 +DockId=0x00000007,0 + +[Window][Onionskin] +Pos=957,264 +Size=330,292 +Collapsed=0 +DockId=0x00000008,3 + +[Window][Layers] +Pos=957,264 +Size=330,292 +Collapsed=0 +DockId=0x00000008,0 + +[Window][Nulls] +Pos=957,264 +Size=330,292 +Collapsed=0 +DockId=0x00000008,1 + + +[Docking][Data] +DockSpace ID=0xFC02A410 Window=0x0E46F4F7 Pos=8,40 Size=1584,852 Split=Y + DockNode ID=0x00000003 Parent=0xFC02A410 SizeRef=1902,680 Split=X + DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1017,1016 Split=X Selected=0x024430EF + DockNode ID=0x00000005 Parent=0x00000001 SizeRef=1264,654 Split=X Selected=0x024430EF + DockNode ID=0x0000000B Parent=0x00000005 SizeRef=38,654 Selected=0x18A5FDB9 + DockNode ID=0x0000000C Parent=0x00000005 SizeRef=1224,654 CentralNode=1 Selected=0x024430EF + DockNode ID=0x00000006 Parent=0x00000001 SizeRef=330,654 Split=Y Selected=0x754E368F + DockNode ID=0x00000007 Parent=0x00000006 SizeRef=631,293 Selected=0x754E368F + DockNode ID=0x00000008 Parent=0x00000006 SizeRef=631,385 Selected=0xCD8384B1 + DockNode ID=0x00000002 Parent=0x00000003 SizeRef=303,1016 Split=Y Selected=0x4EFD0020 + DockNode ID=0x00000009 Parent=0x00000002 SizeRef=634,349 Selected=0x4EFD0020 + DockNode ID=0x0000000A Parent=0x00000002 SizeRef=634,329 Selected=0xC1986EE2 + DockNode ID=0x00000004 Parent=0xFC02A410 SizeRef=1902,334 Selected=0x4F89F0DC +)"; + + Settings::Settings() = default; + + Settings::Settings(const std::string& path) + { + if (path_is_exist(path)) + logger.info(std::format("Using settings from: {}", path)); + else + { + logger.warning("Settings file does not exist; using default"); + save(path, IMGUI_DEFAULT); } - case TYPE_IVEC2_WH: { - ivec2* v = (ivec2*)target; - if ((value = match_key(key + "W"))) { - v->x = std::atoi(value); - return; - } - if ((value = match_key(key + "H"))) { - v->y = std::atoi(value); - return; - } - break; - }; - case TYPE_VEC2: { - vec2* v = (vec2*)target; - if ((value = match_key(key + "X"))) { - v->x = std::atof(value); - return; - } - if ((value = match_key(key + "Y"))) { - v->y = std::atof(value); - return; - } - break; - } - case TYPE_VEC2_WH: { - vec2* v = (vec2*)target; - if ((value = match_key(key + "W"))) { - v->x = std::atof(value); - return; - } - if ((value = match_key(key + "H"))) { - v->y = std::atof(value); - return; - } - break; - }; - case TYPE_VEC3: { - vec3* v = (vec3*)target; - if ((value = match_key(key + "R"))) { - v->x = std::atof(value); - return; - } - if ((value = match_key(key + "G"))) { - v->y = std::atof(value); - return; - } - if ((value = match_key(key + "B"))) { - v->z = std::atof(value); - return; - } - break; - } - case TYPE_VEC4: { - vec4* v = (vec4*)target; - if ((value = match_key(key + "R"))) { - v->x = std::atof(value); - return; - } - if ((value = match_key(key + "G"))) { - v->y = std::atof(value); - return; - } - if ((value = match_key(key + "B"))) { - v->z = std::atof(value); - return; - } - if ((value = match_key(key + "A"))) { - v->w = std::atof(value); - return; - } - break; - } - default: - break; - } - } - log_warning(std::format(SETTINGS_VALUE_INIT_WARNING, line)); -} - -std::string settings_path_get(void) { - std::string filePath = preferences_path_get() + SETTINGS_PATH; - return filePath; -} - -static void _settings_setting_write(Settings* self, std::ostream& out, SettingsEntry entry) { - u8* selfPointer = (u8*)self; - std::string value; - - switch (entry.type) { - case TYPE_INT: - value = std::format("{}", *(int*)(selfPointer + entry.offset)); - out << entry.key << "=" << value << "\n"; - break; - case TYPE_BOOL: - value = std::format("{}", *(bool*)(selfPointer + entry.offset)); - out << entry.key << "=" << value << "\n"; - break; - case TYPE_FLOAT: - value = std::format("{:.3f}", *(f32*)(selfPointer + entry.offset)); - out << entry.key << "=" << value << "\n"; - break; - case TYPE_STRING: { - const std::string data = *reinterpret_cast(selfPointer + entry.offset); - if (!data.empty()) - out << entry.key << "=" << data.c_str() << "\n"; - break; - } - case TYPE_IVEC2: { - ivec2* data = (ivec2*)(selfPointer + entry.offset); - out << entry.key << "X=" << data->x << "\n"; - out << entry.key << "Y=" << data->y << "\n"; - break; - } - case TYPE_IVEC2_WH: { - ivec2* data = (ivec2*)(selfPointer + entry.offset); - out << entry.key << "W=" << data->x << "\n"; - out << entry.key << "H=" << data->y << "\n"; - break; - } - case TYPE_VEC2: { - vec2* data = (vec2*)(selfPointer + entry.offset); - out << entry.key << "X=" << std::format(SETTINGS_FLOAT_FORMAT, data->x) << "\n"; - out << entry.key << "Y=" << std::format(SETTINGS_FLOAT_FORMAT, data->y) << "\n"; - break; - } - case TYPE_VEC2_WH: { - vec2* data = (vec2*)(selfPointer + entry.offset); - out << entry.key << "W=" << std::format(SETTINGS_FLOAT_FORMAT, data->x) << "\n"; - out << entry.key << "H=" << std::format(SETTINGS_FLOAT_FORMAT, data->y) << "\n"; - break; - } - case TYPE_VEC3: { - vec3* data = (vec3*)(selfPointer + entry.offset); - out << entry.key << "R=" << std::format(SETTINGS_FLOAT_FORMAT, data->r) << "\n"; - out << entry.key << "G=" << std::format(SETTINGS_FLOAT_FORMAT, data->g) << "\n"; - out << entry.key << "B=" << std::format(SETTINGS_FLOAT_FORMAT, data->b) << "\n"; - break; - } - case TYPE_VEC4: { - vec4* data = (vec4*)(selfPointer + entry.offset); - out << entry.key << "R=" << std::format(SETTINGS_FLOAT_FORMAT, data->r) << "\n"; - out << entry.key << "G=" << std::format(SETTINGS_FLOAT_FORMAT, data->g) << "\n"; - out << entry.key << "B=" << std::format(SETTINGS_FLOAT_FORMAT, data->b) << "\n"; - out << entry.key << "A=" << std::format(SETTINGS_FLOAT_FORMAT, data->a) << "\n"; - break; - } - default: - break; - } -} - -void settings_save(Settings* self) { - const std::string path = settings_path_get(); - const std::filesystem::path filesystemPath(path); - const std::filesystem::path directory = filesystemPath.parent_path(); - - if (!directory.empty()) { - std::error_code errorCode; - std::filesystem::create_directories(directory, errorCode); - if (errorCode) { - log_error(std::format(SETTINGS_DIRECTORY_ERROR, directory.string(), errorCode.message())); + std::ifstream file(path); + if (!file.is_open()) + { + logger.error(std::format("Failed to open settings file: {}", path)); return; } - } - std::string data; - if (std::filesystem::exists(filesystemPath)) { - if (std::ifstream in(path, std::ios::binary); in) - data.assign(std::istreambuf_iterator(in), std::istreambuf_iterator()); - } + std::string line{}; - std::filesystem::path temp = filesystemPath; - temp += SETTINGS_TEMPORARY_EXTENSION; + auto stream_assign = [](auto& dest, std::istringstream& ss) { ss >> dest; }; - std::ofstream out(temp, std::ios::binary | std::ios::trunc); - if (!out) { - log_error(std::format(SETTINGS_INIT_ERROR, temp.string())); - return; - } + auto value_set = [&](auto& dest, std::istringstream& ss) + { + using T = std::decay_t; - out << SETTINGS_SECTION << "\n"; - for (int i = 0; i < SETTINGS_COUNT; i++) - _settings_setting_write(self, out, SETTINGS_ENTRIES[i]); + if constexpr (std::is_same_v) + { + std::string val; + stream_assign(val, ss); + dest = (val == "true" || val == "1"); + } + else if constexpr (std::is_same_v) + std::getline(ss, dest); + else + stream_assign(dest, ss); + }; - out << "\n" << SETTINGS_SECTION_IMGUI << "\n"; - out << data; + auto entry_load = + [&](const std::string& key, std::istringstream& ss, const std::string& name, auto& value, std::string_view type) + { + using T = std::decay_t; - out.flush(); + auto is_match = [&](const char* suffix) { return key == name + suffix; }; - if (!out.good()) { - log_error(std::format(SETTINGS_SAVE_ERROR, temp.string())); - return; - } + if constexpr (std::is_same_v || std::is_same_v) + { + if (type.ends_with("_WH")) + { + if (is_match("W")) + { + stream_assign(value.x, ss); + return true; + } + if (is_match("H")) + { + stream_assign(value.y, ss); + return true; + } + } + else + { + if (is_match("X")) + { + stream_assign(value.x, ss); + return true; + } + if (is_match("Y")) + { + stream_assign(value.y, ss); + return true; + } + } + } + else if constexpr (std::is_same_v) + { + if (is_match("R")) + { + stream_assign(value.x, ss); + return true; + } + if (is_match("G")) + { + stream_assign(value.y, ss); + return true; + } + if (is_match("B")) + { + stream_assign(value.z, ss); + return true; + } + } + else if constexpr (std::is_same_v) + { + if (is_match("R")) + { + stream_assign(value.x, ss); + return true; + } + if (is_match("G")) + { + stream_assign(value.y, ss); + return true; + } + if (is_match("B")) + { + stream_assign(value.z, ss); + return true; + } + if (is_match("A")) + { + stream_assign(value.w, ss); + return true; + } + } + else + { + if (key == name) + { + value_set(value, ss); + return true; + } + } - out.close(); + return false; + }; - std::error_code errorCode; - std::filesystem::rename(temp, filesystemPath, errorCode); - if (errorCode) { - // Windows can block rename if target exists; try remove+rename - std::filesystem::remove(filesystemPath, errorCode); - errorCode = {}; - std::filesystem::rename(temp, filesystemPath, errorCode); - if (errorCode) { - log_error(std::format(SETTINGS_SAVE_FINALIZE_ERROR, filesystemPath.string(), errorCode.message())); - std::filesystem::remove(temp); - return; + while (std::getline(file, line)) + { + if (line == "[Settings]" || line.empty()) continue; + if (line == "# Dear ImGui") break; + + auto eq = line.find('='); + if (eq == std::string::npos) continue; + + auto key = line.substr(0, eq); + std::istringstream ss(line.substr(eq + 1)); + +#define X(symbol, name, string, type, ...) \ + if (entry_load(key, ss, #name, name, #type)) continue; + SETTINGS_MEMBERS SETTINGS_SHORTCUTS SETTINGS_WINDOWS +#undef X } + + file.close(); } - log_info(std::format(SETTINGS_SAVE_INFO, path)); -} + void Settings::save(const std::string& path, const std::string& imguiData) + { + std::ofstream file(path, std::ios::out | std::ios::binary); + file << "[Settings]\n"; -void settings_init(Settings* self) { - const std::string path = settings_path_get(); - std::ifstream file(path, std::ios::binary); + auto value_save = [&](const std::string& key, const auto& value) + { + using T = std::decay_t; - if (file) - log_info(std::format(SETTINGS_INIT_INFO, path)); - else { - log_warning(std::format(SETTINGS_INIT_WARNING, path)); - settings_save(self); - std::ofstream out(path, std::ios::binary | std::ios::app); - out << SETTINGS_IMGUI_DEFAULT; - out.flush(); - out.close(); - file.open(path, std::ios::binary); - } + if constexpr (std::is_same_v) + file << key << "=" << (value ? "true" : "false") << "\n"; + else + file << key << "=" << value << "\n"; + }; + auto entry_save = [&](const std::string& name, const auto& value, const std::string_view type) + { + using T = std::decay_t; - std::string line; - bool inSettingsSection = false; + if constexpr (std::is_same_v || std::is_same_v) + { + if (type.ends_with("_WH")) + { + value_save(name + "W", value.x); + value_save(name + "H", value.y); + } + else + { + value_save(name + "X", value.x); + value_save(name + "Y", value.y); + } + } + else if constexpr (std::is_same_v) + { + value_save(name + "R", value.x); + value_save(name + "G", value.y); + value_save(name + "B", value.z); + } + else if constexpr (std::is_same_v) + { + value_save(name + "R", value.x); + value_save(name + "G", value.y); + value_save(name + "B", value.z); + value_save(name + "A", value.w); + } + else + value_save(name, value); + }; - while (std::getline(file, line)) { - if (line == SETTINGS_SECTION) { - inSettingsSection = true; - continue; - } - if (line.empty()) - continue; - if (line == SETTINGS_SECTION_IMGUI) - break; - if (inSettingsSection) - _settings_setting_load(self, line); +#define X(symbol, name, string, type, ...) entry_save(#name, name, #type); + SETTINGS_MEMBERS SETTINGS_SHORTCUTS SETTINGS_WINDOWS +#undef X + + file + << "\n# Dear ImGui\n" + << imguiData; + + file.flush(); + file.close(); } } \ No newline at end of file diff --git a/src/settings.h b/src/settings.h index 79fa9fe..0197ee9 100644 --- a/src/settings.h +++ b/src/settings.h @@ -1,366 +1,252 @@ #pragma once +#include + +#include + #include "anm2.h" -#include "render.h" -#include "tool.h" - -#define SETTINGS_SECTION "[Settings]" -#define SETTINGS_SECTION_IMGUI "# Dear ImGui" -#define SETTINGS_INIT_WARNING "Unable to read settings file: {}; using default settings" -#define SETTINGS_INIT_ERROR "Unable to read settings file: {}" -#define SETTINGS_SAVE_ERROR "Failed to write settings file: {}" -#define SETTINGS_SAVE_FINALIZE_ERROR "Failed to write settings file: {} ({})" -#define SETTINGS_VALUE_INIT_WARNING "Unknown setting: {}" -#define SETTINGS_FLOAT_FORMAT "{:.3f}" -#define SETTINGS_INIT_INFO "Initialized settings from: {}" -#define SETTINGS_DIRECTORY_ERROR "Failed to create settings directory: {} ({})" -#define SETTINGS_SAVE_INFO "Saved settings to: {}" - -#define SETTINGS_FOLDER "anm2ed" -#define SETTINGS_PATH "settings.ini" -#define SETTINGS_TEMPORARY_EXTENSION ".tmp" +#include "types.h" +namespace anm2ed::settings +{ #ifdef _WIN32 -#define SETTINGS_RENDER_FFMPEG_PATH_VALUE_DEFAULT "C:\\ffmpeg\\bin\\ffmpeg.exe" + constexpr auto FFMPEG_PATH_DEFAULT = "C:\\ffmpeg\\bin\\ffmpeg.exe"; #else -#define SETTINGS_RENDER_FFMPEG_PATH_VALUE_DEFAULT "/usr/bin/ffmpeg" + constexpr auto FFMPEG_PATH_DEFAULT = "/usr/bin/ffmpeg"; #endif -#define SETTINGS_LIST \ - /* Symbol / Name / Type / Default */ \ - X(WINDOW_SIZE, windowSize, TYPE_IVEC2_WH, {1600, 900}) \ - X(IS_VSYNC, isVsync, TYPE_BOOL, true) \ - X(DISPLAY_SCALE, displayScale, TYPE_FLOAT, 1.0f) \ - \ - X(HOTKEY_CENTER_VIEW, hotkeyCenterView, TYPE_STRING, "Home") \ - X(HOTKEY_FIT, hotkeyFit, TYPE_STRING, "F") \ - X(HOTKEY_ZOOM_IN, hotkeyZoomIn, TYPE_STRING, "Ctrl++") \ - X(HOTKEY_ZOOM_OUT, hotkeyZoomOut, TYPE_STRING, "Ctrl+-") \ - X(HOTKEY_PLAY_PAUSE, hotkeyPlayPause, TYPE_STRING, "Space") \ - X(HOTKEY_ONIONSKIN, hotkeyOnionskin, TYPE_STRING, "O") \ - X(HOTKEY_NEW, hotkeyNew, TYPE_STRING, "Ctrl+N") \ - X(HOTKEY_OPEN, hotkeyOpen, TYPE_STRING, "Ctrl+O") \ - X(HOTKEY_SAVE, hotkeySave, TYPE_STRING, "Ctrl+S") \ - X(HOTKEY_SAVE_AS, hotkeySaveAs, TYPE_STRING, "Ctrl+Shift+S") \ - X(HOTKEY_EXIT, hotkeyExit, TYPE_STRING, "Alt+F4") \ - X(HOTKEY_SHORTEN_FRAME, hotkeyShortenFrame, TYPE_STRING, "F4") \ - X(HOTKEY_EXTEND_FRAME, hotkeyExtendFrame, TYPE_STRING, "F5") \ - X(HOTKEY_INSERT_FRAME, hotkeyInsertFrame, TYPE_STRING, "F6") \ - X(HOTKEY_PREVIOUS_FRAME, hotkeyPreviousFrame, TYPE_STRING, "Comma") \ - X(HOTKEY_NEXT_FRAME, hotkeyNextFrame, TYPE_STRING, "Period") \ - X(HOTKEY_PAN, hotkeyPan, TYPE_STRING, "P") \ - X(HOTKEY_MOVE, hotkeyMove, TYPE_STRING, "V") \ - X(HOTKEY_ROTATE, hotkeyRotate, TYPE_STRING, "R") \ - X(HOTKEY_SCALE, hotkeyScale, TYPE_STRING, "S") \ - X(HOTKEY_CROP, hotkeyCrop, TYPE_STRING, "C") \ - X(HOTKEY_DRAW, hotkeyDraw, TYPE_STRING, "B") \ - X(HOTKEY_ERASE, hotkeyErase, TYPE_STRING, "E") \ - X(HOTKEY_COLOR_PICKER, hotkeyColorPicker, TYPE_STRING, "I") \ - X(HOTKEY_UNDO, hotkeyUndo, TYPE_STRING, "Ctrl+Z") \ - X(HOTKEY_REDO, hotkeyRedo, TYPE_STRING, "Ctrl+Shift+Z") \ - X(HOTKEY_COPY, hotkeyCopy, TYPE_STRING, "Ctrl+C") \ - X(HOTKEY_CUT, hotkeyCut, TYPE_STRING, "Ctrl+X") \ - X(HOTKEY_PASTE, hotkeyPaste, TYPE_STRING, "Ctrl+V") \ - X(HOTKEY_SELECT_ALL, hotkeySelectAll, TYPE_STRING, "Ctrl+A") \ - X(HOTKEY_SELECT_NONE, hotkeySelectNone, TYPE_STRING, "Ctrl+Shift+A") \ - \ - X(PLAYBACK_IS_LOOP, playbackIsLoop, TYPE_BOOL, true) \ - X(PLAYBACK_IS_CLAMP_PLAYHEAD, playbackIsClampPlayhead, TYPE_BOOL, true) \ - \ - X(CHANGE_IS_CROP, changeIsCrop, TYPE_BOOL, false) \ - X(CHANGE_IS_SIZE, changeIsSize, TYPE_BOOL, false) \ - X(CHANGE_IS_POSITION, changeIsPosition, TYPE_BOOL, false) \ - X(CHANGE_IS_PIVOT, changeIsPivot, TYPE_BOOL, false) \ - X(CHANGE_IS_SCALE, changeIsScale, TYPE_BOOL, false) \ - X(CHANGE_IS_ROTATION, changeIsRotation, TYPE_BOOL, false) \ - X(CHANGE_IS_DELAY, changeIsDelay, TYPE_BOOL, false) \ - X(CHANGE_IS_TINT, changeIsTint, TYPE_BOOL, false) \ - X(CHANGE_IS_COLOR_OFFSET, changeIsColorOffset, TYPE_BOOL, false) \ - X(CHANGE_IS_VISIBLE_SET, changeIsVisibleSet, TYPE_BOOL, false) \ - X(CHANGE_IS_INTERPOLATED_SET, changeIsInterpolatedSet, TYPE_BOOL, false) \ - X(CHANGE_IS_FROM_SELECTED_FRAME, changeIsFromSelectedFrame, TYPE_BOOL, false) \ - X(CHANGE_CROP, changeCrop, TYPE_VEC2, {}) \ - X(CHANGE_SIZE, changeSize, TYPE_VEC2, {}) \ - X(CHANGE_POSITION, changePosition, TYPE_VEC2, {}) \ - X(CHANGE_PIVOT, changePivot, TYPE_VEC2, {}) \ - X(CHANGE_SCALE, changeScale, TYPE_VEC2, {}) \ - X(CHANGE_ROTATION, changeRotation, TYPE_FLOAT, 0.0f) \ - X(CHANGE_DELAY, changeDelay, TYPE_INT, 0) \ - X(CHANGE_TINT, changeTint, TYPE_VEC4, {}) \ - X(CHANGE_COLOR_OFFSET, changeColorOffset, TYPE_VEC3, {}) \ - X(CHANGE_IS_VISIBLE, changeIsVisible, TYPE_BOOL, false) \ - X(CHANGE_IS_INTERPOLATED, changeIsInterpolated, TYPE_BOOL, false) \ - X(CHANGE_NUMBER_FRAMES, changeNumberFrames, TYPE_INT, 1) \ - \ - X(SCALE_VALUE, scaleValue, TYPE_FLOAT, 1.0f) \ - \ - X(PREVIEW_IS_AXES, previewIsAxes, TYPE_BOOL, true) \ - X(PREVIEW_IS_GRID, previewIsGrid, TYPE_BOOL, true) \ - X(PREVIEW_IS_ROOT_TRANSFORM, previewIsRootTransform, TYPE_BOOL, true) \ - X(PREVIEW_IS_TRIGGERS, previewIsTriggers, TYPE_BOOL, true) \ - X(PREVIEW_IS_PIVOTS, previewIsPivots, TYPE_BOOL, false) \ - X(PREVIEW_IS_ICONS, previewIsIcons, TYPE_BOOL, true) \ - X(PREVIEW_IS_BORDER, previewIsBorder, TYPE_BOOL, false) \ - X(PREVIEW_IS_ALT_ICONS, previewIsAltIcons, TYPE_BOOL, false) \ - X(PREVIEW_OVERLAY_TRANSPARENCY, previewOverlayTransparency, TYPE_FLOAT, 255.0f) \ - X(PREVIEW_ZOOM, previewZoom, TYPE_FLOAT, 200.0f) \ - X(PREVIEW_PAN, previewPan, TYPE_VEC2, {}) \ - X(PREVIEW_GRID_SIZE, previewGridSize, TYPE_IVEC2, {32, 32}) \ - X(PREVIEW_GRID_OFFSET, previewGridOffset, TYPE_IVEC2, {}) \ - X(PREVIEW_GRID_COLOR, previewGridColor, TYPE_VEC4, {1.0, 1.0, 1.0, 0.125}) \ - X(PREVIEW_AXES_COLOR, previewAxesColor, TYPE_VEC4, {1.0, 1.0, 1.0, 0.125}) \ - X(PREVIEW_BACKGROUND_COLOR, previewBackgroundColor, TYPE_VEC4, {0.113, 0.184, 0.286, 1.0}) \ - \ - X(PROPERTIES_IS_ROUND, propertiesIsRound, TYPE_BOOL, false) \ - \ - X(GENERATE_START_POSITION, generateStartPosition, TYPE_IVEC2, {}) \ - X(GENERATE_SIZE, generateSize, TYPE_IVEC2, {64, 64}) \ - X(GENERATE_PIVOT, generatePivot, TYPE_IVEC2, {32, 32}) \ - X(GENERATE_ROWS, generateRows, TYPE_INT, 4) \ - X(GENERATE_COLUMNS, generateColumns, TYPE_INT, 4) \ - X(GENERATE_COUNT, generateCount, TYPE_INT, 16) \ - X(GENERATE_DELAY, generateDelay, TYPE_INT, 1) \ - \ - X(EDITOR_IS_GRID, editorIsGrid, TYPE_BOOL, true) \ - X(EDITOR_IS_GRID_SNAP, editorIsGridSnap, TYPE_BOOL, true) \ - X(EDITOR_IS_BORDER, editorIsBorder, TYPE_BOOL, true) \ - X(EDITOR_ZOOM, editorZoom, TYPE_FLOAT, 200.0f) \ - X(EDITOR_PAN, editorPan, TYPE_VEC2, {0.0, 0.0}) \ - X(EDITOR_GRID_SIZE, editorGridSize, TYPE_IVEC2, {32, 32}) \ - X(EDITOR_GRID_OFFSET, editorGridOffset, TYPE_IVEC2, {32, 32}) \ - X(EDITOR_GRID_COLOR, editorGridColor, TYPE_VEC4, {1.0, 1.0, 1.0, 0.125}) \ - X(EDITOR_BACKGROUND_COLOR, editorBackgroundColor, TYPE_VEC4, {0.113, 0.184, 0.286, 1.0}) \ - \ - X(MERGE_TYPE, mergeType, TYPE_INT, ANM2_MERGE_APPEND) \ - X(MERGE_IS_DELETE_ANIMATIONS_AFTER, mergeIsDeleteAnimationsAfter, TYPE_BOOL, false) \ - \ - X(BAKE_INTERVAL, bakeInterval, TYPE_INT, 1) \ - X(BAKE_IS_ROUND_SCALE, bakeIsRoundScale, TYPE_BOOL, true) \ - X(BAKE_IS_ROUND_ROTATION, bakeIsRoundRotation, TYPE_BOOL, true) \ - \ - X(TIMELINE_ADD_ITEM_TYPE, timelineAddItemType, TYPE_INT, ANM2_LAYER) \ - X(TIMELINE_IS_SHOW_UNUSED, timelineIsShowUnused, TYPE_BOOL, true) \ - \ - X(ONIONSKIN_IS_ENABLED, onionskinIsEnabled, TYPE_BOOL, false) \ - X(ONIONSKIN_DRAW_ORDER, onionskinDrawOrder, TYPE_INT, ONIONSKIN_BELOW) \ - X(ONIONSKIN_BEFORE_COUNT, onionskinBeforeCount, TYPE_INT, 0) \ - X(ONIONSKIN_AFTER_COUNT, onionskinAfterCount, TYPE_INT, 0) \ - X(ONIONSKIN_BEFORE_COLOR_OFFSET, onionskinBeforeColorOffset, TYPE_VEC3, COLOR_RED) \ - X(ONIONSKIN_AFTER_COLOR_OFFSET, onionskinAfterColorOffset, TYPE_VEC3, COLOR_BLUE) \ - \ - X(TOOL, tool, TYPE_INT, TOOL_PAN) \ - X(TOOL_COLOR, toolColor, TYPE_VEC4, {1.0, 1.0, 1.0, 1.0}) \ - \ - X(RENDER_TYPE, renderType, TYPE_INT, RENDER_PNG) \ - X(RENDER_PATH, renderPath, TYPE_STRING, ".") \ - X(RENDER_FORMAT, renderFormat, TYPE_STRING, "{}.png") \ - X(RENDER_IS_USE_ANIMATION_BOUNDS, renderIsUseAnimationBounds, TYPE_BOOL, true) \ - X(RENDER_IS_TRANSPARENT, renderIsTransparent, TYPE_BOOL, true) \ - X(RENDER_SCALE, renderScale, TYPE_FLOAT, 1.0f) \ - X(RENDER_FFMPEG_PATH, renderFFmpegPath, TYPE_STRING, SETTINGS_RENDER_FFMPEG_PATH_VALUE_DEFAULT) +#define SETTINGS_TYPES \ + X(INT, int) \ + X(BOOL, bool) \ + X(FLOAT, float) \ + X(STRING, std::string) \ + X(IVEC2, glm::ivec2) \ + X(IVEC2_WH, glm::ivec2) \ + X(VEC2, glm::vec2) \ + X(VEC2_WH, glm::vec2) \ + X(VEC3, glm::vec3) \ + X(VEC4, glm::vec4) -#define X(symbol, name, type, ...) const inline DATATYPE_TO_CTYPE(type) SETTINGS_##symbol##_DEFAULT = __VA_ARGS__; -SETTINGS_LIST + enum Type + { +#define X(name, type) name, + SETTINGS_TYPES +#undef X + }; + +#define X(name, type) using TYPE_##name = type; + SETTINGS_TYPES #undef X -struct Settings { -#define X(symbol, name, type, ...) DATATYPE_TO_CTYPE(type) name = SETTINGS_##symbol##_DEFAULT; - SETTINGS_LIST +#define SETTINGS_MEMBERS \ + /* Symbol / Name / String / Type / Default */ \ + X(WINDOW_SIZE, windowSize, "Window Size", IVEC2_WH, {1600, 900}) \ + X(IS_VSYNC, isVsync, "Vsync", BOOL, true) \ + X(DISPLAY_SCALE, displayScale, "Display Scale", FLOAT, 1.0f) \ + \ + X(VIEW_ZOOM_STEP, viewZoomStep, "Zoom Step", FLOAT, 50.0f) \ + \ + X(PLAYBACK_IS_LOOP, playbackIsLoop, "Loop", BOOL, true) \ + X(PLAYBACK_IS_CLAMP_PLAYHEAD, playbackIsClampPlayhead, "Clamp Playhead", BOOL, true) \ + \ + X(CHANGE_IS_CROP, changeIsCrop, "##Is Crop", BOOL, false) \ + X(CHANGE_IS_SIZE, changeIsSize, "##Is Size", BOOL, false) \ + X(CHANGE_IS_POSITION, changeIsPosition, "##Is Position", BOOL, false) \ + X(CHANGE_IS_PIVOT, changeIsPivot, "##Is Pivot", BOOL, false) \ + X(CHANGE_IS_SCALE, changeIsScale, "##Is Scale", BOOL, false) \ + X(CHANGE_IS_ROTATION, changeIsRotation, "##Is Rotation", BOOL, false) \ + X(CHANGE_IS_DELAY, changeIsDelay, "##Is Delay", BOOL, false) \ + X(CHANGE_IS_TINT, changeIsTint, "##Is Tint", BOOL, false) \ + X(CHANGE_IS_COLOR_OFFSET, changeIsColorOffset, "##Is Color Offset", BOOL, false) \ + X(CHANGE_IS_VISIBLE_SET, changeIsVisibleSet, "##Is Visible", BOOL, false) \ + X(CHANGE_IS_INTERPOLATED_SET, changeIsInterpolatedSet, "##Is Interpolated", BOOL, false) \ + X(CHANGE_IS_FROM_SELECTED_FRAME, changeIsFromSelectedFrame, "From Selected Frame", BOOL, false) \ + X(CHANGE_CROP, changeCrop, "Crop", VEC2, {}) \ + X(CHANGE_SIZE, changeSize, "Size", VEC2, {}) \ + X(CHANGE_POSITION, changePosition, "Position", VEC2, {}) \ + X(CHANGE_PIVOT, changePivot, "Pivot", VEC2, {}) \ + X(CHANGE_SCALE, changeScale, "Scale", VEC2, {}) \ + X(CHANGE_ROTATION, changeRotation, "Rotation", FLOAT, 0.0f) \ + X(CHANGE_DELAY, changeDelay, "Delay", INT, 0) \ + X(CHANGE_TINT, changeTint, "Tint", VEC4, {}) \ + X(CHANGE_COLOR_OFFSET, changeColorOffset, "Color Offset", VEC3, {}) \ + X(CHANGE_IS_VISIBLE, changeIsVisible, "Visible", BOOL, false) \ + X(CHANGE_IS_INTERPOLATED, changeIsInterpolated, "Interpolated", BOOL, false) \ + X(CHANGE_NUMBER_FRAMES, changeNumberFrames, "Frame Count", INT, 1) \ + \ + X(SCALE_VALUE, scaleValue, "Scale", FLOAT, 1.0f) \ + \ + X(PREVIEW_IS_AXES, previewIsAxes, "Axes", BOOL, true) \ + X(PREVIEW_IS_GRID, previewIsGrid, "Grid", BOOL, true) \ + X(PREVIEW_IS_ROOT_TRANSFORM, previewIsRootTransform, "Root Transform", BOOL, true) \ + X(PREVIEW_IS_PIVOTS, previewIsPivots, "Pivots", BOOL, false) \ + X(PREVIEW_IS_ICONS, previewIsIcons, "Icons", BOOL, true) \ + X(PREVIEW_IS_BORDER, previewIsBorder, "Border", BOOL, false) \ + X(PREVIEW_IS_ALT_ICONS, previewIsAltIcons, "Alt Icons", BOOL, false) \ + X(PREVIEW_OVERLAY_TRANSPARENCY, previewOverlayTransparency, "Alpha", FLOAT, 255) \ + X(PREVIEW_ZOOM, previewZoom, "Zoom", FLOAT, 200.0f) \ + X(PREVIEW_PAN, previewPan, "Pan", VEC2, {}) \ + X(PREVIEW_GRID_SIZE, previewGridSize, "Size", IVEC2, {32, 32}) \ + X(PREVIEW_GRID_OFFSET, previewGridOffset, "Offset", IVEC2, {}) \ + X(PREVIEW_GRID_COLOR, previewGridColor, "Color", VEC4, {1.0f, 1.0f, 1.0f, 0.125f}) \ + X(PREVIEW_AXES_COLOR, previewAxesColor, "Color", VEC4, {1.0f, 1.0f, 1.0f, 0.125f}) \ + X(PREVIEW_BACKGROUND_COLOR, previewBackgroundColor, "Background Color", VEC4, {0.113f, 0.184f, 0.286f, 1.0f}) \ + \ + X(PROPERTIES_IS_ROUND, propertiesIsRound, "Round", BOOL, false) \ + \ + X(GENERATE_START_POSITION, generateStartPosition, "Start Position", IVEC2, {}) \ + X(GENERATE_SIZE, generateSize, "Size", IVEC2, {64, 64}) \ + X(GENERATE_PIVOT, generatePivot, "Pivot", IVEC2, {32, 32}) \ + X(GENERATE_ROWS, generateRows, "Rows", INT, 4) \ + X(GENERATE_COLUMNS, generateColumns, "Columns", INT, 4) \ + X(GENERATE_COUNT, generateCount, "Count", INT, 16) \ + X(GENERATE_DELAY, generateDelay, "Delay", INT, 1) \ + \ + X(EDITOR_IS_GRID, editorIsGrid, "Grid", BOOL, true) \ + X(EDITOR_IS_GRID_SNAP, editorIsGridSnap, "Snap", BOOL, true) \ + X(EDITOR_IS_BORDER, editorIsBorder, "Border", BOOL, true) \ + X(EDITOR_ZOOM, editorZoom, "Zoom", FLOAT, 200.0f) \ + X(EDITOR_PAN, editorPan, "Pan", VEC2, {0.0, 0.0}) \ + X(EDITOR_GRID_SIZE, editorGridSize, "Size", IVEC2, {32, 32}) \ + X(EDITOR_GRID_OFFSET, editorGridOffset, "Offset", IVEC2, {32, 32}) \ + X(EDITOR_GRID_COLOR, editorGridColor, "Color", VEC4, {1.0, 1.0, 1.0, 0.125}) \ + X(EDITOR_BACKGROUND_COLOR, editorBackgroundColor, "Background Color", VEC4, {0.113, 0.184, 0.286, 1.0}) \ + \ + X(MERGE_TYPE, mergeType, "Type", INT, 0) \ + X(MERGE_IS_DELETE_ANIMATIONS_AFTER, mergeIsDeleteAnimationsAfter, "Delete Animations After", BOOL, false) \ + \ + X(BAKE_INTERVAL, bakeInterval, "Interval", INT, 1) \ + X(BAKE_IS_ROUND_SCALE, bakeIsRoundScale, "Round Scale", BOOL, true) \ + X(BAKE_IS_ROUND_ROTATION, bakeIsRoundRotation, "Round Rotation", BOOL, true) \ + \ + X(TIMELINE_ADD_ITEM_TYPE, timelineAddItemType, "Add Item Type", INT, anm2::LAYER) \ + X(TIMELINE_IS_SHOW_UNUSED, timelineIsShowUnused, "##Show Unused", BOOL, true) \ + \ + X(ONIONSKIN_IS_ENABLED, onionskinIsEnabled, "Enabled", BOOL, false) \ + X(ONIONSKIN_DRAW_ORDER, onionskinDrawOrder, "Draw Order", INT, 0) \ + X(ONIONSKIN_BEFORE_COUNT, onionskinBeforeCount, "Frames", INT, 0) \ + X(ONIONSKIN_AFTER_COUNT, onionskinAfterCount, "Frames", INT, 0) \ + X(ONIONSKIN_BEFORE_COLOR, onionskinBeforeColor, "Color", VEC3, types::color::RED) \ + X(ONIONSKIN_AFTER_COLOR, onionskinAfterColor, "Color", VEC3, types::color::BLUE) \ + \ + X(TOOL, tool, "##Tool", INT, 0) \ + X(TOOL_COLOR, toolColor, "##Color", VEC4, {1.0, 1.0, 1.0, 1.0}) \ + \ + X(RENDER_TYPE, renderType, "Output", INT, 0) \ + X(RENDER_PATH, renderPath, "Path", STRING, ".") \ + X(RENDER_FORMAT, renderFormat, "Format", STRING, "{}.png") \ + X(RENDER_IS_USE_ANIMATION_BOUNDS, renderIsUseAnimationBounds, "Use Animation Bounds", BOOL, true) \ + X(RENDER_IS_TRANSPARENT, renderIsTransparent, "Transparent", BOOL, true) \ + X(RENDER_SCALE, renderScale, "Scale", FLOAT, 1.0f) \ + X(RENDER_FFMPEG_PATH, renderFFmpegPath, "FFmpeg Path", STRING, FFMPEG_PATH_DEFAULT) + +#define SETTINGS_SHORTCUTS \ + /* Symbol / Name / String / Type / Default */ \ + X(SHORTCUT_CENTER_VIEW, shortcutCenterView, "Center View", STRING, "Home") \ + X(SHORTCUT_FIT, shortcutFit, "Fit", STRING, "F") \ + X(SHORTCUT_ZOOM_IN, shortcutZoomIn, "Zoom In", STRING, "Ctrl++") \ + X(SHORTCUT_ZOOM_OUT, shortcutZoomOut, "Zoom Out", STRING, "Ctrl+-") \ + X(SHORTCUT_PLAY_PAUSE, shortcutPlayPause, "Play/Pause", STRING, "Space") \ + X(SHORTCUT_ONIONSKIN, shortcutOnionskin, "Onionskin", STRING, "O") \ + X(SHORTCUT_NEW, shortcutNew, "New", STRING, "Ctrl+N") \ + X(SHORTCUT_OPEN, shortcutOpen, "Open", STRING, "Ctrl+O") \ + X(SHORTCUT_CLOSE, shortcutClose, "Close", STRING, "Ctrl+W") \ + X(SHORTCUT_SAVE, shortcutSave, "Save", STRING, "Ctrl+S") \ + X(SHORTCUT_SAVE_AS, shortcutSaveAs, "Save As", STRING, "Ctrl+Shift+S") \ + X(SHORTCUT_EXIT, shortcutExit, "Exit", STRING, "Alt+F4") \ + X(SHORTCUT_SHORTEN_FRAME, shortcutShortenFrame, "Shorten Frame", STRING, "F4") \ + X(SHORTCUT_EXTEND_FRAME, shortcutExtendFrame, "Extend Frame", STRING, "F5") \ + X(SHORTCUT_INSERT_FRAME, shortcutInsertFrame, "Insert Frame", STRING, "F6") \ + X(SHORTCUT_PREVIOUS_FRAME, shortcutPreviousFrame, "Previous Frame", STRING, "Comma") \ + X(SHORTCUT_NEXT_FRAME, shortcutNextFrame, "Next Frame", STRING, "Period") \ + X(SHORTCUT_PAN, shortcutPan, "Pan", STRING, "P") \ + X(SHORTCUT_MOVE, shortcutMove, "Move", STRING, "V") \ + X(SHORTCUT_ROTATE, shortcutRotate, "Rotate", STRING, "R") \ + X(SHORTCUT_SCALE, shortcutScale, "Scale", STRING, "S") \ + X(SHORTCUT_CROP, shortcutCrop, "Crop", STRING, "C") \ + X(SHORTCUT_DRAW, shortcutDraw, "Draw", STRING, "B") \ + X(SHORTCUT_ERASE, shortcutErase, "Erase", STRING, "E") \ + X(SHORTCUT_COLOR_PICKER, shortcutColorPicker, "Color Picker", STRING, "I") \ + X(SHORTCUT_UNDO, shortcutUndo, "Undo", STRING, "Ctrl+Z") \ + X(SHORTCUT_REDO, shortcutRedo, "Redo", STRING, "Ctrl+Shift+Z") \ + X(SHORTCUT_COLOR, shortcutColor, "Color", STRING, "X") \ + X(SHORTCUT_COPY, shortcutCopy, "Copy", STRING, "Ctrl+C") \ + X(SHORTCUT_CUT, shortcutCut, "Cut", STRING, "Ctrl+X") \ + X(SHORTCUT_ADD, shortcutAdd, "Add", STRING, "Insert") \ + X(SHORTCUT_REMOVE, shortcutRemove, "Remove", STRING, "Delete") \ + X(SHORTCUT_DUPLICATE, shortcutDuplicate, "Duplicate", STRING, "Ctrl+J") \ + X(SHORTCUT_DEFAULT, shortcutDefault, "Default", STRING, "Home") \ + X(SHORTCUT_MERGE, shortcutMerge, "Merge", STRING, "Ctrl+E") \ + X(SHORTCUT_PASTE, shortcutPaste, "Paste", STRING, "Ctrl+V") \ + X(SHORTCUT_SELECT_ALL, shortcutSelectAll, "Select All", STRING, "Ctrl+A") \ + X(SHORTCUT_SELECT_NONE, shortcutSelectNone, "Select None", STRING, "Escape") + +#define SETTINGS_WINDOWS \ + /* Symbol / Name / String / Type / Default */ \ + X(WINDOW_ANIMATIONS, windowIsAnimations, "Animations", BOOL, true) \ + X(WINDOW_ANIMATION_PREVIEW, windowIsAnimationPreview, "Animation Preview", BOOL, true) \ + X(WINDOW_EVENTS, windowIsEvents, "Events", BOOL, true) \ + X(WINDOW_FRAME_PROPERTIES, windowIsFrameProperties, "Frame Properties", BOOL, true) \ + X(WINDOW_LAYERS, windowIsLayers, "Layers", BOOL, true) \ + X(WINDOW_NULLS, windowIsNulls, "Nulls", BOOL, true) \ + X(WINDOW_ONIONSKIN, windowIsOnionskin, "Onionskin", BOOL, true) \ + X(WINDOW_PREVIEW, windowIsSpritesheets, "Spritesheets", BOOL, true) \ + X(WINDOW_SPRITESHEET_EDITOR, windowIsSpritesheetEditor, "Spritesheet Editor", BOOL, true) \ + X(WINDOW_TIMELINE, windowIsTimeline, "Timeline", BOOL, true) \ + X(WINDOW_TOOLS, windowIsTools, "Tools", BOOL, true) + + class Settings + { + public: +#define X(symbol, name, string, type, ...) TYPE_##type name = __VA_ARGS__; + SETTINGS_MEMBERS SETTINGS_SHORTCUTS SETTINGS_WINDOWS #undef X -}; -struct SettingsEntry { - std::string key; - DataType type; - int offset; -}; + Settings(); -const inline SettingsEntry SETTINGS_ENTRIES[] = { -#define X(symbol, name, type, ...) {#name, type, offsetof(Settings, name)}, - SETTINGS_LIST + Settings(const std::string& path); + void save(const std::string& path, const std::string& imguiData); + }; + + enum ShortcutType + { +#define X(symbol, name, string, type, ...) symbol, + SETTINGS_SHORTCUTS #undef X -}; + SHORTCUT_COUNT + }; -constexpr int SETTINGS_COUNT = (int)std::size(SETTINGS_ENTRIES); - -#define HOTKEY_LIST \ - X(NONE, "None") \ - X(CENTER_VIEW, "Center View") \ - X(FIT, "Fit") \ - X(ZOOM_IN, "Zoom In") \ - X(ZOOM_OUT, "Zoom Out") \ - X(PLAY_PAUSE, "Play/Pause") \ - X(ONIONSKIN, "Onionskin") \ - X(NEW, "New") \ - X(OPEN, "Open") \ - X(SAVE, "Save") \ - X(SAVE_AS, "Save As") \ - X(EXIT, "Exit") \ - X(SHORTEN_FRAME, "Shorten Frame") \ - X(EXTEND_FRAME, "Extend Frame") \ - X(INSERT_FRAME, "Insert Frame") \ - X(PREVIOUS_FRAME, "Previous Frame") \ - X(NEXT_FRAME, "Next Frame") \ - X(PAN, "Pan") \ - X(MOVE, "Move") \ - X(ROTATE, "Rotate") \ - X(SCALE, "Scale") \ - X(CROP, "Crop") \ - X(DRAW, "Draw") \ - X(ERASE, "Erase") \ - X(COLOR_PICKER, "Color Picker") \ - X(UNDO, "Undo") \ - X(REDO, "Redo") \ - X(COPY, "Copy") \ - X(CUT, "Cut") \ - X(PASTE, "Paste") \ - X(SELECT_ALL, "Select All") \ - X(SELECT_NONE, "Select None") - -typedef enum { -#define X(name, str) HOTKEY_##name, - HOTKEY_LIST + constexpr const char* SHORTCUT_STRINGS[] = { +#define X(symbol, name, string, type, ...) string, + SETTINGS_SHORTCUTS #undef X - HOTKEY_COUNT -} HotkeyType; + }; -const inline char* HOTKEY_STRINGS[] = { -#define X(name, str) str, - HOTKEY_LIST + using ShortcutMember = std::string Settings::*; + constexpr ShortcutMember SHORTCUT_MEMBERS[] = { +#define X(symbol, name, string, type, ...) &Settings::name, + SETTINGS_SHORTCUTS #undef X -}; + }; -using HotkeyMember = std::string Settings::*; + enum WindowType + { +#define X(symbol, name, string, type, ...) symbol, + SETTINGS_WINDOWS +#undef X + WINDOW_COUNT + }; -const inline HotkeyMember SETTINGS_HOTKEY_MEMBERS[HOTKEY_COUNT] = {nullptr, - &Settings::hotkeyCenterView, - &Settings::hotkeyFit, - &Settings::hotkeyZoomIn, - &Settings::hotkeyZoomOut, - &Settings::hotkeyPlayPause, - &Settings::hotkeyOnionskin, - &Settings::hotkeyNew, - &Settings::hotkeyOpen, - &Settings::hotkeySave, - &Settings::hotkeySaveAs, - &Settings::hotkeyExit, - &Settings::hotkeyShortenFrame, - &Settings::hotkeyExtendFrame, - &Settings::hotkeyInsertFrame, - &Settings::hotkeyPreviousFrame, - &Settings::hotkeyNextFrame, - &Settings::hotkeyPan, - &Settings::hotkeyMove, - &Settings::hotkeyRotate, - &Settings::hotkeyScale, - &Settings::hotkeyCrop, - &Settings::hotkeyDraw, - &Settings::hotkeyErase, - &Settings::hotkeyColorPicker, - &Settings::hotkeyUndo, - &Settings::hotkeyRedo, - &Settings::hotkeyCopy, - &Settings::hotkeyCut, - &Settings::hotkeyPaste, - &Settings::hotkeySelectAll, - &Settings::hotkeySelectNone}; + constexpr const char* WINDOW_STRINGS[] = { +#define X(symbol, name, string, type, ...) string, + SETTINGS_WINDOWS +#undef X + }; -const inline std::string SETTINGS_IMGUI_DEFAULT = R"( -# Dear ImGui -[Window][## Window] -Pos=0,32 -Size=1600,868 -Collapsed=0 - -[Window][Debug##Default] -Pos=60,60 -Size=400,400 -Collapsed=0 - -[Window][Tools] -Pos=8,40 -Size=38,516 -Collapsed=0 -DockId=0x0000000B,0 - -[Window][Animations] -Pos=1289,307 -Size=303,249 -Collapsed=0 -DockId=0x0000000A,0 - -[Window][Events] -Pos=957,264 -Size=330,292 -Collapsed=0 -DockId=0x00000008,2 - -[Window][Spritesheets] -Pos=1289,40 -Size=303,265 -Collapsed=0 -DockId=0x00000009,0 - -[Window][Animation Preview] -Pos=48,40 -Size=907,516 -Collapsed=0 -DockId=0x0000000C,0 - -[Window][Spritesheet Editor] -Pos=48,40 -Size=907,516 -Collapsed=0 -DockId=0x0000000C,1 - -[Window][Timeline] -Pos=8,558 -Size=1584,334 -Collapsed=0 -DockId=0x00000004,0 - -[Window][Frame Properties] -Pos=957,40 -Size=330,222 -Collapsed=0 -DockId=0x00000007,0 - -[Window][Onionskin] -Pos=957,264 -Size=330,292 -Collapsed=0 -DockId=0x00000008,3 - -[Window][Layers] -Pos=957,264 -Size=330,292 -Collapsed=0 -DockId=0x00000008,0 - -[Window][Nulls] -Pos=957,264 -Size=330,292 -Collapsed=0 -DockId=0x00000008,1 - - -[Docking][Data] -DockSpace ID=0xFC02A410 Window=0x0E46F4F7 Pos=8,40 Size=1584,852 Split=Y - DockNode ID=0x00000003 Parent=0xFC02A410 SizeRef=1902,680 Split=X - DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1017,1016 Split=X Selected=0x024430EF - DockNode ID=0x00000005 Parent=0x00000001 SizeRef=1264,654 Split=X Selected=0x024430EF - DockNode ID=0x0000000B Parent=0x00000005 SizeRef=38,654 Selected=0x18A5FDB9 - DockNode ID=0x0000000C Parent=0x00000005 SizeRef=1224,654 CentralNode=1 Selected=0x024430EF - DockNode ID=0x00000006 Parent=0x00000001 SizeRef=330,654 Split=Y Selected=0x754E368F - DockNode ID=0x00000007 Parent=0x00000006 SizeRef=631,293 Selected=0x754E368F - DockNode ID=0x00000008 Parent=0x00000006 SizeRef=631,385 Selected=0xCD8384B1 - DockNode ID=0x00000002 Parent=0x00000003 SizeRef=303,1016 Split=Y Selected=0x4EFD0020 - DockNode ID=0x00000009 Parent=0x00000002 SizeRef=634,349 Selected=0x4EFD0020 - DockNode ID=0x0000000A Parent=0x00000002 SizeRef=634,329 Selected=0xC1986EE2 - DockNode ID=0x00000004 Parent=0xFC02A410 SizeRef=1902,334 Selected=0x4F89F0DC - -)"; - -void settings_save(Settings* self); -void settings_init(Settings* self); -std::string settings_path_get(void); \ No newline at end of file + using WindowMember = bool Settings::*; + static constexpr WindowMember WINDOW_MEMBERS[] = { +#define X(symbol, name, string, type, ...) &Settings::name, + SETTINGS_WINDOWS +#undef X + }; +} diff --git a/src/shader.cpp b/src/shader.cpp index 2eac5ec..b205363 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -1,49 +1,74 @@ #include "shader.h" -static bool _shader_compile(GLuint* self, const std::string& text) { - int isCompile; - const GLchar* source = text.c_str(); +#include "log.h" - glShaderSource(*self, 1, &source, nullptr); - glCompileShader(*self); - glGetShaderiv(*self, GL_COMPILE_STATUS, &isCompile); +using namespace anm2ed::log; - if (!isCompile) { - std::string compileLog(SHADER_INFO_LOG_MAX, '\0'); - glGetShaderInfoLog(*self, SHADER_INFO_LOG_MAX, nullptr, compileLog.data()); - log_error(std::format(SHADER_INIT_ERROR, *self, compileLog.c_str())); - return false; +namespace anm2ed::shader +{ + Shader::Shader() = default; + + Shader::Shader(const char* vertex, const char* fragment) + { + id = glCreateProgram(); + + auto compile = [&](const GLuint& id, const char* text) + { + int isCompile{}; + glShaderSource(id, 1, &text, nullptr); + glCompileShader(id); + glGetShaderiv(id, GL_COMPILE_STATUS, &isCompile); + + if (!isCompile) + { + std::string compileLog(255, '\0'); + glGetShaderInfoLog(id, 255, nullptr, compileLog.data()); + logger.error(std::format("Unable to compile shader {}: {}", id, compileLog.c_str())); + return false; + } + return true; + }; + + auto vertexHandle = glCreateShader(GL_VERTEX_SHADER); + auto fragmentHandle = glCreateShader(GL_FRAGMENT_SHADER); + + if (!(compile(vertexHandle, vertex) && compile(fragmentHandle, fragment))) return; + + glAttachShader(id, vertexHandle); + glAttachShader(id, fragmentHandle); + + glLinkProgram(id); + + auto isLinked = GL_FALSE; + glGetProgramiv(id, GL_LINK_STATUS, &isLinked); + if (!isLinked) + { + glDeleteProgram(id); + id = 0; + } + + glDeleteShader(vertexHandle); + glDeleteShader(fragmentHandle); } - return true; + Shader& Shader::operator=(Shader&& other) noexcept + { + if (this != &other) + { + if (is_valid()) glDeleteProgram(id); + id = other.id; + other.id = 0; + } + return *this; + } + + Shader::~Shader() + { + if (is_valid()) glDeleteProgram(id); + } + + bool Shader::is_valid() const + { + return id != 0; + } } - -bool shader_init(GLuint* self, const std::string& vertex, const std::string& fragment) { - GLuint vertexHandle; - GLuint fragmentHandle; - - vertexHandle = glCreateShader(GL_VERTEX_SHADER); - fragmentHandle = glCreateShader(GL_FRAGMENT_SHADER); - - if (!_shader_compile(&vertexHandle, vertex) || !_shader_compile(&fragmentHandle, fragment)) - return false; - - *self = glCreateProgram(); - - glAttachShader(*self, vertexHandle); - glAttachShader(*self, fragmentHandle); - - glLinkProgram(*self); - - glDeleteShader(vertexHandle); - glDeleteShader(fragmentHandle); - - return true; -} - -void shader_free(GLuint* self) { - if (*self == GL_ID_NONE) - return; - - glDeleteProgram(*self); -} \ No newline at end of file diff --git a/src/shader.h b/src/shader.h index 5b34f38..a0ff1d5 100644 --- a/src/shader.h +++ b/src/shader.h @@ -1,9 +1,156 @@ #pragma once -#include "log.h" +#include -#define SHADER_INFO_LOG_MAX 0xFF -#define SHADER_INIT_ERROR "Failed to initialize shader {}:\n{}" +namespace anm2ed::shader +{ + struct Info + { + const char* vertex; + const char* fragment; + }; -bool shader_init(GLuint* self, const std::string& vertex, const std::string& fragment); -void shader_free(GLuint* self); \ No newline at end of file + constexpr auto VERTEX = R"( + #version 330 core + layout (location = 0) in vec2 i_position; + layout (location = 1) in vec2 i_uv; + out vec2 i_uv_out; + uniform mat4 u_transform; + void main() + { + i_uv_out = i_uv; + gl_Position = u_transform * vec4(i_position, 0.0, 1.0); + } + )"; + + constexpr auto AXIS_VERTEX = R"( + #version 330 core + layout (location = 0) in vec2 i_position; // full screen line segment: -1..1 + uniform vec2 u_origin_ndc; // world origin in NDC + uniform int u_axis; // 0 = X axis, 1 = Y axis + + void main() + { + vec2 pos = (u_axis == 0) + ? vec2(i_position.x, u_origin_ndc.y) // horizontal line across screen + : vec2(u_origin_ndc.x, i_position.x); // vertical line across screen; + + gl_Position = vec4(pos, 0.0, 1.0); + } + )"; + + constexpr auto GRID_VERTEX = R"( +#version 330 core +layout (location = 0) in vec2 i_position; +layout (location = 1) in vec2 i_uv; + +out vec2 i_uv_out; + +void main() { + i_uv_out = i_position; + gl_Position = vec4(i_position, 0.0, 1.0); +} + )"; + + constexpr auto FRAGMENT = R"( + #version 330 core + out vec4 o_fragColor; + uniform vec4 u_color; + void main() + { + o_fragColor = u_color; + } + )"; + + constexpr auto TEXTURE_FRAGMENT = R"( + #version 330 core + in vec2 i_uv_out; + uniform sampler2D u_texture; + uniform vec4 u_tint; + uniform vec3 u_color_offset; + out vec4 o_fragColor; + void main() + { + vec4 texColor = texture(u_texture, i_uv_out); + texColor *= u_tint; + texColor.rgb += u_color_offset; + o_fragColor = texColor; + } + )"; + + constexpr auto GRID_FRAGMENT = R"( + #version 330 core + in vec2 i_uv_out; + + uniform vec2 u_view_size; + uniform vec2 u_pan; + uniform float u_zoom; + uniform vec2 u_size; + uniform vec2 u_offset; + uniform vec4 u_color; + + out vec4 o_fragColor; + + void main() + { + vec2 viewSize = max(u_view_size, vec2(1.0)); + float zoom = max(u_zoom, 1e-6); + vec2 pan = u_pan; + + vec2 world = (i_uv_out - (2.0 * pan / viewSize)) * (viewSize / (2.0 * zoom)); + + vec2 cell = max(u_size, vec2(1.0)); + vec2 grid = (world - u_offset) / cell; + + vec2 d = abs(fract(grid) - 0.5); + float distance = min(d.x, d.y); + + float fw = min(fwidth(grid.x), fwidth(grid.y)); + float alpha = 1.0 - smoothstep(0.0, fw, distance); + + if (alpha <= 0.0) + discard; + + o_fragColor = vec4(u_color.rgb, u_color.a * alpha); + } + )"; + + constexpr auto UNIFORM_AXIS = "u_axis"; + constexpr auto UNIFORM_COLOR = "u_color"; + constexpr auto UNIFORM_TRANSFORM = "u_transform"; + constexpr auto UNIFORM_TINT = "u_tint"; + constexpr auto UNIFORM_COLOR_OFFSET = "u_color_offset"; + constexpr auto UNIFORM_OFFSET = "u_offset"; + constexpr auto UNIFORM_ORIGIN_NDC = "u_origin_ndc"; + constexpr auto UNIFORM_SIZE = "u_size"; + constexpr auto UNIFORM_MODEL = "u_model"; + constexpr auto UNIFORM_RECT_SIZE = "u_rect_size"; + constexpr auto UNIFORM_TEXTURE = "u_texture"; + constexpr auto UNIFORM_VIEW_SIZE = "u_view_size"; + constexpr auto UNIFORM_PAN = "u_pan"; + constexpr auto UNIFORM_ZOOM = "u_zoom"; + + enum Type + { + LINE, + TEXTURE, + AXIS, + GRID, + COUNT + }; + + const Info SHADERS[COUNT] = { + {VERTEX, FRAGMENT}, {VERTEX, TEXTURE_FRAGMENT}, {AXIS_VERTEX, FRAGMENT}, {GRID_VERTEX, GRID_FRAGMENT}}; + + class Shader + { + public: + GLuint id{}; + + Shader(); + Shader(const char* vertex, const char* fragment); + Shader& operator=(Shader&& other) noexcept; + ~Shader(); + bool is_valid() const; + }; +} diff --git a/src/snapshots.cpp b/src/snapshots.cpp deleted file mode 100644 index a928af6..0000000 --- a/src/snapshots.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "snapshots.h" - -static void _snapshot_stack_push(SnapshotStack* stack, Snapshot* snapshot) { - if (stack->top >= SNAPSHOT_STACK_MAX) { - for (int i = 0; i < SNAPSHOT_STACK_MAX - 1; i++) - stack->snapshots[i] = stack->snapshots[i + 1]; - stack->top = SNAPSHOT_STACK_MAX - 1; - } - stack->snapshots[stack->top++] = *snapshot; -} - -static Snapshot* _snapshot_stack_pop(SnapshotStack* stack) { - if (stack->top == 0) - return nullptr; - return &stack->snapshots[--stack->top]; -} - -static void _snapshot_set(Snapshots* self, Snapshot* snapshot) { - if (!snapshot) - return; - - *self->anm2 = snapshot->anm2; - *self->reference = snapshot->reference; - self->preview->time = snapshot->time; - self->action = snapshot->action; - - anm2_spritesheet_texture_pixels_upload(self->anm2); -} - -Snapshot snapshot_get(Snapshots* self) { - Snapshot snapshot = {*self->anm2, *self->reference, self->preview->time, self->action}; - anm2_spritesheet_texture_pixels_download(&snapshot.anm2); - return snapshot; -} - -void snapshots_init(Snapshots* self, Anm2* anm2, Anm2Reference* reference, Preview* preview) { - self->anm2 = anm2; - self->reference = reference; - self->preview = preview; -} - -void snapshots_reset(Snapshots* self) { - self->undoStack = SnapshotStack{}; - self->redoStack = SnapshotStack{}; - self->action.clear(); -} - -void snapshots_undo_push(Snapshots* self, Snapshot* snapshot) { - self->redoStack.top = 0; - _snapshot_stack_push(&self->undoStack, snapshot); -} - -void snapshots_undo(Snapshots* self) { - if (Snapshot* snapshot = _snapshot_stack_pop(&self->undoStack)) { - Snapshot current = snapshot_get(self); - _snapshot_stack_push(&self->redoStack, ¤t); - _snapshot_set(self, snapshot); - } -} - -void snapshots_redo(Snapshots* self) { - if (Snapshot* snapshot = _snapshot_stack_pop(&self->redoStack)) { - Snapshot current = snapshot_get(self); - _snapshot_stack_push(&self->undoStack, ¤t); - _snapshot_set(self, snapshot); - } -} \ No newline at end of file diff --git a/src/snapshots.h b/src/snapshots.h deleted file mode 100644 index cc2e56b..0000000 --- a/src/snapshots.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "anm2.h" -#include "preview.h" - -#define SNAPSHOT_STACK_MAX 100 -#define SNAPSHOT_ACTION "Action" - -struct Snapshot { - Anm2 anm2; - Anm2Reference reference; - float time = 0.0f; - std::string action = SNAPSHOT_ACTION; -}; - -struct SnapshotStack { - Snapshot snapshots[SNAPSHOT_STACK_MAX]; - int top = 0; - - bool empty() const { return top == 0; } -}; - -struct Snapshots { - Anm2* anm2 = nullptr; - Preview* preview = nullptr; - Anm2Reference* reference = nullptr; - std::string action = SNAPSHOT_ACTION; - SnapshotStack undoStack; - SnapshotStack redoStack; -}; - -void snapshots_undo_push(Snapshots* self, Snapshot* snapshot); -void snapshots_init(Snapshots* self, Anm2* anm2, Anm2Reference* reference, Preview* preview); -void snapshots_undo(Snapshots* self); -void snapshots_redo(Snapshots* self); -void snapshots_reset(Snapshots* self); -Snapshot snapshot_get(Snapshots* self); \ No newline at end of file diff --git a/src/spritesheet_editor.cpp b/src/spritesheet_editor.cpp new file mode 100644 index 0000000..d153c43 --- /dev/null +++ b/src/spritesheet_editor.cpp @@ -0,0 +1,128 @@ +#include "spritesheet_editor.h" + +#include "imgui.h" +#include "math.h" +#include "tool.h" +#include "types.h" + +using namespace anm2ed::document_manager; +using namespace anm2ed::settings; +using namespace anm2ed::canvas; +using namespace anm2ed::resources; +using namespace anm2ed::types; +using namespace glm; + +namespace anm2ed::spritesheet_editor +{ + SpritesheetEditor::SpritesheetEditor() : Canvas(vec2()) + { + } + + void SpritesheetEditor::update(DocumentManager& manager, Settings& settings, Resources& resources) + { + auto& document = *manager.get(); + auto& pan = document.editorPan; + auto& zoom = document.editorZoom; + auto& backgroundColor = settings.editorBackgroundColor; + auto& gridColor = settings.editorGridColor; + auto& gridSize = settings.editorGridSize; + auto& gridOffset = settings.editorGridOffset; + auto& isGrid = settings.editorIsGrid; + auto& zoomStep = settings.viewZoomStep; + auto& isBorder = settings.editorIsBorder; + auto spritesheet = document.spritesheet_get(); + auto& tool = settings.tool; + auto& shaderGrid = resources.shaders[shader::GRID]; + auto& shaderTexture = resources.shaders[shader::TEXTURE]; + auto& lineShader = resources.shaders[shader::LINE]; + + if (ImGui::Begin("Spritesheet Editor", &settings.windowIsSpritesheetEditor)) + { + auto childSize = ImVec2(imgui::row_widget_width_get(3), + (ImGui::GetTextLineHeightWithSpacing() * 4) + (ImGui::GetStyle().WindowPadding.y * 2)); + + if (ImGui::BeginChild("##Grid Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + ImGui::Checkbox("Grid", &isGrid); + ImGui::SameLine(); + ImGui::ColorEdit4("Color", value_ptr(gridColor), ImGuiColorEditFlags_NoInputs); + ImGui::InputInt2("Size", value_ptr(gridSize)); + ImGui::InputInt2("Offset", value_ptr(gridOffset)); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##View Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + ImGui::InputFloat("Zoom", &zoom, zoomStep, zoomStep, "%.0f%%"); + + auto widgetSize = ImVec2(imgui::row_widget_width_get(2), 0); + + if (ImGui::Button("Center View", widgetSize)) pan = vec2(); + ImGui::SameLine(); + ImGui::Button("Fit", widgetSize); + + ImGui::TextUnformatted(std::format(POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y).c_str()); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##Background Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + ImGui::ColorEdit4("Background", value_ptr(backgroundColor), ImGuiColorEditFlags_NoInputs); + + ImGui::Checkbox("Border", &isBorder); + } + ImGui::EndChild(); + + auto cursorScreenPos = ImGui::GetCursorScreenPos(); + + size_set(to_vec2(ImGui::GetContentRegionAvail())); + bind(); + viewport_set(); + clear(backgroundColor); + + if (spritesheet) + { + auto& texture = spritesheet->texture; + auto transform = transform_get(zoom, pan) * math::quad_model_get(texture.size); + texture_render(shaderTexture, texture.id, transform); + if (isBorder) rect_render(lineShader, transform); + } + + if (isGrid) grid_render(shaderGrid, zoom, pan, gridSize, gridOffset, gridColor); + + unbind(); + + ImGui::Image(texture, to_imvec2(size)); + + if (ImGui::IsItemHovered()) + { + ImGui::SetKeyboardFocusHere(-1); + + mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos)); + + auto isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); + auto isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); + auto mouseDelta = ImGui::GetIO().MouseDelta; + auto mouseWheel = ImGui::GetIO().MouseWheel; + auto isZoomIn = imgui::chord_repeating(imgui::string_to_chord(settings.shortcutZoomIn)); + auto isZoomOut = imgui::chord_repeating(imgui::string_to_chord(settings.shortcutZoomOut)); + + if ((tool == tool::PAN && isMouseDown) || isMouseMiddleDown) pan += vec2(mouseDelta.x, mouseDelta.y); + + switch (tool) + { + default: + break; + } + + if (mouseWheel != 0 || isZoomIn || isZoomOut) + zoom_set(zoom, pan, mousePos, (mouseWheel > 0 || isZoomIn) ? zoomStep : -zoomStep); + } + } + ImGui::End(); + } +} diff --git a/src/spritesheet_editor.h b/src/spritesheet_editor.h new file mode 100644 index 0000000..fa1010a --- /dev/null +++ b/src/spritesheet_editor.h @@ -0,0 +1,19 @@ +#pragma once + +#include "canvas.h" +#include "document_manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::spritesheet_editor +{ + class SpritesheetEditor : public canvas::Canvas + { + glm::vec2 mousePos{}; + + public: + SpritesheetEditor(); + void update(document_manager::DocumentManager& manager, settings::Settings& settings, + resources::Resources& resources); + }; +} diff --git a/src/spritesheets.cpp b/src/spritesheets.cpp new file mode 100644 index 0000000..e5bbe52 --- /dev/null +++ b/src/spritesheets.cpp @@ -0,0 +1,250 @@ +#include "spritesheets.h" + +#include + +#include "imgui.h" +#include "toast.h" +#include "types.h" + +using namespace anm2ed::anm2; +using namespace anm2ed::settings; +using namespace anm2ed::resources; +using namespace anm2ed::dialog; +using namespace anm2ed::document_manager; +using namespace anm2ed::types; +using namespace anm2ed::toast; +using namespace glm; + +namespace anm2ed::spritesheets +{ + void Spritesheets::update(DocumentManager& manager, Settings& settings, Resources& resources, Dialog& dialog) + { + if (ImGui::Begin("Spritesheets", &settings.windowIsSpritesheets)) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& selection = document.selectedSpritesheets; + auto style = ImGui::GetStyle(); + static ImGuiSelectionExternalStorage storage{}; + storage.UserData = &selection; + storage.AdapterSetItemSelected = imgui::external_storage_set; + + auto childSize = imgui::size_with_footer_get(2); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); + + if (ImGui::BeginChild("##Spritesheets Child", childSize, ImGuiChildFlags_Borders)) + { + auto spritesheetChildSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() * 4); + + ImGuiMultiSelectIO* io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, selection.size(), + anm2.content.spritesheets.size()); + storage.ApplyRequests(io); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2()); + + for (auto& [id, spritesheet] : anm2.content.spritesheets) + { + ImGui::PushID(id); + + if (ImGui::BeginChild("##Spritesheet Child", spritesheetChildSize, ImGuiChildFlags_Borders)) + { + auto isSelected = selection.contains(id); + auto isReferenced = id == document.referenceSpritesheet; + auto cursorPos = ImGui::GetCursorPos(); + auto& texture = spritesheet.texture; + + ImGui::SetNextItemSelectionUserData(id); + ImGui::SetNextItemStorageID(id); + if (ImGui::Selectable("##Spritesheet Selectable", isSelected, 0, spritesheetChildSize)) + document.referenceSpritesheet = id; + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + if (ImGui::BeginItemTooltip()) + { + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); + + auto viewport = ImGui::GetMainViewport(); + + auto size = texture.size.x * texture.size.y > (viewport->Size.x * viewport->Size.y) * 0.5f + ? to_vec2(viewport->Size) * 0.5f + : vec2(texture.size); + + auto aspectRatio = (float)texture.size.x / texture.size.y; + + if (size.x / size.y > aspectRatio) + size.x = size.y * aspectRatio; + else + size.y = size.x / aspectRatio; + + if (ImGui::BeginChild("##Spritesheet Tooltip Image Child", to_imvec2(size), ImGuiChildFlags_Borders)) + ImGui::Image(texture.id, ImGui::GetContentRegionAvail()); + ImGui::EndChild(); + + ImGui::PopStyleVar(); + + ImGui::SameLine(); + + if (ImGui::BeginChild( + "##Spritesheet Info Tooltip Child", + ImVec2(ImGui::CalcTextSize(spritesheet.path.c_str()).x + ImGui::GetTextLineHeightWithSpacing(), + 0))) + { + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); + ImGui::TextUnformatted(spritesheet.path.c_str()); + ImGui::PopFont(); + ImGui::TextUnformatted(std::format("ID: {}", id).c_str()); + ImGui::TextUnformatted(std::format("Size: {} x {}", texture.size.x, texture.size.y).c_str()); + } + ImGui::EndChild(); + + ImGui::EndTooltip(); + } + + ImGui::PopStyleVar(2); + + auto imageSize = to_imvec2(vec2(spritesheetChildSize.y)); + auto aspectRatio = (float)texture.size.x / texture.size.y; + + if (imageSize.x / imageSize.y > aspectRatio) + imageSize.x = imageSize.y * aspectRatio; + else + imageSize.y = imageSize.x / aspectRatio; + + ImGui::SetCursorPos(cursorPos); + ImGui::Image(texture.id, imageSize); + + ImGui::SetCursorPos( + ImVec2(spritesheetChildSize.y + style.ItemSpacing.x, + spritesheetChildSize.y - spritesheetChildSize.y / 2 - ImGui::GetTextLineHeight() / 2)); + + if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); + ImGui::TextUnformatted(std::format("#{} {}", id, spritesheet.path.string()).c_str()); + if (isReferenced) ImGui::PopFont(); + } + ImGui::EndChild(); + + ImGui::PopID(); + } + + io = ImGui::EndMultiSelect(); + storage.ApplyRequests(io); + + ImGui::PopStyleVar(); + } + ImGui::EndChild(); + + ImGui::PopStyleVar(); + + auto rowOneWidgetSize = imgui::widget_size_with_row_get(4); + + imgui::shortcut(settings.shortcutAdd, true); + if (ImGui::Button("Add", rowOneWidgetSize)) dialog.spritesheet_open(); + imgui::set_item_tooltip_shortcut("Add a new spritesheet.", settings.shortcutAdd); + + if (dialog.is_selected_file(dialog::SPRITESHEET_OPEN)) + { + manager.spritesheet_add(dialog.path); + dialog.reset(); + } + + ImGui::SameLine(); + + ImGui::BeginDisabled(selection.empty()); + { + if (ImGui::Button("Reload", rowOneWidgetSize)) + { + for (auto& id : selection) + { + Spritesheet& spritesheet = anm2.content.spritesheets[id]; + spritesheet.reload(document.directory_get()); + toasts.add(std::format("Reloaded spritesheet #{}: {}", id, spritesheet.path.string())); + } + } + ImGui::SetItemTooltip("Reloads the selected spritesheets."); + } + ImGui::EndDisabled(); + + ImGui::SameLine(); + + ImGui::BeginDisabled(selection.size() != 1); + { + if (ImGui::Button("Replace", rowOneWidgetSize)) dialog.spritesheet_replace(); + ImGui::SetItemTooltip("Replace the selected spritesheet with a new one."); + } + ImGui::EndDisabled(); + + if (dialog.is_selected_file(dialog::SPRITESHEET_REPLACE)) + { + auto& id = *selection.begin(); + Spritesheet& spritesheet = anm2.content.spritesheets[id]; + spritesheet = Spritesheet(document.directory_get(), dialog.path); + toasts.add(std::format("Replaced spritesheet #{}: {}", id, spritesheet.path.string())); + dialog.reset(); + } + + ImGui::SameLine(); + + auto unused = anm2.spritesheets_unused(); + + ImGui::BeginDisabled(unused.empty()); + { + imgui::shortcut(settings.shortcutRemove, true); + if (ImGui::Button("Remove Unused", rowOneWidgetSize)) + { + for (auto& id : unused) + { + Spritesheet& spritesheet = anm2.content.spritesheets[id]; + toasts.add(std::format("Removed spritesheet #{}: {}", id, spritesheet.path.string())); + anm2.spritesheet_remove(id); + } + } + imgui::set_item_tooltip_shortcut("Remove all unused spritesheets (i.e., not used in any layer.).", + settings.shortcutRemove); + } + ImGui::EndDisabled(); + + auto rowTwoWidgetSize = imgui::widget_size_with_row_get(3); + + imgui::shortcut(settings.shortcutSelectAll, true); + ImGui::BeginDisabled(selection.size() == anm2.content.spritesheets.size()); + { + if (ImGui::Button("Select All", rowTwoWidgetSize)) + for (auto& id : anm2.content.spritesheets | std::views::keys) + selection.insert(id); + } + ImGui::EndDisabled(); + imgui::set_item_tooltip_shortcut("Select all spritesheets.", settings.shortcutSelectAll); + + ImGui::SameLine(); + + imgui::shortcut(settings.shortcutSelectNone, true); + ImGui::BeginDisabled(selection.empty()); + { + if (ImGui::Button("Select None", rowTwoWidgetSize)) selection.clear(); + } + ImGui::EndDisabled(); + imgui::set_item_tooltip_shortcut("Unselect all spritesheets.", settings.shortcutSelectNone); + + ImGui::SameLine(); + + ImGui::BeginDisabled(selection.empty()); + { + if (ImGui::Button("Save", rowTwoWidgetSize)) + { + for (auto& id : selection) + { + if (Spritesheet& spritesheet = anm2.content.spritesheets[id]; spritesheet.save(document.directory_get())) + toasts.add(std::format("Saved spritesheet #{}: {}", id, spritesheet.path.string())); + else + toasts.add(std::format("Unable to save spritesheet #{}: {}", id, spritesheet.path.string())); + } + } + } + ImGui::EndDisabled(); + ImGui::SetItemTooltip("Save the selected spritesheets."); + } + ImGui::End(); + } +} diff --git a/src/spritesheets.h b/src/spritesheets.h new file mode 100644 index 0000000..dae06b8 --- /dev/null +++ b/src/spritesheets.h @@ -0,0 +1,16 @@ +#pragma once + +#include "dialog.h" +#include "document_manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::spritesheets +{ + class Spritesheets + { + public: + void update(document_manager::DocumentManager& manager, settings::Settings& settings, + resources::Resources& resources, dialog::Dialog& dialog); + }; +} diff --git a/src/state.cpp b/src/state.cpp index 18ad7df..b698828 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -1,228 +1,101 @@ #include "state.h" -static void _tick(State* self) +#include +#include + +#include "filesystem.h" +#include "toast.h" + +using namespace anm2ed::settings; +using namespace anm2ed::dialog; +using namespace anm2ed::toast; +using namespace anm2ed::types; + +namespace anm2ed::state { - preview_tick(&self->preview); -} + constexpr auto TICK_RATE = 30; + constexpr auto TICK_INTERVAL = (1000 / TICK_RATE); + constexpr auto UPDATE_RATE = 120; + constexpr auto UPDATE_INTERVAL = (1000 / UPDATE_RATE); -static void _update(State* self) -{ - SDL_GetWindowSize(self->window, &self->settings.windowSize.x, &self->settings.windowSize.y); - - imgui_update(&self->imgui); + State::State(SDL_Window*& window, std::vector& arguments) + { + dialog = Dialog(window); - if (self->imgui.isQuit) - self->isRunning = false; -} + for (auto argument : arguments) + manager.open(argument); + } -static void _draw(State* self) -{ - imgui_draw(); + void State::tick(Settings& settings) + { + if (auto document = manager.get()) + if (auto animation = document->animation_get()) + if (playback.isPlaying) + playback.tick(document->anm2.info.fps, animation->frameNum, animation->isLoop || settings.playbackIsLoop); + } - SDL_GL_SwapWindow(self->window); -} + void State::update(SDL_Window*& window, Settings& settings) + { + SDL_Event event{}; -bool sdl_init(State* self, bool isTestMode = false) -{ - if (!SDL_Init(SDL_INIT_VIDEO)) - { - log_error(std::format(STATE_SDL_INIT_ERROR, SDL_GetError())); - quit(self); - return false; - } - - if (!isTestMode) log_info(STATE_SDL_INIT_INFO); - - // Todo, when sdl3 mixer is released officially - /* - if ((Mix_Init(STATE_MIX_FLAGS) & mixFlags) != mixFlags) - log_warning(std::format(STATE_MIX_INIT_WARNING, Mix_GetError())); - - if - ( - Mix_OpenAudioDevice - ( - STATE_MIX_SAMPLE_RATE, - STATE_MIX_FORMAT, - STATE_MIX_CHANNELS, - STATE_CHUNK_SIZE, - STATE_MIX_DEVICE, - STATE_MIX_ALLOWED_CHANGES - ) - < 0 - ) - { - log_warning(std::format(STATE_MIX_INIT_WARNING, Mix_GetError())); - Mix_Quit(); + while (SDL_PollEvent(&event)) + { + ImGui_ImplSDL3_ProcessEvent(&event); + switch (event.type) + { + case SDL_EVENT_DROP_FILE: + if (auto droppedFile = event.drop.data; filesystem::path_is_extension(droppedFile, "anm2")) + manager.open(std::string(droppedFile)); + break; + case SDL_EVENT_QUIT: + isQuit = true; + break; + default: + break; + } } - else - log_info(STATE_MIX_INIT_INFO); - */ + ImGui_ImplSDL3_NewFrame(); + ImGui_ImplOpenGL3_NewFrame(); + ImGui::NewFrame(); - if (isTestMode) - { - self->window = SDL_CreateWindow - ( - WINDOW_TITLE, - WINDOW_TEST_MODE_SIZE.x, WINDOW_TEST_MODE_SIZE.y, - WINDOW_TEST_MODE_FLAGS - ); - } - else - { - ivec2 windowSize = self->settings.windowSize; + taskbar.update(settings, dialog, manager, isQuit); + documents.update(taskbar, manager, resources); + dockspace.update(taskbar, documents, manager, settings, resources, dialog, playback); + toasts.update(); - // Fix for auto-fullscreen on Windows - if (SDL_DisplayID* displayIDs = SDL_GetDisplays(nullptr)) - if (displayIDs[0]) - if (const SDL_DisplayMode* displayMode = SDL_GetDesktopDisplayMode(displayIDs[0])) - if (windowSize.x == displayMode->w && windowSize.y == displayMode->h) - windowSize -= ivec2(1, 1); - - self->window = SDL_CreateWindow - ( - WINDOW_TITLE, - windowSize.x, - windowSize.y, - WINDOW_FLAGS - ); - } + ImGui::GetStyle().FontScaleMain = settings.displayScale; + SDL_GetWindowSize(window, &settings.windowSize.x, &settings.windowSize.y); + } - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, STATE_GL_VERSION_MAJOR); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, STATE_GL_VERSION_MINOR); + void State::render(SDL_Window*& window, Settings& settings) + { + glViewport(0, 0, settings.windowSize.x, settings.windowSize.y); + glClear(GL_COLOR_BUFFER_BIT); + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + SDL_GL_SwapWindow(window); + SDL_GL_SetSwapInterval(settings.isVsync); + } - self->glContext = SDL_GL_CreateContext(self->window); - - if (!self->glContext) - { - log_error(std::format(STATE_GL_CONTEXT_INIT_ERROR, SDL_GetError())); - quit(self); - return false; - } + void State::loop(SDL_Window*& window, Settings& settings) + { + auto currentTick = SDL_GetTicks(); + auto currentUpdate = SDL_GetTicks(); - if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) - { - log_error(std::format(STATE_GLAD_INIT_ERROR)); - quit(self); - return false; - } + if (currentTick - previousTick >= TICK_INTERVAL) + { + tick(settings); + previousTick = currentTick; + } - if (!isTestMode) log_info(std::format(STATE_GL_CONTEXT_INIT_INFO, (const char*)glGetString(GL_VERSION))); - - window_vsync_set(self->settings.isVsync); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glLineWidth(STATE_GL_LINE_WIDTH); - glDisable(GL_MULTISAMPLE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LINE_SMOOTH); + if (currentUpdate - previousUpdate >= UPDATE_INTERVAL) + { + update(window, settings); + render(window, settings); + previousUpdate = currentUpdate; + } - return true; + SDL_Delay(1); + } } - -void init(State* self) -{ - log_info(STATE_INIT_INFO); - - settings_init(&self->settings); - - if (!sdl_init(self)) return; - - if (!self->argument.empty()) - { - anm2_deserialize(&self->anm2, self->argument); - window_title_from_path_set(self->window, self->argument); - } - else - anm2_new(&self->anm2); - - resources_init(&self->resources); - dialog_init(&self->dialog, self->window); - clipboard_init(&self->clipboard, &self->anm2); - preview_init(&self->preview, &self->anm2, &self->reference, &self->resources, &self->settings); - generate_preview_init(&self->generatePreview, &self->anm2, &self->reference, &self->resources, &self->settings); - editor_init(&self->editor, &self->anm2, &self->reference, &self->resources, &self->settings); - snapshots_init(&self->snapshots, &self->anm2, &self->reference, &self->preview); - - imgui_init - ( - &self->imgui, - &self->dialog, - &self->resources, - &self->anm2, - &self->reference, - &self->editor, - &self->preview, - &self->generatePreview, - &self->settings, - &self->snapshots, - &self->clipboard, - self->window, - &self->glContext - ); -} - -void loop(State* self) -{ - self->tick = SDL_GetTicks(); - self->update = self->tick; - - while (self->tick > self->lastTick + TICK_DELAY) - { - self->tick = SDL_GetTicks(); - - if (self->tick - self->lastTick < TICK_DELAY) - SDL_Delay(TICK_DELAY - (self->tick - self->lastTick)); - - _tick(self); - - self->lastTick = self->tick; - } - - if (self->settings.isVsync) - { - _update(self); - _draw(self); - } - else - { - while (self->update > self->lastUpdate + UPDATE_DELAY) - { - self->update = SDL_GetTicks(); - - if (self->update - self->lastUpdate < UPDATE_DELAY) - SDL_Delay(UPDATE_DELAY - (self->update - self->lastUpdate)); - - _update(self); - _draw(self); - - self->lastUpdate = self->update; - } - - SDL_Delay(STATE_DELAY_MIN); - } -} - -void quit(State* self) -{ - imgui_free(); - generate_preview_free(&self->generatePreview); - preview_free(&self->preview); - editor_free(&self->editor); - resources_free(&self->resources); - - /* - Mix_CloseAudio(); - Mix_Quit(); - */ - - SDL_GL_DestroyContext(self->glContext); - SDL_Quit(); - - settings_save(&self->settings); - log_info(STATE_QUIT_INFO); - log_free(); -} \ No newline at end of file diff --git a/src/state.h b/src/state.h index 8a084ad..bb1d099 100644 --- a/src/state.h +++ b/src/state.h @@ -1,56 +1,33 @@ #pragma once -#include "imgui.h" +#include -#define STATE_INIT_INFO "Initializing anm2ed (Version 1.1)" -#define STATE_SDL_INIT_ERROR "Failed to initialize SDL! {}" -#define STATE_SDL_INIT_INFO "Initialized SDL" -#define STATE_MIX_INIT_WARNING "Unable to initialize SDL_mixer! {}" -#define STATE_MIX_AUDIO_DEVICE_INIT_WARNING "Unable to initialize audio device! {}" -#define STATE_MIX_INIT_INFO "Initialized SDL_mixer" -#define STATE_GL_CONTEXT_INIT_ERROR "Failed to initialize OpenGL context! {}" -#define STATE_GLAD_INIT_ERROR "Failed to initialize GLAD!" -#define STATE_GL_CONTEXT_INIT_INFO "Initialized OpenGL context (OpenGL {})" -#define STATE_QUIT_INFO "Exiting..." -#define STATE_GL_LINE_WIDTH 2.0f +#include "dockspace.h" -#define STATE_DELAY_MIN 1 +namespace anm2ed::state +{ + class State + { + void tick(settings::Settings& settings); + void update(SDL_Window*& window, settings::Settings& settings); + void render(SDL_Window*& window, settings::Settings& settings); -#define STATE_MIX_FLAGS (MIX_INIT_MP3 | MIX_INIT_OGG | MIX_INIT_WAV) -#define STATE_MIX_SAMPLE_RATE 44100 -#define STATE_MIX_FORMAT MIX_DEFAULT_FORMAT -#define STATE_MIX_CHANNELS 2 -#define STATE_MIX_CHUNK_SIZE 1024 -#define STATE_MIX_DEVICE NULL -#define STATE_MIX_ALLOWED_CHANGES SDL_AUDIO_ALLOW_FORMAT_CHANGE + public: + bool isQuit{}; + dialog::Dialog dialog; + resources::Resources resources; + playback::Playback playback; + document_manager::DocumentManager manager; -#define STATE_GL_VERSION_MAJOR 3 -#define STATE_GL_VERSION_MINOR 3 + taskbar::Taskbar taskbar; + documents::Documents documents; + dockspace::Dockspace dockspace; -struct State { - SDL_Window* window; - SDL_GLContext glContext; - Imgui imgui; - Dialog dialog; - Editor editor; - Preview preview; - GeneratePreview generatePreview; - Anm2 anm2; - Anm2Reference reference; - Resources resources; - Settings settings; - Snapshots snapshots; - Clipboard clipboard; - std::string argument{}; - std::string lastAction{}; - uint64_t lastTick{}; - uint64_t tick{}; - uint64_t update{}; - uint64_t lastUpdate{}; - bool isRunning = true; + uint64_t previousTick{}; + uint64_t previousUpdate{}; + + State(SDL_Window*& window, std::vector& arguments); + + void loop(SDL_Window*& window, settings::Settings& settings); + }; }; - -bool sdl_init(State* self, bool isTestMode); -void init(State* state); -void loop(State* state); -void quit(State* state); \ No newline at end of file diff --git a/src/taskbar.cpp b/src/taskbar.cpp new file mode 100644 index 0000000..2ef70d8 --- /dev/null +++ b/src/taskbar.cpp @@ -0,0 +1,266 @@ +#include "taskbar.h" + +#include +#include + +#include "imgui.h" +#include "types.h" + +using namespace anm2ed::settings; +using namespace anm2ed::dialog; +using namespace anm2ed::document_manager; +using namespace anm2ed::imgui; +using namespace anm2ed::types; + +namespace anm2ed::taskbar +{ + void Taskbar::update(Settings& settings, Dialog& dialog, DocumentManager& manager, bool& isQuit) + { + auto document = manager.get(); + auto animation = document ? document->animation_get() : nullptr; + + if (ImGui::BeginMainMenuBar()) + { + height = ImGui::GetWindowSize().y; + + if (ImGui::BeginMenu("File")) + { + if (ImGui::MenuItem("New", settings.shortcutNew.c_str())) dialog.anm2_new(); + + if (ImGui::MenuItem("Open", settings.shortcutOpen.c_str())) dialog.anm2_open(); + + ImGui::BeginDisabled(!document); + { + if (ImGui::MenuItem("Save", settings.shortcutSave.c_str())) manager.save(); + if (ImGui::MenuItem("Save As", settings.shortcutSaveAs.c_str())) dialog.anm2_save(); + if (ImGui::MenuItem("Explore XML Location")) dialog.file_explorer_open(document->directory_get()); + } + ImGui::EndDisabled(); + + ImGui::Separator(); + if (ImGui::MenuItem("Exit", settings.shortcutExit.c_str())) isQuit = true; + ImGui::EndMenu(); + } + if (dialog.is_selected_file(dialog::ANM2_NEW)) + { + manager.new_(dialog.path); + dialog.reset(); + } + + if (dialog.is_selected_file(dialog::ANM2_OPEN)) + { + manager.open(dialog.path); + dialog.reset(); + } + + if (dialog.is_selected_file(dialog::ANM2_SAVE)) + { + manager.save(dialog.path); + dialog.reset(); + } + + if (ImGui::BeginMenu("Wizard")) + { + ImGui::BeginDisabled(!animation); + { + ImGui::MenuItem("Generate Animation From Grid"); + ImGui::MenuItem("Change All Frame Properties"); + } + ImGui::EndDisabled(); + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Playback")) + { + ImGui::MenuItem("Always Loop", nullptr, &settings.playbackIsLoop); + ImGui::SetItemTooltip("%s", "Animations will always loop during playback, even if looping isn't set."); + + ImGui::MenuItem("Clamp Playhead", nullptr, &settings.playbackIsClampPlayhead); + ImGui::SetItemTooltip("%s", "The playhead will always clamp to the animation's length."); + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Window")) + { + for (auto [i, member] : std::views::enumerate(WINDOW_MEMBERS)) + ImGui::MenuItem(WINDOW_STRINGS[i], nullptr, &(settings.*member)); + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Settings")) + { + if (ImGui::MenuItem("Configure")) isOpenConfigurePopup = true; + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Help")) + { + if (ImGui::MenuItem("About")) isOpenAboutPopup = true; + ImGui::EndMenu(); + } + + ImGui::EndMainMenuBar(); + } + + if (isOpenAboutPopup) + { + ImGui::OpenPopup("About"); + isOpenAboutPopup = false; + } + + if (isOpenConfigurePopup) + { + ImGui::OpenPopup("Configure"); + editSettings = settings; + isOpenConfigurePopup = false; + } + + auto viewport = ImGui::GetMainViewport(); + + ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_None, ImVec2(0.5f, 0.5f)); + ImGui::SetNextWindowSize(to_imvec2(to_vec2(viewport->Size) * 0.5f)); + + if (ImGui::BeginPopupModal("Configure", nullptr, ImGuiWindowFlags_NoResize)) + { + auto childSize = imgui::size_with_footer_get(2); + + if (ImGui::BeginTabBar("##Configure Tabs")) + { + if (ImGui::BeginTabItem("View")) + { + if (ImGui::BeginChild("##Tab Child", childSize, true)) + { + ImGui::InputFloat("Zoom Step", &editSettings.viewZoomStep, 10.0f, 10.0f, "%.2f"); + ImGui::SetItemTooltip("%s", "When zooming in/out with mouse or shortcut, this value will be used."); + editSettings.viewZoomStep = glm::clamp(editSettings.viewZoomStep, 1.0f, 250.0f); + } + ImGui::EndChild(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("Video")) + { + if (ImGui::BeginChild("##Tab Child", childSize, true)) + { + ImGui::InputFloat("Display Scale", &editSettings.displayScale, 0.25f, 0.25f, "%.2f"); + ImGui::SetItemTooltip("%s", "Change the scale of the display."); + editSettings.displayScale = glm::clamp(editSettings.displayScale, 0.5f, 2.0f); + + ImGui::Checkbox("Vsync", &editSettings.isVsync); + ImGui::SetItemTooltip("%s", + "Toggle vertical sync; synchronizes program update rate with monitor refresh rate."); + } + ImGui::EndChild(); + + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("Shortcuts")) + { + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); + + if (ImGui::BeginChild("##Tab Child", childSize, true)) + { + + if (ImGui::BeginTable("Shortcuts", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY)) + { + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableSetupColumn("Shortcut"); + ImGui::TableSetupColumn("Value"); + ImGui::TableHeadersRow(); + + for (int i = 0; i < SHORTCUT_COUNT; ++i) + { + bool isSelected = selectedShortcut == i; + + ShortcutMember member = SHORTCUT_MEMBERS[i]; + std::string* settingString = &(editSettings.*member); + std::string chordString = isSelected ? "" : *settingString; + + ImGui::PushID(i); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::TextUnformatted(SHORTCUT_STRINGS[i]); + ImGui::TableSetColumnIndex(1); + + if (ImGui::Selectable(chordString.c_str(), isSelected)) selectedShortcut = i; + + ImGui::PopID(); + + if (isSelected) + { + ImGuiKeyChord chord{ImGuiKey_None}; + + if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) chord |= ImGuiMod_Ctrl; + if (ImGui::IsKeyDown(ImGuiMod_Shift)) chord |= ImGuiMod_Shift; + if (ImGui::IsKeyDown(ImGuiMod_Alt)) chord |= ImGuiMod_Alt; + if (ImGui::IsKeyDown(ImGuiMod_Super)) chord |= ImGuiMod_Super; + + for (auto& key : imgui::KEY_MAP | std::views::values) + { + if (ImGui::IsKeyPressed(key)) + { + chord |= key; + *settingString = imgui::chord_to_string(chord); + selectedShortcut = -1; + break; + } + } + } + } + ImGui::EndTable(); + } + ImGui::EndChild(); + + ImGui::PopStyleVar(); + + ImGui::EndTabItem(); + } + } + + ImGui::EndTabBar(); + } + + auto widgetSize = imgui::widget_size_with_row_get(3); + + if (ImGui::Button("Save", widgetSize)) + { + settings = editSettings; + ImGui::CloseCurrentPopup(); + } + ImGui::SetItemTooltip("Use the configured settings."); + + ImGui::SameLine(); + + if (ImGui::Button("Use Default Settings", widgetSize)) editSettings = Settings(); + ImGui::SetItemTooltip("Reset the settings to their defaults."); + + ImGui::SameLine(); + + if (ImGui::Button("Close", widgetSize)) ImGui::CloseCurrentPopup(); + ImGui::SetItemTooltip("Close without updating settings."); + + ImGui::EndPopup(); + } + + ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_None, ImVec2(0.5f, 0.5f)); + ImGui::SetNextWindowSize(to_imvec2(to_vec2(viewport->Size) * 0.5f)); + + if (ImGui::BeginPopupModal("About", nullptr, ImGuiWindowFlags_NoResize)) + { + if (ImGui::Button("Close")) ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + + if (ImGui::Shortcut(imgui::string_to_chord(settings.shortcutNew), ImGuiInputFlags_RouteGlobal)) dialog.anm2_new(); + if (ImGui::Shortcut(imgui::string_to_chord(settings.shortcutOpen), ImGuiInputFlags_RouteGlobal)) dialog.anm2_open(); + if (ImGui::Shortcut(imgui::string_to_chord(settings.shortcutSave), ImGuiInputFlags_RouteGlobal)) manager.save(); + if (ImGui::Shortcut(imgui::string_to_chord(settings.shortcutSaveAs), ImGuiInputFlags_RouteGlobal)) + dialog.anm2_save(); + if (ImGui::Shortcut(imgui::string_to_chord(settings.shortcutExit), ImGuiInputFlags_RouteGlobal)) isQuit = true; + } +} diff --git a/src/taskbar.h b/src/taskbar.h new file mode 100644 index 0000000..146c0c6 --- /dev/null +++ b/src/taskbar.h @@ -0,0 +1,22 @@ +#pragma once + +#include "dialog.h" +#include "document_manager.h" +#include "settings.h" + +namespace anm2ed::taskbar +{ + class Taskbar + { + bool isOpenConfigurePopup{}; + bool isOpenAboutPopup{}; + int selectedShortcut{-1}; + settings::Settings editSettings{}; + + public: + float height{}; + + void update(settings::Settings& settings, dialog::Dialog& dialog, document_manager::DocumentManager& manager, + bool& isQuit); + }; +}; diff --git a/src/texture.cpp b/src/texture.cpp index 7d1f1f2..a134a5c 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -1,116 +1,128 @@ -#if defined(__clang__) || defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#endif - #include "texture.h" +#include +#include +#include + +#if defined(__clang__) || defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wmissing-field-initializers" + #pragma GCC diagnostic ignored "-Wunused-function" +#endif + #define STBI_ONLY_PNG -#define STBI_NO_FAILURE_STRINGS -#define STBI_NO_HDR #define STB_IMAGE_IMPLEMENTATION #include #define STB_IMAGE_WRITE_IMPLEMENTATION #include -static void _texture_gl_set(Texture* self, const uint8_t* data) { - if (self->id == GL_ID_NONE) - glGenTextures(1, &self->id); +#if defined(__clang__) || defined(__GNUC__) + #pragma GCC diagnostic pop +#endif - glBindTexture(GL_TEXTURE_2D, self->id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self->size.x, self->size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glBindTexture(GL_TEXTURE_2D, 0); -} +using namespace glm; -std::vector texture_download(const Texture* self) { - std::vector pixels(self->size.x * self->size.y * TEXTURE_CHANNELS); - - glBindTexture(GL_TEXTURE_2D, self->id); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ROW_LENGTH, 0); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); - - return pixels; -} - -bool texture_from_path_init(Texture* self, const std::string& path) { - uint8_t* data = stbi_load(path.c_str(), &self->size.x, &self->size.y, nullptr, TEXTURE_CHANNELS); - - if (!data) { - log_error(std::format(TEXTURE_INIT_ERROR, path)); - return false; +namespace anm2ed::texture +{ + bool Texture::is_valid() + { + return id != 0; } - self->isInvalid = false; + void Texture::download(std::vector& pixels) + { + pixels.resize(size.x * size.y * CHANNELS); + glBindTexture(GL_TEXTURE_2D, id); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + glBindTexture(GL_TEXTURE_2D, 0); + } - log_info(std::format(TEXTURE_INIT_INFO, path)); + void Texture::init(const uint8_t* data, bool isDownload) + { + glGenTextures(1, &id); - _texture_gl_set(self, data); + glBindTexture(GL_TEXTURE_2D, id); - return true; -} + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + glGenerateMipmap(GL_TEXTURE_2D); -bool texture_from_rgba_init(Texture* self, ivec2 size, const uint8_t* data) { - *self = Texture{}; - self->size = size; - self->isInvalid = false; + glBindTexture(GL_TEXTURE_2D, 0); - _texture_gl_set(self, data); + if (isDownload) download(pixels); + } - return true; -} + Texture::Texture() = default; -bool texture_from_rgba_write(const std::string& path, const uint8_t* data, ivec2 size) { - bool isSuccess = stbi_write_png(path.c_str(), size.x, size.y, TEXTURE_CHANNELS, data, size.x * TEXTURE_CHANNELS); - if (!isSuccess) - log_error(std::format(TEXTURE_SAVE_ERROR, path)); - else - log_info(std::format(TEXTURE_SAVE_INFO, path)); + Texture::~Texture() + { + if (is_valid()) glDeleteTextures(1, &id); + } - return isSuccess; -} + Texture::Texture(Texture&& other) + { + *this = std::move(other); + } -bool texture_from_memory_init(Texture* self, ivec2 size, const uint8_t* data, size_t length) { - *self = Texture{}; - self->size = size; + Texture& Texture::operator=(Texture&& other) + { + if (this != &other) + { + if (is_valid()) glDeleteTextures(1, &id); + id = std::exchange(other.id, 0); + size = std::exchange(other.size, {}); + filter = other.filter; + channels = other.channels; + pixels = std::move(other.pixels); + } + return *this; + } - u8* textureData = stbi_load_from_memory(data, length, &self->size.x, &self->size.y, nullptr, TEXTURE_CHANNELS); + Texture::Texture(const char* svgData, size_t svgDataLength, ivec2 svgSize) + { + if (!svgData) return; - if (!textureData) - return false; + const std::unique_ptr document = lunasvg::Document::loadFromData(svgData, svgDataLength); + if (!document) return; - self->isInvalid = false; + const lunasvg::Bitmap bitmap = document->renderToBitmap(svgSize.x, svgSize.y, 0); + if (bitmap.width() == 0 || bitmap.height() == 0) return; - _texture_gl_set(self, textureData); + size = svgSize; + filter = GL_LINEAR; + init(bitmap.data()); + } - return true; -} + Texture::Texture(const std::string& pngPath, bool isDownload) + { + if (const uint8* data = stbi_load(pngPath.c_str(), &size.x, &size.y, nullptr, CHANNELS); data) + { + init(data, isDownload); + stbi_image_free((void*)data); + } + } -bool texture_from_gl_write(Texture* self, const std::string& path) { return texture_from_rgba_write(path, texture_download(self).data(), self->size); } + bool Texture::write_png(const std::string& path) + { + std::vector pixels; + download(pixels); + const bool isSuccess = stbi_write_png(path.c_str(), size.x, size.y, CHANNELS, pixels.data(), size.x * CHANNELS); + return isSuccess; + } -void texture_free(Texture* self) { - if (self->isInvalid) - return; + void Texture::bind(GLuint unit) + { + glActiveTexture(GL_TEXTURE0 + unit); + glBindTexture(GL_TEXTURE_2D, id); + } - glDeleteTextures(1, &self->id); - *self = Texture{}; -} - -bool texture_pixel_set(Texture* self, ivec2 position, vec4 color) { - if (position.x < 0 || position.y < 0 || position.x >= self->size.x || position.y >= self->size.y) - return false; - - uint8_t rgba8[4] = {FLOAT_TO_UINT8(color.r), FLOAT_TO_UINT8(color.g), FLOAT_TO_UINT8(color.b), FLOAT_TO_UINT8(color.a)}; - - glBindTexture(GL_TEXTURE_2D, self->id); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexSubImage2D(GL_TEXTURE_2D, 0, position.x, position.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba8); - - return true; -} + void Texture::unbind(GLuint unit) + { + glActiveTexture(GL_TEXTURE0 + unit); + glBindTexture(GL_TEXTURE_2D, 0); + } +} \ No newline at end of file diff --git a/src/texture.h b/src/texture.h index 9da64cc..834bc09 100644 --- a/src/texture.h +++ b/src/texture.h @@ -1,26 +1,36 @@ #pragma once -#include "log.h" +#include +#include -#define TEXTURE_CHANNELS 4 -#define TEXTURE_INIT_INFO "Initialized texture from file: {}" -#define TEXTURE_INIT_ERROR "Failed to initialize texture from file: {}" -#define TEXTURE_SAVE_INFO "Saved texture to: {}" -#define TEXTURE_SAVE_ERROR "Failed to save texture to: {}" +#include +#include -struct Texture { - GLuint id = GL_ID_NONE; - ivec2 size{}; - bool isInvalid = true; +namespace anm2ed::texture +{ + constexpr auto CHANNELS = 4; - auto operator<=>(const Texture&) const = default; -}; + class Texture + { + public: + GLuint id{}; + glm::ivec2 size{}; + GLint filter = GL_NEAREST; + int channels{}; + std::vector pixels{}; -bool texture_from_gl_write(Texture* self, const std::string& path); -bool texture_from_path_init(Texture* self, const std::string& path); -bool texture_from_rgba_init(Texture* self, ivec2 size, const uint8_t* data); -bool texture_from_rgba_write(const std::string& path, const uint8_t* data, ivec2 size); -bool texture_pixel_set(Texture* self, ivec2 position, vec4 color); -void texture_free(Texture* self); -bool texture_from_memory_init(Texture* self, ivec2 size, const uint8_t* data, size_t length); -std::vector texture_download(const Texture* self); \ No newline at end of file + bool is_valid(); + void download(std::vector& pixels); + void init(const uint8_t* data, bool isDownload = false); + Texture(); + + ~Texture(); + Texture(Texture&& other); + Texture& operator=(Texture&& other); + Texture(const char* svgData, size_t svgDataLength, glm::ivec2 svgSize); + Texture(const std::string& pngPath, bool isDownload = false); + bool write_png(const std::string& path); + void bind(GLuint unit = 0); + void unbind(GLuint unit = 0); + }; +} \ No newline at end of file diff --git a/src/timeline.cpp b/src/timeline.cpp new file mode 100644 index 0000000..0b965a1 --- /dev/null +++ b/src/timeline.cpp @@ -0,0 +1,701 @@ +#include "timeline.h" + +#include + +#include + +#include "imgui.h" + +using namespace anm2ed::types; +using namespace anm2ed::document_manager; +using namespace anm2ed::resources; +using namespace anm2ed::settings; +using namespace anm2ed::playback; +using namespace glm; + +namespace anm2ed::timeline +{ + constexpr auto ROOT_COLOR = ImVec4(0.140f, 0.310f, 0.560f, 1.000f); + constexpr auto ROOT_COLOR_ACTIVE = ImVec4(0.240f, 0.520f, 0.880f, 1.000f); + constexpr auto ROOT_COLOR_HOVERED = ImVec4(0.320f, 0.640f, 1.000f, 1.000f); + + constexpr auto LAYER_COLOR = ImVec4(0.640f, 0.320f, 0.110f, 1.000f); + constexpr auto LAYER_COLOR_ACTIVE = ImVec4(0.840f, 0.450f, 0.170f, 1.000f); + constexpr auto LAYER_COLOR_HOVERED = ImVec4(0.960f, 0.560f, 0.240f, 1.000f); + + constexpr auto NULL_COLOR = ImVec4(0.140f, 0.430f, 0.200f, 1.000f); + constexpr auto NULL_COLOR_ACTIVE = ImVec4(0.250f, 0.650f, 0.350f, 1.000f); + constexpr auto NULL_COLOR_HOVERED = ImVec4(0.350f, 0.800f, 0.480f, 1.000f); + + constexpr auto TRIGGER_COLOR = ImVec4(0.620f, 0.150f, 0.260f, 1.000f); + constexpr auto TRIGGER_COLOR_ACTIVE = ImVec4(0.820f, 0.250f, 0.380f, 1.000f); + constexpr auto TRIGGER_COLOR_HOVERED = ImVec4(0.950f, 0.330f, 0.490f, 1.000f); + + constexpr auto COLOR_HIDDEN_MULTIPLIER = vec4(0.5f, 0.5f, 0.5f, 1.000f); + + constexpr auto FRAME_TIMELINE_COLOR = ImVec4(0.106f, 0.184f, 0.278f, 1.000f); + + constexpr auto FRAME_BORDER_COLOR = ImVec4(1.0f, 1.0f, 1.0f, 0.15f); + constexpr auto FRAME_MULTIPLE_OVERLAY_COLOR = ImVec4(1.0f, 1.0f, 1.0f, 0.05f); + constexpr auto PLAYHEAD_LINE_THICKNESS = 4.0f; + + constexpr auto TEXT_MULTIPLE_COLOR = to_imvec4(color::WHITE); + constexpr auto PLAYHEAD_LINE_COLOR = to_imvec4(color::WHITE); + + constexpr auto FRAME_MULTIPLE = 5; + + constexpr auto HELP_FORMAT = R"(- Press {} to decrement time. +- Press {} to increment time. +- Press {} to extend the selected frame, by one frame. +- Press {} to shorten the selected frame, by one frame. +- Hold Alt while clicking a non-trigger frame to toggle interpolation.)"; + + void Timeline::item_child(anm2::Anm2& anm2, anm2::Reference& reference, anm2::Animation* animation, + Settings& settings, Resources& resources, anm2::Type type, int id, int& index) + { + auto item = animation ? animation->item_get(type, id) : nullptr; + auto isVisible = item ? item->isVisible : false; + auto isActive = reference.itemType == type && reference.itemID == id; + std::string label = "##None"; + icon::Type icon{}; + ImVec4 color{}; + + switch (type) + { + case anm2::ROOT: + label = "Root"; + icon = icon::ROOT; + color = isActive ? ROOT_COLOR_ACTIVE : ROOT_COLOR; + break; + case anm2::LAYER: + label = std::format("#{} {}", id, anm2.content.layers[id].name); + icon = icon::LAYER; + color = isActive ? LAYER_COLOR_ACTIVE : LAYER_COLOR; + break; + case anm2::NULL_: + label = std::format("#{} {}", id, anm2.content.nulls[id].name); + icon = icon::NULL_; + color = isActive ? NULL_COLOR_ACTIVE : NULL_COLOR; + break; + case anm2::TRIGGER: + label = "Triggers"; + icon = icon::TRIGGERS; + color = isActive ? TRIGGER_COLOR_ACTIVE : TRIGGER_COLOR; + break; + default: + break; + } + + color = !isVisible ? to_imvec4(to_vec4(color) * COLOR_HIDDEN_MULTIPLIER) : color; + ImGui::PushStyleColor(ImGuiCol_ChildBg, color); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + + auto itemSize = ImVec2(ImGui::GetContentRegionAvail().x, + ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2)); + + if (ImGui::BeginChild(label.c_str(), itemSize, ImGuiChildFlags_Borders)) + { + if (type != anm2::NONE) + { + anm2::Reference itemReference = {reference.animationIndex, type, id}; + + if (ImGui::IsWindowHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) reference = itemReference; + + ImGui::Image(resources.icons[icon].id, imgui::icon_size_get()); + ImGui::SameLine(); + ImGui::TextUnformatted(label.c_str()); + + anm2::Item* item = animation->item_get(type, id); + bool& isVisible = item->isVisible; + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4()); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); + + ImGui::SetCursorPos(ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + int visibleIcon = isVisible ? icon::VISIBLE : icon::INVISIBLE; + + if (ImGui::ImageButton("##Visible Toggle", resources.icons[visibleIcon].id, imgui::icon_size_get())) + isVisible = !isVisible; + ImGui::SetItemTooltip(isVisible ? "The item is shown. Press to hide." : "The item is hidden. Press to show."); + + if (type == anm2::NULL_) + { + auto& null = anm2.content.nulls.at(id); + auto& isShowRect = null.isShowRect; + + auto rectIcon = isShowRect ? icon::SHOW_RECT : icon::HIDE_RECT; + ImGui::SetCursorPos( + ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + if (ImGui::ImageButton("##Rect Toggle", resources.icons[rectIcon].id, imgui::icon_size_get())) + isShowRect = !isShowRect; + ImGui::SetItemTooltip(isShowRect ? "The null's rect is shown. Press to hide." + : "The null's rect is hidden. Press to show."); + } + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(3); + } + else + { + auto cursorPos = ImGui::GetCursorPos(); + auto& isShowUnused = settings.timelineIsShowUnused; + + ImGui::SetCursorPos(ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4()); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); + + auto unusedIcon = isShowUnused ? icon::SHOW_UNUSED : icon::HIDE_UNUSED; + if (ImGui::ImageButton("##Unused Toggle", resources.icons[unusedIcon].id, imgui::icon_size_get())) + isShowUnused = !isShowUnused; + ImGui::SetItemTooltip(isShowUnused ? "Unused layers/nulls are shown. Press to hide." + : "Unused layers/nulls are hidden. Press to show."); + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(3); + + ImGui::SetCursorPos(cursorPos); + + ImGui::Text("(?)"); + ImGui::SetItemTooltip("%s", std::format(HELP_FORMAT, settings.shortcutNextFrame, settings.shortcutPreviousFrame, + settings.shortcutShortenFrame, settings.shortcutExtendFrame) + .c_str()); + } + } + ImGui::EndChild(); + ImGui::PopStyleColor(); + ImGui::PopStyleVar(2); + index++; + } + + void Timeline::items_child(anm2::Anm2& anm2, anm2::Reference& reference, anm2::Animation* animation, + Settings& settings, Resources& resources) + { + auto itemsChildSize = ImVec2(ImGui::GetTextLineHeightWithSpacing() * 15, ImGui::GetContentRegionAvail().y); + + if (ImGui::BeginChild("##Items Child", itemsChildSize, ImGuiChildFlags_Borders)) + { + auto itemsListChildSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - + ImGui::GetTextLineHeightWithSpacing() - + ImGui::GetStyle().ItemSpacing.y * 2); + + if (ImGui::BeginChild("##Items List Child", itemsListChildSize, ImGuiChildFlags_Borders, + ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar)) + { + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2()); + ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, 0.0f); + if (ImGui::BeginTable("##Item Table", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY)) + { + ImGui::GetCurrentWindow()->Flags |= ImGuiWindowFlags_NoScrollWithMouse; + ImGui::SetScrollY(scroll.y); + + int index{}; + + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableSetupColumn("##Items"); + + auto item_child_row = [&](anm2::Type type, int id = -1) + { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + item_child(anm2, reference, animation, settings, resources, type, id, index); + }; + + item_child_row(anm2::NONE); + + if (animation) + { + item_child_row(anm2::ROOT); + + for (auto& id : animation->layerOrder) + { + if (anm2::Item* item = animation->item_get(anm2::LAYER, id); item) + if (!settings.timelineIsShowUnused && item->frames.empty()) continue; + + item_child_row(anm2::LAYER, id); + } + + for (auto& id : animation->nullAnimations | std::views::keys) + { + if (anm2::Item* item = animation->item_get(anm2::NULL_, id); item) + if (!settings.timelineIsShowUnused && item->frames.empty()) continue; + + item_child_row(anm2::NULL_, id); + } + + item_child_row(anm2::TRIGGER); + } + + if (isHorizontalScroll && ImGui::GetCurrentWindow()->ScrollbarY) + { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Dummy(ImVec2(0, style.ScrollbarSize)); + } + + ImGui::EndTable(); + } + ImGui::PopStyleVar(2); + } + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + ImGui::BeginDisabled(!animation); + { + ImGui::Button("Add", widgetSize); + ImGui::SameLine(); + ImGui::Button("Remove", widgetSize); + } + ImGui::EndDisabled(); + } + ImGui::EndChild(); + } + + void Timeline::frame_child(Document& document, anm2::Animation* animation, Settings& settings, Resources& resources, + Playback& playback, anm2::Type type, int id, int& index, float width) + { + auto& anm2 = document.anm2; + auto& reference = document.reference; + auto item = animation ? animation->item_get(type, id) : nullptr; + auto isVisible = item ? item->isVisible : false; + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + + auto childSize = ImVec2(width, ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2)); + ImVec4 color{}; + ImVec4 colorActive{}; + ImVec4 colorHovered{}; + ImVec4 colorHidden{}; + ImVec4 colorActiveHidden{}; + ImVec4 colorHoveredHidden{}; + + ImGui::PopStyleVar(2); + + ImGui::PushID(index); + + switch (type) + { + case anm2::ROOT: + color = ROOT_COLOR; + colorActive = ROOT_COLOR_ACTIVE; + colorHovered = ROOT_COLOR_HOVERED; + break; + case anm2::LAYER: + color = LAYER_COLOR; + colorActive = LAYER_COLOR_ACTIVE; + colorHovered = LAYER_COLOR_HOVERED; + break; + case anm2::NULL_: + color = NULL_COLOR; + colorActive = NULL_COLOR_ACTIVE; + colorHovered = NULL_COLOR_HOVERED; + break; + case anm2::TRIGGER: + color = TRIGGER_COLOR; + colorActive = TRIGGER_COLOR_ACTIVE; + colorHovered = TRIGGER_COLOR_HOVERED; + break; + default: + color = ImGui::GetStyleColorVec4(ImGuiCol_Button); + colorActive = ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive); + colorHovered = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); + break; + } + + colorHidden = to_imvec4(to_vec4(color) * COLOR_HIDDEN_MULTIPLIER); + colorActiveHidden = to_imvec4(to_vec4(colorActive) * COLOR_HIDDEN_MULTIPLIER); + colorHoveredHidden = to_imvec4(to_vec4(colorHovered) * COLOR_HIDDEN_MULTIPLIER); + + ImGui::PushStyleColor(ImGuiCol_Button, isVisible ? color : colorHidden); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, isVisible ? colorActive : colorActiveHidden); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, isVisible ? colorHovered : colorHoveredHidden); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); + + if (ImGui::BeginChild("##Frames Child", childSize, ImGuiChildFlags_Borders)) + { + auto length = animation ? animation->frameNum : anm2.animations.length(); + 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 imageSize = vec2(ImGui::GetTextLineHeight()); + auto border = ImGui::GetStyle().FrameBorderSize; + auto borderLineLength = frameSize.y / 5; + auto scrollX = ImGui::GetScrollX(); + auto available = ImGui::GetContentRegionAvail(); + auto frameMin = std::max(0, (int)std::floor(scrollX / frameSize.x) - 1); + auto frameMax = std::min(anm2::FRAME_NUM_MAX, (int)std::ceil(scrollX + available.x / frameSize.x) + 1); + auto drawList = ImGui::GetWindowDrawList(); + pickerLineDrawList = drawList; + + if (type == anm2::NONE) + { + drawList->AddRectFilled(cursorScreenPos, + ImVec2(cursorScreenPos.x + framesSize.x, cursorScreenPos.y + framesSize.y), + ImGui::GetColorU32(FRAME_TIMELINE_COLOR)); + + for (int i = frameMin; i < frameMax; i++) + { + auto frameScreenPos = ImVec2(cursorScreenPos.x + frameSize.x * (float)i, cursorScreenPos.y); + + drawList->AddRect(frameScreenPos, ImVec2(frameScreenPos.x + border, frameScreenPos.y + borderLineLength), + ImGui::GetColorU32(FRAME_BORDER_COLOR)); + + drawList->AddRect(ImVec2(frameScreenPos.x, frameScreenPos.y + frameSize.y - borderLineLength), + ImVec2(frameScreenPos.x + border, frameScreenPos.y + frameSize.y), + ImGui::GetColorU32(FRAME_BORDER_COLOR)); + + if (i % FRAME_MULTIPLE == 0) + { + auto string = std::to_string(i); + auto textSize = ImGui::CalcTextSize(string.c_str()); + auto textPos = ImVec2(frameScreenPos.x + (frameSize.x - textSize.x) / 2, + frameScreenPos.y + (frameSize.y - textSize.y) / 2); + + drawList->AddRectFilled(frameScreenPos, + ImVec2(frameScreenPos.x + frameSize.x, frameScreenPos.y + frameSize.y), + ImGui::GetColorU32(FRAME_MULTIPLE_OVERLAY_COLOR)); + + drawList->AddText(textPos, ImGui::GetColorU32(TEXT_MULTIPLE_COLOR), string.c_str()); + } + } + + if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(0)) + isDragging = true; + + if (isDragging) + { + auto childPos = ImGui::GetWindowPos(); + auto mousePos = ImGui::GetIO().MousePos; + auto localMousePos = ImVec2(mousePos.x - childPos.x, mousePos.y - childPos.y); + playback.time = floorf(localMousePos.x / frameSize.x); + reference.frameTime = playback.time; + } + + playback.clamp(settings.playbackIsClampPlayhead ? length : anm2::FRAME_NUM_MAX); + + if (ImGui::IsMouseReleased(0)) isDragging = false; + + ImGui::SetCursorPos(ImVec2(cursorPos.x + frameSize.x * floorf(playback.time), cursorPos.y)); + ImGui::Image(resources.icons[icon::PLAYHEAD].id, frameSize); + } + else if (animation) + { + anm2::Reference itemReference = {reference.animationIndex, type, id}; + if (ImGui::IsWindowHovered() && ImGui::IsMouseReleased(0)) reference = itemReference; + + for (int i = frameMin; i < frameMax; i++) + { + auto frameScreenPos = ImVec2(cursorScreenPos.x + (frameSize.x * i), cursorScreenPos.y); + + if (i % FRAME_MULTIPLE == 0) + { + drawList->AddRectFilled(frameScreenPos, + ImVec2(frameScreenPos.x + frameSize.x, frameScreenPos.y + frameSize.y), + ImGui::GetColorU32(FRAME_MULTIPLE_OVERLAY_COLOR)); + } + drawList->AddRect(frameScreenPos, ImVec2(frameScreenPos.x + frameSize.x, frameScreenPos.y + frameSize.y), + ImGui::GetColorU32(FRAME_BORDER_COLOR)); + } + + auto item = animation->item_get(type, id); + + auto frameTime = 0; + anm2::Reference baseReference = {reference.animationIndex, reference.itemType, reference.itemID, + reference.frameIndex}; + + for (auto [i, frame] : std::views::enumerate(item->frames)) + { + anm2::Reference frameReference = {reference.animationIndex, type, id, (int)i}; + auto isSelected = baseReference == frameReference; + + frameTime += frame.delay; + + if (isSelected) ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive)); + + ImGui::PushID(i); + auto size = ImVec2(frameSize.x * frame.delay, frameSize.y); + + auto icon = type == anm2::TRIGGER ? icon::TRIGGER + : frame.isInterpolated ? icon::INTERPOLATED + : icon::UNINTERPOLATED; + + if (type == anm2::TRIGGER) + ImGui::SetCursorPos(ImVec2(cursorPos.x + frameSize.x * frame.atFrame, cursorPos.y)); + + if (!frame.isVisible) + { + ImGui::PushStyleColor(ImGuiCol_Button, colorHidden); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, colorActiveHidden); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colorHoveredHidden); + } + + if (ImGui::Button("##Frame Button", size)) + { + if (type != anm2::TRIGGER && ImGui::IsKeyDown(ImGuiMod_Alt)) frame.isInterpolated = !frame.isInterpolated; + if (type == anm2::LAYER) document.referenceSpritesheet = anm2.content.layers[id].spritesheetID; + reference = frameReference; + reference.frameTime = frameTime; + } + if (type != anm2::TRIGGER) ImGui::SameLine(); + + if (!frame.isVisible) ImGui::PopStyleColor(3); + + auto imageMin = ImVec2(ImGui::GetItemRectMin().x, + ImGui::GetItemRectMax().y - (ImGui::GetItemRectSize().y / 2) - (imageSize.y / 2)); + auto imageMax = to_imvec2(to_vec2(imageMin) + imageSize); + + drawList->AddImage(resources.icons[icon].id, imageMin, imageMax); + + if (isSelected) ImGui::PopStyleColor(); + + ImGui::PopID(); + } + } + } + ImGui::EndChild(); + ImGui::PopStyleVar(); + ImGui::PopStyleColor(3); + + index++; + ImGui::PopID(); + } + + void Timeline::frames_child(Document& document, anm2::Animation* animation, Settings& settings, Resources& resources, + Playback& playback) + { + auto& anm2 = document.anm2; + + auto itemsChildWidth = ImGui::GetTextLineHeightWithSpacing() * 15; + + auto cursorPos = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(cursorPos.x + itemsChildWidth, cursorPos.y)); + + auto framesChildSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y); + + if (ImGui::BeginChild("##Frames Child", framesChildSize, ImGuiChildFlags_Borders)) + { + auto viewListChildSize = + ImVec2(ImGui::GetContentRegionAvail().x, + ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeightWithSpacing() - style.ItemSpacing.y * 2); + + auto childWidth = ImGui::GetContentRegionAvail().x > anm2.animations.length() * ImGui::GetTextLineHeight() + ? ImGui::GetContentRegionAvail().x + : anm2.animations.length() * ImGui::GetTextLineHeight(); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2()); + if (ImGui::BeginChild("##Frames List Child", viewListChildSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + auto cursorScreenPos = ImGui::GetCursorScreenPos(); + + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2()); + if (ImGui::BeginTable("##Frames List Table", 1, + ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) + { + ImGuiWindow* window = ImGui::GetCurrentWindow(); + window->Flags |= ImGuiWindowFlags_NoScrollWithMouse; + + scroll.x = ImGui::GetScrollX(); + scroll.y = ImGui::GetScrollY(); + + isHorizontalScroll = window->ScrollbarX; + + if (isWindowHovered) + { + auto& io = ImGui::GetIO(); + auto lineHeight = ImGui::GetTextLineHeightWithSpacing() * 2; + + scroll.x -= io.MouseWheelH * lineHeight; + scroll.y -= io.MouseWheel * lineHeight; + } + + ImGui::SetScrollX(scroll.x); + ImGui::SetScrollY(scroll.y); + + int index{}; + + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableSetupColumn("##Frames"); + + auto frames_child_row = [&](anm2::Type type, int id = -1) + { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + frame_child(document, animation, settings, resources, playback, type, id, index, childWidth); + }; + + frames_child_row(anm2::NONE); + + if (animation) + { + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f); + + frames_child_row(anm2::ROOT); + + for (auto& id : animation->layerOrder) + { + if (auto item = animation->item_get(anm2::LAYER, id); item) + if (!settings.timelineIsShowUnused && item->frames.empty()) continue; + + frames_child_row(anm2::LAYER, id); + } + + for (auto& id : animation->nullAnimations | std::views::keys) + { + if (auto item = animation->item_get(anm2::NULL_, id); item) + if (!settings.timelineIsShowUnused && item->frames.empty()) continue; + frames_child_row(anm2::NULL_, id); + } + + frames_child_row(anm2::TRIGGER); + + ImGui::PopStyleVar(); + } + ImGui::EndTable(); + } + + ImDrawList* windowDrawList = ImGui::GetWindowDrawList(); + + auto frameSize = ImVec2(ImGui::GetTextLineHeight(), + ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2)); + auto linePos = ImVec2(cursorScreenPos.x + frameSize.x * floorf(playback.time) + (frameSize.x / 2) - scroll.x, + cursorScreenPos.y + frameSize.y); + auto lineSize = + ImVec2((PLAYHEAD_LINE_THICKNESS / 2.0f), + viewListChildSize.y - frameSize.y - (isHorizontalScroll ? ImGui::GetStyle().ScrollbarSize : 0.0f)); + + auto rectMin = windowDrawList->GetClipRectMin(); + auto rectMax = windowDrawList->GetClipRectMax(); + pickerLineDrawList->PushClipRect(rectMin, rectMax); + pickerLineDrawList->AddRectFilled(linePos, ImVec2(linePos.x + lineSize.x, linePos.y + lineSize.y), + ImGui::GetColorU32(PLAYHEAD_LINE_COLOR)); + pickerLineDrawList->PopClipRect(); + + ImGui::PopStyleVar(); + } + ImGui::EndChild(); + ImGui::PopStyleVar(); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + + ImGui::SetCursorPos( + ImVec2(ImGui::GetStyle().WindowPadding.x, ImGui::GetCursorPos().y + ImGui::GetStyle().ItemSpacing.y)); + + auto widgetSize = imgui::widget_size_with_row_get(9); + + ImGui::BeginDisabled(!animation); + { + auto label = playback.isPlaying ? "Pause" : "Play"; + auto tooltip = playback.isPlaying ? "Pause the animation." : "Play the animation."; + + imgui::shortcut(settings.shortcutPlayPause, true); + if (ImGui::Button(label, widgetSize)) playback.toggle(); + imgui::set_item_tooltip_shortcut(tooltip, settings.shortcutPlayPause); + + ImGui::SameLine(); + + imgui::shortcut(settings.shortcutAdd, true); + ImGui::Button("Insert Frame", widgetSize); + imgui::set_item_tooltip_shortcut("Insert a frame, based on the current selection.", settings.shortcutAdd); + + ImGui::SameLine(); + + imgui::shortcut(settings.shortcutRemove, true); + ImGui::Button("Delete Frame", widgetSize); + imgui::set_item_tooltip_shortcut("Delete the selected frames.", settings.shortcutRemove); + + ImGui::SameLine(); + + ImGui::Button("Bake", widgetSize); + ImGui::SetItemTooltip("%s", "Turn interpolated frames into uninterpolated ones."); + + ImGui::SameLine(); + + if (ImGui::Button("Fit Animation Length", widgetSize)) animation->frameNum = animation->length(); + ImGui::SetItemTooltip("%s", "The animation length will be set to the effective length of the animation."); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + ImGui::InputInt("Animation Length", animation ? &animation->frameNum : &dummy_value(), step::NORMAL, + step::FAST, !animation ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); + if (animation) animation->frameNum = clamp(animation->frameNum, anm2::FRAME_NUM_MIN, anm2::FRAME_NUM_MAX); + ImGui::SetItemTooltip("%s", "Set the animation's length."); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + ImGui::Checkbox("Loop", animation ? &animation->isLoop : &dummy_value()); + ImGui::SetItemTooltip("%s", "Toggle the animation looping."); + } + ImGui::EndDisabled(); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + ImGui::InputInt("FPS", &anm2.info.fps, 1, 5); + anm2.info.fps = clamp(anm2.info.fps, anm2::FPS_MIN, anm2::FPS_MAX); + ImGui::SetItemTooltip("%s", "Set the FPS of all animations."); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + imgui::input_text_string("Author", &anm2.info.createdBy); + ImGui::SetItemTooltip("%s", "Set the author of the document."); + + ImGui::PopStyleVar(); + } + ImGui::EndChild(); + + ImGui::SetCursorPos(cursorPos); + } + + void Timeline::update(DocumentManager& manager, Settings& settings, Resources& resources, Playback& playback) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& reference = document.reference; + auto animation = document.animation_get(); + + style = ImGui::GetStyle(); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); + if (ImGui::Begin("Timeline", &settings.windowIsTimeline)) + { + isWindowHovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); + frames_child(document, animation, settings, resources, playback); + items_child(anm2, reference, animation, settings, resources); + } + ImGui::PopStyleVar(); + ImGui::End(); + + if (imgui::shortcut(settings.shortcutPlayPause, false, true)) playback.toggle(); + + if (animation) + { + if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutPreviousFrame))) + playback.decrement(animation->frameNum); + + if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutNextFrame))) + playback.increment(animation->frameNum); + } + + if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutShortenFrame))) + if (auto frame = anm2.frame_get(reference); frame) frame->shorten(); + + if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutExtendFrame))) + if (auto frame = anm2.frame_get(reference); frame) frame->extend(); + } +} \ No newline at end of file diff --git a/src/timeline.h b/src/timeline.h new file mode 100644 index 0000000..5b32711 --- /dev/null +++ b/src/timeline.h @@ -0,0 +1,35 @@ +#pragma once + +#include "anm2.h" +#include "document.h" +#include "document_manager.h" +#include "playback.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::timeline +{ + class Timeline + { + bool isDragging{}; + bool isWindowHovered{}; + bool isHorizontalScroll{}; + glm::vec2 scroll{}; + ImDrawList* pickerLineDrawList{}; + ImGuiStyle style{}; + + void item_child(anm2::Anm2& anm2, anm2::Reference& reference, anm2::Animation* animation, + settings::Settings& settings, resources::Resources& resources, anm2::Type type, int id, int& index); + void items_child(anm2::Anm2& anm2, anm2::Reference& reference, anm2::Animation* animation, + settings::Settings& settings, resources::Resources& resources); + void frame_child(document::Document& document, anm2::Animation* animation, settings::Settings& settings, + resources::Resources& resources, playback::Playback& playback, anm2::Type type, int id, int& index, + float width); + void frames_child(document::Document& document, anm2::Animation* animation, settings::Settings& settings, + resources::Resources& resources, playback::Playback& playback); + + public: + void update(document_manager::DocumentManager& manager, settings::Settings& settings, + resources::Resources& resources, playback::Playback& playback); + }; +} \ No newline at end of file diff --git a/src/toast.cpp b/src/toast.cpp new file mode 100644 index 0000000..beb84e1 --- /dev/null +++ b/src/toast.cpp @@ -0,0 +1,80 @@ +#include "toast.h" + +#include "log.h" +#include + +#include "types.h" + +using namespace anm2ed::log; +using namespace anm2ed::types; + +namespace anm2ed::toast +{ + constexpr auto LIFETIME = 3.0f; + + Toast::Toast(const std::string& message) + { + this->message = message; + lifetime = LIFETIME; + } + + void Toasts::update() + { + ImGuiIO& io = ImGui::GetIO(); + + auto borderColor = ImGui::GetStyleColorVec4(ImGuiCol_Border); + auto textColor = ImGui::GetStyleColorVec4(ImGuiCol_Text); + + auto position = to_vec2(io.DisplaySize) - to_vec2(ImGui::GetStyle().ItemSpacing); + + for (int i = (int)toasts.size() - 1; i >= 0; --i) + { + Toast& toast = toasts[i]; + + toast.lifetime -= ImGui::GetIO().DeltaTime; + + if (toast.lifetime <= 0.0f) + { + toasts.erase(toasts.begin() + i); + i--; + continue; + } + + auto alpha = toast.lifetime / LIFETIME; + borderColor.w = alpha; + textColor.w = alpha; + + ImGui::SetNextWindowPos(to_imvec2(position), ImGuiCond_None, {1.0f, 1.0f}); + ImGui::SetNextWindowSize(ImVec2(0, ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().WindowPadding.y)); + ImGui::PushStyleColor(ImGuiCol_Text, textColor); + ImGui::PushStyleColor(ImGuiCol_Border, borderColor); + ImGui::SetNextWindowBgAlpha(alpha); + + if (ImGui::Begin(std::format("##Toast #{}", i).c_str(), nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) + { + ImGui::TextUnformatted(toast.message.c_str()); + position.y -= ImGui::GetWindowSize().y + ImGui::GetStyle().ItemSpacing.y; + } + ImGui::End(); + ImGui::PopStyleColor(2); + } + } + + void Toasts::add(const std::string& message) + { + toasts.emplace_back(Toast(message)); + logger.info(message); + } + + void Toasts::add_error(const std::string& message) + { + toasts.emplace_back(Toast(message)); + logger.error(message); + } + + Toasts toasts; +} diff --git a/src/toast.h b/src/toast.h new file mode 100644 index 0000000..306787b --- /dev/null +++ b/src/toast.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +namespace anm2ed::toast +{ + + class Toast + { + public: + std::string message{}; + float lifetime{}; + + Toast(const std::string& message); + }; + + class Toasts + { + public: + std::vector toasts{}; + + void update(); + void add(const std::string& message); + void add_error(const std::string& message); + }; + + extern Toasts toasts; +} diff --git a/src/tool.h b/src/tool.h index 132e806..8814899 100644 --- a/src/tool.h +++ b/src/tool.h @@ -1,37 +1,73 @@ #pragma once -#include "COMMON.h" +#include "icon.h" +#include "settings.h" -#define TOOL_STEP 1 -#define TOOL_STEP_MOD 10 - -enum ToolType +namespace anm2ed::tool { - TOOL_PAN, - TOOL_MOVE, - TOOL_ROTATE, - TOOL_SCALE, - TOOL_CROP, - TOOL_DRAW, - TOOL_ERASE, - TOOL_COLOR_PICKER, - TOOL_UNDO, - TOOL_REDO, - TOOL_COLOR, - TOOL_COUNT, -}; + enum Type + { + PAN, + MOVE, + ROTATE, + SCALE, + CROP, + DRAW, + ERASE, + COLOR_PICKER, + UNDO, + REDO, + COLOR, + COUNT + }; -const SDL_SystemCursor CURSOR_DEFAULT = SDL_SYSTEM_CURSOR_DEFAULT; -const SDL_SystemCursor TOOL_CURSORS[TOOL_COUNT] = -{ - SDL_SYSTEM_CURSOR_POINTER, - SDL_SYSTEM_CURSOR_MOVE, - SDL_SYSTEM_CURSOR_CROSSHAIR, - SDL_SYSTEM_CURSOR_NE_RESIZE, - SDL_SYSTEM_CURSOR_CROSSHAIR, - SDL_SYSTEM_CURSOR_CROSSHAIR, - SDL_SYSTEM_CURSOR_CROSSHAIR, - SDL_SYSTEM_CURSOR_CROSSHAIR, - SDL_SYSTEM_CURSOR_DEFAULT, - SDL_SYSTEM_CURSOR_DEFAULT -}; \ No newline at end of file + struct Info + { + ImGuiMouseCursor cursor{ImGuiMouseCursor_None}; + icon::Type icon{}; + settings::ShortcutType shortcut{}; + const char* label{}; + const char* tooltip{}; + }; + + constexpr Info INFO[] = { + {ImGuiMouseCursor_Hand, icon::PAN, settings::SHORTCUT_PAN, "##Pan", + "Use the pan tool.\nWill shift the view as the cursor is dragged.\nYou can also use the middle mouse button to " + "pan at any time."}, + + {ImGuiMouseCursor_ResizeAll, icon::MOVE, settings::SHORTCUT_MOVE, "##Move", + "Use the move tool.\nAnimation Preview: Will move the position of the frame." + "\nSpritesheet Editor: Will move the pivot, and holding right click will use the Crop functionality instead." + "\nUse mouse or directional keys to change the value."}, + + {ImGuiMouseCursor_Arrow, icon::ROTATE, settings::SHORTCUT_ROTATE, "##Rotate", + "Use the rotate tool.\nWill rotate the selected item as the cursor is dragged, or directional keys are " + "pressed.\n(Animation Preview only.)"}, + + {ImGuiMouseCursor_ResizeNWSE, icon::SCALE, settings::SHORTCUT_SCALE, "##Scale", + "Use the scale tool.\nWill scale the selected item as the cursor is dragged, or directional keys are " + "pressed.\n(Animation Preview only.)"}, + + {ImGuiMouseCursor_ResizeAll, icon::CROP, settings::SHORTCUT_CROP, "##Crop", + "Use the crop tool.\nWill produce a crop rectangle based on how the cursor is dragged." + "\nAlternatively, you can use the arrow keys and Ctrl/Shift to move the size/position, respectively." + "\nHolding right click will use the Move tool's functionality." + "\n(Spritesheet Editor only.)"}, + + {ImGuiMouseCursor_Hand, icon::DRAW, settings::SHORTCUT_DRAW, "##Draw", + "Draws pixels onto the selected spritesheet, with the current color.\n(Spritesheet Editor only.)"}, + + {ImGuiMouseCursor_Arrow, icon::ERASE, settings::SHORTCUT_ERASE, "##Erase", + "Erases pixels from the selected spritesheet.\n(Spritesheet Editor only.)"}, + + {ImGuiMouseCursor_Arrow, icon::COLOR_PICKER, settings::SHORTCUT_COLOR_PICKER, "##Color Picker", + "Selects a color from the canvas.\n(Spritesheet Editor only.)"}, + + {ImGuiMouseCursor_None, icon::UNDO, settings::SHORTCUT_UNDO, "##Undo", "Undoes the last action."}, + + {ImGuiMouseCursor_None, icon::REDO, settings::SHORTCUT_REDO, "##Redo", "Redoes the last action."}, + + {ImGuiMouseCursor_None, icon::NONE, settings::SHORTCUT_COLOR, "##Color", + "Selects the color to be used for drawing.\n(Spritesheet Editor only.)"}, + }; +} \ No newline at end of file diff --git a/src/tools.cpp b/src/tools.cpp new file mode 100644 index 0000000..09eb1db --- /dev/null +++ b/src/tools.cpp @@ -0,0 +1,106 @@ + +#include "tools.h" + +#include + +#include "imgui.h" +#include "tool.h" +#include "types.h" + +using namespace anm2ed::settings; +using namespace anm2ed::resources; +using namespace anm2ed::types; +using namespace glm; + +namespace anm2ed::tools +{ + constexpr auto COLOR_EDIT_LABEL = "##Color Edit"; + + void Tools::update(Settings& settings, Resources& resources) + { + if (ImGui::Begin("Tools", &settings.windowIsTools)) + { + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 2)); + + auto availableWidth = ImGui::GetContentRegionAvail().x; + auto size = vec2(ImGui::GetTextLineHeightWithSpacing() * 1.5f); + auto usedWidth = ImGui::GetStyle().WindowPadding.x; + + auto tool_switch = [&](tool::Type type) + { + switch (type) + { + case tool::UNDO: + break; + case tool::REDO: + break; + case tool::COLOR: + if (ImGui::IsPopupOpen(COLOR_EDIT_LABEL)) + ImGui::CloseCurrentPopup(); + else + isOpenColorEdit = true; + break; + default: + settings.tool = type; + break; + } + }; + + for (int i = 0; i < tool::COUNT; i++) + { + auto& info = tool::INFO[i]; + auto isSelected = settings.tool == i; + + if (isSelected) ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive)); + + auto member = SHORTCUT_MEMBERS[info.shortcut]; + + if (imgui::shortcut(settings.*member, false, true, i == tool::COLOR ? false : true)) tool_switch((tool::Type)i); + + if (i == tool::COLOR) + { + size += to_vec2(ImGui::GetStyle().FramePadding) * 2.0f; + if (ImGui::ColorButton(info.label, to_imvec4(settings.toolColor), ImGuiColorEditFlags_NoTooltip, + to_imvec2(size))) + tool_switch((tool::Type)i); + + colorEditPosition = ImGui::GetCursorScreenPos(); + } + else + { + if (ImGui::ImageButton(info.label, resources.icons[info.icon].id, to_imvec2(size))) + tool_switch((tool::Type)i); + } + + auto widthIncrement = ImGui::GetItemRectSize().x + ImGui::GetStyle().ItemSpacing.x; + usedWidth += widthIncrement; + + if (usedWidth + widthIncrement < availableWidth) + ImGui::SameLine(); + else + usedWidth = ImGui::GetStyle().WindowPadding.x; + + imgui::set_item_tooltip_shortcut(info.tooltip, settings.*SHORTCUT_MEMBERS[info.shortcut]); + + if (isSelected) ImGui::PopStyleColor(); + } + + ImGui::PopStyleVar(); + + if (isOpenColorEdit) + { + ImGui::OpenPopup(COLOR_EDIT_LABEL); + isOpenColorEdit = false; + } + + ImGui::SetNextWindowPos(colorEditPosition, ImGuiCond_None); + + if (ImGui::BeginPopup(COLOR_EDIT_LABEL)) + { + ImGui::ColorPicker4(COLOR_EDIT_LABEL, value_ptr(settings.toolColor)); + ImGui::EndPopup(); + } + } + ImGui::End(); + } +} diff --git a/src/tools.h b/src/tools.h new file mode 100644 index 0000000..895a3b3 --- /dev/null +++ b/src/tools.h @@ -0,0 +1,16 @@ +#pragma once + +#include "resources.h" +#include "settings.h" + +namespace anm2ed::tools +{ + class Tools + { + bool isOpenColorEdit{}; + ImVec2 colorEditPosition{}; + + public: + void update(settings::Settings& settings, resources::Resources& resources); + }; +} diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..a22daa7 --- /dev/null +++ b/src/types.h @@ -0,0 +1,67 @@ +#pragma once + +#include +#include +#include + +namespace anm2ed::types::merge +{ + enum Type + { + PREPEND, + APPEND, + REPLACE, + IGNORE + }; +} + +namespace anm2ed::types::color +{ + using namespace glm; + + constexpr auto WHITE = vec4(1.0); + constexpr auto BLACK = vec4(0.0, 0.0, 0.0, 1.0); + constexpr auto RED = vec4(1.0, 0.0, 0.0, 1.0); + constexpr auto GREEN = vec4(0.0, 1.0, 0.0, 1.0); + constexpr auto BLUE = vec4(0.0, 0.0, 1.0, 1.0); + constexpr auto TRANSPARENT = vec4(); +} + +namespace anm2ed::types::step +{ + constexpr auto NORMAL = 1; + constexpr auto FAST = 10; +} + +namespace anm2ed::types +{ + constexpr ImVec2 to_imvec2(const glm::vec2& v) noexcept + { + return {v.x, v.y}; + } + constexpr glm::vec2 to_vec2(const ImVec2& v) noexcept + { + return {v.x, v.y}; + } + + constexpr glm::ivec2 to_ivec2(const ImVec2& v) noexcept + { + return {v.x, v.y}; + } + + constexpr ImVec4 to_imvec4(const glm::vec4& v) noexcept + { + return {v.x, v.y, v.z, v.w}; + } + + constexpr glm::vec4 to_vec4(const ImVec4& v) noexcept + { + return {v.x, v.y, v.z, v.w}; + } + + template constexpr T& dummy_value() + { + static T value{}; + return value; + } +} \ No newline at end of file diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..110a494 --- /dev/null +++ b/src/util.cpp @@ -0,0 +1,40 @@ +#include "util.h" + +#include +#include + +namespace anm2ed::util::time +{ + std::string get(const char* format) + { + auto now = std::chrono::system_clock::now(); + auto time = std::chrono::system_clock::to_time_t(now); + auto localTime = *std::localtime(&time); + std::ostringstream timeString; + timeString << std::put_time(&localTime, format); + return timeString.str(); + } +} + +namespace anm2ed::util::string +{ + std::string to_lower(const std::string& string) + { + std::string transformed = string; + std::ranges::transform(transformed, transformed.begin(), [](const unsigned char c) { return std::tolower(c); }); + return transformed; + } + + std::string replace_backslash(const std::string& string) + { + std::string transformed = string; + for (char& character : transformed) + if (character == '\\') character = '/'; + return transformed; + } + + bool to_bool(const std::string& string) + { + return to_lower(string) == "true"; + } +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..ec50cb3 --- /dev/null +++ b/src/util.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include +#include + +namespace anm2ed::util::time +{ + std::string get(const char* format); +} + +namespace anm2ed::util::string +{ + std::string to_lower(const std::string& string); + std::string replace_backslash(const std::string& string); + bool to_bool(const std::string& string); +} + +namespace anm2ed::util::map +{ + template int next_id_get(std::map& map) + { + int id = 0; + + for (auto& [key, value] : map) + { + if (key != id) break; + ++id; + } + + return id; + } + + template T1* find(std::map& map, T0 index) + { + return map.contains(index) ? &map[index] : nullptr; + } +} + +namespace anm2ed::util::unordered_map +{ + template T1* find(std::unordered_map& map, T0 index) + { + return map.contains(index) ? &map[index] : nullptr; + } +} + +namespace anm2ed::util::vector +{ + template T* find(std::vector& v, int index) + { + return index >= 0 && index < (int)v.size() ? &v[index] : nullptr; + } +} \ No newline at end of file diff --git a/src/window.cpp b/src/window.cpp deleted file mode 100644 index 6654c77..0000000 --- a/src/window.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "window.h" -#include - -void window_title_from_path_set(SDL_Window* self, const std::string& path) { - if (!path.empty()) - SDL_SetWindowTitle(self, std::format(WINDOW_TITLE_FORMAT, path).c_str()); - else - SDL_SetWindowTitle(self, WINDOW_TITLE); -} - -void window_vsync_set(bool isVsync) { SDL_GL_SetSwapInterval(isVsync); } \ No newline at end of file diff --git a/src/window.h b/src/window.h deleted file mode 100644 index 5cffb22..0000000 --- a/src/window.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "COMMON.h" - -#define WINDOW_TITLE "Anm2Ed" -#define WINDOW_TITLE_FORMAT "Anm2Ed ({})" -#define WINDOW_FLAGS SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL -#define WINDOW_TEST_MODE_FLAGS WINDOW_FLAGS | SDL_WINDOW_HIDDEN - -static const ivec2 WINDOW_TEST_MODE_SIZE = {1, 1}; - -void window_title_from_path_set(SDL_Window* self, const std::string& path); -bool window_color_from_position_get(SDL_Window* self, vec2 position, vec4* color); -void window_vsync_set(bool isVsync); \ No newline at end of file diff --git a/src/xml.cpp b/src/xml.cpp new file mode 100644 index 0000000..c4ff81b --- /dev/null +++ b/src/xml.cpp @@ -0,0 +1,37 @@ +#include "xml.h" + +#include "math.h" + +namespace anm2ed::xml +{ + std::string document_to_string(tinyxml2::XMLDocument& self) + { + tinyxml2::XMLPrinter printer{}; + self.Print(&printer); + return std::string(printer.CStr()); + } + + tinyxml2::XMLError query_string_attribute(tinyxml2::XMLElement* element, const char* attribute, std::string* out) + { + const char* temp = nullptr; + auto result = element->QueryStringAttribute(attribute, &temp); + if (result == tinyxml2::XML_SUCCESS && temp) *out = temp; + return result; + } + + tinyxml2::XMLError query_path_attribute(tinyxml2::XMLElement* element, const char* attribute, + std::filesystem::path* out) + { + std::string temp{}; + auto result = query_string_attribute(element, attribute, &temp); + if (result == tinyxml2::XML_SUCCESS) *out = temp; + return result; + } + + void query_color_attribute(tinyxml2::XMLElement* element, const char* attribute, float& out) + { + int value{}; + element->QueryIntAttribute(attribute, &value); + out = math::uint8_to_float(value); + } +} \ No newline at end of file diff --git a/src/xml.h b/src/xml.h new file mode 100644 index 0000000..9bca4a3 --- /dev/null +++ b/src/xml.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#include + +namespace anm2ed::xml +{ + std::string document_to_string(tinyxml2::XMLDocument& self); + tinyxml2::XMLError query_string_attribute(tinyxml2::XMLElement* element, const char* attribute, std::string* out); + tinyxml2::XMLError query_path_attribute(tinyxml2::XMLElement* element, const char* attribute, + std::filesystem::path* out); + void query_color_attribute(tinyxml2::XMLElement* element, const char* attribute, float& out); +} \ No newline at end of file From 87c2db2a774300b4d6b6745108312c023e1463f5 Mon Sep 17 00:00:00 2001 From: shweet Date: Wed, 22 Oct 2025 21:27:11 -0400 Subject: [PATCH 06/15] Refactoring; structs for popups/multi-selects, additional popups in places --- .vscode/settings.json | 8 -- src/animations.cpp | 72 +++++------ src/animations.h | 10 +- src/anm2.cpp | 139 ++++++++++++++------- src/anm2.h | 20 +++- src/dockspace.cpp | 10 +- src/document.cpp | 58 +++++++-- src/document.h | 17 ++- src/document_manager.cpp | 20 +--- src/documents.cpp | 20 +--- src/documents.h | 2 + src/events.cpp | 45 +++---- src/events.h | 4 +- src/frame_properties.cpp | 2 + src/imgui.cpp | 94 +++++++++++++-- src/imgui.h | 46 ++++++- src/layers.cpp | 127 +++++++++++++++----- src/layers.h | 13 +- src/nulls.cpp | 42 +++---- src/nulls.h | 8 +- src/onionskin.cpp | 6 +- src/settings.h | 2 + src/spritesheets.cpp | 67 +++++------ src/spritesheets.h | 10 +- src/state.cpp | 3 +- src/taskbar.cpp | 39 ++---- src/taskbar.h | 7 +- src/timeline.cpp | 253 ++++++++++++++++++++++++++++++++++----- src/timeline.h | 14 ++- src/tools.cpp | 2 +- src/types.h | 44 +++++++ 31 files changed, 849 insertions(+), 355 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 73ffdc7..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C_Cpp.formatting": "clangFormat", - "editor.formatOnSave": true, - "clang-format.style": "file", - "clangd.arguments": [ - "--compile-commands-dir=build" - ] -} \ No newline at end of file diff --git a/src/animations.cpp b/src/animations.cpp index f41f35a..73e7baf 100644 --- a/src/animations.cpp +++ b/src/animations.cpp @@ -3,33 +3,27 @@ #include #include -#include "imgui.h" - -using namespace anm2ed::document_manager; +using namespace anm2ed::document; using namespace anm2ed::settings; using namespace anm2ed::resources; using namespace anm2ed::types; namespace anm2ed::animations { - void Animations::update(DocumentManager& manager, Settings& settings, Resources& resources) + void Animations::update(Document& document, int& documentIndex, Settings& settings, Resources& resources) { - auto document = manager.get(); - auto& anm2 = document->anm2; - auto& reference = document->reference; - auto& selection = document->selectedAnimations; - storage.UserData = &selection; - storage.AdapterSetItemSelected = imgui::external_storage_set; + auto& anm2 = document.anm2; + auto& reference = document.reference; + auto& selection = document.selectedAnimations; + storage.user_data_set(&selection); if (ImGui::Begin("Animations", &settings.windowIsAnimations)) { - auto childSize = imgui::size_with_footer_get(); + auto childSize = imgui::size_without_footer_get(); if (ImGui::BeginChild("##Animations Child", childSize, ImGuiChildFlags_Borders)) { - ImGuiMultiSelectIO* io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, selection.size(), - anm2.animations.items.size()); - storage.ApplyRequests(io); + storage.begin(anm2.animations.items.size()); for (auto [i, animation] : std::views::enumerate(anm2.animations.items)) { @@ -47,7 +41,7 @@ namespace anm2ed::animations ImGui::PushFont(resources.fonts[font].get(), font::SIZE); ImGui::SetNextItemSelectionUserData(i); if (imgui::selectable_input_text(animation.name, - std::format("###Document #{} Animation #{}", manager.selected, i), + std::format("###Document #{} Animation #{}", documentIndex, i), animation.name, isSelected)) if (!isReferenced) reference = {(int)i}; ImGui::PopFont(); @@ -66,8 +60,8 @@ namespace anm2ed::animations ImGui::PopFont(); } - ImGui::TextUnformatted(std::format("Length: {}", animation.frameNum).c_str()); - ImGui::TextUnformatted(std::format("Loop: {}", animation.isLoop).c_str()); + ImGui::Text("Length: %d", animation.frameNum); + ImGui::Text("Loop: %s", animation.isLoop ? "true" : "false"); ImGui::EndTooltip(); } @@ -102,18 +96,17 @@ namespace anm2ed::animations ImGui::PopID(); } - io = ImGui::EndMultiSelect(); - storage.ApplyRequests(io); + storage.end(); } ImGui::EndChild(); auto widgetSize = imgui::widget_size_with_row_get(5); - imgui::shortcut(settings.shortcutAdd, true); + imgui::shortcut(settings.shortcutAdd); if (ImGui::Button("Add", widgetSize)) { anm2::Animation animation; - if (anm2::Animation* referenceAnimation = document->animation_get()) + if (anm2::Animation* referenceAnimation = document.animation_get()) { for (auto [id, layerAnimation] : referenceAnimation->layerAnimations) animation.layerAnimations[id] = anm2::Item(); @@ -127,6 +120,7 @@ namespace anm2ed::animations anm2.animations.items.insert(anm2.animations.items.begin() + index, animation); selection = {index}; reference = {index}; + document.change(change::ANIMATIONS); } imgui::set_item_tooltip_shortcut("Add a new animation.", settings.shortcutAdd); @@ -135,7 +129,7 @@ namespace anm2ed::animations ImGui::BeginDisabled(selection.empty()); { - imgui::shortcut(settings.shortcutDuplicate, true); + imgui::shortcut(settings.shortcutDuplicate); if (ImGui::Button("Duplicate", widgetSize)) { auto duplicated = selection; @@ -146,6 +140,7 @@ namespace anm2ed::animations selection.insert(++duplicatedEnd); selection.erase(id); } + document.change(change::ANIMATIONS); } imgui::set_item_tooltip_shortcut("Duplicate the selected animation(s).", settings.shortcutDuplicate); @@ -155,7 +150,7 @@ namespace anm2ed::animations { if (ImGui::Button("Merge", widgetSize)) { - ImGui::OpenPopup("Merge Animations"); + mergePopup.open(); mergeSelection.clear(); mergeTarget = *selection.begin(); } @@ -169,14 +164,15 @@ namespace anm2ed::animations ImGui::SameLine(); - imgui::shortcut(settings.shortcutRemove, true); + imgui::shortcut(settings.shortcutRemove); if (ImGui::Button("Remove", widgetSize)) { /* auto selectionErase = set::to_size_t(selection); - if (selectionErase.contains(document->reference.animationIndex)) document->reference.animationIndex = -1; + if (selectionErase.contains(document.reference.animationIndex)) document.reference.animationIndex = -1; vector::range_erase(anm2.animations.items, selectionErase); */ + document.change(change::ANIMATIONS); selection.clear(); } imgui::set_item_tooltip_shortcut("Remove the selected animation(s).", settings.shortcutDuplicate); @@ -185,7 +181,7 @@ namespace anm2ed::animations ImGui::BeginDisabled(selection.size() != 1); { - imgui::shortcut(settings.shortcutDefault, true); + imgui::shortcut(settings.shortcutDefault); if (ImGui::Button("Default", widgetSize)) anm2.animations.defaultAnimation = anm2.animations.items[*selection.begin()].name; imgui::set_item_tooltip_shortcut("Set the selected animation as the default.", settings.shortcutDuplicate); @@ -194,27 +190,23 @@ namespace anm2ed::animations } ImGui::EndDisabled(); - auto viewport = ImGui::GetMainViewport(); + mergePopup.trigger(); - ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_None, ImVec2(0.5f, 0.5f)); - ImGui::SetNextWindowSize(to_imvec2(to_vec2(viewport->Size) * 0.5f)); - - if (ImGui::BeginPopupModal("Merge Animations", nullptr, ImGuiWindowFlags_NoResize)) + if (ImGui::BeginPopupModal(mergePopup.label, &mergePopup.isOpen, ImGuiWindowFlags_NoResize)) { auto merge_close = [&]() { mergeSelection.clear(); - ImGui::CloseCurrentPopup(); + mergePopup.close(); }; auto& type = settings.mergeType; auto& isDeleteAnimationsAfter = settings.mergeIsDeleteAnimationsAfter; - mergeStorage.UserData = &mergeSelection; - mergeStorage.AdapterSetItemSelected = imgui::external_storage_set; + mergeStorage.user_data_set(&mergeSelection); - auto footerSize = ImVec2(0, imgui::footer_height_get()); - auto optionsSize = imgui::child_size_get(2, true); + auto footerSize = imgui::footer_size_get(); + auto optionsSize = imgui::child_size_get(2); auto deleteAfterSize = imgui::child_size_get(); auto animationsSize = ImVec2(0, ImGui::GetContentRegionAvail().y - @@ -222,9 +214,7 @@ namespace anm2ed::animations if (ImGui::BeginChild("Animations", animationsSize, ImGuiChildFlags_Borders)) { - ImGuiMultiSelectIO* io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, mergeSelection.size(), - anm2.animations.items.size()); - mergeStorage.ApplyRequests(io); + mergeSelection.begin(); for (auto [i, animation] : std::views::enumerate(anm2.animations.items)) { @@ -238,14 +228,12 @@ namespace anm2ed::animations ImGui::PopID(); } - io = ImGui::EndMultiSelect(); - mergeStorage.ApplyRequests(io); + mergeSelection.end(); } ImGui::EndChild(); if (ImGui::BeginChild("Merge Options", optionsSize, ImGuiChildFlags_Borders)) { - auto size = ImVec2(optionsSize.x * 0.5f, optionsSize.y - ImGui::GetStyle().WindowPadding.y * 2); if (ImGui::BeginChild("Merge Options 1", size)) diff --git a/src/animations.h b/src/animations.h index a06a582..552b4d1 100644 --- a/src/animations.h +++ b/src/animations.h @@ -1,6 +1,7 @@ #pragma once -#include "document_manager.h" +#include "document.h" +#include "imgui.h" #include "resources.h" #include "settings.h" @@ -8,13 +9,14 @@ namespace anm2ed::animations { class Animations { - ImGuiSelectionExternalStorage mergeStorage{}; - ImGuiSelectionExternalStorage storage{}; + imgui::PopupHelper mergePopup{imgui::PopupHelper("Merge Animations")}; + imgui::MultiSelectStorage mergeStorage{}; + imgui::MultiSelectStorage storage{}; std::set mergeSelection{}; int mergeTarget{}; public: - void update(document_manager::DocumentManager& manager, settings::Settings& settings, + void update(document::Document& document, int& documentIndex, settings::Settings& settings, resources::Resources& resources); }; } \ No newline at end of file diff --git a/src/anm2.cpp b/src/anm2.cpp index a36d94c..b67c7a1 100644 --- a/src/anm2.cpp +++ b/src/anm2.cpp @@ -16,6 +16,7 @@ using namespace anm2ed::util; namespace anm2ed::anm2 { + void Reference::previous_frame(int max) { frameIndex = glm::clamp(--frameIndex, 0, max); @@ -213,20 +214,6 @@ namespace anm2ed::anm2 } } - bool Content::spritesheet_add(const std::string& directory, const std::string& path, int& id) - { - Spritesheet spritesheet(directory, path); - if (!spritesheet.is_valid()) return false; - id = map::next_id_get(spritesheets); - spritesheets[id] = std::move(spritesheet); - return true; - } - - void Content::spritesheet_remove(int& id) - { - spritesheets.erase(id); - } - std::set Content::spritesheets_unused() { std::set used; @@ -778,7 +765,16 @@ namespace anm2ed::anm2 bool Anm2::spritesheet_add(const std::string& directory, const std::string& path, int& id) { - return content.spritesheet_add(directory, path, id); + Spritesheet spritesheet(directory, path); + if (!spritesheet.is_valid()) return false; + id = map::next_id_get(content.spritesheets); + content.spritesheets[id] = std::move(spritesheet); + return true; + } + + void Anm2::spritesheet_remove(int id) + { + content.spritesheets.erase(id); } Spritesheet* Anm2::spritesheet_get(int id) @@ -786,24 +782,60 @@ namespace anm2ed::anm2 return map::find(content.spritesheets, id); } - void Anm2::spritesheet_remove(int id) - { - content.spritesheet_remove(id); - } - std::set Anm2::spritesheets_unused() { return content.spritesheets_unused(); } - void Anm2::layer_add(int& id) + Reference Anm2::layer_add(Reference reference, std::string name, int spritesheetID, locale::Type locale) { - content.layer_add(id); + auto id = reference.itemID == -1 ? map::next_id_get(content.layers) : reference.itemID; + auto& layer = content.layers[id]; + + layer.name = !name.empty() ? name : layer.name; + layer.spritesheetID = content.spritesheets.contains(spritesheetID) ? spritesheetID : 0; + + auto add = [&](Animation* animation, int id) + { + animation->layerAnimations[id] = Item(); + animation->layerOrder.push_back(id); + }; + + if (locale == locale::GLOBAL) + { + for (auto& animation : animations.items) + if (!animation.layerAnimations.contains(id)) add(&animation, id); + } + else if (locale == locale::LOCAL) + { + if (auto animation = animation_get(reference)) + if (!animation->layerAnimations.contains(id)) add(animation, id); + } + + return {reference.animationIndex, LAYER, id}; } - void Anm2::null_add(int& id) + Reference Anm2::null_add(Reference reference, std::string name, locale::Type locale) { - content.null_add(id); + auto id = reference.itemID == -1 ? map::next_id_get(content.nulls) : reference.itemID; + auto& null = content.nulls[id]; + + null.name = !name.empty() ? name : null.name; + + auto add = [&](Animation* animation, int id) { animation->nullAnimations[id] = Item(); }; + + if (locale == locale::GLOBAL) + { + for (auto& animation : animations.items) + if (!animation.nullAnimations.contains(id)) add(&animation, id); + } + else if (locale == locale::LOCAL) + { + if (auto animation = animation_get(reference)) + if (!animation->nullAnimations.contains(id)) add(animation, id); + } + + return {reference.animationIndex, LAYER, id}; } void Anm2::event_add(int& id) @@ -811,45 +843,68 @@ namespace anm2ed::anm2 content.event_add(id); } - std::set Anm2::events_unused() + std::set Anm2::events_unused(Reference reference) { - std::set used; - for (auto& animation : animations.items) - for (auto& frame : animation.triggers.frames) - used.insert(frame.eventID); + std::set used{}; + std::set unused{}; + + if (auto animation = animation_get(reference); animation) + for (auto& frame : animation->triggers.frames) + used.insert(frame.eventID); + else + for (auto& animation : animations.items) + for (auto& frame : animation.triggers.frames) + used.insert(frame.eventID); - std::set unused; for (auto& id : content.events | std::views::keys) if (!used.contains(id)) unused.insert(id); return unused; } - std::set Anm2::layers_unused() + std::set Anm2::layers_unused(Reference reference) { - std::set used; - for (auto& animation : animations.items) - for (auto& id : animation.layerAnimations | std::views::keys) - used.insert(id); + std::set used{}; + std::set unused{}; + + if (auto animation = animation_get(reference); animation) + for (auto& id : animation->layerAnimations | std::views::keys) + used.insert(id); + else + for (auto& animation : animations.items) + for (auto& id : animation.layerAnimations | std::views::keys) + used.insert(id); - std::set unused; for (auto& id : content.layers | std::views::keys) if (!used.contains(id)) unused.insert(id); return unused; } - std::set Anm2::nulls_unused() + std::set Anm2::nulls_unused(Reference reference) { - std::set used; - for (auto& animation : animations.items) - for (auto& id : animation.nullAnimations | std::views::keys) - used.insert(id); + std::set used{}; + std::set unused{}; + + if (auto animation = animation_get(reference); animation) + for (auto& id : animation->nullAnimations | std::views::keys) + used.insert(id); + else + for (auto& animation : animations.items) + for (auto& id : animation.nullAnimations | std::views::keys) + used.insert(id); - std::set unused; for (auto& id : content.nulls | std::views::keys) if (!used.contains(id)) unused.insert(id); return unused; } + + std::vector Anm2::spritesheet_names_get() + { + std::vector spritesheets{}; + for (auto& [id, spritesheet] : content.spritesheets) + spritesheets.push_back(std::format("#{} {}", id, spritesheet.path.c_str())); + return spritesheets; + } } \ No newline at end of file diff --git a/src/anm2.h b/src/anm2.h index ef9a820..5257a11 100644 --- a/src/anm2.h +++ b/src/anm2.h @@ -21,6 +21,10 @@ namespace anm2ed::anm2 constexpr auto MERGED_STRING = "(Merged)"; + constexpr auto LAYER_FORMAT = "#{} {} (Spritesheet: #{})"; + constexpr auto NULL_FORMAT = "#{} {}"; + constexpr auto SPRITESHEET_FORMAT = "#%d %s"; + enum Type { NONE, @@ -44,6 +48,8 @@ namespace anm2ed::anm2 auto operator<=>(const Reference&) const = default; }; + constexpr anm2::Reference REFERENCE_DEFAULT = {-1, anm2::NONE, -1, -1, -1}; + class Info { public: @@ -228,11 +234,15 @@ namespace anm2ed::anm2 Spritesheet* spritesheet_get(int id); void spritesheet_remove(int id); std::set spritesheets_unused(); - void layer_add(int& id); - void null_add(int& id); + int layer_add(); + Reference layer_add(Reference reference = REFERENCE_DEFAULT, std::string name = {}, int spritesheetID = 0, + types::locale::Type locale = types::locale::GLOBAL); + Reference null_add(Reference reference = REFERENCE_DEFAULT, std::string name = {}, + types::locale::Type locale = types::locale::GLOBAL); void event_add(int& id); - std::set events_unused(); - std::set layers_unused(); - std::set nulls_unused(); + std::set events_unused(Reference reference = REFERENCE_DEFAULT); + std::set layers_unused(Reference reference = REFERENCE_DEFAULT); + std::set nulls_unused(Reference reference = REFERENCE_DEFAULT); + std::vector spritesheet_names_get(); }; } \ No newline at end of file diff --git a/src/dockspace.cpp b/src/dockspace.cpp index 855482a..a86d1f3 100644 --- a/src/dockspace.cpp +++ b/src/dockspace.cpp @@ -33,17 +33,17 @@ namespace anm2ed::dockspace { if (ImGui::DockSpace(ImGui::GetID("##DockSpace"), ImVec2(), ImGuiDockNodeFlags_PassthruCentralNode)) { - if (manager.get()) + if (auto document = manager.get(); document) { if (settings.windowIsAnimationPreview) animationPreview.update(manager, settings, resources, playback); - if (settings.windowIsAnimations) animations.update(manager, settings, resources); + if (settings.windowIsAnimations) animations.update(*document, manager.selected, settings, resources); if (settings.windowIsEvents) events.update(manager, settings, resources); if (settings.windowIsFrameProperties) frameProperties.update(manager, settings); - if (settings.windowIsLayers) layers.update(manager, settings, resources); - if (settings.windowIsNulls) nulls.update(manager, settings, resources); + if (settings.windowIsLayers) layers.update(*document, settings, resources); + if (settings.windowIsNulls) nulls.update(*document, manager.selected, settings, resources); if (settings.windowIsOnionskin) onionskin.update(settings); if (settings.windowIsSpritesheetEditor) spritesheetEditor.update(manager, settings, resources); - if (settings.windowIsSpritesheets) spritesheets.update(manager, settings, resources, dialog); + if (settings.windowIsSpritesheets) spritesheets.update(*document, settings, resources, dialog); if (settings.windowIsTimeline) timeline.update(manager, settings, resources, playback); if (settings.windowIsTools) tools.update(settings, resources); } diff --git a/src/document.cpp b/src/document.cpp index 8b002a3..3727f79 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -5,13 +5,21 @@ using namespace anm2ed::anm2; using namespace anm2ed::filesystem; +using namespace anm2ed::types; namespace anm2ed::document { - Document::Document() = default; + Document::Document() + { + for (auto& value : isJustChanged) + value = true; + } Document::Document(const std::string& path, bool isNew, std::string* errorString) { + for (auto& value : isJustChanged) + value = true; + if (!path_is_exist(path)) return; if (isNew) @@ -23,7 +31,8 @@ namespace anm2ed::document } this->path = path; - hash_set(); + on_change(); + clean(); } bool Document::save(const std::string& path, std::string* errorString) @@ -32,7 +41,7 @@ namespace anm2ed::document if (anm2.serialize(this->path, errorString)) { - hash_set(); + clean(); return true; } @@ -40,18 +49,20 @@ namespace anm2ed::document } void Document::hash_set() + { + hash = anm2.hash(); + } + + void Document::clean() { saveHash = anm2.hash(); hash = saveHash; } - void Document::hash_time(double time, double interval) + void Document::change(change::Type type) { - if (time - lastHashTime > interval) - { - hash = anm2.hash(); - lastHashTime = time; - } + hash_set(); + isJustChanged[type] = true; } bool Document::is_dirty() @@ -59,6 +70,11 @@ namespace anm2ed::document return hash != saveHash; } + bool Document::is_just_changed(types::change::Type type) + { + return isJustChanged[type]; + } + std::string Document::directory_get() { return path.parent_path(); @@ -79,6 +95,11 @@ namespace anm2ed::document return anm2.frame_get(reference); } + anm2::Item* Document::item_get() + { + return anm2.item_get(reference); + } + anm2::Spritesheet* Document::spritesheet_get() { return anm2.spritesheet_get(referenceSpritesheet); @@ -88,4 +109,23 @@ namespace anm2ed::document { return !path.empty(); } + + void Document::on_change() + { + if (is_just_changed(change::SPRITESHEETS)) + { + spritesheetNames = anm2.spritesheet_names_get(); + spritesheetNamesCstr.clear(); + for (auto& name : spritesheetNames) + spritesheetNamesCstr.push_back(name.c_str()); + } + } + + void Document::update() + { + on_change(); + + for (auto& value : isJustChanged) + value = false; + } }; \ No newline at end of file diff --git a/src/document.h b/src/document.h index d16377b..7097ce6 100644 --- a/src/document.h +++ b/src/document.h @@ -1,9 +1,11 @@ #pragma once -#include "anm2.h" #include #include +#include "anm2.h" +#include "types.h" + #include namespace anm2ed::document @@ -22,6 +24,7 @@ namespace anm2ed::document int overlayIndex{}; int referenceSpritesheet{-1}; + int referenceLayer{-1}; std::set selectedEvents{}; std::set selectedLayers{}; @@ -29,9 +32,12 @@ namespace anm2ed::document std::set selectedAnimations{}; std::set selectedSpritesheets{}; + std::vector spritesheetNames{}; + std::vector spritesheetNamesCstr{}; + uint64_t hash{}; uint64_t saveHash{}; - double lastHashTime{}; + bool isJustChanged[types::change::COUNT]{}; bool isOpen{true}; Document(); @@ -39,12 +45,17 @@ namespace anm2ed::document Document(const std::string& path, bool isNew = false, std::string* errorString = nullptr); bool save(const std::string& path = {}, std::string* errorString = nullptr); void hash_set(); - void hash_time(double time, double interval = 1.0); + void clean(); + void on_change(); + void change(types::change::Type type); + bool is_just_changed(types::change::Type type); bool is_dirty(); + void update(); std::string directory_get(); std::string filename_get(); anm2::Animation* animation_get(); anm2::Frame* frame_get(); + anm2::Item* item_get(); anm2::Spritesheet* spritesheet_get(); bool is_valid(); }; diff --git a/src/document_manager.cpp b/src/document_manager.cpp index f31bb73..2ad1207 100644 --- a/src/document_manager.cpp +++ b/src/document_manager.cpp @@ -1,9 +1,7 @@ #include "document_manager.h" -#include "toast.h" #include "util.h" -using namespace anm2ed::toast; using namespace anm2ed::util; namespace anm2ed::document_manager @@ -27,10 +25,8 @@ namespace anm2ed::document_manager documents.emplace_back(std::move(document)); selected = documents.size() - 1; pendingSelected = selected; - toasts.add(std::format("Opened document: {}", path)); return true; } - toasts.add_error(std::format("Failed to open document: {} ({})", path, errorString)); return false; } @@ -47,10 +43,7 @@ namespace anm2ed::document_manager document->path = !path.empty() ? path : document->path.string(); - if (document->save(document->path, &errorString)) - toasts.add(std::format("Saved document: {}", document->path.string())); - else - toasts.add_error(std::format("Failed to save document: {} ({})", document->path.string(), errorString)); + document->save(document->path, &errorString); } void DocumentManager::save(const std::string& path) @@ -62,15 +55,4 @@ namespace anm2ed::document_manager { documents.erase(documents.begin() + index); } - - void DocumentManager::spritesheet_add(const std::string& path) - { - auto document = get(); - if (!document) return; - - if (int id{}; document->anm2.spritesheet_add(document->directory_get(), path, id)) - toasts.add(std::format("Added spritesheet #{}: {}", id, path)); - else - toasts.add(std::format("Failed to add spritesheet #{}: {}", id, path)); - } } diff --git a/src/documents.cpp b/src/documents.cpp index 59d3bf8..1059a0d 100644 --- a/src/documents.cpp +++ b/src/documents.cpp @@ -32,10 +32,8 @@ namespace anm2ed::documents for (auto [i, document] : std::views::enumerate(manager.documents)) { auto isDirty = document.is_dirty(); - auto isRequested = i == manager.pendingSelected; auto isSelected = i == manager.selected; - - if (isSelected) document.hash_time(ImGui::GetTime()); + auto isRequested = i == manager.pendingSelected; auto font = isDirty ? font::ITALICS : font::REGULAR; @@ -67,23 +65,18 @@ namespace anm2ed::documents else manager.close(i); } + + if (isSelected) document.update(); } ImGui::EndTabBar(); } - if (isOpenCloseDocumentPopup) - { - ImGui::OpenPopup("Close Document"); - isOpenCloseDocumentPopup = false; - } + closePopup.trigger(); if (isCloseDocument) { - ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_None, ImVec2(0.5f, 0.5f)); - ImGui::SetNextWindowSize(ImVec2(), ImGuiCond_None); - - if (ImGui::BeginPopupModal("Close Document", nullptr, ImGuiWindowFlags_NoResize)) + if (ImGui::BeginPopupModal(closePopup.label, &closePopup.isOpen, ImGuiWindowFlags_NoResize)) { auto closeDocument = manager.get(closeDocumentIndex); @@ -96,8 +89,7 @@ namespace anm2ed::documents auto close = [&]() { closeDocumentIndex = 0; - isCloseDocument = false; - ImGui::CloseCurrentPopup(); + closePopup.close(); }; if (ImGui::Button("Yes", widgetSize)) diff --git a/src/documents.h b/src/documents.h index abe724d..f5bb60a 100644 --- a/src/documents.h +++ b/src/documents.h @@ -1,6 +1,7 @@ #pragma once #include "document_manager.h" +#include "imgui.h" #include "resources.h" #include "taskbar.h" @@ -11,6 +12,7 @@ namespace anm2ed::documents bool isCloseDocument{}; bool isOpenCloseDocumentPopup{}; int closeDocumentIndex{}; + imgui::PopupHelper closePopup{imgui::PopupHelper("Close Document", imgui::POPUP_TO_CONTENT)}; public: float height{}; diff --git a/src/events.cpp b/src/events.cpp index c2c624c..7e69b83 100644 --- a/src/events.cpp +++ b/src/events.cpp @@ -2,8 +2,6 @@ #include -#include "imgui.h" - using namespace anm2ed::document_manager; using namespace anm2ed::settings; using namespace anm2ed::resources; @@ -13,22 +11,22 @@ namespace anm2ed::events { void Events::update(DocumentManager& manager, Settings& settings, Resources& resources) { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& selection = document.selectedEvents; + + if (document.is_just_changed(change::EVENTS)) unusedEventIDs = anm2.events_unused(); + + storage.user_data_set(&selection); + if (ImGui::Begin("Events", &settings.windowIsEvents)) { - auto document = manager.get(); - anm2::Anm2& anm2 = document->anm2; - - auto& selection = document->selectedEvents; - storage.UserData = &selection; - storage.AdapterSetItemSelected = imgui::external_storage_set; - - auto childSize = imgui::size_with_footer_get(); + auto childSize = imgui::size_without_footer_get(); + bool isRenamed{}; if (ImGui::BeginChild("##Events Child", childSize, true)) { - ImGuiMultiSelectIO* io = - ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, selection.size(), anm2.content.events.size()); - storage.ApplyRequests(io); + storage.begin(anm2.content.events.size()); for (auto& [id, event] : anm2.content.events) { @@ -36,8 +34,9 @@ namespace anm2ed::events ImGui::PushID(id); ImGui::SetNextItemSelectionUserData(id); - imgui::selectable_input_text(event.name, std::format("###Document #{} Event #{}", manager.selected, id), - event.name, isSelected); + if (imgui::selectable_input_text(event.name, std::format("###Document #{} Event #{}", manager.selected, id), + event.name, isSelected, 0, &isRenamed)) + if (isRenamed) document.change(change::EVENTS); if (ImGui::BeginItemTooltip()) { ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); @@ -48,31 +47,33 @@ namespace anm2ed::events ImGui::PopID(); } - io = ImGui::EndMultiSelect(); - storage.ApplyRequests(io); + storage.end(); } ImGui::EndChild(); auto widgetSize = imgui::widget_size_with_row_get(2); - imgui::shortcut(settings.shortcutAdd, true); + imgui::shortcut(settings.shortcutAdd); if (ImGui::Button("Add", widgetSize)) { int id{}; anm2.event_add(id); selection = {id}; + document.change(change::EVENTS); } imgui::set_item_tooltip_shortcut("Add an event.", settings.shortcutAdd); ImGui::SameLine(); - std::set unusedEventIDs = anm2.events_unused(); - - imgui::shortcut(settings.shortcutRemove, true); + imgui::shortcut(settings.shortcutRemove); ImGui::BeginDisabled(unusedEventIDs.empty()); { if (ImGui::Button("Remove Unused", widgetSize)) + { for (auto& id : unusedEventIDs) - anm2.content.layers.erase(id); + anm2.content.events.erase(id); + document.change(change::EVENTS); + unusedEventIDs.clear(); + } } ImGui::EndDisabled(); imgui::set_item_tooltip_shortcut("Remove unused events (i.e., ones not used by any trigger in any animation.)", diff --git a/src/events.h b/src/events.h index 9573295..f38f3bf 100644 --- a/src/events.h +++ b/src/events.h @@ -1,6 +1,7 @@ #pragma once #include "document_manager.h" +#include "imgui.h" #include "resources.h" #include "settings.h" @@ -8,7 +9,8 @@ namespace anm2ed::events { class Events { - ImGuiSelectionExternalStorage storage{}; + imgui::MultiSelectStorage storage{}; + std::set unusedEventIDs{}; public: void update(document_manager::DocumentManager& manager, settings::Settings& settings, diff --git a/src/frame_properties.cpp b/src/frame_properties.cpp index 4b57cbf..35ec7ff 100644 --- a/src/frame_properties.cpp +++ b/src/frame_properties.cpp @@ -100,7 +100,9 @@ namespace anm2ed::frame_properties "%s", "Toggle the frame interpolating; i.e., blending its values into the next frame based on the time."); ImGui::SameLine(); + ImGui::EndDisabled(); ImGui::Checkbox("Round", &settings.propertiesIsRound); + ImGui::BeginDisabled(!frame); ImGui::SetItemTooltip( "%s", "When toggled, decimal values will be snapped to their nearest whole value when changed."); diff --git a/src/imgui.cpp b/src/imgui.cpp index 3b6d13d..c3a3007 100644 --- a/src/imgui.cpp +++ b/src/imgui.cpp @@ -6,8 +6,12 @@ #include #include +using namespace anm2ed::types; +using namespace glm; + namespace anm2ed::imgui { + std::string chord_to_string(ImGuiKeyChord chord) { std::string result; @@ -71,14 +75,19 @@ namespace anm2ed::imgui ImGui::GetStyle().ItemSpacing.y * (itemCount); } - ImVec2 size_with_footer_get(int rowCount) + ImVec2 footer_size_get(int itemCount) + { + return ImVec2(ImGui::GetContentRegionAvail().x, footer_height_get(itemCount)); + } + + ImVec2 size_without_footer_get(int rowCount) { return ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - footer_height_get(rowCount)); } - ImVec2 child_size_get(int rowCount, bool isContentRegionAvail) + ImVec2 child_size_get(int rowCount) { - return ImVec2(isContentRegionAvail ? ImGui::GetContentRegionAvail().x : 0, + return ImVec2(ImGui::GetContentRegionAvail().x, (ImGui::GetFrameHeightWithSpacing() * rowCount) + (ImGui::GetStyle().WindowPadding.y * 2.0f)); } @@ -107,8 +116,13 @@ namespace anm2ed::imgui ImGui::Combo(label.c_str(), index, items.data(), (int)items.size()); } + void combo_strings(const std::string& label, int* index, std::vector& strings) + { + ImGui::Combo(label.c_str(), index, strings.data(), (int)strings.size()); + } + bool selectable_input_text(const std::string& label, const std::string& id, std::string& text, bool isSelected, - ImGuiSelectableFlags flags) + ImGuiSelectableFlags flags, bool* isRenamed) { static std::string editID{}; static bool isJustEdit{}; @@ -128,6 +142,7 @@ namespace anm2ed::imgui { editID.clear(); isActivated = true; + if (isRenamed) *isRenamed = true; } if (ImGui::IsItemDeactivatedAfterEdit() || ImGui::IsKeyPressed(ImGuiKey_Escape)) editID.clear(); } @@ -146,10 +161,9 @@ namespace anm2ed::imgui return isActivated; } - void set_item_tooltip_shortcut(const std::string& tooltip, const std::string& shortcut) + void set_item_tooltip_shortcut(const char* tooltip, const std::string& shortcut) { - auto text = shortcut.empty() ? tooltip : std::format("{}\n(Shortcut: {})", tooltip, shortcut); - ImGui::SetItemTooltip("%s", text.c_str()); + ImGui::SetItemTooltip("%s\n(Shortcut: %s)", tooltip, shortcut.c_str()); } void external_storage_set(ImGuiSelectionExternalStorage* self, int id, bool isSelected) @@ -219,17 +233,71 @@ namespace anm2ed::imgui return false; } - bool shortcut(std::string string, bool isSet, bool isGlobal, bool isPopupBlock) + bool shortcut(std::string string, shortcut::Type type) { - if (isPopupBlock && ImGui::GetTopMostPopupModal() != nullptr) return false; - auto flags = isGlobal ? ImGuiInputFlags_RouteGlobal : ImGuiInputFlags_RouteFocused; - - if (isSet) + if (ImGui::GetTopMostPopupModal() != nullptr) return false; + auto flags = type == shortcut::GLOBAL || type == shortcut::GLOBAL_SET ? ImGuiInputFlags_RouteGlobal + : ImGuiInputFlags_RouteFocused; + if (type == shortcut::GLOBAL_SET || type == shortcut::FOCUSED_SET) { ImGui::SetNextItemShortcut(string_to_chord(string), flags); - return true; + return false; } return ImGui::Shortcut(string_to_chord(string), flags); } + + MultiSelectStorage::MultiSelectStorage() + { + internal.AdapterSetItemSelected = external_storage_set; + } + + void MultiSelectStorage::user_data_set(std::set* userData) + { + internal.UserData = userData; + this->userData = userData; + } + + void MultiSelectStorage::begin(size_t size) + { + auto io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, userData ? userData->size() : 0, size); + internal.ApplyRequests(io); + } + + void MultiSelectStorage::end() + { + auto io = ImGui::EndMultiSelect(); + internal.ApplyRequests(io); + } + + PopupHelper::PopupHelper(const char* label, float percent, bool isNoHeight) + { + this->label = label; + this->percent = percent; + this->isNoHeight = isNoHeight; + } + + void PopupHelper::open() + { + isOpen = true; + isTriggered = true; + } + + void PopupHelper::trigger() + { + if (isTriggered) ImGui::OpenPopup(label); + isTriggered = false; + + auto viewport = ImGui::GetMainViewport(); + ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_None, to_imvec2(vec2(0.5f))); + if (isNoHeight) + ImGui::SetNextWindowSize(ImVec2(viewport->Size.x * percent, 0)); + else + ImGui::SetNextWindowSize(to_imvec2(to_vec2(viewport->Size) * percent)); + } + + void PopupHelper::close() + { + isOpen = false; + } } diff --git a/src/imgui.h b/src/imgui.h index 11f9d71..7206a54 100644 --- a/src/imgui.h +++ b/src/imgui.h @@ -1,12 +1,19 @@ #pragma once #include +#include #include #include #include +#include "types.h" + namespace anm2ed::imgui { + constexpr auto POPUP_TO_CONTENT = 0.0f; + constexpr auto POPUP_SMALL = 0.25f; + constexpr auto POPUP_NORMAL = 0.5f; + const std::unordered_map KEY_MAP = {{"A", ImGuiKey_A}, {"B", ImGuiKey_B}, {"C", ImGuiKey_C}, @@ -122,17 +129,46 @@ namespace anm2ed::imgui float row_widget_width_get(int count, float width = ImGui::GetContentRegionAvail().x); ImVec2 widget_size_with_row_get(int count, float width = ImGui::GetContentRegionAvail().x); float footer_height_get(int itemCount = 1); - ImVec2 size_with_footer_get(int rowCount = 1); - ImVec2 child_size_get(int rowCount = 1, bool isContentRegionAvail = false); + ImVec2 footer_size_get(int itemCount = 1); + ImVec2 size_without_footer_get(int rowCount = 1); + ImVec2 child_size_get(int rowCount = 1); int input_text_callback(ImGuiInputTextCallbackData* data); bool input_text_string(const char* label, std::string* string, ImGuiInputTextFlags flags = 0); void combo_strings(const std::string& label, int* index, std::vector& strings); + void combo_strings(const std::string& label, int* index, std::vector& strings); bool selectable_input_text(const std::string& label, const std::string& id, std::string& text, - bool isSelected = false, ImGuiSelectableFlags flags = 0); - void set_item_tooltip_shortcut(const std::string& tooltip, const std::string& shortcut = {}); + bool isSelected = false, ImGuiSelectableFlags flags = 0, bool* isRenamed = nullptr); + void set_item_tooltip_shortcut(const char* tooltip, const std::string& shortcut = {}); void external_storage_set(ImGuiSelectionExternalStorage* self, int id, bool isSelected); ImVec2 icon_size_get(); bool chord_held(ImGuiKeyChord chord); bool chord_repeating(ImGuiKeyChord chord, float delay = 0.125f, float rate = 0.025f); - bool shortcut(std::string string, bool isSet = false, bool isGlobal = false, bool isPopupBlock = true); + bool shortcut(std::string string, types::shortcut::Type type = types::shortcut::FOCUSED_SET); + + class MultiSelectStorage + { + public: + ImGuiSelectionExternalStorage internal{}; + std::set* userData{}; + + MultiSelectStorage(); + void user_data_set(std::set* userData); + void begin(size_t size); + void end(); + }; + + class PopupHelper + { + public: + const char* label{}; + bool isOpen{}; + bool isTriggered{}; + bool isNoHeight{}; + float percent{}; + + PopupHelper(const char* label, float percent = POPUP_NORMAL, bool isNoHeight = false); + void open(); + void trigger(); + void close(); + }; } \ No newline at end of file diff --git a/src/layers.cpp b/src/layers.cpp index 07536d9..a7b958a 100644 --- a/src/layers.cpp +++ b/src/layers.cpp @@ -2,80 +2,151 @@ #include -#include "imgui.h" +#include "util.h" -using namespace anm2ed::document_manager; +using namespace anm2ed::document; using namespace anm2ed::settings; using namespace anm2ed::resources; using namespace anm2ed::types; +using namespace anm2ed::util; namespace anm2ed::layers { - void Layers::update(DocumentManager& manager, Settings& settings, Resources& resources) + void Layers::update(Document& document, Settings& settings, Resources& resources) { + auto& anm2 = document.anm2; + auto& selection = document.selectedLayers; + auto& referenceLayer = document.referenceLayer; + + if (document.is_just_changed(change::LAYERS)) unusedLayerIDs = anm2.layers_unused(); + + storage.user_data_set(&selection); + + auto properties_popup_open = [&](int id = -1) + { + if (id == -1) + { + isAdd = true; + editLayer = anm2::Layer(); + } + else + editLayer = anm2.content.layers.at(id); + + propertiesPopup.open(); + }; + if (ImGui::Begin("Layers", &settings.windowIsLayers)) { - auto document = manager.get(); - anm2::Anm2& anm2 = document->anm2; - - auto& selection = document->selectedLayers; - storage.UserData = &selection; - storage.AdapterSetItemSelected = imgui::external_storage_set; - - auto childSize = imgui::size_with_footer_get(); + auto childSize = imgui::size_without_footer_get(); if (ImGui::BeginChild("##Layers Child", childSize, true)) { - ImGuiMultiSelectIO* io = - ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, selection.size(), anm2.content.layers.size()); - storage.ApplyRequests(io); + storage.begin(anm2.content.layers.size()); for (auto& [id, layer] : anm2.content.layers) { auto isSelected = selection.contains(id); + auto isReferenced = referenceLayer == id; ImGui::PushID(id); + ImGui::SetNextItemSelectionUserData(id); - imgui::selectable_input_text(std::format("#{} {}", id, layer.name), - std::format("###Document #{} Layer #{}", manager.selected, id), layer.name, - isSelected); + if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); + ImGui::Selectable(std::format("#{} {} (Spritesheet: #{})", id, layer.name, layer.spritesheetID).c_str(), + isSelected); + if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + { + referenceLayer = id; + properties_popup_open(id); + } + + if (isReferenced) ImGui::PopFont(); if (ImGui::BeginItemTooltip()) { ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); ImGui::TextUnformatted(layer.name.c_str()); - ImGui::TextUnformatted(std::format("ID: {}", id).c_str()); - ImGui::TextUnformatted(std::format("Spritesheet ID: {}", layer.spritesheetID).c_str()); ImGui::PopFont(); + ImGui::Text("ID: %d", id); + ImGui::Text("Spritesheet ID: %d", layer.spritesheetID); ImGui::EndTooltip(); } ImGui::PopID(); } - io = ImGui::EndMultiSelect(); - storage.ApplyRequests(io); + storage.end(); } ImGui::EndChild(); auto widgetSize = imgui::widget_size_with_row_get(2); - imgui::shortcut(settings.shortcutAdd, true); - ImGui::Button("Add", widgetSize); + imgui::shortcut(settings.shortcutAdd); + if (ImGui::Button("Add", widgetSize)) properties_popup_open(); imgui::set_item_tooltip_shortcut("Add a layer.", settings.shortcutAdd); ImGui::SameLine(); - std::set unusedLayersIDs = anm2.layers_unused(); - - imgui::shortcut(settings.shortcutRemove, true); - ImGui::BeginDisabled(unusedLayersIDs.empty()); + imgui::shortcut(settings.shortcutRemove); + ImGui::BeginDisabled(unusedLayerIDs.empty()); { if (ImGui::Button("Remove Unused", widgetSize)) - for (auto& id : unusedLayersIDs) + { + for (auto& id : unusedLayerIDs) anm2.content.layers.erase(id); + document.change(change::LAYERS); + unusedLayerIDs.clear(); + } } ImGui::EndDisabled(); imgui::set_item_tooltip_shortcut("Remove unused layers (i.e., ones not used in any animation.)", settings.shortcutRemove); } ImGui::End(); + + propertiesPopup.trigger(); + + if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto childSize = imgui::child_size_get(2); + auto& layer = editLayer; + + auto close = [&]() + { + isAdd = false; + editLayer = anm2::Layer(); + propertiesPopup.close(); + }; + + if (ImGui::BeginChild("Child", childSize, ImGuiChildFlags_Borders)) + { + imgui::input_text_string("Name", &layer.name); + ImGui::SetItemTooltip("Set the item's name."); + imgui::combo_strings("Spritesheet", &layer.spritesheetID, document.spritesheetNames); + ImGui::SetItemTooltip("Set the layer item's spritesheet."); + } + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + if (ImGui::Button(isAdd ? "Add" : "Confirm", widgetSize)) + { + if (isAdd) + { + auto id = map::next_id_get(anm2.content.layers); + anm2.content.layers[id] = editLayer; + referenceLayer = id; + } + else + anm2.content.layers[referenceLayer] = editLayer; + document.change(change::LAYERS); + close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) close(); + + ImGui::EndPopup(); + } + + referenceLayer = propertiesPopup.isOpen ? referenceLayer : -1; } } diff --git a/src/layers.h b/src/layers.h index 5007e68..ed1538f 100644 --- a/src/layers.h +++ b/src/layers.h @@ -1,17 +1,22 @@ #pragma once -#include "document_manager.h" +#include "document.h" #include "resources.h" #include "settings.h" +#include "imgui.h" + namespace anm2ed::layers { class Layers { - ImGuiSelectionExternalStorage storage{}; + bool isAdd{}; + imgui::PopupHelper propertiesPopup{imgui::PopupHelper("Layer Properties", imgui::POPUP_SMALL, true)}; + imgui::MultiSelectStorage storage; + anm2::Layer editLayer{}; + std::set unusedLayerIDs{}; public: - void update(document_manager::DocumentManager& manager, settings::Settings& settings, - resources::Resources& resources); + void update(document::Document& document, settings::Settings& settings, resources::Resources& resources); }; } \ No newline at end of file diff --git a/src/nulls.cpp b/src/nulls.cpp index 2d9f9a5..fd6eef4 100644 --- a/src/nulls.cpp +++ b/src/nulls.cpp @@ -2,74 +2,68 @@ #include -#include "imgui.h" - -using namespace anm2ed::document_manager; +using namespace anm2ed::document; using namespace anm2ed::settings; using namespace anm2ed::resources; using namespace anm2ed::types; namespace anm2ed::nulls { - void Nulls::update(DocumentManager& manager, Settings& settings, Resources& resources) + void Nulls::update(Document& document, int& documentIndex, Settings& settings, Resources& resources) { + auto& anm2 = document.anm2; + auto& selection = document.selectedNulls; + + if (document.is_just_changed(change::NULLS)) unusedNullsIDs = anm2.nulls_unused(); + + storage.user_data_set(&selection); + if (ImGui::Begin("Nulls", &settings.windowIsNulls)) { - auto document = manager.get(); - anm2::Anm2& anm2 = document->anm2; - - auto& selection = document->selectedNulls; - storage.UserData = &selection; - storage.AdapterSetItemSelected = imgui::external_storage_set; - - auto childSize = imgui::size_with_footer_get(); + auto childSize = imgui::size_without_footer_get(); if (ImGui::BeginChild("##Nulls Child", childSize, true)) { - ImGuiMultiSelectIO* io = - ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, selection.size(), anm2.content.nulls.size()); - storage.ApplyRequests(io); + storage.begin(anm2.content.nulls.size()); for (auto& [id, null] : anm2.content.nulls) { - const bool isSelected = selection.contains(id); + auto isSelected = selection.contains(id); ImGui::PushID(id); ImGui::SetNextItemSelectionUserData(id); imgui::selectable_input_text(std::format("#{} {}", id, null.name), - std::format("###Document #{} Null #{}", manager.selected, id), null.name, + std::format("###Document #{} Null #{}", documentIndex, id), null.name, isSelected); if (ImGui::BeginItemTooltip()) { ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); ImGui::TextUnformatted(null.name.c_str()); - ImGui::TextUnformatted(std::format("ID: {}", id).c_str()); ImGui::PopFont(); + ImGui::Text("ID: %d", id); ImGui::EndTooltip(); } ImGui::PopID(); } - io = ImGui::EndMultiSelect(); - storage.ApplyRequests(io); + storage.end(); } ImGui::EndChild(); auto widgetSize = imgui::widget_size_with_row_get(2); - imgui::shortcut(settings.shortcutAdd, true); + imgui::shortcut(settings.shortcutAdd); ImGui::Button("Add", widgetSize); imgui::set_item_tooltip_shortcut("Add a null.", settings.shortcutAdd); ImGui::SameLine(); - std::set unusedNullsIDs = anm2.nulls_unused(); - - imgui::shortcut(settings.shortcutRemove, true); + imgui::shortcut(settings.shortcutRemove); ImGui::BeginDisabled(unusedNullsIDs.empty()); { if (ImGui::Button("Remove Unused", widgetSize)) for (auto& id : unusedNullsIDs) anm2.content.nulls.erase(id); + document.change(change::NULLS); } ImGui::EndDisabled(); imgui::set_item_tooltip_shortcut("Remove unused nulls (i.e., ones not used in any animation.)", diff --git a/src/nulls.h b/src/nulls.h index a85bb6f..3acc7bb 100644 --- a/src/nulls.h +++ b/src/nulls.h @@ -1,6 +1,7 @@ #pragma once -#include "document_manager.h" +#include "document.h" +#include "imgui.h" #include "resources.h" #include "settings.h" @@ -8,10 +9,11 @@ namespace anm2ed::nulls { class Nulls { - ImGuiSelectionExternalStorage storage{}; + imgui::MultiSelectStorage storage{}; + std::set unusedNullsIDs{}; public: - void update(document_manager::DocumentManager& manager, settings::Settings& settings, + void update(document::Document& document, int& documentIndex, settings::Settings& settings, resources::Resources& resources); }; } \ No newline at end of file diff --git a/src/onionskin.cpp b/src/onionskin.cpp index 7064d6c..970aaf1 100644 --- a/src/onionskin.cpp +++ b/src/onionskin.cpp @@ -5,6 +5,7 @@ #include "imgui.h" using namespace anm2ed::settings; +using namespace anm2ed::types; using namespace glm; namespace anm2ed::onionskin @@ -23,7 +24,7 @@ namespace anm2ed::onionskin ImGui::PopID(); }; - imgui::shortcut(settings.shortcutOnionskin, true, true); + imgui::shortcut(settings.shortcutOnionskin); ImGui::Checkbox("Enabled", &settings.onionskinIsEnabled); order_configure("Before", settings.onionskinBeforeCount, settings.onionskinBeforeColor); @@ -36,7 +37,8 @@ namespace anm2ed::onionskin ImGui::RadioButton("After", &settings.onionskinDrawOrder, ABOVE); } - if (imgui::shortcut(settings.shortcutOnionskin)) settings.onionskinIsEnabled = !settings.onionskinIsEnabled; + if (imgui::shortcut(settings.shortcutOnionskin), shortcut::GLOBAL) + settings.onionskinIsEnabled = !settings.onionskinIsEnabled; ImGui::End(); } diff --git a/src/settings.h b/src/settings.h index 0197ee9..3fa327f 100644 --- a/src/settings.h +++ b/src/settings.h @@ -120,6 +120,8 @@ namespace anm2ed::settings X(BAKE_IS_ROUND_ROTATION, bakeIsRoundRotation, "Round Rotation", BOOL, true) \ \ X(TIMELINE_ADD_ITEM_TYPE, timelineAddItemType, "Add Item Type", INT, anm2::LAYER) \ + X(TIMELINE_ADD_ITEM_LOCALITY, timelineAddItemLocale, "Add Item Locale", INT, types::locale::GLOBAL) \ + X(TIMELINE_ADD_ITEM_SOURCE, timelineAddItemSource, "Add Item Source", INT, types::source::NEW) \ X(TIMELINE_IS_SHOW_UNUSED, timelineIsShowUnused, "##Show Unused", BOOL, true) \ \ X(ONIONSKIN_IS_ENABLED, onionskinIsEnabled, "Enabled", BOOL, false) \ diff --git a/src/spritesheets.cpp b/src/spritesheets.cpp index e5bbe52..5de52d5 100644 --- a/src/spritesheets.cpp +++ b/src/spritesheets.cpp @@ -1,35 +1,33 @@ #include "spritesheets.h" -#include - #include "imgui.h" #include "toast.h" -#include "types.h" +#include using namespace anm2ed::anm2; using namespace anm2ed::settings; using namespace anm2ed::resources; using namespace anm2ed::dialog; -using namespace anm2ed::document_manager; +using namespace anm2ed::document; using namespace anm2ed::types; using namespace anm2ed::toast; using namespace glm; namespace anm2ed::spritesheets { - void Spritesheets::update(DocumentManager& manager, Settings& settings, Resources& resources, Dialog& dialog) + void Spritesheets::update(Document& document, Settings& settings, Resources& resources, Dialog& dialog) { + auto& anm2 = document.anm2; + auto& selection = document.selectedSpritesheets; + + if (document.is_just_changed(change::SPRITESHEETS)) unusedSpritesheetIDs = anm2.spritesheets_unused(); + if (ImGui::Begin("Spritesheets", &settings.windowIsSpritesheets)) { - auto& document = *manager.get(); - auto& anm2 = document.anm2; - auto& selection = document.selectedSpritesheets; auto style = ImGui::GetStyle(); - static ImGuiSelectionExternalStorage storage{}; - storage.UserData = &selection; - storage.AdapterSetItemSelected = imgui::external_storage_set; + storage.user_data_set(&selection); - auto childSize = imgui::size_with_footer_get(2); + auto childSize = imgui::size_without_footer_get(2); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); @@ -37,12 +35,10 @@ namespace anm2ed::spritesheets { auto spritesheetChildSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() * 4); - ImGuiMultiSelectIO* io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, selection.size(), - anm2.content.spritesheets.size()); - storage.ApplyRequests(io); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2()); + storage.begin(anm2.content.spritesheets.size()); + for (auto& [id, spritesheet] : anm2.content.spritesheets) { ImGui::PushID(id); @@ -94,8 +90,8 @@ namespace anm2ed::spritesheets ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); ImGui::TextUnformatted(spritesheet.path.c_str()); ImGui::PopFont(); - ImGui::TextUnformatted(std::format("ID: {}", id).c_str()); - ImGui::TextUnformatted(std::format("Size: {} x {}", texture.size.x, texture.size.y).c_str()); + ImGui::Text("ID: %d", id); + ImGui::Text("Size: %d x %d", texture.size.x, texture.size.y); } ImGui::EndChild(); @@ -120,7 +116,7 @@ namespace anm2ed::spritesheets spritesheetChildSize.y - spritesheetChildSize.y / 2 - ImGui::GetTextLineHeight() / 2)); if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); - ImGui::TextUnformatted(std::format("#{} {}", id, spritesheet.path.string()).c_str()); + ImGui::Text(SPRITESHEET_FORMAT, id, spritesheet.path.c_str()); if (isReferenced) ImGui::PopFont(); } ImGui::EndChild(); @@ -128,8 +124,7 @@ namespace anm2ed::spritesheets ImGui::PopID(); } - io = ImGui::EndMultiSelect(); - storage.ApplyRequests(io); + storage.end(); ImGui::PopStyleVar(); } @@ -139,13 +134,16 @@ namespace anm2ed::spritesheets auto rowOneWidgetSize = imgui::widget_size_with_row_get(4); - imgui::shortcut(settings.shortcutAdd, true); + imgui::shortcut(settings.shortcutAdd); if (ImGui::Button("Add", rowOneWidgetSize)) dialog.spritesheet_open(); imgui::set_item_tooltip_shortcut("Add a new spritesheet.", settings.shortcutAdd); if (dialog.is_selected_file(dialog::SPRITESHEET_OPEN)) { - manager.spritesheet_add(dialog.path); + int id{}; + anm2.spritesheet_add(document.directory_get(), dialog.path, id); + selection = {id}; + document.change(change::SPRITESHEETS); dialog.reset(); } @@ -186,19 +184,19 @@ namespace anm2ed::spritesheets ImGui::SameLine(); - auto unused = anm2.spritesheets_unused(); - - ImGui::BeginDisabled(unused.empty()); + ImGui::BeginDisabled(unusedSpritesheetIDs.empty()); { - imgui::shortcut(settings.shortcutRemove, true); + imgui::shortcut(settings.shortcutRemove); if (ImGui::Button("Remove Unused", rowOneWidgetSize)) { - for (auto& id : unused) + for (auto& id : unusedSpritesheetIDs) { Spritesheet& spritesheet = anm2.content.spritesheets[id]; toasts.add(std::format("Removed spritesheet #{}: {}", id, spritesheet.path.string())); anm2.spritesheet_remove(id); } + unusedSpritesheetIDs.clear(); + document.change(change::SPRITESHEETS); } imgui::set_item_tooltip_shortcut("Remove all unused spritesheets (i.e., not used in any layer.).", settings.shortcutRemove); @@ -207,7 +205,7 @@ namespace anm2ed::spritesheets auto rowTwoWidgetSize = imgui::widget_size_with_row_get(3); - imgui::shortcut(settings.shortcutSelectAll, true); + imgui::shortcut(settings.shortcutSelectAll); ImGui::BeginDisabled(selection.size() == anm2.content.spritesheets.size()); { if (ImGui::Button("Select All", rowTwoWidgetSize)) @@ -219,13 +217,11 @@ namespace anm2ed::spritesheets ImGui::SameLine(); - imgui::shortcut(settings.shortcutSelectNone, true); + imgui::shortcut(settings.shortcutSelectNone); ImGui::BeginDisabled(selection.empty()); - { - if (ImGui::Button("Select None", rowTwoWidgetSize)) selection.clear(); - } - ImGui::EndDisabled(); + if (ImGui::Button("Select None", rowTwoWidgetSize)) selection.clear(); imgui::set_item_tooltip_shortcut("Unselect all spritesheets.", settings.shortcutSelectNone); + ImGui::EndDisabled(); ImGui::SameLine(); @@ -235,7 +231,8 @@ namespace anm2ed::spritesheets { for (auto& id : selection) { - if (Spritesheet& spritesheet = anm2.content.spritesheets[id]; spritesheet.save(document.directory_get())) + Spritesheet& spritesheet = anm2.content.spritesheets[id]; + if (spritesheet.save(document.directory_get())) toasts.add(std::format("Saved spritesheet #{}: {}", id, spritesheet.path.string())); else toasts.add(std::format("Unable to save spritesheet #{}: {}", id, spritesheet.path.string())); diff --git a/src/spritesheets.h b/src/spritesheets.h index dae06b8..7bed4ce 100644 --- a/src/spritesheets.h +++ b/src/spritesheets.h @@ -1,7 +1,8 @@ #pragma once #include "dialog.h" -#include "document_manager.h" +#include "document.h" +#include "imgui.h" #include "resources.h" #include "settings.h" @@ -9,8 +10,11 @@ namespace anm2ed::spritesheets { class Spritesheets { + imgui::MultiSelectStorage storage{}; + std::set unusedSpritesheetIDs{}; + public: - void update(document_manager::DocumentManager& manager, settings::Settings& settings, - resources::Resources& resources, dialog::Dialog& dialog); + void update(document::Document& document, settings::Settings& settings, resources::Resources& resources, + dialog::Dialog& dialog); }; } diff --git a/src/state.cpp b/src/state.cpp index b698828..2a247b6 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -60,10 +60,11 @@ namespace anm2ed::state ImGui::NewFrame(); taskbar.update(settings, dialog, manager, isQuit); - documents.update(taskbar, manager, resources); dockspace.update(taskbar, documents, manager, settings, resources, dialog, playback); toasts.update(); + documents.update(taskbar, manager, resources); + ImGui::GetStyle().FontScaleMain = settings.displayScale; SDL_GetWindowSize(window, &settings.windowSize.x, &settings.windowSize.y); } diff --git a/src/taskbar.cpp b/src/taskbar.cpp index 2ef70d8..a769476 100644 --- a/src/taskbar.cpp +++ b/src/taskbar.cpp @@ -4,12 +4,10 @@ #include #include "imgui.h" -#include "types.h" using namespace anm2ed::settings; using namespace anm2ed::dialog; using namespace anm2ed::document_manager; -using namespace anm2ed::imgui; using namespace anm2ed::types; namespace anm2ed::taskbar @@ -91,41 +89,25 @@ namespace anm2ed::taskbar if (ImGui::BeginMenu("Settings")) { - if (ImGui::MenuItem("Configure")) isOpenConfigurePopup = true; + if (ImGui::MenuItem("Configure")) configurePopup.open(); ImGui::EndMenu(); } if (ImGui::BeginMenu("Help")) { - if (ImGui::MenuItem("About")) isOpenAboutPopup = true; + if (ImGui::MenuItem("About")) aboutPopup.open(); ImGui::EndMenu(); } ImGui::EndMainMenuBar(); } - if (isOpenAboutPopup) + configurePopup.trigger(); + + if (ImGui::BeginPopupModal(configurePopup.label, &configurePopup.isOpen, ImGuiWindowFlags_NoResize)) { - ImGui::OpenPopup("About"); - isOpenAboutPopup = false; - } - - if (isOpenConfigurePopup) - { - ImGui::OpenPopup("Configure"); - editSettings = settings; - isOpenConfigurePopup = false; - } - - auto viewport = ImGui::GetMainViewport(); - - ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_None, ImVec2(0.5f, 0.5f)); - ImGui::SetNextWindowSize(to_imvec2(to_vec2(viewport->Size) * 0.5f)); - - if (ImGui::BeginPopupModal("Configure", nullptr, ImGuiWindowFlags_NoResize)) - { - auto childSize = imgui::size_with_footer_get(2); + auto childSize = imgui::size_without_footer_get(2); if (ImGui::BeginTabBar("##Configure Tabs")) { @@ -230,7 +212,7 @@ namespace anm2ed::taskbar if (ImGui::Button("Save", widgetSize)) { settings = editSettings; - ImGui::CloseCurrentPopup(); + configurePopup.close(); } ImGui::SetItemTooltip("Use the configured settings."); @@ -247,12 +229,11 @@ namespace anm2ed::taskbar ImGui::EndPopup(); } - ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_None, ImVec2(0.5f, 0.5f)); - ImGui::SetNextWindowSize(to_imvec2(to_vec2(viewport->Size) * 0.5f)); + aboutPopup.trigger(); - if (ImGui::BeginPopupModal("About", nullptr, ImGuiWindowFlags_NoResize)) + if (ImGui::BeginPopupModal(aboutPopup.label, &aboutPopup.isOpen, ImGuiWindowFlags_NoResize)) { - if (ImGui::Button("Close")) ImGui::CloseCurrentPopup(); + if (ImGui::Button("Close")) aboutPopup.close(); ImGui::EndPopup(); } diff --git a/src/taskbar.h b/src/taskbar.h index 146c0c6..257b5aa 100644 --- a/src/taskbar.h +++ b/src/taskbar.h @@ -2,16 +2,17 @@ #include "dialog.h" #include "document_manager.h" +#include "imgui.h" #include "settings.h" namespace anm2ed::taskbar { class Taskbar { - bool isOpenConfigurePopup{}; - bool isOpenAboutPopup{}; - int selectedShortcut{-1}; + imgui::PopupHelper configurePopup{imgui::PopupHelper("Configure")}; + imgui::PopupHelper aboutPopup{imgui::PopupHelper("About")}; settings::Settings editSettings{}; + int selectedShortcut{}; public: float height{}; diff --git a/src/timeline.cpp b/src/timeline.cpp index 0b965a1..ef50288 100644 --- a/src/timeline.cpp +++ b/src/timeline.cpp @@ -68,7 +68,8 @@ namespace anm2ed::timeline color = isActive ? ROOT_COLOR_ACTIVE : ROOT_COLOR; break; case anm2::LAYER: - label = std::format("#{} {}", id, anm2.content.layers[id].name); + label = std::format("#{} {} (Spritesheet: #{})", id, anm2.content.layers.at(id).name, + anm2.content.layers[id].spritesheetID); icon = icon::LAYER; color = isActive ? LAYER_COLOR_ACTIVE : LAYER_COLOR; break; @@ -165,10 +166,12 @@ namespace anm2ed::timeline ImGui::SetCursorPos(cursorPos); + ImGui::BeginDisabled(); ImGui::Text("(?)"); ImGui::SetItemTooltip("%s", std::format(HELP_FORMAT, settings.shortcutNextFrame, settings.shortcutPreviousFrame, settings.shortcutShortenFrame, settings.shortcutExtendFrame) .c_str()); + ImGui::EndDisabled(); } } ImGui::EndChild(); @@ -177,9 +180,11 @@ namespace anm2ed::timeline index++; } - void Timeline::items_child(anm2::Anm2& anm2, anm2::Reference& reference, anm2::Animation* animation, - Settings& settings, Resources& resources) + void Timeline::items_child(Document& document, anm2::Animation* animation, Settings& settings, Resources& resources) { + auto& anm2 = document.anm2; + auto& reference = document.reference; + auto itemsChildSize = ImVec2(ImGui::GetTextLineHeightWithSpacing() * 15, ImGui::GetContentRegionAvail().y); if (ImGui::BeginChild("##Items Child", itemsChildSize, ImGuiChildFlags_Borders)) @@ -250,13 +255,24 @@ namespace anm2ed::timeline auto widgetSize = imgui::widget_size_with_row_get(2); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + ImGui::BeginDisabled(!animation); { - ImGui::Button("Add", widgetSize); + if (ImGui::Button("Add", widgetSize)) propertiesPopup.open(); + ImGui::SetItemTooltip("%s", "Add a new item to the animation."); ImGui::SameLine(); - ImGui::Button("Remove", widgetSize); + + ImGui::BeginDisabled(document.item_get()); + { + ImGui::Button("Remove", widgetSize); + ImGui::SetItemTooltip("%s", "Remove the selected items from the animation."); + } + ImGui::EndDisabled(); } ImGui::EndDisabled(); + + ImGui::PopStyleVar(); } ImGui::EndChild(); } @@ -317,10 +333,6 @@ namespace anm2ed::timeline colorActiveHidden = to_imvec4(to_vec4(colorActive) * COLOR_HIDDEN_MULTIPLIER); colorHoveredHidden = to_imvec4(to_vec4(colorHovered) * COLOR_HIDDEN_MULTIPLIER); - ImGui::PushStyleColor(ImGuiCol_Button, isVisible ? color : colorHidden); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, isVisible ? colorActive : colorActiveHidden); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, isVisible ? colorHovered : colorHoveredHidden); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); if (ImGui::BeginChild("##Frames Child", childSize, ImGuiChildFlags_Borders)) @@ -420,11 +432,10 @@ namespace anm2ed::timeline { anm2::Reference frameReference = {reference.animationIndex, type, id, (int)i}; auto isSelected = baseReference == frameReference; + auto isFrameVisible = isVisible && frame.isVisible; frameTime += frame.delay; - if (isSelected) ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive)); - ImGui::PushID(i); auto size = ImVec2(frameSize.x * frame.delay, frameSize.y); @@ -435,12 +446,11 @@ namespace anm2ed::timeline if (type == anm2::TRIGGER) ImGui::SetCursorPos(ImVec2(cursorPos.x + frameSize.x * frame.atFrame, cursorPos.y)); - if (!frame.isVisible) - { - ImGui::PushStyleColor(ImGuiCol_Button, colorHidden); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, colorActiveHidden); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colorHoveredHidden); - } + ImGui::PushStyleColor(ImGuiCol_Button, isFrameVisible ? color : colorHidden); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, isFrameVisible ? colorActive : colorActiveHidden); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, isFrameVisible ? colorHovered : colorHoveredHidden); + + if (isSelected) ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive)); if (ImGui::Button("##Frame Button", size)) { @@ -451,7 +461,8 @@ namespace anm2ed::timeline } if (type != anm2::TRIGGER) ImGui::SameLine(); - if (!frame.isVisible) ImGui::PopStyleColor(3); + ImGui::PopStyleColor(3); + if (isSelected) ImGui::PopStyleColor(); auto imageMin = ImVec2(ImGui::GetItemRectMin().x, ImGui::GetItemRectMax().y - (ImGui::GetItemRectSize().y / 2) - (imageSize.y / 2)); @@ -459,15 +470,12 @@ namespace anm2ed::timeline drawList->AddImage(resources.icons[icon].id, imageMin, imageMax); - if (isSelected) ImGui::PopStyleColor(); - ImGui::PopID(); } } } ImGui::EndChild(); ImGui::PopStyleVar(); - ImGui::PopStyleColor(3); index++; ImGui::PopID(); @@ -600,19 +608,19 @@ namespace anm2ed::timeline auto label = playback.isPlaying ? "Pause" : "Play"; auto tooltip = playback.isPlaying ? "Pause the animation." : "Play the animation."; - imgui::shortcut(settings.shortcutPlayPause, true); + imgui::shortcut(settings.shortcutPlayPause); if (ImGui::Button(label, widgetSize)) playback.toggle(); imgui::set_item_tooltip_shortcut(tooltip, settings.shortcutPlayPause); ImGui::SameLine(); - imgui::shortcut(settings.shortcutAdd, true); + imgui::shortcut(settings.shortcutAdd); ImGui::Button("Insert Frame", widgetSize); imgui::set_item_tooltip_shortcut("Insert a frame, based on the current selection.", settings.shortcutAdd); ImGui::SameLine(); - imgui::shortcut(settings.shortcutRemove, true); + imgui::shortcut(settings.shortcutRemove); ImGui::Button("Delete Frame", widgetSize); imgui::set_item_tooltip_shortcut("Delete the selected frames.", settings.shortcutRemove); @@ -662,6 +670,187 @@ namespace anm2ed::timeline ImGui::SetCursorPos(cursorPos); } + void Timeline::popups(Document& document, anm2::Animation* animation, Settings& settings) + { + auto item_properties_reset = [&]() + { + addItemName.clear(); + addItemSpritesheetID = {}; + addItemID = -1; + isUnusedItemsSet = false; + }; + + auto& anm2 = document.anm2; + auto& reference = document.reference; + + propertiesPopup.trigger(); + + if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto item_properties_close = [&]() + { + item_properties_reset(); + propertiesPopup.close(); + }; + + auto& type = settings.timelineAddItemType; + auto& locale = settings.timelineAddItemLocale; + auto& source = settings.timelineAddItemSource; + + if (!isUnusedItemsSet) + { + unusedItems = type == anm2::LAYER ? anm2.layers_unused(reference) + : type == anm2::NULL_ ? anm2.nulls_unused(reference) + : std::set{}; + + isUnusedItemsSet = true; + } + + auto footerSize = imgui::footer_size_get(); + auto optionsSize = imgui::child_size_get(11); + auto itemsSize = ImVec2(0, ImGui::GetContentRegionAvail().y - + (optionsSize.y + footerSize.y + ImGui::GetStyle().ItemSpacing.y * 4)); + + if (ImGui::BeginChild("Options", optionsSize, ImGuiChildFlags_Borders)) + { + ImGui::SeparatorText("Type"); + + auto size = ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, ImGui::GetFrameHeightWithSpacing()); + + if (ImGui::BeginChild("Type Layer", size)) + { + ImGui::RadioButton("Layer", &type, anm2::LAYER); + ImGui::SetItemTooltip("Layers are a basic visual element in an animation, used for displaying spritesheets."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("Type Null", size)) + { + ImGui::RadioButton("Null", &type, anm2::NULL_); + ImGui::SetItemTooltip( + "Nulls are invisible elements in an animation, used for interfacing with a game engine."); + } + ImGui::EndChild(); + + ImGui::SeparatorText("Source"); + + bool isNewOnly = unusedItems.empty(); + if (isNewOnly) source = source::NEW; + + if (ImGui::BeginChild("Source New", size)) + { + ImGui::RadioButton("New", &source, source::NEW); + ImGui::SetItemTooltip("Create a new item to be used."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("Source Existing", size)) + { + ImGui::BeginDisabled(isNewOnly); + ImGui::RadioButton("Existing", &source, source::EXISTING); + ImGui::EndDisabled(); + ImGui::SetItemTooltip("Use a pre-existing, presently unused item."); + } + ImGui::EndChild(); + + ImGui::SeparatorText("Locale"); + + if (ImGui::BeginChild("Locale Global", size)) + { + ImGui::RadioButton("Global", &locale, locale::GLOBAL); + ImGui::SetItemTooltip("The item will be inserted into all animations, if not already present."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("Locale Local", size)) + { + ImGui::RadioButton("Local", &locale, locale::LOCAL); + ImGui::SetItemTooltip("The item will only be inserted into this animation."); + } + ImGui::EndChild(); + + ImGui::SeparatorText("Options"); + + ImGui::BeginDisabled(source == source::EXISTING); + { + imgui::input_text_string("Name", &addItemName); + ImGui::SetItemTooltip("Set the item's name."); + ImGui::BeginDisabled(type != anm2::LAYER); + { + auto spritesheets = anm2.spritesheet_names_get(); + imgui::combo_strings("Spritesheet", &addItemSpritesheetID, spritesheets); + ImGui::SetItemTooltip("Set the layer item's spritesheet."); + } + ImGui::EndDisabled(); + } + ImGui::EndDisabled(); + } + ImGui::EndChild(); + + if (ImGui::BeginChild("Items", itemsSize, ImGuiChildFlags_Borders)) + { + if (animation && source == source::EXISTING) + { + for (auto id : unusedItems) + { + auto isSelected = addItemID == id; + + ImGui::PushID(id); + + if (type == anm2::LAYER) + { + auto& layer = anm2.content.layers[id]; + if (ImGui::Selectable( + std::format("#{} {} (Spritesheet: #{})", id, layer.name, layer.spritesheetID).c_str(), + isSelected)) + addItemID = id; + } + else if (type == anm2::NULL_) + { + auto& null = anm2.content.nulls[id]; + if (ImGui::Selectable(std::format("#{} {}", id, null.name).c_str(), isSelected)) addItemID = id; + } + + ImGui::PopID(); + } + } + } + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + if (ImGui::Button("Add", widgetSize)) + { + anm2::Reference addReference; + + if (type == anm2::LAYER) + addReference = anm2.layer_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName, + addItemSpritesheetID, (locale::Type)locale); + else if (type == anm2::NULL_) + addReference = + anm2.null_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName, (locale::Type)locale); + + reference = addReference; + + item_properties_close(); + } + ImGui::SetItemTooltip("Add the item, with the settings specified."); + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) item_properties_close(); + ImGui::SetItemTooltip("Cancel adding an item."); + + ImGui::EndPopup(); + } + } + void Timeline::update(DocumentManager& manager, Settings& settings, Resources& resources, Playback& playback) { auto& document = *manager.get(); @@ -676,20 +865,28 @@ namespace anm2ed::timeline { isWindowHovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); frames_child(document, animation, settings, resources, playback); - items_child(anm2, reference, animation, settings, resources); + items_child(document, animation, settings, resources); } ImGui::PopStyleVar(); ImGui::End(); - if (imgui::shortcut(settings.shortcutPlayPause, false, true)) playback.toggle(); + popups(document, animation, settings); + + if (imgui::shortcut(settings.shortcutPlayPause, shortcut::GLOBAL)) playback.toggle(); if (animation) { if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutPreviousFrame))) - playback.decrement(animation->frameNum); + { + playback.decrement(settings.playbackIsClampPlayhead ? animation->frameNum : anm2::FRAME_NUM_MAX); + reference.frameTime = playback.time; + } if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutNextFrame))) - playback.increment(animation->frameNum); + { + playback.increment(settings.playbackIsClampPlayhead ? animation->frameNum : anm2::FRAME_NUM_MAX); + reference.frameTime = playback.time; + } } if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutShortenFrame))) diff --git a/src/timeline.h b/src/timeline.h index 5b32711..799a6e7 100644 --- a/src/timeline.h +++ b/src/timeline.h @@ -3,6 +3,7 @@ #include "anm2.h" #include "document.h" #include "document_manager.h" +#include "imgui.h" #include "playback.h" #include "resources.h" #include "settings.h" @@ -14,20 +15,29 @@ namespace anm2ed::timeline bool isDragging{}; bool isWindowHovered{}; bool isHorizontalScroll{}; + imgui::PopupHelper propertiesPopup{imgui::PopupHelper("Item Properties")}; + std::string addItemName{}; + int addItemSpritesheetID{}; + bool addItemIsRect{}; + int addItemID{-1}; + bool isUnusedItemsSet{}; + std::set unusedItems{}; glm::vec2 scroll{}; ImDrawList* pickerLineDrawList{}; ImGuiStyle style{}; void item_child(anm2::Anm2& anm2, anm2::Reference& reference, anm2::Animation* animation, settings::Settings& settings, resources::Resources& resources, anm2::Type type, int id, int& index); - void items_child(anm2::Anm2& anm2, anm2::Reference& reference, anm2::Animation* animation, - settings::Settings& settings, resources::Resources& resources); + void items_child(Document& document, anm2::Animation* animation, settings::Settings& settings, + resources::Resources& resources); void frame_child(document::Document& document, anm2::Animation* animation, settings::Settings& settings, resources::Resources& resources, playback::Playback& playback, anm2::Type type, int id, int& index, float width); void frames_child(document::Document& document, anm2::Animation* animation, settings::Settings& settings, resources::Resources& resources, playback::Playback& playback); + void popups(document::Document& document, anm2::Animation* animation, settings::Settings& settings); + public: void update(document_manager::DocumentManager& manager, settings::Settings& settings, resources::Resources& resources, playback::Playback& playback); diff --git a/src/tools.cpp b/src/tools.cpp index 09eb1db..3e32d0f 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -55,7 +55,7 @@ namespace anm2ed::tools auto member = SHORTCUT_MEMBERS[info.shortcut]; - if (imgui::shortcut(settings.*member, false, true, i == tool::COLOR ? false : true)) tool_switch((tool::Type)i); + if (imgui::shortcut(settings.*member, shortcut::GLOBAL_SET)) tool_switch((tool::Type)i); if (i == tool::COLOR) { diff --git a/src/types.h b/src/types.h index a22daa7..a4b7b82 100644 --- a/src/types.h +++ b/src/types.h @@ -4,6 +4,50 @@ #include #include +namespace anm2ed::types::change +{ + enum Type + { + LAYERS, + NULLS, + SPRITESHEETS, + EVENTS, + ANIMATIONS, + ITEMS, + FRAMES, + COUNT + }; +} + +namespace anm2ed::types::shortcut +{ + enum Type + { + FOCUSED, + GLOBAL, + FOCUSED_SET, + GLOBAL_SET + }; +} + +namespace anm2ed::types::locale +{ + enum Type + { + LOCAL, + GLOBAL + }; +} + +namespace anm2ed::types::source +{ + enum Type + { + NEW, + EXISTING + }; +} + namespace anm2ed::types::merge { enum Type From fe9366f9ef6697de9862d805df2bc6ed1a4a6370 Mon Sep 17 00:00:00 2001 From: shweet Date: Sun, 26 Oct 2025 00:10:44 -0400 Subject: [PATCH 07/15] context menus, document refactoring, fixes --- src/animation_preview.cpp | 64 ++++-- src/animation_preview.h | 8 +- src/animations.cpp | 189 +++++++++-------- src/animations.h | 12 +- src/anm2.cpp | 336 ++++++++++++++++++++++++++++- src/anm2.h | 116 +++++----- src/canvas.h | 24 +-- src/clipboard.cpp | 25 +++ src/clipboard.h | 14 ++ src/dialog.h | 6 +- src/dockspace.cpp | 23 +- src/dockspace.h | 5 +- src/document.cpp | 423 ++++++++++++++++++++++++++++++++++--- src/document.h | 101 +++++++-- src/document_manager.cpp | 58 ----- src/document_manager.h | 27 --- src/documents.cpp | 7 +- src/documents.h | 4 +- src/events.cpp | 91 +++++--- src/events.h | 9 +- src/filesystem.h | 8 +- src/font.h | 6 +- src/frame_properties.cpp | 4 +- src/frame_properties.h | 6 +- src/icon.h | 4 +- src/imgui.cpp | 18 +- src/imgui.h | 60 +++--- src/layers.cpp | 146 +++++++------ src/layers.h | 15 +- src/loader.h | 2 +- src/log.h | 14 +- src/manager.cpp | 120 +++++++++++ src/manager.h | 40 ++++ src/math.h | 17 +- src/nulls.cpp | 129 +++++++++-- src/nulls.h | 10 +- src/onionskin.cpp | 14 +- src/onionskin.h | 8 +- src/playback.h | 10 +- src/settings.h | 4 +- src/shader.h | 31 +-- src/snapshots.cpp | 68 ++++++ src/snapshots.h | 42 ++++ src/spritesheet_editor.cpp | 4 +- src/spritesheet_editor.h | 5 +- src/spritesheets.cpp | 164 +++++++++----- src/spritesheets.h | 11 +- src/state.cpp | 23 +- src/state.h | 14 +- src/taskbar.cpp | 10 +- src/taskbar.h | 7 +- src/texture.cpp | 54 +++-- src/texture.h | 23 +- src/timeline.cpp | 166 ++++++++++----- src/timeline.h | 27 +-- src/toast.cpp | 10 +- src/toast.h | 7 +- src/tools.cpp | 11 +- src/tools.h | 3 +- src/types.h | 10 + src/util.h | 53 ++++- src/xml.h | 11 +- 62 files changed, 2138 insertions(+), 793 deletions(-) create mode 100644 src/clipboard.cpp create mode 100644 src/clipboard.h delete mode 100644 src/document_manager.cpp delete mode 100644 src/document_manager.h create mode 100644 src/manager.cpp create mode 100644 src/manager.h create mode 100644 src/snapshots.cpp create mode 100644 src/snapshots.h diff --git a/src/animation_preview.cpp b/src/animation_preview.cpp index 17be4b5..8db80c7 100644 --- a/src/animation_preview.cpp +++ b/src/animation_preview.cpp @@ -7,7 +7,7 @@ #include "tool.h" #include "types.h" -using namespace anm2ed::document_manager; +using namespace anm2ed::manager; using namespace anm2ed::settings; using namespace anm2ed::canvas; using namespace anm2ed::playback; @@ -17,6 +17,7 @@ using namespace glm; namespace anm2ed::animation_preview { + constexpr auto NULL_COLOR = vec4(0.0f, 0.0f, 1.0f, 0.90f); constexpr auto TARGET_SIZE = vec2(32, 32); constexpr auto PIVOT_SIZE = vec2(8, 8); constexpr auto POINT_SIZE = vec2(4, 4); @@ -27,10 +28,11 @@ namespace anm2ed::animation_preview { } - void AnimationPreview::update(DocumentManager& manager, Settings& settings, Resources& resources, Playback& playback) + void AnimationPreview::update(Manager& manager, Settings& settings, Resources& resources) { auto& document = *manager.get(); auto& anm2 = document.anm2; + auto& playback = document.playback; auto& reference = document.reference; auto animation = document.animation_get(); auto& pan = document.previewPan; @@ -143,12 +145,10 @@ namespace anm2ed::animation_preview if (isAxes) axes_render(shaderAxes, zoom, pan, axesColor); if (isGrid) grid_render(shaderGrid, zoom, pan, gridSize, gridOffset, gridColor); - auto frameTime = reference.frameTime > -1 && !playback.isPlaying ? reference.frameTime : playback.time; - - if (animation) + auto render = [&](float time, vec3 colorOffset = {}, float alphaOffset = {}, bool isOnionskin = false) { auto transform = transform_get(zoom, pan); - auto root = animation->rootAnimation.frame_generate(playback.time, anm2::ROOT); + auto root = animation->rootAnimation.frame_generate(time, anm2::ROOT); if (isRootTransform) transform *= math::quad_model_parent_get(root.position, {}, math::percent_to_unit(root.scale), root.rotation); @@ -158,7 +158,9 @@ namespace anm2ed::animation_preview auto rootTransform = transform * math::quad_model_get(TARGET_SIZE, root.position, TARGET_SIZE * 0.5f, math::percent_to_unit(root.scale), root.rotation); - texture_render(shaderTexture, resources.icons[icon::TARGET].id, rootTransform, color::GREEN); + vec4 color = isOnionskin ? vec4(colorOffset, alphaOffset) : color::GREEN; + + texture_render(shaderTexture, resources.icons[icon::TARGET].id, rootTransform, color); } for (auto& id : animation->layerOrder) @@ -168,7 +170,7 @@ namespace anm2ed::animation_preview auto& layer = anm2.content.layers.at(id); - if (auto frame = layerAnimation.frame_generate(frameTime, anm2::LAYER); frame.isVisible) + if (auto frame = layerAnimation.frame_generate(time, anm2::LAYER); frame.isVisible) { auto spritesheet = anm2.spritesheet_get(layer.spritesheetID); if (!spritesheet) continue; @@ -183,17 +185,23 @@ namespace anm2ed::animation_preview auto uvMin = frame.crop / vec2(texture.size) + inset; auto uvMax = (frame.crop + frame.size) / vec2(texture.size) - inset; auto vertices = math::uv_vertices_get(uvMin, uvMax); + vec3 frameColorOffset = frame.offset + colorOffset; + vec4 frameTint = frame.tint; + frameTint.a = std::max(0.0f, frameTint.a - alphaOffset); - texture_render(shaderTexture, texture.id, layerTransform, frame.tint, frame.offset, vertices.data()); + texture_render(shaderTexture, texture.id, layerTransform, frameTint, frameColorOffset, vertices.data()); - if (isBorder) rect_render(shaderLine, layerTransform, color::RED); + auto color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : color::RED; + + if (isBorder) rect_render(shaderLine, layerTransform, color); if (isPivots) { auto pivotTransform = transform * math::quad_model_get(PIVOT_SIZE, frame.position, PIVOT_SIZE * 0.5f, math::percent_to_unit(frame.scale), frame.rotation); - texture_render(shaderTexture, resources.icons[icon::PIVOT].id, pivotTransform, color::RED); + + texture_render(shaderTexture, resources.icons[icon::PIVOT].id, pivotTransform, color); } } } @@ -206,11 +214,13 @@ namespace anm2ed::animation_preview auto& isShowRect = anm2.content.nulls[id].isShowRect; - if (auto frame = nullAnimation.frame_generate(frameTime, anm2::NULL_); frame.isVisible) + if (auto frame = nullAnimation.frame_generate(time, anm2::NULL_); frame.isVisible) { auto icon = isShowRect ? icon::POINT : icon::TARGET; auto& size = isShowRect ? POINT_SIZE : TARGET_SIZE; - auto& color = id == reference.itemID && reference.itemType == anm2::NULL_ ? color::RED : color::BLUE; + auto color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) + : id == reference.itemID && reference.itemType == anm2::NULL_ ? color::RED + : NULL_COLOR; auto nullTransform = transform * math::quad_model_get(size, frame.position, size * 0.5f, math::percent_to_unit(frame.scale), frame.rotation); @@ -228,6 +238,34 @@ namespace anm2ed::animation_preview } } } + }; + + auto onionskin_render = [&](float time, int count, int direction, vec3 color) + { + for (int i = 1; i <= count; i++) + { + float useTime = time + (float)(direction * i); + float alphaOffset = (1.0f / (count + 1)) * i; + render(useTime, color, alphaOffset, true); + } + }; + + auto onionskins_render = [&](float time) + { + onionskin_render(time, settings.onionskinBeforeCount, -1, settings.onionskinBeforeColor); + onionskin_render(time, settings.onionskinAfterCount, 1, settings.onionskinAfterColor); + }; + + auto frameTime = reference.frameTime > -1 && !playback.isPlaying ? reference.frameTime : playback.time; + + if (animation) + { + auto& drawOrder = settings.onionskinDrawOrder; + auto& isEnabled = settings.onionskinIsEnabled; + + if (drawOrder == draw_order::BELOW && isEnabled) onionskins_render(frameTime); + render(frameTime); + if (drawOrder == draw_order::ABOVE && isEnabled) onionskins_render(frameTime); } unbind(); diff --git a/src/animation_preview.h b/src/animation_preview.h index 278c7eb..ef490dd 100644 --- a/src/animation_preview.h +++ b/src/animation_preview.h @@ -1,8 +1,7 @@ #pragma once #include "canvas.h" -#include "document_manager.h" -#include "playback.h" +#include "manager.h" #include "resources.h" #include "settings.h" @@ -15,7 +14,6 @@ namespace anm2ed::animation_preview public: AnimationPreview(); - void update(document_manager::DocumentManager& manager, settings::Settings& settings, - resources::Resources& resources, playback::Playback& playback); + void update(manager::Manager&, settings::Settings&, resources::Resources&); }; -} \ No newline at end of file +} diff --git a/src/animations.cpp b/src/animations.cpp index 73e7baf..9d2b208 100644 --- a/src/animations.cpp +++ b/src/animations.cpp @@ -1,21 +1,24 @@ #include "animations.h" -#include #include -using namespace anm2ed::document; +using namespace anm2ed::clipboard; +using namespace anm2ed::manager; using namespace anm2ed::settings; using namespace anm2ed::resources; using namespace anm2ed::types; namespace anm2ed::animations { - void Animations::update(Document& document, int& documentIndex, Settings& settings, Resources& resources) + void Animations::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) { + auto& document = *manager.get(); auto& anm2 = document.anm2; auto& reference = document.reference; - auto& selection = document.selectedAnimations; - storage.user_data_set(&selection); + auto& hovered = document.hoveredAnimation; + auto& multiSelect = document.animationMultiSelect; + auto& mergeMultiSelect = document.animationMergeMultiSelect; + auto& mergeTarget = document.mergeTarget; if (ImGui::Begin("Animations", &settings.windowIsAnimations)) { @@ -23,7 +26,7 @@ namespace anm2ed::animations if (ImGui::BeginChild("##Animations Child", childSize, ImGuiChildFlags_Borders)) { - storage.begin(anm2.animations.items.size()); + multiSelect.start(anm2.animations.items.size()); for (auto [i, animation] : std::views::enumerate(anm2.animations.items)) { @@ -31,7 +34,6 @@ namespace anm2ed::animations auto isDefault = anm2.animations.defaultAnimation == animation.name; auto isReferenced = reference.animationIndex == i; - auto isSelected = selection.contains(i); auto font = isDefault && isReferenced ? font::BOLD_ITALICS : isDefault ? font::BOLD @@ -41,9 +43,10 @@ namespace anm2ed::animations ImGui::PushFont(resources.fonts[font].get(), font::SIZE); ImGui::SetNextItemSelectionUserData(i); if (imgui::selectable_input_text(animation.name, - std::format("###Document #{} Animation #{}", documentIndex, i), - animation.name, isSelected)) - if (!isReferenced) reference = {(int)i}; + std::format("###Document #{} Animation #{}", manager.selected, i), + animation.name, multiSelect.contains(i))) + reference = {(int)i}; + if (ImGui::IsItemHovered()) hovered = i; ImGui::PopFont(); if (ImGui::BeginItemTooltip()) @@ -68,10 +71,11 @@ namespace anm2ed::animations if (ImGui::BeginDragDropSource()) { - std::vector sorted = {}; - ImGui::SetDragDropPayload("Animation Drag Drop", sorted.data(), sorted.size() * sizeof(int)); - for (auto& index : sorted) - ImGui::TextUnformatted(anm2.animations.items[index].name.c_str()); + static std::vector selection; + selection.assign(multiSelect.begin(), multiSelect.end()); + ImGui::SetDragDropPayload("Animation Drag Drop", selection.data(), selection.size() * sizeof(int)); + for (auto& i : selection) + ImGui::TextUnformatted(anm2.animations.items[i].name.c_str()); ImGui::EndDragDropSource(); } @@ -79,16 +83,11 @@ namespace anm2ed::animations { if (auto payload = ImGui::AcceptDragDropPayload("Animation Drag Drop")) { - auto count = payload->DataSize / sizeof(int); - auto data = (int*)(payload->Data); - std::vector indices(data, data + count); - //std::vector destinationIndices = vector::indices_move(anm2.animations.items, indices, i); - - selection.clear(); - /* - for (const auto& index : destinationIndices) - selection.insert((int)index); - */ + auto payloadIndices = (int*)(payload->Data); + auto payloadCount = payload->DataSize / sizeof(int); + std::vector indices(payloadIndices, payloadIndices + payloadCount); + std::sort(indices.begin(), indices.end()); + document.animations_move(indices, i); } ImGui::EndDragDropTarget(); } @@ -96,63 +95,90 @@ namespace anm2ed::animations ImGui::PopID(); } - storage.end(); + multiSelect.finish(); + + auto copy = [&]() + { + if (!multiSelect.empty()) + { + std::string clipboardText{}; + for (auto& i : multiSelect) + clipboardText += anm2.animations.items[i].to_string(); + clipboard.set(clipboardText); + } + else if (hovered > -1) + clipboard.set(anm2.animations.items[hovered].to_string()); + }; + + auto cut = [&]() + { + copy(); + + if (!multiSelect.empty()) + { + for (auto& i : multiSelect | std::views::reverse) + anm2.animations.items.erase(anm2.animations.items.begin() + i); + multiSelect.clear(); + } + else if (hovered > -1) + { + anm2.animations.items.erase(anm2.animations.items.begin() + hovered); + hovered = -1; + } + }; + + auto paste = [&]() + { + auto clipboardText = clipboard.get(); + document.animations_deserialize(clipboardText); + }; + + if (imgui::shortcut(settings.shortcutCut, shortcut::FOCUSED)) cut(); + if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (imgui::shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::BeginDisabled(multiSelect.empty() && hovered == -1); + if (ImGui::MenuItem("Cut", settings.shortcutCut.c_str())) cut(); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(clipboard.is_empty()); + if (ImGui::MenuItem("Paste", settings.shortcutPaste.c_str())) paste(); + ImGui::EndDisabled(); + + ImGui::EndPopup(); + } } ImGui::EndChild(); auto widgetSize = imgui::widget_size_with_row_get(5); imgui::shortcut(settings.shortcutAdd); - if (ImGui::Button("Add", widgetSize)) - { - anm2::Animation animation; - if (anm2::Animation* referenceAnimation = document.animation_get()) - { - for (auto [id, layerAnimation] : referenceAnimation->layerAnimations) - animation.layerAnimations[id] = anm2::Item(); - animation.layerOrder = referenceAnimation->layerOrder; - for (auto [id, nullAnimation] : referenceAnimation->nullAnimations) - animation.nullAnimations[id] = anm2::Item(); - } - animation.rootAnimation.frames.emplace_back(anm2::Frame()); - - auto index = selection.empty() ? (int)anm2.animations.items.size() - 1 : (int)std::ranges::max(selection) + 1; - anm2.animations.items.insert(anm2.animations.items.begin() + index, animation); - selection = {index}; - reference = {index}; - document.change(change::ANIMATIONS); - } + if (ImGui::Button("Add", widgetSize)) document.animation_add(); imgui::set_item_tooltip_shortcut("Add a new animation.", settings.shortcutAdd); ImGui::SameLine(); - ImGui::BeginDisabled(selection.empty()); + ImGui::BeginDisabled(multiSelect.empty()); { - imgui::shortcut(settings.shortcutDuplicate); - if (ImGui::Button("Duplicate", widgetSize)) - { - auto duplicated = selection; - auto duplicatedEnd = std::ranges::max(duplicated); - for (auto& id : duplicated) - { - anm2.animations.items.insert(anm2.animations.items.begin() + duplicatedEnd, anm2.animations.items[id]); - selection.insert(++duplicatedEnd); - selection.erase(id); - } - document.change(change::ANIMATIONS); - } + if (ImGui::Button("Duplicate", widgetSize)) document.animation_duplicate(); imgui::set_item_tooltip_shortcut("Duplicate the selected animation(s).", settings.shortcutDuplicate); ImGui::SameLine(); - ImGui::BeginDisabled(selection.size() != 1); + if (imgui::shortcut(settings.shortcutMerge, shortcut::FOCUSED)) + if (multiSelect.size() > 0) document.animations_merge_quick(); + + ImGui::BeginDisabled(multiSelect.size() != 1); { if (ImGui::Button("Merge", widgetSize)) { mergePopup.open(); - mergeSelection.clear(); - mergeTarget = *selection.begin(); + mergeMultiSelect.clear(); + mergeTarget = *multiSelect.begin(); } } ImGui::EndDisabled(); @@ -165,28 +191,16 @@ namespace anm2ed::animations ImGui::SameLine(); imgui::shortcut(settings.shortcutRemove); - if (ImGui::Button("Remove", widgetSize)) - { - /* - auto selectionErase = set::to_size_t(selection); - if (selectionErase.contains(document.reference.animationIndex)) document.reference.animationIndex = -1; - vector::range_erase(anm2.animations.items, selectionErase); - */ - document.change(change::ANIMATIONS); - selection.clear(); - } + if (ImGui::Button("Remove", widgetSize)) document.animation_remove(); imgui::set_item_tooltip_shortcut("Remove the selected animation(s).", settings.shortcutDuplicate); ImGui::SameLine(); - ImGui::BeginDisabled(selection.size() != 1); - { - imgui::shortcut(settings.shortcutDefault); - if (ImGui::Button("Default", widgetSize)) - anm2.animations.defaultAnimation = anm2.animations.items[*selection.begin()].name; - imgui::set_item_tooltip_shortcut("Set the selected animation as the default.", settings.shortcutDuplicate); - } + imgui::shortcut(settings.shortcutDefault); + ImGui::BeginDisabled(multiSelect.size() != 1); + if (ImGui::Button("Default", widgetSize)) document.animation_default(); ImGui::EndDisabled(); + imgui::set_item_tooltip_shortcut("Set the selected animation as the default.", settings.shortcutDefault); } ImGui::EndDisabled(); @@ -196,15 +210,13 @@ namespace anm2ed::animations { auto merge_close = [&]() { - mergeSelection.clear(); + mergeMultiSelect.clear(); mergePopup.close(); }; auto& type = settings.mergeType; auto& isDeleteAnimationsAfter = settings.mergeIsDeleteAnimationsAfter; - mergeStorage.user_data_set(&mergeSelection); - auto footerSize = imgui::footer_size_get(); auto optionsSize = imgui::child_size_get(2); auto deleteAfterSize = imgui::child_size_get(); @@ -214,21 +226,19 @@ namespace anm2ed::animations if (ImGui::BeginChild("Animations", animationsSize, ImGuiChildFlags_Borders)) { - mergeSelection.begin(); + mergeMultiSelect.start(anm2.animations.items.size()); for (auto [i, animation] : std::views::enumerate(anm2.animations.items)) { - auto isSelected = mergeSelection.contains(i); - ImGui::PushID(i); ImGui::SetNextItemSelectionUserData(i); - ImGui::Selectable(animation.name.c_str(), isSelected); + ImGui::Selectable(animation.name.c_str(), mergeMultiSelect.contains(i)); ImGui::PopID(); } - mergeSelection.end(); + mergeMultiSelect.finish(); } ImGui::EndChild(); @@ -262,12 +272,7 @@ namespace anm2ed::animations if (ImGui::Button("Merge", widgetSize)) { - /* - std::set sources = set::to_set(mergeSelection); - const auto merged = anm2.animations.merge(mergeTarget, sources, (MergeType)type, isDeleteAnimationsAfter); - selection = {merged}; - reference = {merged}; - */ + document.animations_merge((merge::Type)type, isDeleteAnimationsAfter); merge_close(); } ImGui::SameLine(); diff --git a/src/animations.h b/src/animations.h index 552b4d1..e03e7e9 100644 --- a/src/animations.h +++ b/src/animations.h @@ -1,7 +1,8 @@ #pragma once -#include "document.h" +#include "clipboard.h" #include "imgui.h" +#include "manager.h" #include "resources.h" #include "settings.h" @@ -10,13 +11,8 @@ namespace anm2ed::animations class Animations { imgui::PopupHelper mergePopup{imgui::PopupHelper("Merge Animations")}; - imgui::MultiSelectStorage mergeStorage{}; - imgui::MultiSelectStorage storage{}; - std::set mergeSelection{}; - int mergeTarget{}; public: - void update(document::Document& document, int& documentIndex, settings::Settings& settings, - resources::Resources& resources); + void update(manager::Manager&, settings::Settings&, resources::Resources&, clipboard::Clipboard&); }; -} \ No newline at end of file +} diff --git a/src/anm2.cpp b/src/anm2.cpp index b67c7a1..652b8f4 100644 --- a/src/anm2.cpp +++ b/src/anm2.cpp @@ -13,6 +13,7 @@ using namespace anm2ed::filesystem; using namespace anm2ed::texture; using namespace anm2ed::types; using namespace anm2ed::util; +using namespace glm; namespace anm2ed::anm2 { @@ -64,14 +65,14 @@ namespace anm2ed::anm2 // If it doesn't work beyond that then that's on the user :^) if (!path_is_exist(path)) path = string::to_lower(path); if (!path_is_exist(path)) path = string::replace_backslash(path); - texture = Texture(path, true); + texture = Texture(path); } Spritesheet::Spritesheet(const std::string& directory, const std::string& path) { this->path = !path.empty() ? path : this->path.string(); WorkingDirectory workingDirectory(directory); - texture = Texture(this->path, true); + texture = Texture(this->path); } bool Spritesheet::save(const std::string& directory, const std::string& path) @@ -99,6 +100,22 @@ namespace anm2ed::anm2 return texture.is_valid(); } + std::string Spritesheet::to_string(int id) + { + XMLDocument document{}; + + auto* element = document.NewElement("Spritesheet"); + + element->SetAttribute("Id", id); + element->SetAttribute("Path", path.c_str()); + + document.InsertFirstChild(element); + + XMLPrinter printer; + document.Print(&printer); + return std::string(printer.CStr()); + } + Layer::Layer() = default; Layer::Layer(XMLElement* element, int& id) @@ -118,6 +135,23 @@ namespace anm2ed::anm2 parent->InsertEndChild(element); } + std::string Layer::to_string(int id) + { + XMLDocument document{}; + + auto* element = document.NewElement("Layer"); + + element->SetAttribute("Id", id); + element->SetAttribute("Name", name.c_str()); + element->SetAttribute("SpritesheetId", spritesheetID); + + document.InsertFirstChild(element); + + XMLPrinter printer; + document.Print(&printer); + return std::string(printer.CStr()); + } + Null::Null() = default; Null::Null(XMLElement* element, int& id) @@ -138,6 +172,22 @@ namespace anm2ed::anm2 parent->InsertEndChild(element); } + std::string Null::to_string(int id) + { + XMLDocument document{}; + + auto* element = document.NewElement("Null"); + + element->SetAttribute("Id", id); + element->SetAttribute("Name", name.c_str()); + + document.InsertFirstChild(element); + + XMLPrinter printer; + document.Print(&printer); + return std::string(printer.CStr()); + } + Event::Event() = default; Event::Event(XMLElement* element, int& id) @@ -155,6 +205,22 @@ namespace anm2ed::anm2 parent->InsertEndChild(element); } + std::string Event::to_string(int id) + { + XMLDocument document{}; + + auto* element = document.NewElement("Event"); + + element->SetAttribute("Id", id); + element->SetAttribute("Name", name.c_str()); + + document.InsertFirstChild(element); + + XMLPrinter printer; + document.Print(&printer); + return std::string(printer.CStr()); + } + Content::Content() = default; void Content::serialize(XMLDocument& document, XMLElement* parent) @@ -245,6 +311,134 @@ namespace anm2ed::anm2 events[id] = Event(); } + bool Content::spritesheets_deserialize(const std::string& string, const std::string& directory, merge::Type type, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Spritesheet")) + { + if (errorString) *errorString = "No valid spritesheet(s)."; + return false; + } + + WorkingDirectory workingDirectory(directory); + + for (auto element = document.FirstChildElement("Spritesheet"); element; + element = element->NextSiblingElement("Spritesheet")) + { + auto spritesheet = Spritesheet(element, id); + + if (type == merge::APPEND) id = map::next_id_get(spritesheets); + + spritesheets[id] = std::move(spritesheet); + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + + bool Content::layers_deserialize(const std::string& string, merge::Type type, std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Layer")) + { + if (errorString) *errorString = "No valid layer(s)."; + return false; + } + + for (auto element = document.FirstChildElement("Layer"); element; element = element->NextSiblingElement("Layer")) + { + auto layer = Layer(element, id); + + if (type == merge::APPEND) id = map::next_id_get(layers); + + layers[id] = layer; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + + bool Content::nulls_deserialize(const std::string& string, merge::Type type, std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Null")) + { + if (errorString) *errorString = "No valid null(s)."; + return false; + } + + for (auto element = document.FirstChildElement("Null"); element; element = element->NextSiblingElement("Null")) + { + auto layer = Null(element, id); + + if (type == merge::APPEND) id = map::next_id_get(nulls); + + nulls[id] = layer; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + + bool Content::events_deserialize(const std::string& string, merge::Type type, std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Event")) + { + if (errorString) *errorString = "No valid event(s)."; + return false; + } + + for (auto element = document.FirstChildElement("Event"); element; element = element->NextSiblingElement("Event")) + { + auto layer = Event(element, id); + + if (type == merge::APPEND) id = map::next_id_get(events); + + events[id] = layer; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + Frame::Frame() = default; Frame::Frame(XMLElement* element, Type type) @@ -504,6 +698,25 @@ namespace anm2ed::anm2 return nullptr; } + void Animation::item_remove(Type type, int id) + { + switch (type) + { + case LAYER: + layerAnimations.erase(id); + for (auto [i, value] : std::views::enumerate(layerOrder)) + if (value == id) layerOrder.erase(layerOrder.begin() + i); + break; + case NULL_: + nullAnimations.erase(id); + break; + case ROOT: + case TRIGGER: + default: + break; + } + } + void Animation::serialize(XMLDocument& document, XMLElement* parent) { auto element = document.NewElement("Animation"); @@ -551,6 +764,39 @@ namespace anm2ed::anm2 return length; } + std::string Animation::to_string() + { + XMLDocument document{}; + + auto* element = document.NewElement("Animation"); + document.InsertFirstChild(element); + + element->SetAttribute("Name", name.c_str()); + element->SetAttribute("FrameNum", frameNum); + element->SetAttribute("Loop", isLoop); + + rootAnimation.serialize(document, element, ROOT); + + auto layerAnimationsElement = document.NewElement("LayerAnimations"); + for (auto& i : layerOrder) + { + Item& layerAnimation = layerAnimations.at(i); + layerAnimation.serialize(document, layerAnimationsElement, LAYER, i); + } + element->InsertEndChild(layerAnimationsElement); + + auto nullAnimationsElement = document.NewElement("NullAnimations"); + for (auto& [id, nullAnimation] : nullAnimations) + nullAnimation.serialize(document, nullAnimationsElement, NULL_, id); + element->InsertEndChild(nullAnimationsElement); + + triggers.serialize(document, element, TRIGGER); + + XMLPrinter printer; + document.Print(&printer); + return std::string(printer.CStr()); + } + Animations::Animations() = default; Animations::Animations(XMLElement* element) @@ -660,6 +906,37 @@ namespace anm2ed::anm2 return finalIndex; } + bool Animations::animations_deserialize(const std::string& string, int start, std::set& indices, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + if (!document.FirstChildElement("Animation")) + { + if (errorString) *errorString = "No valid animation(s)."; + return false; + } + + int count{}; + for (auto element = document.FirstChildElement("Animation"); element; + element = element->NextSiblingElement("Animation")) + { + auto index = start + count; + items.insert(items.begin() + start + count, Animation(element)); + indices.insert(index); + count++; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + Anm2::Anm2() { info.createdOn = time::get("%d-%B-%Y %I:%M:%S"); @@ -697,7 +974,7 @@ namespace anm2ed::anm2 XMLPrinter printer; document.Print(&printer); - return printer.CStr(); + return std::string(printer.CStr()); } Anm2::Anm2(const std::string& path, std::string* errorString) @@ -710,8 +987,6 @@ namespace anm2ed::anm2 return; } - isValid = false; - WorkingDirectory workingDirectory(path, true); const XMLElement* element = document.RootElement(); @@ -907,4 +1182,53 @@ namespace anm2ed::anm2 spritesheets.push_back(std::format("#{} {}", id, spritesheet.path.c_str())); return spritesheets; } -} \ No newline at end of file + + void Anm2::bake(Reference reference, int interval, bool isRoundScale, bool isRoundRotation) + { + Item* item = item_get(reference); + if (!item) return; + + Frame* frame = frame_get(reference); + if (!frame) return; + + if (frame->delay == FRAME_DELAY_MIN) return; + + Reference referenceNext = reference; + referenceNext.frameIndex = reference.frameIndex + 1; + + Frame* frameNext = frame_get(referenceNext); + if (!frameNext) frameNext = frame; + + Frame baseFrame = *frame; + Frame baseFrameNext = *frameNext; + + int delay{}; + int index = reference.frameIndex; + + while (delay < baseFrame.delay) + { + float interpolation = (float)delay / baseFrame.delay; + + Frame baked = baseFrame; + baked.delay = std::min(interval, baseFrame.delay - delay); + baked.isInterpolated = (index == reference.frameIndex) ? baseFrame.isInterpolated : false; + + baked.rotation = glm::mix(baseFrame.rotation, baseFrameNext.rotation, interpolation); + baked.position = glm::mix(baseFrame.position, baseFrameNext.position, interpolation); + baked.scale = glm::mix(baseFrame.scale, baseFrameNext.scale, interpolation); + baked.offset = glm::mix(baseFrame.offset, baseFrameNext.offset, interpolation); + baked.tint = glm::mix(baseFrame.tint, baseFrameNext.tint, interpolation); + + if (isRoundScale) baked.scale = vec2(ivec2(baked.scale)); + if (isRoundRotation) baked.rotation = (int)baked.rotation; + + if (index == reference.frameIndex) + item->frames[index] = baked; + else + item->frames.insert(item->frames.begin() + index, baked); + index++; + + delay += baked.delay; + } + } +} diff --git a/src/anm2.h b/src/anm2.h index 5257a11..02aaf5a 100644 --- a/src/anm2.h +++ b/src/anm2.h @@ -21,6 +21,7 @@ namespace anm2ed::anm2 constexpr auto MERGED_STRING = "(Merged)"; + constexpr auto NO_PATH = "(No Path)"; constexpr auto LAYER_FORMAT = "#{} {} (Spritesheet: #{})"; constexpr auto NULL_FORMAT = "#{} {}"; constexpr auto SPRITESHEET_FORMAT = "#%d %s"; @@ -43,8 +44,8 @@ namespace anm2ed::anm2 int frameIndex{-1}; int frameTime{-1}; - void previous_frame(int max = FRAME_NUM_MAX - 1); - void next_frame(int max = FRAME_NUM_MAX - 1); + void previous_frame(int = FRAME_NUM_MAX - 1); + void next_frame(int = FRAME_NUM_MAX - 1); auto operator<=>(const Reference&) const = default; }; @@ -59,8 +60,8 @@ namespace anm2ed::anm2 int version{}; Info(); - Info(tinyxml2::XMLElement* element); - void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent); + Info(tinyxml2::XMLElement*); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); }; class Spritesheet @@ -70,12 +71,13 @@ namespace anm2ed::anm2 texture::Texture texture; Spritesheet(); - Spritesheet(tinyxml2::XMLElement* element, int& id); - Spritesheet(const std::string& directory, const std::string& path = {}); - bool save(const std::string& directory, const std::string& path = {}); - void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent, int id); - void reload(const std::string& directory); + Spritesheet(tinyxml2::XMLElement*, int&); + Spritesheet(const std::string&, const std::string& = {}); + bool save(const std::string&, const std::string& = {}); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); + void reload(const std::string&); bool is_valid(); + std::string to_string(int id); }; class Layer @@ -85,8 +87,9 @@ namespace anm2ed::anm2 int spritesheetID{}; Layer(); - Layer(tinyxml2::XMLElement* element, int& id); - void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent, int id); + Layer(tinyxml2::XMLElement*, int&); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); + std::string to_string(int); }; class Null @@ -96,8 +99,9 @@ namespace anm2ed::anm2 bool isShowRect{}; Null(); - Null(tinyxml2::XMLElement* element, int& id); - void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent, int id); + Null(tinyxml2::XMLElement*, int&); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); + std::string to_string(int); }; class Event @@ -106,8 +110,9 @@ namespace anm2ed::anm2 std::string name{"New Event"}; Event(); - Event(tinyxml2::XMLElement* element, int& id); - void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent, int id); + Event(tinyxml2::XMLElement*, int&); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); + std::string to_string(int); }; struct Content @@ -119,14 +124,18 @@ namespace anm2ed::anm2 Content(); - void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent); - Content(tinyxml2::XMLElement* element); - bool spritesheet_add(const std::string& directory, const std::string& path, int& id); - void spritesheet_remove(int& id); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); + Content(tinyxml2::XMLElement*); + bool spritesheet_add(const std::string&, const std::string&, int&); + void spritesheet_remove(int&); std::set spritesheets_unused(); - void layer_add(int& id); - void null_add(int& id); - void event_add(int& id); + void layer_add(int&); + void null_add(int&); + void event_add(int&); + bool spritesheets_deserialize(const std::string&, const std::string&, types::merge::Type, std::string* = nullptr); + bool layers_deserialize(const std::string&, types::merge::Type, std::string* = nullptr); + bool nulls_deserialize(const std::string&, types::merge::Type, std::string* = nullptr); + bool events_deserialize(const std::string&, types::merge::Type, std::string* = nullptr); }; #define MEMBERS \ @@ -152,8 +161,8 @@ namespace anm2ed::anm2 #undef X Frame(); - Frame(tinyxml2::XMLElement* element, Type type); - void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent, Type type); + Frame(tinyxml2::XMLElement*, Type); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, Type); void shorten(); void extend(); }; @@ -175,10 +184,10 @@ namespace anm2ed::anm2 Item(); - Item(tinyxml2::XMLElement* element, Type type, int* id = nullptr); - void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent, Type type, int id = -1); - int length(Type type); - Frame frame_generate(float time, Type type); + Item(tinyxml2::XMLElement*, Type, int* = nullptr); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, Type, int = -1); + int length(Type); + Frame frame_generate(float, Type); }; class Animation @@ -194,10 +203,12 @@ namespace anm2ed::anm2 Item triggers; Animation(); - Animation(tinyxml2::XMLElement* element); - Item* item_get(Type type, int id = -1); - void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent); + Animation(tinyxml2::XMLElement*); + Item* item_get(Type, int = -1); + void item_remove(Type, int = -1); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); int length(); + std::string to_string(); }; struct Animations @@ -207,42 +218,41 @@ namespace anm2ed::anm2 Animations(); - Animations(tinyxml2::XMLElement* element); - void serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent); + Animations(tinyxml2::XMLElement*); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); int length(); - int merge(int target, std::set& sources, types::merge::Type type, bool isDeleteAfter = true); + int merge(int, std::set&, types::merge::Type = types::merge::APPEND, bool = true); + bool animations_deserialize(const std::string&, int, std::set&, std::string* = nullptr); }; class Anm2 { - bool isValid{false}; - public: Info info{}; Content content{}; Animations animations{}; Anm2(); - bool serialize(const std::string& path, std::string* errorString = nullptr); + bool serialize(const std::string&, std::string* = nullptr); std::string to_string(); - Anm2(const std::string& path, std::string* errorString = nullptr); + Anm2(const std::string&, std::string* = nullptr); uint64_t hash(); - Animation* animation_get(Reference& reference); - Item* item_get(Reference& reference); - Frame* frame_get(Reference& reference); - bool spritesheet_add(const std::string& directory, const std::string& path, int& id); - Spritesheet* spritesheet_get(int id); - void spritesheet_remove(int id); + Animation* animation_get(Reference&); + Item* item_get(Reference&); + Frame* frame_get(Reference&); + bool spritesheet_add(const std::string&, const std::string&, int&); + Spritesheet* spritesheet_get(int); + void spritesheet_remove(int); std::set spritesheets_unused(); int layer_add(); - Reference layer_add(Reference reference = REFERENCE_DEFAULT, std::string name = {}, int spritesheetID = 0, - types::locale::Type locale = types::locale::GLOBAL); - Reference null_add(Reference reference = REFERENCE_DEFAULT, std::string name = {}, - types::locale::Type locale = types::locale::GLOBAL); - void event_add(int& id); - std::set events_unused(Reference reference = REFERENCE_DEFAULT); - std::set layers_unused(Reference reference = REFERENCE_DEFAULT); - std::set nulls_unused(Reference reference = REFERENCE_DEFAULT); + Reference layer_add(Reference = REFERENCE_DEFAULT, std::string = {}, int = 0, + types::locale::Type = types::locale::GLOBAL); + Reference null_add(Reference = REFERENCE_DEFAULT, std::string = {}, types::locale::Type = types::locale::GLOBAL); + void event_add(int&); + std::set events_unused(Reference = REFERENCE_DEFAULT); + std::set layers_unused(Reference = REFERENCE_DEFAULT); + std::set nulls_unused(Reference = REFERENCE_DEFAULT); std::vector spritesheet_names_get(); + void bake(Reference, int = 1, bool = true, bool = true); }; -} \ No newline at end of file +} diff --git a/src/canvas.h b/src/canvas.h index 55e1672..573d22d 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -32,24 +32,24 @@ namespace anm2ed::canvas glm::vec2 size{}; Canvas(); - Canvas(glm::vec2 size); + Canvas(glm::vec2); ~Canvas(); bool is_valid(); void framebuffer_set(); void framebuffer_resize_check(); - void size_set(glm::vec2 size); - glm::mat4 transform_get(float zoom, glm::vec2 pan); - void axes_render(shader::Shader& shader, float zoom, glm::vec2 pan, glm::vec4 color = glm::vec4(1.0f)); - void grid_render(shader::Shader& shader, float zoom, glm::vec2 pan, glm::ivec2 size = glm::ivec2(32, 32), - glm::ivec2 offset = {}, glm::vec4 color = glm::vec4(1.0f)); - void texture_render(shader::Shader& shader, GLuint& texture, glm::mat4& transform, glm::vec4 tint = glm::vec4(1.0f), - glm::vec3 colorOffset = {}, float* vertices = (float*)TEXTURE_VERTICES); - void rect_render(shader::Shader& shader, glm::mat4& transform, glm::vec4 color = glm::vec4(1.0f)); + void size_set(glm::vec2); + glm::mat4 transform_get(float, glm::vec2); + void axes_render(shader::Shader&, float, glm::vec2, glm::vec4 = glm::vec4(1.0f)); + void grid_render(shader::Shader&, float, glm::vec2, glm::ivec2 = glm::ivec2(32, 32), glm::ivec2 = {}, + glm::vec4 = glm::vec4(1.0f)); + void texture_render(shader::Shader&, GLuint&, glm::mat4&, glm::vec4 = glm::vec4(1.0f), glm::vec3 = {}, + float* = (float*)TEXTURE_VERTICES); + void rect_render(shader::Shader&, glm::mat4&, glm::vec4 = glm::vec4(1.0f)); void viewport_set(); - void clear(glm::vec4& color); + void clear(glm::vec4&); void bind(); void unbind(); - void zoom_set(float& zoom, glm::vec2& pan, glm::vec2& focus, float step); - glm::vec2 position_translate(float& zoom, glm::vec2& pan, glm::vec2 position); + void zoom_set(float&, glm::vec2&, glm::vec2&, float); + glm::vec2 position_translate(float&, glm::vec2&, glm::vec2); }; } diff --git a/src/clipboard.cpp b/src/clipboard.cpp new file mode 100644 index 0000000..8ec5e53 --- /dev/null +++ b/src/clipboard.cpp @@ -0,0 +1,25 @@ +#include "clipboard.h" + +#include + +namespace anm2ed::clipboard +{ + std::string Clipboard::get() + { + auto text = SDL_GetClipboardText(); + auto string = std::string(text); + SDL_free(text); + + return string; + } + + bool Clipboard::is_empty() + { + return get().empty(); + } + + void Clipboard::set(const std::string& string) + { + SDL_SetClipboardText(string.data()); + } +} \ No newline at end of file diff --git a/src/clipboard.h b/src/clipboard.h new file mode 100644 index 0000000..0b13a07 --- /dev/null +++ b/src/clipboard.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace anm2ed::clipboard +{ + class Clipboard + { + public: + bool is_empty(); + std::string get(); + void set(const std::string&); + }; +} diff --git a/src/dialog.h b/src/dialog.h index e6983c9..487c37f 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -26,14 +26,14 @@ namespace anm2ed::dialog int replaceID{-1}; Dialog(); - Dialog(SDL_Window* window); + Dialog(SDL_Window*); void anm2_new(); void anm2_open(); void anm2_save(); void spritesheet_open(); void spritesheet_replace(); - void file_explorer_open(const std::string& path); + void file_explorer_open(const std::string&); void reset(); - bool is_selected_file(Type type); + bool is_selected_file(Type); }; } diff --git a/src/dockspace.cpp b/src/dockspace.cpp index a86d1f3..f77f28d 100644 --- a/src/dockspace.cpp +++ b/src/dockspace.cpp @@ -6,7 +6,8 @@ using namespace anm2ed::animations; using namespace anm2ed::dialog; -using namespace anm2ed::document_manager; +using namespace anm2ed::clipboard; +using namespace anm2ed::manager; using namespace anm2ed::documents; using namespace anm2ed::playback; using namespace anm2ed::resources; @@ -15,8 +16,8 @@ using namespace anm2ed::taskbar; namespace anm2ed::dockspace { - void Dockspace::update(Taskbar& taskbar, Documents& documents, DocumentManager& manager, Settings& settings, - Resources& resources, Dialog& dialog, Playback& playback) + void Dockspace::update(Taskbar& taskbar, Documents& documents, Manager& manager, Settings& settings, + Resources& resources, Dialog& dialog, Clipboard& clipboard) { auto viewport = ImGui::GetMainViewport(); @@ -35,17 +36,17 @@ namespace anm2ed::dockspace { if (auto document = manager.get(); document) { - if (settings.windowIsAnimationPreview) animationPreview.update(manager, settings, resources, playback); - if (settings.windowIsAnimations) animations.update(*document, manager.selected, settings, resources); - if (settings.windowIsEvents) events.update(manager, settings, resources); + if (settings.windowIsAnimationPreview) animationPreview.update(manager, settings, resources); + if (settings.windowIsAnimations) animations.update(manager, settings, resources, clipboard); + if (settings.windowIsEvents) events.update(manager, settings, resources, clipboard); if (settings.windowIsFrameProperties) frameProperties.update(manager, settings); - if (settings.windowIsLayers) layers.update(*document, settings, resources); - if (settings.windowIsNulls) nulls.update(*document, manager.selected, settings, resources); + if (settings.windowIsLayers) layers.update(manager, settings, resources, clipboard); + if (settings.windowIsNulls) nulls.update(manager, settings, resources, clipboard); if (settings.windowIsOnionskin) onionskin.update(settings); if (settings.windowIsSpritesheetEditor) spritesheetEditor.update(manager, settings, resources); - if (settings.windowIsSpritesheets) spritesheets.update(*document, settings, resources, dialog); - if (settings.windowIsTimeline) timeline.update(manager, settings, resources, playback); - if (settings.windowIsTools) tools.update(settings, resources); + if (settings.windowIsSpritesheets) spritesheets.update(manager, settings, resources, dialog, clipboard); + if (settings.windowIsTimeline) timeline.update(manager, settings, resources); + if (settings.windowIsTools) tools.update(manager, settings, resources); } } } diff --git a/src/dockspace.h b/src/dockspace.h index 59f4969..04ef75f 100644 --- a/src/dockspace.h +++ b/src/dockspace.h @@ -31,8 +31,7 @@ namespace anm2ed::dockspace tools::Tools tools; public: - void update(taskbar::Taskbar& taskbar, documents::Documents& documents, document_manager::DocumentManager& manager, - settings::Settings& settings, resources::Resources& resources, dialog::Dialog& dialog, - playback::Playback& playback); + void update(taskbar::Taskbar&, documents::Documents&, manager::Manager&, settings::Settings&, resources::Resources&, + dialog::Dialog&, clipboard::Clipboard&); }; } diff --git a/src/document.cpp b/src/document.cpp index 3727f79..7cdf70e 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -2,24 +2,21 @@ #include "anm2.h" #include "filesystem.h" +#include "toast.h" +#include "util.h" +#include +#include using namespace anm2ed::anm2; using namespace anm2ed::filesystem; +using namespace anm2ed::toast; using namespace anm2ed::types; +using namespace anm2ed::util; namespace anm2ed::document { - Document::Document() - { - for (auto& value : isJustChanged) - value = true; - } - Document::Document(const std::string& path, bool isNew, std::string* errorString) { - for (auto& value : isJustChanged) - value = true; - if (!path_is_exist(path)) return; if (isNew) @@ -31,8 +28,8 @@ namespace anm2ed::document } this->path = path; - on_change(); clean(); + change(change::ALL); } bool Document::save(const std::string& path, std::string* errorString) @@ -62,7 +59,42 @@ namespace anm2ed::document void Document::change(change::Type type) { hash_set(); - isJustChanged[type] = true; + + auto layer_set = [&]() { unusedLayerIDs = anm2.layers_unused(); }; + auto null_set = [&]() { unusedNullIDs = anm2.nulls_unused(); }; + auto event_set = [&]() { unusedEventIDs = anm2.events_unused(); }; + auto spritesheet_set = [&]() + { + unusedSpritesheetIDs = anm2.spritesheets_unused(); + spritesheetNames = anm2.spritesheet_names_get(); + spritesheetNamesCstr.clear(); + for (auto& name : spritesheetNames) + spritesheetNamesCstr.push_back(name.c_str()); + }; + + switch (type) + { + case change::LAYERS: + layer_set(); + break; + case change::NULLS: + null_set(); + break; + case change::EVENTS: + event_set(); + break; + case change::SPRITESHEETS: + spritesheet_set(); + break; + case change::ALL: + layer_set(); + null_set(); + event_set(); + spritesheet_set(); + break; + default: + break; + } } bool Document::is_dirty() @@ -70,11 +102,6 @@ namespace anm2ed::document return hash != saveHash; } - bool Document::is_just_changed(types::change::Type type) - { - return isJustChanged[type]; - } - std::string Document::directory_get() { return path.parent_path(); @@ -85,9 +112,9 @@ namespace anm2ed::document return path.filename().string(); } - anm2::Animation* Document::animation_get() + bool Document::is_valid() { - return anm2.animation_get(reference); + return !path.empty(); } anm2::Frame* Document::frame_get() @@ -95,6 +122,42 @@ namespace anm2ed::document return anm2.frame_get(reference); } + void Document::frames_bake(int interval, bool isRoundScale, bool isRoundRotation) + { + snapshot("Bake Frames"); + anm2.bake(reference, interval, isRoundScale, isRoundRotation); + change(change::FRAMES); + } + + void Document::frames_add(anm2::Item* item) + { + if (!item) return; + + auto frame = frame_get(); + + if (frame) + { + item->frames.insert(item->frames.begin() + reference.frameIndex, *frame); + reference.frameIndex++; + } + else if (!item->frames.empty()) + { + auto frame = item->frames.back(); + item->frames.emplace_back(frame); + reference.frameIndex = item->frames.size() - 1; + } + } + + void Document::frames_delete(anm2::Item* item) + { + if (!item) return; + + snapshot("Delete Frames"); + item->frames.erase(item->frames.begin() + reference.frameIndex); + reference.frameIndex = glm::max(-1, --reference.frameIndex); + change(change::FRAMES); + } + anm2::Item* Document::item_get() { return anm2.item_get(reference); @@ -105,27 +168,317 @@ namespace anm2ed::document return anm2.spritesheet_get(referenceSpritesheet); } - bool Document::is_valid() + void Document::spritesheet_add(const std::string& path) { - return !path.empty(); - } - - void Document::on_change() - { - if (is_just_changed(change::SPRITESHEETS)) + int id{}; + snapshot("Add Spritesheet"); + if (anm2.spritesheet_add(directory_get(), path, id)) { - spritesheetNames = anm2.spritesheet_names_get(); - spritesheetNamesCstr.clear(); - for (auto& name : spritesheetNames) - spritesheetNamesCstr.push_back(name.c_str()); + spritesheetMultiSelect = {id}; + toasts.info(std::format("Initialized spritesheet #{}: {}", id, path)); + change(change::SPRITESHEETS); } + else + toasts.error(std::format("Failed to initialize spritesheet: {}", path)); } - void Document::update() + void Document::spritesheets_deserialize(const std::string& string, merge::Type type) { - on_change(); - - for (auto& value : isJustChanged) - value = false; + snapshot("Paste Spritesheet(s)"); + std::string errorString{}; + if (anm2.content.spritesheets_deserialize(string, directory_get(), type, &errorString)) + change(change::SPRITESHEETS); + else + toasts.error(std::format("Failed to deserialize spritesheet(s): {}", errorString)); } -}; \ No newline at end of file + + void Document::layers_deserialize(const std::string& string, merge::Type type) + { + snapshot("Paste Layer(s)"); + std::string errorString{}; + if (anm2.content.layers_deserialize(string, type, &errorString)) + change(change::NULLS); + else + toasts.error(std::format("Failed to deserialize layer(s): {}", errorString)); + } + + void Document::layer_set(anm2::Layer& layer) + { + if (referenceLayer > -1) + { + snapshot("Set Layer"); + anm2.content.layers[referenceLayer] = layer; + layersMultiSelect = {referenceLayer}; + } + else + { + snapshot("Add Layer"); + auto id = map::next_id_get(anm2.content.layers); + anm2.content.layers[id] = layer; + layersMultiSelect = {id}; + } + change(change::LAYERS); + } + + void Document::layers_remove_unused() + { + snapshot("Remove Unused Layers"); + for (auto& id : unusedLayerIDs) + anm2.content.layers.erase(id); + change(change::LAYERS); + unusedLayerIDs.clear(); + } + + void Document::null_set(anm2::Null& null) + { + if (referenceNull > -1) + { + snapshot("Set Null"); + anm2.content.nulls[referenceNull] = null; + nullMultiSelect = {referenceNull}; + } + else + { + snapshot("Add Null"); + auto id = map::next_id_get(anm2.content.nulls); + anm2.content.nulls[id] = null; + nullMultiSelect = {id}; + } + change(change::NULLS); + } + + void Document::null_rect_toggle(anm2::Null& null) + { + snapshot("Null Rect"); + null.isShowRect = !null.isShowRect; + change(change::NULLS); + } + + void Document::nulls_remove_unused() + { + snapshot("Remove Unused Nulls"); + for (auto& id : unusedNullIDs) + anm2.content.nulls.erase(id); + change(change::NULLS); + unusedNullIDs.clear(); + } + + void Document::nulls_deserialize(const std::string& string, merge::Type type) + { + snapshot("Paste Null(s)"); + std::string errorString{}; + if (anm2.content.nulls_deserialize(string, type, &errorString)) + change(change::NULLS); + else + toasts.error(std::format("Failed to deserialize null(s): {}", errorString)); + } + + void Document::event_add() + { + snapshot("Add Event"); + int id{}; + anm2.event_add(id); + eventMultiSelect = {id}; + change(change::EVENTS); + } + + void Document::events_remove_unused() + { + snapshot("Remove Unused Events"); + for (auto& id : unusedEventIDs) + anm2.content.events.erase(id); + change(change::EVENTS); + unusedEventIDs.clear(); + } + + void Document::events_deserialize(const std::string& string, merge::Type type) + { + snapshot("Paste Event(s)"); + std::string errorString{}; + if (anm2.content.events_deserialize(string, type, &errorString)) + change(change::EVENTS); + else + toasts.error(std::format("Failed to deserialize event(s): {}", errorString)); + } + + void Document::item_visible_toggle(anm2::Item* item) + { + if (!item) return; + + snapshot("Item Visible"); + item->isVisible = !item->isVisible; + + change(change::ITEMS); + } + + void Document::item_add(anm2::Type type, int id, std::string& name, locale::Type locale, int spritesheetID) + { + snapshot("Add Item"); + + anm2::Reference addReference; + + if (type == anm2::LAYER) + addReference = + anm2.layer_add({reference.animationIndex, anm2::LAYER, id}, name, spritesheetID, (locale::Type)locale); + else if (type == anm2::NULL_) + addReference = anm2.null_add({reference.animationIndex, anm2::LAYER, id}, name, (locale::Type)locale); + + reference = addReference; + + change(change::ITEMS); + } + + void Document::item_remove(anm2::Animation* animation) + { + snapshot("Remove Item"); + + if (!animation) return; + + animation->item_remove(reference.itemType, reference.itemID); + reference = {reference.animationIndex}; + change(change::ITEMS); + } + + anm2::Animation* Document::animation_get() + { + return anm2.animation_get(reference); + } + + void Document::animation_add() + { + snapshot("Add Animation"); + anm2::Animation animation; + if (anm2::Animation* referenceAnimation = animation_get()) + { + for (auto [id, layerAnimation] : referenceAnimation->layerAnimations) + animation.layerAnimations[id] = anm2::Item(); + animation.layerOrder = referenceAnimation->layerOrder; + for (auto [id, nullAnimation] : referenceAnimation->nullAnimations) + animation.nullAnimations[id] = anm2::Item(); + } + animation.rootAnimation.frames.emplace_back(anm2::Frame()); + + auto index = + animationMultiSelect.empty() ? (int)anm2.animations.items.size() - 1 : *animationMultiSelect.rbegin() + 1; + anm2.animations.items.insert(anm2.animations.items.begin() + index, animation); + animationMultiSelect = {index}; + reference = {index}; + change(change::ANIMATIONS); + } + + void Document::animation_duplicate() + { + snapshot("Duplicate Animation(s)"); + auto duplicated = animationMultiSelect; + auto duplicatedEnd = std::ranges::max(duplicated); + for (auto& id : duplicated) + { + anm2.animations.items.insert(anm2.animations.items.begin() + duplicatedEnd, anm2.animations.items[id]); + animationMultiSelect.insert(++duplicatedEnd); + animationMultiSelect.erase(id); + } + change(change::ANIMATIONS); + } + + void Document::animations_move(std::vector& indices, int index) + { + snapshot("Move Animation(s)"); + animationMultiSelect = vector::move_indices(anm2.animations.items, indices, index); + change(change::ANIMATIONS); + } + + void Document::animation_remove() + { + snapshot("Remove Animation(s)"); + for (auto& i : animationMultiSelect | std::views::reverse) + anm2.animations.items.erase(anm2.animations.items.begin() + i); + animationMultiSelect.clear(); + + change(change::ANIMATIONS); + } + + void Document::animation_default() + { + snapshot("Default Animation"); + anm2.animations.defaultAnimation = anm2.animations.items[*animationMultiSelect.begin()].name; + change(change::ANIMATIONS); + } + + void Document::animations_deserialize(const std::string& string) + { + snapshot("Paste Animations"); + auto& multiSelect = animationMultiSelect; + auto start = multiSelect.empty() ? anm2.animations.items.size() : *multiSelect.rbegin() + 1; + std::set indices{}; + std::string errorString{}; + if (anm2.animations.animations_deserialize(string, start, indices, &errorString)) + { + multiSelect = indices; + change(change::ANIMATIONS); + } + else + toasts.error(std::format("Failed to deserialize animation(s): {}", errorString)); + } + + void Document::animations_merge_quick() + { + snapshot("Merge Animations"); + int merged{}; + if (animationMultiSelect.size() > 1) + merged = anm2.animations.merge(*animationMultiSelect.begin(), animationMultiSelect); + else if (animationMultiSelect.size() == 1 && *animationMultiSelect.begin() != (int)anm2.animations.items.size() - 1) + { + auto start = *animationMultiSelect.begin(); + auto next = *animationMultiSelect.begin() + 1; + std::set animationSet{}; + animationSet.insert(start); + animationSet.insert(next); + + merged = anm2.animations.merge(start, animationSet); + } + else + return; + + animationMultiSelect = {merged}; + reference = {merged}; + change(change::ANIMATIONS); + } + + void Document::animations_merge(merge::Type type, bool isDeleteAnimationsAfter) + { + snapshot("Merge Animations"); + auto merged = anm2.animations.merge(mergeTarget, animationMergeMultiSelect, type, isDeleteAnimationsAfter); + animationMultiSelect = {merged}; + reference = {merged}; + change(change::ANIMATIONS); + } + + void Document::snapshot(const std::string& message) + { + snapshots.push(anm2, reference, message); + } + + void Document::undo() + { + snapshots.undo(anm2, reference, message); + toasts.info(std::format("Undo: {}", message)); + change(change::ALL); + } + + void Document::redo() + { + toasts.info(std::format("Redo: {}", message)); + snapshots.redo(anm2, reference, message); + change(change::ALL); + } + + bool Document::is_undo() + { + return !snapshots.undoStack.is_empty(); + } + + bool Document::is_redo() + { + return !snapshots.redoStack.is_empty(); + } +} \ No newline at end of file diff --git a/src/document.h b/src/document.h index 7097ce6..69b27ff 100644 --- a/src/document.h +++ b/src/document.h @@ -4,6 +4,9 @@ #include #include "anm2.h" +#include "imgui.h" +#include "playback.h" +#include "snapshots.h" #include "types.h" #include @@ -15,7 +18,9 @@ namespace anm2ed::document public: std::filesystem::path path{}; anm2::Anm2 anm2{}; - anm2::Reference reference{}; + std::string message{}; + playback::Playback playback{}; + snapshots::Snapshots snapshots{}; float previewZoom{200}; glm::vec2 previewPan{}; @@ -23,40 +28,92 @@ namespace anm2ed::document float editorZoom{200}; int overlayIndex{}; + anm2::Reference reference{}; + int hoveredAnimation{-1}; + int mergeTarget{-1}; + imgui::MultiSelectStorage animationMultiSelect; + imgui::MultiSelectStorage animationMergeMultiSelect; + int referenceSpritesheet{-1}; - int referenceLayer{-1}; - - std::set selectedEvents{}; - std::set selectedLayers{}; - std::set selectedNulls{}; - std::set selectedAnimations{}; - std::set selectedSpritesheets{}; - + int hoveredSpritesheet{-1}; + std::set unusedSpritesheetIDs{}; std::vector spritesheetNames{}; std::vector spritesheetNamesCstr{}; + imgui::MultiSelectStorage spritesheetMultiSelect; + + int referenceLayer{-1}; + int hoveredLayer{-1}; + std::set unusedLayerIDs{}; + imgui::MultiSelectStorage layersMultiSelect; + + int referenceNull{-1}; + int hoveredNull{-1}; + std::set unusedNullIDs{}; + imgui::MultiSelectStorage nullMultiSelect; + + int referenceEvent{-1}; + int hoveredEvent{-1}; + std::set unusedEventIDs{}; + imgui::MultiSelectStorage eventMultiSelect; uint64_t hash{}; uint64_t saveHash{}; - bool isJustChanged[types::change::COUNT]{}; bool isOpen{true}; - Document(); - - Document(const std::string& path, bool isNew = false, std::string* errorString = nullptr); - bool save(const std::string& path = {}, std::string* errorString = nullptr); + Document(const std::string&, bool = false, std::string* = nullptr); + bool save(const std::string& = {}, std::string* = nullptr); void hash_set(); void clean(); void on_change(); - void change(types::change::Type type); - bool is_just_changed(types::change::Type type); + void change(types::change::Type); bool is_dirty(); - void update(); std::string directory_get(); std::string filename_get(); - anm2::Animation* animation_get(); - anm2::Frame* frame_get(); - anm2::Item* item_get(); - anm2::Spritesheet* spritesheet_get(); bool is_valid(); + + anm2::Frame* frame_get(); + void frames_add(anm2::Item* item); + void frames_delete(anm2::Item* item); + void frames_bake(int, bool, bool); + + anm2::Item* item_get(); + void item_add(anm2::Type, int, std::string&, types::locale::Type, int); + void item_remove(anm2::Animation* animation); + + anm2::Spritesheet* spritesheet_get(); + void spritesheet_add(const std::string&); + void spritesheets_deserialize(const std::string&, types::merge::Type); + + void layer_set(anm2::Layer& layer); + void layers_remove_unused(); + void layers_deserialize(const std::string&, types::merge::Type); + + void null_set(anm2::Null& null); + void null_rect_toggle(anm2::Null& null); + void nulls_remove_unused(); + void nulls_deserialize(const std::string&, types::merge::Type); + + void event_add(); + void events_remove_unused(); + void events_deserialize(const std::string&, types::merge::Type); + + void item_visible_toggle(anm2::Item*); + + void animation_add(); + void animation_duplicate(); + void animation_default(); + void animation_remove(); + void animations_move(std::vector&, int); + void animations_merge(types::merge::Type, bool); + void animations_merge_quick(); + anm2::Animation* animation_get(); + void animations_deserialize(const std::string& string); + + void snapshot(const std::string& message); + void undo(); + void redo(); + + bool is_undo(); + bool is_redo(); }; -}; \ No newline at end of file +} diff --git a/src/document_manager.cpp b/src/document_manager.cpp deleted file mode 100644 index 2ad1207..0000000 --- a/src/document_manager.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "document_manager.h" - -#include "util.h" - -using namespace anm2ed::util; - -namespace anm2ed::document_manager -{ - Document* DocumentManager::get() - { - return vector::find(documents, selected); - } - - Document* DocumentManager::get(int index) - { - return vector::find(documents, index); - } - - bool DocumentManager::open(const std::string& path, bool isNew) - { - std::string errorString{}; - Document document = Document(path, isNew, &errorString); - if (document.is_valid()) - { - documents.emplace_back(std::move(document)); - selected = documents.size() - 1; - pendingSelected = selected; - return true; - } - return false; - } - - bool DocumentManager::new_(const std::string& path) - { - return open(path, true); - } - - void DocumentManager::save(int index, const std::string& path) - { - auto document = get(index); - if (!document) return; - std::string errorString{}; - - document->path = !path.empty() ? path : document->path.string(); - - document->save(document->path, &errorString); - } - - void DocumentManager::save(const std::string& path) - { - save(selected, path); - } - - void DocumentManager::close(int index) - { - documents.erase(documents.begin() + index); - } -} diff --git a/src/document_manager.h b/src/document_manager.h deleted file mode 100644 index 8bd5071..0000000 --- a/src/document_manager.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include - -#include "document.h" - -using namespace anm2ed::document; - -namespace anm2ed::document_manager -{ - class DocumentManager - { - public: - std::vector documents{}; - int selected{}; - int pendingSelected{}; - - Document* get(); - Document* get(int index); - bool open(const std::string& path, bool isNew = false); - bool new_(const std::string& path); - void save(int index, const std::string& path = {}); - void save(const std::string& path = {}); - void close(int index); - void spritesheet_add(const std::string& path); - }; -} diff --git a/src/documents.cpp b/src/documents.cpp index 1059a0d..ebfa28a 100644 --- a/src/documents.cpp +++ b/src/documents.cpp @@ -5,12 +5,12 @@ #include "imgui.h" using namespace anm2ed::taskbar; -using namespace anm2ed::document_manager; +using namespace anm2ed::manager; using namespace anm2ed::resources; namespace anm2ed::documents { - void Documents::update(Taskbar& taskbar, DocumentManager& manager, Resources& resources) + void Documents::update(Taskbar& taskbar, Manager& manager, Resources& resources) { auto viewport = ImGui::GetMainViewport(); auto windowHeight = ImGui::GetFrameHeightWithSpacing(); @@ -32,7 +32,6 @@ namespace anm2ed::documents for (auto [i, document] : std::views::enumerate(manager.documents)) { auto isDirty = document.is_dirty(); - auto isSelected = i == manager.selected; auto isRequested = i == manager.pendingSelected; auto font = isDirty ? font::ITALICS : font::REGULAR; @@ -65,8 +64,6 @@ namespace anm2ed::documents else manager.close(i); } - - if (isSelected) document.update(); } ImGui::EndTabBar(); diff --git a/src/documents.h b/src/documents.h index f5bb60a..4aa184a 100644 --- a/src/documents.h +++ b/src/documents.h @@ -1,7 +1,7 @@ #pragma once -#include "document_manager.h" #include "imgui.h" +#include "manager.h" #include "resources.h" #include "taskbar.h" @@ -17,6 +17,6 @@ namespace anm2ed::documents public: float height{}; - void update(taskbar::Taskbar& taskbar, document_manager::DocumentManager& manager, resources::Resources& resources); + void update(taskbar::Taskbar&, manager::Manager&, resources::Resources&); }; } diff --git a/src/events.cpp b/src/events.cpp index 7e69b83..46def77 100644 --- a/src/events.cpp +++ b/src/events.cpp @@ -2,22 +2,21 @@ #include -using namespace anm2ed::document_manager; +using namespace anm2ed::clipboard; +using namespace anm2ed::manager; using namespace anm2ed::settings; using namespace anm2ed::resources; using namespace anm2ed::types; namespace anm2ed::events { - void Events::update(DocumentManager& manager, Settings& settings, Resources& resources) + void Events::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) { auto& document = *manager.get(); auto& anm2 = document.anm2; - auto& selection = document.selectedEvents; - - if (document.is_just_changed(change::EVENTS)) unusedEventIDs = anm2.events_unused(); - - storage.user_data_set(&selection); + auto& unused = document.unusedEventIDs; + auto& hovered = document.hoveredEvent; + auto& multiSelect = document.eventMultiSelect; if (ImGui::Begin("Events", &settings.windowIsEvents)) { @@ -26,17 +25,16 @@ namespace anm2ed::events if (ImGui::BeginChild("##Events Child", childSize, true)) { - storage.begin(anm2.content.events.size()); + multiSelect.start(anm2.content.events.size()); for (auto& [id, event] : anm2.content.events) { - auto isSelected = selection.contains(id); - ImGui::PushID(id); ImGui::SetNextItemSelectionUserData(id); if (imgui::selectable_input_text(event.name, std::format("###Document #{} Event #{}", manager.selected, id), - event.name, isSelected, 0, &isRenamed)) - if (isRenamed) document.change(change::EVENTS); + event.name, multiSelect.contains(id), 0, &isRenamed)) + if (ImGui::IsItemHovered()) hovered = id; + if (isRenamed) document.change(change::EVENTS); if (ImGui::BeginItemTooltip()) { ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); @@ -47,34 +45,67 @@ namespace anm2ed::events ImGui::PopID(); } - storage.end(); + multiSelect.finish(); + + auto copy = [&]() + { + if (!multiSelect.empty()) + { + std::string clipboardText{}; + for (auto& id : multiSelect) + clipboardText += anm2.content.events[id].to_string(id); + clipboard.set(clipboardText); + } + else if (hovered > -1) + clipboard.set(anm2.content.events[hovered].to_string(hovered)); + }; + + auto paste = [&](merge::Type type) + { + auto clipboardText = clipboard.get(); + document.events_deserialize(clipboardText, type); + }; + + if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (imgui::shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::BeginDisabled(); + ImGui::MenuItem("Cut", settings.shortcutCut.c_str()); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(multiSelect.empty() && hovered == -1); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(clipboard.is_empty()); + { + if (ImGui::BeginMenu("Paste")) + { + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + + ImGui::EndMenu(); + } + } + ImGui::EndDisabled(); + + ImGui::EndPopup(); + } } ImGui::EndChild(); auto widgetSize = imgui::widget_size_with_row_get(2); imgui::shortcut(settings.shortcutAdd); - if (ImGui::Button("Add", widgetSize)) - { - int id{}; - anm2.event_add(id); - selection = {id}; - document.change(change::EVENTS); - } + if (ImGui::Button("Add", widgetSize)) document.event_add(); imgui::set_item_tooltip_shortcut("Add an event.", settings.shortcutAdd); ImGui::SameLine(); imgui::shortcut(settings.shortcutRemove); - ImGui::BeginDisabled(unusedEventIDs.empty()); - { - if (ImGui::Button("Remove Unused", widgetSize)) - { - for (auto& id : unusedEventIDs) - anm2.content.events.erase(id); - document.change(change::EVENTS); - unusedEventIDs.clear(); - } - } + ImGui::BeginDisabled(unused.empty()); + if (ImGui::Button("Remove Unused", widgetSize)) document.events_remove_unused(); ImGui::EndDisabled(); imgui::set_item_tooltip_shortcut("Remove unused events (i.e., ones not used by any trigger in any animation.)", settings.shortcutRemove); diff --git a/src/events.h b/src/events.h index f38f3bf..ef27454 100644 --- a/src/events.h +++ b/src/events.h @@ -1,7 +1,7 @@ #pragma once -#include "document_manager.h" -#include "imgui.h" +#include "clipboard.h" +#include "manager.h" #include "resources.h" #include "settings.h" @@ -9,11 +9,8 @@ namespace anm2ed::events { class Events { - imgui::MultiSelectStorage storage{}; - std::set unusedEventIDs{}; public: - void update(document_manager::DocumentManager& manager, settings::Settings& settings, - resources::Resources& resources); + void update(manager::Manager&, settings::Settings&, resources::Resources&, clipboard::Clipboard&); }; } diff --git a/src/filesystem.h b/src/filesystem.h index 804ed22..0959d78 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -6,15 +6,15 @@ namespace anm2ed::filesystem { std::string path_preferences_get(); - bool path_is_exist(const std::string& path); - bool path_is_extension(const std::string& path, const std::string& extension); + bool path_is_exist(const std::string&); + bool path_is_extension(const std::string&, const std::string&); class WorkingDirectory { public: std::filesystem::path previous; - WorkingDirectory(const std::string& path, bool isFile = false); + WorkingDirectory(const std::string&, bool = false); ~WorkingDirectory(); }; -} \ No newline at end of file +} diff --git a/src/font.h b/src/font.h index e6dccc2..f5e4802 100644 --- a/src/font.h +++ b/src/font.h @@ -5230,9 +5230,9 @@ namespace anm2ed::font public: Font(); - Font(void* data, size_t length, int size); + Font(void*, size_t, int); ~Font(); ImFont* get(); - Font& operator=(Font&& other) noexcept; + Font& operator=(Font&&) noexcept; }; -}; \ No newline at end of file +}; diff --git a/src/frame_properties.cpp b/src/frame_properties.cpp index 35ec7ff..57e75f0 100644 --- a/src/frame_properties.cpp +++ b/src/frame_properties.cpp @@ -9,7 +9,7 @@ #include "types.h" using namespace anm2ed::settings; -using namespace anm2ed::document_manager; +using namespace anm2ed::manager; using namespace anm2ed::math; using namespace anm2ed::types; using namespace glm; @@ -17,7 +17,7 @@ using namespace glm; namespace anm2ed::frame_properties { - void FrameProperties::update(DocumentManager& manager, Settings& settings) + void FrameProperties::update(Manager& manager, Settings& settings) { if (ImGui::Begin("Frame Properties", &settings.windowIsFrameProperties)) { diff --git a/src/frame_properties.h b/src/frame_properties.h index 27ea5ee..ab092ee 100644 --- a/src/frame_properties.h +++ b/src/frame_properties.h @@ -1,6 +1,6 @@ #pragma once -#include "document_manager.h" +#include "manager.h" #include "settings.h" namespace anm2ed::frame_properties @@ -8,6 +8,6 @@ namespace anm2ed::frame_properties class FrameProperties { public: - void update(document_manager::DocumentManager& manager, settings::Settings& settings); + void update(manager::Manager&, settings::Settings&); }; -} \ No newline at end of file +} diff --git a/src/icon.h b/src/icon.h index 737a2c3..7af6181 100644 --- a/src/icon.h +++ b/src/icon.h @@ -118,7 +118,7 @@ namespace icon )"; constexpr auto TARGET_DATA = R"( - + )"; constexpr auto INTERPOLATED_DATA = R"( @@ -142,7 +142,7 @@ namespace icon )"; #define LIST \ - X(NONE, NONE_DATA, SIZE_NORMAL) \ + X(NONE, NONE_DATA, SIZE_SMALL) \ X(FILE, FILE_DATA, SIZE_NORMAL) \ X(FOLDER, FOLDER_DATA, SIZE_NORMAL) \ X(CLOSE, CLOSE_DATA, SIZE_NORMAL) \ diff --git a/src/imgui.cpp b/src/imgui.cpp index c3a3007..883c15d 100644 --- a/src/imgui.cpp +++ b/src/imgui.cpp @@ -252,19 +252,15 @@ namespace anm2ed::imgui internal.AdapterSetItemSelected = external_storage_set; } - void MultiSelectStorage::user_data_set(std::set* userData) + void MultiSelectStorage::start(size_t size) { - internal.UserData = userData; - this->userData = userData; - } + internal.UserData = this; - void MultiSelectStorage::begin(size_t size) - { - auto io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, userData ? userData->size() : 0, size); + auto io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, this->size(), size); internal.ApplyRequests(io); } - void MultiSelectStorage::end() + void MultiSelectStorage::finish() { auto io = ImGui::EndMultiSelect(); internal.ApplyRequests(io); @@ -281,6 +277,7 @@ namespace anm2ed::imgui { isOpen = true; isTriggered = true; + isJustOpened = true; } void PopupHelper::trigger() @@ -296,6 +293,11 @@ namespace anm2ed::imgui ImGui::SetNextWindowSize(to_imvec2(to_vec2(viewport->Size) * percent)); } + void PopupHelper::end() + { + isJustOpened = false; + } + void PopupHelper::close() { isOpen = false; diff --git a/src/imgui.h b/src/imgui.h index 7206a54..2deec12 100644 --- a/src/imgui.h +++ b/src/imgui.h @@ -124,37 +124,43 @@ namespace anm2ed::imgui {"Super", ImGuiMod_Super}, }; - std::string chord_to_string(ImGuiKeyChord chord); - ImGuiKeyChord string_to_chord(const std::string& string); - float row_widget_width_get(int count, float width = ImGui::GetContentRegionAvail().x); - ImVec2 widget_size_with_row_get(int count, float width = ImGui::GetContentRegionAvail().x); - float footer_height_get(int itemCount = 1); - ImVec2 footer_size_get(int itemCount = 1); - ImVec2 size_without_footer_get(int rowCount = 1); - ImVec2 child_size_get(int rowCount = 1); - int input_text_callback(ImGuiInputTextCallbackData* data); - bool input_text_string(const char* label, std::string* string, ImGuiInputTextFlags flags = 0); - void combo_strings(const std::string& label, int* index, std::vector& strings); - void combo_strings(const std::string& label, int* index, std::vector& strings); - bool selectable_input_text(const std::string& label, const std::string& id, std::string& text, - bool isSelected = false, ImGuiSelectableFlags flags = 0, bool* isRenamed = nullptr); - void set_item_tooltip_shortcut(const char* tooltip, const std::string& shortcut = {}); - void external_storage_set(ImGuiSelectionExternalStorage* self, int id, bool isSelected); + std::string chord_to_string(ImGuiKeyChord); + ImGuiKeyChord string_to_chord(const std::string&); + float row_widget_width_get(int, float = ImGui::GetContentRegionAvail().x); + ImVec2 widget_size_with_row_get(int, float = ImGui::GetContentRegionAvail().x); + float footer_height_get(int = 1); + ImVec2 footer_size_get(int = 1); + ImVec2 size_without_footer_get(int = 1); + ImVec2 child_size_get(int = 1); + int input_text_callback(ImGuiInputTextCallbackData*); + bool input_text_string(const char*, std::string*, ImGuiInputTextFlags = 0); + void combo_strings(const std::string&, int*, std::vector&); + void combo_strings(const std::string&, int*, std::vector&); + bool selectable_input_text(const std::string&, const std::string&, std::string&, bool = false, + ImGuiSelectableFlags = 0, bool* = nullptr); + void set_item_tooltip_shortcut(const char*, const std::string& = {}); + void external_storage_set(ImGuiSelectionExternalStorage*, int, bool); ImVec2 icon_size_get(); - bool chord_held(ImGuiKeyChord chord); - bool chord_repeating(ImGuiKeyChord chord, float delay = 0.125f, float rate = 0.025f); - bool shortcut(std::string string, types::shortcut::Type type = types::shortcut::FOCUSED_SET); + bool chord_held(ImGuiKeyChord); + bool chord_repeating(ImGuiKeyChord, float = 0.125f, float = 0.025f); + bool shortcut(std::string, types::shortcut::Type = types::shortcut::FOCUSED_SET); - class MultiSelectStorage + class MultiSelectStorage : public std::set { public: ImGuiSelectionExternalStorage internal{}; - std::set* userData{}; + using std::set::set; + using std::set::operator=; + using std::set::begin; + using std::set::rbegin; + using std::set::end; + using std::set::size; + using std::set::insert; + using std::set::erase; MultiSelectStorage(); - void user_data_set(std::set* userData); - void begin(size_t size); - void end(); + void start(size_t); + void finish(); }; class PopupHelper @@ -163,12 +169,14 @@ namespace anm2ed::imgui const char* label{}; bool isOpen{}; bool isTriggered{}; + bool isJustOpened{}; bool isNoHeight{}; float percent{}; - PopupHelper(const char* label, float percent = POPUP_NORMAL, bool isNoHeight = false); + PopupHelper(const char*, float = POPUP_NORMAL, bool = false); void open(); void trigger(); + void end(); void close(); }; -} \ No newline at end of file +} diff --git a/src/layers.cpp b/src/layers.cpp index a7b958a..69b1546 100644 --- a/src/layers.cpp +++ b/src/layers.cpp @@ -2,38 +2,24 @@ #include -#include "util.h" - using namespace anm2ed::document; -using namespace anm2ed::settings; +using namespace anm2ed::clipboard; +using namespace anm2ed::manager; using namespace anm2ed::resources; +using namespace anm2ed::settings; using namespace anm2ed::types; -using namespace anm2ed::util; namespace anm2ed::layers { - void Layers::update(Document& document, Settings& settings, Resources& resources) + void Layers::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) { + auto& document = *manager.get(); auto& anm2 = document.anm2; - auto& selection = document.selectedLayers; - auto& referenceLayer = document.referenceLayer; - - if (document.is_just_changed(change::LAYERS)) unusedLayerIDs = anm2.layers_unused(); - - storage.user_data_set(&selection); - - auto properties_popup_open = [&](int id = -1) - { - if (id == -1) - { - isAdd = true; - editLayer = anm2::Layer(); - } - else - editLayer = anm2.content.layers.at(id); - - propertiesPopup.open(); - }; + auto& reference = document.referenceLayer; + auto& unused = document.unusedLayerIDs; + auto& hovered = document.hoveredLayer; + auto& multiSelect = document.layersMultiSelect; + auto& propertiesPopup = manager.layerPropertiesPopup; if (ImGui::Begin("Layers", &settings.windowIsLayers)) { @@ -41,26 +27,24 @@ namespace anm2ed::layers if (ImGui::BeginChild("##Layers Child", childSize, true)) { - storage.begin(anm2.content.layers.size()); + multiSelect.start(anm2.content.layers.size()); for (auto& [id, layer] : anm2.content.layers) { - auto isSelected = selection.contains(id); - auto isReferenced = referenceLayer == id; + auto isSelected = multiSelect.contains(id); ImGui::PushID(id); ImGui::SetNextItemSelectionUserData(id); - if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); - ImGui::Selectable(std::format("#{} {} (Spritesheet: #{})", id, layer.name, layer.spritesheetID).c_str(), - isSelected); - if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + ImGui::Selectable(std::format(anm2::LAYER_FORMAT, id, layer.name, layer.spritesheetID).c_str(), isSelected); + if (ImGui::IsItemHovered()) { - referenceLayer = id; - properties_popup_open(id); + hovered = id; + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) manager.layer_properties_open(id); } + else + hovered = -1; - if (isReferenced) ImGui::PopFont(); if (ImGui::BeginItemTooltip()) { ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); @@ -73,50 +57,83 @@ namespace anm2ed::layers ImGui::PopID(); } - storage.end(); + multiSelect.finish(); + + auto copy = [&]() + { + if (!multiSelect.empty()) + { + std::string clipboardText{}; + for (auto& id : multiSelect) + clipboardText += anm2.content.layers[id].to_string(id); + clipboard.set(clipboardText); + } + else if (hovered > -1) + clipboard.set(anm2.content.layers[hovered].to_string(hovered)); + }; + + auto paste = [&](merge::Type type) + { + auto clipboardText = clipboard.get(); + document.layers_deserialize(clipboardText, type); + }; + + if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (imgui::shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::BeginDisabled(); + ImGui::MenuItem("Cut", settings.shortcutCut.c_str()); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(multiSelect.empty() && hovered == -1); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(clipboard.is_empty()); + { + if (ImGui::BeginMenu("Paste")) + { + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + + ImGui::EndMenu(); + } + } + ImGui::EndDisabled(); + + ImGui::EndPopup(); + } } ImGui::EndChild(); auto widgetSize = imgui::widget_size_with_row_get(2); imgui::shortcut(settings.shortcutAdd); - if (ImGui::Button("Add", widgetSize)) properties_popup_open(); + if (ImGui::Button("Add", widgetSize)) manager.layer_properties_open(); imgui::set_item_tooltip_shortcut("Add a layer.", settings.shortcutAdd); ImGui::SameLine(); imgui::shortcut(settings.shortcutRemove); - ImGui::BeginDisabled(unusedLayerIDs.empty()); - { - if (ImGui::Button("Remove Unused", widgetSize)) - { - for (auto& id : unusedLayerIDs) - anm2.content.layers.erase(id); - document.change(change::LAYERS); - unusedLayerIDs.clear(); - } - } + ImGui::BeginDisabled(unused.empty()); + if (ImGui::Button("Remove Unused", widgetSize)) document.layers_remove_unused(); ImGui::EndDisabled(); imgui::set_item_tooltip_shortcut("Remove unused layers (i.e., ones not used in any animation.)", settings.shortcutRemove); } ImGui::End(); - propertiesPopup.trigger(); + manager.layer_properties_trigger(); if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) { auto childSize = imgui::child_size_get(2); - auto& layer = editLayer; - - auto close = [&]() - { - isAdd = false; - editLayer = anm2::Layer(); - propertiesPopup.close(); - }; + auto& layer = manager.editLayer; if (ImGui::BeginChild("Child", childSize, ImGuiChildFlags_Borders)) { + if (propertiesPopup.isJustOpened) ImGui::SetKeyboardFocusHere(); imgui::input_text_string("Name", &layer.name); ImGui::SetItemTooltip("Set the item's name."); imgui::combo_strings("Spritesheet", &layer.spritesheetID, document.spritesheetNames); @@ -126,27 +143,18 @@ namespace anm2ed::layers auto widgetSize = imgui::widget_size_with_row_get(2); - if (ImGui::Button(isAdd ? "Add" : "Confirm", widgetSize)) + if (ImGui::Button(reference == -1 ? "Add" : "Confirm", widgetSize)) { - if (isAdd) - { - auto id = map::next_id_get(anm2.content.layers); - anm2.content.layers[id] = editLayer; - referenceLayer = id; - } - else - anm2.content.layers[referenceLayer] = editLayer; - document.change(change::LAYERS); - close(); + document.layer_set(layer); + manager.layer_properties_close(); } ImGui::SameLine(); - if (ImGui::Button("Cancel", widgetSize)) close(); + if (ImGui::Button("Cancel", widgetSize)) manager.layer_properties_close(); + manager.layer_properties_end(); ImGui::EndPopup(); } - - referenceLayer = propertiesPopup.isOpen ? referenceLayer : -1; } } diff --git a/src/layers.h b/src/layers.h index ed1538f..e72c331 100644 --- a/src/layers.h +++ b/src/layers.h @@ -1,22 +1,15 @@ #pragma once -#include "document.h" +#include "clipboard.h" +#include "manager.h" #include "resources.h" #include "settings.h" -#include "imgui.h" - namespace anm2ed::layers { class Layers { - bool isAdd{}; - imgui::PopupHelper propertiesPopup{imgui::PopupHelper("Layer Properties", imgui::POPUP_SMALL, true)}; - imgui::MultiSelectStorage storage; - anm2::Layer editLayer{}; - std::set unusedLayerIDs{}; - public: - void update(document::Document& document, settings::Settings& settings, resources::Resources& resources); + void update(manager::Manager&, settings::Settings&, resources::Resources&, clipboard::Clipboard&); }; -} \ No newline at end of file +} diff --git a/src/loader.h b/src/loader.h index fda6a20..d3cbbb1 100644 --- a/src/loader.h +++ b/src/loader.h @@ -18,7 +18,7 @@ namespace anm2ed::loader std::vector arguments; bool isError{}; - Loader(int argc, const char** argv); + Loader(int, const char**); ~Loader(); }; } diff --git a/src/log.h b/src/log.h index 84b61f5..1870827 100644 --- a/src/log.h +++ b/src/log.h @@ -30,15 +30,15 @@ namespace anm2ed::log std::ofstream file{}; public: - void write(const Level level, const std::string& message); - void info(const std::string& message); - void warning(const std::string& message); - void error(const std::string& message); - void fatal(const std::string& message); - void open(const std::filesystem::path& path); + void write(const Level, const std::string&); + void info(const std::string&); + void warning(const std::string&); + void error(const std::string&); + void fatal(const std::string&); + void open(const std::filesystem::path&); Logger(); ~Logger(); }; extern Logger logger; -} \ No newline at end of file +} diff --git a/src/manager.cpp b/src/manager.cpp new file mode 100644 index 0000000..a839622 --- /dev/null +++ b/src/manager.cpp @@ -0,0 +1,120 @@ +#include "manager.h" + +#include "toast.h" + +#include "util.h" + +using namespace anm2ed::toast; +using namespace anm2ed::types; +using namespace anm2ed::util; + +namespace anm2ed::manager +{ + Document* Manager::get(int index) + { + return vector::find(documents, index > -1 ? index : selected); + } + + void Manager::open(const std::string& path, bool isNew) + { + std::string errorString{}; + Document document = Document(path, isNew, &errorString); + if (document.is_valid()) + { + documents.emplace_back(std::move(document)); + selected = documents.size() - 1; + pendingSelected = selected; + toasts.info(std::format("Initialized document: {}", path)); + } + else + toasts.error(std::format("Failed to initialize document: {} ({})", path, errorString)); + } + + void Manager::new_(const std::string& path) + { + open(path, true); + } + + void Manager::save(int index, const std::string& path) + { + if (auto document = get(index); document) + { + std::string errorString{}; + document->path = !path.empty() ? path : document->path.string(); + document->save(document->path, &errorString); + } + } + + void Manager::save(const std::string& path) + { + save(selected, path); + } + + void Manager::close(int index) + { + documents.erase(documents.begin() + index); + } + + void Manager::layer_properties_open(int id) + { + if (auto document = get(); document) + { + if (id == -1) + editLayer = anm2::Layer(); + else + editLayer = document->anm2.content.layers.at(id); + + document->referenceLayer = id; + + layerPropertiesPopup.open(); + } + } + + void Manager::layer_properties_trigger() + { + layerPropertiesPopup.trigger(); + } + + void Manager::layer_properties_end() + { + layerPropertiesPopup.end(); + } + + void Manager::layer_properties_close() + { + editLayer = anm2::Layer(); + layerPropertiesPopup.close(); + } + + void Manager::null_properties_open(int id) + { + if (auto document = get(); document) + { + if (id == -1) + editNull = anm2::Null(); + else + editNull = document->anm2.content.nulls.at(id); + + document->referenceNull = id; + + nullPropertiesPopup.open(); + } + } + + void Manager::null_properties_trigger() + { + nullPropertiesPopup.trigger(); + } + + void Manager::null_properties_end() + { + nullPropertiesPopup.end(); + } + + void Manager::null_properties_close() + { + editNull = anm2::Null(); + nullPropertiesPopup.close(); + } + +} diff --git a/src/manager.h b/src/manager.h new file mode 100644 index 0000000..1d46381 --- /dev/null +++ b/src/manager.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include "document.h" +#include "imgui.h" + +using namespace anm2ed::document; + +namespace anm2ed::manager +{ + class Manager + { + public: + std::vector documents{}; + int selected{}; + int pendingSelected{}; + + anm2::Layer editLayer{}; + imgui::PopupHelper layerPropertiesPopup{imgui::PopupHelper("Layer Properties", imgui::POPUP_SMALL, true)}; + + anm2::Null editNull{}; + imgui::PopupHelper nullPropertiesPopup{imgui::PopupHelper("Null Properties", imgui::POPUP_SMALL, true)}; + + Document* get(int = -1); + void open(const std::string&, bool = false); + void new_(const std::string&); + void save(int, const std::string& = {}); + void save(const std::string& = {}); + void close(int); + void layer_properties_open(int = -1); + void layer_properties_trigger(); + void layer_properties_end(); + void layer_properties_close(); + void null_properties_open(int = -1); + void null_properties_trigger(); + void null_properties_end(); + void null_properties_close(); + }; +} diff --git a/src/math.h b/src/math.h index c058de3..6e928be 100644 --- a/src/math.h +++ b/src/math.h @@ -31,16 +31,15 @@ namespace anm2ed::math 1.0f, 1.0f, uvMax.x, uvMax.y, 0.0f, 1.0f, uvMin.x, uvMax.y}; } - float round_nearest_multiple(float value, float multiple); + float round_nearest_multiple(float, float); - int float_decimals_needed(float value); + int float_decimals_needed(float); - const char* float_format_get(float value); + const char* float_format_get(float); - const char* vec2_format_get(glm::vec2& value); + const char* vec2_format_get(glm::vec2&); - glm::mat4 quad_model_get(glm::vec2 size = {}, glm::vec2 position = {}, glm::vec2 pivot = {}, - glm::vec2 scale = glm::vec2(1.0f), float rotation = {}); - glm::mat4 quad_model_parent_get(glm::vec2 position = {}, glm::vec2 pivot = {}, glm::vec2 scale = glm::vec2(1.0f), - float rotation = {}); -} \ No newline at end of file + glm::mat4 quad_model_get(glm::vec2 = {}, glm::vec2 = {}, glm::vec2 = {}, + glm::vec2 = glm::vec2(1.0f), float = {}); + glm::mat4 quad_model_parent_get(glm::vec2 = {}, glm::vec2 = {}, glm::vec2 = glm::vec2(1.0f), float = {}); +} diff --git a/src/nulls.cpp b/src/nulls.cpp index fd6eef4..f40dd9e 100644 --- a/src/nulls.cpp +++ b/src/nulls.cpp @@ -2,21 +2,23 @@ #include -using namespace anm2ed::document; +using namespace anm2ed::clipboard; +using namespace anm2ed::manager; using namespace anm2ed::settings; using namespace anm2ed::resources; using namespace anm2ed::types; namespace anm2ed::nulls { - void Nulls::update(Document& document, int& documentIndex, Settings& settings, Resources& resources) + void Nulls::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) { + auto& document = *manager.get(); auto& anm2 = document.anm2; - auto& selection = document.selectedNulls; - - if (document.is_just_changed(change::NULLS)) unusedNullsIDs = anm2.nulls_unused(); - - storage.user_data_set(&selection); + auto& reference = document.referenceNull; + auto& unused = document.unusedNullIDs; + auto& hovered = document.hoveredNull; + auto& multiSelect = document.nullMultiSelect; + auto& propertiesPopup = manager.nullPropertiesPopup; if (ImGui::Begin("Nulls", &settings.windowIsNulls)) { @@ -24,17 +26,25 @@ namespace anm2ed::nulls if (ImGui::BeginChild("##Nulls Child", childSize, true)) { - storage.begin(anm2.content.nulls.size()); + multiSelect.start(anm2.content.nulls.size()); for (auto& [id, null] : anm2.content.nulls) { - auto isSelected = selection.contains(id); + auto isSelected = multiSelect.contains(id); + auto isReferenced = reference == id; ImGui::PushID(id); ImGui::SetNextItemSelectionUserData(id); - imgui::selectable_input_text(std::format("#{} {}", id, null.name), - std::format("###Document #{} Null #{}", documentIndex, id), null.name, - isSelected); + if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); + ImGui::Selectable(std::format(anm2::NULL_FORMAT, id, null.name).c_str(), isSelected); + if (ImGui::IsItemHovered()) + { + hovered = id; + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) manager.null_properties_open(id); + } + + if (isReferenced) ImGui::PopFont(); + if (ImGui::BeginItemTooltip()) { ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); @@ -46,29 +56,106 @@ namespace anm2ed::nulls ImGui::PopID(); } - storage.end(); + multiSelect.finish(); + + auto copy = [&]() + { + if (!multiSelect.empty()) + { + std::string clipboardText{}; + for (auto& id : multiSelect) + clipboardText += anm2.content.nulls[id].to_string(id); + clipboard.set(clipboardText); + } + else if (hovered > -1) + clipboard.set(anm2.content.nulls[hovered].to_string(hovered)); + }; + + auto paste = [&](merge::Type type) + { + auto clipboardText = clipboard.get(); + document.nulls_deserialize(clipboardText, type); + }; + + if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (imgui::shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::BeginDisabled(); + ImGui::MenuItem("Cut", settings.shortcutCut.c_str()); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(multiSelect.empty() && hovered == -1); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(clipboard.is_empty()); + { + if (ImGui::BeginMenu("Paste")) + { + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + + ImGui::EndMenu(); + } + } + ImGui::EndDisabled(); + + ImGui::EndPopup(); + } } ImGui::EndChild(); auto widgetSize = imgui::widget_size_with_row_get(2); imgui::shortcut(settings.shortcutAdd); - ImGui::Button("Add", widgetSize); + if (ImGui::Button("Add", widgetSize)) manager.null_properties_open(); imgui::set_item_tooltip_shortcut("Add a null.", settings.shortcutAdd); ImGui::SameLine(); imgui::shortcut(settings.shortcutRemove); - ImGui::BeginDisabled(unusedNullsIDs.empty()); - { - if (ImGui::Button("Remove Unused", widgetSize)) - for (auto& id : unusedNullsIDs) - anm2.content.nulls.erase(id); - document.change(change::NULLS); - } + ImGui::BeginDisabled(unused.empty()); + if (ImGui::Button("Remove Unused", widgetSize)) document.nulls_remove_unused(); ImGui::EndDisabled(); imgui::set_item_tooltip_shortcut("Remove unused nulls (i.e., ones not used in any animation.)", settings.shortcutRemove); } ImGui::End(); + + manager.null_properties_trigger(); + + if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto childSize = imgui::child_size_get(2); + auto& null = manager.editNull; + + if (ImGui::BeginChild("Child", childSize, ImGuiChildFlags_Borders)) + { + if (propertiesPopup.isJustOpened) ImGui::SetKeyboardFocusHere(); + imgui::input_text_string("Name", &null.name); + ImGui::SetItemTooltip("Set the null's name."); + + ImGui::Checkbox("Rect", &null.isShowRect); + ImGui::SetItemTooltip("The null will have a rectangle show around it."); + } + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + if (ImGui::Button(reference == -1 ? "Add" : "Confirm", widgetSize)) + { + document.null_set(null); + manager.null_properties_close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) manager.null_properties_close(); + + ImGui::EndPopup(); + } + + manager.null_properties_end(); } } \ No newline at end of file diff --git a/src/nulls.h b/src/nulls.h index 3acc7bb..1eba1bb 100644 --- a/src/nulls.h +++ b/src/nulls.h @@ -1,7 +1,7 @@ #pragma once -#include "document.h" -#include "imgui.h" +#include "clipboard.h" +#include "manager.h" #include "resources.h" #include "settings.h" @@ -9,11 +9,7 @@ namespace anm2ed::nulls { class Nulls { - imgui::MultiSelectStorage storage{}; - std::set unusedNullsIDs{}; - public: - void update(document::Document& document, int& documentIndex, settings::Settings& settings, - resources::Resources& resources); + void update(manager::Manager&, settings::Settings&, resources::Resources&, clipboard::Clipboard&); }; } \ No newline at end of file diff --git a/src/onionskin.cpp b/src/onionskin.cpp index 970aaf1..1ec35b6 100644 --- a/src/onionskin.cpp +++ b/src/onionskin.cpp @@ -3,6 +3,7 @@ #include #include "imgui.h" +#include "types.h" using namespace anm2ed::settings; using namespace anm2ed::types; @@ -24,7 +25,6 @@ namespace anm2ed::onionskin ImGui::PopID(); }; - imgui::shortcut(settings.shortcutOnionskin); ImGui::Checkbox("Enabled", &settings.onionskinIsEnabled); order_configure("Before", settings.onionskinBeforeCount, settings.onionskinBeforeColor); @@ -32,14 +32,14 @@ namespace anm2ed::onionskin ImGui::Text("Order"); ImGui::SameLine(); - ImGui::RadioButton("Before", &settings.onionskinDrawOrder, BELOW); + ImGui::RadioButton("Before", &settings.onionskinDrawOrder, draw_order::BELOW); ImGui::SameLine(); - ImGui::RadioButton("After", &settings.onionskinDrawOrder, ABOVE); + ImGui::RadioButton("After", &settings.onionskinDrawOrder, draw_order::ABOVE); } - - if (imgui::shortcut(settings.shortcutOnionskin), shortcut::GLOBAL) - settings.onionskinIsEnabled = !settings.onionskinIsEnabled; - ImGui::End(); + + if (imgui::shortcut(settings.shortcutOnionskin, shortcut::GLOBAL)) + settings.onionskinIsEnabled = !settings.onionskinIsEnabled; } + } diff --git a/src/onionskin.h b/src/onionskin.h index 2157670..43f9358 100644 --- a/src/onionskin.h +++ b/src/onionskin.h @@ -4,15 +4,9 @@ namespace anm2ed::onionskin { - enum Type - { - BELOW, - ABOVE - }; - class Onionskin { public: - void update(settings::Settings& settings); + void update(settings::Settings&); }; } diff --git a/src/playback.h b/src/playback.h index edbd7f3..291c527 100644 --- a/src/playback.h +++ b/src/playback.h @@ -10,9 +10,9 @@ namespace anm2ed::playback bool isFinished{}; void toggle(); - void clamp(int length); - void tick(int fps, int length, bool isLoop); - void decrement(int length); - void increment(int length); + void clamp(int); + void tick(int, int, bool); + void decrement(int); + void increment(int); }; -} \ No newline at end of file +} diff --git a/src/settings.h b/src/settings.h index 3fa327f..535c27a 100644 --- a/src/settings.h +++ b/src/settings.h @@ -206,8 +206,8 @@ namespace anm2ed::settings Settings(); - Settings(const std::string& path); - void save(const std::string& path, const std::string& imguiData); + Settings(const std::string&); + void save(const std::string&, const std::string&); }; enum ShortcutType diff --git a/src/shader.h b/src/shader.h index a0ff1d5..c29db47 100644 --- a/src/shader.h +++ b/src/shader.h @@ -39,19 +39,6 @@ namespace anm2ed::shader } )"; - constexpr auto GRID_VERTEX = R"( -#version 330 core -layout (location = 0) in vec2 i_position; -layout (location = 1) in vec2 i_uv; - -out vec2 i_uv_out; - -void main() { - i_uv_out = i_position; - gl_Position = vec4(i_position, 0.0, 1.0); -} - )"; - constexpr auto FRAGMENT = R"( #version 330 core out vec4 o_fragColor; @@ -78,6 +65,19 @@ void main() { } )"; + constexpr auto GRID_VERTEX = R"( +#version 330 core +layout (location = 0) in vec2 i_position; +layout (location = 1) in vec2 i_uv; + +out vec2 i_uv_out; + +void main() { + i_uv_out = i_position; + gl_Position = vec4(i_position, 0.0, 1.0); +} + )"; + constexpr auto GRID_FRAGMENT = R"( #version 330 core in vec2 i_uv_out; @@ -98,6 +98,7 @@ void main() { vec2 pan = u_pan; vec2 world = (i_uv_out - (2.0 * pan / viewSize)) * (viewSize / (2.0 * zoom)); + world += vec2(0.5); // Half pixel nudge vec2 cell = max(u_size, vec2(1.0)); vec2 grid = (world - u_offset) / cell; @@ -148,8 +149,8 @@ void main() { GLuint id{}; Shader(); - Shader(const char* vertex, const char* fragment); - Shader& operator=(Shader&& other) noexcept; + Shader(const char*, const char*); + Shader& operator=(Shader&&) noexcept; ~Shader(); bool is_valid() const; }; diff --git a/src/snapshots.cpp b/src/snapshots.cpp new file mode 100644 index 0000000..a456be6 --- /dev/null +++ b/src/snapshots.cpp @@ -0,0 +1,68 @@ +#include "snapshots.h" + +namespace anm2ed::snapshots +{ + bool SnapshotStack::is_empty() + { + return top == 0; + } + + void SnapshotStack::push(Snapshot& snapshot) + { + if (top >= MAX) + { + for (int i = 0; i < MAX - 1; i++) + snapshots[i] = snapshots[i + 1]; + top = MAX - 1; + } + snapshots[top++] = snapshot; + } + + Snapshot* SnapshotStack::pop() + { + if (is_empty()) return nullptr; + return &snapshots[--top]; + } + + void SnapshotStack::clear() + { + top = 0; + } + + void Snapshots::push(const anm2::Anm2& anm2, anm2::Reference reference, const std::string& message) + { + Snapshot snapshot = {anm2, reference, message}; + undoStack.push(snapshot); + redoStack.clear(); + } + + void Snapshots::undo(anm2::Anm2& anm2, anm2::Reference& reference, std::string& message) + { + if (auto current = undoStack.pop()) + { + Snapshot snapshot = {anm2, reference, message}; + redoStack.push(snapshot); + anm2 = current->anm2; + reference = current->reference; + message = current->message; + } + } + + void Snapshots::redo(anm2::Anm2& anm2, anm2::Reference& reference, std::string& message) + { + if (auto current = redoStack.pop()) + { + Snapshot snapshot = {anm2, reference, message}; + undoStack.push(snapshot); + anm2 = current->anm2; + reference = current->reference; + message = current->message; + } + } + + void Snapshots::reset() + { + undoStack.clear(); + redoStack.clear(); + } +}; diff --git a/src/snapshots.h b/src/snapshots.h new file mode 100644 index 0000000..e0f12ff --- /dev/null +++ b/src/snapshots.h @@ -0,0 +1,42 @@ +#pragma once + +#include "anm2.h" + +namespace anm2ed::snapshots +{ + constexpr auto ACTION = "Action"; + constexpr auto MAX = 100; + + class Snapshot + { + public: + anm2::Anm2 anm2{}; + anm2::Reference reference{}; + std::string message = ACTION; + }; + + class SnapshotStack + { + public: + Snapshot snapshots[MAX]; + int top{}; + + bool is_empty(); + void push(Snapshot& snapshot); + Snapshot* pop(); + void clear(); + }; + + class Snapshots + { + public: + SnapshotStack undoStack{}; + SnapshotStack redoStack{}; + + Snapshot* get(); + void push(const anm2::Anm2&, anm2::Reference, const std::string&); + void undo(anm2::Anm2& anm2, anm2::Reference& reference, std::string&); + void redo(anm2::Anm2& anm2, anm2::Reference& reference, std::string&); + void reset(); + }; +} diff --git a/src/spritesheet_editor.cpp b/src/spritesheet_editor.cpp index d153c43..81e7141 100644 --- a/src/spritesheet_editor.cpp +++ b/src/spritesheet_editor.cpp @@ -5,7 +5,7 @@ #include "tool.h" #include "types.h" -using namespace anm2ed::document_manager; +using namespace anm2ed::manager; using namespace anm2ed::settings; using namespace anm2ed::canvas; using namespace anm2ed::resources; @@ -18,7 +18,7 @@ namespace anm2ed::spritesheet_editor { } - void SpritesheetEditor::update(DocumentManager& manager, Settings& settings, Resources& resources) + void SpritesheetEditor::update(Manager& manager, Settings& settings, Resources& resources) { auto& document = *manager.get(); auto& pan = document.editorPan; diff --git a/src/spritesheet_editor.h b/src/spritesheet_editor.h index fa1010a..c1b1c00 100644 --- a/src/spritesheet_editor.h +++ b/src/spritesheet_editor.h @@ -1,7 +1,7 @@ #pragma once #include "canvas.h" -#include "document_manager.h" +#include "manager.h" #include "resources.h" #include "settings.h" @@ -13,7 +13,6 @@ namespace anm2ed::spritesheet_editor public: SpritesheetEditor(); - void update(document_manager::DocumentManager& manager, settings::Settings& settings, - resources::Resources& resources); + void update(manager::Manager&, settings::Settings&, resources::Resources&); }; } diff --git a/src/spritesheets.cpp b/src/spritesheets.cpp index 5de52d5..e2dbaca 100644 --- a/src/spritesheets.cpp +++ b/src/spritesheets.cpp @@ -1,10 +1,13 @@ #include "spritesheets.h" +#include + #include "imgui.h" #include "toast.h" -#include using namespace anm2ed::anm2; +using namespace anm2ed::clipboard; +using namespace anm2ed::manager; using namespace anm2ed::settings; using namespace anm2ed::resources; using namespace anm2ed::dialog; @@ -15,17 +18,72 @@ using namespace glm; namespace anm2ed::spritesheets { - void Spritesheets::update(Document& document, Settings& settings, Resources& resources, Dialog& dialog) + void Spritesheets::update(Manager& manager, Settings& settings, Resources& resources, Dialog& dialog, + Clipboard& clipboard) { + auto& document = *manager.get(); auto& anm2 = document.anm2; - auto& selection = document.selectedSpritesheets; - - if (document.is_just_changed(change::SPRITESHEETS)) unusedSpritesheetIDs = anm2.spritesheets_unused(); + auto& multiSelect = document.spritesheetMultiSelect; + auto& unused = document.unusedSpritesheetIDs; + auto& hovered = document.hoveredSpritesheet; + auto& reference = document.referenceSpritesheet; if (ImGui::Begin("Spritesheets", &settings.windowIsSpritesheets)) { auto style = ImGui::GetStyle(); - storage.user_data_set(&selection); + + auto context_menu = [&]() + { + auto copy = [&]() + { + if (!multiSelect.empty()) + { + std::string clipboardText{}; + for (auto& id : multiSelect) + clipboardText += anm2.content.spritesheets[id].to_string(id); + clipboard.set(clipboardText); + } + else if (hovered > -1) + clipboard.set(anm2.content.spritesheets[hovered].to_string(hovered)); + }; + + auto paste = [&](merge::Type type) + { + auto clipboardText = clipboard.get(); + document.spritesheets_deserialize(clipboardText, type); + }; + + if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (imgui::shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::BeginDisabled(); + ImGui::MenuItem("Cut", settings.shortcutCut.c_str()); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(multiSelect.empty() && hovered == -1); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(clipboard.is_empty()); + { + if (ImGui::BeginMenu("Paste")) + { + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + + ImGui::EndMenu(); + } + } + ImGui::EndDisabled(); + + ImGui::EndPopup(); + } + ImGui::PopStyleVar(2); + }; auto childSize = imgui::size_without_footer_get(2); @@ -37,7 +95,7 @@ namespace anm2ed::spritesheets ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2()); - storage.begin(anm2.content.spritesheets.size()); + multiSelect.start(anm2.content.spritesheets.size()); for (auto& [id, spritesheet] : anm2.content.spritesheets) { @@ -45,15 +103,16 @@ namespace anm2ed::spritesheets if (ImGui::BeginChild("##Spritesheet Child", spritesheetChildSize, ImGuiChildFlags_Borders)) { - auto isSelected = selection.contains(id); - auto isReferenced = id == document.referenceSpritesheet; + auto isSelected = multiSelect.contains(id); + auto isReferenced = id == reference; auto cursorPos = ImGui::GetCursorPos(); - auto& texture = spritesheet.texture; + auto& texture = spritesheet.texture.is_valid() ? spritesheet.texture : resources.icons[icon::NONE]; + auto path = spritesheet.path.empty() ? anm2::NO_PATH : spritesheet.path.c_str(); ImGui::SetNextItemSelectionUserData(id); ImGui::SetNextItemStorageID(id); - if (ImGui::Selectable("##Spritesheet Selectable", isSelected, 0, spritesheetChildSize)) - document.referenceSpritesheet = id; + if (ImGui::Selectable("##Spritesheet Selectable", isSelected, 0, spritesheetChildSize)) reference = id; + if (ImGui::IsItemHovered()) hovered = id; ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); @@ -63,32 +122,31 @@ namespace anm2ed::spritesheets auto viewport = ImGui::GetMainViewport(); - auto size = texture.size.x * texture.size.y > (viewport->Size.x * viewport->Size.y) * 0.5f - ? to_vec2(viewport->Size) * 0.5f - : vec2(texture.size); - + auto textureSize = texture.size.x * texture.size.y > (viewport->Size.x * viewport->Size.y) * 0.5f + ? to_vec2(viewport->Size) * 0.5f + : vec2(texture.size); auto aspectRatio = (float)texture.size.x / texture.size.y; - if (size.x / size.y > aspectRatio) - size.x = size.y * aspectRatio; + if (textureSize.x / textureSize.y > aspectRatio) + textureSize.x = textureSize.y * aspectRatio; else - size.y = size.x / aspectRatio; + textureSize.y = textureSize.x / aspectRatio; - if (ImGui::BeginChild("##Spritesheet Tooltip Image Child", to_imvec2(size), ImGuiChildFlags_Borders)) + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); + if (ImGui::BeginChild("##Spritesheet Tooltip Image Child", to_imvec2(textureSize), + ImGuiChildFlags_Borders)) ImGui::Image(texture.id, ImGui::GetContentRegionAvail()); + ImGui::PopStyleVar(); ImGui::EndChild(); ImGui::PopStyleVar(); ImGui::SameLine(); - if (ImGui::BeginChild( - "##Spritesheet Info Tooltip Child", - ImVec2(ImGui::CalcTextSize(spritesheet.path.c_str()).x + ImGui::GetTextLineHeightWithSpacing(), - 0))) + if (ImGui::BeginChild("##Spritesheet Info Tooltip Child")) { ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); - ImGui::TextUnformatted(spritesheet.path.c_str()); + ImGui::TextUnformatted(path); ImGui::PopFont(); ImGui::Text("ID: %d", id); ImGui::Text("Size: %d x %d", texture.size.x, texture.size.y); @@ -97,7 +155,6 @@ namespace anm2ed::spritesheets ImGui::EndTooltip(); } - ImGui::PopStyleVar(2); auto imageSize = to_imvec2(vec2(spritesheetChildSize.y)); @@ -116,22 +173,24 @@ namespace anm2ed::spritesheets spritesheetChildSize.y - spritesheetChildSize.y / 2 - ImGui::GetTextLineHeight() / 2)); if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); - ImGui::Text(SPRITESHEET_FORMAT, id, spritesheet.path.c_str()); + ImGui::Text(SPRITESHEET_FORMAT, id, path); if (isReferenced) ImGui::PopFont(); + + context_menu(); } ImGui::EndChild(); ImGui::PopID(); } - storage.end(); + multiSelect.finish(); - ImGui::PopStyleVar(); + ImGui::PopStyleVar(2); + + context_menu(); } ImGui::EndChild(); - ImGui::PopStyleVar(); - auto rowOneWidgetSize = imgui::widget_size_with_row_get(4); imgui::shortcut(settings.shortcutAdd); @@ -140,24 +199,21 @@ namespace anm2ed::spritesheets if (dialog.is_selected_file(dialog::SPRITESHEET_OPEN)) { - int id{}; - anm2.spritesheet_add(document.directory_get(), dialog.path, id); - selection = {id}; - document.change(change::SPRITESHEETS); + document.spritesheet_add(dialog.path); dialog.reset(); } ImGui::SameLine(); - ImGui::BeginDisabled(selection.empty()); + ImGui::BeginDisabled(multiSelect.empty()); { if (ImGui::Button("Reload", rowOneWidgetSize)) { - for (auto& id : selection) + for (auto& id : multiSelect) { Spritesheet& spritesheet = anm2.content.spritesheets[id]; spritesheet.reload(document.directory_get()); - toasts.add(std::format("Reloaded spritesheet #{}: {}", id, spritesheet.path.string())); + toasts.info(std::format("Reloaded spritesheet #{}: {}", id, spritesheet.path.string())); } } ImGui::SetItemTooltip("Reloads the selected spritesheets."); @@ -166,7 +222,7 @@ namespace anm2ed::spritesheets ImGui::SameLine(); - ImGui::BeginDisabled(selection.size() != 1); + ImGui::BeginDisabled(multiSelect.size() != 1); { if (ImGui::Button("Replace", rowOneWidgetSize)) dialog.spritesheet_replace(); ImGui::SetItemTooltip("Replace the selected spritesheet with a new one."); @@ -175,27 +231,27 @@ namespace anm2ed::spritesheets if (dialog.is_selected_file(dialog::SPRITESHEET_REPLACE)) { - auto& id = *selection.begin(); + auto& id = *multiSelect.begin(); Spritesheet& spritesheet = anm2.content.spritesheets[id]; spritesheet = Spritesheet(document.directory_get(), dialog.path); - toasts.add(std::format("Replaced spritesheet #{}: {}", id, spritesheet.path.string())); + toasts.info(std::format("Replaced spritesheet #{}: {}", id, spritesheet.path.string())); dialog.reset(); } ImGui::SameLine(); - ImGui::BeginDisabled(unusedSpritesheetIDs.empty()); + ImGui::BeginDisabled(unused.empty()); { imgui::shortcut(settings.shortcutRemove); if (ImGui::Button("Remove Unused", rowOneWidgetSize)) { - for (auto& id : unusedSpritesheetIDs) + for (auto& id : unused) { Spritesheet& spritesheet = anm2.content.spritesheets[id]; - toasts.add(std::format("Removed spritesheet #{}: {}", id, spritesheet.path.string())); + toasts.info(std::format("Removed spritesheet #{}: {}", id, spritesheet.path.string())); anm2.spritesheet_remove(id); } - unusedSpritesheetIDs.clear(); + unused.clear(); document.change(change::SPRITESHEETS); } imgui::set_item_tooltip_shortcut("Remove all unused spritesheets (i.e., not used in any layer.).", @@ -206,11 +262,11 @@ namespace anm2ed::spritesheets auto rowTwoWidgetSize = imgui::widget_size_with_row_get(3); imgui::shortcut(settings.shortcutSelectAll); - ImGui::BeginDisabled(selection.size() == anm2.content.spritesheets.size()); + ImGui::BeginDisabled(multiSelect.size() == anm2.content.spritesheets.size()); { if (ImGui::Button("Select All", rowTwoWidgetSize)) for (auto& id : anm2.content.spritesheets | std::views::keys) - selection.insert(id); + multiSelect.insert(id); } ImGui::EndDisabled(); imgui::set_item_tooltip_shortcut("Select all spritesheets.", settings.shortcutSelectAll); @@ -218,24 +274,24 @@ namespace anm2ed::spritesheets ImGui::SameLine(); imgui::shortcut(settings.shortcutSelectNone); - ImGui::BeginDisabled(selection.empty()); - if (ImGui::Button("Select None", rowTwoWidgetSize)) selection.clear(); + ImGui::BeginDisabled(multiSelect.empty()); + if (ImGui::Button("Select None", rowTwoWidgetSize)) multiSelect.clear(); imgui::set_item_tooltip_shortcut("Unselect all spritesheets.", settings.shortcutSelectNone); ImGui::EndDisabled(); ImGui::SameLine(); - ImGui::BeginDisabled(selection.empty()); + ImGui::BeginDisabled(multiSelect.empty()); { if (ImGui::Button("Save", rowTwoWidgetSize)) { - for (auto& id : selection) + for (auto& id : multiSelect) { Spritesheet& spritesheet = anm2.content.spritesheets[id]; if (spritesheet.save(document.directory_get())) - toasts.add(std::format("Saved spritesheet #{}: {}", id, spritesheet.path.string())); + toasts.info(std::format("Saved spritesheet #{}: {}", id, spritesheet.path.string())); else - toasts.add(std::format("Unable to save spritesheet #{}: {}", id, spritesheet.path.string())); + toasts.info(std::format("Unable to save spritesheet #{}: {}", id, spritesheet.path.string())); } } } @@ -244,4 +300,4 @@ namespace anm2ed::spritesheets } ImGui::End(); } -} +} \ No newline at end of file diff --git a/src/spritesheets.h b/src/spritesheets.h index 7bed4ce..27a30d5 100644 --- a/src/spritesheets.h +++ b/src/spritesheets.h @@ -1,8 +1,8 @@ #pragma once +#include "clipboard.h" #include "dialog.h" -#include "document.h" -#include "imgui.h" +#include "manager.h" #include "resources.h" #include "settings.h" @@ -10,11 +10,8 @@ namespace anm2ed::spritesheets { class Spritesheets { - imgui::MultiSelectStorage storage{}; - std::set unusedSpritesheetIDs{}; - public: - void update(document::Document& document, settings::Settings& settings, resources::Resources& resources, - dialog::Dialog& dialog); + void update(manager::Manager&, settings::Settings&, resources::Resources&, dialog::Dialog&, + clipboard::Clipboard& clipboard); }; } diff --git a/src/state.cpp b/src/state.cpp index 2a247b6..ab209f4 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -30,8 +30,9 @@ namespace anm2ed::state { if (auto document = manager.get()) if (auto animation = document->animation_get()) - if (playback.isPlaying) - playback.tick(document->anm2.info.fps, animation->frameNum, animation->isLoop || settings.playbackIsLoop); + if (document->playback.isPlaying) + document->playback.tick(document->anm2.info.fps, animation->frameNum, + animation->isLoop || settings.playbackIsLoop); } void State::update(SDL_Window*& window, Settings& settings) @@ -44,9 +45,21 @@ namespace anm2ed::state switch (event.type) { case SDL_EVENT_DROP_FILE: - if (auto droppedFile = event.drop.data; filesystem::path_is_extension(droppedFile, "anm2")) + { + auto droppedFile = event.drop.data; + if (filesystem::path_is_extension(droppedFile, "anm2")) manager.open(std::string(droppedFile)); + else if (filesystem::path_is_extension(droppedFile, "png")) + { + if (auto document = manager.get()) + document->spritesheet_add(droppedFile); + else + toasts.warning(std::format("Could not open spritesheet: (open a document first!)", droppedFile)); + } + else + toasts.warning(std::format("Could not parse file: {} (must be .anm2 or .png)", droppedFile)); break; + } case SDL_EVENT_QUIT: isQuit = true; break; @@ -59,8 +72,8 @@ namespace anm2ed::state ImGui_ImplOpenGL3_NewFrame(); ImGui::NewFrame(); - taskbar.update(settings, dialog, manager, isQuit); - dockspace.update(taskbar, documents, manager, settings, resources, dialog, playback); + taskbar.update(manager, settings, dialog, isQuit); + dockspace.update(taskbar, documents, manager, settings, resources, dialog, clipboard); toasts.update(); documents.update(taskbar, manager, resources); diff --git a/src/state.h b/src/state.h index bb1d099..4ee9adc 100644 --- a/src/state.h +++ b/src/state.h @@ -8,16 +8,16 @@ namespace anm2ed::state { class State { - void tick(settings::Settings& settings); - void update(SDL_Window*& window, settings::Settings& settings); - void render(SDL_Window*& window, settings::Settings& settings); + void tick(settings::Settings&); + void update(SDL_Window*&, settings::Settings&); + void render(SDL_Window*&, settings::Settings&); public: bool isQuit{}; dialog::Dialog dialog; resources::Resources resources; - playback::Playback playback; - document_manager::DocumentManager manager; + manager::Manager manager; + clipboard::Clipboard clipboard; taskbar::Taskbar taskbar; documents::Documents documents; @@ -26,8 +26,8 @@ namespace anm2ed::state uint64_t previousTick{}; uint64_t previousUpdate{}; - State(SDL_Window*& window, std::vector& arguments); + State(SDL_Window*&, std::vector&); - void loop(SDL_Window*& window, settings::Settings& settings); + void loop(SDL_Window*&, settings::Settings&); }; }; diff --git a/src/taskbar.cpp b/src/taskbar.cpp index a769476..cec33ac 100644 --- a/src/taskbar.cpp +++ b/src/taskbar.cpp @@ -7,12 +7,12 @@ using namespace anm2ed::settings; using namespace anm2ed::dialog; -using namespace anm2ed::document_manager; +using namespace anm2ed::manager; using namespace anm2ed::types; namespace anm2ed::taskbar { - void Taskbar::update(Settings& settings, Dialog& dialog, DocumentManager& manager, bool& isQuit) + void Taskbar::update(Manager& manager, Settings& settings, Dialog& dialog, bool& isQuit) { auto document = manager.get(); auto animation = document ? document->animation_get() : nullptr; @@ -89,7 +89,11 @@ namespace anm2ed::taskbar if (ImGui::BeginMenu("Settings")) { - if (ImGui::MenuItem("Configure")) configurePopup.open(); + if (ImGui::MenuItem("Configure")) + { + editSettings = settings; + configurePopup.open(); + } ImGui::EndMenu(); } diff --git a/src/taskbar.h b/src/taskbar.h index 257b5aa..b013eab 100644 --- a/src/taskbar.h +++ b/src/taskbar.h @@ -1,8 +1,8 @@ #pragma once #include "dialog.h" -#include "document_manager.h" #include "imgui.h" +#include "manager.h" #include "settings.h" namespace anm2ed::taskbar @@ -12,12 +12,11 @@ namespace anm2ed::taskbar imgui::PopupHelper configurePopup{imgui::PopupHelper("Configure")}; imgui::PopupHelper aboutPopup{imgui::PopupHelper("About")}; settings::Settings editSettings{}; - int selectedShortcut{}; + int selectedShortcut{-1}; public: float height{}; - void update(settings::Settings& settings, dialog::Dialog& dialog, document_manager::DocumentManager& manager, - bool& isQuit); + void update(manager::Manager&, settings::Settings&, dialog::Dialog&, bool&); }; }; diff --git a/src/texture.cpp b/src/texture.cpp index a134a5c..76c9761 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -29,7 +29,7 @@ namespace anm2ed::texture return id != 0; } - void Texture::download(std::vector& pixels) + void Texture::download() { pixels.resize(size.x * size.y * CHANNELS); glBindTexture(GL_TEXTURE_2D, id); @@ -37,9 +37,20 @@ namespace anm2ed::texture glBindTexture(GL_TEXTURE_2D, 0); } - void Texture::init(const uint8_t* data, bool isDownload) + void Texture::upload(const uint8_t* data) { - glGenTextures(1, &id); + if (!data || size.x <= 0 || size.y <= 0) return; + + const size_t pixelCount = static_cast(size.x) * static_cast(size.y) * CHANNELS; + pixels.assign(data, data + pixelCount); + upload(); + } + + void Texture::upload() + { + if (pixels.empty() || size.x <= 0 || size.y <= 0) return; + + if (!is_valid()) glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); @@ -48,12 +59,10 @@ namespace anm2ed::texture glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); - - if (isDownload) download(pixels); } Texture::Texture() = default; @@ -63,11 +72,31 @@ namespace anm2ed::texture if (is_valid()) glDeleteTextures(1, &id); } + Texture::Texture(const Texture& other) + { + *this = other; + } + Texture::Texture(Texture&& other) { *this = std::move(other); } + Texture& Texture::operator=(const Texture& other) + { + if (this != &other) + { + if (is_valid()) glDeleteTextures(1, &id); + id = 0; + size = other.size; + filter = other.filter; + channels = other.channels; + pixels = other.pixels; + if (!pixels.empty()) upload(); + } + return *this; + } + Texture& Texture::operator=(Texture&& other) { if (this != &other) @@ -94,24 +123,21 @@ namespace anm2ed::texture size = svgSize; filter = GL_LINEAR; - init(bitmap.data()); + upload(bitmap.data()); } - Texture::Texture(const std::string& pngPath, bool isDownload) + Texture::Texture(const std::string& pngPath) { if (const uint8* data = stbi_load(pngPath.c_str(), &size.x, &size.y, nullptr, CHANNELS); data) { - init(data, isDownload); + upload(data); stbi_image_free((void*)data); } } bool Texture::write_png(const std::string& path) { - std::vector pixels; - download(pixels); - const bool isSuccess = stbi_write_png(path.c_str(), size.x, size.y, CHANNELS, pixels.data(), size.x * CHANNELS); - return isSuccess; + return stbi_write_png(path.c_str(), size.x, size.y, CHANNELS, this->pixels.data(), size.x * CHANNELS); } void Texture::bind(GLuint unit) @@ -125,4 +151,4 @@ namespace anm2ed::texture glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(GL_TEXTURE_2D, 0); } -} \ No newline at end of file +} diff --git a/src/texture.h b/src/texture.h index 834bc09..9fc8076 100644 --- a/src/texture.h +++ b/src/texture.h @@ -20,17 +20,20 @@ namespace anm2ed::texture std::vector pixels{}; bool is_valid(); - void download(std::vector& pixels); - void init(const uint8_t* data, bool isDownload = false); + void download(); + void upload(const uint8_t*); + void upload(); Texture(); ~Texture(); - Texture(Texture&& other); - Texture& operator=(Texture&& other); - Texture(const char* svgData, size_t svgDataLength, glm::ivec2 svgSize); - Texture(const std::string& pngPath, bool isDownload = false); - bool write_png(const std::string& path); - void bind(GLuint unit = 0); - void unbind(GLuint unit = 0); + Texture(const Texture&); + Texture(Texture&&); + Texture& operator=(const Texture&); + Texture& operator=(Texture&&); + Texture(const char*, size_t, glm::ivec2); + Texture(const std::string&); + bool write_png(const std::string&); + void bind(GLuint = 0); + void unbind(GLuint = 0); }; -} \ No newline at end of file +} diff --git a/src/timeline.cpp b/src/timeline.cpp index ef50288..dd47ff6 100644 --- a/src/timeline.cpp +++ b/src/timeline.cpp @@ -7,7 +7,7 @@ #include "imgui.h" using namespace anm2ed::types; -using namespace anm2ed::document_manager; +using namespace anm2ed::manager; using namespace anm2ed::resources; using namespace anm2ed::settings; using namespace anm2ed::playback; @@ -50,9 +50,12 @@ namespace anm2ed::timeline - Press {} to shorten the selected frame, by one frame. - Hold Alt while clicking a non-trigger frame to toggle interpolation.)"; - void Timeline::item_child(anm2::Anm2& anm2, anm2::Reference& reference, anm2::Animation* animation, - Settings& settings, Resources& resources, anm2::Type type, int id, int& index) + void Timeline::item_child(Manager& manager, Document& document, anm2::Animation* animation, Settings& settings, + Resources& resources, anm2::Type type, int id, int& index) { + auto& anm2 = document.anm2; + auto& reference = document.reference; + auto item = animation ? animation->item_get(type, id) : nullptr; auto isVisible = item ? item->isVisible : false; auto isActive = reference.itemType == type && reference.itemID == id; @@ -102,7 +105,24 @@ namespace anm2ed::timeline { anm2::Reference itemReference = {reference.animationIndex, type, id}; - if (ImGui::IsWindowHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) reference = itemReference; + if (ImGui::IsWindowHovered()) + { + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + { + switch (type) + { + case anm2::LAYER: + manager.layer_properties_open(id); // Handled in layers.cpp + break; + case anm2::NULL_: + manager.null_properties_open(id); // Handled in layers.cpp + default: + break; + } + } + + if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) reference = itemReference; + } ImGui::Image(resources.icons[icon].id, imgui::icon_size_get()); ImGui::SameLine(); @@ -121,7 +141,7 @@ namespace anm2ed::timeline int visibleIcon = isVisible ? icon::VISIBLE : icon::INVISIBLE; if (ImGui::ImageButton("##Visible Toggle", resources.icons[visibleIcon].id, imgui::icon_size_get())) - isVisible = !isVisible; + document.item_visible_toggle(item); ImGui::SetItemTooltip(isVisible ? "The item is shown. Press to hide." : "The item is hidden. Press to show."); if (type == anm2::NULL_) @@ -134,7 +154,7 @@ namespace anm2ed::timeline ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x, (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); if (ImGui::ImageButton("##Rect Toggle", resources.icons[rectIcon].id, imgui::icon_size_get())) - isShowRect = !isShowRect; + document.null_rect_toggle(null); ImGui::SetItemTooltip(isShowRect ? "The null's rect is shown. Press to hide." : "The null's rect is hidden. Press to show."); } @@ -180,9 +200,9 @@ namespace anm2ed::timeline index++; } - void Timeline::items_child(Document& document, anm2::Animation* animation, Settings& settings, Resources& resources) + void Timeline::items_child(Manager& manager, Document& document, anm2::Animation* animation, Settings& settings, + Resources& resources) { - auto& anm2 = document.anm2; auto& reference = document.reference; auto itemsChildSize = ImVec2(ImGui::GetTextLineHeightWithSpacing() * 15, ImGui::GetContentRegionAvail().y); @@ -212,7 +232,7 @@ namespace anm2ed::timeline { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); - item_child(anm2, reference, animation, settings, resources, type, id, index); + item_child(manager, document, animation, settings, resources, type, id, index); }; item_child_row(anm2::NONE); @@ -253,20 +273,24 @@ namespace anm2ed::timeline } ImGui::EndChild(); - auto widgetSize = imgui::widget_size_with_row_get(2); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + style.WindowPadding.x, ImGui::GetCursorPosY())); + auto widgetSize = imgui::widget_size_with_row_get(2, ImGui::GetContentRegionAvail().x - style.WindowPadding.x); + ImGui::BeginDisabled(!animation); { + imgui::shortcut(settings.shortcutAdd); if (ImGui::Button("Add", widgetSize)) propertiesPopup.open(); - ImGui::SetItemTooltip("%s", "Add a new item to the animation."); + imgui::set_item_tooltip_shortcut("Add a new item to the animation.", settings.shortcutAdd); ImGui::SameLine(); - ImGui::BeginDisabled(document.item_get()); + ImGui::BeginDisabled(!document.item_get() && reference.itemType != anm2::LAYER && + reference.itemType != anm2::NULL_); { - ImGui::Button("Remove", widgetSize); - ImGui::SetItemTooltip("%s", "Remove the selected items from the animation."); + imgui::shortcut(settings.shortcutRemove); + if (ImGui::Button("Remove", widgetSize)) document.item_remove(animation); + imgui::set_item_tooltip_shortcut("Remove the selected items from the animation.", settings.shortcutRemove); } ImGui::EndDisabled(); } @@ -278,9 +302,10 @@ namespace anm2ed::timeline } void Timeline::frame_child(Document& document, anm2::Animation* animation, Settings& settings, Resources& resources, - Playback& playback, anm2::Type type, int id, int& index, float width) + anm2::Type type, int id, int& index, float width) { auto& anm2 = document.anm2; + auto& playback = document.playback; auto& reference = document.reference; auto item = animation ? animation->item_get(type, id) : nullptr; auto isVisible = item ? item->isVisible : false; @@ -455,7 +480,11 @@ namespace anm2ed::timeline if (ImGui::Button("##Frame Button", size)) { if (type != anm2::TRIGGER && ImGui::IsKeyDown(ImGuiMod_Alt)) frame.isInterpolated = !frame.isInterpolated; - if (type == anm2::LAYER) document.referenceSpritesheet = anm2.content.layers[id].spritesheetID; + if (type == anm2::LAYER) + { + document.referenceSpritesheet = anm2.content.layers[id].spritesheetID; + document.layersMultiSelect = {id}; + } reference = frameReference; reference.frameTime = frameTime; } @@ -481,10 +510,10 @@ namespace anm2ed::timeline ImGui::PopID(); } - void Timeline::frames_child(Document& document, anm2::Animation* animation, Settings& settings, Resources& resources, - Playback& playback) + void Timeline::frames_child(Document& document, anm2::Animation* animation, Settings& settings, Resources& resources) { auto& anm2 = document.anm2; + auto& playback = document.playback; auto itemsChildWidth = ImGui::GetTextLineHeightWithSpacing() * 15; @@ -541,7 +570,7 @@ namespace anm2ed::timeline { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); - frame_child(document, animation, settings, resources, playback, type, id, index, childWidth); + frame_child(document, animation, settings, resources, type, id, index, childWidth); }; frames_child_row(anm2::NONE); @@ -614,25 +643,35 @@ namespace anm2ed::timeline ImGui::SameLine(); - imgui::shortcut(settings.shortcutAdd); - ImGui::Button("Insert Frame", widgetSize); - imgui::set_item_tooltip_shortcut("Insert a frame, based on the current selection.", settings.shortcutAdd); + auto item = document.item_get(); - ImGui::SameLine(); + ImGui::BeginDisabled(!item); + { + imgui::shortcut(settings.shortcutAdd); + if (ImGui::Button("Insert Frame", widgetSize)) document.frames_add(item); + imgui::set_item_tooltip_shortcut("Insert a frame, based on the current selection.", settings.shortcutAdd); - imgui::shortcut(settings.shortcutRemove); - ImGui::Button("Delete Frame", widgetSize); - imgui::set_item_tooltip_shortcut("Delete the selected frames.", settings.shortcutRemove); + ImGui::SameLine(); - ImGui::SameLine(); + ImGui::BeginDisabled(!document.frame_get()); + { + imgui::shortcut(settings.shortcutRemove); + if (ImGui::Button("Delete Frame", widgetSize)) document.frames_delete(item); + imgui::set_item_tooltip_shortcut("Delete the selected frames.", settings.shortcutRemove); - ImGui::Button("Bake", widgetSize); - ImGui::SetItemTooltip("%s", "Turn interpolated frames into uninterpolated ones."); + ImGui::SameLine(); + + if (ImGui::Button("Bake", widgetSize)) bakePopup.open(); + ImGui::SetItemTooltip("Turn interpolated frames into uninterpolated ones."); + } + ImGui::EndDisabled(); + } + ImGui::EndDisabled(); ImGui::SameLine(); if (ImGui::Button("Fit Animation Length", widgetSize)) animation->frameNum = animation->length(); - ImGui::SetItemTooltip("%s", "The animation length will be set to the effective length of the animation."); + ImGui::SetItemTooltip("The animation length will be set to the effective length of the animation."); ImGui::SameLine(); @@ -640,13 +679,13 @@ namespace anm2ed::timeline ImGui::InputInt("Animation Length", animation ? &animation->frameNum : &dummy_value(), step::NORMAL, step::FAST, !animation ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); if (animation) animation->frameNum = clamp(animation->frameNum, anm2::FRAME_NUM_MIN, anm2::FRAME_NUM_MAX); - ImGui::SetItemTooltip("%s", "Set the animation's length."); + ImGui::SetItemTooltip("Set the animation's length."); ImGui::SameLine(); ImGui::SetNextItemWidth(widgetSize.x); ImGui::Checkbox("Loop", animation ? &animation->isLoop : &dummy_value()); - ImGui::SetItemTooltip("%s", "Toggle the animation looping."); + ImGui::SetItemTooltip("Toggle the animation looping."); } ImGui::EndDisabled(); @@ -655,13 +694,13 @@ namespace anm2ed::timeline ImGui::SetNextItemWidth(widgetSize.x); ImGui::InputInt("FPS", &anm2.info.fps, 1, 5); anm2.info.fps = clamp(anm2.info.fps, anm2::FPS_MIN, anm2::FPS_MAX); - ImGui::SetItemTooltip("%s", "Set the FPS of all animations."); + ImGui::SetItemTooltip("Set the FPS of all animations."); ImGui::SameLine(); ImGui::SetNextItemWidth(widgetSize.x); imgui::input_text_string("Author", &anm2.info.createdBy); - ImGui::SetItemTooltip("%s", "Set the author of the document."); + ImGui::SetItemTooltip("Set the author of the document."); ImGui::PopStyleVar(); } @@ -710,7 +749,6 @@ namespace anm2ed::timeline auto optionsSize = imgui::child_size_get(11); auto itemsSize = ImVec2(0, ImGui::GetContentRegionAvail().y - (optionsSize.y + footerSize.y + ImGui::GetStyle().ItemSpacing.y * 4)); - if (ImGui::BeginChild("Options", optionsSize, ImGuiChildFlags_Borders)) { ImGui::SeparatorText("Type"); @@ -827,17 +865,7 @@ namespace anm2ed::timeline if (ImGui::Button("Add", widgetSize)) { - anm2::Reference addReference; - - if (type == anm2::LAYER) - addReference = anm2.layer_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName, - addItemSpritesheetID, (locale::Type)locale); - else if (type == anm2::NULL_) - addReference = - anm2.null_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName, (locale::Type)locale); - - reference = addReference; - + document.item_add((anm2::Type)type, addItemID, addItemName, (locale::Type)locale, addItemSpritesheetID); item_properties_close(); } ImGui::SetItemTooltip("Add the item, with the settings specified."); @@ -849,11 +877,49 @@ namespace anm2ed::timeline ImGui::EndPopup(); } + + bakePopup.trigger(); + + if (ImGui::BeginPopupModal(bakePopup.label, &bakePopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto& interval = settings.bakeInterval; + auto& isRoundRotation = settings.bakeIsRoundRotation; + auto& isRoundScale = settings.bakeIsRoundScale; + + auto frame = document.frame_get(); + + ImGui::InputInt("Interval", &interval, step::NORMAL, step::FAST); + ImGui::SetItemTooltip("Set the maximum delay of each frame that will be baked."); + interval = glm::clamp(interval, anm2::FRAME_DELAY_MIN, frame ? frame->delay : anm2::FRAME_DELAY_MIN); + + ImGui::Checkbox("Round Rotation", &isRoundRotation); + ImGui::SetItemTooltip("Rotation will be rounded to the nearest whole number."); + + ImGui::Checkbox("Round Scale", &isRoundScale); + ImGui::SetItemTooltip("Scale will be rounded to the nearest whole number."); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + if (ImGui::Button("Bake", widgetSize)) + { + document.frames_bake(interval, isRoundScale, isRoundRotation); + bakePopup.close(); + } + ImGui::SetItemTooltip("Bake the selected frame(s) with the options selected."); + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) bakePopup.close(); + ImGui::SetItemTooltip("Cancel baking frames."); + + ImGui::EndPopup(); + } } - void Timeline::update(DocumentManager& manager, Settings& settings, Resources& resources, Playback& playback) + void Timeline::update(Manager& manager, Settings& settings, Resources& resources) { auto& document = *manager.get(); + auto& playback = document.playback; auto& anm2 = document.anm2; auto& reference = document.reference; auto animation = document.animation_get(); @@ -864,8 +930,8 @@ namespace anm2ed::timeline if (ImGui::Begin("Timeline", &settings.windowIsTimeline)) { isWindowHovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); - frames_child(document, animation, settings, resources, playback); - items_child(document, animation, settings, resources); + frames_child(document, animation, settings, resources); + items_child(manager, document, animation, settings, resources); } ImGui::PopStyleVar(); ImGui::End(); diff --git a/src/timeline.h b/src/timeline.h index 799a6e7..5284ca7 100644 --- a/src/timeline.h +++ b/src/timeline.h @@ -2,9 +2,7 @@ #include "anm2.h" #include "document.h" -#include "document_manager.h" -#include "imgui.h" -#include "playback.h" +#include "manager.h" #include "resources.h" #include "settings.h" @@ -16,6 +14,7 @@ namespace anm2ed::timeline bool isWindowHovered{}; bool isHorizontalScroll{}; imgui::PopupHelper propertiesPopup{imgui::PopupHelper("Item Properties")}; + imgui::PopupHelper bakePopup{imgui::PopupHelper("Bake", imgui::POPUP_SMALL, true)}; std::string addItemName{}; int addItemSpritesheetID{}; bool addItemIsRect{}; @@ -26,20 +25,16 @@ namespace anm2ed::timeline ImDrawList* pickerLineDrawList{}; ImGuiStyle style{}; - void item_child(anm2::Anm2& anm2, anm2::Reference& reference, anm2::Animation* animation, - settings::Settings& settings, resources::Resources& resources, anm2::Type type, int id, int& index); - void items_child(Document& document, anm2::Animation* animation, settings::Settings& settings, - resources::Resources& resources); - void frame_child(document::Document& document, anm2::Animation* animation, settings::Settings& settings, - resources::Resources& resources, playback::Playback& playback, anm2::Type type, int id, int& index, - float width); - void frames_child(document::Document& document, anm2::Animation* animation, settings::Settings& settings, - resources::Resources& resources, playback::Playback& playback); + void item_child(manager::Manager&, Document&, anm2::Animation*, settings::Settings&, resources::Resources&, + anm2::Type, int, int&); + void items_child(manager::Manager&, Document&, anm2::Animation*, settings::Settings&, resources::Resources&); + void frame_child(document::Document&, anm2::Animation*, settings::Settings&, resources::Resources&, anm2::Type, int, + int&, float); + void frames_child(document::Document&, anm2::Animation*, settings::Settings&, resources::Resources&); - void popups(document::Document& document, anm2::Animation* animation, settings::Settings& settings); + void popups(document::Document&, anm2::Animation*, settings::Settings&); public: - void update(document_manager::DocumentManager& manager, settings::Settings& settings, - resources::Resources& resources, playback::Playback& playback); + void update(manager::Manager&, settings::Settings&, resources::Resources&); }; -} \ No newline at end of file +} diff --git a/src/toast.cpp b/src/toast.cpp index beb84e1..a0d65c1 100644 --- a/src/toast.cpp +++ b/src/toast.cpp @@ -64,17 +64,23 @@ namespace anm2ed::toast } } - void Toasts::add(const std::string& message) + void Toasts::info(const std::string& message) { toasts.emplace_back(Toast(message)); logger.info(message); } - void Toasts::add_error(const std::string& message) + void Toasts::error(const std::string& message) { toasts.emplace_back(Toast(message)); logger.error(message); } + void Toasts::warning(const std::string& message) + { + toasts.emplace_back(Toast(message)); + logger.warning(message); + } + Toasts toasts; } diff --git a/src/toast.h b/src/toast.h index 306787b..6aff2cc 100644 --- a/src/toast.h +++ b/src/toast.h @@ -12,7 +12,7 @@ namespace anm2ed::toast std::string message{}; float lifetime{}; - Toast(const std::string& message); + Toast(const std::string&); }; class Toasts @@ -21,8 +21,9 @@ namespace anm2ed::toast std::vector toasts{}; void update(); - void add(const std::string& message); - void add_error(const std::string& message); + void info(const std::string&); + void error(const std::string&); + void warning(const std::string&); }; extern Toasts toasts; diff --git a/src/tools.cpp b/src/tools.cpp index 3e32d0f..c0d6073 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -8,6 +8,7 @@ #include "types.h" using namespace anm2ed::settings; +using namespace anm2ed::manager; using namespace anm2ed::resources; using namespace anm2ed::types; using namespace glm; @@ -16,8 +17,10 @@ namespace anm2ed::tools { constexpr auto COLOR_EDIT_LABEL = "##Color Edit"; - void Tools::update(Settings& settings, Resources& resources) + void Tools::update(Manager& manager, Settings& settings, Resources& resources) { + auto& document = *manager.get(); + if (ImGui::Begin("Tools", &settings.windowIsTools)) { ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 2)); @@ -31,8 +34,10 @@ namespace anm2ed::tools switch (type) { case tool::UNDO: + if (document.is_undo()) document.undo(); break; case tool::REDO: + if (document.is_redo()) document.redo(); break; case tool::COLOR: if (ImGui::IsPopupOpen(COLOR_EDIT_LABEL)) @@ -68,8 +73,12 @@ namespace anm2ed::tools } else { + if (i == tool::UNDO) ImGui::BeginDisabled(!document.is_undo()); + if (i == tool::REDO) ImGui::BeginDisabled(!document.is_redo()); if (ImGui::ImageButton(info.label, resources.icons[info.icon].id, to_imvec2(size))) tool_switch((tool::Type)i); + if (i == tool::UNDO) ImGui::EndDisabled(); + if (i == tool::REDO) ImGui::EndDisabled(); } auto widthIncrement = ImGui::GetItemRectSize().x + ImGui::GetStyle().ItemSpacing.x; diff --git a/src/tools.h b/src/tools.h index 895a3b3..377b636 100644 --- a/src/tools.h +++ b/src/tools.h @@ -1,5 +1,6 @@ #pragma once +#include "manager.h" #include "resources.h" #include "settings.h" @@ -11,6 +12,6 @@ namespace anm2ed::tools ImVec2 colorEditPosition{}; public: - void update(settings::Settings& settings, resources::Resources& resources); + void update(manager::Manager&, settings::Settings&, resources::Resources&); }; } diff --git a/src/types.h b/src/types.h index a4b7b82..439d138 100644 --- a/src/types.h +++ b/src/types.h @@ -15,10 +15,20 @@ namespace anm2ed::types::change ANIMATIONS, ITEMS, FRAMES, + ALL, COUNT }; } +namespace anm2ed::types::draw_order +{ + enum Type + { + BELOW, + ABOVE + }; +} + namespace anm2ed::types::shortcut { enum Type diff --git a/src/util.h b/src/util.h index ec50cb3..ec99f47 100644 --- a/src/util.h +++ b/src/util.h @@ -1,20 +1,23 @@ #pragma once +#include #include +#include +#include #include #include #include namespace anm2ed::util::time { - std::string get(const char* format); + std::string get(const char*); } namespace anm2ed::util::string { - std::string to_lower(const std::string& string); - std::string replace_backslash(const std::string& string); - bool to_bool(const std::string& string); + std::string to_lower(const std::string&); + std::string replace_backslash(const std::string&); + bool to_bool(const std::string&); } namespace anm2ed::util::map @@ -52,4 +55,44 @@ namespace anm2ed::util::vector { return index >= 0 && index < (int)v.size() ? &v[index] : nullptr; } -} \ No newline at end of file + + template std::set move_indices(std::vector& v, std::vector& indices, int index) + { + if (indices.empty()) return {}; + + std::vector sorted = indices; + std::sort(sorted.begin(), sorted.end()); + sorted.erase(std::unique(sorted.begin(), sorted.end()), sorted.end()); + + // Determine if we are dragging items from below the target (insert before) or above (insert after) + bool insertAfter = !sorted.empty() && sorted.front() <= index; + + std::vector moveItems; + moveItems.reserve(sorted.size()); + for (int i : sorted) + moveItems.push_back(std::move(v[i])); + + for (auto i : sorted | std::views::reverse) + v.erase(v.begin() + i); + + int originalSize = (int)v.size() + (int)sorted.size(); + int reference = insertAfter ? index + 1 : index; + reference = std::clamp(reference, 0, originalSize); + + int removedBeforeReference = 0; + for (int i : sorted) + if (i < reference) ++removedBeforeReference; + + int insertPos = reference - removedBeforeReference; + insertPos = std::clamp(insertPos, 0, (int)v.size()); + + v.insert(v.begin() + insertPos, std::make_move_iterator(moveItems.begin()), + std::make_move_iterator(moveItems.end())); + + std::set moveIndices{}; + for (int i = 0; i < (int)moveItems.size(); i++) + moveIndices.insert(insertPos + i); + + return moveIndices; + } +} diff --git a/src/xml.h b/src/xml.h index 9bca4a3..100ec82 100644 --- a/src/xml.h +++ b/src/xml.h @@ -7,9 +7,8 @@ namespace anm2ed::xml { - std::string document_to_string(tinyxml2::XMLDocument& self); - tinyxml2::XMLError query_string_attribute(tinyxml2::XMLElement* element, const char* attribute, std::string* out); - tinyxml2::XMLError query_path_attribute(tinyxml2::XMLElement* element, const char* attribute, - std::filesystem::path* out); - void query_color_attribute(tinyxml2::XMLElement* element, const char* attribute, float& out); -} \ No newline at end of file + std::string document_to_string(tinyxml2::XMLDocument&); + tinyxml2::XMLError query_string_attribute(tinyxml2::XMLElement*, const char*, std::string*); + tinyxml2::XMLError query_path_attribute(tinyxml2::XMLElement*, const char*, std::filesystem::path*); + void query_color_attribute(tinyxml2::XMLElement*, const char*, float&); +} From dd3aeae6d2bbe30a876b6c17836766c3a609a33d Mon Sep 17 00:00:00 2001 From: shweet Date: Sun, 26 Oct 2025 16:06:34 -0400 Subject: [PATCH 08/15] Snapshots, refactoring --- src/animation_preview.cpp | 56 ++++++++++++---- src/animation_preview.h | 2 +- src/anm2.cpp | 44 +++++++++++++ src/anm2.h | 1 + src/canvas.cpp | 24 +++++-- src/canvas.h | 4 +- src/document.cpp | 128 +++++++++++++++++++++++++++++++++---- src/document.h | 17 ++++- src/frame_properties.cpp | 72 ++++++++++----------- src/imgui.cpp | 4 +- src/shader.h | 37 +++++------ src/spritesheet_editor.cpp | 100 ++++++++++++++++++++++++++--- src/spritesheet_editor.h | 1 + src/texture.cpp | 52 +++++++++++++++ src/texture.h | 2 + src/timeline.cpp | 5 +- 16 files changed, 443 insertions(+), 106 deletions(-) diff --git a/src/animation_preview.cpp b/src/animation_preview.cpp index 8db80c7..f73ded1 100644 --- a/src/animation_preview.cpp +++ b/src/animation_preview.cpp @@ -19,7 +19,6 @@ namespace anm2ed::animation_preview { constexpr auto NULL_COLOR = vec4(0.0f, 0.0f, 1.0f, 0.90f); constexpr auto TARGET_SIZE = vec2(32, 32); - constexpr auto PIVOT_SIZE = vec2(8, 8); constexpr auto POINT_SIZE = vec2(4, 4); constexpr auto NULL_RECT_SIZE = vec2(100); constexpr auto TRIGGER_TEXT_COLOR = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); @@ -83,9 +82,17 @@ namespace anm2ed::animation_preview auto widgetSize = imgui::widget_size_with_row_get(2); + imgui::shortcut(settings.shortcutCenterView); if (ImGui::Button("Center View", widgetSize)) pan = vec2(); + imgui::set_item_tooltip_shortcut("Centers the view.", settings.shortcutCenterView); + ImGui::SameLine(); - ImGui::Button("Fit", widgetSize); + + imgui::shortcut(settings.shortcutFit); + if (ImGui::Button("Fit", widgetSize)) + if (animation) set_to_rect(zoom, pan, animation->rect(isRootTransform)); + imgui::set_item_tooltip_shortcut("Set the view to match the extent of the animation.", settings.shortcutFit); + ImGui::TextUnformatted(std::format(POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y).c_str()); } ImGui::EndChild(); @@ -181,9 +188,8 @@ namespace anm2ed::animation_preview auto layerTransform = transform * math::quad_model_get(frame.size, frame.position, frame.pivot, math::percent_to_unit(frame.scale), frame.rotation); - auto inset = 0.5f / vec2(texture.size); // needed to avoid bleed - auto uvMin = frame.crop / vec2(texture.size) + inset; - auto uvMax = (frame.crop + frame.size) / vec2(texture.size) - inset; + auto uvMin = frame.crop / vec2(texture.size); + auto uvMax = (frame.crop + frame.size) / vec2(texture.size); auto vertices = math::uv_vertices_get(uvMin, uvMax); vec3 frameColorOffset = frame.offset + colorOffset; vec4 frameTint = frame.tint; @@ -298,15 +304,24 @@ namespace anm2ed::animation_preview mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos)); - auto isRound = settings.propertiesIsRound; + auto isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); + auto isMouseReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Left); auto isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); auto isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); + auto isLeftPressed = ImGui::IsKeyPressed(ImGuiKey_LeftArrow, false); + auto isRightPressed = ImGui::IsKeyPressed(ImGuiKey_RightArrow, false); + auto isUpPressed = ImGui::IsKeyPressed(ImGuiKey_UpArrow, false); + auto isDownPressed = ImGui::IsKeyPressed(ImGuiKey_DownArrow, false); + auto isLeftReleased = ImGui::IsKeyReleased(ImGuiKey_LeftArrow); + auto isRightReleased = ImGui::IsKeyReleased(ImGuiKey_RightArrow); + auto isUpReleased = ImGui::IsKeyReleased(ImGuiKey_UpArrow); + auto isDownReleased = ImGui::IsKeyReleased(ImGuiKey_DownArrow); auto isLeft = imgui::chord_repeating(ImGuiKey_LeftArrow); auto isRight = imgui::chord_repeating(ImGuiKey_RightArrow); auto isUp = imgui::chord_repeating(ImGuiKey_UpArrow); auto isDown = imgui::chord_repeating(ImGuiKey_DownArrow); auto isMouseRightDown = ImGui::IsMouseDown(ImGuiMouseButton_Right); - auto mouseDelta = to_vec2(ImGui::GetIO().MouseDelta); + auto mouseDelta = to_ivec2(ImGui::GetIO().MouseDelta); auto mouseWheel = ImGui::GetIO().MouseWheel; auto isZoomIn = imgui::chord_repeating(imgui::string_to_chord(settings.shortcutZoomIn)); auto isZoomOut = imgui::chord_repeating(imgui::string_to_chord(settings.shortcutZoomOut)); @@ -314,7 +329,10 @@ namespace anm2ed::animation_preview auto frame = document.frame_get(); auto useTool = tool; auto step = isMod ? step::FAST : step::NORMAL; - auto isClick = isMouseDown; + auto isKeyPressed = isLeftPressed || isRightPressed || isUpPressed || isDownPressed; + auto isKeyReleased = isLeftReleased || isRightReleased || isUpReleased || isDownReleased; + auto isBegin = isMouseClick || isKeyPressed; + auto isEnd = isMouseReleased || isKeyReleased; if (isMouseMiddleDown) useTool = tool::PAN; if (tool == tool::MOVE && isMouseRightDown) useTool = tool::SCALE; @@ -323,30 +341,42 @@ namespace anm2ed::animation_preview switch (useTool) { case tool::PAN: - if (isClick || isMouseMiddleDown) pan += isRound ? vec2(ivec2(mouseDelta)) : mouseDelta; + if (isMouseDown || isMouseMiddleDown) pan += mouseDelta; break; case tool::MOVE: if (!frame) break; - if (isClick) frame->position = isRound ? vec2(ivec2(mousePos)) : mousePos; + if (isBegin) document.snapshot("Frame Position"); + if (isMouseDown) frame->position = mousePos; if (isLeft) frame->position.x -= step; if (isRight) frame->position.x += step; if (isUp) frame->position.y -= step; if (isDown) frame->position.y += step; + if (isEnd) document.change(change::FRAMES); break; case tool::SCALE: if (!frame) break; - if (isClick) frame->scale += isRound ? vec2(ivec2(mouseDelta)) : mouseDelta; + if (isBegin) document.snapshot("Frame Scale"); + if (isMouseDown) frame->scale += mouseDelta; + if (isLeft) frame->scale.x -= step; + if (isRight) frame->scale.x += step; + if (isUp) frame->scale.y -= step; + if (isDown) frame->scale.y += step; + if (isEnd) document.change(change::FRAMES); break; case tool::ROTATE: if (!frame) break; - if (isClick) frame->rotation += isRound ? (int)mouseDelta.y : mouseDelta.y; + if (isBegin) document.snapshot("Frame Rotation"); + if (isMouseDown) frame->rotation += mouseDelta.y; + if (isLeft || isDown) frame->rotation -= step; + if (isUp || isRight) frame->rotation += step; + if (isEnd) document.change(change::FRAMES); break; default: break; } if (mouseWheel != 0 || isZoomIn || isZoomOut) - zoom_set(zoom, pan, mousePos, (mouseWheel > 0 || isZoomIn) ? zoomStep : -zoomStep); + zoom_set(zoom, pan, vec2(mousePos), (mouseWheel > 0 || isZoomIn) ? zoomStep : -zoomStep); } } ImGui::End(); diff --git a/src/animation_preview.h b/src/animation_preview.h index ef490dd..65a1a18 100644 --- a/src/animation_preview.h +++ b/src/animation_preview.h @@ -10,7 +10,7 @@ namespace anm2ed::animation_preview class AnimationPreview : public canvas::Canvas { bool isPreviewHovered{}; - glm::vec2 mousePos{}; + glm::ivec2 mousePos{}; public: AnimationPreview(); diff --git a/src/anm2.cpp b/src/anm2.cpp index 652b8f4..814f0cd 100644 --- a/src/anm2.cpp +++ b/src/anm2.cpp @@ -797,6 +797,50 @@ namespace anm2ed::anm2 return std::string(printer.CStr()); } + vec4 Animation::rect(bool isRootTransform) + { + f32 minX = std::numeric_limits::infinity(); + f32 minY = std::numeric_limits::infinity(); + f32 maxX = -std::numeric_limits::infinity(); + f32 maxY = -std::numeric_limits::infinity(); + bool any = false; + + constexpr ivec2 CORNERS[4] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; + + for (float t = 0.0f; t < (float)frameNum; t += 1.0f) + { + mat4 transform(1.0f); + + if (isRootTransform) + { + auto root = rootAnimation.frame_generate(t, anm2::ROOT); + transform *= math::quad_model_parent_get(root.position, {}, math::percent_to_unit(root.scale), root.rotation); + } + + for (auto& [id, layerAnimation] : layerAnimations) + { + auto frame = layerAnimation.frame_generate(t, anm2::LAYER); + + if (frame.size == vec2() || !frame.isVisible) continue; + + auto layerTransform = transform * math::quad_model_get(frame.size, frame.position, frame.pivot, + math::percent_to_unit(frame.scale), frame.rotation); + for (auto& corner : CORNERS) + { + vec4 world = layerTransform * vec4(corner, 0.0f, 1.0f); + minX = std::min(minX, world.x); + minY = std::min(minY, world.y); + maxX = std::max(maxX, world.x); + maxY = std::max(maxY, world.y); + any = true; + } + } + } + + if (!any) return vec4(-1.0f); + return {minX, minY, maxX - minX, maxY - minY}; + } + Animations::Animations() = default; Animations::Animations(XMLElement* element) diff --git a/src/anm2.h b/src/anm2.h index 02aaf5a..935f71c 100644 --- a/src/anm2.h +++ b/src/anm2.h @@ -208,6 +208,7 @@ namespace anm2ed::anm2 void item_remove(Type, int = -1); void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); int length(); + glm::vec4 rect(bool); std::string to_string(); }; diff --git a/src/canvas.cpp b/src/canvas.cpp index 2932a80..526829b 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -3,6 +3,7 @@ #include "math.h" #include #include +#include #include using namespace glm; @@ -183,13 +184,11 @@ namespace anm2ed::canvas void Canvas::grid_render(Shader& shader, float zoom, vec2 pan, ivec2 size, ivec2 offset, vec4 color) { - auto zoomFactor = math::percent_to_unit(zoom); + auto transform = glm::inverse(transform_get(zoom, pan)); glUseProgram(shader.id); - glUniform2f(glGetUniformLocation(shader.id, shader::UNIFORM_VIEW_SIZE), this->size.x, this->size.y); - glUniform2f(glGetUniformLocation(shader.id, shader::UNIFORM_PAN), pan.x, pan.y); - glUniform1f(glGetUniformLocation(shader.id, shader::UNIFORM_ZOOM), zoomFactor); + glUniformMatrix4fv(glGetUniformLocation(shader.id, shader::UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); glUniform2f(glGetUniformLocation(shader.id, shader::UNIFORM_SIZE), (float)size.x, (float)size.y); glUniform2f(glGetUniformLocation(shader.id, shader::UNIFORM_OFFSET), (float)offset.x, (float)offset.y); glUniform4f(glGetUniformLocation(shader.id, shader::UNIFORM_COLOR), color.r, color.g, color.b, color.a); @@ -262,7 +261,7 @@ namespace anm2ed::canvas glBindFramebuffer(GL_FRAMEBUFFER, 0); } - void Canvas::zoom_set(float& zoom, vec2& pan, vec2& focus, float step) + void Canvas::zoom_set(float& zoom, vec2& pan, vec2 focus, float step) { auto zoomFactor = math::percent_to_unit(zoom); float newZoom = glm::clamp(math::round_nearest_multiple(zoom + step, step), canvas::ZOOM_MIN, canvas::ZOOM_MAX); @@ -279,4 +278,19 @@ namespace anm2ed::canvas auto zoomFactor = math::percent_to_unit(zoom); return (position - pan - (size * 0.5f)) / zoomFactor; } + + void Canvas::set_to_rect(float& zoom, vec2& pan, vec4 rect) + { + if (rect != vec4(-1.0f) && (rect.z > 0 && rect.w > 0)) + { + f32 scaleX = size.x / rect.z; + f32 scaleY = size.y / rect.w; + f32 fitScale = std::min(scaleX, scaleY); + + zoom = math::unit_to_percent(fitScale); + + vec2 rectCenter = {rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f}; + pan = -rectCenter * fitScale; + } + } } diff --git a/src/canvas.h b/src/canvas.h index 573d22d..271bc6e 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -9,6 +9,7 @@ namespace anm2ed::canvas { constexpr float TEXTURE_VERTICES[] = {0, 0, 0.0f, 0.0f, 1, 0, 1.0f, 0.0f, 1, 1, 1.0f, 1.0f, 0, 1, 0.0f, 1.0f}; + constexpr auto PIVOT_SIZE = glm::vec2(8, 8); constexpr auto ZOOM_MIN = 1.0f; constexpr auto ZOOM_MAX = 2000.0f; constexpr auto POSITION_FORMAT = "Position: ({:8} {:8})"; @@ -49,7 +50,8 @@ namespace anm2ed::canvas void clear(glm::vec4&); void bind(); void unbind(); - void zoom_set(float&, glm::vec2&, glm::vec2&, float); + void zoom_set(float&, glm::vec2&, glm::vec2, float); glm::vec2 position_translate(float&, glm::vec2&, glm::vec2); + void set_to_rect(float& zoom, glm::vec2& pan, glm::vec4 rect); }; } diff --git a/src/document.cpp b/src/document.cpp index 7cdf70e..ff46ba3 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -13,6 +13,8 @@ using namespace anm2ed::toast; using namespace anm2ed::types; using namespace anm2ed::util; +using namespace glm; + namespace anm2ed::document { Document::Document(const std::string& path, bool isNew, std::string* errorString) @@ -158,6 +160,110 @@ namespace anm2ed::document change(change::FRAMES); } + void Document::frame_crop_set(anm2::Frame* frame, vec2 crop) + { + if (!frame) return; + snapshot("Frame Crop"); + frame->crop = crop; + change(change::FRAMES); + } + + void Document::frame_size_set(anm2::Frame* frame, vec2 size) + { + if (!frame) return; + snapshot("Frame Size"); + frame->size = size; + change(change::FRAMES); + } + + void Document::frame_position_set(anm2::Frame* frame, vec2 position) + { + if (!frame) return; + snapshot("Frame Position"); + frame->position = position; + change(change::FRAMES); + } + + void Document::frame_pivot_set(anm2::Frame* frame, vec2 pivot) + { + if (!frame) return; + snapshot("Frame Pivot"); + frame->pivot = pivot; + change(change::FRAMES); + } + + void Document::frame_scale_set(anm2::Frame* frame, vec2 scale) + { + if (!frame) return; + snapshot("Frame Scale"); + frame->scale = scale; + change(change::FRAMES); + } + + void Document::frame_rotation_set(anm2::Frame* frame, float rotation) + { + if (!frame) return; + snapshot("Frame Rotation"); + frame->rotation = rotation; + change(change::FRAMES); + } + + void Document::frame_delay_set(anm2::Frame* frame, int delay) + { + if (!frame) return; + snapshot("Frame Delay"); + frame->delay = delay; + change(change::FRAMES); + } + + void Document::frame_tint_set(anm2::Frame* frame, vec4 tint) + { + if (!frame) return; + snapshot("Frame Tint"); + frame->tint = tint; + change(change::FRAMES); + } + + void Document::frame_offset_set(anm2::Frame* frame, vec3 offset) + { + if (!frame) return; + snapshot("Frame Color Offset"); + frame->offset = offset; + change(change::FRAMES); + } + + void Document::frame_is_visible_set(anm2::Frame* frame, bool isVisible) + { + if (!frame) return; + snapshot("Frame Visibility"); + frame->isVisible = isVisible; + change(change::FRAMES); + } + + void Document::frame_is_interpolated_set(anm2::Frame* frame, bool isInterpolated) + { + if (!frame) return; + snapshot("Frame Interpolation"); + frame->isInterpolated = isInterpolated; + change(change::FRAMES); + } + + void Document::frame_flip_x(anm2::Frame* frame) + { + if (!frame) return; + snapshot("Frame Flip X"); + frame->scale.x = -frame->scale.x; + change(change::FRAMES); + } + + void Document::frame_flip_y(anm2::Frame* frame) + { + if (!frame) return; + snapshot("Frame Flip Y"); + frame->scale.y = -frame->scale.y; + change(change::FRAMES); + } + anm2::Item* Document::item_get() { return anm2.item_get(reference); @@ -301,16 +407,6 @@ namespace anm2ed::document toasts.error(std::format("Failed to deserialize event(s): {}", errorString)); } - void Document::item_visible_toggle(anm2::Item* item) - { - if (!item) return; - - snapshot("Item Visible"); - item->isVisible = !item->isVisible; - - change(change::ITEMS); - } - void Document::item_add(anm2::Type type, int id, std::string& name, locale::Type locale, int spritesheetID) { snapshot("Add Item"); @@ -330,15 +426,21 @@ namespace anm2ed::document void Document::item_remove(anm2::Animation* animation) { - snapshot("Remove Item"); - if (!animation) return; - + snapshot("Remove Item"); animation->item_remove(reference.itemType, reference.itemID); reference = {reference.animationIndex}; change(change::ITEMS); } + void Document::item_visible_toggle(anm2::Item* item) + { + if (!item) return; + snapshot("Item Visibility"); + item->isVisible = !item->isVisible; + change(change::ITEMS); + } + anm2::Animation* Document::animation_get() { return anm2.animation_get(reference); diff --git a/src/document.h b/src/document.h index 69b27ff..d7c92c2 100644 --- a/src/document.h +++ b/src/document.h @@ -73,12 +73,27 @@ namespace anm2ed::document anm2::Frame* frame_get(); void frames_add(anm2::Item* item); + void frames_change(); void frames_delete(anm2::Item* item); void frames_bake(int, bool, bool); + void frame_crop_set(anm2::Frame*, glm::vec2); + void frame_size_set(anm2::Frame*, glm::vec2); + void frame_position_set(anm2::Frame*, glm::vec2); + void frame_pivot_set(anm2::Frame*, glm::vec2); + void frame_scale_set(anm2::Frame*, glm::vec2); + void frame_rotation_set(anm2::Frame*, float); + void frame_delay_set(anm2::Frame*, int); + void frame_tint_set(anm2::Frame*, glm::vec4); + void frame_offset_set(anm2::Frame*, glm::vec3); + void frame_is_visible_set(anm2::Frame*, bool); + void frame_is_interpolated_set(anm2::Frame*, bool); + void frame_flip_x(anm2::Frame* frame); + void frame_flip_y(anm2::Frame* frame); anm2::Item* item_get(); void item_add(anm2::Type, int, std::string&, types::locale::Type, int); void item_remove(anm2::Animation* animation); + void item_visible_toggle(anm2::Item*); anm2::Spritesheet* spritesheet_get(); void spritesheet_add(const std::string&); @@ -97,8 +112,6 @@ namespace anm2ed::document void events_remove_unused(); void events_deserialize(const std::string&, types::merge::Type); - void item_visible_toggle(anm2::Item*); - void animation_add(); void animation_duplicate(); void animation_default(); diff --git a/src/frame_properties.cpp b/src/frame_properties.cpp index 57e75f0..2ab5320 100644 --- a/src/frame_properties.cpp +++ b/src/frame_properties.cpp @@ -25,8 +25,8 @@ namespace anm2ed::frame_properties auto& anm2 = document.anm2; auto& reference = document.reference; auto& type = reference.itemType; - auto& isRound = settings.propertiesIsRound; auto frame = document.frame_get(); + auto useFrame = frame ? *frame : anm2::Frame(); ImGui::BeginDisabled(!frame); { @@ -44,77 +44,75 @@ namespace anm2ed::frame_properties } else { - ImGui::BeginDisabled(type == anm2::ROOT || type == anm2::NULL_); { - if (ImGui::InputFloat2("Crop", frame ? value_ptr(frame->crop) : &dummy_value(), - frame ? vec2_format_get(frame->crop) : "")) - if (isRound) frame->crop = ivec2(frame->crop); + if (ImGui::InputFloat2("Crop", frame ? value_ptr(useFrame.crop) : &dummy_value(), + frame ? vec2_format_get(useFrame.crop) : "")) + document.frame_crop_set(frame, useFrame.crop); ImGui::SetItemTooltip("%s", "Change the crop position the frame uses."); - if (ImGui::InputFloat2("Size", frame ? value_ptr(frame->size) : &dummy_value(), - frame ? vec2_format_get(frame->size) : "")) - if (isRound) frame->crop = ivec2(frame->size); + if (ImGui::InputFloat2("Size", frame ? value_ptr(useFrame.size) : &dummy_value(), + frame ? vec2_format_get(useFrame.size) : "")) + document.frame_size_set(frame, useFrame.size); ImGui::SetItemTooltip("%s", "Change the size of the crop the frame uses."); } ImGui::EndDisabled(); - if (ImGui::InputFloat2("Position", frame ? value_ptr(frame->position) : &dummy_value(), - frame ? vec2_format_get(frame->position) : "")) - if (isRound) frame->position = ivec2(frame->position); + if (ImGui::InputFloat2("Position", frame ? value_ptr(useFrame.position) : &dummy_value(), + frame ? vec2_format_get(useFrame.position) : "")) + document.frame_position_set(frame, useFrame.position); ImGui::SetItemTooltip("%s", "Change the position of the frame."); ImGui::BeginDisabled(type == anm2::ROOT || type == anm2::NULL_); { - if (ImGui::InputFloat2("Pivot", frame ? value_ptr(frame->pivot) : &dummy_value(), - frame ? vec2_format_get(frame->pivot) : "")) - if (isRound) frame->position = ivec2(frame->position); + if (ImGui::InputFloat2("Pivot", frame ? value_ptr(useFrame.pivot) : &dummy_value(), + frame ? vec2_format_get(useFrame.pivot) : "")) + document.frame_pivot_set(frame, useFrame.pivot); ImGui::SetItemTooltip("%s", "Change the pivot of the frame; i.e., where it is centered."); } ImGui::EndDisabled(); - if (ImGui::InputFloat2("Scale", frame ? value_ptr(frame->scale) : &dummy_value(), - frame ? vec2_format_get(frame->scale) : "")) - if (isRound) frame->position = ivec2(frame->position); + if (ImGui::InputFloat2("Scale", frame ? value_ptr(useFrame.scale) : &dummy_value(), + frame ? vec2_format_get(useFrame.scale) : "")) + document.frame_scale_set(frame, useFrame.scale); ImGui::SetItemTooltip("%s", "Change the scale of the frame, in percent."); - if (ImGui::InputFloat("Rotation", frame ? &frame->rotation : &dummy_value(), step::NORMAL, step::FAST, - frame ? float_format_get(frame->rotation) : "")) - if (isRound) frame->rotation = (int)frame->rotation; + if (ImGui::InputFloat("Rotation", frame ? &useFrame.rotation : &dummy_value(), step::NORMAL, + step::FAST, frame ? float_format_get(useFrame.rotation) : "")) + document.frame_rotation_set(frame, useFrame.rotation); ImGui::SetItemTooltip("%s", "Change the rotation of the frame."); - ImGui::InputInt("Duration", frame ? &frame->delay : &dummy_value(), step::NORMAL, step::FAST, - !frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); + if (ImGui::InputInt("Duration", frame ? &useFrame.delay : &dummy_value(), step::NORMAL, step::FAST, + !frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0)) + document.frame_delay_set(frame, useFrame.delay); ImGui::SetItemTooltip("%s", "Change how long the frame lasts."); - ImGui::ColorEdit4("Tint", frame ? value_ptr(frame->tint) : &dummy_value()); + if (ImGui::ColorEdit4("Tint", frame ? value_ptr(useFrame.tint) : &dummy_value())) + document.frame_tint_set(frame, useFrame.tint); ImGui::SetItemTooltip("%s", "Change the tint of the frame."); - ImGui::ColorEdit3("Color Offset", frame ? value_ptr(frame->offset) : &dummy_value()); + + if (ImGui::ColorEdit3("Color Offset", frame ? value_ptr(useFrame.offset) : &dummy_value())) + document.frame_offset_set(frame, useFrame.offset); ImGui::SetItemTooltip("%s", "Change the color added onto the frame."); - ImGui::Checkbox("Visible", frame ? &frame->isVisible : &dummy_value()); + if (ImGui::Checkbox("Visible", frame ? &useFrame.isVisible : &dummy_value())) + document.frame_is_visible_set(frame, useFrame.isVisible); ImGui::SetItemTooltip("%s", "Toggle the frame's visibility."); + ImGui::SameLine(); - ImGui::Checkbox("Interpolated", frame ? &frame->isInterpolated : &dummy_value()); + + if (ImGui::Checkbox("Interpolated", frame ? &useFrame.isInterpolated : &dummy_value())) + document.frame_is_interpolated_set(frame, useFrame.isInterpolated); ImGui::SetItemTooltip( "%s", "Toggle the frame interpolating; i.e., blending its values into the next frame based on the time."); - ImGui::SameLine(); - ImGui::EndDisabled(); - ImGui::Checkbox("Round", &settings.propertiesIsRound); - ImGui::BeginDisabled(!frame); - ImGui::SetItemTooltip( - "%s", "When toggled, decimal values will be snapped to their nearest whole value when changed."); - auto widgetSize = imgui::widget_size_with_row_get(2); - if (ImGui::Button("Flip X", widgetSize)) - if (frame) frame->scale.x = -frame->scale.x; + if (ImGui::Button("Flip X", widgetSize)) document.frame_flip_x(frame); ImGui::SetItemTooltip("%s", "Flip the horizontal scale of the frame, to cheat mirroring the frame " "horizontally.\n(Note: the format does not support mirroring.)"); ImGui::SameLine(); - if (ImGui::Button("Flip Y", widgetSize)) - if (frame) frame->scale.y = -frame->scale.y; + if (ImGui::Button("Flip Y", widgetSize)) document.frame_flip_y(frame); ImGui::SetItemTooltip("%s", "Flip the vertical scale of the frame, to cheat mirroring the frame " "vertically.\n(Note: the format does not support mirroring.)"); } diff --git a/src/imgui.cpp b/src/imgui.cpp index 883c15d..1224aad 100644 --- a/src/imgui.cpp +++ b/src/imgui.cpp @@ -236,8 +236,8 @@ namespace anm2ed::imgui bool shortcut(std::string string, shortcut::Type type) { if (ImGui::GetTopMostPopupModal() != nullptr) return false; - auto flags = type == shortcut::GLOBAL || type == shortcut::GLOBAL_SET ? ImGuiInputFlags_RouteGlobal - : ImGuiInputFlags_RouteFocused; + int flags = type == shortcut::GLOBAL || type == shortcut::GLOBAL_SET ? ImGuiInputFlags_RouteGlobal + : ImGuiInputFlags_RouteFocused; if (type == shortcut::GLOBAL_SET || type == shortcut::FOCUSED_SET) { ImGui::SetNextItemShortcut(string_to_chord(string), flags); diff --git a/src/shader.h b/src/shader.h index c29db47..be761fc 100644 --- a/src/shader.h +++ b/src/shader.h @@ -66,25 +66,24 @@ namespace anm2ed::shader )"; constexpr auto GRID_VERTEX = R"( -#version 330 core -layout (location = 0) in vec2 i_position; -layout (location = 1) in vec2 i_uv; + #version 330 core + layout (location = 0) in vec2 i_position; + layout (location = 1) in vec2 i_uv; -out vec2 i_uv_out; + out vec2 i_uv_out; -void main() { - i_uv_out = i_position; - gl_Position = vec4(i_position, 0.0, 1.0); -} + void main() + { + i_uv_out = i_position; + gl_Position = vec4(i_position, 0.0, 1.0); + } )"; constexpr auto GRID_FRAGMENT = R"( #version 330 core in vec2 i_uv_out; - uniform vec2 u_view_size; - uniform vec2 u_pan; - uniform float u_zoom; + uniform mat4 u_transform; uniform vec2 u_size; uniform vec2 u_offset; uniform vec4 u_color; @@ -93,18 +92,15 @@ void main() { void main() { - vec2 viewSize = max(u_view_size, vec2(1.0)); - float zoom = max(u_zoom, 1e-6); - vec2 pan = u_pan; - - vec2 world = (i_uv_out - (2.0 * pan / viewSize)) * (viewSize / (2.0 * zoom)); - world += vec2(0.5); // Half pixel nudge + vec4 world4 = u_transform * vec4(i_uv_out, 0.0, 1.0); + vec2 world = world4.xy / world4.w; vec2 cell = max(u_size, vec2(1.0)); vec2 grid = (world - u_offset) / cell; - vec2 d = abs(fract(grid) - 0.5); - float distance = min(d.x, d.y); + vec2 frac = fract(grid); + vec2 distToLine = min(frac, 1.0 - frac); + float distance = min(distToLine.x, distToLine.y); float fw = min(fwidth(grid.x), fwidth(grid.y)); float alpha = 1.0 - smoothstep(0.0, fw, distance); @@ -127,9 +123,6 @@ void main() { constexpr auto UNIFORM_MODEL = "u_model"; constexpr auto UNIFORM_RECT_SIZE = "u_rect_size"; constexpr auto UNIFORM_TEXTURE = "u_texture"; - constexpr auto UNIFORM_VIEW_SIZE = "u_view_size"; - constexpr auto UNIFORM_PAN = "u_pan"; - constexpr auto UNIFORM_ZOOM = "u_zoom"; enum Type { diff --git a/src/spritesheet_editor.cpp b/src/spritesheet_editor.cpp index 81e7141..24c90dc 100644 --- a/src/spritesheet_editor.cpp +++ b/src/spritesheet_editor.cpp @@ -21,6 +21,9 @@ namespace anm2ed::spritesheet_editor void SpritesheetEditor::update(Manager& manager, Settings& settings, Resources& resources) { auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& reference = document.reference; + auto& referenceSpritesheet = document.referenceSpritesheet; auto& pan = document.editorPan; auto& zoom = document.editorZoom; auto& backgroundColor = settings.editorBackgroundColor; @@ -59,9 +62,16 @@ namespace anm2ed::spritesheet_editor auto widgetSize = ImVec2(imgui::row_widget_width_get(2), 0); - if (ImGui::Button("Center View", widgetSize)) pan = vec2(); + imgui::shortcut(settings.shortcutCenterView); + if (ImGui::Button("Center View", widgetSize)) pan = -size * 0.5f; + imgui::set_item_tooltip_shortcut("Centers the view.", settings.shortcutCenterView); + ImGui::SameLine(); - ImGui::Button("Fit", widgetSize); + + imgui::shortcut(settings.shortcutFit); + if (ImGui::Button("Fit", widgetSize)) + if (spritesheet) set_to_rect(zoom, pan, {0, 0, spritesheet->texture.size.x, spritesheet->texture.size.y}); + imgui::set_item_tooltip_shortcut("Set the view to match the extent of the spritesheet.", settings.shortcutFit); ImGui::TextUnformatted(std::format(POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y).c_str()); } @@ -84,12 +94,27 @@ namespace anm2ed::spritesheet_editor viewport_set(); clear(backgroundColor); + auto frame = document.frame_get(); + if (spritesheet) { auto& texture = spritesheet->texture; - auto transform = transform_get(zoom, pan) * math::quad_model_get(texture.size); - texture_render(shaderTexture, texture.id, transform); - if (isBorder) rect_render(lineShader, transform); + auto transform = transform_get(zoom, pan); + + auto spritesheetTransform = transform * math::quad_model_get(texture.size); + texture_render(shaderTexture, texture.id, spritesheetTransform); + if (isBorder) rect_render(lineShader, spritesheetTransform); + + if (frame && reference.itemID > -1 && + anm2.content.layers.at(reference.itemID).spritesheetID == referenceSpritesheet) + { + auto cropTransform = transform * math::quad_model_get(frame->size, frame->crop); + rect_render(lineShader, cropTransform, color::RED); + + auto pivotTransform = + transform * math::quad_model_get(canvas::PIVOT_SIZE, frame->crop + frame->pivot, PIVOT_SIZE * 0.5f); + texture_render(shaderTexture, resources.icons[icon::PIVOT].id, pivotTransform, color::RED); + } } if (isGrid) grid_render(shaderGrid, zoom, pan, gridSize, gridOffset, gridColor); @@ -102,19 +127,78 @@ namespace anm2ed::spritesheet_editor { ImGui::SetKeyboardFocusHere(-1); + previousMousePos = mousePos; mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos)); + auto isMouseClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left); auto isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); auto isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); - auto mouseDelta = ImGui::GetIO().MouseDelta; + auto mouseDelta = to_ivec2(ImGui::GetIO().MouseDelta); auto mouseWheel = ImGui::GetIO().MouseWheel; + auto& toolColor = settings.toolColor; auto isZoomIn = imgui::chord_repeating(imgui::string_to_chord(settings.shortcutZoomIn)); auto isZoomOut = imgui::chord_repeating(imgui::string_to_chord(settings.shortcutZoomOut)); + auto isLeft = imgui::chord_repeating(ImGuiKey_LeftArrow); + auto isRight = imgui::chord_repeating(ImGuiKey_RightArrow); + auto isUp = imgui::chord_repeating(ImGuiKey_UpArrow); + auto isDown = imgui::chord_repeating(ImGuiKey_DownArrow); + auto isMod = ImGui::IsKeyDown(ImGuiMod_Shift); + auto step = isMod ? step::FAST : step::NORMAL; + auto useTool = tool; + auto isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); + auto isMouseReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Left); + auto isLeftPressed = ImGui::IsKeyPressed(ImGuiKey_LeftArrow, false); + auto isRightPressed = ImGui::IsKeyPressed(ImGuiKey_RightArrow, false); + auto isUpPressed = ImGui::IsKeyPressed(ImGuiKey_UpArrow, false); + auto isDownPressed = ImGui::IsKeyPressed(ImGuiKey_DownArrow, false); + auto isLeftReleased = ImGui::IsKeyReleased(ImGuiKey_LeftArrow); + auto isRightReleased = ImGui::IsKeyReleased(ImGuiKey_RightArrow); + auto isUpReleased = ImGui::IsKeyReleased(ImGuiKey_UpArrow); + auto isDownReleased = ImGui::IsKeyReleased(ImGuiKey_DownArrow); + auto frame = document.frame_get(); + auto isKeyPressed = isLeftPressed || isRightPressed || isUpPressed || isDownPressed; + auto isKeyReleased = isLeftReleased || isRightReleased || isUpReleased || isDownReleased; + auto isBegin = isMouseClick || isKeyPressed; + auto isEnd = isMouseReleased || isKeyReleased; - if ((tool == tool::PAN && isMouseDown) || isMouseMiddleDown) pan += vec2(mouseDelta.x, mouseDelta.y); + if (isMouseMiddleDown) useTool = tool::PAN; - switch (tool) + switch (useTool) { + case tool::PAN: + if (isMouseDown || isMouseMiddleDown) pan += mouseDelta; + break; + case tool::MOVE: + if (!frame) break; + if (isBegin) document.snapshot("Frame Pivot"); + if (isMouseDown) frame->pivot = ivec2(mousePos - frame->crop); + if (isLeft) frame->pivot.x -= step; + if (isRight) frame->pivot.x += step; + if (isUp) frame->pivot.y -= step; + if (isDown) frame->pivot.y += step; + if (isEnd) document.change(change::FRAMES); + break; + case tool::CROP: + if (!frame) break; + if (isBegin) document.snapshot(isMod ? "Frame Size" : "Frame Crop"); + if (isMouseClicked) frame->crop = ivec2(mousePos); + if (isMouseDown) frame->size = ivec2(mousePos - frame->crop); + if (isLeft) isMod ? frame->size.x -= step : frame->crop.x -= step; + if (isRight) isMod ? frame->size.x += step : frame->crop.x += step; + if (isUp) isMod ? frame->size.y -= step : frame->crop.y -= step; + if (isDown) isMod ? frame->size.y += step : frame->crop.y += step; + if (isEnd) document.change(change::FRAMES); + break; + case tool::DRAW: + case tool::ERASE: + { + if (!spritesheet) break; + if (isMouseClicked) document.snapshot(tool == tool::DRAW ? "Draw" : "Erase"); + auto color = tool == tool::DRAW ? toolColor : vec4(); + if (isMouseDown) spritesheet->texture.pixel_line(ivec2(previousMousePos), ivec2(mousePos), color); + if (isMouseReleased) document.change(change::FRAMES); + break; + } default: break; } diff --git a/src/spritesheet_editor.h b/src/spritesheet_editor.h index c1b1c00..13fdb13 100644 --- a/src/spritesheet_editor.h +++ b/src/spritesheet_editor.h @@ -10,6 +10,7 @@ namespace anm2ed::spritesheet_editor class SpritesheetEditor : public canvas::Canvas { glm::vec2 mousePos{}; + glm::vec2 previousMousePos{}; public: SpritesheetEditor(); diff --git a/src/texture.cpp b/src/texture.cpp index 76c9761..306889a 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -20,6 +20,9 @@ #pragma GCC diagnostic pop #endif +#include "math.h" + +using namespace anm2ed::math; using namespace glm; namespace anm2ed::texture @@ -140,6 +143,55 @@ namespace anm2ed::texture return stbi_write_png(path.c_str(), size.x, size.y, CHANNELS, this->pixels.data(), size.x * CHANNELS); } + void Texture::pixel_set(ivec2 position, vec4 color) + { + if (position.x < 0 || position.y < 0 || position.x >= size.x || position.y >= size.y) return; + + uint8 rgba8[4] = {(uint8)float_to_uint8(color.r), (uint8)float_to_uint8(color.g), (uint8)float_to_uint8(color.b), + (uint8)float_to_uint8(color.a)}; + + glBindTexture(GL_TEXTURE_2D, id); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, position.x, position.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba8); + glBindTexture(GL_TEXTURE_2D, 0); + } + + void Texture::pixel_line(ivec2 start, ivec2 end, vec4 color) + { + auto plot = [&](ivec2 pos) + { + pixel_set(pos, color); + }; + + int x0 = start.x; + int y0 = start.y; + int x1 = end.x; + int y1 = end.y; + + int dx = std::abs(x1 - x0); + int dy = -std::abs(y1 - y0); + int sx = x0 < x1 ? 1 : -1; + int sy = y0 < y1 ? 1 : -1; + int err = dx + dy; + + while (true) + { + plot({x0, y0}); + if (x0 == x1 && y0 == y1) break; + int e2 = 2 * err; + if (e2 >= dy) + { + err += dy; + x0 += sx; + } + if (e2 <= dx) + { + err += dx; + y0 += sy; + } + } + } + void Texture::bind(GLuint unit) { glActiveTexture(GL_TEXTURE0 + unit); diff --git a/src/texture.h b/src/texture.h index 9fc8076..a5e5b0e 100644 --- a/src/texture.h +++ b/src/texture.h @@ -33,6 +33,8 @@ namespace anm2ed::texture Texture(const char*, size_t, glm::ivec2); Texture(const std::string&); bool write_png(const std::string&); + void pixel_set(glm::ivec2, glm::vec4); + void pixel_line(glm::ivec2, glm::ivec2, glm::vec4); void bind(GLuint = 0); void unbind(GLuint = 0); }; diff --git a/src/timeline.cpp b/src/timeline.cpp index dd47ff6..e0e71f6 100644 --- a/src/timeline.cpp +++ b/src/timeline.cpp @@ -46,8 +46,8 @@ namespace anm2ed::timeline constexpr auto HELP_FORMAT = R"(- Press {} to decrement time. - Press {} to increment time. -- Press {} to extend the selected frame, by one frame. - Press {} to shorten the selected frame, by one frame. +- Press {} to extend the selected frame, by one frame. - Hold Alt while clicking a non-trigger frame to toggle interpolation.)"; void Timeline::item_child(Manager& manager, Document& document, anm2::Animation* animation, Settings& settings, @@ -479,7 +479,8 @@ namespace anm2ed::timeline if (ImGui::Button("##Frame Button", size)) { - if (type != anm2::TRIGGER && ImGui::IsKeyDown(ImGuiMod_Alt)) frame.isInterpolated = !frame.isInterpolated; + if (type != anm2::TRIGGER && ImGui::IsKeyDown(ImGuiMod_Alt)) + document.frame_is_interpolated_set(&frame, !frame.isInterpolated); if (type == anm2::LAYER) { document.referenceSpritesheet = anm2.content.layers[id].spritesheetID; From 729d5fb21634fb1df44bf3f0ce3af180a56ac27c Mon Sep 17 00:00:00 2001 From: shweet Date: Tue, 28 Oct 2025 15:47:54 -0400 Subject: [PATCH 09/15] Autosave feature, spritesheet editor dashed lines, refactoring, fixes --- CMakeLists.txt | 5 +- src/animation_preview.cpp | 77 ++++---- src/animations.cpp | 19 +- src/anm2.cpp | 211 +++++++++++++++++++--- src/anm2.h | 14 +- src/canvas.cpp | 24 ++- src/canvas.h | 9 +- src/dockspace.cpp | 9 +- src/dockspace.h | 2 + src/document.cpp | 131 ++++++++++++-- src/document.h | 23 ++- src/documents.cpp | 101 ++++++++--- src/documents.h | 7 +- src/events.cpp | 2 + src/filesystem.cpp | 5 + src/filesystem.h | 1 + src/frame_properties.cpp | 4 +- src/icon.h | 10 ++ src/imgui.cpp | 5 + src/imgui.h | 1 + src/layers.cpp | 2 + src/loader.cpp | 2 +- src/manager.cpp | 219 +++++++++++++++++++++-- src/manager.h | 30 +++- src/nulls.cpp | 2 + src/settings.h | 8 +- src/shader.h | 86 ++++++++- src/spritesheet_editor.cpp | 14 +- src/spritesheets.cpp | 2 + src/state.cpp | 9 +- src/state.h | 5 +- src/taskbar.cpp | 353 +++++++++++++++++++++++++++++++++---- src/taskbar.h | 11 +- src/timeline.cpp | 111 +++++++++--- src/timeline.h | 16 +- src/types.h | 10 ++ src/util.h | 12 ++ src/welcome.cpp | 106 +++++++++++ src/welcome.h | 16 ++ 39 files changed, 1446 insertions(+), 228 deletions(-) create mode 100644 src/welcome.cpp create mode 100644 src/welcome.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2602b5b..9316794 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,13 +63,14 @@ if (WIN32) target_link_options(${PROJECT_NAME} PRIVATE /STACK:0xffffff) else () target_compile_options(${PROJECT_NAME} PRIVATE - -O2 -Wall -Wextra -pedantic + -Wall -Wextra -pedantic ) if (CMAKE_BUILD_TYPE STREQUAL "Debug") target_compile_definitions(${PROJECT_NAME} PRIVATE DEBUG) - target_compile_options(${PROJECT_NAME} PRIVATE -pg) + target_compile_options(${PROJECT_NAME} PRIVATE -O0 -pg) else () set(CMAKE_BUILD_TYPE "Release") + target_compile_options(${PROJECT_NAME} PRIVATE -O2) endif () target_link_libraries(${PROJECT_NAME} PRIVATE m) diff --git a/src/animation_preview.cpp b/src/animation_preview.cpp index f73ded1..4c523b0 100644 --- a/src/animation_preview.cpp +++ b/src/animation_preview.cpp @@ -48,15 +48,18 @@ namespace anm2ed::animation_preview auto& isRootTransform = settings.previewIsRootTransform; auto& isPivots = settings.previewIsPivots; auto& isAxes = settings.previewIsAxes; - auto& isIcons = settings.previewIsIcons; auto& isAltIcons = settings.previewIsAltIcons; auto& isBorder = settings.previewIsBorder; auto& tool = settings.tool; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; auto& shaderLine = resources.shaders[shader::LINE]; auto& shaderAxes = resources.shaders[shader::AXIS]; auto& shaderGrid = resources.shaders[shader::GRID]; auto& shaderTexture = resources.shaders[shader::TEXTURE]; + settings.previewPan = pan; + settings.previewZoom = zoom; + if (ImGui::Begin("Animation Preview", &settings.windowIsAnimationPreview)) { @@ -128,7 +131,6 @@ namespace anm2ed::animation_preview { ImGui::Checkbox("Root Transform", &isRootTransform); ImGui::Checkbox("Pivots", &isPivots); - ImGui::Checkbox("Icons", &isIcons); } ImGui::EndChild(); @@ -152,7 +154,8 @@ namespace anm2ed::animation_preview if (isAxes) axes_render(shaderAxes, zoom, pan, axesColor); if (isGrid) grid_render(shaderGrid, zoom, pan, gridSize, gridOffset, gridColor); - auto render = [&](float time, vec3 colorOffset = {}, float alphaOffset = {}, bool isOnionskin = false) + auto render = [&](anm2::Animation* animation, float time, vec3 colorOffset = {}, float alphaOffset = {}, + bool isOnionskin = false) { auto transform = transform_get(zoom, pan); auto root = animation->rootAnimation.frame_generate(time, anm2::ROOT); @@ -160,7 +163,7 @@ namespace anm2ed::animation_preview if (isRootTransform) transform *= math::quad_model_parent_get(root.position, {}, math::percent_to_unit(root.scale), root.rotation); - if (isIcons && root.isVisible && animation->rootAnimation.isVisible) + if (!isOnlyShowLayers && root.isVisible && animation->rootAnimation.isVisible) { auto rootTransform = transform * math::quad_model_get(TARGET_SIZE, root.position, TARGET_SIZE * 0.5f, math::percent_to_unit(root.scale), root.rotation); @@ -185,13 +188,14 @@ namespace anm2ed::animation_preview auto& texture = spritesheet->texture; if (!texture.is_valid()) continue; - auto layerTransform = transform * math::quad_model_get(frame.size, frame.position, frame.pivot, - math::percent_to_unit(frame.scale), frame.rotation); + auto layerModel = math::quad_model_get(frame.size, frame.position, frame.pivot, + math::percent_to_unit(frame.scale), frame.rotation); + auto layerTransform = transform * layerModel; auto uvMin = frame.crop / vec2(texture.size); auto uvMax = (frame.crop + frame.size) / vec2(texture.size); auto vertices = math::uv_vertices_get(uvMin, uvMax); - vec3 frameColorOffset = frame.offset + colorOffset; + vec3 frameColorOffset = frame.colorOffset + colorOffset; vec4 frameTint = frame.tint; frameTint.a = std::max(0.0f, frameTint.a - alphaOffset); @@ -199,48 +203,46 @@ namespace anm2ed::animation_preview auto color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : color::RED; - if (isBorder) rect_render(shaderLine, layerTransform, color); + if (isBorder) rect_render(shaderLine, layerTransform, layerModel, color); if (isPivots) { - auto pivotTransform = - transform * math::quad_model_get(PIVOT_SIZE, frame.position, PIVOT_SIZE * 0.5f, - math::percent_to_unit(frame.scale), frame.rotation); + auto pivotModel = math::quad_model_get(PIVOT_SIZE, frame.position, PIVOT_SIZE * 0.5f, + math::percent_to_unit(frame.scale), frame.rotation); + auto pivotTransform = transform * pivotModel; texture_render(shaderTexture, resources.icons[icon::PIVOT].id, pivotTransform, color); } } } - if (isIcons) + for (auto& [id, nullAnimation] : animation->nullAnimations) { - for (auto& [id, nullAnimation] : animation->nullAnimations) + if (!nullAnimation.isVisible || isOnlyShowLayers) continue; + + auto& isShowRect = anm2.content.nulls[id].isShowRect; + + if (auto frame = nullAnimation.frame_generate(time, anm2::NULL_); frame.isVisible) { - if (!nullAnimation.isVisible) continue; + auto icon = isShowRect ? icon::POINT : icon::TARGET; + auto& size = isShowRect ? POINT_SIZE : TARGET_SIZE; + auto color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) + : id == reference.itemID && reference.itemType == anm2::NULL_ ? color::RED + : NULL_COLOR; - auto& isShowRect = anm2.content.nulls[id].isShowRect; + auto nullModel = math::quad_model_get(size, frame.position, size * 0.5f, math::percent_to_unit(frame.scale), + frame.rotation); + auto nullTransform = transform * nullModel; - if (auto frame = nullAnimation.frame_generate(time, anm2::NULL_); frame.isVisible) + texture_render(shaderTexture, resources.icons[icon].id, nullTransform, color); + + if (isShowRect) { - auto icon = isShowRect ? icon::POINT : icon::TARGET; - auto& size = isShowRect ? POINT_SIZE : TARGET_SIZE; - auto color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) - : id == reference.itemID && reference.itemType == anm2::NULL_ ? color::RED - : NULL_COLOR; + auto rectModel = math::quad_model_get(NULL_RECT_SIZE, frame.position, NULL_RECT_SIZE * 0.5f, + math::percent_to_unit(frame.scale), frame.rotation); + auto rectTransform = transform * rectModel; - auto nullTransform = transform * math::quad_model_get(size, frame.position, size * 0.5f, - math::percent_to_unit(frame.scale), frame.rotation); - - texture_render(shaderTexture, resources.icons[icon].id, nullTransform, color); - - if (isShowRect) - { - auto rectTransform = - transform * math::quad_model_get(NULL_RECT_SIZE, frame.position, NULL_RECT_SIZE * 0.5f, - math::percent_to_unit(frame.scale), frame.rotation); - - rect_render(shaderLine, rectTransform, color); - } + rect_render(shaderLine, rectTransform, rectModel, color); } } } @@ -252,7 +254,7 @@ namespace anm2ed::animation_preview { float useTime = time + (float)(direction * i); float alphaOffset = (1.0f / (count + 1)) * i; - render(useTime, color, alphaOffset, true); + render(animation, useTime, color, alphaOffset, true); } }; @@ -270,7 +272,10 @@ namespace anm2ed::animation_preview auto& isEnabled = settings.onionskinIsEnabled; if (drawOrder == draw_order::BELOW && isEnabled) onionskins_render(frameTime); - render(frameTime); + render(animation, frameTime); + if (overlayIndex > 0) + render(document.anm2.animation_get({overlayIndex - 1}), frameTime, {}, + 1.0f - math::uint8_to_float(overlayTransparency)); if (drawOrder == draw_order::ABOVE && isEnabled) onionskins_render(frameTime); } diff --git a/src/animations.cpp b/src/animations.cpp index 9d2b208..30f4ee9 100644 --- a/src/animations.cpp +++ b/src/animations.cpp @@ -20,6 +20,8 @@ namespace anm2ed::animations auto& mergeMultiSelect = document.animationMergeMultiSelect; auto& mergeTarget = document.mergeTarget; + hovered = -1; + if (ImGui::Begin("Animations", &settings.windowIsAnimations)) { auto childSize = imgui::size_without_footer_get(); @@ -45,7 +47,7 @@ namespace anm2ed::animations if (imgui::selectable_input_text(animation.name, std::format("###Document #{} Animation #{}", manager.selected, i), animation.name, multiSelect.contains(i))) - reference = {(int)i}; + document.animation_set(i); if (ImGui::IsItemHovered()) hovered = i; ImGui::PopFont(); @@ -113,18 +115,7 @@ namespace anm2ed::animations auto cut = [&]() { copy(); - - if (!multiSelect.empty()) - { - for (auto& i : multiSelect | std::views::reverse) - anm2.animations.items.erase(anm2.animations.items.begin() + i); - multiSelect.clear(); - } - else if (hovered > -1) - { - anm2.animations.items.erase(anm2.animations.items.begin() + hovered); - hovered = -1; - } + document.animations_remove(); }; auto paste = [&]() @@ -191,7 +182,7 @@ namespace anm2ed::animations ImGui::SameLine(); imgui::shortcut(settings.shortcutRemove); - if (ImGui::Button("Remove", widgetSize)) document.animation_remove(); + if (ImGui::Button("Remove", widgetSize)) document.animations_remove(); imgui::set_item_tooltip_shortcut("Remove the selected animation(s).", settings.shortcutDuplicate); ImGui::SameLine(); diff --git a/src/anm2.cpp b/src/anm2.cpp index 814f0cd..3ec5acf 100644 --- a/src/anm2.cpp +++ b/src/anm2.cpp @@ -17,17 +17,6 @@ using namespace glm; namespace anm2ed::anm2 { - - void Reference::previous_frame(int max) - { - frameIndex = glm::clamp(--frameIndex, 0, max); - } - - void Reference::next_frame(int max) - { - frameIndex = glm::clamp(++frameIndex, 0, max); - } - Info::Info() = default; Info::Info(XMLElement* element) @@ -466,9 +455,9 @@ namespace anm2ed::anm2 xml::query_color_attribute(element, "GreenTint", tint.g); xml::query_color_attribute(element, "BlueTint", tint.b); xml::query_color_attribute(element, "AlphaTint", tint.a); - xml::query_color_attribute(element, "RedOffset", offset.r); - xml::query_color_attribute(element, "GreenOffset", offset.g); - xml::query_color_attribute(element, "BlueOffset", offset.b); + xml::query_color_attribute(element, "RedOffset", colorOffset.r); + xml::query_color_attribute(element, "GreenOffset", colorOffset.g); + xml::query_color_attribute(element, "BlueOffset", colorOffset.b); element->QueryFloatAttribute("Rotation", &rotation); element->QueryBoolAttribute("Interpolated", &isInterpolated); } @@ -497,9 +486,9 @@ namespace anm2ed::anm2 element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); - element->SetAttribute("RedOffset", math::float_to_uint8(offset.r)); - element->SetAttribute("GreenOffset", math::float_to_uint8(offset.g)); - element->SetAttribute("BlueOffset", math::float_to_uint8(offset.b)); + element->SetAttribute("RedOffset", math::float_to_uint8(colorOffset.r)); + element->SetAttribute("GreenOffset", math::float_to_uint8(colorOffset.g)); + element->SetAttribute("BlueOffset", math::float_to_uint8(colorOffset.b)); element->SetAttribute("Rotation", rotation); element->SetAttribute("Interpolated", isInterpolated); break; @@ -520,9 +509,9 @@ namespace anm2ed::anm2 element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); - element->SetAttribute("RedOffset", math::float_to_uint8(offset.r)); - element->SetAttribute("GreenOffset", math::float_to_uint8(offset.g)); - element->SetAttribute("BlueOffset", math::float_to_uint8(offset.b)); + element->SetAttribute("RedOffset", math::float_to_uint8(colorOffset.r)); + element->SetAttribute("GreenOffset", math::float_to_uint8(colorOffset.g)); + element->SetAttribute("BlueOffset", math::float_to_uint8(colorOffset.b)); element->SetAttribute("Rotation", rotation); element->SetAttribute("Interpolated", isInterpolated); break; @@ -537,6 +526,69 @@ namespace anm2ed::anm2 parent->InsertEndChild(element); } + std::string Frame::to_string(Type type) + { + XMLDocument document; + auto element = document.NewElement(type == TRIGGER ? "Trigger" : "Frame"); + + switch (type) + { + case ROOT: + case NULL_: + element->SetAttribute("XPosition", position.x); + element->SetAttribute("YPosition", position.y); + element->SetAttribute("Delay", delay); + element->SetAttribute("Visible", isVisible); + element->SetAttribute("XScale", scale.x); + element->SetAttribute("YScale", scale.y); + element->SetAttribute("RedTint", math::float_to_uint8(tint.r)); + element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); + element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); + element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); + element->SetAttribute("RedOffset", math::float_to_uint8(colorOffset.r)); + element->SetAttribute("GreenOffset", math::float_to_uint8(colorOffset.g)); + element->SetAttribute("BlueOffset", math::float_to_uint8(colorOffset.b)); + element->SetAttribute("Rotation", rotation); + element->SetAttribute("Interpolated", isInterpolated); + break; + case LAYER: + element->SetAttribute("XPosition", position.x); + element->SetAttribute("YPosition", position.y); + element->SetAttribute("XPivot", pivot.x); + element->SetAttribute("YPivot", pivot.y); + element->SetAttribute("XCrop", crop.x); + element->SetAttribute("YCrop", crop.y); + element->SetAttribute("Width", size.x); + element->SetAttribute("Height", size.y); + element->SetAttribute("XScale", scale.x); + element->SetAttribute("YScale", scale.y); + element->SetAttribute("Delay", delay); + element->SetAttribute("Visible", isVisible); + element->SetAttribute("RedTint", math::float_to_uint8(tint.r)); + element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); + element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); + element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); + element->SetAttribute("RedOffset", math::float_to_uint8(colorOffset.r)); + element->SetAttribute("GreenOffset", math::float_to_uint8(colorOffset.g)); + element->SetAttribute("BlueOffset", math::float_to_uint8(colorOffset.b)); + element->SetAttribute("Rotation", rotation); + element->SetAttribute("Interpolated", isInterpolated); + break; + case TRIGGER: + element->SetAttribute("EventId", eventID); + element->SetAttribute("AtFrame", atFrame); + break; + default: + break; + } + + document.InsertFirstChild(element); + + XMLPrinter printer; + document.Print(&printer); + return std::string(printer.CStr()); + } + void Frame::shorten() { delay = glm::clamp(--delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); @@ -640,13 +692,98 @@ namespace anm2ed::anm2 frame.rotation = glm::mix(frame.rotation, frameNext->rotation, interpolation); frame.position = glm::mix(frame.position, frameNext->position, interpolation); frame.scale = glm::mix(frame.scale, frameNext->scale, interpolation); - frame.offset = glm::mix(frame.offset, frameNext->offset, interpolation); + frame.colorOffset = glm::mix(frame.colorOffset, frameNext->colorOffset, interpolation); frame.tint = glm::mix(frame.tint, frameNext->tint, interpolation); } return frame; } + void Item::frames_change(anm2::FrameChange& change, frame_change::Type type, int start, int numberFrames) + { + auto useStart = numberFrames > -1 ? start : 0; + auto end = numberFrames > -1 ? start + numberFrames : (int)frames.size(); + vector::clamp_in_bounds(frames, useStart); + end = glm::clamp(end, start, (int)frames.size()); + + for (int i = useStart; i < end; i++) + { + Frame& frame = frames[i]; + + if (change.isVisible) frame.isVisible = *change.isVisible; + if (change.isInterpolated) frame.isInterpolated = *change.isInterpolated; + + switch (type) + { + case frame_change::ADJUST: + if (change.rotation) frame.rotation = *change.rotation; + if (change.delay) frame.delay = std::max(FRAME_DELAY_MIN, *change.delay); + if (change.crop) frame.crop = *change.crop; + if (change.pivot) frame.pivot = *change.pivot; + if (change.position) frame.position = *change.position; + if (change.size) frame.size = *change.size; + if (change.scale) frame.scale = *change.scale; + if (change.colorOffset) frame.colorOffset = glm::clamp(*change.colorOffset, 0.0f, 1.0f); + if (change.tint) frame.tint = glm::clamp(*change.tint, 0.0f, 1.0f); + break; + + case frame_change::ADD: + if (change.rotation) frame.rotation += *change.rotation; + if (change.delay) frame.delay = std::max(FRAME_DELAY_MIN, frame.delay + *change.delay); + if (change.crop) frame.crop += *change.crop; + if (change.pivot) frame.pivot += *change.pivot; + if (change.position) frame.position += *change.position; + if (change.size) frame.size += *change.size; + if (change.scale) frame.scale += *change.scale; + if (change.colorOffset) frame.colorOffset = glm::clamp(frame.colorOffset + *change.colorOffset, 0.0f, 1.0f); + if (change.tint) frame.tint = glm::clamp(frame.tint + *change.tint, 0.0f, 1.0f); + break; + + case frame_change::SUBTRACT: + if (change.rotation) frame.rotation -= *change.rotation; + if (change.delay) frame.delay = std::max(FRAME_DELAY_MIN, frame.delay - *change.delay); + if (change.crop) frame.crop -= *change.crop; + if (change.pivot) frame.pivot -= *change.pivot; + if (change.position) frame.position -= *change.position; + if (change.size) frame.size -= *change.size; + if (change.scale) frame.scale -= *change.scale; + if (change.colorOffset) frame.colorOffset = glm::clamp(frame.colorOffset - *change.colorOffset, 0.0f, 1.0f); + if (change.tint) frame.tint = glm::clamp(frame.tint - *change.tint, 0.0f, 1.0f); + break; + } + } + } + + bool Item::frames_deserialize(const std::string& string, Type type, int start, std::set& indices, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + if (!document.FirstChildElement("Frame")) + { + if (errorString) *errorString = "No valid frame(s)."; + return false; + } + + int count{}; + for (auto element = document.FirstChildElement("Frame"); element; element = element->NextSiblingElement("Frame")) + { + auto index = start + count; + frames.insert(frames.begin() + start + count, Frame(element, type)); + indices.insert(index); + count++; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + Animation::Animation() = default; Animation::Animation(XMLElement* element) @@ -1048,12 +1185,12 @@ namespace anm2ed::anm2 return std::hash{}(to_string()); } - Animation* Anm2::animation_get(Reference& reference) + Animation* Anm2::animation_get(Reference reference) { return vector::find(animations.items, reference.animationIndex); } - Item* Anm2::item_get(Reference& reference) + Item* Anm2::item_get(Reference reference) { if (Animation* animation = animation_get(reference)) { @@ -1074,7 +1211,7 @@ namespace anm2ed::anm2 return nullptr; } - Frame* Anm2::frame_get(Reference& reference) + Frame* Anm2::frame_get(Reference reference) { Item* item = item_get(reference); if (!item) return nullptr; @@ -1260,7 +1397,7 @@ namespace anm2ed::anm2 baked.rotation = glm::mix(baseFrame.rotation, baseFrameNext.rotation, interpolation); baked.position = glm::mix(baseFrame.position, baseFrameNext.position, interpolation); baked.scale = glm::mix(baseFrame.scale, baseFrameNext.scale, interpolation); - baked.offset = glm::mix(baseFrame.offset, baseFrameNext.offset, interpolation); + baked.colorOffset = glm::mix(baseFrame.colorOffset, baseFrameNext.colorOffset, interpolation); baked.tint = glm::mix(baseFrame.tint, baseFrameNext.tint, interpolation); if (isRoundScale) baked.scale = vec2(ivec2(baked.scale)); @@ -1275,4 +1412,26 @@ namespace anm2ed::anm2 delay += baked.delay; } } -} + + void Anm2::generate_from_grid(Reference reference, ivec2 startPosition, ivec2 size, ivec2 pivot, int columns, + int count, int delay) + { + auto item = item_get(reference); + if (!item) return; + + for (int i = 0; i < count; i++) + { + auto row = i / columns; + auto column = i % columns; + + Frame frame{}; + + frame.delay = delay; + frame.pivot = pivot; + frame.size = size; + frame.crop = startPosition + ivec2(size.x * column, size.y * row); + + item->frames.emplace_back(frame); + } + } +} \ No newline at end of file diff --git a/src/anm2.h b/src/anm2.h index 935f71c..056cc84 100644 --- a/src/anm2.h +++ b/src/anm2.h @@ -44,8 +44,6 @@ namespace anm2ed::anm2 int frameIndex{-1}; int frameTime{-1}; - void previous_frame(int = FRAME_NUM_MAX - 1); - void next_frame(int = FRAME_NUM_MAX - 1); auto operator<=>(const Reference&) const = default; }; @@ -150,7 +148,7 @@ namespace anm2ed::anm2 X(position, glm::vec2, {}) \ X(size, glm::vec2, {}) \ X(scale, glm::vec2, glm::vec2(100.0f)) \ - X(offset, glm::vec3, types::color::TRANSPARENT) \ + X(colorOffset, glm::vec3, types::color::TRANSPARENT) \ X(tint, glm::vec4, types::color::WHITE) class Frame @@ -162,6 +160,7 @@ namespace anm2ed::anm2 Frame(); Frame(tinyxml2::XMLElement*, Type); + std::string to_string(Type type); void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, Type); void shorten(); void extend(); @@ -188,6 +187,8 @@ namespace anm2ed::anm2 void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, Type, int = -1); int length(Type); Frame frame_generate(float, Type); + void frames_change(anm2::FrameChange&, types::frame_change::Type, int, int = 0); + bool frames_deserialize(const std::string&, Type, int, std::set&, std::string*); }; class Animation @@ -238,9 +239,9 @@ namespace anm2ed::anm2 std::string to_string(); Anm2(const std::string&, std::string* = nullptr); uint64_t hash(); - Animation* animation_get(Reference&); - Item* item_get(Reference&); - Frame* frame_get(Reference&); + Animation* animation_get(Reference); + Item* item_get(Reference); + Frame* frame_get(Reference); bool spritesheet_add(const std::string&, const std::string&, int&); Spritesheet* spritesheet_get(int); void spritesheet_remove(int); @@ -255,5 +256,6 @@ namespace anm2ed::anm2 std::set nulls_unused(Reference = REFERENCE_DEFAULT); std::vector spritesheet_names_get(); void bake(Reference, int = 1, bool = true, bool = true); + void generate_from_grid(Reference, glm::ivec2, glm::ivec2, glm::ivec2, int, int, int); }; } diff --git a/src/canvas.cpp b/src/canvas.cpp index 526829b..2776404 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -226,13 +226,35 @@ namespace anm2ed::canvas glUseProgram(0); } - void Canvas::rect_render(Shader& shader, mat4& transform, vec4 color) + void Canvas::rect_render(Shader& shader, const mat4& transform, const mat4& model, vec4 color, float dashLength, + float dashGap, float dashOffset) { glUseProgram(shader.id); glUniformMatrix4fv(glGetUniformLocation(shader.id, shader::UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); + if (auto location = glGetUniformLocation(shader.id, shader::UNIFORM_MODEL); location != -1) + glUniformMatrix4fv(location, 1, GL_FALSE, value_ptr(model)); glUniform4fv(glGetUniformLocation(shader.id, shader::UNIFORM_COLOR), 1, value_ptr(color)); + auto origin = model * vec4(0.0f, 0.0f, 0.0f, 1.0f); + auto edgeX = model * vec4(1.0f, 0.0f, 0.0f, 1.0f); + auto edgeY = model * vec4(0.0f, 1.0f, 0.0f, 1.0f); + + auto axisX = vec2(edgeX - origin); + auto axisY = vec2(edgeY - origin); + + if (auto location = glGetUniformLocation(shader.id, shader::UNIFORM_AXIS_X); location != -1) + glUniform2fv(location, 1, value_ptr(axisX)); + if (auto location = glGetUniformLocation(shader.id, shader::UNIFORM_AXIS_Y); location != -1) + glUniform2fv(location, 1, value_ptr(axisY)); + + if (auto location = glGetUniformLocation(shader.id, shader::UNIFORM_DASH_LENGTH); location != -1) + glUniform1f(location, dashLength); + if (auto location = glGetUniformLocation(shader.id, shader::UNIFORM_DASH_GAP); location != -1) + glUniform1f(location, dashGap); + if (auto location = glGetUniformLocation(shader.id, shader::UNIFORM_DASH_OFFSET); location != -1) + glUniform1f(location, dashOffset); + glBindVertexArray(rectVAO); glDrawArrays(GL_LINE_LOOP, 0, 4); diff --git a/src/canvas.h b/src/canvas.h index 271bc6e..925c62d 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -14,6 +14,10 @@ namespace anm2ed::canvas constexpr auto ZOOM_MAX = 2000.0f; constexpr auto POSITION_FORMAT = "Position: ({:8} {:8})"; + constexpr auto DASH_LENGTH = 4.0f; + constexpr auto DASH_GAP = 1.0f; + constexpr auto DASH_OFFSET = 1.0f; + class Canvas { public: @@ -39,13 +43,14 @@ namespace anm2ed::canvas void framebuffer_set(); void framebuffer_resize_check(); void size_set(glm::vec2); - glm::mat4 transform_get(float, glm::vec2); + glm::mat4 transform_get(float = 100.0f, glm::vec2 = {}); void axes_render(shader::Shader&, float, glm::vec2, glm::vec4 = glm::vec4(1.0f)); void grid_render(shader::Shader&, float, glm::vec2, glm::ivec2 = glm::ivec2(32, 32), glm::ivec2 = {}, glm::vec4 = glm::vec4(1.0f)); void texture_render(shader::Shader&, GLuint&, glm::mat4&, glm::vec4 = glm::vec4(1.0f), glm::vec3 = {}, float* = (float*)TEXTURE_VERTICES); - void rect_render(shader::Shader&, glm::mat4&, glm::vec4 = glm::vec4(1.0f)); + void rect_render(shader::Shader&, const glm::mat4&, const glm::mat4&, glm::vec4 = glm::vec4(1.0f), + float dashLength = DASH_LENGTH, float dashGap = DASH_GAP, float dashOffset = DASH_OFFSET); void viewport_set(); void clear(glm::vec4&); void bind(); diff --git a/src/dockspace.cpp b/src/dockspace.cpp index f77f28d..ec28d91 100644 --- a/src/dockspace.cpp +++ b/src/dockspace.cpp @@ -13,6 +13,7 @@ using namespace anm2ed::playback; using namespace anm2ed::resources; using namespace anm2ed::settings; using namespace anm2ed::taskbar; +using namespace anm2ed::welcome; namespace anm2ed::dockspace { @@ -32,9 +33,9 @@ namespace anm2ed::dockspace ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus)) { - if (ImGui::DockSpace(ImGui::GetID("##DockSpace"), ImVec2(), ImGuiDockNodeFlags_PassthruCentralNode)) + if (auto document = manager.get(); document) { - if (auto document = manager.get(); document) + if (ImGui::DockSpace(ImGui::GetID("##DockSpace"), ImVec2(), ImGuiDockNodeFlags_PassthruCentralNode)) { if (settings.windowIsAnimationPreview) animationPreview.update(manager, settings, resources); if (settings.windowIsAnimations) animations.update(manager, settings, resources, clipboard); @@ -45,10 +46,12 @@ namespace anm2ed::dockspace if (settings.windowIsOnionskin) onionskin.update(settings); if (settings.windowIsSpritesheetEditor) spritesheetEditor.update(manager, settings, resources); if (settings.windowIsSpritesheets) spritesheets.update(manager, settings, resources, dialog, clipboard); - if (settings.windowIsTimeline) timeline.update(manager, settings, resources); + if (settings.windowIsTimeline) timeline.update(manager, settings, resources, clipboard); if (settings.windowIsTools) tools.update(manager, settings, resources); } } + else + welcome.update(manager, resources, dialog, taskbar, documents); } ImGui::End(); } diff --git a/src/dockspace.h b/src/dockspace.h index 04ef75f..532fed3 100644 --- a/src/dockspace.h +++ b/src/dockspace.h @@ -13,6 +13,7 @@ #include "taskbar.h" #include "timeline.h" #include "tools.h" +#include "welcome.h" namespace anm2ed::dockspace { @@ -29,6 +30,7 @@ namespace anm2ed::dockspace spritesheets::Spritesheets spritesheets; timeline::Timeline timeline; tools::Tools tools; + welcome::Welcome welcome; public: void update(taskbar::Taskbar&, documents::Documents&, manager::Manager&, settings::Settings&, resources::Resources&, diff --git a/src/document.cpp b/src/document.cpp index ff46ba3..a24ccb4 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1,17 +1,20 @@ #include "document.h" +#include +#include + #include "anm2.h" #include "filesystem.h" +#include "log.h" #include "toast.h" #include "util.h" -#include -#include using namespace anm2ed::anm2; using namespace anm2ed::filesystem; using namespace anm2ed::toast; using namespace anm2ed::types; using namespace anm2ed::util; +using namespace anm2ed::log; using namespace glm; @@ -40,9 +43,28 @@ namespace anm2ed::document if (anm2.serialize(this->path, errorString)) { + toasts.info(std::format("Saved document to: {}", path)); clean(); return true; } + else if (errorString) + toasts.warning(std::format("Could not save document to: {} ({})", path, *errorString)); + + return false; + } + + bool Document::autosave(const std::string& path, std::string* errorString) + { + if (anm2.serialize(path, errorString)) + { + autosaveHash = hash; + lastAutosaveTime = 0.0f; + toasts.info("Autosaving..."); + logger.info(std::format("Autosaved document to: {}", path)); + return true; + } + else if (errorString) + toasts.warning(std::format("Could not autosave document to: {} ({})", path, *errorString)); return false; } @@ -56,6 +78,8 @@ namespace anm2ed::document { saveHash = anm2.hash(); hash = saveHash; + lastAutosaveTime = 0.0f; + isForceDirty = false; } void Document::change(change::Type type) @@ -88,6 +112,8 @@ namespace anm2ed::document case change::SPRITESHEETS: spritesheet_set(); break; + case change::ITEMS: + break; case change::ALL: layer_set(); null_set(); @@ -104,14 +130,19 @@ namespace anm2ed::document return hash != saveHash; } - std::string Document::directory_get() + bool Document::is_autosave_dirty() + { + return hash != autosaveHash; + } + + std::filesystem::path Document::directory_get() { return path.parent_path(); } - std::string Document::filename_get() + std::filesystem::path Document::filename_get() { - return path.filename().string(); + return path.filename(); } bool Document::is_valid() @@ -224,11 +255,11 @@ namespace anm2ed::document change(change::FRAMES); } - void Document::frame_offset_set(anm2::Frame* frame, vec3 offset) + void Document::frame_color_offset_set(anm2::Frame* frame, vec3 colorOffset) { if (!frame) return; snapshot("Frame Color Offset"); - frame->offset = offset; + frame->colorOffset = colorOffset; change(change::FRAMES); } @@ -264,6 +295,52 @@ namespace anm2ed::document change(change::FRAMES); } + void Document::frame_shorten() + { + auto frame = frame_get(); + if (!frame) return; + snapshot("Shorten Frame"); + frame->shorten(); + change(change::FRAMES); + } + + void Document::frame_extend() + { + auto frame = frame_get(); + if (!frame) return; + snapshot("Extend Frame"); + frame->extend(); + change(change::FRAMES); + } + + void Document::frames_change(anm2::FrameChange& frameChange, frame_change::Type type, bool isFromSelectedFrame, + int numberFrames) + { + auto item = item_get(); + if (!item) return; + snapshot("Change All Frame Properties"); + item->frames_change(frameChange, type, isFromSelectedFrame && frame_get() ? reference.frameIndex : 0, + isFromSelectedFrame ? numberFrames : -1); + change(change::FRAMES); + } + + void Document::frames_deserialize(const std::string& string) + { + if (auto item = item_get()) + { + snapshot("Paste Frame(s)"); + std::set indices{}; + std::string errorString{}; + auto start = reference.frameIndex + 1; + if (item->frames_deserialize(string, reference.itemType, start, indices, &errorString)) + change(change::FRAMES); + else + toasts.error(std::format("Failed to deserialize frame(s): {}", errorString)); + } + else + toasts.error(std::format("Failed to deserialize frame(s): select an item first!")); + } + anm2::Item* Document::item_get() { return anm2.item_get(reference); @@ -446,6 +523,13 @@ namespace anm2ed::document return anm2.animation_get(reference); } + void Document::animation_set(int index) + { + snapshot("Select Animation"); + reference = {index}; + change(change::ITEMS); + } + void Document::animation_add() { snapshot("Add Animation"); @@ -489,12 +573,21 @@ namespace anm2ed::document change(change::ANIMATIONS); } - void Document::animation_remove() + void Document::animations_remove() { snapshot("Remove Animation(s)"); - for (auto& i : animationMultiSelect | std::views::reverse) - anm2.animations.items.erase(anm2.animations.items.begin() + i); - animationMultiSelect.clear(); + + if (!animationMultiSelect.empty()) + { + for (auto& i : animationMultiSelect | std::views::reverse) + anm2.animations.items.erase(anm2.animations.items.begin() + i); + animationMultiSelect.clear(); + } + else if (hoveredAnimation > -1) + { + anm2.animations.items.erase(anm2.animations.items.begin() + hoveredAnimation); + hoveredAnimation = -1; + } change(change::ANIMATIONS); } @@ -508,7 +601,7 @@ namespace anm2ed::document void Document::animations_deserialize(const std::string& string) { - snapshot("Paste Animations"); + snapshot("Paste Animation(s)"); auto& multiSelect = animationMultiSelect; auto start = multiSelect.empty() ? anm2.animations.items.size() : *multiSelect.rbegin() + 1; std::set indices{}; @@ -522,9 +615,21 @@ namespace anm2ed::document toasts.error(std::format("Failed to deserialize animation(s): {}", errorString)); } + void Document::generate_animation_from_grid(ivec2 startPosition, ivec2 size, ivec2 pivot, int columns, int count, + int delay) + { + snapshot("Generate Animation from Grid"); + + anm2.generate_from_grid(reference, startPosition, size, pivot, columns, count, delay); + + if (auto animation = animation_get()) animation->frameNum = animation->length(); + + change(change::ALL); + } + void Document::animations_merge_quick() { - snapshot("Merge Animations"); + snapshot("Merge Animation(s)"); int merged{}; if (animationMultiSelect.size() > 1) merged = anm2.animations.merge(*animationMultiSelect.begin(), animationMultiSelect); diff --git a/src/document.h b/src/document.h index d7c92c2..46ec309 100644 --- a/src/document.h +++ b/src/document.h @@ -26,6 +26,7 @@ namespace anm2ed::document glm::vec2 previewPan{}; glm::vec2 editorPan{}; float editorZoom{200}; + int overlayIndex{}; anm2::Reference reference{}; @@ -34,6 +35,8 @@ namespace anm2ed::document imgui::MultiSelectStorage animationMultiSelect; imgui::MultiSelectStorage animationMergeMultiSelect; + anm2::Reference hoveredFrame{anm2::REFERENCE_DEFAULT}; + int referenceSpritesheet{-1}; int hoveredSpritesheet{-1}; std::set unusedSpritesheetIDs{}; @@ -58,17 +61,22 @@ namespace anm2ed::document uint64_t hash{}; uint64_t saveHash{}; + uint64_t autosaveHash{}; + double lastAutosaveTime{}; bool isOpen{true}; + bool isForceDirty{false}; Document(const std::string&, bool = false, std::string* = nullptr); bool save(const std::string& = {}, std::string* = nullptr); + bool autosave(const std::string&, std::string* = nullptr); void hash_set(); void clean(); void on_change(); void change(types::change::Type); bool is_dirty(); - std::string directory_get(); - std::string filename_get(); + bool is_autosave_dirty(); + std::filesystem::path directory_get(); + std::filesystem::path filename_get(); bool is_valid(); anm2::Frame* frame_get(); @@ -84,11 +92,15 @@ namespace anm2ed::document void frame_rotation_set(anm2::Frame*, float); void frame_delay_set(anm2::Frame*, int); void frame_tint_set(anm2::Frame*, glm::vec4); - void frame_offset_set(anm2::Frame*, glm::vec3); + void frame_color_offset_set(anm2::Frame*, glm::vec3); void frame_is_visible_set(anm2::Frame*, bool); void frame_is_interpolated_set(anm2::Frame*, bool); void frame_flip_x(anm2::Frame* frame); void frame_flip_y(anm2::Frame* frame); + void frame_shorten(); + void frame_extend(); + void frames_change(anm2::FrameChange&, types::frame_change::Type, bool, int = -1); + void frames_deserialize(const std::string&); anm2::Item* item_get(); void item_add(anm2::Type, int, std::string&, types::locale::Type, int); @@ -113,15 +125,18 @@ namespace anm2ed::document void events_deserialize(const std::string&, types::merge::Type); void animation_add(); + void animation_set(int); void animation_duplicate(); void animation_default(); - void animation_remove(); + void animations_remove(); void animations_move(std::vector&, int); void animations_merge(types::merge::Type, bool); void animations_merge_quick(); anm2::Animation* animation_get(); void animations_deserialize(const std::string& string); + void generate_animation_from_grid(glm::ivec2, glm::ivec2, glm::ivec2, int, int, int); + void snapshot(const std::string& message); void undo(); void redo(); diff --git a/src/documents.cpp b/src/documents.cpp index ebfa28a..5fae943 100644 --- a/src/documents.cpp +++ b/src/documents.cpp @@ -1,16 +1,19 @@ #include "documents.h" -#include +#include -#include "imgui.h" +#include "util.h" using namespace anm2ed::taskbar; using namespace anm2ed::manager; +using namespace anm2ed::settings; using namespace anm2ed::resources; +using namespace anm2ed::types; +using namespace anm2ed::util; namespace anm2ed::documents { - void Documents::update(Taskbar& taskbar, Manager& manager, Resources& resources) + void Documents::update(Taskbar& taskbar, Manager& manager, Settings& settings, Resources& resources, bool& isQuitting) { auto viewport = ImGui::GetMainViewport(); auto windowHeight = ImGui::GetFrameHeightWithSpacing(); @@ -19,6 +22,14 @@ namespace anm2ed::documents ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + taskbar.height)); ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, windowHeight)); + for (auto& document : manager.documents) + { + auto isDirty = document.is_dirty() && document.is_autosave_dirty(); + document.lastAutosaveTime += ImGui::GetIO().DeltaTime; + + if (isDirty && document.lastAutosaveTime > time::SECOND_S) manager.autosave(document); + } + if (ImGui::Begin("##Documents", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | @@ -29,14 +40,48 @@ namespace anm2ed::documents if (ImGui::BeginTabBar("Documents Bar", ImGuiTabBarFlags_Reorderable)) { - for (auto [i, document] : std::views::enumerate(manager.documents)) + auto documentsCount = (int)manager.documents.size(); + bool closeShortcut = imgui::shortcut(settings.shortcutClose, shortcut::GLOBAL) && !closePopup.is_open(); + int closeShortcutIndex = + closeShortcut && manager.selected >= 0 && manager.selected < documentsCount ? manager.selected : -1; + + std::vector closeIndices{}; + closeIndices.reserve(documentsCount); + + for (int i = 0; i < documentsCount; ++i) { - auto isDirty = document.is_dirty(); + auto& document = manager.documents[i]; + auto isDirty = document.is_dirty() || document.isForceDirty; + + if (!closePopup.is_open()) + { + if (isQuitting) + document.isOpen = false; + else if (i == closeShortcutIndex) + document.isOpen = false; + } + + if (!closePopup.is_open() && !document.isOpen) + { + if (isDirty) + { + closePopup.open(); + closeDocumentIndex = i; + document.isOpen = true; + } + else + { + closeIndices.push_back(i); + continue; + } + } + auto isRequested = i == manager.pendingSelected; auto font = isDirty ? font::ITALICS : font::REGULAR; - auto string = isDirty ? std::format("[Not Saved] {}", document.filename_get()) : document.filename_get(); + auto string = isDirty ? std::format("[Not Saved] {}", document.filename_get().string()) + : document.filename_get().string(); auto label = std::format("{}###Document{}", string, i); @@ -46,24 +91,17 @@ namespace anm2ed::documents ImGui::PushFont(resources.fonts[font].get(), font::SIZE); if (ImGui::BeginTabItem(label.c_str(), &document.isOpen, flags)) { - manager.selected = i; + manager.set(i); if (isRequested) manager.pendingSelected = -1; ImGui::EndTabItem(); } ImGui::PopFont(); + } - if (!document.isOpen) - { - if (isDirty) - { - isCloseDocument = true; - isOpenCloseDocumentPopup = true; - closeDocumentIndex = i; - document.isOpen = true; - } - else - manager.close(i); - } + for (auto it = closeIndices.rbegin(); it != closeIndices.rend(); ++it) + { + if (closePopup.is_open() && closeDocumentIndex > *it) --closeDocumentIndex; + manager.close(*it); } ImGui::EndTabBar(); @@ -71,21 +109,21 @@ namespace anm2ed::documents closePopup.trigger(); - if (isCloseDocument) + if (ImGui::BeginPopupModal(closePopup.label, &closePopup.isOpen, ImGuiWindowFlags_NoResize)) { - if (ImGui::BeginPopupModal(closePopup.label, &closePopup.isOpen, ImGuiWindowFlags_NoResize)) + if (closeDocumentIndex >= 0 && closeDocumentIndex < (int)manager.documents.size()) { - auto closeDocument = manager.get(closeDocumentIndex); + auto& closeDocument = manager.documents[closeDocumentIndex]; ImGui::TextUnformatted(std::format("The document \"{}\" has been modified.\nDo you want to save it?", - closeDocument->filename_get()) + closeDocument.filename_get().string()) .c_str()); auto widgetSize = imgui::widget_size_with_row_get(3); auto close = [&]() { - closeDocumentIndex = 0; + closeDocumentIndex = -1; closePopup.close(); }; @@ -106,10 +144,19 @@ namespace anm2ed::documents ImGui::SameLine(); - if (ImGui::Button("Cancel", widgetSize)) close(); - - ImGui::EndPopup(); + if (ImGui::Button("Cancel", widgetSize)) + { + isQuitting = false; + close(); + } } + else + { + closeDocumentIndex = -1; + closePopup.close(); + } + + ImGui::EndPopup(); } } diff --git a/src/documents.h b/src/documents.h index 4aa184a..80050cc 100644 --- a/src/documents.h +++ b/src/documents.h @@ -3,20 +3,19 @@ #include "imgui.h" #include "manager.h" #include "resources.h" +#include "settings.h" #include "taskbar.h" namespace anm2ed::documents { class Documents { - bool isCloseDocument{}; - bool isOpenCloseDocumentPopup{}; - int closeDocumentIndex{}; + int closeDocumentIndex{-1}; imgui::PopupHelper closePopup{imgui::PopupHelper("Close Document", imgui::POPUP_TO_CONTENT)}; public: float height{}; - void update(taskbar::Taskbar&, manager::Manager&, resources::Resources&); + void update(taskbar::Taskbar&, manager::Manager&, settings::Settings&, resources::Resources&, bool&); }; } diff --git a/src/events.cpp b/src/events.cpp index 46def77..cc8a417 100644 --- a/src/events.cpp +++ b/src/events.cpp @@ -18,6 +18,8 @@ namespace anm2ed::events auto& hovered = document.hoveredEvent; auto& multiSelect = document.eventMultiSelect; + hovered = -1; + if (ImGui::Begin("Events", &settings.windowIsEvents)) { auto childSize = imgui::size_without_footer_get(); diff --git a/src/filesystem.cpp b/src/filesystem.cpp index 057fa95..c62dcaa 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -6,6 +6,11 @@ namespace anm2ed::filesystem { + bool directories_create(const std::string& path) + { + return std::filesystem::create_directories(path); + } + std::string path_preferences_get() { char* preferencesPath = SDL_GetPrefPath("", "anm2ed"); diff --git a/src/filesystem.h b/src/filesystem.h index 0959d78..2c2db96 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -8,6 +8,7 @@ namespace anm2ed::filesystem std::string path_preferences_get(); bool path_is_exist(const std::string&); bool path_is_extension(const std::string&, const std::string&); + bool directories_create(const std::string&); class WorkingDirectory { diff --git a/src/frame_properties.cpp b/src/frame_properties.cpp index 2ab5320..7a086dc 100644 --- a/src/frame_properties.cpp +++ b/src/frame_properties.cpp @@ -91,8 +91,8 @@ namespace anm2ed::frame_properties document.frame_tint_set(frame, useFrame.tint); ImGui::SetItemTooltip("%s", "Change the tint of the frame."); - if (ImGui::ColorEdit3("Color Offset", frame ? value_ptr(useFrame.offset) : &dummy_value())) - document.frame_offset_set(frame, useFrame.offset); + if (ImGui::ColorEdit3("Color Offset", frame ? value_ptr(useFrame.colorOffset) : &dummy_value())) + document.frame_color_offset_set(frame, useFrame.colorOffset); ImGui::SetItemTooltip("%s", "Change the color added onto the frame."); if (ImGui::Checkbox("Visible", frame ? &useFrame.isVisible : &dummy_value())) diff --git a/src/icon.h b/src/icon.h index 7af6181..50ab178 100644 --- a/src/icon.h +++ b/src/icon.h @@ -55,6 +55,14 @@ namespace icon constexpr auto HIDE_UNUSED_DATA = R"( +)"; + + constexpr auto SHOW_LAYERS_DATA = R"( + +)"; + + constexpr auto HIDE_LAYERS_DATA = R"( + )"; constexpr auto SHOW_RECT_DATA = R"( @@ -156,6 +164,8 @@ namespace icon X(HIDE_RECT, HIDE_RECT_DATA, SIZE_NORMAL) \ X(SHOW_UNUSED, SHOW_UNUSED_DATA, SIZE_NORMAL) \ X(HIDE_UNUSED, HIDE_UNUSED_DATA, SIZE_NORMAL) \ + X(SHOW_LAYERS, SHOW_LAYERS_DATA, SIZE_NORMAL) \ + X(HIDE_LAYERS, HIDE_LAYERS_DATA, SIZE_NORMAL) \ X(PAN, PAN_DATA, SIZE_NORMAL) \ X(MOVE, MOVE_DATA, SIZE_NORMAL) \ X(ROTATE, ROTATE_DATA, SIZE_NORMAL) \ diff --git a/src/imgui.cpp b/src/imgui.cpp index 1224aad..d5a1713 100644 --- a/src/imgui.cpp +++ b/src/imgui.cpp @@ -280,6 +280,11 @@ namespace anm2ed::imgui isJustOpened = true; } + bool PopupHelper::is_open() + { + return isOpen; + } + void PopupHelper::trigger() { if (isTriggered) ImGui::OpenPopup(label); diff --git a/src/imgui.h b/src/imgui.h index 2deec12..7e032ec 100644 --- a/src/imgui.h +++ b/src/imgui.h @@ -174,6 +174,7 @@ namespace anm2ed::imgui float percent{}; PopupHelper(const char*, float = POPUP_NORMAL, bool = false); + bool is_open(); void open(); void trigger(); void end(); diff --git a/src/layers.cpp b/src/layers.cpp index 69b1546..e7ae3a3 100644 --- a/src/layers.cpp +++ b/src/layers.cpp @@ -21,6 +21,8 @@ namespace anm2ed::layers auto& multiSelect = document.layersMultiSelect; auto& propertiesPopup = manager.layerPropertiesPopup; + hovered = -1; + if (ImGui::Begin("Layers", &settings.windowIsLayers)) { auto childSize = imgui::size_without_footer_get(); diff --git a/src/loader.cpp b/src/loader.cpp index 034c126..bcb82d5 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -73,7 +73,7 @@ namespace anm2ed::loader ImGuiIO& io = ImGui::GetIO(); io.IniFilename = nullptr; - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; io.ConfigWindowsMoveFromTitleBarOnly = true; ImGui::LoadIniSettingsFromDisk(settings_path().c_str()); diff --git a/src/manager.cpp b/src/manager.cpp index a839622..7be966d 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -1,33 +1,73 @@ #include "manager.h" -#include "toast.h" +#include +#include "filesystem.h" +#include "log.h" +#include "toast.h" #include "util.h" +using namespace anm2ed::log; using namespace anm2ed::toast; using namespace anm2ed::types; using namespace anm2ed::util; namespace anm2ed::manager { + constexpr std::size_t RECENT_LIMIT = 10; + + std::filesystem::path Manager::recent_files_path_get() + { + return filesystem::path_preferences_get() + "recent.txt"; + } + + std::filesystem::path Manager::autosave_path_get() + { + return filesystem::path_preferences_get() + "autosave.txt"; + } + + std::filesystem::path Manager::autosave_directory_get() + { + return filesystem::path_preferences_get() + "autosave"; + } + + Manager::Manager() + { + recent_files_load(); + autosave_files_load(); + } + Document* Manager::get(int index) { return vector::find(documents, index > -1 ? index : selected); } - void Manager::open(const std::string& path, bool isNew) + void Manager::open(const std::string& path, bool isNew, bool isRecent) { std::string errorString{}; - Document document = Document(path, isNew, &errorString); - if (document.is_valid()) + documents.emplace_back(path, isNew, &errorString); + + auto& document = documents.back(); + if (!document.is_valid()) { - documents.emplace_back(std::move(document)); - selected = documents.size() - 1; - pendingSelected = selected; - toasts.info(std::format("Initialized document: {}", path)); + documents.pop_back(); + toasts.error(std::format("Failed to open document: {} ({})", path, errorString)); + return; } - else - toasts.error(std::format("Failed to initialize document: {} ({})", path, errorString)); + + if (isRecent) + { + recentFiles.erase(std::remove(recentFiles.begin(), recentFiles.end(), path), recentFiles.end()); + recentFiles.insert(recentFiles.begin(), path); + + if (recentFiles.size() > RECENT_LIMIT) recentFiles.resize(RECENT_LIMIT); + + recent_files_write(); + } + + selected = (int)documents.size() - 1; + pendingSelected = selected; + toasts.info(std::format("Opened document: {}", path)); } void Manager::new_(const std::string& path) @@ -50,9 +90,53 @@ namespace anm2ed::manager save(selected, path); } + void Manager::autosave(Document& document) + { + auto filename = "." + document.filename_get().string() + ".autosave"; + auto path = document.directory_get() / filename; + std::string errorString{}; + document.autosave(path, &errorString); + + autosaveFiles.erase(std::remove(autosaveFiles.begin(), autosaveFiles.end(), path), autosaveFiles.end()); + autosaveFiles.insert(autosaveFiles.begin(), path); + + autosave_files_write(); + } + void Manager::close(int index) { + if (index < 0 || index >= (int)documents.size()) return; + documents.erase(documents.begin() + index); + + if (documents.empty()) + { + selected = -1; + pendingSelected = -1; + return; + } + + if (selected >= index) selected = std::max(0, selected - 1); + + selected = std::clamp(selected, 0, (int)documents.size() - 1); + pendingSelected = selected; + + if (selected >= 0 && selected < (int)documents.size()) documents[selected].change(change::ALL); + } + + void Manager::set(int index) + { + if (documents.empty()) + { + selected = -1; + pendingSelected = -1; + return; + } + + index = std::clamp(index, 0, (int)documents.size() - 1); + selected = index; + + if (auto document = get()) document->change(change::ALL); } void Manager::layer_properties_open(int id) @@ -117,4 +201,119 @@ namespace anm2ed::manager nullPropertiesPopup.close(); } + void Manager::recent_files_load() + { + auto path = recent_files_path_get(); + + std::ifstream file(path); + if (!file) + { + logger.warning(std::format("Could not load recent files from: {}. Skipping...", path.string())); + return; + } + + logger.info(std::format("Loading recent files from: {}", path.string())); + + std::string line{}; + + while (std::getline(file, line)) + { + if (line.empty()) continue; + if (std::find(recentFiles.begin(), recentFiles.end(), line) != recentFiles.end()) continue; + recentFiles.emplace_back(line); + } + } + + void Manager::recent_files_write() + { + auto path = recent_files_path_get(); + + std::ofstream file; + file.open(path, std::ofstream::out | std::ofstream::trunc); + + if (!file.is_open()) + { + logger.warning(std::format("Could not write recent files to: {}. Skipping...", path.string())); + return; + } + + for (auto& path : recentFiles) + file << path.string() << '\n'; + } + + void Manager::recent_files_clear() + { + recentFiles.clear(); + recent_files_write(); + } + + void Manager::autosave_files_open() + { + for (auto& path : autosaveFiles) + { + auto fileName = path.filename().string(); + if (!fileName.empty() && fileName.front() == '.') fileName.erase(fileName.begin()); + + auto restorePath = path.parent_path() / fileName; + restorePath.replace_extension(""); + open(path.string(), false, false); + + if (auto document = get()) + { + document->isForceDirty = true; + document->path = restorePath; + document->change(change::ALL); + } + } + + autosave_files_clear(); + } + + void Manager::autosave_files_load() + { + auto path = autosave_path_get(); + + std::ifstream file(path); + if (!file) + { + logger.warning(std::format("Could not load autosave files from: {}. Skipping...", path.string())); + return; + } + + logger.info(std::format("Loading autosave files from: {}", path.string())); + + std::string line{}; + + while (std::getline(file, line)) + { + if (line.empty()) continue; + if (std::find(autosaveFiles.begin(), autosaveFiles.end(), line) != autosaveFiles.end()) continue; + autosaveFiles.emplace_back(line); + } + } + + void Manager::autosave_files_write() + { + std::ofstream autosaveWriteFile; + autosaveWriteFile.open(autosave_path_get(), std::ofstream::out | std::ofstream::trunc); + + for (auto& path : autosaveFiles) + autosaveWriteFile << path.string() << "\n"; + + autosaveWriteFile.close(); + } + + void Manager::autosave_files_clear() + { + for (auto& path : autosaveFiles) + std::filesystem::remove(path); + + autosaveFiles.clear(); + autosave_files_write(); + } + + Manager::~Manager() + { + autosave_files_clear(); + } } diff --git a/src/manager.h b/src/manager.h index 1d46381..4a4417c 100644 --- a/src/manager.h +++ b/src/manager.h @@ -9,12 +9,20 @@ using namespace anm2ed::document; namespace anm2ed::manager { + constexpr auto FILE_LABEL_FORMAT = "{} [{}]"; + class Manager { + std::filesystem::path recent_files_path_get(); + std::filesystem::path autosave_path_get(); + public: std::vector documents{}; - int selected{}; - int pendingSelected{}; + std::vector recentFiles{}; + std::vector autosaveFiles{}; + + int selected{-1}; + int pendingSelected{-1}; anm2::Layer editLayer{}; imgui::PopupHelper layerPropertiesPopup{imgui::PopupHelper("Layer Properties", imgui::POPUP_SMALL, true)}; @@ -22,11 +30,16 @@ namespace anm2ed::manager anm2::Null editNull{}; imgui::PopupHelper nullPropertiesPopup{imgui::PopupHelper("Null Properties", imgui::POPUP_SMALL, true)}; + Manager(); + ~Manager(); + Document* get(int = -1); - void open(const std::string&, bool = false); + void open(const std::string&, bool = false, bool = true); void new_(const std::string&); void save(int, const std::string& = {}); void save(const std::string& = {}); + void autosave(Document&); + void set(int); void close(int); void layer_properties_open(int = -1); void layer_properties_trigger(); @@ -36,5 +49,16 @@ namespace anm2ed::manager void null_properties_trigger(); void null_properties_end(); void null_properties_close(); + + void recent_files_load(); + void recent_files_write(); + void recent_files_clear(); + + void autosave_files_load(); + void autosave_files_open(); + void autosave_files_write(); + void autosave_files_clear(); + + std::filesystem::path autosave_directory_get(); }; } diff --git a/src/nulls.cpp b/src/nulls.cpp index f40dd9e..42879e1 100644 --- a/src/nulls.cpp +++ b/src/nulls.cpp @@ -20,6 +20,8 @@ namespace anm2ed::nulls auto& multiSelect = document.nullMultiSelect; auto& propertiesPopup = manager.nullPropertiesPopup; + hovered = -1; + if (ImGui::Begin("Nulls", &settings.windowIsNulls)) { auto childSize = imgui::size_without_footer_get(); diff --git a/src/settings.h b/src/settings.h index 535c27a..9f9aa3d 100644 --- a/src/settings.h +++ b/src/settings.h @@ -44,6 +44,9 @@ namespace anm2ed::settings X(IS_VSYNC, isVsync, "Vsync", BOOL, true) \ X(DISPLAY_SCALE, displayScale, "Display Scale", FLOAT, 1.0f) \ \ + X(FILE_IS_AUTOSAVE, fileIsAutosave, "Autosave", BOOL, true) \ + X(FILE_AUTOSAVE_TIME, fileAutosaveTime, "Autosave Time", INT, 1) \ + \ X(VIEW_ZOOM_STEP, viewZoomStep, "Zoom Step", FLOAT, 50.0f) \ \ X(PLAYBACK_IS_LOOP, playbackIsLoop, "Loop", BOOL, true) \ @@ -60,7 +63,6 @@ namespace anm2ed::settings X(CHANGE_IS_COLOR_OFFSET, changeIsColorOffset, "##Is Color Offset", BOOL, false) \ X(CHANGE_IS_VISIBLE_SET, changeIsVisibleSet, "##Is Visible", BOOL, false) \ X(CHANGE_IS_INTERPOLATED_SET, changeIsInterpolatedSet, "##Is Interpolated", BOOL, false) \ - X(CHANGE_IS_FROM_SELECTED_FRAME, changeIsFromSelectedFrame, "From Selected Frame", BOOL, false) \ X(CHANGE_CROP, changeCrop, "Crop", VEC2, {}) \ X(CHANGE_SIZE, changeSize, "Size", VEC2, {}) \ X(CHANGE_POSITION, changePosition, "Position", VEC2, {}) \ @@ -73,6 +75,7 @@ namespace anm2ed::settings X(CHANGE_IS_VISIBLE, changeIsVisible, "Visible", BOOL, false) \ X(CHANGE_IS_INTERPOLATED, changeIsInterpolated, "Interpolated", BOOL, false) \ X(CHANGE_NUMBER_FRAMES, changeNumberFrames, "Frame Count", INT, 1) \ + X(CHANGE_IS_FROM_SELECTED_FRAME, changeIsFromSelectedFrame, "From Selected Frame", BOOL, false) \ \ X(SCALE_VALUE, scaleValue, "Scale", FLOAT, 1.0f) \ \ @@ -80,7 +83,6 @@ namespace anm2ed::settings X(PREVIEW_IS_GRID, previewIsGrid, "Grid", BOOL, true) \ X(PREVIEW_IS_ROOT_TRANSFORM, previewIsRootTransform, "Root Transform", BOOL, true) \ X(PREVIEW_IS_PIVOTS, previewIsPivots, "Pivots", BOOL, false) \ - X(PREVIEW_IS_ICONS, previewIsIcons, "Icons", BOOL, true) \ X(PREVIEW_IS_BORDER, previewIsBorder, "Border", BOOL, false) \ X(PREVIEW_IS_ALT_ICONS, previewIsAltIcons, "Alt Icons", BOOL, false) \ X(PREVIEW_OVERLAY_TRANSPARENCY, previewOverlayTransparency, "Alpha", FLOAT, 255) \ @@ -101,6 +103,7 @@ namespace anm2ed::settings X(GENERATE_COLUMNS, generateColumns, "Columns", INT, 4) \ X(GENERATE_COUNT, generateCount, "Count", INT, 16) \ X(GENERATE_DELAY, generateDelay, "Delay", INT, 1) \ + X(GENERATE_ZOOM, generateZoom, "Zoom", FLOAT, 100.0f) \ \ X(EDITOR_IS_GRID, editorIsGrid, "Grid", BOOL, true) \ X(EDITOR_IS_GRID_SNAP, editorIsGridSnap, "Snap", BOOL, true) \ @@ -123,6 +126,7 @@ namespace anm2ed::settings X(TIMELINE_ADD_ITEM_LOCALITY, timelineAddItemLocale, "Add Item Locale", INT, types::locale::GLOBAL) \ X(TIMELINE_ADD_ITEM_SOURCE, timelineAddItemSource, "Add Item Source", INT, types::source::NEW) \ X(TIMELINE_IS_SHOW_UNUSED, timelineIsShowUnused, "##Show Unused", BOOL, true) \ + X(TIMELINE_IS_ONLY_SHOW_LAYERS, timelineIsOnlyShowLayers, "##Only Show Layers", BOOL, true) \ \ X(ONIONSKIN_IS_ENABLED, onionskinIsEnabled, "Enabled", BOOL, false) \ X(ONIONSKIN_DRAW_ORDER, onionskinDrawOrder, "Draw Order", INT, 0) \ diff --git a/src/shader.h b/src/shader.h index be761fc..ab7e0f4 100644 --- a/src/shader.h +++ b/src/shader.h @@ -112,6 +112,79 @@ namespace anm2ed::shader } )"; + constexpr auto DASHED_VERTEX = R"( + #version 330 core + layout (location = 0) in vec2 i_position; + + out vec2 v_local; + + uniform mat4 u_transform; + + void main() + { + v_local = i_position; + gl_Position = u_transform * vec4(i_position, 0.0, 1.0); + } + )"; + + constexpr auto DASHED_FRAGMENT = R"( + #version 330 core + in vec2 v_local; + + uniform vec4 u_color; + uniform vec2 u_axis_x; + uniform vec2 u_axis_y; + uniform float u_dash_length; + uniform float u_dash_gap; + uniform float u_dash_offset; + + out vec4 o_fragColor; + + void main() + { + vec2 local = clamp(v_local, 0.0, 1.0); + + float lengthX = max(length(u_axis_x), 1e-4); + float lengthY = max(length(u_axis_y), 1e-4); + + float dash = max(u_dash_length, 1e-4); + float gap = max(u_dash_gap, 0.0); + float period = max(dash + gap, 1e-4); + + vec2 pixel = max(fwidth(v_local), vec2(1e-5)); + + float bottomMask = 1.0 - smoothstep(pixel.y, pixel.y * 2.0, local.y); + float topMask = 1.0 - smoothstep(pixel.y, pixel.y * 2.0, 1.0 - local.y); + float leftMask = 1.0 - smoothstep(pixel.x, pixel.x * 2.0, local.x); + float rightMask = 1.0 - smoothstep(pixel.x, pixel.x * 2.0, 1.0 - local.x); + + float perimeterOffset = u_dash_offset; + + float bottomPos = mod(perimeterOffset + local.x * lengthX, period); + if (bottomPos < 0.0) bottomPos += period; + float bottomDash = bottomMask * (bottomPos <= dash ? 1.0 : 0.0); + + float rightPos = mod(perimeterOffset + lengthX + local.y * lengthY, period); + if (rightPos < 0.0) rightPos += period; + float rightDash = rightMask * (rightPos <= dash ? 1.0 : 0.0); + + float topPos = mod(perimeterOffset + lengthX + lengthY + (1.0 - local.x) * lengthX, period); + if (topPos < 0.0) topPos += period; + float topDash = topMask * (topPos <= dash ? 1.0 : 0.0); + + float leftPos = mod(perimeterOffset + 2.0 * lengthX + lengthY + (1.0 - local.y) * lengthY, period); + if (leftPos < 0.0) leftPos += period; + float leftDash = leftMask * (leftPos <= dash ? 1.0 : 0.0); + + float alpha = max(max(bottomDash, topDash), max(leftDash, rightDash)); + + if (alpha <= 0.0) + discard; + + o_fragColor = vec4(u_color.rgb, u_color.a * alpha); + } + )"; + constexpr auto UNIFORM_AXIS = "u_axis"; constexpr auto UNIFORM_COLOR = "u_color"; constexpr auto UNIFORM_TRANSFORM = "u_transform"; @@ -123,18 +196,27 @@ namespace anm2ed::shader constexpr auto UNIFORM_MODEL = "u_model"; constexpr auto UNIFORM_RECT_SIZE = "u_rect_size"; constexpr auto UNIFORM_TEXTURE = "u_texture"; + constexpr auto UNIFORM_AXIS_X = "u_axis_x"; + constexpr auto UNIFORM_AXIS_Y = "u_axis_y"; + constexpr auto UNIFORM_DASH_LENGTH = "u_dash_length"; + constexpr auto UNIFORM_DASH_GAP = "u_dash_gap"; + constexpr auto UNIFORM_DASH_OFFSET = "u_dash_offset"; enum Type { LINE, + DASHED, TEXTURE, AXIS, GRID, COUNT }; - const Info SHADERS[COUNT] = { - {VERTEX, FRAGMENT}, {VERTEX, TEXTURE_FRAGMENT}, {AXIS_VERTEX, FRAGMENT}, {GRID_VERTEX, GRID_FRAGMENT}}; + const Info SHADERS[COUNT] = {{VERTEX, FRAGMENT}, + {DASHED_VERTEX, DASHED_FRAGMENT}, + {VERTEX, TEXTURE_FRAGMENT}, + {AXIS_VERTEX, FRAGMENT}, + {GRID_VERTEX, GRID_FRAGMENT}}; class Shader { diff --git a/src/spritesheet_editor.cpp b/src/spritesheet_editor.cpp index 24c90dc..ff10925 100644 --- a/src/spritesheet_editor.cpp +++ b/src/spritesheet_editor.cpp @@ -37,7 +37,7 @@ namespace anm2ed::spritesheet_editor auto& tool = settings.tool; auto& shaderGrid = resources.shaders[shader::GRID]; auto& shaderTexture = resources.shaders[shader::TEXTURE]; - auto& lineShader = resources.shaders[shader::LINE]; + auto& dashedShader = resources.shaders[shader::DASHED]; if (ImGui::Begin("Spritesheet Editor", &settings.windowIsSpritesheetEditor)) { @@ -96,20 +96,22 @@ namespace anm2ed::spritesheet_editor auto frame = document.frame_get(); - if (spritesheet) + if (spritesheet && spritesheet->texture.is_valid()) { auto& texture = spritesheet->texture; auto transform = transform_get(zoom, pan); - auto spritesheetTransform = transform * math::quad_model_get(texture.size); + auto spritesheetModel = math::quad_model_get(texture.size); + auto spritesheetTransform = transform * spritesheetModel; texture_render(shaderTexture, texture.id, spritesheetTransform); - if (isBorder) rect_render(lineShader, spritesheetTransform); + if (isBorder) rect_render(dashedShader, spritesheetTransform, spritesheetModel); if (frame && reference.itemID > -1 && anm2.content.layers.at(reference.itemID).spritesheetID == referenceSpritesheet) { - auto cropTransform = transform * math::quad_model_get(frame->size, frame->crop); - rect_render(lineShader, cropTransform, color::RED); + auto cropModel = math::quad_model_get(frame->size, frame->crop); + auto cropTransform = transform * cropModel; + rect_render(dashedShader, cropTransform, cropModel, color::RED); auto pivotTransform = transform * math::quad_model_get(canvas::PIVOT_SIZE, frame->crop + frame->pivot, PIVOT_SIZE * 0.5f); diff --git a/src/spritesheets.cpp b/src/spritesheets.cpp index e2dbaca..ea8c78f 100644 --- a/src/spritesheets.cpp +++ b/src/spritesheets.cpp @@ -28,6 +28,8 @@ namespace anm2ed::spritesheets auto& hovered = document.hoveredSpritesheet; auto& reference = document.referenceSpritesheet; + hovered = -1; + if (ImGui::Begin("Spritesheets", &settings.windowIsSpritesheets)) { auto style = ImGui::GetStyle(); diff --git a/src/state.cpp b/src/state.cpp index ab209f4..fae94f2 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -61,7 +61,7 @@ namespace anm2ed::state break; } case SDL_EVENT_QUIT: - isQuit = true; + isQuitting = true; break; default: break; @@ -72,14 +72,15 @@ namespace anm2ed::state ImGui_ImplOpenGL3_NewFrame(); ImGui::NewFrame(); - taskbar.update(manager, settings, dialog, isQuit); + taskbar.update(manager, settings, resources, dialog, isQuitting); + documents.update(taskbar, manager, settings, resources, isQuitting); dockspace.update(taskbar, documents, manager, settings, resources, dialog, clipboard); toasts.update(); - documents.update(taskbar, manager, resources); - ImGui::GetStyle().FontScaleMain = settings.displayScale; SDL_GetWindowSize(window, &settings.windowSize.x, &settings.windowSize.y); + + if (isQuitting && manager.documents.empty()) isQuit = true; } void State::render(SDL_Window*& window, Settings& settings) diff --git a/src/state.h b/src/state.h index 4ee9adc..6f04633 100644 --- a/src/state.h +++ b/src/state.h @@ -14,9 +14,10 @@ namespace anm2ed::state public: bool isQuit{}; - dialog::Dialog dialog; - resources::Resources resources; + bool isQuitting{}; manager::Manager manager; + resources::Resources resources; + dialog::Dialog dialog; clipboard::Clipboard clipboard; taskbar::Taskbar taskbar; diff --git a/src/taskbar.cpp b/src/taskbar.cpp index cec33ac..04da3b4 100644 --- a/src/taskbar.cpp +++ b/src/taskbar.cpp @@ -4,18 +4,25 @@ #include #include "imgui.h" +#include "math.h" -using namespace anm2ed::settings; +using namespace anm2ed::canvas; using namespace anm2ed::dialog; using namespace anm2ed::manager; +using namespace anm2ed::resources; +using namespace anm2ed::settings; using namespace anm2ed::types; +using namespace glm; namespace anm2ed::taskbar { - void Taskbar::update(Manager& manager, Settings& settings, Dialog& dialog, bool& isQuit) + Taskbar::Taskbar() : generate(vec2()) + { + } + + void Taskbar::update(Manager& manager, Settings& settings, Resources& resources, Dialog& dialog, bool& isQuitting) { auto document = manager.get(); - auto animation = document ? document->animation_get() : nullptr; if (ImGui::BeginMainMenuBar()) { @@ -27,6 +34,32 @@ namespace anm2ed::taskbar if (ImGui::MenuItem("Open", settings.shortcutOpen.c_str())) dialog.anm2_open(); + if (manager.recentFiles.empty()) + { + ImGui::BeginDisabled(); + ImGui::MenuItem("Open Recent"); + ImGui::EndDisabled(); + } + else + { + if (ImGui::BeginMenu("Open Recent")) + { + for (auto [i, file] : std::views::enumerate(manager.recentFiles)) + { + auto label = std::format(FILE_LABEL_FORMAT, file.filename().string(), file.string()); + + ImGui::PushID(i); + if (ImGui::MenuItem(label.c_str())) manager.open(file); + ImGui::PopID(); + } + + if (!manager.recentFiles.empty()) + if (ImGui::MenuItem("Clear List")) manager.recent_files_clear(); + + ImGui::EndMenu(); + } + } + ImGui::BeginDisabled(!document); { if (ImGui::MenuItem("Save", settings.shortcutSave.c_str())) manager.save(); @@ -36,7 +69,7 @@ namespace anm2ed::taskbar ImGui::EndDisabled(); ImGui::Separator(); - if (ImGui::MenuItem("Exit", settings.shortcutExit.c_str())) isQuit = true; + if (ImGui::MenuItem("Exit", settings.shortcutExit.c_str())) isQuitting = true; ImGui::EndMenu(); } if (dialog.is_selected_file(dialog::ANM2_NEW)) @@ -59,11 +92,10 @@ namespace anm2ed::taskbar if (ImGui::BeginMenu("Wizard")) { - ImGui::BeginDisabled(!animation); - { - ImGui::MenuItem("Generate Animation From Grid"); - ImGui::MenuItem("Change All Frame Properties"); - } + auto item = document ? document->item_get() : nullptr; + ImGui::BeginDisabled(!item || document->reference.itemType != anm2::LAYER); + if (ImGui::MenuItem("Generate Animation From Grid")) generatePopup.open(); + if (ImGui::MenuItem("Change All Frame Properties")) changePopup.open(); ImGui::EndDisabled(); ImGui::EndMenu(); } @@ -107,6 +139,264 @@ namespace anm2ed::taskbar ImGui::EndMainMenuBar(); } + generatePopup.trigger(); + + if (ImGui::BeginPopupModal(generatePopup.label, &generatePopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto& startPosition = settings.generateStartPosition; + auto& size = settings.generateSize; + auto& pivot = settings.generatePivot; + auto& rows = settings.generateRows; + auto& columns = settings.generateColumns; + auto& count = settings.generateCount; + auto& delay = settings.generateDelay; + auto& zoom = settings.generateZoom; + auto& zoomStep = settings.viewZoomStep; + + auto childSize = ImVec2(imgui::row_widget_width_get(2), imgui::size_without_footer_get().y); + + if (ImGui::BeginChild("##Options Child", childSize, ImGuiChildFlags_Borders)) + { + ImGui::InputInt2("Start Position", value_ptr(startPosition)); + ImGui::InputInt2("Frame Size", value_ptr(size)); + ImGui::InputInt2("Pivot", value_ptr(pivot)); + ImGui::InputInt("Rows", &rows, step::NORMAL, step::FAST); + ImGui::InputInt("Columns", &columns, step::NORMAL, step::FAST); + + ImGui::InputInt("Count", &count, step::NORMAL, step::FAST); + count = glm::min(count, rows * columns); + + ImGui::InputInt("Delay", &delay, step::NORMAL, step::FAST); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##Preview Child", childSize, ImGuiChildFlags_Borders)) + { + auto& backgroundColor = settings.previewBackgroundColor; + auto& time = generateTime; + auto& shaderTexture = resources.shaders[shader::TEXTURE]; + + auto previewSize = ImVec2(ImGui::GetContentRegionAvail().x, imgui::size_without_footer_get(2).y); + + generate.size_set(to_vec2(previewSize)); + generate.bind(); + generate.viewport_set(); + generate.clear(backgroundColor); + + if (document && document->reference.itemType == anm2::LAYER) + { + auto& texture = document->anm2.content + .spritesheets[document->anm2.content.layers[document->reference.itemID].spritesheetID] + .texture; + + auto index = std::clamp((int)(time * count), 0, count); + auto row = index / columns; + auto column = index % columns; + auto crop = startPosition + ivec2(size.x * column, size.y * row); + auto uvMin = (vec2(crop) + vec2(0.5f)) / vec2(texture.size); + auto uvMax = (vec2(crop) + vec2(size) - vec2(0.5f)) / vec2(texture.size); + + mat4 transform = generate.transform_get(zoom) * math::quad_model_get(size, {}, pivot); + + generate.texture_render(shaderTexture, texture.id, transform, vec4(1.0f), {}, + math::uv_vertices_get(uvMin, uvMax).data()); + } + generate.unbind(); + + ImGui::Image(generate.texture, previewSize); + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::SliderFloat("##Time", &time, 0.0f, 1.0f, ""); + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::InputFloat("##Zoom", &zoom, zoomStep, zoomStep, "%.0f%%"); + zoom = glm::clamp(zoom, canvas::ZOOM_MIN, canvas::ZOOM_MAX); + } + + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + if (ImGui::Button("Generate", widgetSize)) + { + document->generate_animation_from_grid(startPosition, size, pivot, columns, count, delay); + generatePopup.close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) generatePopup.close(); + + ImGui::EndPopup(); + } + + changePopup.trigger(); + + if (ImGui::BeginPopupModal(changePopup.label, &changePopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto& isCrop = settings.changeIsCrop; + auto& isSize = settings.changeIsSize; + auto& isPosition = settings.changeIsPosition; + auto& isPivot = settings.changeIsPivot; + auto& isScale = settings.changeIsScale; + auto& isRotation = settings.changeIsRotation; + auto& isDelay = settings.changeIsDelay; + auto& isTint = settings.changeIsTint; + auto& isColorOffset = settings.changeIsColorOffset; + auto& isVisibleSet = settings.changeIsVisibleSet; + auto& isInterpolatedSet = settings.changeIsInterpolatedSet; + auto& crop = settings.changeCrop; + auto& size = settings.changeSize; + auto& position = settings.changePosition; + auto& pivot = settings.changePivot; + auto& scale = settings.changeScale; + auto& rotation = settings.changeRotation; + auto& delay = settings.changeDelay; + auto& tint = settings.changeTint; + auto& colorOffset = settings.changeColorOffset; + auto& isVisible = settings.changeIsVisible; + auto& isInterpolated = settings.changeIsInterpolated; + + auto& isFromSelectedFrame = settings.changeIsFromSelectedFrame; + auto& numberFrames = settings.changeNumberFrames; + + auto propertiesSize = imgui::child_size_get(10); + + if (ImGui::BeginChild("##Properties", propertiesSize, ImGuiChildFlags_Borders)) + { + auto start = [&](const char* checkboxLabel, bool& isEnabled) + { + ImGui::Checkbox(checkboxLabel, &isEnabled); + ImGui::SameLine(); + ImGui::BeginDisabled(!isEnabled); + }; + auto end = [&]() { ImGui::EndDisabled(); }; + + auto bool_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, bool& value) + { + start(checkboxLabel, isEnabled); + ImGui::Checkbox(valueLabel, &value); + end(); + }; + + auto color3_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, vec3& value) + { + start(checkboxLabel, isEnabled); + ImGui::ColorEdit3(valueLabel, value_ptr(value)); + end(); + }; + + auto color4_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, vec4& value) + { + start(checkboxLabel, isEnabled); + ImGui::ColorEdit4(valueLabel, value_ptr(value)); + end(); + }; + + auto float2_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, vec2& value) + { + start(checkboxLabel, isEnabled); + ImGui::InputFloat2(valueLabel, value_ptr(value), math::vec2_format_get(value)); + end(); + }; + + auto float_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, float& value) + { + start(checkboxLabel, isEnabled); + ImGui::InputFloat(valueLabel, &value, step::NORMAL, step::FAST, math::float_format_get(value)); + end(); + }; + + auto int_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, int& value) + { + start(checkboxLabel, isEnabled); + ImGui::InputInt(valueLabel, &value, step::NORMAL, step::FAST); + end(); + }; + + float2_value("##Is Crop", "Crop", isCrop, crop); + float2_value("##Is Size", "Size", isSize, size); + float2_value("##Is Position", "Position", isPosition, position); + float2_value("##Is Pivot", "Pivot", isPivot, pivot); + float2_value("##Is Scale", "Scale", isScale, scale); + float_value("##Is Rotation", "Rotation", isRotation, rotation); + int_value("##Is Delay", "Delay", isDelay, delay); + color4_value("##Is Tint", "Tint", isTint, tint); + color3_value("##Is Color Offset", "Color Offset", isColorOffset, colorOffset); + bool_value("##Is Visible", "Visible", isVisibleSet, isVisible); + ImGui::SameLine(); + bool_value("##Is Interpolated", "Interpolated", isInterpolatedSet, isInterpolated); + } + ImGui::EndChild(); + + auto settingsSize = imgui::child_size_get(2); + + if (ImGui::BeginChild("##Settings", settingsSize, ImGuiChildFlags_Borders)) + { + ImGui::Checkbox("From Selected Frame", &isFromSelectedFrame); + ImGui::SetItemTooltip("The frames after the currently referenced frame will be changed with these values.\nIf" + "off, will use all frames."); + + ImGui::BeginDisabled(!isFromSelectedFrame); + ImGui::InputInt("Number of Frames", &numberFrames, step::NORMAL, step::FAST); + numberFrames = glm::clamp(numberFrames, anm2::FRAME_NUM_MIN, + (int)document->item_get()->frames.size() - document->reference.frameIndex); + ImGui::SetItemTooltip("Set the number of frames that will be changed."); + ImGui::EndDisabled(); + } + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(4); + + auto frame_change = [&](frame_change::Type type) + { + anm2::FrameChange frameChange; + frameChange.crop = isCrop ? std::make_optional(crop) : std::nullopt; + frameChange.size = isSize ? std::make_optional(size) : std::nullopt; + frameChange.position = isPosition ? std::make_optional(position) : std::nullopt; + frameChange.pivot = isPivot ? std::make_optional(pivot) : std::nullopt; + frameChange.scale = isScale ? std::make_optional(scale) : std::nullopt; + frameChange.rotation = isRotation ? std::make_optional(rotation) : std::nullopt; + frameChange.delay = isDelay ? std::make_optional(delay) : std::nullopt; + frameChange.tint = isTint ? std::make_optional(tint) : std::nullopt; + frameChange.colorOffset = isColorOffset ? std::make_optional(colorOffset) : std::nullopt; + frameChange.isVisible = isVisibleSet ? std::make_optional(isVisible) : std::nullopt; + frameChange.isInterpolated = isInterpolatedSet ? std::make_optional(isInterpolated) : std::nullopt; + + document->frames_change(frameChange, type, isFromSelectedFrame, numberFrames); + }; + + if (ImGui::Button("Add", widgetSize)) + { + frame_change(frame_change::ADD); + changePopup.close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Subtract", widgetSize)) + { + frame_change(frame_change::SUBTRACT); + changePopup.close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Adjust", widgetSize)) + { + frame_change(frame_change::ADJUST); + changePopup.close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) changePopup.close(); + + ImGui::EndPopup(); + } + configurePopup.trigger(); if (ImGui::BeginPopupModal(configurePopup.label, &configurePopup.isOpen, ImGuiWindowFlags_NoResize)) @@ -115,29 +405,33 @@ namespace anm2ed::taskbar if (ImGui::BeginTabBar("##Configure Tabs")) { - if (ImGui::BeginTabItem("View")) + if (ImGui::BeginTabItem("General")) { if (ImGui::BeginChild("##Tab Child", childSize, true)) { - ImGui::InputFloat("Zoom Step", &editSettings.viewZoomStep, 10.0f, 10.0f, "%.2f"); - ImGui::SetItemTooltip("%s", "When zooming in/out with mouse or shortcut, this value will be used."); - editSettings.viewZoomStep = glm::clamp(editSettings.viewZoomStep, 1.0f, 250.0f); - } - ImGui::EndChild(); - ImGui::EndTabItem(); - } + ImGui::SeparatorText("File"); + + ImGui::Checkbox("Autosaving", &editSettings.fileIsAutosave); + ImGui::SetItemTooltip("Enables autosaving of documents."); + + ImGui::BeginDisabled(!editSettings.fileIsAutosave); + ImGui::InputInt("Autosave Time (minutes", &editSettings.fileAutosaveTime, step::NORMAL, step::FAST); + editSettings.fileAutosaveTime = glm::clamp(editSettings.fileAutosaveTime, 0, 10); + ImGui::SetItemTooltip("If changed, will autosave documents using this interval."); + ImGui::EndDisabled(); + + ImGui::SeparatorText("View"); - if (ImGui::BeginTabItem("Video")) - { - if (ImGui::BeginChild("##Tab Child", childSize, true)) - { ImGui::InputFloat("Display Scale", &editSettings.displayScale, 0.25f, 0.25f, "%.2f"); - ImGui::SetItemTooltip("%s", "Change the scale of the display."); + ImGui::SetItemTooltip("Change the scale of the display."); editSettings.displayScale = glm::clamp(editSettings.displayScale, 0.5f, 2.0f); + ImGui::InputFloat("Zoom Step", &editSettings.viewZoomStep, 10.0f, 10.0f, "%.2f"); + ImGui::SetItemTooltip("When zooming in/out with mouse or shortcut, this value will be used."); + editSettings.viewZoomStep = glm::clamp(editSettings.viewZoomStep, 1.0f, 250.0f); + ImGui::Checkbox("Vsync", &editSettings.isVsync); - ImGui::SetItemTooltip("%s", - "Toggle vertical sync; synchronizes program update rate with monitor refresh rate."); + ImGui::SetItemTooltip("Toggle vertical sync; synchronizes program update rate with monitor refresh rate."); } ImGui::EndChild(); @@ -241,11 +535,10 @@ namespace anm2ed::taskbar ImGui::EndPopup(); } - if (ImGui::Shortcut(imgui::string_to_chord(settings.shortcutNew), ImGuiInputFlags_RouteGlobal)) dialog.anm2_new(); - if (ImGui::Shortcut(imgui::string_to_chord(settings.shortcutOpen), ImGuiInputFlags_RouteGlobal)) dialog.anm2_open(); - if (ImGui::Shortcut(imgui::string_to_chord(settings.shortcutSave), ImGuiInputFlags_RouteGlobal)) manager.save(); - if (ImGui::Shortcut(imgui::string_to_chord(settings.shortcutSaveAs), ImGuiInputFlags_RouteGlobal)) - dialog.anm2_save(); - if (ImGui::Shortcut(imgui::string_to_chord(settings.shortcutExit), ImGuiInputFlags_RouteGlobal)) isQuit = true; + if (imgui::shortcut(settings.shortcutNew, shortcut::GLOBAL)) dialog.anm2_new(); + if (imgui::shortcut(settings.shortcutOpen, shortcut::GLOBAL)) dialog.anm2_open(); + if (imgui::shortcut(settings.shortcutSave, shortcut::GLOBAL)) document->save(); + if (imgui::shortcut(settings.shortcutSaveAs, shortcut::GLOBAL)) dialog.anm2_save(); + if (imgui::shortcut(settings.shortcutExit, shortcut::GLOBAL)) isQuitting = true; } } diff --git a/src/taskbar.h b/src/taskbar.h index b013eab..9549ae2 100644 --- a/src/taskbar.h +++ b/src/taskbar.h @@ -1,22 +1,31 @@ #pragma once +#include "canvas.h" #include "dialog.h" #include "imgui.h" #include "manager.h" +#include "resources.h" #include "settings.h" namespace anm2ed::taskbar { class Taskbar { + canvas::Canvas generate; + float generateTime{}; + imgui::PopupHelper generatePopup{imgui::PopupHelper("Generate Animation from Grid")}; + imgui::PopupHelper changePopup{imgui::PopupHelper("Change All Frame Properties", imgui::POPUP_SMALL, true)}; + imgui::PopupHelper renderPopup{imgui::PopupHelper("Render Animation")}; imgui::PopupHelper configurePopup{imgui::PopupHelper("Configure")}; imgui::PopupHelper aboutPopup{imgui::PopupHelper("About")}; settings::Settings editSettings{}; int selectedShortcut{-1}; + bool isQuittingMode{}; public: float height{}; - void update(manager::Manager&, settings::Settings&, dialog::Dialog&, bool&); + Taskbar(); + void update(manager::Manager&, settings::Settings&, resources::Resources&, dialog::Dialog&, bool&); }; }; diff --git a/src/timeline.cpp b/src/timeline.cpp index e0e71f6..dfdfeb0 100644 --- a/src/timeline.cpp +++ b/src/timeline.cpp @@ -11,6 +11,7 @@ using namespace anm2ed::manager; using namespace anm2ed::resources; using namespace anm2ed::settings; using namespace anm2ed::playback; +using namespace anm2ed::clipboard; using namespace glm; namespace anm2ed::timeline @@ -50,14 +51,63 @@ namespace anm2ed::timeline - Press {} to extend the selected frame, by one frame. - Hold Alt while clicking a non-trigger frame to toggle interpolation.)"; + void Timeline::context_menu(Document& document, Settings& settings, Clipboard& clipboard) + { + auto& hoveredFrame = document.hoveredFrame; + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + + auto copy = [&]() + { + if (auto frame = document.anm2.frame_get(hoveredFrame)) clipboard.set(frame->to_string(hoveredFrame.itemType)); + }; + + auto cut = [&]() + { + if (auto frame = document.anm2.frame_get(hoveredFrame)) + { + if (auto item = document.anm2.item_get(hoveredFrame)) + { + clipboard.set(frame->to_string(hoveredFrame.itemType)); + document.frames_delete(item); + hoveredFrame = anm2::REFERENCE_DEFAULT; + } + } + }; + + auto paste = [&]() { document.frames_deserialize(clipboard.get()); }; + + if (imgui::shortcut(settings.shortcutCut, shortcut::FOCUSED)) cut(); + if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (imgui::shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::BeginDisabled(hoveredFrame == anm2::REFERENCE_DEFAULT); + if (ImGui::MenuItem("Cut", settings.shortcutCut.c_str())) cut(); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(clipboard.is_empty()); + if (ImGui::MenuItem("Paste")) paste(); + ImGui::EndDisabled(); + + ImGui::EndPopup(); + } + + ImGui::PopStyleVar(2); + } + void Timeline::item_child(Manager& manager, Document& document, anm2::Animation* animation, Settings& settings, - Resources& resources, anm2::Type type, int id, int& index) + Resources& resources, Clipboard& clipboard, anm2::Type type, int id, int& index) { auto& anm2 = document.anm2; auto& reference = document.reference; - auto item = animation ? animation->item_get(type, id) : nullptr; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; auto isVisible = item ? item->isVisible : false; + if (isOnlyShowLayers && type != anm2::LAYER) isVisible = false; auto isActive = reference.itemType == type && reference.itemID == id; std::string label = "##None"; icon::Type icon{}; @@ -129,7 +179,6 @@ namespace anm2ed::timeline ImGui::TextUnformatted(label.c_str()); anm2::Item* item = animation->item_get(type, id); - bool& isVisible = item->isVisible; ImGui::PushStyleColor(ImGuiCol_Button, ImVec4()); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4()); @@ -138,7 +187,7 @@ namespace anm2ed::timeline ImGui::SetCursorPos(ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); - int visibleIcon = isVisible ? icon::VISIBLE : icon::INVISIBLE; + int visibleIcon = item->isVisible ? icon::VISIBLE : icon::INVISIBLE; if (ImGui::ImageButton("##Visible Toggle", resources.icons[visibleIcon].id, imgui::icon_size_get())) document.item_visible_toggle(item); @@ -165,22 +214,32 @@ namespace anm2ed::timeline else { auto cursorPos = ImGui::GetCursorPos(); - auto& isShowUnused = settings.timelineIsShowUnused; - - ImGui::SetCursorPos(ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, - (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4()); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4()); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4()); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); + ImGui::SetCursorPos(ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + auto& isShowUnused = settings.timelineIsShowUnused; auto unusedIcon = isShowUnused ? icon::SHOW_UNUSED : icon::HIDE_UNUSED; if (ImGui::ImageButton("##Unused Toggle", resources.icons[unusedIcon].id, imgui::icon_size_get())) isShowUnused = !isShowUnused; ImGui::SetItemTooltip(isShowUnused ? "Unused layers/nulls are shown. Press to hide." : "Unused layers/nulls are hidden. Press to show."); + auto onlyShowLayersIcon = isOnlyShowLayers ? icon::SHOW_LAYERS : icon::HIDE_LAYERS; + ImGui::SetCursorPos( + ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + if (ImGui::ImageButton("##Layers Visibility Toggle", resources.icons[onlyShowLayersIcon].id, + imgui::icon_size_get())) + isOnlyShowLayers = !isOnlyShowLayers; + ImGui::SetItemTooltip(isOnlyShowLayers + ? "Only layers are visible. Press to toggle visibility for all items." + : "Non-layer items are visible. Press to toggle visiblity only for layers."); + ImGui::PopStyleVar(); ImGui::PopStyleColor(3); @@ -201,7 +260,7 @@ namespace anm2ed::timeline } void Timeline::items_child(Manager& manager, Document& document, anm2::Animation* animation, Settings& settings, - Resources& resources) + Resources& resources, Clipboard& clipboard) { auto& reference = document.reference; @@ -232,7 +291,7 @@ namespace anm2ed::timeline { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); - item_child(manager, document, animation, settings, resources, type, id, index); + item_child(manager, document, animation, settings, resources, clipboard, type, id, index); }; item_child_row(anm2::NONE); @@ -302,13 +361,16 @@ namespace anm2ed::timeline } void Timeline::frame_child(Document& document, anm2::Animation* animation, Settings& settings, Resources& resources, - anm2::Type type, int id, int& index, float width) + Clipboard& clipboard, anm2::Type type, int id, int& index, float width) { auto& anm2 = document.anm2; auto& playback = document.playback; auto& reference = document.reference; + auto& hoveredFrame = document.hoveredFrame; auto item = animation ? animation->item_get(type, id) : nullptr; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; auto isVisible = item ? item->isVisible : false; + if (isOnlyShowLayers && type != anm2::LAYER) isVisible = false; ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); @@ -489,6 +551,8 @@ namespace anm2ed::timeline reference = frameReference; reference.frameTime = frameTime; } + if (ImGui::IsItemHovered()) hoveredFrame = frameReference; + if (type != anm2::TRIGGER) ImGui::SameLine(); ImGui::PopStyleColor(3); @@ -502,6 +566,8 @@ namespace anm2ed::timeline ImGui::PopID(); } + + context_menu(document, settings, clipboard); } } ImGui::EndChild(); @@ -511,10 +577,12 @@ namespace anm2ed::timeline ImGui::PopID(); } - void Timeline::frames_child(Document& document, anm2::Animation* animation, Settings& settings, Resources& resources) + void Timeline::frames_child(Document& document, anm2::Animation* animation, Settings& settings, Resources& resources, + Clipboard& clipboard) { auto& anm2 = document.anm2; auto& playback = document.playback; + auto& hoveredFrame = document.hoveredFrame; auto itemsChildWidth = ImGui::GetTextLineHeightWithSpacing() * 15; @@ -571,11 +639,13 @@ namespace anm2ed::timeline { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); - frame_child(document, animation, settings, resources, type, id, index, childWidth); + frame_child(document, animation, settings, resources, clipboard, type, id, index, childWidth); }; frames_child_row(anm2::NONE); + //hoveredFrame = anm2::REFERENCE_DEFAULT; + if (animation) { ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f); @@ -622,6 +692,8 @@ namespace anm2ed::timeline pickerLineDrawList->PopClipRect(); ImGui::PopStyleVar(); + + context_menu(document, settings, clipboard); } ImGui::EndChild(); ImGui::PopStyleVar(); @@ -917,7 +989,7 @@ namespace anm2ed::timeline } } - void Timeline::update(Manager& manager, Settings& settings, Resources& resources) + void Timeline::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) { auto& document = *manager.get(); auto& playback = document.playback; @@ -931,8 +1003,8 @@ namespace anm2ed::timeline if (ImGui::Begin("Timeline", &settings.windowIsTimeline)) { isWindowHovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); - frames_child(document, animation, settings, resources); - items_child(manager, document, animation, settings, resources); + frames_child(document, animation, settings, resources, clipboard); + items_child(manager, document, animation, settings, resources, clipboard); } ImGui::PopStyleVar(); ImGui::End(); @@ -956,10 +1028,7 @@ namespace anm2ed::timeline } } - if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutShortenFrame))) - if (auto frame = anm2.frame_get(reference); frame) frame->shorten(); - - if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutExtendFrame))) - if (auto frame = anm2.frame_get(reference); frame) frame->extend(); + if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutShortenFrame))) document.frame_shorten(); + if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutExtendFrame))) document.frame_extend(); } } \ No newline at end of file diff --git a/src/timeline.h b/src/timeline.h index 5284ca7..9bb6f16 100644 --- a/src/timeline.h +++ b/src/timeline.h @@ -1,6 +1,7 @@ #pragma once #include "anm2.h" +#include "clipboard.h" #include "document.h" #include "manager.h" #include "resources.h" @@ -25,16 +26,19 @@ namespace anm2ed::timeline ImDrawList* pickerLineDrawList{}; ImGuiStyle style{}; + void context_menu(document::Document&, settings::Settings&, clipboard::Clipboard&); void item_child(manager::Manager&, Document&, anm2::Animation*, settings::Settings&, resources::Resources&, - anm2::Type, int, int&); - void items_child(manager::Manager&, Document&, anm2::Animation*, settings::Settings&, resources::Resources&); - void frame_child(document::Document&, anm2::Animation*, settings::Settings&, resources::Resources&, anm2::Type, int, - int&, float); - void frames_child(document::Document&, anm2::Animation*, settings::Settings&, resources::Resources&); + clipboard::Clipboard&, anm2::Type, int, int&); + void items_child(manager::Manager&, Document&, anm2::Animation*, settings::Settings&, resources::Resources&, + clipboard::Clipboard&); + void frame_child(document::Document&, anm2::Animation*, settings::Settings&, resources::Resources&, + clipboard::Clipboard&, anm2::Type, int, int&, float); + void frames_child(document::Document&, anm2::Animation*, settings::Settings&, resources::Resources&, + clipboard::Clipboard&); void popups(document::Document&, anm2::Animation*, settings::Settings&); public: - void update(manager::Manager&, settings::Settings&, resources::Resources&); + void update(manager::Manager&, settings::Settings&, resources::Resources&, clipboard::Clipboard&); }; } diff --git a/src/types.h b/src/types.h index 439d138..acc12b3 100644 --- a/src/types.h +++ b/src/types.h @@ -69,6 +69,16 @@ namespace anm2ed::types::merge }; } +namespace anm2ed::types::frame_change +{ + enum Type + { + ADD, + SUBTRACT, + ADJUST + }; +} + namespace anm2ed::types::color { using namespace glm; diff --git a/src/util.h b/src/util.h index ec99f47..b66ac09 100644 --- a/src/util.h +++ b/src/util.h @@ -10,6 +10,9 @@ namespace anm2ed::util::time { + constexpr auto SECOND_S = 1.0; + constexpr auto SECOND_M = 60.0; + std::string get(const char*); } @@ -95,4 +98,13 @@ namespace anm2ed::util::vector return moveIndices; } + + template bool in_bounds(std::vector& v, int& index) + { + return index >= 0 || index <= (int)v.size() - 1; + } + template void clamp_in_bounds(std::vector& v, int& index) + { + index = std::clamp(index, 0, (int)v.size() - 1); + } } diff --git a/src/welcome.cpp b/src/welcome.cpp new file mode 100644 index 0000000..2114906 --- /dev/null +++ b/src/welcome.cpp @@ -0,0 +1,106 @@ +#include "welcome.h" + +#include + +using namespace anm2ed::dialog; +using namespace anm2ed::taskbar; +using namespace anm2ed::documents; +using namespace anm2ed::resources; +using namespace anm2ed::manager; + +namespace anm2ed::welcome +{ + void Welcome::update(Manager& manager, Resources& resources, Dialog& dialog, Taskbar& taskbar, Documents& documents) + { + auto viewport = ImGui::GetMainViewport(); + auto windowHeight = viewport->Size.y - taskbar.height - documents.height; + + ImGui::SetNextWindowViewport(viewport->ID); + ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + taskbar.height + documents.height)); + ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, windowHeight)); + + if (ImGui::Begin("##Welcome", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoScrollWithMouse)) + { + + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE_LARGE); + ImGui::Text("Anm2Ed"); + ImGui::PopFont(); + + ImGui::Text( + "Select a recent file or an option below. You can also drag and drop files into the window to open them."); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + if (ImGui::Button("New", widgetSize)) dialog.anm2_new(); // handled in taskbar.cpp + + ImGui::SameLine(); + + if (ImGui::Button("Open", widgetSize)) dialog.anm2_open(); // handled in taskbar.cpp + + if (ImGui::BeginChild("##Recent Child", ImVec2(), ImGuiChildFlags_Borders)) + { + for (auto [i, file] : std::views::enumerate(manager.recentFiles)) + { + ImGui::PushID(i); + + auto label = std::format(FILE_LABEL_FORMAT, file.filename().string(), file.string()); + + if (ImGui::Selectable(label.c_str())) + { + manager.open(file); + ImGui::PopID(); + break; + } + + ImGui::PopID(); + } + } + ImGui::EndChild(); + } + ImGui::End(); + + if (!manager.autosaveFiles.empty() && !restorePopup.is_open()) restorePopup.open(); + + restorePopup.trigger(); + + if (ImGui::BeginPopupModal(restorePopup.label, &restorePopup.isOpen, ImGuiWindowFlags_NoResize)) + { + ImGui::Text("Autosaved files detected. Would you like to restore them?"); + + auto childSize = imgui::child_size_get(5); + + if (ImGui::BeginChild("##Autosave Documents", childSize, ImGuiChildFlags_Borders, + ImGuiWindowFlags_HorizontalScrollbar)) + { + for (auto& file : manager.autosaveFiles) + { + auto label = std::format(FILE_LABEL_FORMAT, file.filename().string(), file.string()); + ImGui::TextUnformatted(label.c_str()); + } + } + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + if (ImGui::Button("Yes", widgetSize)) + { + manager.autosave_files_open(); + restorePopup.close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("No", widgetSize)) + { + manager.autosave_files_clear(); + restorePopup.close(); + } + + ImGui::EndPopup(); + } + } + +} diff --git a/src/welcome.h b/src/welcome.h new file mode 100644 index 0000000..238470f --- /dev/null +++ b/src/welcome.h @@ -0,0 +1,16 @@ +#pragma once + +#include "documents.h" +#include "manager.h" +#include "taskbar.h" + +namespace anm2ed::welcome +{ + class Welcome + { + imgui::PopupHelper restorePopup{imgui::PopupHelper("Restore", imgui::POPUP_SMALL, true)}; + + public: + void update(manager::Manager&, resources::Resources&, dialog::Dialog&, taskbar::Taskbar&, documents::Documents&); + }; +}; \ No newline at end of file From 99b7d9f49d8d3d18c33a3a2eba601a0c55c3dd08 Mon Sep 17 00:00:00 2001 From: shweet Date: Sat, 1 Nov 2025 00:54:22 -0400 Subject: [PATCH 10/15] FFmpeg and sound support; refactor, etc. --- .gitmodules | 3 +++ external/SDL_mixer | 1 + src/anm2.cpp | 22 ++++++++++++++--- src/anm2.h | 5 +++- src/canvas.cpp | 34 +++++++++++++++++++++++++- src/canvas.h | 5 ++++ src/snapshots.cpp | 14 +++++++++++ src/spritesheet_editor.cpp | 22 ++++++++++++++--- src/texture.cpp | 49 +++++++++++++++++++++++++++++++++----- src/texture.h | 6 ++++- 10 files changed, 146 insertions(+), 15 deletions(-) create mode 160000 external/SDL_mixer diff --git a/.gitmodules b/.gitmodules index b1f95ec..39508a8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -14,3 +14,6 @@ [submodule "external/lunasvg"] path = external/lunasvg url = https://github.com/sammycage/lunasvg +[submodule "external/SDL_mixer"] + path = external/SDL_mixer + url = https://github.com/libsdl-org/SDL_mixer diff --git a/external/SDL_mixer b/external/SDL_mixer new file mode 160000 index 0000000..8c516fc --- /dev/null +++ b/external/SDL_mixer @@ -0,0 +1 @@ +Subproject commit 8c516fcd2eca48262188426fbe75365ba4326346 diff --git a/src/anm2.cpp b/src/anm2.cpp index 3ec5acf..f7e644b 100644 --- a/src/anm2.cpp +++ b/src/anm2.cpp @@ -1356,12 +1356,28 @@ namespace anm2ed::anm2 return unused; } + std::vector Anm2::event_names_get() + { + std::vector names{}; + for (auto& event : content.events | std::views::values) + names.push_back(event.name); + return names; + } + + std::vector Anm2::animation_names_get() + { + std::vector names{}; + for (auto& animation : animations.items) + names.push_back(animation.name); + return names; + } + std::vector Anm2::spritesheet_names_get() { - std::vector spritesheets{}; + std::vector names{}; for (auto& [id, spritesheet] : content.spritesheets) - spritesheets.push_back(std::format("#{} {}", id, spritesheet.path.c_str())); - return spritesheets; + names.push_back(std::format(SPRITESHEET_FORMAT, id, spritesheet.path.c_str())); + return names; } void Anm2::bake(Reference reference, int interval, bool isRoundScale, bool isRoundRotation) diff --git a/src/anm2.h b/src/anm2.h index 056cc84..afcdea9 100644 --- a/src/anm2.h +++ b/src/anm2.h @@ -24,7 +24,8 @@ namespace anm2ed::anm2 constexpr auto NO_PATH = "(No Path)"; constexpr auto LAYER_FORMAT = "#{} {} (Spritesheet: #{})"; constexpr auto NULL_FORMAT = "#{} {}"; - constexpr auto SPRITESHEET_FORMAT = "#%d %s"; + constexpr auto SPRITESHEET_FORMAT_C = "#%d %s"; + constexpr auto SPRITESHEET_FORMAT = "#{} {}"; enum Type { @@ -254,7 +255,9 @@ namespace anm2ed::anm2 std::set events_unused(Reference = REFERENCE_DEFAULT); std::set layers_unused(Reference = REFERENCE_DEFAULT); std::set nulls_unused(Reference = REFERENCE_DEFAULT); + std::vector animation_names_get(); std::vector spritesheet_names_get(); + std::vector event_names_get(); void bake(Reference, int = 1, bool = true, bool = true); void generate_from_grid(Reference, glm::ivec2, glm::ivec2, glm::ivec2, int, int, int); }; diff --git a/src/canvas.cpp b/src/canvas.cpp index 2776404..6359da4 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1,11 +1,15 @@ #include "canvas.h" -#include "math.h" +#include +#include #include #include #include #include +#include "math.h" +#include "texture.h" + using namespace glm; using namespace anm2ed::shader; @@ -283,6 +287,21 @@ namespace anm2ed::canvas glBindFramebuffer(GL_FRAMEBUFFER, 0); } + std::vector Canvas::pixels_get() + { + auto count = size.x * size.y * texture::CHANNELS; + std::vector pixels(count); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + return pixels; + } + void Canvas::zoom_set(float& zoom, vec2& pan, vec2 focus, float step) { auto zoomFactor = math::percent_to_unit(zoom); @@ -295,6 +314,19 @@ namespace anm2ed::canvas } } + vec4 Canvas::pixel_read(vec2 position, vec2 framebufferSize) + { + uint8_t rgba[4]{}; + + glBindTexture(GL_READ_FRAMEBUFFER, fbo); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(position.x, framebufferSize.y - 1 - position.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + return vec4(math::uint8_to_float(rgba[0]), math::uint8_to_float(rgba[1]), math::uint8_to_float(rgba[2]), + math::uint8_to_float(rgba[3])); + } + vec2 Canvas::position_translate(float& zoom, vec2& pan, vec2 position) { auto zoomFactor = math::percent_to_unit(zoom); diff --git a/src/canvas.h b/src/canvas.h index 925c62d..cb99da7 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -18,6 +18,9 @@ namespace anm2ed::canvas constexpr auto DASH_GAP = 1.0f; constexpr auto DASH_OFFSET = 1.0f; + constexpr auto STEP = 1.0f; + constexpr auto STEP_FAST = 5.0f; + class Canvas { public: @@ -43,6 +46,7 @@ namespace anm2ed::canvas void framebuffer_set(); void framebuffer_resize_check(); void size_set(glm::vec2); + glm::vec4 pixel_read(glm::vec2, glm::vec2); glm::mat4 transform_get(float = 100.0f, glm::vec2 = {}); void axes_render(shader::Shader&, float, glm::vec2, glm::vec4 = glm::vec4(1.0f)); void grid_render(shader::Shader&, float, glm::vec2, glm::ivec2 = glm::ivec2(32, 32), glm::ivec2 = {}, @@ -58,5 +62,6 @@ namespace anm2ed::canvas void zoom_set(float&, glm::vec2&, glm::vec2, float); glm::vec2 position_translate(float&, glm::vec2&, glm::vec2); void set_to_rect(float& zoom, glm::vec2& pan, glm::vec4 rect); + std::vector pixels_get(); }; } diff --git a/src/snapshots.cpp b/src/snapshots.cpp index a456be6..b473529 100644 --- a/src/snapshots.cpp +++ b/src/snapshots.cpp @@ -2,6 +2,15 @@ namespace anm2ed::snapshots { + namespace + { + void textures_ensure(anm2::Anm2& anm2) + { + for (auto& [id, spritesheet] : anm2.content.spritesheets) + spritesheet.texture.ensure_pixels(); + } + } + bool SnapshotStack::is_empty() { return top == 0; @@ -31,6 +40,7 @@ namespace anm2ed::snapshots void Snapshots::push(const anm2::Anm2& anm2, anm2::Reference reference, const std::string& message) { + textures_ensure(const_cast(anm2)); Snapshot snapshot = {anm2, reference, message}; undoStack.push(snapshot); redoStack.clear(); @@ -40,8 +50,10 @@ namespace anm2ed::snapshots { if (auto current = undoStack.pop()) { + textures_ensure(anm2); Snapshot snapshot = {anm2, reference, message}; redoStack.push(snapshot); + textures_ensure(current->anm2); anm2 = current->anm2; reference = current->reference; message = current->message; @@ -52,8 +64,10 @@ namespace anm2ed::snapshots { if (auto current = redoStack.pop()) { + textures_ensure(anm2); Snapshot snapshot = {anm2, reference, message}; undoStack.push(snapshot); + textures_ensure(current->anm2); anm2 = current->anm2; reference = current->reference; message = current->message; diff --git a/src/spritesheet_editor.cpp b/src/spritesheet_editor.cpp index ff10925..5861fbd 100644 --- a/src/spritesheet_editor.cpp +++ b/src/spritesheet_editor.cpp @@ -14,6 +14,8 @@ using namespace glm; namespace anm2ed::spritesheet_editor { + constexpr auto PIVOT_COLOR = color::PINK; + SpritesheetEditor::SpritesheetEditor() : Canvas(vec2()) { } @@ -115,7 +117,7 @@ namespace anm2ed::spritesheet_editor auto pivotTransform = transform * math::quad_model_get(canvas::PIVOT_SIZE, frame->crop + frame->pivot, PIVOT_SIZE * 0.5f); - texture_render(shaderTexture, resources.icons[icon::PIVOT].id, pivotTransform, color::RED); + texture_render(shaderTexture, resources.icons[icon::PIVOT].id, pivotTransform, PIVOT_COLOR); } } @@ -145,7 +147,7 @@ namespace anm2ed::spritesheet_editor auto isUp = imgui::chord_repeating(ImGuiKey_UpArrow); auto isDown = imgui::chord_repeating(ImGuiKey_DownArrow); auto isMod = ImGui::IsKeyDown(ImGuiMod_Shift); - auto step = isMod ? step::FAST : step::NORMAL; + auto step = isMod ? canvas::STEP_FAST : canvas::STEP; auto useTool = tool; auto isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); auto isMouseReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Left); @@ -195,12 +197,26 @@ namespace anm2ed::spritesheet_editor case tool::ERASE: { if (!spritesheet) break; - if (isMouseClicked) document.snapshot(tool == tool::DRAW ? "Draw" : "Erase"); auto color = tool == tool::DRAW ? toolColor : vec4(); + if (isMouseClicked) document.snapshot(tool == tool::DRAW ? "Draw" : "Erase"); if (isMouseDown) spritesheet->texture.pixel_line(ivec2(previousMousePos), ivec2(mousePos), color); if (isMouseReleased) document.change(change::FRAMES); break; } + case tool::COLOR_PICKER: + { + if (isMouseDown) + { + auto position = to_vec2(ImGui::GetMousePos()); + toolColor = pixel_read(position, {settings.windowSize.x, settings.windowSize.y}); + if (ImGui::BeginTooltip()) + { + ImGui::ColorButton("##Color Picker Button", to_imvec4(toolColor)); + ImGui::EndTooltip(); + } + } + break; + } default: break; } diff --git a/src/texture.cpp b/src/texture.cpp index 306889a..f508c47 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -32,12 +32,20 @@ namespace anm2ed::texture return id != 0; } + std::vector Texture::pixels_get() + { + ensure_pixels(); + return pixels; + } + void Texture::download() { - pixels.resize(size.x * size.y * CHANNELS); + if (size.x <= 0 || size.y <= 0 || !is_valid()) return; + pixels.resize(static_cast(size.x) * static_cast(size.y) * CHANNELS); glBindTexture(GL_TEXTURE_2D, id); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); glBindTexture(GL_TEXTURE_2D, 0); + isPixelsDirty = false; } void Texture::upload(const uint8_t* data) @@ -66,6 +74,7 @@ namespace anm2ed::texture glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); + isPixelsDirty = false; } Texture::Texture() = default; @@ -91,6 +100,7 @@ namespace anm2ed::texture { if (is_valid()) glDeleteTextures(1, &id); id = 0; + other.ensure_pixels(); size = other.size; filter = other.filter; channels = other.channels; @@ -110,6 +120,9 @@ namespace anm2ed::texture filter = other.filter; channels = other.channels; pixels = std::move(other.pixels); + isPixelsDirty = other.isPixelsDirty; + other.isPixelsDirty = true; + if (!pixels.empty()) upload(); } return *this; } @@ -129,9 +142,15 @@ namespace anm2ed::texture upload(bitmap.data()); } + Texture::Texture(const uint8_t* data, ivec2 size) + { + this->size = size; + upload(data); + } + Texture::Texture(const std::string& pngPath) { - if (const uint8* data = stbi_load(pngPath.c_str(), &size.x, &size.y, nullptr, CHANNELS); data) + if (const uint8_t* data = stbi_load(pngPath.c_str(), &size.x, &size.y, nullptr, CHANNELS); data) { upload(data); stbi_image_free((void*)data); @@ -140,6 +159,7 @@ namespace anm2ed::texture bool Texture::write_png(const std::string& path) { + ensure_pixels(); return stbi_write_png(path.c_str(), size.x, size.y, CHANNELS, this->pixels.data(), size.x * CHANNELS); } @@ -147,6 +167,7 @@ namespace anm2ed::texture { if (position.x < 0 || position.y < 0 || position.x >= size.x || position.y >= size.y) return; + ensure_pixels(); uint8 rgba8[4] = {(uint8)float_to_uint8(color.r), (uint8)float_to_uint8(color.g), (uint8)float_to_uint8(color.b), (uint8)float_to_uint8(color.a)}; @@ -154,14 +175,23 @@ namespace anm2ed::texture glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexSubImage2D(GL_TEXTURE_2D, 0, position.x, position.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba8); glBindTexture(GL_TEXTURE_2D, 0); + if (!pixels.empty()) + { + auto index = (position.y * size.x + position.x) * CHANNELS; + pixels[index + 0] = rgba8[0]; + pixels[index + 1] = rgba8[1]; + pixels[index + 2] = rgba8[2]; + pixels[index + 3] = rgba8[3]; + isPixelsDirty = false; + } + else + isPixelsDirty = true; } void Texture::pixel_line(ivec2 start, ivec2 end, vec4 color) { - auto plot = [&](ivec2 pos) - { - pixel_set(pos, color); - }; + ensure_pixels(); + auto plot = [&](ivec2 pos) { pixel_set(pos, color); }; int x0 = start.x; int y0 = start.y; @@ -192,6 +222,13 @@ namespace anm2ed::texture } } + void Texture::ensure_pixels() const + { + if (size.x <= 0 || size.y <= 0) return; + if (!pixels.empty() && !isPixelsDirty) return; + const_cast(this)->download(); + } + void Texture::bind(GLuint unit) { glActiveTexture(GL_TEXTURE0 + unit); diff --git a/src/texture.h b/src/texture.h index a5e5b0e..419c64c 100644 --- a/src/texture.h +++ b/src/texture.h @@ -17,7 +17,8 @@ namespace anm2ed::texture glm::ivec2 size{}; GLint filter = GL_NEAREST; int channels{}; - std::vector pixels{}; + mutable std::vector pixels{}; + mutable bool isPixelsDirty{true}; bool is_valid(); void download(); @@ -30,10 +31,13 @@ namespace anm2ed::texture Texture(Texture&&); Texture& operator=(const Texture&); Texture& operator=(Texture&&); + Texture(const uint8_t*, glm::ivec2); Texture(const char*, size_t, glm::ivec2); Texture(const std::string&); bool write_png(const std::string&); void pixel_set(glm::ivec2, glm::vec4); + void ensure_pixels() const; + std::vector pixels_get(); void pixel_line(glm::ivec2, glm::ivec2, glm::vec4); void bind(GLuint = 0); void unbind(GLuint = 0); From 62cd94ca78e3cfbef199473618106745ecac2f0b Mon Sep 17 00:00:00 2001 From: shweet Date: Sat, 1 Nov 2025 19:51:19 -0400 Subject: [PATCH 11/15] Big refactor, shuffling a lot of files around --- CMakeLists.txt | 38 +- src/animation_preview.h | 19 - src/animations.h | 18 - src/anm2.cpp | 1453 ----------------- src/anm2.h | 264 --- src/anm2/animation.cpp | 206 +++ src/anm2/animation.h | 35 + src/anm2/animations.cpp | 155 ++ src/anm2/animations.h | 22 + src/anm2/anm2.cpp | 376 +++++ src/anm2/anm2.h | 72 + src/anm2/content.cpp | 256 +++ src/anm2/content.h | 46 + src/anm2/event.cpp | 36 + src/anm2/event.h | 20 + src/anm2/frame.cpp | 126 ++ src/anm2/frame.h | 91 ++ src/anm2/info.cpp | 40 + src/anm2/info.h | 25 + src/anm2/item.cpp | 200 +++ src/anm2/item.h | 26 + src/anm2/layer.cpp | 39 + src/anm2/layer.h | 22 + src/anm2/null.cpp | 38 + src/anm2/null.h | 22 + src/anm2/sound.cpp | 59 + src/anm2/sound.h | 30 + src/anm2/spritesheet.cpp | 70 + src/anm2/spritesheet.h | 30 + src/canvas.cpp | 13 +- src/canvas.h | 16 +- src/clipboard.cpp | 2 +- src/clipboard.h | 2 +- src/dialog.cpp | 54 +- src/dialog.h | 86 +- src/dockspace.h | 39 - src/document.cpp | 245 ++- src/document.h | 72 +- src/events.h | 16 - src/frame_properties.cpp | 124 -- src/{ => imgui}/dockspace.cpp | 24 +- src/imgui/dockspace.h | 41 + src/{ => imgui}/documents.cpp | 11 +- src/{ => imgui}/documents.h | 4 +- src/{imgui.cpp => imgui/imgui_.cpp} | 196 +-- src/{imgui.h => imgui/imgui_.h} | 49 +- src/{ => imgui}/taskbar.cpp | 138 +- src/imgui/taskbar.h | 31 + src/{ => imgui}/toast.cpp | 6 +- src/{ => imgui}/toast.h | 6 +- src/{ => imgui/window}/animation_preview.cpp | 131 +- src/imgui/window/animation_preview.h | 21 + src/{ => imgui/window}/animations.cpp | 55 +- src/imgui/window/animations.h | 17 + src/imgui/window/events.cpp | 160 ++ src/imgui/window/events.h | 18 + src/imgui/window/frame_properties.cpp | 125 ++ src/{ => imgui/window}/frame_properties.h | 4 +- src/{ => imgui/window}/layers.cpp | 34 +- src/{ => imgui/window}/layers.h | 4 +- src/{ => imgui/window}/nulls.cpp | 30 +- src/{ => imgui/window}/nulls.h | 4 +- src/imgui/window/onionskin.cpp | 55 + src/{ => imgui/window}/onionskin.h | 4 +- src/{events.cpp => imgui/window/sounds.cpp} | 74 +- src/imgui/window/sounds.h | 16 + src/{ => imgui/window}/spritesheet_editor.cpp | 18 +- src/{ => imgui/window}/spritesheet_editor.h | 6 +- src/{ => imgui/window}/spritesheets.cpp | 34 +- src/imgui/window/spritesheets.h | 16 + src/{ => imgui/window}/timeline.cpp | 74 +- src/imgui/window/timeline.h | 39 + src/{ => imgui/window}/tools.cpp | 46 +- src/{ => imgui/window}/tools.h | 6 +- src/{ => imgui/window}/welcome.cpp | 32 +- src/imgui/window/welcome.h | 16 + src/loader.cpp | 55 +- src/loader.h | 6 +- src/log.cpp | 17 +- src/log.h | 9 +- src/main.cpp | 7 +- src/manager.cpp | 14 +- src/manager.h | 15 +- src/onionskin.cpp | 45 - src/playback.cpp | 2 +- src/playback.h | 2 +- src/render.cpp | 96 ++ src/render.h | 32 + src/resource/audio.cpp | 49 + src/resource/audio.h | 24 + src/{ => resource}/font.cpp | 2 +- src/{ => resource}/font.h | 12 +- src/{ => resource}/icon.h | 2 +- src/{ => resource}/shader.cpp | 4 +- src/{ => resource}/shader.h | 7 +- src/{ => resource}/texture.cpp | 96 +- src/{ => resource}/texture.h | 16 +- src/resources.cpp | 7 +- src/resources.h | 8 +- src/settings.cpp | 11 +- src/settings.h | 12 +- src/snapshots.cpp | 18 +- src/snapshots.h | 9 +- src/spritesheets.h | 17 - src/state.cpp | 15 +- src/state.h | 24 +- src/taskbar.h | 31 - src/timeline.h | 44 - src/tool.h | 26 +- src/types.h | 35 +- src/{filesystem.cpp => util/filesystem_.cpp} | 9 +- src/{filesystem.h => util/filesystem_.h} | 3 +- src/util/map_.h | 24 + src/{math.cpp => util/math_.cpp} | 4 +- src/{math.h => util/math_.h} | 9 +- src/{util.cpp => util/string_.cpp} | 30 +- src/util/string_.h | 11 + src/util/time_.cpp | 16 + src/util/time_.h | 10 + src/util/unordered_map_.h | 11 + src/{util.h => util/vector_.h} | 47 - src/util/xml_.cpp | 38 + src/{xml.h => util/xml_.h} | 2 +- src/welcome.h | 16 - src/xml.cpp | 37 - 125 files changed, 4073 insertions(+), 3011 deletions(-) delete mode 100644 src/animation_preview.h delete mode 100644 src/animations.h delete mode 100644 src/anm2.cpp delete mode 100644 src/anm2.h create mode 100644 src/anm2/animation.cpp create mode 100644 src/anm2/animation.h create mode 100644 src/anm2/animations.cpp create mode 100644 src/anm2/animations.h create mode 100644 src/anm2/anm2.cpp create mode 100644 src/anm2/anm2.h create mode 100644 src/anm2/content.cpp create mode 100644 src/anm2/content.h create mode 100644 src/anm2/event.cpp create mode 100644 src/anm2/event.h create mode 100644 src/anm2/frame.cpp create mode 100644 src/anm2/frame.h create mode 100644 src/anm2/info.cpp create mode 100644 src/anm2/info.h create mode 100644 src/anm2/item.cpp create mode 100644 src/anm2/item.h create mode 100644 src/anm2/layer.cpp create mode 100644 src/anm2/layer.h create mode 100644 src/anm2/null.cpp create mode 100644 src/anm2/null.h create mode 100644 src/anm2/sound.cpp create mode 100644 src/anm2/sound.h create mode 100644 src/anm2/spritesheet.cpp create mode 100644 src/anm2/spritesheet.h delete mode 100644 src/dockspace.h delete mode 100644 src/events.h delete mode 100644 src/frame_properties.cpp rename src/{ => imgui}/dockspace.cpp (83%) create mode 100644 src/imgui/dockspace.h rename src/{ => imgui}/documents.cpp (94%) rename src/{ => imgui}/documents.h (70%) rename src/{imgui.cpp => imgui/imgui_.cpp} (87%) rename src/{imgui.h => imgui/imgui_.h} (87%) rename src/{ => imgui}/taskbar.cpp (80%) create mode 100644 src/imgui/taskbar.h rename src/{ => imgui}/toast.cpp (97%) rename src/{ => imgui}/toast.h (85%) rename src/{ => imgui/window}/animation_preview.cpp (80%) create mode 100644 src/imgui/window/animation_preview.h rename src/{ => imgui/window}/animations.cpp (80%) create mode 100644 src/imgui/window/animations.h create mode 100644 src/imgui/window/events.cpp create mode 100644 src/imgui/window/events.h create mode 100644 src/imgui/window/frame_properties.cpp rename src/{ => imgui/window}/frame_properties.h (53%) rename src/{ => imgui/window}/layers.cpp (79%) rename src/{ => imgui/window}/layers.h (52%) rename src/{ => imgui/window}/nulls.cpp (82%) rename src/{ => imgui/window}/nulls.h (52%) create mode 100644 src/imgui/window/onionskin.cpp rename src/{ => imgui/window}/onionskin.h (54%) rename src/{events.cpp => imgui/window/sounds.cpp} (54%) create mode 100644 src/imgui/window/sounds.h rename src/{ => imgui/window}/spritesheet_editor.cpp (96%) rename src/{ => imgui/window}/spritesheet_editor.h (55%) rename src/{ => imgui/window}/spritesheets.cpp (90%) create mode 100644 src/imgui/window/spritesheets.h rename src/{ => imgui/window}/timeline.cpp (96%) create mode 100644 src/imgui/window/timeline.h rename src/{ => imgui/window}/tools.cpp (66%) rename src/{ => imgui/window}/tools.h (51%) rename src/{ => imgui/window}/welcome.cpp (69%) create mode 100644 src/imgui/window/welcome.h delete mode 100644 src/onionskin.cpp create mode 100644 src/render.cpp create mode 100644 src/render.h create mode 100644 src/resource/audio.cpp create mode 100644 src/resource/audio.h rename src/{ => resource}/font.cpp (95%) rename src/{ => resource}/font.h (99%) rename src/{ => resource}/icon.h (99%) rename src/{ => resource}/shader.cpp (96%) rename src/{ => resource}/shader.h (98%) rename src/{ => resource}/texture.cpp (64%) rename src/{ => resource}/texture.h (74%) delete mode 100644 src/spritesheets.h delete mode 100644 src/taskbar.h delete mode 100644 src/timeline.h rename src/{filesystem.cpp => util/filesystem_.cpp} (87%) rename src/{filesystem.h => util/filesystem_.h} (82%) create mode 100644 src/util/map_.h rename src/{math.cpp => util/math_.cpp} (98%) rename src/{math.h => util/math_.h} (88%) rename src/{util.cpp => util/string_.cpp} (55%) create mode 100644 src/util/string_.h create mode 100644 src/util/time_.cpp create mode 100644 src/util/time_.h create mode 100644 src/util/unordered_map_.h rename src/{util.h => util/vector_.h} (67%) create mode 100644 src/util/xml_.cpp rename src/{xml.h => util/xml_.h} (93%) delete mode 100644 src/welcome.h delete mode 100644 src/xml.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9316794..dd30ade 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,10 +19,30 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) -set(SDL_SHARED OFF CACHE BOOL "" FORCE) + set(SDL_STATIC ON CACHE BOOL "" FORCE) +set(SDL_SHARED OFF CACHE BOOL "" FORCE) +set(SDL_HAPTIC OFF CACHE BOOL "" FORCE) +set(SDL_SENSOR OFF CACHE BOOL "" FORCE) +set(SDL_HIDAPI OFF CACHE BOOL "" FORCE) +set(SDL_CAMERA OFF CACHE BOOL "" FORCE) +set(SDL_TRAY OFF CACHE BOOL "" FORCE) add_subdirectory(external/SDL EXCLUDE_FROM_ALL) +set(SDLMIXER_DEPS_SHARED OFF CACHE BOOL "" FORCE) +set(SDLMIXER_FLAC_LIBFLAC OFF CACHE BOOL "" FORCE) +set(SDLMIXER_GME OFF CACHE BOOL "" FORCE) +set(SDLMIXER_MOD_XMP OFF CACHE BOOL "" FORCE) +set(SDLMIXER_MP3_MPG123 OFF CACHE BOOL "" FORCE) +set(SDLMIXER_MIDI_FLUIDSYNTH OFF CACHE BOOL "" FORCE) +set(SDLMIXER_OPUS OFF CACHE BOOL "" FORCE) +set(SDLMIXER_VORBIS_VORBISFILE OFF CACHE BOOL "" FORCE) +set(SDLMIXER_VORBIS_TREMOR OFF CACHE BOOL "" FORCE) +set(SDLMIXER_WAVPACK OFF CACHE BOOL "" FORCE) +set(SDLMIXER_TEST OFF CACHE BOOL "" FORCE) +set(SDLMIXER_INSTALL OFF CACHE BOOL "" FORCE) +add_subdirectory(external/SDL_mixer EXCLUDE_FROM_ALL) + add_subdirectory(external/lunasvg) set(GLAD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/include/glad/glad.cpp) @@ -39,6 +59,18 @@ set(IMGUI_SRC set(TINYXML2_SRC external/tinyxml2/tinyxml2.cpp) file(GLOB PROJECT_SRC CONFIGURE_DEPENDS + src/anm2/*.cpp + src/anm2/*.h + src/resource/*.cpp + src/resource/*.h + src/imgui/*.cpp + src/imgui/*.h + src/imgui/window/*.cpp + src/imgui/window/*.h + src/util/*.cpp + src/util/*.h + src/window/*.cpp + src/window/*.h src/*.cpp src/*.h ) @@ -88,6 +120,8 @@ target_include_directories(${PROJECT_NAME} PRIVATE external/glm external/tinyxml2 external/lunasvg + external/SDL + external/SDL_mixer include include/glad src @@ -96,7 +130,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE src/util ) -target_link_libraries(${PROJECT_NAME} PRIVATE GL SDL3-static lunasvg) +target_link_libraries(${PROJECT_NAME} PRIVATE GL SDL3-static SDL3_mixer::SDL3_mixer lunasvg) message(STATUS "System: ${CMAKE_SYSTEM_NAME}") message(STATUS "Project: ${PROJECT_NAME}") diff --git a/src/animation_preview.h b/src/animation_preview.h deleted file mode 100644 index 65a1a18..0000000 --- a/src/animation_preview.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "canvas.h" -#include "manager.h" -#include "resources.h" -#include "settings.h" - -namespace anm2ed::animation_preview -{ - class AnimationPreview : public canvas::Canvas - { - bool isPreviewHovered{}; - glm::ivec2 mousePos{}; - - public: - AnimationPreview(); - void update(manager::Manager&, settings::Settings&, resources::Resources&); - }; -} diff --git a/src/animations.h b/src/animations.h deleted file mode 100644 index e03e7e9..0000000 --- a/src/animations.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "clipboard.h" -#include "imgui.h" -#include "manager.h" -#include "resources.h" -#include "settings.h" - -namespace anm2ed::animations -{ - class Animations - { - imgui::PopupHelper mergePopup{imgui::PopupHelper("Merge Animations")}; - - public: - void update(manager::Manager&, settings::Settings&, resources::Resources&, clipboard::Clipboard&); - }; -} diff --git a/src/anm2.cpp b/src/anm2.cpp deleted file mode 100644 index f7e644b..0000000 --- a/src/anm2.cpp +++ /dev/null @@ -1,1453 +0,0 @@ -#include "anm2.h" - -#include - -#include "filesystem.h" -#include "math.h" -#include "texture.h" -#include "util.h" -#include "xml.h" - -using namespace tinyxml2; -using namespace anm2ed::filesystem; -using namespace anm2ed::texture; -using namespace anm2ed::types; -using namespace anm2ed::util; -using namespace glm; - -namespace anm2ed::anm2 -{ - Info::Info() = default; - - Info::Info(XMLElement* element) - { - if (!element) return; - xml::query_string_attribute(element, "CreatedBy", &createdBy); - xml::query_string_attribute(element, "CreatedOn", &createdOn); - element->QueryIntAttribute("Fps", &fps); - element->QueryIntAttribute("Version", &version); - } - - void Info::serialize(XMLDocument& document, XMLElement* parent) - { - auto infoElement = document.NewElement("Info"); - infoElement->SetAttribute("CreatedBy", createdBy.c_str()); - infoElement->SetAttribute("CreatedOn", createdOn.c_str()); - infoElement->SetAttribute("Fps", fps); - infoElement->SetAttribute("Version", version); - parent->InsertEndChild(infoElement); - } - - Spritesheet::Spritesheet() = default; - - Spritesheet::Spritesheet(XMLElement* element, int& id) - { - if (!element) return; - element->QueryIntAttribute("Id", &id); - xml::query_path_attribute(element, "Path", &path); - // Spritesheet paths from Isaac Rebirth are made with the assumption that - // the paths are case-insensitive (as the game was developed on Windows) - // However when using the resource dumper, the spritesheet paths are all lowercase (on Linux anyway) - // If the check doesn't work, set the spritesheet path to lowercase - // If that check doesn't work, replace backslashes with slashes - // At the minimum this should make all textures be able to be loaded on Linux - // If it doesn't work beyond that then that's on the user :^) - if (!path_is_exist(path)) path = string::to_lower(path); - if (!path_is_exist(path)) path = string::replace_backslash(path); - texture = Texture(path); - } - - Spritesheet::Spritesheet(const std::string& directory, const std::string& path) - { - this->path = !path.empty() ? path : this->path.string(); - WorkingDirectory workingDirectory(directory); - texture = Texture(this->path); - } - - bool Spritesheet::save(const std::string& directory, const std::string& path) - { - this->path = !path.empty() ? path : this->path.string(); - WorkingDirectory workingDirectory(directory); - return texture.write_png(this->path); - } - - void Spritesheet::serialize(XMLDocument& document, XMLElement* parent, int id) - { - auto element = document.NewElement("Spritesheet"); - element->SetAttribute("Id", id); - element->SetAttribute("Path", path.c_str()); - parent->InsertEndChild(element); - } - - void Spritesheet::reload(const std::string& directory) - { - *this = Spritesheet(directory, this->path); - } - - bool Spritesheet::is_valid() - { - return texture.is_valid(); - } - - std::string Spritesheet::to_string(int id) - { - XMLDocument document{}; - - auto* element = document.NewElement("Spritesheet"); - - element->SetAttribute("Id", id); - element->SetAttribute("Path", path.c_str()); - - document.InsertFirstChild(element); - - XMLPrinter printer; - document.Print(&printer); - return std::string(printer.CStr()); - } - - Layer::Layer() = default; - - Layer::Layer(XMLElement* element, int& id) - { - if (!element) return; - element->QueryIntAttribute("Id", &id); - xml::query_string_attribute(element, "Name", &name); - element->QueryIntAttribute("SpritesheetId", &spritesheetID); - } - - void Layer::serialize(XMLDocument& document, XMLElement* parent, int id) - { - auto element = document.NewElement("Layer"); - element->SetAttribute("Id", id); - element->SetAttribute("Name", name.c_str()); - element->SetAttribute("SpritesheetId", spritesheetID); - parent->InsertEndChild(element); - } - - std::string Layer::to_string(int id) - { - XMLDocument document{}; - - auto* element = document.NewElement("Layer"); - - element->SetAttribute("Id", id); - element->SetAttribute("Name", name.c_str()); - element->SetAttribute("SpritesheetId", spritesheetID); - - document.InsertFirstChild(element); - - XMLPrinter printer; - document.Print(&printer); - return std::string(printer.CStr()); - } - - Null::Null() = default; - - Null::Null(XMLElement* element, int& id) - { - if (!element) return; - element->QueryIntAttribute("Id", &id); - xml::query_string_attribute(element, "Name", &name); - element->QueryBoolAttribute("ShowRect", &isShowRect); - } - - void Null::serialize(XMLDocument& document, XMLElement* parent, int id) - { - auto element = document.NewElement("Null"); - element->SetAttribute("Id", id); - element->SetAttribute("Name", name.c_str()); - if (isShowRect) element->SetAttribute("ShowRect", isShowRect); - - parent->InsertEndChild(element); - } - - std::string Null::to_string(int id) - { - XMLDocument document{}; - - auto* element = document.NewElement("Null"); - - element->SetAttribute("Id", id); - element->SetAttribute("Name", name.c_str()); - - document.InsertFirstChild(element); - - XMLPrinter printer; - document.Print(&printer); - return std::string(printer.CStr()); - } - - Event::Event() = default; - - Event::Event(XMLElement* element, int& id) - { - if (!element) return; - element->QueryIntAttribute("Id", &id); - xml::query_string_attribute(element, "Name", &name); - } - - void Event::serialize(XMLDocument& document, XMLElement* parent, int id) - { - auto element = document.NewElement("Event"); - element->SetAttribute("Id", id); - element->SetAttribute("Name", name.c_str()); - parent->InsertEndChild(element); - } - - std::string Event::to_string(int id) - { - XMLDocument document{}; - - auto* element = document.NewElement("Event"); - - element->SetAttribute("Id", id); - element->SetAttribute("Name", name.c_str()); - - document.InsertFirstChild(element); - - XMLPrinter printer; - document.Print(&printer); - return std::string(printer.CStr()); - } - - Content::Content() = default; - - void Content::serialize(XMLDocument& document, XMLElement* parent) - { - auto element = document.NewElement("Content"); - - auto spritesheetsElement = document.NewElement("Spritesheets"); - for (auto& [id, spritesheet] : spritesheets) - spritesheet.serialize(document, spritesheetsElement, id); - element->InsertEndChild(spritesheetsElement); - - auto layersElement = document.NewElement("Layers"); - for (auto& [id, layer] : layers) - layer.serialize(document, layersElement, id); - element->InsertEndChild(layersElement); - - auto nullsElement = document.NewElement("Nulls"); - for (auto& [id, null] : nulls) - null.serialize(document, nullsElement, id); - element->InsertEndChild(nullsElement); - - auto eventsElement = document.NewElement("Events"); - for (auto& [id, event] : events) - event.serialize(document, eventsElement, id); - element->InsertEndChild(eventsElement); - - parent->InsertEndChild(element); - } - - Content::Content(XMLElement* element) - { - int id{}; - - if (auto spritesheetsElement = element->FirstChildElement("Spritesheets")) - { - for (auto child = spritesheetsElement->FirstChildElement("Spritesheet"); child; - child = child->NextSiblingElement("Spritesheet")) - spritesheets[id] = Spritesheet(child, id); - } - - if (auto layersElement = element->FirstChildElement("Layers")) - { - for (auto child = layersElement->FirstChildElement("Layer"); child; child = child->NextSiblingElement("Layer")) - layers[id] = Layer(child, id); - } - - if (auto nullsElement = element->FirstChildElement("Nulls")) - { - for (auto child = nullsElement->FirstChildElement("Null"); child; child = child->NextSiblingElement("Null")) - nulls[id] = Null(child, id); - } - - if (auto eventsElement = element->FirstChildElement("Events")) - { - for (auto child = eventsElement->FirstChildElement("Event"); child; child = child->NextSiblingElement("Event")) - events[id] = Event(child, id); - } - } - - std::set Content::spritesheets_unused() - { - std::set used; - for (auto& layer : layers | std::views::values) - if (layer.spritesheetID != -1) used.insert(layer.spritesheetID); - - std::set unused; - for (auto& id : spritesheets | std::views::keys) - if (!used.contains(id)) unused.insert(id); - - return unused; - } - - void Content::layer_add(int& id) - { - id = map::next_id_get(layers); - layers[id] = Layer(); - } - - void Content::null_add(int& id) - { - id = map::next_id_get(nulls); - nulls[id] = Null(); - } - - void Content::event_add(int& id) - { - id = map::next_id_get(events); - events[id] = Event(); - } - - bool Content::spritesheets_deserialize(const std::string& string, const std::string& directory, merge::Type type, - std::string* errorString) - { - XMLDocument document{}; - - if (document.Parse(string.c_str()) == XML_SUCCESS) - { - int id{}; - - if (!document.FirstChildElement("Spritesheet")) - { - if (errorString) *errorString = "No valid spritesheet(s)."; - return false; - } - - WorkingDirectory workingDirectory(directory); - - for (auto element = document.FirstChildElement("Spritesheet"); element; - element = element->NextSiblingElement("Spritesheet")) - { - auto spritesheet = Spritesheet(element, id); - - if (type == merge::APPEND) id = map::next_id_get(spritesheets); - - spritesheets[id] = std::move(spritesheet); - } - - return true; - } - else if (errorString) - *errorString = document.ErrorStr(); - - return false; - } - - bool Content::layers_deserialize(const std::string& string, merge::Type type, std::string* errorString) - { - XMLDocument document{}; - - if (document.Parse(string.c_str()) == XML_SUCCESS) - { - int id{}; - - if (!document.FirstChildElement("Layer")) - { - if (errorString) *errorString = "No valid layer(s)."; - return false; - } - - for (auto element = document.FirstChildElement("Layer"); element; element = element->NextSiblingElement("Layer")) - { - auto layer = Layer(element, id); - - if (type == merge::APPEND) id = map::next_id_get(layers); - - layers[id] = layer; - } - - return true; - } - else if (errorString) - *errorString = document.ErrorStr(); - - return false; - } - - bool Content::nulls_deserialize(const std::string& string, merge::Type type, std::string* errorString) - { - XMLDocument document{}; - - if (document.Parse(string.c_str()) == XML_SUCCESS) - { - int id{}; - - if (!document.FirstChildElement("Null")) - { - if (errorString) *errorString = "No valid null(s)."; - return false; - } - - for (auto element = document.FirstChildElement("Null"); element; element = element->NextSiblingElement("Null")) - { - auto layer = Null(element, id); - - if (type == merge::APPEND) id = map::next_id_get(nulls); - - nulls[id] = layer; - } - - return true; - } - else if (errorString) - *errorString = document.ErrorStr(); - - return false; - } - - bool Content::events_deserialize(const std::string& string, merge::Type type, std::string* errorString) - { - XMLDocument document{}; - - if (document.Parse(string.c_str()) == XML_SUCCESS) - { - int id{}; - - if (!document.FirstChildElement("Event")) - { - if (errorString) *errorString = "No valid event(s)."; - return false; - } - - for (auto element = document.FirstChildElement("Event"); element; element = element->NextSiblingElement("Event")) - { - auto layer = Event(element, id); - - if (type == merge::APPEND) id = map::next_id_get(events); - - events[id] = layer; - } - - return true; - } - else if (errorString) - *errorString = document.ErrorStr(); - - return false; - } - - Frame::Frame() = default; - - Frame::Frame(XMLElement* element, Type type) - { - if (!element) return; - - if (type != TRIGGER) - { - element->QueryFloatAttribute("XPosition", &position.x); - element->QueryFloatAttribute("YPosition", &position.y); - if (type == LAYER) - { - element->QueryFloatAttribute("XPivot", &pivot.x); - element->QueryFloatAttribute("YPivot", &pivot.y); - element->QueryFloatAttribute("XCrop", &crop.x); - element->QueryFloatAttribute("YCrop", &crop.y); - element->QueryFloatAttribute("Width", &size.x); - element->QueryFloatAttribute("Height", &size.y); - } - element->QueryFloatAttribute("XScale", &scale.x); - element->QueryFloatAttribute("YScale", &scale.y); - element->QueryIntAttribute("Delay", &delay); - element->QueryBoolAttribute("Visible", &isVisible); - xml::query_color_attribute(element, "RedTint", tint.r); - xml::query_color_attribute(element, "GreenTint", tint.g); - xml::query_color_attribute(element, "BlueTint", tint.b); - xml::query_color_attribute(element, "AlphaTint", tint.a); - xml::query_color_attribute(element, "RedOffset", colorOffset.r); - xml::query_color_attribute(element, "GreenOffset", colorOffset.g); - xml::query_color_attribute(element, "BlueOffset", colorOffset.b); - element->QueryFloatAttribute("Rotation", &rotation); - element->QueryBoolAttribute("Interpolated", &isInterpolated); - } - else - { - element->QueryIntAttribute("EventId", &eventID); - element->QueryIntAttribute("AtFrame", &atFrame); - } - } - - void Frame::serialize(XMLDocument& document, XMLElement* parent, Type type) - { - auto element = document.NewElement(type == TRIGGER ? "Trigger" : "Frame"); - - switch (type) - { - case ROOT: - case NULL_: - element->SetAttribute("XPosition", position.x); - element->SetAttribute("YPosition", position.y); - element->SetAttribute("Delay", delay); - element->SetAttribute("Visible", isVisible); - element->SetAttribute("XScale", scale.x); - element->SetAttribute("YScale", scale.y); - element->SetAttribute("RedTint", math::float_to_uint8(tint.r)); - element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); - element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); - element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); - element->SetAttribute("RedOffset", math::float_to_uint8(colorOffset.r)); - element->SetAttribute("GreenOffset", math::float_to_uint8(colorOffset.g)); - element->SetAttribute("BlueOffset", math::float_to_uint8(colorOffset.b)); - element->SetAttribute("Rotation", rotation); - element->SetAttribute("Interpolated", isInterpolated); - break; - case LAYER: - element->SetAttribute("XPosition", position.x); - element->SetAttribute("YPosition", position.y); - element->SetAttribute("XPivot", pivot.x); - element->SetAttribute("YPivot", pivot.y); - element->SetAttribute("XCrop", crop.x); - element->SetAttribute("YCrop", crop.y); - element->SetAttribute("Width", size.x); - element->SetAttribute("Height", size.y); - element->SetAttribute("XScale", scale.x); - element->SetAttribute("YScale", scale.y); - element->SetAttribute("Delay", delay); - element->SetAttribute("Visible", isVisible); - element->SetAttribute("RedTint", math::float_to_uint8(tint.r)); - element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); - element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); - element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); - element->SetAttribute("RedOffset", math::float_to_uint8(colorOffset.r)); - element->SetAttribute("GreenOffset", math::float_to_uint8(colorOffset.g)); - element->SetAttribute("BlueOffset", math::float_to_uint8(colorOffset.b)); - element->SetAttribute("Rotation", rotation); - element->SetAttribute("Interpolated", isInterpolated); - break; - case TRIGGER: - element->SetAttribute("EventId", eventID); - element->SetAttribute("AtFrame", atFrame); - break; - default: - break; - } - - parent->InsertEndChild(element); - } - - std::string Frame::to_string(Type type) - { - XMLDocument document; - auto element = document.NewElement(type == TRIGGER ? "Trigger" : "Frame"); - - switch (type) - { - case ROOT: - case NULL_: - element->SetAttribute("XPosition", position.x); - element->SetAttribute("YPosition", position.y); - element->SetAttribute("Delay", delay); - element->SetAttribute("Visible", isVisible); - element->SetAttribute("XScale", scale.x); - element->SetAttribute("YScale", scale.y); - element->SetAttribute("RedTint", math::float_to_uint8(tint.r)); - element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); - element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); - element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); - element->SetAttribute("RedOffset", math::float_to_uint8(colorOffset.r)); - element->SetAttribute("GreenOffset", math::float_to_uint8(colorOffset.g)); - element->SetAttribute("BlueOffset", math::float_to_uint8(colorOffset.b)); - element->SetAttribute("Rotation", rotation); - element->SetAttribute("Interpolated", isInterpolated); - break; - case LAYER: - element->SetAttribute("XPosition", position.x); - element->SetAttribute("YPosition", position.y); - element->SetAttribute("XPivot", pivot.x); - element->SetAttribute("YPivot", pivot.y); - element->SetAttribute("XCrop", crop.x); - element->SetAttribute("YCrop", crop.y); - element->SetAttribute("Width", size.x); - element->SetAttribute("Height", size.y); - element->SetAttribute("XScale", scale.x); - element->SetAttribute("YScale", scale.y); - element->SetAttribute("Delay", delay); - element->SetAttribute("Visible", isVisible); - element->SetAttribute("RedTint", math::float_to_uint8(tint.r)); - element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); - element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); - element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); - element->SetAttribute("RedOffset", math::float_to_uint8(colorOffset.r)); - element->SetAttribute("GreenOffset", math::float_to_uint8(colorOffset.g)); - element->SetAttribute("BlueOffset", math::float_to_uint8(colorOffset.b)); - element->SetAttribute("Rotation", rotation); - element->SetAttribute("Interpolated", isInterpolated); - break; - case TRIGGER: - element->SetAttribute("EventId", eventID); - element->SetAttribute("AtFrame", atFrame); - break; - default: - break; - } - - document.InsertFirstChild(element); - - XMLPrinter printer; - document.Print(&printer); - return std::string(printer.CStr()); - } - - void Frame::shorten() - { - delay = glm::clamp(--delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); - } - - void Frame::extend() - { - delay = glm::clamp(++delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); - } - - Item::Item() = default; - - Item::Item(XMLElement* element, Type type, int* id) - { - if (type == LAYER && id) element->QueryIntAttribute("LayerId", id); - if (type == NULL_ && id) element->QueryIntAttribute("NullId", id); - - element->QueryBoolAttribute("Visible", &isVisible); - - for (auto child = type == TRIGGER ? element->FirstChildElement("Trigger") : element->FirstChildElement("Frame"); - child; child = type == TRIGGER ? child->NextSiblingElement("Trigger") : child->NextSiblingElement("Frame")) - frames.push_back(Frame(child, type)); - } - - void Item::serialize(XMLDocument& document, XMLElement* parent, Type type, int id) - { - auto typeString = type == ROOT ? "RootAnimation" - : type == LAYER ? "LayerAnimation" - : type == NULL_ ? "NullAnimation" - : "Triggers"; - - auto element = document.NewElement(typeString); - - if (type == LAYER) element->SetAttribute("LayerId", id); - if (type == NULL_) element->SetAttribute("NullId", id); - if (type == LAYER || type == NULL_) element->SetAttribute("Visible", isVisible); - - for (auto& frame : frames) - frame.serialize(document, element, type); - parent->InsertEndChild(element); - } - - int Item::length(Type type) - { - int length{}; - - if (type == TRIGGER) - for (auto& frame : frames) - length = frame.atFrame > length ? frame.atFrame : length; - else - for (auto& frame : frames) - length += frame.delay; - - return length; - } - - Frame Item::frame_generate(float time, Type type) - { - Frame frame{}; - frame.isVisible = false; - - if (frames.empty()) return frame; - - Frame* frameNext = nullptr; - int delayCurrent = 0; - int delayNext = 0; - - for (auto [i, iFrame] : std::views::enumerate(frames)) - { - if (type == TRIGGER) - { - if ((int)time == iFrame.atFrame) - { - frame = iFrame; - break; - } - } - else - { - frame = iFrame; - - delayNext += frame.delay; - - if (time >= delayCurrent && time < delayNext) - { - if (i + 1 < (int)frames.size()) - frameNext = &frames[i + 1]; - else - frameNext = nullptr; - break; - } - - delayCurrent += frame.delay; - } - } - - if (type != TRIGGER && frame.isInterpolated && frameNext && frame.delay > 1) - { - auto interpolation = (time - delayCurrent) / (delayNext - delayCurrent); - - frame.rotation = glm::mix(frame.rotation, frameNext->rotation, interpolation); - frame.position = glm::mix(frame.position, frameNext->position, interpolation); - frame.scale = glm::mix(frame.scale, frameNext->scale, interpolation); - frame.colorOffset = glm::mix(frame.colorOffset, frameNext->colorOffset, interpolation); - frame.tint = glm::mix(frame.tint, frameNext->tint, interpolation); - } - - return frame; - } - - void Item::frames_change(anm2::FrameChange& change, frame_change::Type type, int start, int numberFrames) - { - auto useStart = numberFrames > -1 ? start : 0; - auto end = numberFrames > -1 ? start + numberFrames : (int)frames.size(); - vector::clamp_in_bounds(frames, useStart); - end = glm::clamp(end, start, (int)frames.size()); - - for (int i = useStart; i < end; i++) - { - Frame& frame = frames[i]; - - if (change.isVisible) frame.isVisible = *change.isVisible; - if (change.isInterpolated) frame.isInterpolated = *change.isInterpolated; - - switch (type) - { - case frame_change::ADJUST: - if (change.rotation) frame.rotation = *change.rotation; - if (change.delay) frame.delay = std::max(FRAME_DELAY_MIN, *change.delay); - if (change.crop) frame.crop = *change.crop; - if (change.pivot) frame.pivot = *change.pivot; - if (change.position) frame.position = *change.position; - if (change.size) frame.size = *change.size; - if (change.scale) frame.scale = *change.scale; - if (change.colorOffset) frame.colorOffset = glm::clamp(*change.colorOffset, 0.0f, 1.0f); - if (change.tint) frame.tint = glm::clamp(*change.tint, 0.0f, 1.0f); - break; - - case frame_change::ADD: - if (change.rotation) frame.rotation += *change.rotation; - if (change.delay) frame.delay = std::max(FRAME_DELAY_MIN, frame.delay + *change.delay); - if (change.crop) frame.crop += *change.crop; - if (change.pivot) frame.pivot += *change.pivot; - if (change.position) frame.position += *change.position; - if (change.size) frame.size += *change.size; - if (change.scale) frame.scale += *change.scale; - if (change.colorOffset) frame.colorOffset = glm::clamp(frame.colorOffset + *change.colorOffset, 0.0f, 1.0f); - if (change.tint) frame.tint = glm::clamp(frame.tint + *change.tint, 0.0f, 1.0f); - break; - - case frame_change::SUBTRACT: - if (change.rotation) frame.rotation -= *change.rotation; - if (change.delay) frame.delay = std::max(FRAME_DELAY_MIN, frame.delay - *change.delay); - if (change.crop) frame.crop -= *change.crop; - if (change.pivot) frame.pivot -= *change.pivot; - if (change.position) frame.position -= *change.position; - if (change.size) frame.size -= *change.size; - if (change.scale) frame.scale -= *change.scale; - if (change.colorOffset) frame.colorOffset = glm::clamp(frame.colorOffset - *change.colorOffset, 0.0f, 1.0f); - if (change.tint) frame.tint = glm::clamp(frame.tint - *change.tint, 0.0f, 1.0f); - break; - } - } - } - - bool Item::frames_deserialize(const std::string& string, Type type, int start, std::set& indices, - std::string* errorString) - { - XMLDocument document{}; - - if (document.Parse(string.c_str()) == XML_SUCCESS) - { - if (!document.FirstChildElement("Frame")) - { - if (errorString) *errorString = "No valid frame(s)."; - return false; - } - - int count{}; - for (auto element = document.FirstChildElement("Frame"); element; element = element->NextSiblingElement("Frame")) - { - auto index = start + count; - frames.insert(frames.begin() + start + count, Frame(element, type)); - indices.insert(index); - count++; - } - - return true; - } - else if (errorString) - *errorString = document.ErrorStr(); - - return false; - } - - Animation::Animation() = default; - - Animation::Animation(XMLElement* element) - { - int id{}; - - xml::query_string_attribute(element, "Name", &name); - element->QueryIntAttribute("FrameNum", &frameNum); - element->QueryBoolAttribute("Loop", &isLoop); - - if (auto rootAnimationElement = element->FirstChildElement("RootAnimation")) - rootAnimation = Item(rootAnimationElement, ROOT); - - if (auto layerAnimationsElement = element->FirstChildElement("LayerAnimations")) - { - for (auto child = layerAnimationsElement->FirstChildElement("LayerAnimation"); child; - child = child->NextSiblingElement("LayerAnimation")) - { - layerAnimations[id] = Item(child, LAYER, &id); - layerOrder.push_back(id); - } - } - - if (auto nullAnimationsElement = element->FirstChildElement("NullAnimations")) - { - for (auto child = nullAnimationsElement->FirstChildElement("NullAnimation"); child; - child = child->NextSiblingElement("NullAnimation")) - nullAnimations[id] = Item(child, NULL_, &id); - } - - if (auto triggersElement = element->FirstChildElement("Triggers")) triggers = Item(triggersElement, TRIGGER); - } - - Item* Animation::item_get(Type type, int id) - { - switch (type) - { - case ROOT: - return &rootAnimation; - case LAYER: - return unordered_map::find(layerAnimations, id); - case NULL_: - return map::find(nullAnimations, id); - case TRIGGER: - return &triggers; - default: - return nullptr; - } - return nullptr; - } - - void Animation::item_remove(Type type, int id) - { - switch (type) - { - case LAYER: - layerAnimations.erase(id); - for (auto [i, value] : std::views::enumerate(layerOrder)) - if (value == id) layerOrder.erase(layerOrder.begin() + i); - break; - case NULL_: - nullAnimations.erase(id); - break; - case ROOT: - case TRIGGER: - default: - break; - } - } - - void Animation::serialize(XMLDocument& document, XMLElement* parent) - { - auto element = document.NewElement("Animation"); - element->SetAttribute("Name", name.c_str()); - element->SetAttribute("FrameNum", frameNum); - element->SetAttribute("Loop", isLoop); - - rootAnimation.serialize(document, element, ROOT); - - auto layerAnimationsElement = document.NewElement("LayerAnimations"); - for (auto& i : layerOrder) - { - Item& layerAnimation = layerAnimations.at(i); - layerAnimation.serialize(document, layerAnimationsElement, LAYER, i); - } - element->InsertEndChild(layerAnimationsElement); - - auto nullAnimationsElement = document.NewElement("NullAnimations"); - for (auto& [id, nullAnimation] : nullAnimations) - nullAnimation.serialize(document, nullAnimationsElement, NULL_, id); - element->InsertEndChild(nullAnimationsElement); - - triggers.serialize(document, element, TRIGGER); - - parent->InsertEndChild(element); - } - - int Animation::length() - { - int length{}; - - if (int rootAnimationLength = rootAnimation.length(ROOT); rootAnimationLength > length) - length = rootAnimationLength; - - for (auto& layerAnimation : layerAnimations | std::views::values) - if (int layerAnimationLength = layerAnimation.length(LAYER); layerAnimationLength > length) - length = layerAnimationLength; - - for (auto& nullAnimation : nullAnimations | std::views::values) - if (int nullAnimationLength = nullAnimation.length(NULL_); nullAnimationLength > length) - length = nullAnimationLength; - - if (int triggersLength = triggers.length(TRIGGER); triggersLength > length) length = triggersLength; - - return length; - } - - std::string Animation::to_string() - { - XMLDocument document{}; - - auto* element = document.NewElement("Animation"); - document.InsertFirstChild(element); - - element->SetAttribute("Name", name.c_str()); - element->SetAttribute("FrameNum", frameNum); - element->SetAttribute("Loop", isLoop); - - rootAnimation.serialize(document, element, ROOT); - - auto layerAnimationsElement = document.NewElement("LayerAnimations"); - for (auto& i : layerOrder) - { - Item& layerAnimation = layerAnimations.at(i); - layerAnimation.serialize(document, layerAnimationsElement, LAYER, i); - } - element->InsertEndChild(layerAnimationsElement); - - auto nullAnimationsElement = document.NewElement("NullAnimations"); - for (auto& [id, nullAnimation] : nullAnimations) - nullAnimation.serialize(document, nullAnimationsElement, NULL_, id); - element->InsertEndChild(nullAnimationsElement); - - triggers.serialize(document, element, TRIGGER); - - XMLPrinter printer; - document.Print(&printer); - return std::string(printer.CStr()); - } - - vec4 Animation::rect(bool isRootTransform) - { - f32 minX = std::numeric_limits::infinity(); - f32 minY = std::numeric_limits::infinity(); - f32 maxX = -std::numeric_limits::infinity(); - f32 maxY = -std::numeric_limits::infinity(); - bool any = false; - - constexpr ivec2 CORNERS[4] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; - - for (float t = 0.0f; t < (float)frameNum; t += 1.0f) - { - mat4 transform(1.0f); - - if (isRootTransform) - { - auto root = rootAnimation.frame_generate(t, anm2::ROOT); - transform *= math::quad_model_parent_get(root.position, {}, math::percent_to_unit(root.scale), root.rotation); - } - - for (auto& [id, layerAnimation] : layerAnimations) - { - auto frame = layerAnimation.frame_generate(t, anm2::LAYER); - - if (frame.size == vec2() || !frame.isVisible) continue; - - auto layerTransform = transform * math::quad_model_get(frame.size, frame.position, frame.pivot, - math::percent_to_unit(frame.scale), frame.rotation); - for (auto& corner : CORNERS) - { - vec4 world = layerTransform * vec4(corner, 0.0f, 1.0f); - minX = std::min(minX, world.x); - minY = std::min(minY, world.y); - maxX = std::max(maxX, world.x); - maxY = std::max(maxY, world.y); - any = true; - } - } - } - - if (!any) return vec4(-1.0f); - return {minX, minY, maxX - minX, maxY - minY}; - } - - Animations::Animations() = default; - - Animations::Animations(XMLElement* element) - { - xml::query_string_attribute(element, "DefaultAnimation", &defaultAnimation); - - for (auto child = element->FirstChildElement("Animation"); child; child = child->NextSiblingElement("Animation")) - items.push_back(Animation(child)); - } - - void Animations::serialize(XMLDocument& document, XMLElement* parent) - { - auto element = document.NewElement("Animations"); - element->SetAttribute("DefaultAnimation", defaultAnimation.c_str()); - for (auto& animation : items) - animation.serialize(document, element); - parent->InsertEndChild(element); - } - - int Animations::length() - { - int length{}; - - for (auto& animation : items) - if (int animationLength = animation.length(); animationLength > length) length = animationLength; - - return length; - } - - int Animations::merge(int target, std::set& sources, merge::Type type, bool isDeleteAfter) - { - Animation& animation = items.at(target); - - if (!animation.name.ends_with(MERGED_STRING)) animation.name = animation.name + " " + MERGED_STRING; - - auto merge_item = [&](Item& destination, Item& source) - { - switch (type) - { - case merge::APPEND: - destination.frames.insert(destination.frames.end(), source.frames.begin(), source.frames.end()); - break; - case merge::PREPEND: - destination.frames.insert(destination.frames.begin(), source.frames.begin(), source.frames.end()); - break; - case merge::REPLACE: - if (destination.frames.size() < source.frames.size()) destination.frames.resize(source.frames.size()); - for (int i = 0; i < (int)source.frames.size(); i++) - destination.frames[i] = source.frames[i]; - break; - case merge::IGNORE: - default: - break; - } - }; - - for (auto& i : sources) - { - if (i == target) continue; - if (i < 0 || i >= (int)items.size()) continue; - - auto& source = items.at(i); - - merge_item(animation.rootAnimation, source.rootAnimation); - - for (auto& [id, layerAnimation] : source.layerAnimations) - { - if (!animation.layerAnimations.contains(id)) - { - animation.layerAnimations[id] = layerAnimation; - animation.layerOrder.emplace_back(id); - } - merge_item(animation.layerAnimations[id], layerAnimation); - } - - for (auto& [id, nullAnimation] : source.nullAnimations) - { - if (!animation.nullAnimations.contains(id)) animation.nullAnimations[id] = nullAnimation; - merge_item(animation.nullAnimations[id], nullAnimation); - } - - merge_item(animation.triggers, source.triggers); - } - - if (isDeleteAfter) - { - for (auto& source : std::ranges::reverse_view(sources)) - { - if (source == target) continue; - items.erase(items.begin() + source); - } - } - - int finalIndex = target; - - if (isDeleteAfter) - { - int numDeletedBefore = 0; - for (auto& idx : sources) - { - if (idx == target) continue; - if (idx >= 0 && idx < target) ++numDeletedBefore; - } - finalIndex -= numDeletedBefore; - } - - return finalIndex; - } - - bool Animations::animations_deserialize(const std::string& string, int start, std::set& indices, - std::string* errorString) - { - XMLDocument document{}; - - if (document.Parse(string.c_str()) == XML_SUCCESS) - { - if (!document.FirstChildElement("Animation")) - { - if (errorString) *errorString = "No valid animation(s)."; - return false; - } - - int count{}; - for (auto element = document.FirstChildElement("Animation"); element; - element = element->NextSiblingElement("Animation")) - { - auto index = start + count; - items.insert(items.begin() + start + count, Animation(element)); - indices.insert(index); - count++; - } - - return true; - } - else if (errorString) - *errorString = document.ErrorStr(); - - return false; - } - - Anm2::Anm2() - { - info.createdOn = time::get("%d-%B-%Y %I:%M:%S"); - } - - bool Anm2::serialize(const std::string& path, std::string* errorString) - { - XMLDocument document; - - auto* element = document.NewElement("AnimatedActor"); - document.InsertFirstChild(element); - - info.serialize(document, element); - content.serialize(document, element); - animations.serialize(document, element); - - if (document.SaveFile(path.c_str()) != XML_SUCCESS) - { - if (errorString) *errorString = document.ErrorStr(); - return false; - } - return true; - } - - std::string Anm2::to_string() - { - XMLDocument document; - - auto* element = document.NewElement("AnimatedActor"); - document.InsertFirstChild(element); - - info.serialize(document, element); - content.serialize(document, element); - animations.serialize(document, element); - - XMLPrinter printer; - document.Print(&printer); - return std::string(printer.CStr()); - } - - Anm2::Anm2(const std::string& path, std::string* errorString) - { - XMLDocument document; - - if (document.LoadFile(path.c_str()) != XML_SUCCESS) - { - if (errorString) *errorString = document.ErrorStr(); - return; - } - - WorkingDirectory workingDirectory(path, true); - - const XMLElement* element = document.RootElement(); - - if (auto infoElement = element->FirstChildElement("Info")) info = Info((XMLElement*)infoElement); - - if (auto contentElement = element->FirstChildElement("Content")) content = Content((XMLElement*)contentElement); - - if (auto animationsElement = element->FirstChildElement("Animations")) - animations = Animations((XMLElement*)animationsElement); - } - - uint64_t Anm2::hash() - { - return std::hash{}(to_string()); - } - - Animation* Anm2::animation_get(Reference reference) - { - return vector::find(animations.items, reference.animationIndex); - } - - Item* Anm2::item_get(Reference reference) - { - if (Animation* animation = animation_get(reference)) - { - switch (reference.itemType) - { - case ROOT: - return &animation->rootAnimation; - case LAYER: - return unordered_map::find(animation->layerAnimations, reference.itemID); - case NULL_: - return map::find(animation->nullAnimations, reference.itemID); - case TRIGGER: - return &animation->triggers; - default: - return nullptr; - } - } - return nullptr; - } - - Frame* Anm2::frame_get(Reference reference) - { - Item* item = item_get(reference); - if (!item) return nullptr; - return vector::find(item->frames, reference.frameIndex); - return nullptr; - } - - bool Anm2::spritesheet_add(const std::string& directory, const std::string& path, int& id) - { - Spritesheet spritesheet(directory, path); - if (!spritesheet.is_valid()) return false; - id = map::next_id_get(content.spritesheets); - content.spritesheets[id] = std::move(spritesheet); - return true; - } - - void Anm2::spritesheet_remove(int id) - { - content.spritesheets.erase(id); - } - - Spritesheet* Anm2::spritesheet_get(int id) - { - return map::find(content.spritesheets, id); - } - - std::set Anm2::spritesheets_unused() - { - return content.spritesheets_unused(); - } - - Reference Anm2::layer_add(Reference reference, std::string name, int spritesheetID, locale::Type locale) - { - auto id = reference.itemID == -1 ? map::next_id_get(content.layers) : reference.itemID; - auto& layer = content.layers[id]; - - layer.name = !name.empty() ? name : layer.name; - layer.spritesheetID = content.spritesheets.contains(spritesheetID) ? spritesheetID : 0; - - auto add = [&](Animation* animation, int id) - { - animation->layerAnimations[id] = Item(); - animation->layerOrder.push_back(id); - }; - - if (locale == locale::GLOBAL) - { - for (auto& animation : animations.items) - if (!animation.layerAnimations.contains(id)) add(&animation, id); - } - else if (locale == locale::LOCAL) - { - if (auto animation = animation_get(reference)) - if (!animation->layerAnimations.contains(id)) add(animation, id); - } - - return {reference.animationIndex, LAYER, id}; - } - - Reference Anm2::null_add(Reference reference, std::string name, locale::Type locale) - { - auto id = reference.itemID == -1 ? map::next_id_get(content.nulls) : reference.itemID; - auto& null = content.nulls[id]; - - null.name = !name.empty() ? name : null.name; - - auto add = [&](Animation* animation, int id) { animation->nullAnimations[id] = Item(); }; - - if (locale == locale::GLOBAL) - { - for (auto& animation : animations.items) - if (!animation.nullAnimations.contains(id)) add(&animation, id); - } - else if (locale == locale::LOCAL) - { - if (auto animation = animation_get(reference)) - if (!animation->nullAnimations.contains(id)) add(animation, id); - } - - return {reference.animationIndex, LAYER, id}; - } - - void Anm2::event_add(int& id) - { - content.event_add(id); - } - - std::set Anm2::events_unused(Reference reference) - { - std::set used{}; - std::set unused{}; - - if (auto animation = animation_get(reference); animation) - for (auto& frame : animation->triggers.frames) - used.insert(frame.eventID); - else - for (auto& animation : animations.items) - for (auto& frame : animation.triggers.frames) - used.insert(frame.eventID); - - for (auto& id : content.events | std::views::keys) - if (!used.contains(id)) unused.insert(id); - - return unused; - } - - std::set Anm2::layers_unused(Reference reference) - { - std::set used{}; - std::set unused{}; - - if (auto animation = animation_get(reference); animation) - for (auto& id : animation->layerAnimations | std::views::keys) - used.insert(id); - else - for (auto& animation : animations.items) - for (auto& id : animation.layerAnimations | std::views::keys) - used.insert(id); - - for (auto& id : content.layers | std::views::keys) - if (!used.contains(id)) unused.insert(id); - - return unused; - } - - std::set Anm2::nulls_unused(Reference reference) - { - std::set used{}; - std::set unused{}; - - if (auto animation = animation_get(reference); animation) - for (auto& id : animation->nullAnimations | std::views::keys) - used.insert(id); - else - for (auto& animation : animations.items) - for (auto& id : animation.nullAnimations | std::views::keys) - used.insert(id); - - for (auto& id : content.nulls | std::views::keys) - if (!used.contains(id)) unused.insert(id); - - return unused; - } - - std::vector Anm2::event_names_get() - { - std::vector names{}; - for (auto& event : content.events | std::views::values) - names.push_back(event.name); - return names; - } - - std::vector Anm2::animation_names_get() - { - std::vector names{}; - for (auto& animation : animations.items) - names.push_back(animation.name); - return names; - } - - std::vector Anm2::spritesheet_names_get() - { - std::vector names{}; - for (auto& [id, spritesheet] : content.spritesheets) - names.push_back(std::format(SPRITESHEET_FORMAT, id, spritesheet.path.c_str())); - return names; - } - - void Anm2::bake(Reference reference, int interval, bool isRoundScale, bool isRoundRotation) - { - Item* item = item_get(reference); - if (!item) return; - - Frame* frame = frame_get(reference); - if (!frame) return; - - if (frame->delay == FRAME_DELAY_MIN) return; - - Reference referenceNext = reference; - referenceNext.frameIndex = reference.frameIndex + 1; - - Frame* frameNext = frame_get(referenceNext); - if (!frameNext) frameNext = frame; - - Frame baseFrame = *frame; - Frame baseFrameNext = *frameNext; - - int delay{}; - int index = reference.frameIndex; - - while (delay < baseFrame.delay) - { - float interpolation = (float)delay / baseFrame.delay; - - Frame baked = baseFrame; - baked.delay = std::min(interval, baseFrame.delay - delay); - baked.isInterpolated = (index == reference.frameIndex) ? baseFrame.isInterpolated : false; - - baked.rotation = glm::mix(baseFrame.rotation, baseFrameNext.rotation, interpolation); - baked.position = glm::mix(baseFrame.position, baseFrameNext.position, interpolation); - baked.scale = glm::mix(baseFrame.scale, baseFrameNext.scale, interpolation); - baked.colorOffset = glm::mix(baseFrame.colorOffset, baseFrameNext.colorOffset, interpolation); - baked.tint = glm::mix(baseFrame.tint, baseFrameNext.tint, interpolation); - - if (isRoundScale) baked.scale = vec2(ivec2(baked.scale)); - if (isRoundRotation) baked.rotation = (int)baked.rotation; - - if (index == reference.frameIndex) - item->frames[index] = baked; - else - item->frames.insert(item->frames.begin() + index, baked); - index++; - - delay += baked.delay; - } - } - - void Anm2::generate_from_grid(Reference reference, ivec2 startPosition, ivec2 size, ivec2 pivot, int columns, - int count, int delay) - { - auto item = item_get(reference); - if (!item) return; - - for (int i = 0; i < count; i++) - { - auto row = i / columns; - auto column = i % columns; - - Frame frame{}; - - frame.delay = delay; - frame.pivot = pivot; - frame.size = size; - frame.crop = startPosition + ivec2(size.x * column, size.y * row); - - item->frames.emplace_back(frame); - } - } -} \ No newline at end of file diff --git a/src/anm2.h b/src/anm2.h deleted file mode 100644 index afcdea9..0000000 --- a/src/anm2.h +++ /dev/null @@ -1,264 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "texture.h" -#include "types.h" - -namespace anm2ed::anm2 -{ - constexpr auto FRAME_NUM_MIN = 1; - constexpr auto FRAME_NUM_MAX = 100000000; - constexpr auto FRAME_DELAY_MIN = 1; - constexpr auto FRAME_DELAY_MAX = FRAME_NUM_MAX; - constexpr auto FPS_MIN = 1; - constexpr auto FPS_MAX = 120; - - constexpr auto MERGED_STRING = "(Merged)"; - - constexpr auto NO_PATH = "(No Path)"; - constexpr auto LAYER_FORMAT = "#{} {} (Spritesheet: #{})"; - constexpr auto NULL_FORMAT = "#{} {}"; - constexpr auto SPRITESHEET_FORMAT_C = "#%d %s"; - constexpr auto SPRITESHEET_FORMAT = "#{} {}"; - - enum Type - { - NONE, - ROOT, - LAYER, - NULL_, - TRIGGER - }; - - class Reference - { - public: - int animationIndex{-1}; - Type itemType{NONE}; - int itemID{-1}; - int frameIndex{-1}; - int frameTime{-1}; - - auto operator<=>(const Reference&) const = default; - }; - - constexpr anm2::Reference REFERENCE_DEFAULT = {-1, anm2::NONE, -1, -1, -1}; - - class Info - { - public: - std::string createdBy{"robot"}; - std::string createdOn{}; - int fps = 30; - int version{}; - - Info(); - Info(tinyxml2::XMLElement*); - void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); - }; - - class Spritesheet - { - public: - std::filesystem::path path{}; - texture::Texture texture; - - Spritesheet(); - Spritesheet(tinyxml2::XMLElement*, int&); - Spritesheet(const std::string&, const std::string& = {}); - bool save(const std::string&, const std::string& = {}); - void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); - void reload(const std::string&); - bool is_valid(); - std::string to_string(int id); - }; - - class Layer - { - public: - std::string name{"New Layer"}; - int spritesheetID{}; - - Layer(); - Layer(tinyxml2::XMLElement*, int&); - void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); - std::string to_string(int); - }; - - class Null - { - public: - std::string name{"New Null"}; - bool isShowRect{}; - - Null(); - Null(tinyxml2::XMLElement*, int&); - void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); - std::string to_string(int); - }; - - class Event - { - public: - std::string name{"New Event"}; - - Event(); - Event(tinyxml2::XMLElement*, int&); - void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); - std::string to_string(int); - }; - - struct Content - { - std::map spritesheets{}; - std::map layers{}; - std::map nulls{}; - std::map events{}; - - Content(); - - void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); - Content(tinyxml2::XMLElement*); - bool spritesheet_add(const std::string&, const std::string&, int&); - void spritesheet_remove(int&); - std::set spritesheets_unused(); - void layer_add(int&); - void null_add(int&); - void event_add(int&); - bool spritesheets_deserialize(const std::string&, const std::string&, types::merge::Type, std::string* = nullptr); - bool layers_deserialize(const std::string&, types::merge::Type, std::string* = nullptr); - bool nulls_deserialize(const std::string&, types::merge::Type, std::string* = nullptr); - bool events_deserialize(const std::string&, types::merge::Type, std::string* = nullptr); - }; - -#define MEMBERS \ - X(isVisible, bool, true) \ - X(isInterpolated, bool, false) \ - X(rotation, float, 0.0f) \ - X(delay, int, FRAME_DELAY_MIN) \ - X(atFrame, int, -1) \ - X(eventID, int, -1) \ - X(pivot, glm::vec2, {}) \ - X(crop, glm::vec2, {}) \ - X(position, glm::vec2, {}) \ - X(size, glm::vec2, {}) \ - X(scale, glm::vec2, glm::vec2(100.0f)) \ - X(colorOffset, glm::vec3, types::color::TRANSPARENT) \ - X(tint, glm::vec4, types::color::WHITE) - - class Frame - { - public: -#define X(name, type, ...) type name = __VA_ARGS__; - MEMBERS -#undef X - - Frame(); - Frame(tinyxml2::XMLElement*, Type); - std::string to_string(Type type); - void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, Type); - void shorten(); - void extend(); - }; - - struct FrameChange - { -#define X(name, type, ...) std::optional name{}; - MEMBERS -#undef X - }; - -#undef MEMBERS - - class Item - { - public: - std::vector frames{}; - bool isVisible{true}; - - Item(); - - Item(tinyxml2::XMLElement*, Type, int* = nullptr); - void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, Type, int = -1); - int length(Type); - Frame frame_generate(float, Type); - void frames_change(anm2::FrameChange&, types::frame_change::Type, int, int = 0); - bool frames_deserialize(const std::string&, Type, int, std::set&, std::string*); - }; - - class Animation - { - public: - std::string name{"New Animation"}; - int frameNum{FRAME_NUM_MIN}; - bool isLoop{true}; - Item rootAnimation; - std::unordered_map layerAnimations{}; - std::vector layerOrder{}; - std::map nullAnimations{}; - Item triggers; - - Animation(); - Animation(tinyxml2::XMLElement*); - Item* item_get(Type, int = -1); - void item_remove(Type, int = -1); - void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); - int length(); - glm::vec4 rect(bool); - std::string to_string(); - }; - - struct Animations - { - std::string defaultAnimation{}; - std::vector items{}; - - Animations(); - - Animations(tinyxml2::XMLElement*); - void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); - int length(); - int merge(int, std::set&, types::merge::Type = types::merge::APPEND, bool = true); - bool animations_deserialize(const std::string&, int, std::set&, std::string* = nullptr); - }; - - class Anm2 - { - public: - Info info{}; - Content content{}; - Animations animations{}; - - Anm2(); - bool serialize(const std::string&, std::string* = nullptr); - std::string to_string(); - Anm2(const std::string&, std::string* = nullptr); - uint64_t hash(); - Animation* animation_get(Reference); - Item* item_get(Reference); - Frame* frame_get(Reference); - bool spritesheet_add(const std::string&, const std::string&, int&); - Spritesheet* spritesheet_get(int); - void spritesheet_remove(int); - std::set spritesheets_unused(); - int layer_add(); - Reference layer_add(Reference = REFERENCE_DEFAULT, std::string = {}, int = 0, - types::locale::Type = types::locale::GLOBAL); - Reference null_add(Reference = REFERENCE_DEFAULT, std::string = {}, types::locale::Type = types::locale::GLOBAL); - void event_add(int&); - std::set events_unused(Reference = REFERENCE_DEFAULT); - std::set layers_unused(Reference = REFERENCE_DEFAULT); - std::set nulls_unused(Reference = REFERENCE_DEFAULT); - std::vector animation_names_get(); - std::vector spritesheet_names_get(); - std::vector event_names_get(); - void bake(Reference, int = 1, bool = true, bool = true); - void generate_from_grid(Reference, glm::ivec2, glm::ivec2, glm::ivec2, int, int, int); - }; -} diff --git a/src/anm2/animation.cpp b/src/anm2/animation.cpp new file mode 100644 index 0000000..a275dbc --- /dev/null +++ b/src/anm2/animation.cpp @@ -0,0 +1,206 @@ +#include "animation.h" + +#include "map_.h" +#include "math_.h" +#include "unordered_map_.h" +#include "xml_.h" +#include + +using namespace anm2ed::util; +using namespace glm; + +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Animation::Animation(XMLElement* element) + { + int id{}; + + xml::query_string_attribute(element, "Name", &name); + element->QueryIntAttribute("FrameNum", &frameNum); + element->QueryBoolAttribute("Loop", &isLoop); + + if (auto rootAnimationElement = element->FirstChildElement("RootAnimation")) + rootAnimation = Item(rootAnimationElement, ROOT); + + if (auto layerAnimationsElement = element->FirstChildElement("LayerAnimations")) + { + for (auto child = layerAnimationsElement->FirstChildElement("LayerAnimation"); child; + child = child->NextSiblingElement("LayerAnimation")) + { + layerAnimations[id] = Item(child, LAYER, &id); + layerOrder.push_back(id); + } + } + + if (auto nullAnimationsElement = element->FirstChildElement("NullAnimations")) + for (auto child = nullAnimationsElement->FirstChildElement("NullAnimation"); child; + child = child->NextSiblingElement("NullAnimation")) + nullAnimations[id] = Item(child, NULL_, &id); + + if (auto triggersElement = element->FirstChildElement("Triggers")) triggers = Item(triggersElement, TRIGGER); + } + + Item* Animation::item_get(Type type, int id) + { + switch (type) + { + case ROOT: + return &rootAnimation; + case LAYER: + return unordered_map::find(layerAnimations, id); + case NULL_: + return map::find(nullAnimations, id); + case TRIGGER: + return &triggers; + default: + return nullptr; + } + return nullptr; + } + + void Animation::item_remove(Type type, int id) + { + switch (type) + { + case LAYER: + layerAnimations.erase(id); + for (auto [i, value] : std::views::enumerate(layerOrder)) + if (value == id) layerOrder.erase(layerOrder.begin() + i); + break; + case NULL_: + nullAnimations.erase(id); + break; + case ROOT: + case TRIGGER: + default: + break; + } + } + + void Animation::serialize(XMLDocument& document, XMLElement* parent) + { + auto element = document.NewElement("Animation"); + element->SetAttribute("Name", name.c_str()); + element->SetAttribute("FrameNum", frameNum); + element->SetAttribute("Loop", isLoop); + + rootAnimation.serialize(document, element, ROOT); + + auto layerAnimationsElement = document.NewElement("LayerAnimations"); + for (auto& i : layerOrder) + { + Item& layerAnimation = layerAnimations.at(i); + layerAnimation.serialize(document, layerAnimationsElement, LAYER, i); + } + element->InsertEndChild(layerAnimationsElement); + + auto nullAnimationsElement = document.NewElement("NullAnimations"); + for (auto& [id, nullAnimation] : nullAnimations) + nullAnimation.serialize(document, nullAnimationsElement, NULL_, id); + element->InsertEndChild(nullAnimationsElement); + + triggers.serialize(document, element, TRIGGER); + + parent->InsertEndChild(element); + } + + int Animation::length() + { + int length{}; + + if (int rootAnimationLength = rootAnimation.length(ROOT); rootAnimationLength > length) + length = rootAnimationLength; + + for (auto& layerAnimation : layerAnimations | std::views::values) + if (int layerAnimationLength = layerAnimation.length(LAYER); layerAnimationLength > length) + length = layerAnimationLength; + + for (auto& nullAnimation : nullAnimations | std::views::values) + if (int nullAnimationLength = nullAnimation.length(NULL_); nullAnimationLength > length) + length = nullAnimationLength; + + if (int triggersLength = triggers.length(TRIGGER); triggersLength > length) length = triggersLength; + + return length; + } + + std::string Animation::to_string() + { + XMLDocument document{}; + + auto* element = document.NewElement("Animation"); + document.InsertFirstChild(element); + + element->SetAttribute("Name", name.c_str()); + element->SetAttribute("FrameNum", frameNum); + element->SetAttribute("Loop", isLoop); + + rootAnimation.serialize(document, element, ROOT); + + auto layerAnimationsElement = document.NewElement("LayerAnimations"); + for (auto& i : layerOrder) + { + Item& layerAnimation = layerAnimations.at(i); + layerAnimation.serialize(document, layerAnimationsElement, LAYER, i); + } + element->InsertEndChild(layerAnimationsElement); + + auto nullAnimationsElement = document.NewElement("NullAnimations"); + for (auto& [id, nullAnimation] : nullAnimations) + nullAnimation.serialize(document, nullAnimationsElement, NULL_, id); + element->InsertEndChild(nullAnimationsElement); + + triggers.serialize(document, element, TRIGGER); + + XMLPrinter printer; + document.Print(&printer); + return std::string(printer.CStr()); + } + + vec4 Animation::rect(bool isRootTransform) + { + float minX = std::numeric_limits::infinity(); + float minY = std::numeric_limits::infinity(); + float maxX = -std::numeric_limits::infinity(); + float maxY = -std::numeric_limits::infinity(); + bool any = false; + + constexpr ivec2 CORNERS[4] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; + + for (float t = 0.0f; t < (float)frameNum; t += 1.0f) + { + mat4 transform(1.0f); + + if (isRootTransform) + { + auto root = rootAnimation.frame_generate(t, anm2::ROOT); + transform *= math::quad_model_parent_get(root.position, {}, math::percent_to_unit(root.scale), root.rotation); + } + + for (auto& [id, layerAnimation] : layerAnimations) + { + auto frame = layerAnimation.frame_generate(t, anm2::LAYER); + + if (frame.size == vec2() || !frame.isVisible) continue; + + auto layerTransform = transform * math::quad_model_get(frame.size, frame.position, frame.pivot, + math::percent_to_unit(frame.scale), frame.rotation); + for (auto& corner : CORNERS) + { + vec4 world = layerTransform * vec4(corner, 0.0f, 1.0f); + minX = std::min(minX, world.x); + minY = std::min(minY, world.y); + maxX = std::max(maxX, world.x); + maxY = std::max(maxY, world.y); + any = true; + } + } + } + + if (!any) return vec4(-1.0f); + return {minX, minY, maxX - minX, maxY - minY}; + } + +} \ No newline at end of file diff --git a/src/anm2/animation.h b/src/anm2/animation.h new file mode 100644 index 0000000..dc47fc7 --- /dev/null +++ b/src/anm2/animation.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#include "item.h" + +namespace anm2ed::anm2 +{ + constexpr auto FRAME_NUM_MIN = 1; + constexpr auto FRAME_NUM_MAX = FRAME_DELAY_MAX; + + class Animation + { + public: + std::string name{"New Animation"}; + int frameNum{FRAME_NUM_MIN}; + bool isLoop{true}; + Item rootAnimation; + std::unordered_map layerAnimations{}; + std::vector layerOrder{}; + std::map nullAnimations{}; + Item triggers; + + Animation() = default; + Animation(tinyxml2::XMLElement*); + Item* item_get(Type, int = -1); + void item_remove(Type, int = -1); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); + int length(); + glm::vec4 rect(bool); + std::string to_string(); + }; + +} \ No newline at end of file diff --git a/src/anm2/animations.cpp b/src/anm2/animations.cpp new file mode 100644 index 0000000..1ace1bb --- /dev/null +++ b/src/anm2/animations.cpp @@ -0,0 +1,155 @@ +#include "animations.h" + +#include + +#include "xml_.h" + +using namespace tinyxml2; +using namespace anm2ed::types; +using namespace anm2ed::util; + +namespace anm2ed::anm2 +{ + Animations::Animations(XMLElement* element) + { + xml::query_string_attribute(element, "DefaultAnimation", &defaultAnimation); + + for (auto child = element->FirstChildElement("Animation"); child; child = child->NextSiblingElement("Animation")) + items.push_back(Animation(child)); + } + + XMLElement* Animations::to_element(XMLDocument& document) + { + auto element = document.NewElement("Animations"); + element->SetAttribute("DefaultAnimation", defaultAnimation.c_str()); + for (auto& animation : items) + animation.serialize(document, element); + return element; + } + + void Animations::serialize(XMLDocument& document, XMLElement* parent) + { + parent->InsertEndChild(to_element(document)); + } + + int Animations::length() + { + int length{}; + + for (auto& animation : items) + if (int animationLength = animation.length(); animationLength > length) length = animationLength; + + return length; + } + + int Animations::merge(int target, std::set& sources, merge::Type type, bool isDeleteAfter) + { + Animation& animation = items.at(target); + + if (!animation.name.ends_with(MERGED_STRING)) animation.name = animation.name + " " + MERGED_STRING; + + auto merge_item = [&](Item& destination, Item& source) + { + switch (type) + { + case merge::APPEND: + destination.frames.insert(destination.frames.end(), source.frames.begin(), source.frames.end()); + break; + case merge::PREPEND: + destination.frames.insert(destination.frames.begin(), source.frames.begin(), source.frames.end()); + break; + case merge::REPLACE: + if (destination.frames.size() < source.frames.size()) destination.frames.resize(source.frames.size()); + for (int i = 0; i < (int)source.frames.size(); i++) + destination.frames[i] = source.frames[i]; + break; + case merge::IGNORE: + default: + break; + } + }; + + for (auto& i : sources) + { + if (i == target) continue; + if (i < 0 || i >= (int)items.size()) continue; + + auto& source = items.at(i); + + merge_item(animation.rootAnimation, source.rootAnimation); + + for (auto& [id, layerAnimation] : source.layerAnimations) + { + if (!animation.layerAnimations.contains(id)) + { + animation.layerAnimations[id] = layerAnimation; + animation.layerOrder.emplace_back(id); + } + merge_item(animation.layerAnimations[id], layerAnimation); + } + + for (auto& [id, nullAnimation] : source.nullAnimations) + { + if (!animation.nullAnimations.contains(id)) animation.nullAnimations[id] = nullAnimation; + merge_item(animation.nullAnimations[id], nullAnimation); + } + + merge_item(animation.triggers, source.triggers); + } + + if (isDeleteAfter) + { + for (auto& source : std::ranges::reverse_view(sources)) + { + if (source == target) continue; + items.erase(items.begin() + source); + } + } + + int finalIndex = target; + + if (isDeleteAfter) + { + int numDeletedBefore = 0; + for (auto& idx : sources) + { + if (idx == target) continue; + if (idx >= 0 && idx < target) ++numDeletedBefore; + } + finalIndex -= numDeletedBefore; + } + + return finalIndex; + } + + bool Animations::animations_deserialize(const std::string& string, int start, std::set& indices, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + if (!document.FirstChildElement("Animation")) + { + if (errorString) *errorString = "No valid animation(s)."; + return false; + } + + int count{}; + for (auto element = document.FirstChildElement("Animation"); element; + element = element->NextSiblingElement("Animation")) + { + auto index = start + count; + items.insert(items.begin() + start + count, Animation(element)); + indices.insert(index); + count++; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } +} \ No newline at end of file diff --git a/src/anm2/animations.h b/src/anm2/animations.h new file mode 100644 index 0000000..ce377b2 --- /dev/null +++ b/src/anm2/animations.h @@ -0,0 +1,22 @@ +#pragma once + +#include "animation.h" + +namespace anm2ed::anm2 +{ + constexpr auto MERGED_STRING = "(Merged)"; + + struct Animations + { + std::string defaultAnimation{}; + std::vector items{}; + + Animations() = default; + Animations(tinyxml2::XMLElement*); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&); + int length(); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); + int merge(int, std::set&, types::merge::Type = types::merge::APPEND, bool = true); + bool animations_deserialize(const std::string&, int, std::set&, std::string* = nullptr); + }; +} \ No newline at end of file diff --git a/src/anm2/anm2.cpp b/src/anm2/anm2.cpp new file mode 100644 index 0000000..0b53b9c --- /dev/null +++ b/src/anm2/anm2.cpp @@ -0,0 +1,376 @@ +#include "anm2.h" + +#include + +#include "filesystem_.h" +#include "map_.h" +#include "time_.h" +#include "unordered_map_.h" +#include "vector_.h" + +using namespace tinyxml2; +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace glm; + +namespace anm2ed::anm2 +{ + Anm2::Anm2() + { + info.createdOn = time::get("%d-%B-%Y %I:%M:%S"); + } + + bool Anm2::serialize(const std::string& path, std::string* errorString) + { + XMLDocument document; + + auto* element = document.NewElement("AnimatedActor"); + document.InsertFirstChild(element); + + info.serialize(document, element); + content.serialize(document, element); + animations.serialize(document, element); + + if (document.SaveFile(path.c_str()) != XML_SUCCESS) + { + if (errorString) *errorString = document.ErrorStr(); + return false; + } + return true; + } + + std::string Anm2::to_string() + { + XMLDocument document; + + auto* element = document.NewElement("AnimatedActor"); + document.InsertFirstChild(element); + + info.serialize(document, element); + content.serialize(document, element); + animations.serialize(document, element); + + XMLPrinter printer; + document.Print(&printer); + return std::string(printer.CStr()); + } + + Anm2::Anm2(const std::string& path, std::string* errorString) + { + XMLDocument document; + + if (document.LoadFile(path.c_str()) != XML_SUCCESS) + { + if (errorString) *errorString = document.ErrorStr(); + return; + } + + filesystem::WorkingDirectory workingDirectory(path, true); + + const XMLElement* element = document.RootElement(); + + if (auto infoElement = element->FirstChildElement("Info")) info = Info((XMLElement*)infoElement); + if (auto contentElement = element->FirstChildElement("Content")) content = Content((XMLElement*)contentElement); + if (auto animationsElement = element->FirstChildElement("Animations")) + animations = Animations((XMLElement*)animationsElement); + } + + uint64_t Anm2::hash() + { + return std::hash{}(to_string()); + } + + Animation* Anm2::animation_get(Reference reference) + { + return vector::find(animations.items, reference.animationIndex); + } + + std::vector Anm2::animation_names_get() + { + std::vector names{}; + for (auto& animation : animations.items) + names.push_back(animation.name); + return names; + } + + Item* Anm2::item_get(Reference reference) + { + if (Animation* animation = animation_get(reference)) + { + switch (reference.itemType) + { + case ROOT: + return &animation->rootAnimation; + case LAYER: + return unordered_map::find(animation->layerAnimations, reference.itemID); + case NULL_: + return map::find(animation->nullAnimations, reference.itemID); + case TRIGGER: + return &animation->triggers; + default: + return nullptr; + } + } + return nullptr; + } + + Frame* Anm2::frame_get(Reference reference) + { + Item* item = item_get(reference); + if (!item) return nullptr; + return vector::find(item->frames, reference.frameIndex); + return nullptr; + } + + bool Anm2::spritesheet_add(const std::string& directory, const std::string& path, int& id) + { + Spritesheet spritesheet(directory, path); + if (!spritesheet.is_valid()) return false; + id = map::next_id_get(content.spritesheets); + content.spritesheets[id] = std::move(spritesheet); + return true; + } + + void Anm2::spritesheet_remove(int id) + { + content.spritesheets.erase(id); + } + + Spritesheet* Anm2::spritesheet_get(int id) + { + return map::find(content.spritesheets, id); + } + + std::set Anm2::spritesheets_unused() + { + return content.spritesheets_unused(); + } + + std::vector Anm2::spritesheet_names_get() + { + std::vector names{}; + for (auto& [id, spritesheet] : content.spritesheets) + names.push_back(std::format(SPRITESHEET_FORMAT, id, spritesheet.path.c_str())); + return names; + } + + Reference Anm2::layer_add(Reference reference, std::string name, int spritesheetID, locale::Type locale) + { + auto id = reference.itemID == -1 ? map::next_id_get(content.layers) : reference.itemID; + auto& layer = content.layers[id]; + + layer.name = !name.empty() ? name : layer.name; + layer.spritesheetID = content.spritesheets.contains(spritesheetID) ? spritesheetID : 0; + + auto add = [&](Animation* animation, int id) + { + animation->layerAnimations[id] = Item(); + animation->layerOrder.push_back(id); + }; + + if (locale == locale::GLOBAL) + { + for (auto& animation : animations.items) + if (!animation.layerAnimations.contains(id)) add(&animation, id); + } + else if (locale == locale::LOCAL) + { + if (auto animation = animation_get(reference)) + if (!animation->layerAnimations.contains(id)) add(animation, id); + } + + return {reference.animationIndex, LAYER, id}; + } + + Reference Anm2::null_add(Reference reference, std::string name, locale::Type locale) + { + auto id = reference.itemID == -1 ? map::next_id_get(content.nulls) : reference.itemID; + auto& null = content.nulls[id]; + + null.name = !name.empty() ? name : null.name; + + auto add = [&](Animation* animation, int id) { animation->nullAnimations[id] = Item(); }; + + if (locale == locale::GLOBAL) + { + for (auto& animation : animations.items) + if (!animation.nullAnimations.contains(id)) add(&animation, id); + } + else if (locale == locale::LOCAL) + { + if (auto animation = animation_get(reference)) + if (!animation->nullAnimations.contains(id)) add(animation, id); + } + + return {reference.animationIndex, LAYER, id}; + } + + void Anm2::event_add(int& id) + { + content.event_add(id); + } + + std::set Anm2::events_unused(Reference reference) + { + std::set used{}; + std::set unused{}; + + if (auto animation = animation_get(reference); animation) + for (auto& frame : animation->triggers.frames) + used.insert(frame.eventID); + else + for (auto& animation : animations.items) + for (auto& frame : animation.triggers.frames) + used.insert(frame.eventID); + + for (auto& id : content.events | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + std::set Anm2::layers_unused(Reference reference) + { + std::set used{}; + std::set unused{}; + + if (auto animation = animation_get(reference); animation) + for (auto& id : animation->layerAnimations | std::views::keys) + used.insert(id); + else + for (auto& animation : animations.items) + for (auto& id : animation.layerAnimations | std::views::keys) + used.insert(id); + + for (auto& id : content.layers | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + std::set Anm2::nulls_unused(Reference reference) + { + std::set used{}; + std::set unused{}; + + if (auto animation = animation_get(reference); animation) + for (auto& id : animation->nullAnimations | std::views::keys) + used.insert(id); + else + for (auto& animation : animations.items) + for (auto& id : animation.nullAnimations | std::views::keys) + used.insert(id); + + for (auto& id : content.nulls | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + std::vector Anm2::event_names_get() + { + std::vector names{}; + for (auto& event : content.events | std::views::values) + names.push_back(event.name); + return names; + } + + bool Anm2::sound_add(const std::string& directory, const std::string& path, int& id) + { + id = map::next_id_get(content.sounds); + content.sounds[id] = Sound(directory, path); + return true; + } + + std::set Anm2::sounds_unused() + { + std::set used; + for (auto& event : content.events | std::views::values) + used.insert(event.soundID); + + std::set unused; + for (auto& id : content.sounds | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + std::vector Anm2::sound_names_get() + { + std::vector names{}; + for (auto& [id, sound] : content.sounds) + names.push_back(std::format(SOUND_FORMAT, id, sound.path.c_str())); + return names; + } + + void Anm2::bake(Reference reference, int interval, bool isRoundScale, bool isRoundRotation) + { + Item* item = item_get(reference); + if (!item) return; + + Frame* frame = frame_get(reference); + if (!frame) return; + + if (frame->delay == FRAME_DELAY_MIN) return; + + Reference referenceNext = reference; + referenceNext.frameIndex = reference.frameIndex + 1; + + Frame* frameNext = frame_get(referenceNext); + if (!frameNext) frameNext = frame; + + Frame baseFrame = *frame; + Frame baseFrameNext = *frameNext; + + int delay{}; + int index = reference.frameIndex; + + while (delay < baseFrame.delay) + { + float interpolation = (float)delay / baseFrame.delay; + + Frame baked = baseFrame; + baked.delay = std::min(interval, baseFrame.delay - delay); + baked.isInterpolated = (index == reference.frameIndex) ? baseFrame.isInterpolated : false; + + baked.rotation = glm::mix(baseFrame.rotation, baseFrameNext.rotation, interpolation); + baked.position = glm::mix(baseFrame.position, baseFrameNext.position, interpolation); + baked.scale = glm::mix(baseFrame.scale, baseFrameNext.scale, interpolation); + baked.colorOffset = glm::mix(baseFrame.colorOffset, baseFrameNext.colorOffset, interpolation); + baked.tint = glm::mix(baseFrame.tint, baseFrameNext.tint, interpolation); + + if (isRoundScale) baked.scale = vec2(ivec2(baked.scale)); + if (isRoundRotation) baked.rotation = (int)baked.rotation; + + if (index == reference.frameIndex) + item->frames[index] = baked; + else + item->frames.insert(item->frames.begin() + index, baked); + index++; + + delay += baked.delay; + } + } + + void Anm2::generate_from_grid(Reference reference, ivec2 startPosition, ivec2 size, ivec2 pivot, int columns, + int count, int delay) + { + auto item = item_get(reference); + if (!item) return; + + for (int i = 0; i < count; i++) + { + auto row = i / columns; + auto column = i % columns; + + Frame frame{}; + + frame.delay = delay; + frame.pivot = pivot; + frame.size = size; + frame.crop = startPosition + ivec2(size.x * column, size.y * row); + + item->frames.emplace_back(frame); + } + } +} diff --git a/src/anm2/anm2.h b/src/anm2/anm2.h new file mode 100644 index 0000000..9ce3207 --- /dev/null +++ b/src/anm2/anm2.h @@ -0,0 +1,72 @@ +#pragma once + +#include +#include + +#include "types.h" + +#include "animations.h" +#include "content.h" +#include "info.h" + +namespace anm2ed::anm2 +{ + constexpr auto NO_PATH = "[No Path]"; + + struct Reference + { + int animationIndex{-1}; + Type itemType{NONE}; + int itemID{-1}; + int frameIndex{-1}; + int frameTime{-1}; + + auto operator<=>(const Reference&) const = default; + }; + + constexpr anm2::Reference REFERENCE_DEFAULT = {-1, anm2::NONE, -1, -1, -1}; + + class Anm2 + { + public: + Info info{}; + Content content{}; + Animations animations{}; + + Anm2(); + bool serialize(const std::string&, std::string* = nullptr); + std::string to_string(); + Anm2(const std::string&, std::string* = nullptr); + uint64_t hash(); + Animation* animation_get(Reference); + std::vector animation_names_get(); + + Item* item_get(Reference); + + Frame* frame_get(Reference); + + bool spritesheet_add(const std::string&, const std::string&, int&); + Spritesheet* spritesheet_get(int); + void spritesheet_remove(int); + std::set spritesheets_unused(); + std::vector spritesheet_names_get(); + + int layer_add(); + Reference layer_add(Reference = REFERENCE_DEFAULT, std::string = {}, int = 0, + types::locale::Type = types::locale::GLOBAL); + std::set layers_unused(Reference = REFERENCE_DEFAULT); + + Reference null_add(Reference = REFERENCE_DEFAULT, std::string = {}, types::locale::Type = types::locale::GLOBAL); + std::set nulls_unused(Reference = REFERENCE_DEFAULT); + + bool sound_add(const std::string& directory, const std::string& path, int& id); + std::vector sound_names_get(); + std::set sounds_unused(); + + void event_add(int&); + std::set events_unused(Reference = REFERENCE_DEFAULT); + std::vector event_names_get(); + void bake(Reference, int = 1, bool = true, bool = true); + void generate_from_grid(Reference, glm::ivec2, glm::ivec2, glm::ivec2, int, int, int); + }; +} diff --git a/src/anm2/content.cpp b/src/anm2/content.cpp new file mode 100644 index 0000000..d2ca4f1 --- /dev/null +++ b/src/anm2/content.cpp @@ -0,0 +1,256 @@ +#include "content.h" + +#include + +#include "filesystem_.h" +#include "map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Content::Content(XMLElement* element) + { + int id{}; + + if (auto spritesheetsElement = element->FirstChildElement("Spritesheets")) + for (auto child = spritesheetsElement->FirstChildElement("Spritesheet"); child; + child = child->NextSiblingElement("Spritesheet")) + spritesheets[id] = Spritesheet(child, id); + + if (auto layersElement = element->FirstChildElement("Layers")) + for (auto child = layersElement->FirstChildElement("Layer"); child; child = child->NextSiblingElement("Layer")) + layers[id] = Layer(child, id); + + if (auto nullsElement = element->FirstChildElement("Nulls")) + for (auto child = nullsElement->FirstChildElement("Null"); child; child = child->NextSiblingElement("Null")) + nulls[id] = Null(child, id); + + if (auto eventsElement = element->FirstChildElement("Events")) + for (auto child = eventsElement->FirstChildElement("Event"); child; child = child->NextSiblingElement("Event")) + events[id] = Event(child, id); + } + + void Content::serialize(XMLDocument& document, XMLElement* parent) + { + auto element = document.NewElement("Content"); + + auto spritesheetsElement = document.NewElement("Spritesheets"); + for (auto& [id, spritesheet] : spritesheets) + spritesheet.serialize(document, spritesheetsElement, id); + element->InsertEndChild(spritesheetsElement); + + auto layersElement = document.NewElement("Layers"); + for (auto& [id, layer] : layers) + layer.serialize(document, layersElement, id); + element->InsertEndChild(layersElement); + + auto nullsElement = document.NewElement("Nulls"); + for (auto& [id, null] : nulls) + null.serialize(document, nullsElement, id); + element->InsertEndChild(nullsElement); + + auto eventsElement = document.NewElement("Events"); + for (auto& [id, event] : events) + event.serialize(document, eventsElement, id); + element->InsertEndChild(eventsElement); + + parent->InsertEndChild(element); + } + + std::set Content::spritesheets_unused() + { + std::set used; + for (auto& layer : layers | std::views::values) + if (layer.spritesheetID != -1) used.insert(layer.spritesheetID); + + std::set unused; + for (auto& id : spritesheets | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + void Content::layer_add(int& id) + { + id = map::next_id_get(layers); + layers[id] = Layer(); + } + + void Content::null_add(int& id) + { + id = map::next_id_get(nulls); + nulls[id] = Null(); + } + + void Content::event_add(int& id) + { + id = map::next_id_get(events); + events[id] = Event(); + } + + bool Content::spritesheets_deserialize(const std::string& string, const std::string& directory, merge::Type type, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Spritesheet")) + { + if (errorString) *errorString = "No valid spritesheet(s)."; + return false; + } + + filesystem::WorkingDirectory workingDirectory(directory); + + for (auto element = document.FirstChildElement("Spritesheet"); element; + element = element->NextSiblingElement("Spritesheet")) + { + auto spritesheet = Spritesheet(element, id); + + if (type == merge::APPEND) id = map::next_id_get(spritesheets); + + spritesheets[id] = std::move(spritesheet); + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + + bool Content::layers_deserialize(const std::string& string, merge::Type type, std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Layer")) + { + if (errorString) *errorString = "No valid layer(s)."; + return false; + } + + for (auto element = document.FirstChildElement("Layer"); element; element = element->NextSiblingElement("Layer")) + { + auto layer = Layer(element, id); + + if (type == merge::APPEND) id = map::next_id_get(layers); + + layers[id] = layer; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + + bool Content::nulls_deserialize(const std::string& string, merge::Type type, std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Null")) + { + if (errorString) *errorString = "No valid null(s)."; + return false; + } + + for (auto element = document.FirstChildElement("Null"); element; element = element->NextSiblingElement("Null")) + { + auto layer = Null(element, id); + + if (type == merge::APPEND) id = map::next_id_get(nulls); + + nulls[id] = layer; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + + bool Content::events_deserialize(const std::string& string, merge::Type type, std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Event")) + { + if (errorString) *errorString = "No valid event(s)."; + return false; + } + + for (auto element = document.FirstChildElement("Event"); element; element = element->NextSiblingElement("Event")) + { + auto layer = Event(element, id); + + if (type == merge::APPEND) id = map::next_id_get(events); + + events[id] = layer; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + + bool Content::sounds_deserialize(const std::string& string, const std::string& directory, merge::Type type, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Sound")) + { + if (errorString) *errorString = "No valid sound(s)."; + return false; + } + + filesystem::WorkingDirectory workingDirectory(directory); + + for (auto element = document.FirstChildElement("Sound"); element; element = element->NextSiblingElement("Sound")) + { + auto sound = Sound(element, id); + + if (type == merge::APPEND) id = map::next_id_get(sounds); + + sounds[id] = std::move(sound); + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + +} \ No newline at end of file diff --git a/src/anm2/content.h b/src/anm2/content.h new file mode 100644 index 0000000..e97650b --- /dev/null +++ b/src/anm2/content.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include + +#include "event.h" +#include "layer.h" +#include "null.h" +#include "sound.h" +#include "spritesheet.h" + +#include "types.h" + +namespace anm2ed::anm2 +{ + struct Content + { + std::map spritesheets{}; + std::map layers{}; + std::map nulls{}; + std::map events{}; + std::map sounds{}; + + Content() = default; + + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); + Content(tinyxml2::XMLElement*); + + bool spritesheet_add(const std::string&, const std::string&, int&); + std::set spritesheets_unused(); + void spritesheet_remove(int&); + bool spritesheets_deserialize(const std::string&, const std::string&, types::merge::Type, std::string* = nullptr); + + void layer_add(int&); + bool layers_deserialize(const std::string&, types::merge::Type, std::string* = nullptr); + + void null_add(int&); + bool nulls_deserialize(const std::string&, types::merge::Type, std::string* = nullptr); + + void event_add(int&); + bool events_deserialize(const std::string&, types::merge::Type, std::string* = nullptr); + + void sound_add(int&); + bool sounds_deserialize(const std::string&, const std::string&, types::merge::Type, std::string* = nullptr); + }; +} \ No newline at end of file diff --git a/src/anm2/event.cpp b/src/anm2/event.cpp new file mode 100644 index 0000000..7427897 --- /dev/null +++ b/src/anm2/event.cpp @@ -0,0 +1,36 @@ +#include "event.h" + +#include "xml_.h" + +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Event::Event(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_string_attribute(element, "Name", &name); + } + + XMLElement* Event::to_element(XMLDocument& document, int id) + { + auto element = document.NewElement("Event"); + element->SetAttribute("Id", id); + element->SetAttribute("Name", name.c_str()); + return element; + } + + void Event::serialize(XMLDocument& document, XMLElement* parent, int id) + { + parent->InsertEndChild(to_element(document, id)); + } + + std::string Event::to_string(int id) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, id)); + return xml::document_to_string(document); + } +} \ No newline at end of file diff --git a/src/anm2/event.h b/src/anm2/event.h new file mode 100644 index 0000000..3f23d86 --- /dev/null +++ b/src/anm2/event.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +namespace anm2ed::anm2 +{ + class Event + { + public: + std::string name{"New Event"}; + int soundID{}; + + Event() = default; + Event(tinyxml2::XMLElement*, int&); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, int); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); + std::string to_string(int); + }; +} \ No newline at end of file diff --git a/src/anm2/frame.cpp b/src/anm2/frame.cpp new file mode 100644 index 0000000..0ff462b --- /dev/null +++ b/src/anm2/frame.cpp @@ -0,0 +1,126 @@ +#include "frame.h" + +#include "math_.h" +#include "xml_.h" + +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Frame::Frame(XMLElement* element, Type type) + { + if (type != TRIGGER) + { + element->QueryFloatAttribute("XPosition", &position.x); + element->QueryFloatAttribute("YPosition", &position.y); + if (type == LAYER) + { + element->QueryFloatAttribute("XPivot", &pivot.x); + element->QueryFloatAttribute("YPivot", &pivot.y); + element->QueryFloatAttribute("XCrop", &crop.x); + element->QueryFloatAttribute("YCrop", &crop.y); + element->QueryFloatAttribute("Width", &size.x); + element->QueryFloatAttribute("Height", &size.y); + } + element->QueryFloatAttribute("XScale", &scale.x); + element->QueryFloatAttribute("YScale", &scale.y); + element->QueryIntAttribute("Delay", &delay); + element->QueryBoolAttribute("Visible", &isVisible); + xml::query_color_attribute(element, "RedTint", tint.r); + xml::query_color_attribute(element, "GreenTint", tint.g); + xml::query_color_attribute(element, "BlueTint", tint.b); + xml::query_color_attribute(element, "AlphaTint", tint.a); + xml::query_color_attribute(element, "RedOffset", colorOffset.r); + xml::query_color_attribute(element, "GreenOffset", colorOffset.g); + xml::query_color_attribute(element, "BlueOffset", colorOffset.b); + element->QueryFloatAttribute("Rotation", &rotation); + element->QueryBoolAttribute("Interpolated", &isInterpolated); + } + else + { + element->QueryIntAttribute("EventId", &eventID); + element->QueryIntAttribute("AtFrame", &atFrame); + } + } + + XMLElement* Frame::to_element(XMLDocument& document, Type type) + { + auto element = document.NewElement(type == TRIGGER ? "Trigger" : "Frame"); + + switch (type) + { + case ROOT: + case NULL_: + element->SetAttribute("XPosition", position.x); + element->SetAttribute("YPosition", position.y); + element->SetAttribute("Delay", delay); + element->SetAttribute("Visible", isVisible); + element->SetAttribute("XScale", scale.x); + element->SetAttribute("YScale", scale.y); + element->SetAttribute("RedTint", math::float_to_uint8(tint.r)); + element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); + element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); + element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); + element->SetAttribute("RedOffset", math::float_to_uint8(colorOffset.r)); + element->SetAttribute("GreenOffset", math::float_to_uint8(colorOffset.g)); + element->SetAttribute("BlueOffset", math::float_to_uint8(colorOffset.b)); + element->SetAttribute("Rotation", rotation); + element->SetAttribute("Interpolated", isInterpolated); + break; + case LAYER: + element->SetAttribute("XPosition", position.x); + element->SetAttribute("YPosition", position.y); + element->SetAttribute("XPivot", pivot.x); + element->SetAttribute("YPivot", pivot.y); + element->SetAttribute("XCrop", crop.x); + element->SetAttribute("YCrop", crop.y); + element->SetAttribute("Width", size.x); + element->SetAttribute("Height", size.y); + element->SetAttribute("XScale", scale.x); + element->SetAttribute("YScale", scale.y); + element->SetAttribute("Delay", delay); + element->SetAttribute("Visible", isVisible); + element->SetAttribute("RedTint", math::float_to_uint8(tint.r)); + element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); + element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); + element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); + element->SetAttribute("RedOffset", math::float_to_uint8(colorOffset.r)); + element->SetAttribute("GreenOffset", math::float_to_uint8(colorOffset.g)); + element->SetAttribute("BlueOffset", math::float_to_uint8(colorOffset.b)); + element->SetAttribute("Rotation", rotation); + element->SetAttribute("Interpolated", isInterpolated); + break; + case TRIGGER: + element->SetAttribute("EventId", eventID); + element->SetAttribute("AtFrame", atFrame); + break; + default: + break; + } + + return element; + } + + void Frame::serialize(XMLDocument& document, XMLElement* parent, Type type) + { + parent->InsertEndChild(to_element(document, type)); + } + + std::string Frame::to_string(Type type) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, type)); + return xml::document_to_string(document); + } + + void Frame::shorten() + { + delay = glm::clamp(--delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); + } + + void Frame::extend() + { + delay = glm::clamp(++delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); + } +} \ No newline at end of file diff --git a/src/anm2/frame.h b/src/anm2/frame.h new file mode 100644 index 0000000..b5a3f76 --- /dev/null +++ b/src/anm2/frame.h @@ -0,0 +1,91 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include + +#include "types.h" + +namespace anm2ed::anm2 +{ + constexpr auto FRAME_DELAY_MIN = 1; + constexpr auto FRAME_DELAY_MAX = 100000; + +#define TYPE_LIST \ + X(NONE, "None", "None") \ + X(ROOT, "Root", "RootAnimation") \ + X(LAYER, "Layer", "LayerAnimation") \ + X(NULL_, "Null", "NullAnimation") \ + X(TRIGGER, "Trigger", "Triggers") + + enum Type + { +#define X(symbol, string, animationString) symbol, + TYPE_LIST +#undef X + }; + + constexpr const char* TYPE_STRINGS[] = { +#define X(symbol, string, animationString) string, + TYPE_LIST +#undef X + }; + + constexpr const char* TYPE_ANIMATION_STRINGS[] = { +#define X(symbol, string, animationString) animationString, + TYPE_LIST +#undef X + }; + + enum ChangeType + { + ADD, + SUBTRACT, + ADJUST + }; + +#define MEMBERS \ + X(isVisible, bool, true) \ + X(isInterpolated, bool, false) \ + X(rotation, float, 0.0f) \ + X(delay, int, FRAME_DELAY_MIN) \ + X(atFrame, int, -1) \ + X(eventID, int, -1) \ + X(pivot, glm::vec2, {}) \ + X(crop, glm::vec2, {}) \ + X(position, glm::vec2, {}) \ + X(size, glm::vec2, {}) \ + X(scale, glm::vec2, glm::vec2(100.0f)) \ + X(colorOffset, glm::vec3, types::color::TRANSPARENT) \ + X(tint, glm::vec4, types::color::WHITE) + + class Frame + { + public: +#define X(name, type, ...) type name = __VA_ARGS__; + MEMBERS +#undef X + + Frame() = default; + Frame(tinyxml2::XMLElement*, Type); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, Type); + std::string to_string(Type type); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, Type); + void shorten(); + void extend(); + }; + + struct FrameChange + { +#define X(name, type, ...) std::optional name{}; + MEMBERS +#undef X + }; + +#undef MEMBERS + +} \ No newline at end of file diff --git a/src/anm2/info.cpp b/src/anm2/info.cpp new file mode 100644 index 0000000..2ea0433 --- /dev/null +++ b/src/anm2/info.cpp @@ -0,0 +1,40 @@ +#include "info.h" + +#include "xml_.h" + +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Info::Info(XMLElement* element) + { + if (!element) return; + xml::query_string_attribute(element, "CreatedBy", &createdBy); + xml::query_string_attribute(element, "CreatedOn", &createdOn); + element->QueryIntAttribute("Fps", &fps); + element->QueryIntAttribute("Version", &version); + } + + XMLElement* Info::to_element(XMLDocument& document) + { + auto element = document.NewElement("Info"); + element->SetAttribute("CreatedBy", createdBy.c_str()); + element->SetAttribute("CreatedOn", createdOn.c_str()); + element->SetAttribute("Fps", fps); + element->SetAttribute("Version", version); + return element; + } + + void Info::serialize(XMLDocument& document, XMLElement* parent) + { + parent->InsertEndChild(to_element(document)); + } + + std::string Info::to_string() + { + XMLDocument document{}; + document.InsertEndChild(to_element(document)); + return xml::document_to_string(document); + } +} \ No newline at end of file diff --git a/src/anm2/info.h b/src/anm2/info.h new file mode 100644 index 0000000..c2fd400 --- /dev/null +++ b/src/anm2/info.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +namespace anm2ed::anm2 +{ + constexpr auto FPS_MIN = 1; + constexpr auto FPS_MAX = 120; + + class Info + { + public: + std::string createdBy{"robot"}; + std::string createdOn{}; + int fps = 30; + int version{}; + + Info() = default; + Info(tinyxml2::XMLElement*); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument& document); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); + std::string to_string(); + }; +} \ No newline at end of file diff --git a/src/anm2/item.cpp b/src/anm2/item.cpp new file mode 100644 index 0000000..0b20ca5 --- /dev/null +++ b/src/anm2/item.cpp @@ -0,0 +1,200 @@ +#include "item.h" +#include + +#include "xml_.h" + +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Item::Item(XMLElement* element, Type type, int* id) + { + if (type == LAYER && id) element->QueryIntAttribute("LayerId", id); + if (type == NULL_ && id) element->QueryIntAttribute("NullId", id); + + element->QueryBoolAttribute("Visible", &isVisible); + + for (auto child = type == TRIGGER ? element->FirstChildElement("Trigger") : element->FirstChildElement("Frame"); + child; child = type == TRIGGER ? child->NextSiblingElement("Trigger") : child->NextSiblingElement("Frame")) + frames.push_back(Frame(child, type)); + } + + XMLElement* Item::to_element(XMLDocument& document, Type type, int id) + { + auto element = document.NewElement(TYPE_ANIMATION_STRINGS[type]); + + if (type == LAYER) element->SetAttribute("LayerId", id); + if (type == NULL_) element->SetAttribute("NullId", id); + if (type == LAYER || type == NULL_) element->SetAttribute("Visible", isVisible); + + for (auto& frame : frames) + frame.serialize(document, element, type); + + return element; + } + + void Item::serialize(XMLDocument& document, XMLElement* parent, Type type, int id) + { + parent->InsertEndChild(to_element(document, type, id)); + } + + std::string Item::to_string(Type type, int id) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, type, id)); + return xml::document_to_string(document); + } + + int Item::length(Type type) + { + int length{}; + + if (type == TRIGGER) + for (auto& frame : frames) + length = frame.atFrame > length ? frame.atFrame : length; + else + for (auto& frame : frames) + length += frame.delay; + + return length; + } + + Frame Item::frame_generate(float time, Type type) + { + Frame frame{}; + frame.isVisible = false; + + if (frames.empty()) return frame; + + Frame* frameNext = nullptr; + int delayCurrent = 0; + int delayNext = 0; + + for (auto [i, iFrame] : std::views::enumerate(frames)) + { + if (type == TRIGGER) + { + if ((int)time == iFrame.atFrame) + { + frame = iFrame; + break; + } + } + else + { + frame = iFrame; + + delayNext += frame.delay; + + if (time >= delayCurrent && time < delayNext) + { + if (i + 1 < (int)frames.size()) + frameNext = &frames[i + 1]; + else + frameNext = nullptr; + break; + } + + delayCurrent += frame.delay; + } + } + + if (type != TRIGGER && frame.isInterpolated && frameNext && frame.delay > 1) + { + auto interpolation = (time - delayCurrent) / (delayNext - delayCurrent); + + frame.rotation = glm::mix(frame.rotation, frameNext->rotation, interpolation); + frame.position = glm::mix(frame.position, frameNext->position, interpolation); + frame.scale = glm::mix(frame.scale, frameNext->scale, interpolation); + frame.colorOffset = glm::mix(frame.colorOffset, frameNext->colorOffset, interpolation); + frame.tint = glm::mix(frame.tint, frameNext->tint, interpolation); + } + + return frame; + } + + void Item::frames_change(anm2::FrameChange& change, ChangeType type, int start, int numberFrames) + { + auto useStart = numberFrames > -1 ? start : 0; + auto end = numberFrames > -1 ? start + numberFrames : (int)frames.size(); + end = glm::clamp(end, start, (int)frames.size()); + + for (int i = useStart; i < end; i++) + { + Frame& frame = frames[i]; + + if (change.isVisible) frame.isVisible = *change.isVisible; + if (change.isInterpolated) frame.isInterpolated = *change.isInterpolated; + + switch (type) + { + case ADJUST: + if (change.rotation) frame.rotation = *change.rotation; + if (change.delay) frame.delay = std::max(FRAME_DELAY_MIN, *change.delay); + if (change.crop) frame.crop = *change.crop; + if (change.pivot) frame.pivot = *change.pivot; + if (change.position) frame.position = *change.position; + if (change.size) frame.size = *change.size; + if (change.scale) frame.scale = *change.scale; + if (change.colorOffset) frame.colorOffset = glm::clamp(*change.colorOffset, 0.0f, 1.0f); + if (change.tint) frame.tint = glm::clamp(*change.tint, 0.0f, 1.0f); + break; + + case ADD: + if (change.rotation) frame.rotation += *change.rotation; + if (change.delay) frame.delay = std::max(FRAME_DELAY_MIN, frame.delay + *change.delay); + if (change.crop) frame.crop += *change.crop; + if (change.pivot) frame.pivot += *change.pivot; + if (change.position) frame.position += *change.position; + if (change.size) frame.size += *change.size; + if (change.scale) frame.scale += *change.scale; + if (change.colorOffset) frame.colorOffset = glm::clamp(frame.colorOffset + *change.colorOffset, 0.0f, 1.0f); + if (change.tint) frame.tint = glm::clamp(frame.tint + *change.tint, 0.0f, 1.0f); + break; + + case SUBTRACT: + if (change.rotation) frame.rotation -= *change.rotation; + if (change.delay) frame.delay = std::max(FRAME_DELAY_MIN, frame.delay - *change.delay); + if (change.crop) frame.crop -= *change.crop; + if (change.pivot) frame.pivot -= *change.pivot; + if (change.position) frame.position -= *change.position; + if (change.size) frame.size -= *change.size; + if (change.scale) frame.scale -= *change.scale; + if (change.colorOffset) frame.colorOffset = glm::clamp(frame.colorOffset - *change.colorOffset, 0.0f, 1.0f); + if (change.tint) frame.tint = glm::clamp(frame.tint - *change.tint, 0.0f, 1.0f); + break; + } + } + } + + bool Item::frames_deserialize(const std::string& string, Type type, int start, std::set& indices, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + if (!document.FirstChildElement("Frame")) + { + if (errorString) *errorString = "No valid frame(s)."; + return false; + } + + int count{}; + for (auto element = document.FirstChildElement("Frame"); element; element = element->NextSiblingElement("Frame")) + { + auto index = start + count; + frames.insert(frames.begin() + start + count, Frame(element, type)); + indices.insert(index); + count++; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } +} \ No newline at end of file diff --git a/src/anm2/item.h b/src/anm2/item.h new file mode 100644 index 0000000..cb3b20c --- /dev/null +++ b/src/anm2/item.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +#include "frame.h" + +namespace anm2ed::anm2 +{ + class Item + { + public: + std::vector frames{}; + bool isVisible{true}; + + Item() = default; + Item(tinyxml2::XMLElement*, Type, int* = nullptr); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, Type, int); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, Type, int = -1); + std::string to_string(Type, int = -1); + int length(Type); + Frame frame_generate(float, Type); + void frames_change(anm2::FrameChange&, ChangeType, int, int = 0); + bool frames_deserialize(const std::string&, Type, int, std::set&, std::string*); + }; +} \ No newline at end of file diff --git a/src/anm2/layer.cpp b/src/anm2/layer.cpp new file mode 100644 index 0000000..4ca3106 --- /dev/null +++ b/src/anm2/layer.cpp @@ -0,0 +1,39 @@ +#include "layer.h" + +#include "xml_.h" + +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Layer::Layer(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_string_attribute(element, "Name", &name); + element->QueryIntAttribute("SpritesheetId", &spritesheetID); + } + + XMLElement* Layer::to_element(XMLDocument& document, int id) + { + auto element = document.NewElement("Layer"); + element->SetAttribute("Id", id); + element->SetAttribute("Name", name.c_str()); + element->SetAttribute("SpritesheetId", spritesheetID); + return element; + } + + void Layer::serialize(XMLDocument& document, XMLElement* parent, int id) + { + parent->InsertEndChild(to_element(document, id)); + } + + std::string Layer::to_string(int id) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, id)); + return xml::document_to_string(document); + } + +} \ No newline at end of file diff --git a/src/anm2/layer.h b/src/anm2/layer.h new file mode 100644 index 0000000..715fe1b --- /dev/null +++ b/src/anm2/layer.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +namespace anm2ed::anm2 +{ + constexpr auto LAYER_FORMAT = "#{} {} (Spritesheet: #{})"; + + class Layer + { + public: + std::string name{"New Layer"}; + int spritesheetID{}; + + Layer() = default; + Layer(tinyxml2::XMLElement*, int&); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, int); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); + std::string to_string(int); + }; +} \ No newline at end of file diff --git a/src/anm2/null.cpp b/src/anm2/null.cpp new file mode 100644 index 0000000..272228a --- /dev/null +++ b/src/anm2/null.cpp @@ -0,0 +1,38 @@ +#include "null.h" + +#include "xml_.h" + +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Null::Null(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_string_attribute(element, "Name", &name); + element->QueryBoolAttribute("ShowRect", &isShowRect); + } + + XMLElement* Null::to_element(XMLDocument& document, int id) + { + auto element = document.NewElement("Null"); + element->SetAttribute("Id", id); + element->SetAttribute("Name", name.c_str()); + if (isShowRect) element->SetAttribute("ShowRect", isShowRect); + return element; + } + + void Null::serialize(XMLDocument& document, XMLElement* parent, int id) + { + parent->InsertEndChild(to_element(document, id)); + } + + std::string Null::to_string(int id) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, id)); + return xml::document_to_string(document); + } +} \ No newline at end of file diff --git a/src/anm2/null.h b/src/anm2/null.h new file mode 100644 index 0000000..1691be9 --- /dev/null +++ b/src/anm2/null.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +namespace anm2ed::anm2 +{ + constexpr auto NULL_FORMAT = "#{} {}"; + + class Null + { + public: + std::string name{"New Null"}; + bool isShowRect{}; + + Null() = default; + Null(tinyxml2::XMLElement*, int&); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument& document, int id); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); + std::string to_string(int); + }; +} \ No newline at end of file diff --git a/src/anm2/sound.cpp b/src/anm2/sound.cpp new file mode 100644 index 0000000..eca9655 --- /dev/null +++ b/src/anm2/sound.cpp @@ -0,0 +1,59 @@ +#include "sound.h" + +#include "filesystem_.h" +#include "string_.h" +#include "xml_.h" + +using namespace anm2ed::resource; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Sound::Sound(const Sound& other) : path(other.path) + { + audio = path.empty() ? Audio() : Audio(path.c_str()); + } + + Sound& Sound::operator=(const Sound& other) + { + if (this != &other) + { + path = other.path; + audio = path.empty() ? Audio() : Audio(path.c_str()); + } + return *this; + } + + Sound::Sound(const std::string& directory, const std::string& path) + { + filesystem::WorkingDirectory workingDirectory(directory); + this->path = !path.empty() ? std::filesystem::relative(path).string() : this->path.string(); + this->path = string::backslash_replace_to_lower(this->path); + audio = Audio(this->path.c_str()); + } + + Sound::Sound(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_path_attribute(element, "Path", &path); + string::backslash_replace_to_lower(this->path); + audio = Audio(this->path.c_str()); + } + + XMLElement* Sound::to_element(XMLDocument& document, int id) + { + auto element = document.NewElement("Sound"); + element->SetAttribute("Id", id); + element->SetAttribute("Path", path.c_str()); + return element; + } + + std::string Sound::to_string(int id) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, id)); + return xml::document_to_string(document); + } +} \ No newline at end of file diff --git a/src/anm2/sound.h b/src/anm2/sound.h new file mode 100644 index 0000000..fc1e43f --- /dev/null +++ b/src/anm2/sound.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +#include "audio.h" + +namespace anm2ed::anm2 +{ + constexpr auto SOUND_FORMAT = "#{} {}"; + constexpr auto SOUND_FORMAT_C = "#%d %s"; + + class Sound + { + public: + std::filesystem::path path{}; + resource::Audio audio{}; + + Sound() = default; + Sound(Sound&&) noexcept = default; + Sound& operator=(Sound&&) noexcept = default; + + Sound(const Sound&); + Sound& operator=(const Sound&); + Sound(tinyxml2::XMLElement*, int&); + Sound(const std::string&, const std::string&); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, int); + std::string to_string(int); + }; +} \ No newline at end of file diff --git a/src/anm2/spritesheet.cpp b/src/anm2/spritesheet.cpp new file mode 100644 index 0000000..309c40e --- /dev/null +++ b/src/anm2/spritesheet.cpp @@ -0,0 +1,70 @@ +#include "spritesheet.h" + +#include "filesystem_.h" +#include "string_.h" +#include "xml_.h" + +using namespace anm2ed::resource; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Spritesheet::Spritesheet(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_path_attribute(element, "Path", &path); + // Spritesheet paths from Isaac Rebirth are made with the assumption that paths are case-insensitive + // However when using the resource dumper, the spritesheet paths are all lowercase (on Linux anyway) + // This will handle this case and make the paths OS-agnostic + this->path = string::backslash_replace_to_lower(this->path); + texture = Texture(path); + } + + Spritesheet::Spritesheet(const std::string& directory, const std::string& path) + { + filesystem::WorkingDirectory workingDirectory(directory); + this->path = !path.empty() ? std::filesystem::relative(path).string() : this->path.string(); + this->path = string::backslash_replace_to_lower(this->path); + texture = Texture(this->path); + } + + XMLElement* Spritesheet::to_element(XMLDocument& document, int id) + { + auto element = document.NewElement("Spritesheet"); + element->SetAttribute("Id", id); + element->SetAttribute("Path", path.c_str()); + return element; + } + + void Spritesheet::serialize(XMLDocument& document, XMLElement* parent, int id) + { + parent->InsertEndChild(to_element(document, id)); + } + + std::string Spritesheet::to_string(int id) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, id)); + return xml::document_to_string(document); + } + + bool Spritesheet::save(const std::string& directory, const std::string& path) + { + filesystem::WorkingDirectory workingDirectory(directory); + this->path = !path.empty() ? std::filesystem::relative(path).string() : this->path.string(); + return texture.write_png(this->path); + } + + void Spritesheet::reload(const std::string& directory) + { + *this = Spritesheet(directory, this->path); + } + + bool Spritesheet::is_valid() + { + return texture.is_valid(); + } + +} \ No newline at end of file diff --git a/src/anm2/spritesheet.h b/src/anm2/spritesheet.h new file mode 100644 index 0000000..6db08f9 --- /dev/null +++ b/src/anm2/spritesheet.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include + +#include "texture.h" + +namespace anm2ed::anm2 +{ + constexpr auto SPRITESHEET_FORMAT_C = "#%d %s"; + constexpr auto SPRITESHEET_FORMAT = "#{} {}"; + + class Spritesheet + { + public: + std::filesystem::path path{}; + resource::Texture texture; + + Spritesheet() = default; + Spritesheet(tinyxml2::XMLElement*, int&); + Spritesheet(const std::string&, const std::string& = {}); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, int); + std::string to_string(int id); + bool save(const std::string&, const std::string& = {}); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); + void reload(const std::string&); + bool is_valid(); + }; +} \ No newline at end of file diff --git a/src/canvas.cpp b/src/canvas.cpp index 6359da4..0ea9e2f 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1,19 +1,20 @@ #include "canvas.h" #include -#include #include #include #include #include -#include "math.h" +#include "math_.h" #include "texture.h" using namespace glm; -using namespace anm2ed::shader; +using namespace anm2ed::resource; +using namespace anm2ed::util; +using namespace anm2ed::canvas; -namespace anm2ed::canvas +namespace anm2ed { constexpr float AXIS_VERTICES[] = {-1.0f, 0.0f, 1.0f, 0.0f}; constexpr float GRID_VERTICES[] = {-1.f, -1.f, 0.f, 0.f, 3.f, -1.f, 2.f, 0.f, -1.f, 3.f, 0.f, 2.f}; @@ -305,7 +306,7 @@ namespace anm2ed::canvas void Canvas::zoom_set(float& zoom, vec2& pan, vec2 focus, float step) { auto zoomFactor = math::percent_to_unit(zoom); - float newZoom = glm::clamp(math::round_nearest_multiple(zoom + step, step), canvas::ZOOM_MIN, canvas::ZOOM_MAX); + float newZoom = glm::clamp(math::round_nearest_multiple(zoom + step, step), ZOOM_MIN, ZOOM_MAX); if (newZoom != zoom) { float newZoomFactor = math::percent_to_unit(newZoom); @@ -347,4 +348,4 @@ namespace anm2ed::canvas pan = -rectCenter * fitScale; } } -} +} \ No newline at end of file diff --git a/src/canvas.h b/src/canvas.h index cb99da7..b1955b8 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -20,7 +20,10 @@ namespace anm2ed::canvas constexpr auto STEP = 1.0f; constexpr auto STEP_FAST = 5.0f; +} +namespace anm2ed +{ class Canvas { public: @@ -48,13 +51,14 @@ namespace anm2ed::canvas void size_set(glm::vec2); glm::vec4 pixel_read(glm::vec2, glm::vec2); glm::mat4 transform_get(float = 100.0f, glm::vec2 = {}); - void axes_render(shader::Shader&, float, glm::vec2, glm::vec4 = glm::vec4(1.0f)); - void grid_render(shader::Shader&, float, glm::vec2, glm::ivec2 = glm::ivec2(32, 32), glm::ivec2 = {}, + void axes_render(resource::Shader&, float, glm::vec2, glm::vec4 = glm::vec4(1.0f)); + void grid_render(resource::Shader&, float, glm::vec2, glm::ivec2 = glm::ivec2(32, 32), glm::ivec2 = {}, glm::vec4 = glm::vec4(1.0f)); - void texture_render(shader::Shader&, GLuint&, glm::mat4&, glm::vec4 = glm::vec4(1.0f), glm::vec3 = {}, - float* = (float*)TEXTURE_VERTICES); - void rect_render(shader::Shader&, const glm::mat4&, const glm::mat4&, glm::vec4 = glm::vec4(1.0f), - float dashLength = DASH_LENGTH, float dashGap = DASH_GAP, float dashOffset = DASH_OFFSET); + void texture_render(resource::Shader&, GLuint&, glm::mat4&, glm::vec4 = glm::vec4(1.0f), glm::vec3 = {}, + float* = (float*)canvas::TEXTURE_VERTICES); + void rect_render(resource::Shader&, const glm::mat4&, const glm::mat4&, glm::vec4 = glm::vec4(1.0f), + float dashLength = canvas::DASH_LENGTH, float dashGap = canvas::DASH_GAP, + float dashOffset = canvas::DASH_OFFSET); void viewport_set(); void clear(glm::vec4&); void bind(); diff --git a/src/clipboard.cpp b/src/clipboard.cpp index 8ec5e53..e66150d 100644 --- a/src/clipboard.cpp +++ b/src/clipboard.cpp @@ -2,7 +2,7 @@ #include -namespace anm2ed::clipboard +namespace anm2ed { std::string Clipboard::get() { diff --git a/src/clipboard.h b/src/clipboard.h index 0b13a07..9e8ec8b 100644 --- a/src/clipboard.h +++ b/src/clipboard.h @@ -2,7 +2,7 @@ #include -namespace anm2ed::clipboard +namespace anm2ed { class Clipboard { diff --git a/src/dialog.cpp b/src/dialog.cpp index 67da4f6..ddffb95 100644 --- a/src/dialog.cpp +++ b/src/dialog.cpp @@ -8,10 +8,6 @@ namespace anm2ed::dialog { - - constexpr SDL_DialogFileFilter FILE_FILTER_ANM2[] = {{"Anm2 file", "anm2;xml"}}; - constexpr SDL_DialogFileFilter FILE_FILTER_SPRITESHEET[] = {{"PNG image", "png"}}; - void callback(void* userData, const char* const* filelist, int filter) { auto self = (Dialog*)(userData); @@ -24,8 +20,12 @@ namespace anm2ed::dialog else self->selectedFilter = -1; } +} - Dialog::Dialog() = default; +using namespace anm2ed::dialog; + +namespace anm2ed +{ Dialog::Dialog(SDL_Window* window) { @@ -33,36 +33,24 @@ namespace anm2ed::dialog this->window = window; } - void Dialog::anm2_new() + void Dialog::file_open(dialog::Type type) { - SDL_ShowSaveFileDialog(callback, this, window, FILE_FILTER_ANM2, std::size(FILE_FILTER_ANM2), nullptr); - type = ANM2_NEW; + SDL_ShowOpenFileDialog(callback, this, window, FILTERS[TYPE_FILTERS[type]], std::size(FILTERS[TYPE_FILTERS[type]]), + nullptr, false); + this->type = type; } - void Dialog::anm2_open() + void Dialog::file_save(dialog::Type type) { - SDL_ShowOpenFileDialog(callback, this, window, FILE_FILTER_ANM2, std::size(FILE_FILTER_ANM2), nullptr, false); - type = ANM2_OPEN; + SDL_ShowSaveFileDialog(callback, this, window, FILTERS[TYPE_FILTERS[type]], std::size(FILTERS[TYPE_FILTERS[type]]), + nullptr); + this->type = type; } - void Dialog::anm2_save() + void Dialog::folder_open(dialog::Type type) { - SDL_ShowSaveFileDialog(callback, this, window, FILE_FILTER_ANM2, std::size(FILE_FILTER_ANM2), nullptr); - type = ANM2_SAVE; - } - - void Dialog::spritesheet_open() - { - SDL_ShowOpenFileDialog(callback, this, window, FILE_FILTER_SPRITESHEET, std::size(FILE_FILTER_SPRITESHEET), nullptr, - false); - type = SPRITESHEET_OPEN; - } - - void Dialog::spritesheet_replace() - { - SDL_ShowOpenFileDialog(callback, this, window, FILE_FILTER_SPRITESHEET, std::size(FILE_FILTER_SPRITESHEET), nullptr, - false); - type = SPRITESHEET_REPLACE; + SDL_ShowOpenFolderDialog(callback, this, window, nullptr, false); + this->type = type; } void Dialog::file_explorer_open(const std::string& path) @@ -79,8 +67,16 @@ namespace anm2ed::dialog *this = Dialog(this->window); } - bool Dialog::is_selected_file(Type type) + bool Dialog::is_selected(dialog::Type type) { return this->type == type && !path.empty(); } + + void Dialog::set_string_to_selected_path(std::string& string, dialog::Type type) + { + if (type == NONE) return; + if (!is_selected(type)) return; + string = path; + reset(); + } }; diff --git a/src/dialog.h b/src/dialog.h index 487c37f..46f716a 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -6,34 +6,88 @@ namespace anm2ed::dialog { +#if defined(_WIN32) + #define EXECUTABLE_FILTER {"Executable", "exe"} +#else + #define EXECUTABLE_FILTER \ + { \ + } +#endif + +#define FILTER_LIST \ + X(NO_FILTER, {}) \ + X(ANM2, {"Anm2 file", "anm2;xml"}) \ + X(PNG, {"PNG image", "png"}) \ + X(SOUND, {"WAV file;OGG file", "wav;ogg"}) \ + X(GIF, {"GIF image", "gif"}) \ + X(WEBM, {"WebM video", "webm"}) \ + X(MP4, {"MP4 video", "MP4"}) \ + X(EXECUTABLE, EXECUTABLE_FILTER) + + enum Filter + { +#define X(symbol, ...) symbol, + FILTER_LIST +#undef X + }; + + constexpr SDL_DialogFileFilter FILTERS[][1] = { +#define X(symbol, ...) {__VA_ARGS__}, + FILTER_LIST +#undef X + }; + +#undef FILTER_LIST + +#define DIALOG_LIST \ + X(NONE, NO_FILTER) \ + X(ANM2_NEW, ANM2) \ + X(ANM2_OPEN, ANM2) \ + X(ANM2_SAVE, ANM2) \ + X(SOUND_OPEN, SOUND) \ + X(SPRITESHEET_OPEN, PNG) \ + X(SPRITESHEET_REPLACE, PNG) \ + X(FFMPEG_PATH_SET, EXECUTABLE) \ + X(PNG_DIRECTORY_SET, NO_FILTER) \ + X(GIF_PATH_SET, GIF) \ + X(WEBM_PATH_SET, WEBM) \ + X(MP4_PATH_SET, MP4) + enum Type { - NONE, - ANM2_NEW, - ANM2_OPEN, - ANM2_SAVE, - SPRITESHEET_OPEN, - SPRITESHEET_REPLACE +#define X(symbol, filter) symbol, + DIALOG_LIST +#undef X }; + constexpr Filter TYPE_FILTERS[] = { +#define X(symbol, filter) filter, + DIALOG_LIST +#undef X + }; + +#undef DIALOG_LIST +} + +namespace anm2ed +{ + class Dialog { public: SDL_Window* window{}; std::string path{}; - Type type{NONE}; + dialog::Type type{dialog::NONE}; int selectedFilter{-1}; - int replaceID{-1}; - Dialog(); + Dialog() = default; Dialog(SDL_Window*); - void anm2_new(); - void anm2_open(); - void anm2_save(); - void spritesheet_open(); - void spritesheet_replace(); - void file_explorer_open(const std::string&); + void file_open(dialog::Type type); + void file_save(dialog::Type type); + void folder_open(dialog::Type type); + bool is_selected(dialog::Type type); void reset(); - bool is_selected_file(Type); + void file_explorer_open(const std::string&); + void set_string_to_selected_path(std::string& set, dialog::Type type); }; } diff --git a/src/dockspace.h b/src/dockspace.h deleted file mode 100644 index 532fed3..0000000 --- a/src/dockspace.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "animation_preview.h" -#include "animations.h" -#include "documents.h" -#include "events.h" -#include "frame_properties.h" -#include "layers.h" -#include "nulls.h" -#include "onionskin.h" -#include "spritesheet_editor.h" -#include "spritesheets.h" -#include "taskbar.h" -#include "timeline.h" -#include "tools.h" -#include "welcome.h" - -namespace anm2ed::dockspace -{ - class Dockspace - { - animation_preview::AnimationPreview animationPreview; - animations::Animations animations; - events::Events events; - frame_properties::FrameProperties frameProperties; - layers::Layers layers; - nulls::Nulls nulls; - onionskin::Onionskin onionskin; - spritesheet_editor::SpritesheetEditor spritesheetEditor; - spritesheets::Spritesheets spritesheets; - timeline::Timeline timeline; - tools::Tools tools; - welcome::Welcome welcome; - - public: - void update(taskbar::Taskbar&, documents::Documents&, manager::Manager&, settings::Settings&, resources::Resources&, - dialog::Dialog&, clipboard::Clipboard&); - }; -} diff --git a/src/document.cpp b/src/document.cpp index a24ccb4..a17f208 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -3,26 +3,24 @@ #include #include -#include "anm2.h" -#include "filesystem.h" +#include "filesystem_.h" #include "log.h" +#include "map_.h" #include "toast.h" -#include "util.h" +#include "vector_.h" using namespace anm2ed::anm2; -using namespace anm2ed::filesystem; -using namespace anm2ed::toast; +using namespace anm2ed::imgui; using namespace anm2ed::types; using namespace anm2ed::util; -using namespace anm2ed::log; using namespace glm; -namespace anm2ed::document +namespace anm2ed { Document::Document(const std::string& path, bool isNew, std::string* errorString) { - if (!path_is_exist(path)) return; + if (!filesystem::path_is_exist(path)) return; if (isNew) anm2 = anm2::Anm2(); @@ -34,7 +32,7 @@ namespace anm2ed::document this->path = path; clean(); - change(change::ALL); + change(Document::ALL); } bool Document::save(const std::string& path, std::string* errorString) @@ -43,12 +41,12 @@ namespace anm2ed::document if (anm2.serialize(this->path, errorString)) { - toasts.info(std::format("Saved document to: {}", path)); + toasts.info(std::format("Saved document to: {}", this->path.string())); clean(); return true; } else if (errorString) - toasts.warning(std::format("Could not save document to: {} ({})", path, *errorString)); + toasts.warning(std::format("Could not save document to: {} ({})", this->path.string(), *errorString)); return false; } @@ -82,43 +80,76 @@ namespace anm2ed::document isForceDirty = false; } - void Document::change(change::Type type) + void Document::change(ChangeType type) { hash_set(); - auto layer_set = [&]() { unusedLayerIDs = anm2.layers_unused(); }; - auto null_set = [&]() { unusedNullIDs = anm2.nulls_unused(); }; - auto event_set = [&]() { unusedEventIDs = anm2.events_unused(); }; - auto spritesheet_set = [&]() + auto layers_set = [&]() { unusedLayerIDs = anm2.layers_unused(); }; + auto nulls_set = [&]() { unusedNullIDs = anm2.nulls_unused(); }; + auto events_set = [&]() + { + unusedEventIDs = anm2.events_unused(); + eventNames = anm2.event_names_get(); + for (auto& name : eventNames) + eventNamesCStr.push_back(name.c_str()); + }; + + auto animations_set = [&]() + { + animationNames = anm2.animation_names_get(); + animationNamesCStr.clear(); + animationNames.insert(animationNames.begin(), "None"); + for (auto& name : animationNames) + animationNamesCStr.push_back(name.c_str()); + }; + + auto spritesheets_set = [&]() { unusedSpritesheetIDs = anm2.spritesheets_unused(); spritesheetNames = anm2.spritesheet_names_get(); - spritesheetNamesCstr.clear(); + spritesheetNamesCStr.clear(); for (auto& name : spritesheetNames) - spritesheetNamesCstr.push_back(name.c_str()); + spritesheetNamesCStr.push_back(name.c_str()); + }; + + auto sounds_set = [&]() + { + unusedSoundIDs = anm2.sounds_unused(); + soundNames = anm2.sound_names_get(); + soundNamesCStr.clear(); + for (auto& name : soundNames) + soundNamesCStr.push_back(name.c_str()); }; switch (type) { - case change::LAYERS: - layer_set(); + case LAYERS: + layers_set(); break; - case change::NULLS: - null_set(); + case NULLS: + nulls_set(); break; - case change::EVENTS: - event_set(); + case EVENTS: + events_set(); break; - case change::SPRITESHEETS: - spritesheet_set(); + case ANIMATIONS: + animations_set(); break; - case change::ITEMS: + case SPRITESHEETS: + spritesheets_set(); break; - case change::ALL: - layer_set(); - null_set(); - event_set(); - spritesheet_set(); + case SOUNDS: + sounds_set(); + break; + case ITEMS: + break; + case ALL: + layers_set(); + nulls_set(); + events_set(); + animations_set(); + spritesheets_set(); + sounds_set(); break; default: break; @@ -159,7 +190,7 @@ namespace anm2ed::document { snapshot("Bake Frames"); anm2.bake(reference, interval, isRoundScale, isRoundRotation); - change(change::FRAMES); + change(Document::FRAMES); } void Document::frames_add(anm2::Item* item) @@ -188,7 +219,7 @@ namespace anm2ed::document snapshot("Delete Frames"); item->frames.erase(item->frames.begin() + reference.frameIndex); reference.frameIndex = glm::max(-1, --reference.frameIndex); - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_crop_set(anm2::Frame* frame, vec2 crop) @@ -196,7 +227,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Crop"); frame->crop = crop; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_size_set(anm2::Frame* frame, vec2 size) @@ -204,7 +235,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Size"); frame->size = size; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_position_set(anm2::Frame* frame, vec2 position) @@ -212,7 +243,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Position"); frame->position = position; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_pivot_set(anm2::Frame* frame, vec2 pivot) @@ -220,7 +251,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Pivot"); frame->pivot = pivot; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_scale_set(anm2::Frame* frame, vec2 scale) @@ -228,7 +259,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Scale"); frame->scale = scale; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_rotation_set(anm2::Frame* frame, float rotation) @@ -236,7 +267,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Rotation"); frame->rotation = rotation; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_delay_set(anm2::Frame* frame, int delay) @@ -244,7 +275,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Delay"); frame->delay = delay; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_tint_set(anm2::Frame* frame, vec4 tint) @@ -252,7 +283,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Tint"); frame->tint = tint; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_color_offset_set(anm2::Frame* frame, vec3 colorOffset) @@ -260,7 +291,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Color Offset"); frame->colorOffset = colorOffset; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_is_visible_set(anm2::Frame* frame, bool isVisible) @@ -268,7 +299,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Visibility"); frame->isVisible = isVisible; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_is_interpolated_set(anm2::Frame* frame, bool isInterpolated) @@ -276,7 +307,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Interpolation"); frame->isInterpolated = isInterpolated; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_flip_x(anm2::Frame* frame) @@ -284,7 +315,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Flip X"); frame->scale.x = -frame->scale.x; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_flip_y(anm2::Frame* frame) @@ -292,7 +323,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Frame Flip Y"); frame->scale.y = -frame->scale.y; - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_shorten() @@ -301,7 +332,7 @@ namespace anm2ed::document if (!frame) return; snapshot("Shorten Frame"); frame->shorten(); - change(change::FRAMES); + change(Document::FRAMES); } void Document::frame_extend() @@ -310,10 +341,10 @@ namespace anm2ed::document if (!frame) return; snapshot("Extend Frame"); frame->extend(); - change(change::FRAMES); + change(Document::FRAMES); } - void Document::frames_change(anm2::FrameChange& frameChange, frame_change::Type type, bool isFromSelectedFrame, + void Document::frames_change(anm2::FrameChange& frameChange, anm2::ChangeType type, bool isFromSelectedFrame, int numberFrames) { auto item = item_get(); @@ -321,7 +352,7 @@ namespace anm2ed::document snapshot("Change All Frame Properties"); item->frames_change(frameChange, type, isFromSelectedFrame && frame_get() ? reference.frameIndex : 0, isFromSelectedFrame ? numberFrames : -1); - change(change::FRAMES); + change(Document::FRAMES); } void Document::frames_deserialize(const std::string& string) @@ -333,7 +364,7 @@ namespace anm2ed::document std::string errorString{}; auto start = reference.frameIndex + 1; if (item->frames_deserialize(string, reference.itemType, start, indices, &errorString)) - change(change::FRAMES); + change(Document::FRAMES); else toasts.error(std::format("Failed to deserialize frame(s): {}", errorString)); } @@ -359,7 +390,7 @@ namespace anm2ed::document { spritesheetMultiSelect = {id}; toasts.info(std::format("Initialized spritesheet #{}: {}", id, path)); - change(change::SPRITESHEETS); + change(Document::SPRITESHEETS); } else toasts.error(std::format("Failed to initialize spritesheet: {}", path)); @@ -370,7 +401,7 @@ namespace anm2ed::document snapshot("Paste Spritesheet(s)"); std::string errorString{}; if (anm2.content.spritesheets_deserialize(string, directory_get(), type, &errorString)) - change(change::SPRITESHEETS); + change(Document::SPRITESHEETS); else toasts.error(std::format("Failed to deserialize spritesheet(s): {}", errorString)); } @@ -380,7 +411,7 @@ namespace anm2ed::document snapshot("Paste Layer(s)"); std::string errorString{}; if (anm2.content.layers_deserialize(string, type, &errorString)) - change(change::NULLS); + change(Document::NULLS); else toasts.error(std::format("Failed to deserialize layer(s): {}", errorString)); } @@ -400,7 +431,7 @@ namespace anm2ed::document anm2.content.layers[id] = layer; layersMultiSelect = {id}; } - change(change::LAYERS); + change(Document::LAYERS); } void Document::layers_remove_unused() @@ -408,7 +439,7 @@ namespace anm2ed::document snapshot("Remove Unused Layers"); for (auto& id : unusedLayerIDs) anm2.content.layers.erase(id); - change(change::LAYERS); + change(Document::LAYERS); unusedLayerIDs.clear(); } @@ -427,14 +458,14 @@ namespace anm2ed::document anm2.content.nulls[id] = null; nullMultiSelect = {id}; } - change(change::NULLS); + change(Document::NULLS); } void Document::null_rect_toggle(anm2::Null& null) { snapshot("Null Rect"); null.isShowRect = !null.isShowRect; - change(change::NULLS); + change(Document::NULLS); } void Document::nulls_remove_unused() @@ -442,7 +473,7 @@ namespace anm2ed::document snapshot("Remove Unused Nulls"); for (auto& id : unusedNullIDs) anm2.content.nulls.erase(id); - change(change::NULLS); + change(Document::NULLS); unusedNullIDs.clear(); } @@ -451,18 +482,27 @@ namespace anm2ed::document snapshot("Paste Null(s)"); std::string errorString{}; if (anm2.content.nulls_deserialize(string, type, &errorString)) - change(change::NULLS); + change(Document::NULLS); else toasts.error(std::format("Failed to deserialize null(s): {}", errorString)); } - void Document::event_add() + void Document::event_set(anm2::Event& event) { - snapshot("Add Event"); - int id{}; - anm2.event_add(id); - eventMultiSelect = {id}; - change(change::EVENTS); + if (referenceEvent > -1) + { + snapshot("Set Event"); + anm2.content.events[referenceEvent] = event; + eventMultiSelect = {referenceEvent}; + } + else + { + snapshot("Add Event"); + auto id = map::next_id_get(anm2.content.events); + anm2.content.events[id] = event; + eventMultiSelect = {id}; + } + change(Document::EVENTS); } void Document::events_remove_unused() @@ -470,7 +510,7 @@ namespace anm2ed::document snapshot("Remove Unused Events"); for (auto& id : unusedEventIDs) anm2.content.events.erase(id); - change(change::EVENTS); + change(Document::EVENTS); unusedEventIDs.clear(); } @@ -479,7 +519,40 @@ namespace anm2ed::document snapshot("Paste Event(s)"); std::string errorString{}; if (anm2.content.events_deserialize(string, type, &errorString)) - change(change::EVENTS); + change(Document::EVENTS); + else + toasts.error(std::format("Failed to deserialize event(s): {}", errorString)); + } + + void Document::sound_add(const std::string& path) + { + int id{}; + snapshot("Add Sound"); + if (anm2.sound_add(directory_get(), path, id)) + { + soundMultiSelect = {id}; + toasts.info(std::format("Initialized sound #{}: {}", id, path)); + change(Document::SOUNDS); + } + else + toasts.error(std::format("Failed to initialize sound: {}", path)); + } + + void Document::sounds_remove_unused() + { + snapshot("Remove Unused Sounds"); + for (auto& id : unusedSoundIDs) + anm2.content.sounds.erase(id); + change(Document::LAYERS); + unusedSoundIDs.clear(); + } + + void Document::sounds_deserialize(const std::string& string, merge::Type type) + { + snapshot("Paste Sound(s)"); + std::string errorString{}; + if (anm2.content.sounds_deserialize(string, directory_get(), type, &errorString)) + change(Document::EVENTS); else toasts.error(std::format("Failed to deserialize event(s): {}", errorString)); } @@ -498,7 +571,7 @@ namespace anm2ed::document reference = addReference; - change(change::ITEMS); + change(Document::ITEMS); } void Document::item_remove(anm2::Animation* animation) @@ -507,7 +580,7 @@ namespace anm2ed::document snapshot("Remove Item"); animation->item_remove(reference.itemType, reference.itemID); reference = {reference.animationIndex}; - change(change::ITEMS); + change(Document::ITEMS); } void Document::item_visible_toggle(anm2::Item* item) @@ -515,7 +588,7 @@ namespace anm2ed::document if (!item) return; snapshot("Item Visibility"); item->isVisible = !item->isVisible; - change(change::ITEMS); + change(Document::ITEMS); } anm2::Animation* Document::animation_get() @@ -527,7 +600,7 @@ namespace anm2ed::document { snapshot("Select Animation"); reference = {index}; - change(change::ITEMS); + change(Document::ITEMS); } void Document::animation_add() @@ -549,7 +622,7 @@ namespace anm2ed::document anm2.animations.items.insert(anm2.animations.items.begin() + index, animation); animationMultiSelect = {index}; reference = {index}; - change(change::ANIMATIONS); + change(Document::ANIMATIONS); } void Document::animation_duplicate() @@ -563,14 +636,14 @@ namespace anm2ed::document animationMultiSelect.insert(++duplicatedEnd); animationMultiSelect.erase(id); } - change(change::ANIMATIONS); + change(Document::ANIMATIONS); } void Document::animations_move(std::vector& indices, int index) { snapshot("Move Animation(s)"); animationMultiSelect = vector::move_indices(anm2.animations.items, indices, index); - change(change::ANIMATIONS); + change(Document::ANIMATIONS); } void Document::animations_remove() @@ -589,14 +662,14 @@ namespace anm2ed::document hoveredAnimation = -1; } - change(change::ANIMATIONS); + change(Document::ANIMATIONS); } void Document::animation_default() { snapshot("Default Animation"); anm2.animations.defaultAnimation = anm2.animations.items[*animationMultiSelect.begin()].name; - change(change::ANIMATIONS); + change(Document::ANIMATIONS); } void Document::animations_deserialize(const std::string& string) @@ -609,7 +682,7 @@ namespace anm2ed::document if (anm2.animations.animations_deserialize(string, start, indices, &errorString)) { multiSelect = indices; - change(change::ANIMATIONS); + change(Document::ANIMATIONS); } else toasts.error(std::format("Failed to deserialize animation(s): {}", errorString)); @@ -624,7 +697,7 @@ namespace anm2ed::document if (auto animation = animation_get()) animation->frameNum = animation->length(); - change(change::ALL); + change(Document::ALL); } void Document::animations_merge_quick() @@ -648,7 +721,7 @@ namespace anm2ed::document animationMultiSelect = {merged}; reference = {merged}; - change(change::ANIMATIONS); + change(Document::ANIMATIONS); } void Document::animations_merge(merge::Type type, bool isDeleteAnimationsAfter) @@ -657,7 +730,7 @@ namespace anm2ed::document auto merged = anm2.animations.merge(mergeTarget, animationMergeMultiSelect, type, isDeleteAnimationsAfter); animationMultiSelect = {merged}; reference = {merged}; - change(change::ANIMATIONS); + change(Document::ANIMATIONS); } void Document::snapshot(const std::string& message) @@ -669,22 +742,22 @@ namespace anm2ed::document { snapshots.undo(anm2, reference, message); toasts.info(std::format("Undo: {}", message)); - change(change::ALL); + change(Document::ALL); } void Document::redo() { toasts.info(std::format("Redo: {}", message)); snapshots.redo(anm2, reference, message); - change(change::ALL); + change(Document::ALL); } - bool Document::is_undo() + bool Document::is_able_to_undo() { return !snapshots.undoStack.is_empty(); } - bool Document::is_redo() + bool Document::is_able_to_redo() { return !snapshots.redoStack.is_empty(); } diff --git a/src/document.h b/src/document.h index 46ec309..35ae5ef 100644 --- a/src/document.h +++ b/src/document.h @@ -3,24 +3,38 @@ #include #include -#include "anm2.h" -#include "imgui.h" +#include "anm2/anm2.h" +#include "imgui_.h" #include "playback.h" #include "snapshots.h" #include "types.h" #include -namespace anm2ed::document +namespace anm2ed { class Document { public: + enum ChangeType + { + LAYERS, + NULLS, + SPRITESHEETS, + EVENTS, + ANIMATIONS, + ITEMS, + FRAMES, + SOUNDS, + ALL, + COUNT + }; + std::filesystem::path path{}; anm2::Anm2 anm2{}; std::string message{}; - playback::Playback playback{}; - snapshots::Snapshots snapshots{}; + Playback playback{}; + Snapshots snapshots{}; float previewZoom{200}; glm::vec2 previewPan{}; @@ -34,6 +48,8 @@ namespace anm2ed::document int mergeTarget{-1}; imgui::MultiSelectStorage animationMultiSelect; imgui::MultiSelectStorage animationMergeMultiSelect; + std::vector animationNamesCStr{}; + std::vector animationNames{}; anm2::Reference hoveredFrame{anm2::REFERENCE_DEFAULT}; @@ -41,7 +57,7 @@ namespace anm2ed::document int hoveredSpritesheet{-1}; std::set unusedSpritesheetIDs{}; std::vector spritesheetNames{}; - std::vector spritesheetNamesCstr{}; + std::vector spritesheetNamesCStr{}; imgui::MultiSelectStorage spritesheetMultiSelect; int referenceLayer{-1}; @@ -58,6 +74,15 @@ namespace anm2ed::document int hoveredEvent{-1}; std::set unusedEventIDs{}; imgui::MultiSelectStorage eventMultiSelect; + std::vector eventNamesCStr{}; + std::vector eventNames{}; + + int referenceSound{-1}; + int hoveredSound{-1}; + std::set unusedSoundIDs{}; + imgui::MultiSelectStorage soundMultiSelect; + std::vector soundNamesCStr{}; + std::vector soundNames{}; uint64_t hash{}; uint64_t saveHash{}; @@ -72,7 +97,7 @@ namespace anm2ed::document void hash_set(); void clean(); void on_change(); - void change(types::change::Type); + void change(ChangeType); bool is_dirty(); bool is_autosave_dirty(); std::filesystem::path directory_get(); @@ -81,7 +106,6 @@ namespace anm2ed::document anm2::Frame* frame_get(); void frames_add(anm2::Item* item); - void frames_change(); void frames_delete(anm2::Item* item); void frames_bake(int, bool, bool); void frame_crop_set(anm2::Frame*, glm::vec2); @@ -99,31 +123,35 @@ namespace anm2ed::document void frame_flip_y(anm2::Frame* frame); void frame_shorten(); void frame_extend(); - void frames_change(anm2::FrameChange&, types::frame_change::Type, bool, int = -1); + void frames_change(anm2::FrameChange&, anm2::ChangeType, bool, int = -1); void frames_deserialize(const std::string&); anm2::Item* item_get(); void item_add(anm2::Type, int, std::string&, types::locale::Type, int); - void item_remove(anm2::Animation* animation); + void item_remove(anm2::Animation*); void item_visible_toggle(anm2::Item*); anm2::Spritesheet* spritesheet_get(); void spritesheet_add(const std::string&); void spritesheets_deserialize(const std::string&, types::merge::Type); - void layer_set(anm2::Layer& layer); + void layer_set(anm2::Layer&); void layers_remove_unused(); void layers_deserialize(const std::string&, types::merge::Type); - void null_set(anm2::Null& null); - void null_rect_toggle(anm2::Null& null); + void null_set(anm2::Null&); + void null_rect_toggle(anm2::Null&); void nulls_remove_unused(); void nulls_deserialize(const std::string&, types::merge::Type); - void event_add(); + void event_set(anm2::Event&); void events_remove_unused(); void events_deserialize(const std::string&, types::merge::Type); + void sound_add(const std::string& path); + void sounds_remove_unused(); + void sounds_deserialize(const std::string& string, types::merge::Type); + void animation_add(); void animation_set(int); void animation_duplicate(); @@ -141,7 +169,19 @@ namespace anm2ed::document void undo(); void redo(); - bool is_undo(); - bool is_redo(); + bool is_able_to_undo(); + bool is_able_to_redo(); }; + +#define DOCUMENT_SNAPSHOT(document, message) document.snapshot(message); +#define DOCUMENT_CHANGE(document, changeType) document.change(changeType); + +#define DOCUMENT_EDIT(document, message, changeType, body) \ + { \ + \ + DOCUMENT_SNAPSHOT(document, message) \ + body; \ + DOCUMENT_CHANGE(document, changeType) \ + } + } diff --git a/src/events.h b/src/events.h deleted file mode 100644 index ef27454..0000000 --- a/src/events.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "clipboard.h" -#include "manager.h" -#include "resources.h" -#include "settings.h" - -namespace anm2ed::events -{ - class Events - { - - public: - void update(manager::Manager&, settings::Settings&, resources::Resources&, clipboard::Clipboard&); - }; -} diff --git a/src/frame_properties.cpp b/src/frame_properties.cpp deleted file mode 100644 index 7a086dc..0000000 --- a/src/frame_properties.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include "frame_properties.h" - -#include - -#include - -#include "imgui.h" -#include "math.h" -#include "types.h" - -using namespace anm2ed::settings; -using namespace anm2ed::manager; -using namespace anm2ed::math; -using namespace anm2ed::types; -using namespace glm; - -namespace anm2ed::frame_properties -{ - - void FrameProperties::update(Manager& manager, Settings& settings) - { - if (ImGui::Begin("Frame Properties", &settings.windowIsFrameProperties)) - { - auto& document = *manager.get(); - auto& anm2 = document.anm2; - auto& reference = document.reference; - auto& type = reference.itemType; - auto frame = document.frame_get(); - auto useFrame = frame ? *frame : anm2::Frame(); - - ImGui::BeginDisabled(!frame); - { - if (type == anm2::TRIGGER) - { - std::vector eventNames{}; - for (auto& event : anm2.content.events | std::views::values) - eventNames.emplace_back(event.name); - - imgui::combo_strings("Event", frame ? &frame->eventID : &dummy_value(), eventNames); - ImGui::SetItemTooltip("%s", "Change the event this trigger uses."); - ImGui::InputInt("At Frame", frame ? &frame->atFrame : &dummy_value(), step::NORMAL, step::FAST, - !frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); - ImGui::SetItemTooltip("%s", "Change the frame the trigger will be activated at."); - } - else - { - ImGui::BeginDisabled(type == anm2::ROOT || type == anm2::NULL_); - { - if (ImGui::InputFloat2("Crop", frame ? value_ptr(useFrame.crop) : &dummy_value(), - frame ? vec2_format_get(useFrame.crop) : "")) - document.frame_crop_set(frame, useFrame.crop); - ImGui::SetItemTooltip("%s", "Change the crop position the frame uses."); - - if (ImGui::InputFloat2("Size", frame ? value_ptr(useFrame.size) : &dummy_value(), - frame ? vec2_format_get(useFrame.size) : "")) - document.frame_size_set(frame, useFrame.size); - ImGui::SetItemTooltip("%s", "Change the size of the crop the frame uses."); - } - ImGui::EndDisabled(); - - if (ImGui::InputFloat2("Position", frame ? value_ptr(useFrame.position) : &dummy_value(), - frame ? vec2_format_get(useFrame.position) : "")) - document.frame_position_set(frame, useFrame.position); - ImGui::SetItemTooltip("%s", "Change the position of the frame."); - - ImGui::BeginDisabled(type == anm2::ROOT || type == anm2::NULL_); - { - if (ImGui::InputFloat2("Pivot", frame ? value_ptr(useFrame.pivot) : &dummy_value(), - frame ? vec2_format_get(useFrame.pivot) : "")) - document.frame_pivot_set(frame, useFrame.pivot); - ImGui::SetItemTooltip("%s", "Change the pivot of the frame; i.e., where it is centered."); - } - ImGui::EndDisabled(); - - if (ImGui::InputFloat2("Scale", frame ? value_ptr(useFrame.scale) : &dummy_value(), - frame ? vec2_format_get(useFrame.scale) : "")) - document.frame_scale_set(frame, useFrame.scale); - ImGui::SetItemTooltip("%s", "Change the scale of the frame, in percent."); - - if (ImGui::InputFloat("Rotation", frame ? &useFrame.rotation : &dummy_value(), step::NORMAL, - step::FAST, frame ? float_format_get(useFrame.rotation) : "")) - document.frame_rotation_set(frame, useFrame.rotation); - ImGui::SetItemTooltip("%s", "Change the rotation of the frame."); - - if (ImGui::InputInt("Duration", frame ? &useFrame.delay : &dummy_value(), step::NORMAL, step::FAST, - !frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0)) - document.frame_delay_set(frame, useFrame.delay); - ImGui::SetItemTooltip("%s", "Change how long the frame lasts."); - - if (ImGui::ColorEdit4("Tint", frame ? value_ptr(useFrame.tint) : &dummy_value())) - document.frame_tint_set(frame, useFrame.tint); - ImGui::SetItemTooltip("%s", "Change the tint of the frame."); - - if (ImGui::ColorEdit3("Color Offset", frame ? value_ptr(useFrame.colorOffset) : &dummy_value())) - document.frame_color_offset_set(frame, useFrame.colorOffset); - ImGui::SetItemTooltip("%s", "Change the color added onto the frame."); - - if (ImGui::Checkbox("Visible", frame ? &useFrame.isVisible : &dummy_value())) - document.frame_is_visible_set(frame, useFrame.isVisible); - ImGui::SetItemTooltip("%s", "Toggle the frame's visibility."); - - ImGui::SameLine(); - - if (ImGui::Checkbox("Interpolated", frame ? &useFrame.isInterpolated : &dummy_value())) - document.frame_is_interpolated_set(frame, useFrame.isInterpolated); - ImGui::SetItemTooltip( - "%s", "Toggle the frame interpolating; i.e., blending its values into the next frame based on the time."); - - auto widgetSize = imgui::widget_size_with_row_get(2); - - if (ImGui::Button("Flip X", widgetSize)) document.frame_flip_x(frame); - ImGui::SetItemTooltip("%s", "Flip the horizontal scale of the frame, to cheat mirroring the frame " - "horizontally.\n(Note: the format does not support mirroring.)"); - ImGui::SameLine(); - if (ImGui::Button("Flip Y", widgetSize)) document.frame_flip_y(frame); - ImGui::SetItemTooltip("%s", "Flip the vertical scale of the frame, to cheat mirroring the frame " - "vertically.\n(Note: the format does not support mirroring.)"); - } - } - ImGui::EndDisabled(); - } - ImGui::End(); - } -} \ No newline at end of file diff --git a/src/dockspace.cpp b/src/imgui/dockspace.cpp similarity index 83% rename from src/dockspace.cpp rename to src/imgui/dockspace.cpp index ec28d91..4a5a99d 100644 --- a/src/dockspace.cpp +++ b/src/imgui/dockspace.cpp @@ -1,22 +1,13 @@ #include "dockspace.h" -#include "animations.h" -#include "onionskin.h" -#include "tools.h" - -using namespace anm2ed::animations; -using namespace anm2ed::dialog; -using namespace anm2ed::clipboard; -using namespace anm2ed::manager; -using namespace anm2ed::documents; -using namespace anm2ed::playback; -using namespace anm2ed::resources; -using namespace anm2ed::settings; -using namespace anm2ed::taskbar; -using namespace anm2ed::welcome; - -namespace anm2ed::dockspace +namespace anm2ed::imgui { + void Dockspace::tick(Manager& manager, Settings& settings) + { + if (auto document = manager.get(); document) + if (settings.windowIsAnimationPreview) animationPreview.tick(manager, *document, settings); + } + void Dockspace::update(Taskbar& taskbar, Documents& documents, Manager& manager, Settings& settings, Resources& resources, Dialog& dialog, Clipboard& clipboard) { @@ -44,6 +35,7 @@ namespace anm2ed::dockspace if (settings.windowIsLayers) layers.update(manager, settings, resources, clipboard); if (settings.windowIsNulls) nulls.update(manager, settings, resources, clipboard); if (settings.windowIsOnionskin) onionskin.update(settings); + if (settings.windowIsSounds) sounds.update(manager, settings, resources, dialog, clipboard); if (settings.windowIsSpritesheetEditor) spritesheetEditor.update(manager, settings, resources); if (settings.windowIsSpritesheets) spritesheets.update(manager, settings, resources, dialog, clipboard); if (settings.windowIsTimeline) timeline.update(manager, settings, resources, clipboard); diff --git a/src/imgui/dockspace.h b/src/imgui/dockspace.h new file mode 100644 index 0000000..52cd852 --- /dev/null +++ b/src/imgui/dockspace.h @@ -0,0 +1,41 @@ +#pragma once + +#include "documents.h" +#include "taskbar.h" +#include "window/animation_preview.h" +#include "window/animations.h" +#include "window/events.h" +#include "window/frame_properties.h" +#include "window/layers.h" +#include "window/nulls.h" +#include "window/onionskin.h" +#include "window/sounds.h" +#include "window/spritesheet_editor.h" +#include "window/spritesheets.h" +#include "window/timeline.h" +#include "window/tools.h" +#include "window/welcome.h" + +namespace anm2ed::imgui +{ + class Dockspace + { + AnimationPreview animationPreview; + Animations animations; + Events events; + FrameProperties frameProperties; + Layers layers; + Nulls nulls; + Onionskin onionskin; + SpritesheetEditor spritesheetEditor; + Spritesheets spritesheets; + Sounds sounds; + Timeline timeline; + Tools tools; + Welcome welcome; + + public: + void tick(Manager&, Settings&); + void update(Taskbar&, Documents&, Manager&, Settings&, Resources&, Dialog&, Clipboard&); + }; +} diff --git a/src/documents.cpp b/src/imgui/documents.cpp similarity index 94% rename from src/documents.cpp rename to src/imgui/documents.cpp index 5fae943..9988778 100644 --- a/src/documents.cpp +++ b/src/imgui/documents.cpp @@ -2,16 +2,13 @@ #include -#include "util.h" +#include "time_.h" -using namespace anm2ed::taskbar; -using namespace anm2ed::manager; -using namespace anm2ed::settings; -using namespace anm2ed::resources; +using namespace anm2ed::resource; using namespace anm2ed::types; using namespace anm2ed::util; -namespace anm2ed::documents +namespace anm2ed::imgui { void Documents::update(Taskbar& taskbar, Manager& manager, Settings& settings, Resources& resources, bool& isQuitting) { @@ -27,7 +24,7 @@ namespace anm2ed::documents auto isDirty = document.is_dirty() && document.is_autosave_dirty(); document.lastAutosaveTime += ImGui::GetIO().DeltaTime; - if (isDirty && document.lastAutosaveTime > time::SECOND_S) manager.autosave(document); + if (isDirty && document.lastAutosaveTime > settings.fileAutosaveTime * time::SECOND_M) manager.autosave(document); } if (ImGui::Begin("##Documents", nullptr, diff --git a/src/documents.h b/src/imgui/documents.h similarity index 70% rename from src/documents.h rename to src/imgui/documents.h index 80050cc..0011f8b 100644 --- a/src/documents.h +++ b/src/imgui/documents.h @@ -6,7 +6,7 @@ #include "settings.h" #include "taskbar.h" -namespace anm2ed::documents +namespace anm2ed::imgui { class Documents { @@ -16,6 +16,6 @@ namespace anm2ed::documents public: float height{}; - void update(taskbar::Taskbar&, manager::Manager&, settings::Settings&, resources::Resources&, bool&); + void update(Taskbar&, Manager&, Settings&, Resources&, bool&); }; } diff --git a/src/imgui.cpp b/src/imgui/imgui_.cpp similarity index 87% rename from src/imgui.cpp rename to src/imgui/imgui_.cpp index d5a1713..ebcee70 100644 --- a/src/imgui.cpp +++ b/src/imgui/imgui_.cpp @@ -1,4 +1,4 @@ -#include "imgui.h" +#include "imgui_.h" #include @@ -11,6 +11,97 @@ using namespace glm; namespace anm2ed::imgui { + int input_text_callback(ImGuiInputTextCallbackData* data) + { + if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) + { + auto* string = (std::string*)(data->UserData); + string->resize(data->BufTextLen); + data->Buf = string->data(); + } + return 0; + } + + bool input_text_string(const char* label, std::string* string, ImGuiInputTextFlags flags) + { + flags |= ImGuiInputTextFlags_CallbackResize; + return ImGui::InputText(label, string->data(), string->capacity() + 1, flags, input_text_callback, string); + } + + bool combo_strings(const std::string& label, int* index, std::vector& strings) + { + std::vector items{}; + for (auto& string : strings) + items.push_back(string.c_str()); + return ImGui::Combo(label.c_str(), index, items.data(), (int)items.size()); + } + + bool combo_strings(const std::string& label, int* index, std::vector& strings) + { + return ImGui::Combo(label.c_str(), index, strings.data(), (int)strings.size()); + } + + bool input_int_range(const char* label, int& value, int min, int max, int step, int stepFast, + ImGuiInputTextFlags flags) + { + auto isActivated = ImGui::InputInt(label, &value, step, stepFast, flags); + value = glm::clamp(value, min, max); + return isActivated; + } + + bool selectable_input_text(const std::string& label, const std::string& id, std::string& text, bool isSelected, + ImGuiSelectableFlags flags, bool* isRenamed) + { + static std::string editID{}; + static bool isJustEdit{}; + const bool isEditing = editID == id; + bool isActivated{}; + + if (isEditing) + { + if (isJustEdit) + { + ImGui::SetKeyboardFocusHere(); + isJustEdit = false; + } + + ImGui::SetNextItemWidth(-FLT_MIN); + if (input_text_string("##Edit", &text, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) + { + editID.clear(); + isActivated = true; + if (isRenamed) *isRenamed = true; + } + if (ImGui::IsItemDeactivatedAfterEdit() || ImGui::IsKeyPressed(ImGuiKey_Escape)) editID.clear(); + } + else + { + if (ImGui::Selectable(label.c_str(), isSelected, flags)) isActivated = true; + + if ((ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGuiKey_F2) && isSelected) || + (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))) + { + editID = id; + isJustEdit = true; + } + } + + return isActivated; + } + + void set_item_tooltip_shortcut(const char* tooltip, const std::string& shortcut) + { + ImGui::SetItemTooltip("%s\n(Shortcut: %s)", tooltip, shortcut.c_str()); + } + + void external_storage_set(ImGuiSelectionExternalStorage* self, int id, bool isSelected) + { + auto* set = (std::set*)self->UserData; + if (isSelected) + set->insert(id); + else + set->erase(id); + }; std::string chord_to_string(ImGuiKeyChord chord) { @@ -91,90 +182,6 @@ namespace anm2ed::imgui (ImGui::GetFrameHeightWithSpacing() * rowCount) + (ImGui::GetStyle().WindowPadding.y * 2.0f)); } - int input_text_callback(ImGuiInputTextCallbackData* data) - { - if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) - { - auto* string = (std::string*)(data->UserData); - string->resize(data->BufTextLen); - data->Buf = string->data(); - } - return 0; - } - - bool input_text_string(const char* label, std::string* string, ImGuiInputTextFlags flags) - { - flags |= ImGuiInputTextFlags_CallbackResize; - return ImGui::InputText(label, string->data(), string->capacity() + 1, flags, input_text_callback, string); - } - - void combo_strings(const std::string& label, int* index, std::vector& strings) - { - std::vector items{}; - for (auto& string : strings) - items.push_back(string.c_str()); - ImGui::Combo(label.c_str(), index, items.data(), (int)items.size()); - } - - void combo_strings(const std::string& label, int* index, std::vector& strings) - { - ImGui::Combo(label.c_str(), index, strings.data(), (int)strings.size()); - } - - bool selectable_input_text(const std::string& label, const std::string& id, std::string& text, bool isSelected, - ImGuiSelectableFlags flags, bool* isRenamed) - { - static std::string editID{}; - static bool isJustEdit{}; - const bool isEditing = editID == id; - bool isActivated{}; - - if (isEditing) - { - if (isJustEdit) - { - ImGui::SetKeyboardFocusHere(); - isJustEdit = false; - } - - ImGui::SetNextItemWidth(-FLT_MIN); - if (input_text_string("##Edit", &text, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) - { - editID.clear(); - isActivated = true; - if (isRenamed) *isRenamed = true; - } - if (ImGui::IsItemDeactivatedAfterEdit() || ImGui::IsKeyPressed(ImGuiKey_Escape)) editID.clear(); - } - else - { - if (ImGui::Selectable(label.c_str(), isSelected, flags)) isActivated = true; - - if ((ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGuiKey_F2) && isSelected) || - (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))) - { - editID = id; - isJustEdit = true; - } - } - - return isActivated; - } - - void set_item_tooltip_shortcut(const char* tooltip, const std::string& shortcut) - { - ImGui::SetItemTooltip("%s\n(Shortcut: %s)", tooltip, shortcut.c_str()); - } - - void external_storage_set(ImGuiSelectionExternalStorage* self, int id, bool isSelected) - { - auto* set = (std::set*)self->UserData; - if (isSelected) - set->insert(id); - else - set->erase(id); - }; - ImVec2 icon_size_get() { return ImVec2(ImGui::GetTextLineHeightWithSpacing(), ImGui::GetTextLineHeightWithSpacing()); @@ -266,11 +273,11 @@ namespace anm2ed::imgui internal.ApplyRequests(io); } - PopupHelper::PopupHelper(const char* label, float percent, bool isNoHeight) + PopupHelper::PopupHelper(const char* label, PopupType type, PopupPosition position) { this->label = label; - this->percent = percent; - this->isNoHeight = isNoHeight; + this->type = type; + this->position = position; } void PopupHelper::open() @@ -291,11 +298,16 @@ namespace anm2ed::imgui isTriggered = false; auto viewport = ImGui::GetMainViewport(); - ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_None, to_imvec2(vec2(0.5f))); - if (isNoHeight) - ImGui::SetNextWindowSize(ImVec2(viewport->Size.x * percent, 0)); + + if (position == POPUP_CENTER) + ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_None, to_imvec2(vec2(0.5f))); else - ImGui::SetNextWindowSize(to_imvec2(to_vec2(viewport->Size) * percent)); + ImGui::SetNextWindowPos(ImGui::GetItemRectMin(), ImGuiCond_None); + + if (POPUP_IS_HEIGHT_SET[type]) + ImGui::SetNextWindowSize(to_imvec2(to_vec2(viewport->Size) * POPUP_MULTIPLIERS[type])); + else + ImGui::SetNextWindowSize(ImVec2(viewport->Size.x * POPUP_MULTIPLIERS[type], 0)); } void PopupHelper::end() diff --git a/src/imgui.h b/src/imgui/imgui_.h similarity index 87% rename from src/imgui.h rename to src/imgui/imgui_.h index 7e032ec..0555b4f 100644 --- a/src/imgui.h +++ b/src/imgui/imgui_.h @@ -10,9 +10,41 @@ namespace anm2ed::imgui { - constexpr auto POPUP_TO_CONTENT = 0.0f; - constexpr auto POPUP_SMALL = 0.25f; - constexpr auto POPUP_NORMAL = 0.5f; + constexpr auto DRAG_SPEED = 1.0f; + constexpr auto STEP = 1.0f; + constexpr auto STEP_FAST = 5.0f; + +#define POPUP_LIST \ + X(POPUP_SMALL, 0.25f, true) \ + X(POPUP_NORMAL, 0.5f, true) \ + X(POPUP_TO_CONTENT, 0.0f, true) \ + X(POPUP_SMALL_NO_HEIGHT, 0.25f, false) \ + X(POPUP_NORMAL_NO_HEIGHT, 0.5f, false) + + enum PopupType + { +#define X(name, multiplier, isHeightSet) name, + POPUP_LIST +#undef X + }; + + enum PopupPosition + { + POPUP_CENTER, + POPUP_BY_ITEM + }; + + constexpr float POPUP_MULTIPLIERS[] = { +#define X(name, multiplier, isHeightSet) multiplier, + POPUP_LIST +#undef X + }; + + constexpr bool POPUP_IS_HEIGHT_SET[] = { +#define X(name, multiplier, isHeightSet) isHeightSet, + POPUP_LIST +#undef X + }; const std::unordered_map KEY_MAP = {{"A", ImGuiKey_A}, {"B", ImGuiKey_B}, @@ -134,8 +166,9 @@ namespace anm2ed::imgui ImVec2 child_size_get(int = 1); int input_text_callback(ImGuiInputTextCallbackData*); bool input_text_string(const char*, std::string*, ImGuiInputTextFlags = 0); - void combo_strings(const std::string&, int*, std::vector&); - void combo_strings(const std::string&, int*, std::vector&); + bool input_int_range(const char*, int&, int, int, int = STEP, int = STEP_FAST, ImGuiInputTextFlags = 0); + bool combo_strings(const std::string&, int*, std::vector&); + bool combo_strings(const std::string&, int*, std::vector&); bool selectable_input_text(const std::string&, const std::string&, std::string&, bool = false, ImGuiSelectableFlags = 0, bool* = nullptr); void set_item_tooltip_shortcut(const char*, const std::string& = {}); @@ -167,13 +200,13 @@ namespace anm2ed::imgui { public: const char* label{}; + PopupType type{}; + PopupPosition position{}; bool isOpen{}; bool isTriggered{}; bool isJustOpened{}; - bool isNoHeight{}; - float percent{}; - PopupHelper(const char*, float = POPUP_NORMAL, bool = false); + PopupHelper(const char*, PopupType = POPUP_NORMAL, PopupPosition = POPUP_CENTER); bool is_open(); void open(); void trigger(); diff --git a/src/taskbar.cpp b/src/imgui/taskbar.cpp similarity index 80% rename from src/taskbar.cpp rename to src/imgui/taskbar.cpp index 04da3b4..e04b0fe 100644 --- a/src/taskbar.cpp +++ b/src/imgui/taskbar.cpp @@ -3,18 +3,18 @@ #include #include -#include "imgui.h" -#include "math.h" +#include "math_.h" +#include "render.h" +#include "shader.h" +#include "types.h" -using namespace anm2ed::canvas; -using namespace anm2ed::dialog; -using namespace anm2ed::manager; -using namespace anm2ed::resources; -using namespace anm2ed::settings; +using namespace anm2ed::resource; using namespace anm2ed::types; +using namespace anm2ed::canvas; +using namespace anm2ed::util; using namespace glm; -namespace anm2ed::taskbar +namespace anm2ed::imgui { Taskbar::Taskbar() : generate(vec2()) { @@ -30,9 +30,9 @@ namespace anm2ed::taskbar if (ImGui::BeginMenu("File")) { - if (ImGui::MenuItem("New", settings.shortcutNew.c_str())) dialog.anm2_new(); + if (ImGui::MenuItem("New", settings.shortcutNew.c_str())) dialog.file_open(dialog::ANM2_NEW); - if (ImGui::MenuItem("Open", settings.shortcutOpen.c_str())) dialog.anm2_open(); + if (ImGui::MenuItem("Open", settings.shortcutOpen.c_str())) dialog.file_open(dialog::ANM2_NEW); if (manager.recentFiles.empty()) { @@ -63,7 +63,7 @@ namespace anm2ed::taskbar ImGui::BeginDisabled(!document); { if (ImGui::MenuItem("Save", settings.shortcutSave.c_str())) manager.save(); - if (ImGui::MenuItem("Save As", settings.shortcutSaveAs.c_str())) dialog.anm2_save(); + if (ImGui::MenuItem("Save As", settings.shortcutSaveAs.c_str())) dialog.file_save(dialog::ANM2_SAVE); if (ImGui::MenuItem("Explore XML Location")) dialog.file_explorer_open(document->directory_get()); } ImGui::EndDisabled(); @@ -72,19 +72,19 @@ namespace anm2ed::taskbar if (ImGui::MenuItem("Exit", settings.shortcutExit.c_str())) isQuitting = true; ImGui::EndMenu(); } - if (dialog.is_selected_file(dialog::ANM2_NEW)) + if (dialog.is_selected(dialog::ANM2_NEW)) { manager.new_(dialog.path); dialog.reset(); } - if (dialog.is_selected_file(dialog::ANM2_OPEN)) + if (dialog.is_selected(dialog::ANM2_OPEN)) { manager.open(dialog.path); dialog.reset(); } - if (dialog.is_selected_file(dialog::ANM2_SAVE)) + if (dialog.is_selected(dialog::ANM2_SAVE)) { manager.save(dialog.path); dialog.reset(); @@ -92,11 +92,16 @@ namespace anm2ed::taskbar if (ImGui::BeginMenu("Wizard")) { + auto animation = document ? document->animation_get() : nullptr; auto item = document ? document->item_get() : nullptr; ImGui::BeginDisabled(!item || document->reference.itemType != anm2::LAYER); if (ImGui::MenuItem("Generate Animation From Grid")) generatePopup.open(); if (ImGui::MenuItem("Change All Frame Properties")) changePopup.open(); ImGui::EndDisabled(); + ImGui::Separator(); + ImGui::BeginDisabled(!animation); + if (ImGui::MenuItem("Render Animation")) renderPopup.open(); + ImGui::EndDisabled(); ImGui::EndMenu(); } @@ -160,13 +165,13 @@ namespace anm2ed::taskbar ImGui::InputInt2("Start Position", value_ptr(startPosition)); ImGui::InputInt2("Frame Size", value_ptr(size)); ImGui::InputInt2("Pivot", value_ptr(pivot)); - ImGui::InputInt("Rows", &rows, step::NORMAL, step::FAST); - ImGui::InputInt("Columns", &columns, step::NORMAL, step::FAST); + ImGui::InputInt("Rows", &rows, imgui::STEP, imgui::STEP_FAST); + ImGui::InputInt("Columns", &columns, imgui::STEP, imgui::STEP_FAST); - ImGui::InputInt("Count", &count, step::NORMAL, step::FAST); + ImGui::InputInt("Count", &count, imgui::STEP, imgui::STEP_FAST); count = glm::min(count, rows * columns); - ImGui::InputInt("Delay", &delay, step::NORMAL, step::FAST); + ImGui::InputInt("Delay", &delay, imgui::STEP, imgui::STEP_FAST); } ImGui::EndChild(); @@ -176,7 +181,7 @@ namespace anm2ed::taskbar { auto& backgroundColor = settings.previewBackgroundColor; auto& time = generateTime; - auto& shaderTexture = resources.shaders[shader::TEXTURE]; + auto& shaderTexture = resources.shaders[resource::shader::TEXTURE]; auto previewSize = ImVec2(ImGui::GetContentRegionAvail().x, imgui::size_without_footer_get(2).y); @@ -191,7 +196,7 @@ namespace anm2ed::taskbar .spritesheets[document->anm2.content.layers[document->reference.itemID].spritesheetID] .texture; - auto index = std::clamp((int)(time * count), 0, count); + auto index = std::clamp((int)(time * count - 1), 0, count - 1); auto row = index / columns; auto column = index % columns; auto crop = startPosition + ivec2(size.x * column, size.y * row); @@ -212,7 +217,7 @@ namespace anm2ed::taskbar ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::InputFloat("##Zoom", &zoom, zoomStep, zoomStep, "%.0f%%"); - zoom = glm::clamp(zoom, canvas::ZOOM_MIN, canvas::ZOOM_MAX); + zoom = glm::clamp(zoom, ZOOM_MIN, ZOOM_MAX); } ImGui::EndChild(); @@ -305,14 +310,14 @@ namespace anm2ed::taskbar auto float_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, float& value) { start(checkboxLabel, isEnabled); - ImGui::InputFloat(valueLabel, &value, step::NORMAL, step::FAST, math::float_format_get(value)); + ImGui::InputFloat(valueLabel, &value, imgui::STEP, imgui::STEP_FAST, math::float_format_get(value)); end(); }; auto int_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, int& value) { start(checkboxLabel, isEnabled); - ImGui::InputInt(valueLabel, &value, step::NORMAL, step::FAST); + ImGui::InputInt(valueLabel, &value, imgui::STEP, imgui::STEP_FAST); end(); }; @@ -340,7 +345,7 @@ namespace anm2ed::taskbar "off, will use all frames."); ImGui::BeginDisabled(!isFromSelectedFrame); - ImGui::InputInt("Number of Frames", &numberFrames, step::NORMAL, step::FAST); + ImGui::InputInt("Number of Frames", &numberFrames, imgui::STEP, imgui::STEP_FAST); numberFrames = glm::clamp(numberFrames, anm2::FRAME_NUM_MIN, (int)document->item_get()->frames.size() - document->reference.frameIndex); ImGui::SetItemTooltip("Set the number of frames that will be changed."); @@ -350,7 +355,7 @@ namespace anm2ed::taskbar auto widgetSize = imgui::widget_size_with_row_get(4); - auto frame_change = [&](frame_change::Type type) + auto frame_change = [&](anm2::ChangeType type) { anm2::FrameChange frameChange; frameChange.crop = isCrop ? std::make_optional(crop) : std::nullopt; @@ -370,7 +375,7 @@ namespace anm2ed::taskbar if (ImGui::Button("Add", widgetSize)) { - frame_change(frame_change::ADD); + frame_change(anm2::ADD); changePopup.close(); } @@ -378,7 +383,7 @@ namespace anm2ed::taskbar if (ImGui::Button("Subtract", widgetSize)) { - frame_change(frame_change::SUBTRACT); + frame_change(anm2::SUBTRACT); changePopup.close(); } @@ -386,7 +391,7 @@ namespace anm2ed::taskbar if (ImGui::Button("Adjust", widgetSize)) { - frame_change(frame_change::ADJUST); + frame_change(anm2::ADJUST); changePopup.close(); } @@ -415,7 +420,7 @@ namespace anm2ed::taskbar ImGui::SetItemTooltip("Enables autosaving of documents."); ImGui::BeginDisabled(!editSettings.fileIsAutosave); - ImGui::InputInt("Autosave Time (minutes", &editSettings.fileAutosaveTime, step::NORMAL, step::FAST); + ImGui::InputInt("Autosave Time (minutes", &editSettings.fileAutosaveTime, imgui::STEP, imgui::STEP_FAST); editSettings.fileAutosaveTime = glm::clamp(editSettings.fileAutosaveTime, 0, 10); ImGui::SetItemTooltip("If changed, will autosave documents using this interval."); ImGui::EndDisabled(); @@ -521,12 +526,79 @@ namespace anm2ed::taskbar ImGui::SameLine(); - if (ImGui::Button("Close", widgetSize)) ImGui::CloseCurrentPopup(); + if (ImGui::Button("Close", widgetSize)) configurePopup.close(); ImGui::SetItemTooltip("Close without updating settings."); ImGui::EndPopup(); } + renderPopup.trigger(); + + if (ImGui::BeginPopupModal(renderPopup.label, &renderPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto animation = document ? document->animation_get() : nullptr; + if (!animation) renderPopup.close(); + + auto& playback = document->playback; + auto& ffmpegPath = settings.renderFFmpegPath; + auto& path = settings.renderPath; + auto& format = settings.renderFormat; + auto& type = settings.renderType; + auto& start = manager.recordingStart; + auto& end = manager.recordingEnd; + auto& isRange = settings.renderIsRange; + auto widgetSize = imgui::widget_size_with_row_get(2); + auto dialogType = type == render::PNGS ? dialog::PNG_DIRECTORY_SET + : type == render::GIF ? dialog::GIF_PATH_SET + : type == render::WEBM ? dialog::WEBM_PATH_SET + : dialog::NONE; + + if (ImGui::ImageButton("##FFmpeg Path Set", resources.icons[icon::FOLDER].id, imgui::icon_size_get())) + dialog.file_open(dialog::FFMPEG_PATH_SET); + ImGui::SameLine(); + imgui::input_text_string("FFmpeg Path", &ffmpegPath); + dialog.set_string_to_selected_path(ffmpegPath, dialog::FFMPEG_PATH_SET); + + if (ImGui::ImageButton("##Path Set", resources.icons[icon::FOLDER].id, imgui::icon_size_get())) + { + if (dialogType == dialog::PNG_DIRECTORY_SET) + dialog.folder_open(dialogType); + else + dialog.file_open(dialogType); + } + ImGui::SameLine(); + imgui::input_text_string(type == render::PNGS ? "Directory" : "Path", &path); + dialog.set_string_to_selected_path(path, dialogType); + + ImGui::Combo("Type", &type, render::STRINGS, render::COUNT); + + ImGui::BeginDisabled(type != render::PNGS); + imgui::input_text_string("Format", &format); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(!isRange); + imgui::input_int_range("Start", start, 0, animation->frameNum - 1); + ImGui::InputInt("End", &end, start, animation->frameNum); + ImGui::EndDisabled(); + + ImGui::Checkbox("Custom Range", &isRange); + + if (ImGui::Button("Render", widgetSize)) + { + manager.isRecording = true; + playback.time = start; + playback.isPlaying = true; + renderPopup.close(); + manager.progressPopup.open(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) renderPopup.close(); + + ImGui::EndPopup(); + } + aboutPopup.trigger(); if (ImGui::BeginPopupModal(aboutPopup.label, &aboutPopup.isOpen, ImGuiWindowFlags_NoResize)) @@ -535,10 +607,10 @@ namespace anm2ed::taskbar ImGui::EndPopup(); } - if (imgui::shortcut(settings.shortcutNew, shortcut::GLOBAL)) dialog.anm2_new(); - if (imgui::shortcut(settings.shortcutOpen, shortcut::GLOBAL)) dialog.anm2_open(); + if (imgui::shortcut(settings.shortcutNew, shortcut::GLOBAL)) dialog.file_open(dialog::ANM2_NEW); + if (imgui::shortcut(settings.shortcutOpen, shortcut::GLOBAL)) dialog.file_open(dialog::ANM2_OPEN); if (imgui::shortcut(settings.shortcutSave, shortcut::GLOBAL)) document->save(); - if (imgui::shortcut(settings.shortcutSaveAs, shortcut::GLOBAL)) dialog.anm2_save(); + if (imgui::shortcut(settings.shortcutSaveAs, shortcut::GLOBAL)) dialog.file_save(dialog::ANM2_SAVE); if (imgui::shortcut(settings.shortcutExit, shortcut::GLOBAL)) isQuitting = true; } } diff --git a/src/imgui/taskbar.h b/src/imgui/taskbar.h new file mode 100644 index 0000000..1785468 --- /dev/null +++ b/src/imgui/taskbar.h @@ -0,0 +1,31 @@ +#pragma once + +#include "canvas.h" +#include "dialog.h" +#include "imgui_.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Taskbar + { + Canvas generate; + float generateTime{}; + PopupHelper generatePopup{PopupHelper("Generate Animation from Grid")}; + PopupHelper changePopup{PopupHelper("Change All Frame Properties", imgui::POPUP_SMALL_NO_HEIGHT)}; + PopupHelper renderPopup{PopupHelper("Render Animation", imgui::POPUP_SMALL_NO_HEIGHT)}; + PopupHelper configurePopup{PopupHelper("Configure")}; + PopupHelper aboutPopup{PopupHelper("About")}; + Settings editSettings{}; + int selectedShortcut{-1}; + bool isQuittingMode{}; + + public: + float height{}; + + Taskbar(); + void update(Manager&, Settings&, Resources&, Dialog&, bool&); + }; +}; diff --git a/src/toast.cpp b/src/imgui/toast.cpp similarity index 97% rename from src/toast.cpp rename to src/imgui/toast.cpp index a0d65c1..8de56ec 100644 --- a/src/toast.cpp +++ b/src/imgui/toast.cpp @@ -5,10 +5,9 @@ #include "types.h" -using namespace anm2ed::log; using namespace anm2ed::types; -namespace anm2ed::toast +namespace anm2ed::imgui { constexpr auto LIFETIME = 3.0f; @@ -82,5 +81,6 @@ namespace anm2ed::toast logger.warning(message); } - Toasts toasts; } + +anm2ed::imgui::Toasts toasts; diff --git a/src/toast.h b/src/imgui/toast.h similarity index 85% rename from src/toast.h rename to src/imgui/toast.h index 6aff2cc..ca33d34 100644 --- a/src/toast.h +++ b/src/imgui/toast.h @@ -3,9 +3,8 @@ #include #include -namespace anm2ed::toast +namespace anm2ed::imgui { - class Toast { public: @@ -26,5 +25,6 @@ namespace anm2ed::toast void warning(const std::string&); }; - extern Toasts toasts; } + +extern anm2ed::imgui::Toasts toasts; diff --git a/src/animation_preview.cpp b/src/imgui/window/animation_preview.cpp similarity index 80% rename from src/animation_preview.cpp rename to src/imgui/window/animation_preview.cpp index 4c523b0..da3ae99 100644 --- a/src/animation_preview.cpp +++ b/src/imgui/window/animation_preview.cpp @@ -1,21 +1,22 @@ #include "animation_preview.h" +#include + #include -#include "imgui.h" -#include "math.h" +#include "log.h" +#include "math_.h" +#include "toast.h" #include "tool.h" #include "types.h" -using namespace anm2ed::manager; -using namespace anm2ed::settings; using namespace anm2ed::canvas; -using namespace anm2ed::playback; -using namespace anm2ed::resources; using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace anm2ed::resource; using namespace glm; -namespace anm2ed::animation_preview +namespace anm2ed::imgui { constexpr auto NULL_COLOR = vec4(0.0f, 0.0f, 1.0f, 0.90f); constexpr auto TARGET_SIZE = vec2(32, 32); @@ -27,6 +28,75 @@ namespace anm2ed::animation_preview { } + void AnimationPreview::tick(Manager& manager, Document& document, Settings& settings) + { + auto& anm2 = document.anm2; + auto& playback = document.playback; + + if (playback.isPlaying) + { + auto& isSound = settings.timelineIsSound; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; + + if (isSound && !anm2.content.sounds.empty()) + if (auto animation = document.animation_get(); animation) + if (animation->triggers.isVisible && !isOnlyShowLayers) + if (auto trigger = animation->triggers.frame_generate(playback.time, anm2::TRIGGER); trigger.isVisible) + anm2.content.sounds[anm2.content.events[trigger.eventID].soundID].audio.play(); + + document.reference.frameTime = playback.time; + } + + if (manager.isRecording) + { + auto pixels = pixels_get(); + renderFrames.push_back(Texture(pixels.data(), size)); + + if (playback.isFinished) + { + auto& ffmpegPath = settings.renderFFmpegPath; + auto& path = settings.renderPath; + auto& type = settings.renderType; + + if (type == render::PNGS) + { + auto& format = settings.renderFormat; + bool isSuccess{true}; + for (auto [i, frame] : std::views::enumerate(renderFrames)) + { + std::filesystem::path outputPath = + std::filesystem::path(path) / std::vformat(format, std::make_format_args(i)); + + if (!frame.write_png(outputPath)) + { + isSuccess = false; + break; + } + logger.info(std::format("Saved frame to PNG: {}", outputPath.string())); + } + + if (isSuccess) + toasts.info(std::format("Exported rendered frames to: {}", path)); + else + toasts.warning(std::format("Could not export frames to: {}", path)); + } + else + { + if (animation_render(ffmpegPath, path, renderFrames, (render::Type)type, size, anm2.info.fps)) + toasts.info(std::format("Exported rendered animation to: {}", path)); + else + toasts.warning(std::format("Could not output rendered animation: {}", path)); + } + + renderFrames.clear(); + playback.isPlaying = false; + playback.isFinished = false; + manager.isRecording = false; + manager.progressPopup.close(); + } + } + } + void AnimationPreview::update(Manager& manager, Settings& settings, Resources& resources) { auto& document = *manager.get(); @@ -62,7 +132,6 @@ namespace anm2ed::animation_preview if (ImGui::Begin("Animation Preview", &settings.windowIsAnimationPreview)) { - auto childSize = ImVec2(imgui::row_widget_width_get(4), (ImGui::GetTextLineHeightWithSpacing() * 4) + (ImGui::GetStyle().WindowPadding.y * 2)); @@ -110,12 +179,7 @@ namespace anm2ed::animation_preview ImGui::SameLine(); ImGui::ColorEdit4("Color", value_ptr(axesColor), ImGuiColorEditFlags_NoInputs); - std::vector animationNames{}; - animationNames.emplace_back("None"); - for (auto& animation : anm2.animations.items) - animationNames.emplace_back(animation.name); - - imgui::combo_strings("Overlay", &overlayIndex, animationNames); + imgui::combo_strings("Overlay", &overlayIndex, document.animationNamesCStr); ImGui::InputFloat("Alpha", &overlayTransparency, 0, 0, "%.0f"); } @@ -253,6 +317,8 @@ namespace anm2ed::animation_preview for (int i = 1; i <= count; i++) { float useTime = time + (float)(direction * i); + if (useTime < 0.0f || useTime > animation->frameNum) continue; + float alphaOffset = (1.0f / (count + 1)) * i; render(animation, useTime, color, alphaOffset, true); } @@ -272,10 +338,13 @@ namespace anm2ed::animation_preview auto& isEnabled = settings.onionskinIsEnabled; if (drawOrder == draw_order::BELOW && isEnabled) onionskins_render(frameTime); + render(animation, frameTime); + if (overlayIndex > 0) render(document.anm2.animation_get({overlayIndex - 1}), frameTime, {}, 1.0f - math::uint8_to_float(overlayTransparency)); + if (drawOrder == draw_order::ABOVE && isEnabled) onionskins_render(frameTime); } @@ -285,7 +354,7 @@ namespace anm2ed::animation_preview isPreviewHovered = ImGui::IsItemHovered(); - if (animation && animation->triggers.isVisible) + if (animation && animation->triggers.isVisible && !isOnlyShowLayers) { if (auto trigger = animation->triggers.frame_generate(frameTime, anm2::TRIGGER); trigger.isVisible) { @@ -333,7 +402,7 @@ namespace anm2ed::animation_preview auto isMod = ImGui::IsKeyDown(ImGuiMod_Shift); auto frame = document.frame_get(); auto useTool = tool; - auto step = isMod ? step::FAST : step::NORMAL; + auto step = isMod ? canvas::STEP_FAST : canvas::STEP; auto isKeyPressed = isLeftPressed || isRightPressed || isUpPressed || isDownPressed; auto isKeyReleased = isLeftReleased || isRightReleased || isUpReleased || isDownReleased; auto isBegin = isMouseClick || isKeyPressed; @@ -343,6 +412,8 @@ namespace anm2ed::animation_preview if (tool == tool::MOVE && isMouseRightDown) useTool = tool::SCALE; if (tool == tool::SCALE && isMouseRightDown) useTool = tool::MOVE; + ImGui::SetMouseCursor(tool::INFO[useTool].cursor); + switch (useTool) { case tool::PAN: @@ -356,7 +427,7 @@ namespace anm2ed::animation_preview if (isRight) frame->position.x += step; if (isUp) frame->position.y -= step; if (isDown) frame->position.y += step; - if (isEnd) document.change(change::FRAMES); + if (isEnd) document.change(Document::FRAMES); break; case tool::SCALE: if (!frame) break; @@ -366,7 +437,7 @@ namespace anm2ed::animation_preview if (isRight) frame->scale.x += step; if (isUp) frame->scale.y -= step; if (isDown) frame->scale.y += step; - if (isEnd) document.change(change::FRAMES); + if (isEnd) document.change(Document::FRAMES); break; case tool::ROTATE: if (!frame) break; @@ -374,7 +445,7 @@ namespace anm2ed::animation_preview if (isMouseDown) frame->rotation += mouseDelta.y; if (isLeft || isDown) frame->rotation -= step; if (isUp || isRight) frame->rotation += step; - if (isEnd) document.change(change::FRAMES); + if (isEnd) document.change(Document::FRAMES); break; default: break; @@ -385,5 +456,27 @@ namespace anm2ed::animation_preview } } ImGui::End(); + + manager.progressPopup.trigger(); + + if (ImGui::BeginPopupModal(manager.progressPopup.label, &manager.progressPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + if (!animation) return; + + auto& start = manager.recordingStart; + auto& end = manager.recordingEnd; + auto progress = (playback.time - start) / (end - start); + + ImGui::ProgressBar(progress); + + if (ImGui::Button("Cancel", ImVec2(ImGui::GetContentRegionAvail().x, 0))) + { + playback.isPlaying = false; + manager.isRecording = false; + manager.progressPopup.close(); + } + + ImGui::EndPopup(); + } } } diff --git a/src/imgui/window/animation_preview.h b/src/imgui/window/animation_preview.h new file mode 100644 index 0000000..486e174 --- /dev/null +++ b/src/imgui/window/animation_preview.h @@ -0,0 +1,21 @@ +#pragma once + +#include "canvas.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class AnimationPreview : public Canvas + { + bool isPreviewHovered{}; + glm::ivec2 mousePos{}; + std::vector renderFrames{}; + + public: + AnimationPreview(); + void tick(Manager&, Document&, Settings&); + void update(Manager&, Settings&, Resources&); + }; +} diff --git a/src/animations.cpp b/src/imgui/window/animations.cpp similarity index 80% rename from src/animations.cpp rename to src/imgui/window/animations.cpp index 30f4ee9..c3ed704 100644 --- a/src/animations.cpp +++ b/src/imgui/window/animations.cpp @@ -2,13 +2,10 @@ #include -using namespace anm2ed::clipboard; -using namespace anm2ed::manager; -using namespace anm2ed::settings; -using namespace anm2ed::resources; +using namespace anm2ed::resource; using namespace anm2ed::types; -namespace anm2ed::animations +namespace anm2ed::imgui { void Animations::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) { @@ -24,7 +21,7 @@ namespace anm2ed::animations if (ImGui::Begin("Animations", &settings.windowIsAnimations)) { - auto childSize = imgui::size_without_footer_get(); + auto childSize = size_without_footer_get(); if (ImGui::BeginChild("##Animations Child", childSize, ImGuiChildFlags_Borders)) { @@ -44,9 +41,8 @@ namespace anm2ed::animations ImGui::PushFont(resources.fonts[font].get(), font::SIZE); ImGui::SetNextItemSelectionUserData(i); - if (imgui::selectable_input_text(animation.name, - std::format("###Document #{} Animation #{}", manager.selected, i), - animation.name, multiSelect.contains(i))) + if (selectable_input_text(animation.name, std::format("###Document #{} Animation #{}", manager.selected, i), + animation.name, multiSelect.contains(i))) document.animation_set(i); if (ImGui::IsItemHovered()) hovered = i; ImGui::PopFont(); @@ -124,9 +120,9 @@ namespace anm2ed::animations document.animations_deserialize(clipboardText); }; - if (imgui::shortcut(settings.shortcutCut, shortcut::FOCUSED)) cut(); - if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); - if (imgui::shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(); + if (shortcut(settings.shortcutCut, shortcut::FOCUSED)) cut(); + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(); if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) { @@ -144,23 +140,23 @@ namespace anm2ed::animations } ImGui::EndChild(); - auto widgetSize = imgui::widget_size_with_row_get(5); + auto widgetSize = widget_size_with_row_get(5); - imgui::shortcut(settings.shortcutAdd); + shortcut(settings.shortcutAdd); if (ImGui::Button("Add", widgetSize)) document.animation_add(); - imgui::set_item_tooltip_shortcut("Add a new animation.", settings.shortcutAdd); + set_item_tooltip_shortcut("Add a new animation.", settings.shortcutAdd); ImGui::SameLine(); ImGui::BeginDisabled(multiSelect.empty()); { - imgui::shortcut(settings.shortcutDuplicate); + shortcut(settings.shortcutDuplicate); if (ImGui::Button("Duplicate", widgetSize)) document.animation_duplicate(); - imgui::set_item_tooltip_shortcut("Duplicate the selected animation(s).", settings.shortcutDuplicate); + set_item_tooltip_shortcut("Duplicate the selected animation(s).", settings.shortcutDuplicate); ImGui::SameLine(); - if (imgui::shortcut(settings.shortcutMerge, shortcut::FOCUSED)) + if (shortcut(settings.shortcutMerge, shortcut::FOCUSED)) if (multiSelect.size() > 0) document.animations_merge_quick(); ImGui::BeginDisabled(multiSelect.size() != 1); @@ -174,24 +170,23 @@ namespace anm2ed::animations } ImGui::EndDisabled(); - imgui::set_item_tooltip_shortcut( - "Open the merge popup.\nUsing the shortcut will merge the animations with\nthe last " - "configured merge settings.", - settings.shortcutMerge); + set_item_tooltip_shortcut("Open the merge popup.\nUsing the shortcut will merge the animations with\nthe last " + "configured merge settings.", + settings.shortcutMerge); ImGui::SameLine(); - imgui::shortcut(settings.shortcutRemove); + shortcut(settings.shortcutRemove); if (ImGui::Button("Remove", widgetSize)) document.animations_remove(); - imgui::set_item_tooltip_shortcut("Remove the selected animation(s).", settings.shortcutDuplicate); + set_item_tooltip_shortcut("Remove the selected animation(s).", settings.shortcutDuplicate); ImGui::SameLine(); - imgui::shortcut(settings.shortcutDefault); + shortcut(settings.shortcutDefault); ImGui::BeginDisabled(multiSelect.size() != 1); if (ImGui::Button("Default", widgetSize)) document.animation_default(); ImGui::EndDisabled(); - imgui::set_item_tooltip_shortcut("Set the selected animation as the default.", settings.shortcutDefault); + set_item_tooltip_shortcut("Set the selected animation as the default.", settings.shortcutDefault); } ImGui::EndDisabled(); @@ -208,9 +203,9 @@ namespace anm2ed::animations auto& type = settings.mergeType; auto& isDeleteAnimationsAfter = settings.mergeIsDeleteAnimationsAfter; - auto footerSize = imgui::footer_size_get(); - auto optionsSize = imgui::child_size_get(2); - auto deleteAfterSize = imgui::child_size_get(); + auto footerSize = footer_size_get(); + auto optionsSize = child_size_get(2); + auto deleteAfterSize = child_size_get(); auto animationsSize = ImVec2(0, ImGui::GetContentRegionAvail().y - (optionsSize.y + deleteAfterSize.y + footerSize.y + ImGui::GetStyle().ItemSpacing.y * 3)); @@ -259,7 +254,7 @@ namespace anm2ed::animations ImGui::Checkbox("Delete Animations After", &isDeleteAnimationsAfter); ImGui::EndChild(); - auto widgetSize = imgui::widget_size_with_row_get(2); + auto widgetSize = widget_size_with_row_get(2); if (ImGui::Button("Merge", widgetSize)) { diff --git a/src/imgui/window/animations.h b/src/imgui/window/animations.h new file mode 100644 index 0000000..6257a29 --- /dev/null +++ b/src/imgui/window/animations.h @@ -0,0 +1,17 @@ +#pragma once + +#include "clipboard.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Animations + { + PopupHelper mergePopup{PopupHelper("Merge Animations")}; + + public: + void update(Manager&, Settings&, Resources&, Clipboard&); + }; +} diff --git a/src/imgui/window/events.cpp b/src/imgui/window/events.cpp new file mode 100644 index 0000000..fa3da45 --- /dev/null +++ b/src/imgui/window/events.cpp @@ -0,0 +1,160 @@ +#include "events.h" + +#include + +using namespace anm2ed::resource; +using namespace anm2ed::types; + +namespace anm2ed::imgui +{ + void Events::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& unused = document.unusedEventIDs; + auto& hovered = document.hoveredEvent; + auto& reference = document.referenceEvent; + auto& multiSelect = document.eventMultiSelect; + + hovered = -1; + + if (ImGui::Begin("Events", &settings.windowIsEvents)) + { + auto childSize = size_without_footer_get(); + + if (ImGui::BeginChild("##Events Child", childSize, true)) + { + multiSelect.start(anm2.content.events.size()); + + for (auto& [id, event] : anm2.content.events) + { + ImGui::PushID(id); + ImGui::SetNextItemSelectionUserData(id); + ImGui::Selectable(event.name.c_str(), multiSelect.contains(id)); + if (ImGui::IsItemHovered()) + { + hovered = id; + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + { + reference = id; + editEvent = document.anm2.content.events[reference]; + propertiesPopup.open(); + } + } + + if (ImGui::BeginItemTooltip()) + { + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); + ImGui::TextUnformatted(event.name.c_str()); + ImGui::PopFont(); + ImGui::EndTooltip(); + } + ImGui::PopID(); + } + + multiSelect.finish(); + + auto copy = [&]() + { + if (!multiSelect.empty()) + { + std::string clipboardText{}; + for (auto& id : multiSelect) + clipboardText += anm2.content.events[id].to_string(id); + clipboard.set(clipboardText); + } + else if (hovered > -1) + clipboard.set(anm2.content.events[hovered].to_string(hovered)); + }; + + auto paste = [&](merge::Type type) + { + auto clipboardText = clipboard.get(); + document.events_deserialize(clipboardText, type); + }; + + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::BeginDisabled(); + ImGui::MenuItem("Cut", settings.shortcutCut.c_str()); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(multiSelect.empty() && hovered == -1); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(clipboard.is_empty()); + { + if (ImGui::BeginMenu("Paste")) + { + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + + ImGui::EndMenu(); + } + } + ImGui::EndDisabled(); + + ImGui::EndPopup(); + } + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + shortcut(settings.shortcutAdd); + if (ImGui::Button("Add", widgetSize)) + { + reference = -1; + editEvent = anm2::Event(); + propertiesPopup.open(); + } + set_item_tooltip_shortcut("Add an event.", settings.shortcutAdd); + ImGui::SameLine(); + + shortcut(settings.shortcutRemove); + ImGui::BeginDisabled(unused.empty()); + if (ImGui::Button("Remove Unused", widgetSize)) document.events_remove_unused(); + ImGui::EndDisabled(); + set_item_tooltip_shortcut("Remove unused events (i.e., ones not used by any trigger in any animation.)", + settings.shortcutRemove); + } + ImGui::End(); + + propertiesPopup.trigger(); + + if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto childSize = child_size_get(2); + auto& event = editEvent; + + if (ImGui::BeginChild("Child", childSize, ImGuiChildFlags_Borders)) + { + if (propertiesPopup.isJustOpened) ImGui::SetKeyboardFocusHere(); + input_text_string("Name", &event.name); + ImGui::SetItemTooltip("Set the event's name."); + combo_strings("Sound", &event.soundID, document.soundNames); + ImGui::SetItemTooltip("Set the event sound; it will play when a trigger associated with this event activates."); + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + if (ImGui::Button(reference == -1 ? "Add" : "Confirm", widgetSize)) + { + document.event_set(event); + propertiesPopup.close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) propertiesPopup.close(); + + propertiesPopup.end(); + ImGui::EndPopup(); + } + } +} diff --git a/src/imgui/window/events.h b/src/imgui/window/events.h new file mode 100644 index 0000000..25a3705 --- /dev/null +++ b/src/imgui/window/events.h @@ -0,0 +1,18 @@ +#pragma once + +#include "clipboard.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Events + { + anm2::Event editEvent{}; + PopupHelper propertiesPopup{PopupHelper("Event Properties", POPUP_SMALL_NO_HEIGHT)}; + + public: + void update(Manager&, Settings&, Resources&, Clipboard&); + }; +} diff --git a/src/imgui/window/frame_properties.cpp b/src/imgui/window/frame_properties.cpp new file mode 100644 index 0000000..f83b002 --- /dev/null +++ b/src/imgui/window/frame_properties.cpp @@ -0,0 +1,125 @@ +#include "frame_properties.h" + +#include + +#include + +#include "math_.h" +#include "types.h" + +using namespace anm2ed::util::math; +using namespace anm2ed::types; +using namespace glm; + +namespace anm2ed::imgui +{ + void FrameProperties::update(Manager& manager, Settings& settings) + { + if (ImGui::Begin("Frame Properties", &settings.windowIsFrameProperties)) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& reference = document.reference; + auto& type = reference.itemType; + auto frame = document.frame_get(); + auto useFrame = frame ? *frame : anm2::Frame(); + + ImGui::BeginDisabled(!frame); + { + if (type == anm2::TRIGGER) + { + std::vector eventNames{}; + for (auto& event : anm2.content.events | std::views::values) + eventNames.emplace_back(event.name); + + if (imgui::combo_strings("Event", frame ? &useFrame.eventID : &dummy_value(), eventNames)) + DOCUMENT_EDIT(document, "Trigger Event", Document::FRAMES, frame->eventID = useFrame.eventID); + ImGui::SetItemTooltip("Change the event this trigger uses."); + if (ImGui::InputInt("At Frame", frame ? &useFrame.atFrame : &dummy_value(), imgui::STEP, + imgui::STEP_FAST, !frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0)) + DOCUMENT_EDIT(document, "Trigger At Frame", Document::FRAMES, frame->atFrame = useFrame.atFrame); + ImGui::SetItemTooltip("Change the frame the trigger will be activated at."); + } + else + { + ImGui::BeginDisabled(type == anm2::ROOT || type == anm2::NULL_); + { + if (ImGui::InputFloat2("Crop", frame ? value_ptr(useFrame.crop) : &dummy_value(), + frame ? vec2_format_get(useFrame.crop) : "")) + DOCUMENT_EDIT(document, "Frame Crop", Document::FRAMES, frame->crop = useFrame.crop); + ImGui::SetItemTooltip("Change the crop position the frame uses."); + + if (ImGui::InputFloat2("Size", frame ? value_ptr(useFrame.size) : &dummy_value(), + frame ? vec2_format_get(useFrame.size) : "")) + DOCUMENT_EDIT(document, "Frame Size", Document::FRAMES, frame->size = useFrame.size); + ImGui::SetItemTooltip("Change the size of the crop the frame uses."); + } + ImGui::EndDisabled(); + + if (ImGui::InputFloat2("Position", frame ? value_ptr(useFrame.position) : &dummy_value(), + frame ? vec2_format_get(useFrame.position) : "")) + DOCUMENT_EDIT(document, "Frame Position", Document::FRAMES, frame->position = useFrame.position); + ImGui::SetItemTooltip("Change the position of the frame."); + + ImGui::BeginDisabled(type == anm2::ROOT || type == anm2::NULL_); + { + if (ImGui::InputFloat2("Pivot", frame ? value_ptr(useFrame.pivot) : &dummy_value(), + frame ? vec2_format_get(useFrame.pivot) : "")) + DOCUMENT_EDIT(document, "Frame Pivot", Document::FRAMES, frame->pivot = useFrame.pivot); + ImGui::SetItemTooltip("Change the pivot of the frame; i.e., where it is centered."); + } + ImGui::EndDisabled(); + + if (ImGui::InputFloat2("Scale", frame ? value_ptr(useFrame.scale) : &dummy_value(), + frame ? vec2_format_get(useFrame.scale) : "")) + DOCUMENT_EDIT(document, "Frame Scale", Document::FRAMES, frame->scale = useFrame.scale); + ImGui::SetItemTooltip("Change the scale of the frame, in percent."); + + if (ImGui::InputFloat("Rotation", frame ? &useFrame.rotation : &dummy_value(), imgui::STEP, + imgui::STEP_FAST, frame ? float_format_get(useFrame.rotation) : "")) + DOCUMENT_EDIT(document, "Frame Rotation", Document::FRAMES, frame->rotation = useFrame.rotation); + ImGui::SetItemTooltip("Change the rotation of the frame."); + + if (ImGui::InputInt("Duration", frame ? &useFrame.delay : &dummy_value(), imgui::STEP, imgui::STEP_FAST, + !frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0)) + DOCUMENT_EDIT(document, "Frame Duration", Document::FRAMES, frame->delay = useFrame.delay); + ImGui::SetItemTooltip("Change how long the frame lasts."); + + if (ImGui::ColorEdit4("Tint", frame ? value_ptr(useFrame.tint) : &dummy_value())) + DOCUMENT_EDIT(document, "Frame Tint", Document::FRAMES, frame->tint = useFrame.tint); + ImGui::SetItemTooltip("Change the tint of the frame."); + + if (ImGui::ColorEdit3("Color Offset", frame ? value_ptr(useFrame.colorOffset) : &dummy_value())) + DOCUMENT_EDIT(document, "Frame Color Offset", Document::FRAMES, frame->colorOffset = useFrame.colorOffset); + ImGui::SetItemTooltip("Change the color added onto the frame."); + + if (ImGui::Checkbox("Visible", frame ? &useFrame.isVisible : &dummy_value())) + DOCUMENT_EDIT(document, "Frame Visibility", Document::FRAMES, frame->isVisible = useFrame.isVisible); + ImGui::SetItemTooltip("Toggle the frame's visibility."); + + ImGui::SameLine(); + + if (ImGui::Checkbox("Interpolated", frame ? &useFrame.isInterpolated : &dummy_value())) + DOCUMENT_EDIT(document, "Frame Interpolation", Document::FRAMES, + frame->isInterpolated = useFrame.isInterpolated); + ImGui::SetItemTooltip( + "Toggle the frame interpolating; i.e., blending its values into the next frame based on the time."); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + if (ImGui::Button("Flip X", widgetSize)) + DOCUMENT_EDIT(document, "Frame Flip X", Document::FRAMES, frame->scale.x = -frame->scale.x); + ImGui::SetItemTooltip("%s", "Flip the horizontal scale of the frame, to cheat mirroring the frame " + "horizontally.\n(Note: the format does not support mirroring.)"); + ImGui::SameLine(); + if (ImGui::Button("Flip Y", widgetSize)) + DOCUMENT_EDIT(document, "Frame Flip Y", Document::FRAMES, frame->scale.y = -frame->scale.y); + ImGui::SetItemTooltip("%s", "Flip the vertical scale of the frame, to cheat mirroring the frame " + "vertically.\n(Note: the format does not support mirroring.)"); + } + } + ImGui::EndDisabled(); + } + ImGui::End(); + } +} \ No newline at end of file diff --git a/src/frame_properties.h b/src/imgui/window/frame_properties.h similarity index 53% rename from src/frame_properties.h rename to src/imgui/window/frame_properties.h index ab092ee..d8cfd86 100644 --- a/src/frame_properties.h +++ b/src/imgui/window/frame_properties.h @@ -3,11 +3,11 @@ #include "manager.h" #include "settings.h" -namespace anm2ed::frame_properties +namespace anm2ed::imgui { class FrameProperties { public: - void update(manager::Manager&, settings::Settings&); + void update(Manager&, Settings&); }; } diff --git a/src/layers.cpp b/src/imgui/window/layers.cpp similarity index 79% rename from src/layers.cpp rename to src/imgui/window/layers.cpp index e7ae3a3..1b12e34 100644 --- a/src/layers.cpp +++ b/src/imgui/window/layers.cpp @@ -2,14 +2,10 @@ #include -using namespace anm2ed::document; -using namespace anm2ed::clipboard; -using namespace anm2ed::manager; -using namespace anm2ed::resources; -using namespace anm2ed::settings; +using namespace anm2ed::resource; using namespace anm2ed::types; -namespace anm2ed::layers +namespace anm2ed::imgui { void Layers::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) { @@ -25,7 +21,7 @@ namespace anm2ed::layers if (ImGui::Begin("Layers", &settings.windowIsLayers)) { - auto childSize = imgui::size_without_footer_get(); + auto childSize = size_without_footer_get(); if (ImGui::BeginChild("##Layers Child", childSize, true)) { @@ -80,8 +76,8 @@ namespace anm2ed::layers document.layers_deserialize(clipboardText, type); }; - if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); - if (imgui::shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) { @@ -110,19 +106,19 @@ namespace anm2ed::layers } ImGui::EndChild(); - auto widgetSize = imgui::widget_size_with_row_get(2); + auto widgetSize = widget_size_with_row_get(2); - imgui::shortcut(settings.shortcutAdd); + shortcut(settings.shortcutAdd); if (ImGui::Button("Add", widgetSize)) manager.layer_properties_open(); - imgui::set_item_tooltip_shortcut("Add a layer.", settings.shortcutAdd); + set_item_tooltip_shortcut("Add a layer.", settings.shortcutAdd); ImGui::SameLine(); - imgui::shortcut(settings.shortcutRemove); + shortcut(settings.shortcutRemove); ImGui::BeginDisabled(unused.empty()); if (ImGui::Button("Remove Unused", widgetSize)) document.layers_remove_unused(); ImGui::EndDisabled(); - imgui::set_item_tooltip_shortcut("Remove unused layers (i.e., ones not used in any animation.)", - settings.shortcutRemove); + set_item_tooltip_shortcut("Remove unused layers (i.e., ones not used in any animation.)", + settings.shortcutRemove); } ImGui::End(); @@ -130,20 +126,20 @@ namespace anm2ed::layers if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) { - auto childSize = imgui::child_size_get(2); + auto childSize = child_size_get(2); auto& layer = manager.editLayer; if (ImGui::BeginChild("Child", childSize, ImGuiChildFlags_Borders)) { if (propertiesPopup.isJustOpened) ImGui::SetKeyboardFocusHere(); - imgui::input_text_string("Name", &layer.name); + input_text_string("Name", &layer.name); ImGui::SetItemTooltip("Set the item's name."); - imgui::combo_strings("Spritesheet", &layer.spritesheetID, document.spritesheetNames); + combo_strings("Spritesheet", &layer.spritesheetID, document.spritesheetNames); ImGui::SetItemTooltip("Set the layer item's spritesheet."); } ImGui::EndChild(); - auto widgetSize = imgui::widget_size_with_row_get(2); + auto widgetSize = widget_size_with_row_get(2); if (ImGui::Button(reference == -1 ? "Add" : "Confirm", widgetSize)) { diff --git a/src/layers.h b/src/imgui/window/layers.h similarity index 52% rename from src/layers.h rename to src/imgui/window/layers.h index e72c331..2431571 100644 --- a/src/layers.h +++ b/src/imgui/window/layers.h @@ -5,11 +5,11 @@ #include "resources.h" #include "settings.h" -namespace anm2ed::layers +namespace anm2ed::imgui { class Layers { public: - void update(manager::Manager&, settings::Settings&, resources::Resources&, clipboard::Clipboard&); + void update(Manager&, Settings&, Resources&, Clipboard&); }; } diff --git a/src/nulls.cpp b/src/imgui/window/nulls.cpp similarity index 82% rename from src/nulls.cpp rename to src/imgui/window/nulls.cpp index 42879e1..302674c 100644 --- a/src/nulls.cpp +++ b/src/imgui/window/nulls.cpp @@ -2,13 +2,10 @@ #include -using namespace anm2ed::clipboard; -using namespace anm2ed::manager; -using namespace anm2ed::settings; -using namespace anm2ed::resources; +using namespace anm2ed::resource; using namespace anm2ed::types; -namespace anm2ed::nulls +namespace anm2ed::imgui { void Nulls::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) { @@ -24,7 +21,7 @@ namespace anm2ed::nulls if (ImGui::Begin("Nulls", &settings.windowIsNulls)) { - auto childSize = imgui::size_without_footer_get(); + auto childSize = size_without_footer_get(); if (ImGui::BeginChild("##Nulls Child", childSize, true)) { @@ -79,8 +76,8 @@ namespace anm2ed::nulls document.nulls_deserialize(clipboardText, type); }; - if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); - if (imgui::shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) { @@ -109,19 +106,18 @@ namespace anm2ed::nulls } ImGui::EndChild(); - auto widgetSize = imgui::widget_size_with_row_get(2); + auto widgetSize = widget_size_with_row_get(2); - imgui::shortcut(settings.shortcutAdd); + shortcut(settings.shortcutAdd); if (ImGui::Button("Add", widgetSize)) manager.null_properties_open(); - imgui::set_item_tooltip_shortcut("Add a null.", settings.shortcutAdd); + set_item_tooltip_shortcut("Add a null.", settings.shortcutAdd); ImGui::SameLine(); - imgui::shortcut(settings.shortcutRemove); + shortcut(settings.shortcutRemove); ImGui::BeginDisabled(unused.empty()); if (ImGui::Button("Remove Unused", widgetSize)) document.nulls_remove_unused(); ImGui::EndDisabled(); - imgui::set_item_tooltip_shortcut("Remove unused nulls (i.e., ones not used in any animation.)", - settings.shortcutRemove); + set_item_tooltip_shortcut("Remove unused nulls (i.e., ones not used in any animation.)", settings.shortcutRemove); } ImGui::End(); @@ -129,13 +125,13 @@ namespace anm2ed::nulls if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) { - auto childSize = imgui::child_size_get(2); + auto childSize = child_size_get(2); auto& null = manager.editNull; if (ImGui::BeginChild("Child", childSize, ImGuiChildFlags_Borders)) { if (propertiesPopup.isJustOpened) ImGui::SetKeyboardFocusHere(); - imgui::input_text_string("Name", &null.name); + input_text_string("Name", &null.name); ImGui::SetItemTooltip("Set the null's name."); ImGui::Checkbox("Rect", &null.isShowRect); @@ -143,7 +139,7 @@ namespace anm2ed::nulls } ImGui::EndChild(); - auto widgetSize = imgui::widget_size_with_row_get(2); + auto widgetSize = widget_size_with_row_get(2); if (ImGui::Button(reference == -1 ? "Add" : "Confirm", widgetSize)) { diff --git a/src/nulls.h b/src/imgui/window/nulls.h similarity index 52% rename from src/nulls.h rename to src/imgui/window/nulls.h index 1eba1bb..7ffd1fd 100644 --- a/src/nulls.h +++ b/src/imgui/window/nulls.h @@ -5,11 +5,11 @@ #include "resources.h" #include "settings.h" -namespace anm2ed::nulls +namespace anm2ed::imgui { class Nulls { public: - void update(manager::Manager&, settings::Settings&, resources::Resources&, clipboard::Clipboard&); + void update(Manager&, Settings&, Resources&, Clipboard&); }; } \ No newline at end of file diff --git a/src/imgui/window/onionskin.cpp b/src/imgui/window/onionskin.cpp new file mode 100644 index 0000000..793d5b1 --- /dev/null +++ b/src/imgui/window/onionskin.cpp @@ -0,0 +1,55 @@ +#include "onionskin.h" + +#include + +#include "imgui_.h" + +using namespace anm2ed::types; +using namespace glm; + +namespace anm2ed::imgui +{ + constexpr auto FRAMES_MAX = 100; + + void Onionskin::update(Settings& settings) + { + auto& isEnabled = settings.onionskinIsEnabled; + auto& beforeCount = settings.onionskinBeforeCount; + auto& beforeColor = settings.onionskinBeforeColor; + auto& afterCount = settings.onionskinAfterCount; + auto& afterColor = settings.onionskinAfterColor; + auto& drawOrder = settings.onionskinDrawOrder; + + if (ImGui::Begin("Onionskin", &settings.windowIsOnionskin)) + { + auto configure_widgets = [&](const char* separator, int& frames, vec3& color) + { + ImGui::PushID(separator); + ImGui::SeparatorText(separator); + input_int_range("Frames", frames, 0, FRAMES_MAX); + ImGui::SetItemTooltip("Change the amount of frames this onionskin will use."); + ImGui::ColorEdit3("Color", value_ptr(color)); + ImGui::SetItemTooltip("Change the color of the frames this onionskin will use."); + ImGui::PopID(); + }; + + ImGui::Checkbox("Enabled", &isEnabled); + set_item_tooltip_shortcut("Toggle onionskinning.", settings.shortcutOnionskin); + + configure_widgets("Before", beforeCount, beforeColor); + configure_widgets("After", afterCount, afterColor); + + ImGui::Text("Draw Order"); + ImGui::SameLine(); + ImGui::RadioButton("Below", &drawOrder, draw_order::BELOW); + ImGui::SetItemTooltip("The onionskin frames will draw below the original frames."); + ImGui::SameLine(); + ImGui::RadioButton("Above", &drawOrder, draw_order::ABOVE); + ImGui::SetItemTooltip("The onionskin frames will draw above the original frames."); + } + ImGui::End(); + + if (shortcut(settings.shortcutOnionskin, shortcut::GLOBAL)) isEnabled = !isEnabled; + } + +} diff --git a/src/onionskin.h b/src/imgui/window/onionskin.h similarity index 54% rename from src/onionskin.h rename to src/imgui/window/onionskin.h index 43f9358..6b23aed 100644 --- a/src/onionskin.h +++ b/src/imgui/window/onionskin.h @@ -2,11 +2,11 @@ #include "settings.h" -namespace anm2ed::onionskin +namespace anm2ed::imgui { class Onionskin { public: - void update(settings::Settings&); + void update(Settings&); }; } diff --git a/src/events.cpp b/src/imgui/window/sounds.cpp similarity index 54% rename from src/events.cpp rename to src/imgui/window/sounds.cpp index cc8a417..c567d62 100644 --- a/src/events.cpp +++ b/src/imgui/window/sounds.cpp @@ -1,47 +1,58 @@ -#include "events.h" +#include "sounds.h" #include -using namespace anm2ed::clipboard; -using namespace anm2ed::manager; -using namespace anm2ed::settings; -using namespace anm2ed::resources; +using namespace anm2ed::dialog; using namespace anm2ed::types; +using namespace anm2ed::resource; -namespace anm2ed::events +namespace anm2ed::imgui { - void Events::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) + void Sounds::update(Manager& manager, Settings& settings, Resources& resources, Dialog& dialog, Clipboard& clipboard) { auto& document = *manager.get(); auto& anm2 = document.anm2; - auto& unused = document.unusedEventIDs; - auto& hovered = document.hoveredEvent; - auto& multiSelect = document.eventMultiSelect; + auto& reference = document.referenceNull; + auto& unused = document.unusedNullIDs; + auto& hovered = document.hoveredNull; + auto& multiSelect = document.soundMultiSelect; hovered = -1; - if (ImGui::Begin("Events", &settings.windowIsEvents)) + if (ImGui::Begin("Sounds", &settings.windowIsSounds)) { auto childSize = imgui::size_without_footer_get(); - bool isRenamed{}; - if (ImGui::BeginChild("##Events Child", childSize, true)) + if (ImGui::BeginChild("##Sounds Child", childSize, true)) { - multiSelect.start(anm2.content.events.size()); + multiSelect.start(anm2.content.sounds.size()); - for (auto& [id, event] : anm2.content.events) + for (auto& [id, sound] : anm2.content.sounds) { + auto isSelected = multiSelect.contains(id); + auto isReferenced = reference == id; + ImGui::PushID(id); ImGui::SetNextItemSelectionUserData(id); - if (imgui::selectable_input_text(event.name, std::format("###Document #{} Event #{}", manager.selected, id), - event.name, multiSelect.contains(id), 0, &isRenamed)) - if (ImGui::IsItemHovered()) hovered = id; - if (isRenamed) document.change(change::EVENTS); + if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); + if (ImGui::Selectable(std::format(anm2::SOUND_FORMAT, id, sound.path.string()).c_str(), isSelected)) + sound.audio.play(); + if (ImGui::IsItemHovered()) + { + hovered = id; + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + ; + } + + if (isReferenced) ImGui::PopFont(); + if (ImGui::BeginItemTooltip()) { ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); - ImGui::TextUnformatted(event.name.c_str()); + ImGui::TextUnformatted(sound.path.c_str()); ImGui::PopFont(); + ImGui::Text("ID: %d", id); + ImGui::Text("Click to play."); ImGui::EndTooltip(); } ImGui::PopID(); @@ -55,17 +66,17 @@ namespace anm2ed::events { std::string clipboardText{}; for (auto& id : multiSelect) - clipboardText += anm2.content.events[id].to_string(id); + clipboardText += anm2.content.sounds[id].to_string(id); clipboard.set(clipboardText); } else if (hovered > -1) - clipboard.set(anm2.content.events[hovered].to_string(hovered)); + clipboard.set(anm2.content.sounds[hovered].to_string(hovered)); }; auto paste = [&](merge::Type type) { auto clipboardText = clipboard.get(); - document.events_deserialize(clipboardText, type); + document.sounds_deserialize(clipboardText, type); }; if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); @@ -101,17 +112,24 @@ namespace anm2ed::events auto widgetSize = imgui::widget_size_with_row_get(2); imgui::shortcut(settings.shortcutAdd); - if (ImGui::Button("Add", widgetSize)) document.event_add(); - imgui::set_item_tooltip_shortcut("Add an event.", settings.shortcutAdd); + if (ImGui::Button("Add", widgetSize)) dialog.file_open(dialog::SOUND_OPEN); + imgui::set_item_tooltip_shortcut("Add a sound.", settings.shortcutAdd); ImGui::SameLine(); imgui::shortcut(settings.shortcutRemove); ImGui::BeginDisabled(unused.empty()); - if (ImGui::Button("Remove Unused", widgetSize)) document.events_remove_unused(); + if (ImGui::Button("Remove Unused", widgetSize)) + ; ImGui::EndDisabled(); - imgui::set_item_tooltip_shortcut("Remove unused events (i.e., ones not used by any trigger in any animation.)", + imgui::set_item_tooltip_shortcut("Remove unused sounds (i.e., ones not used in any trigger.)", settings.shortcutRemove); } ImGui::End(); + + if (dialog.is_selected(dialog::SOUND_OPEN)) + { + document.sound_add(dialog.path); + dialog.reset(); + } } -} +} \ No newline at end of file diff --git a/src/imgui/window/sounds.h b/src/imgui/window/sounds.h new file mode 100644 index 0000000..c39efa6 --- /dev/null +++ b/src/imgui/window/sounds.h @@ -0,0 +1,16 @@ +#pragma once + +#include "clipboard.h" +#include "dialog.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Sounds + { + public: + void update(Manager&, Settings&, Resources&, Dialog&, Clipboard&); + }; +} diff --git a/src/spritesheet_editor.cpp b/src/imgui/window/spritesheet_editor.cpp similarity index 96% rename from src/spritesheet_editor.cpp rename to src/imgui/window/spritesheet_editor.cpp index 5861fbd..8a0f9de 100644 --- a/src/spritesheet_editor.cpp +++ b/src/imgui/window/spritesheet_editor.cpp @@ -1,18 +1,16 @@ #include "spritesheet_editor.h" -#include "imgui.h" -#include "math.h" +#include "math_.h" #include "tool.h" #include "types.h" -using namespace anm2ed::manager; -using namespace anm2ed::settings; using namespace anm2ed::canvas; -using namespace anm2ed::resources; using namespace anm2ed::types; +using namespace anm2ed::resource; +using namespace anm2ed::util; using namespace glm; -namespace anm2ed::spritesheet_editor +namespace anm2ed::imgui { constexpr auto PIVOT_COLOR = color::PINK; @@ -167,6 +165,8 @@ namespace anm2ed::spritesheet_editor if (isMouseMiddleDown) useTool = tool::PAN; + ImGui::SetMouseCursor(tool::INFO[useTool].cursor); + switch (useTool) { case tool::PAN: @@ -180,7 +180,7 @@ namespace anm2ed::spritesheet_editor if (isRight) frame->pivot.x += step; if (isUp) frame->pivot.y -= step; if (isDown) frame->pivot.y += step; - if (isEnd) document.change(change::FRAMES); + if (isEnd) document.change(Document::FRAMES); break; case tool::CROP: if (!frame) break; @@ -191,7 +191,7 @@ namespace anm2ed::spritesheet_editor if (isRight) isMod ? frame->size.x += step : frame->crop.x += step; if (isUp) isMod ? frame->size.y -= step : frame->crop.y -= step; if (isDown) isMod ? frame->size.y += step : frame->crop.y += step; - if (isEnd) document.change(change::FRAMES); + if (isEnd) document.change(Document::FRAMES); break; case tool::DRAW: case tool::ERASE: @@ -200,7 +200,7 @@ namespace anm2ed::spritesheet_editor auto color = tool == tool::DRAW ? toolColor : vec4(); if (isMouseClicked) document.snapshot(tool == tool::DRAW ? "Draw" : "Erase"); if (isMouseDown) spritesheet->texture.pixel_line(ivec2(previousMousePos), ivec2(mousePos), color); - if (isMouseReleased) document.change(change::FRAMES); + if (isMouseReleased) document.change(Document::FRAMES); break; } case tool::COLOR_PICKER: diff --git a/src/spritesheet_editor.h b/src/imgui/window/spritesheet_editor.h similarity index 55% rename from src/spritesheet_editor.h rename to src/imgui/window/spritesheet_editor.h index 13fdb13..55db23d 100644 --- a/src/spritesheet_editor.h +++ b/src/imgui/window/spritesheet_editor.h @@ -5,15 +5,15 @@ #include "resources.h" #include "settings.h" -namespace anm2ed::spritesheet_editor +namespace anm2ed::imgui { - class SpritesheetEditor : public canvas::Canvas + class SpritesheetEditor : public Canvas { glm::vec2 mousePos{}; glm::vec2 previousMousePos{}; public: SpritesheetEditor(); - void update(manager::Manager&, settings::Settings&, resources::Resources&); + void update(Manager&, Settings&, Resources&); }; } diff --git a/src/spritesheets.cpp b/src/imgui/window/spritesheets.cpp similarity index 90% rename from src/spritesheets.cpp rename to src/imgui/window/spritesheets.cpp index ea8c78f..2d22b13 100644 --- a/src/spritesheets.cpp +++ b/src/imgui/window/spritesheets.cpp @@ -2,21 +2,13 @@ #include -#include "imgui.h" #include "toast.h" -using namespace anm2ed::anm2; -using namespace anm2ed::clipboard; -using namespace anm2ed::manager; -using namespace anm2ed::settings; -using namespace anm2ed::resources; -using namespace anm2ed::dialog; -using namespace anm2ed::document; using namespace anm2ed::types; -using namespace anm2ed::toast; +using namespace anm2ed::resource; using namespace glm; -namespace anm2ed::spritesheets +namespace anm2ed::imgui { void Spritesheets::update(Manager& manager, Settings& settings, Resources& resources, Dialog& dialog, Clipboard& clipboard) @@ -175,7 +167,7 @@ namespace anm2ed::spritesheets spritesheetChildSize.y - spritesheetChildSize.y / 2 - ImGui::GetTextLineHeight() / 2)); if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); - ImGui::Text(SPRITESHEET_FORMAT, id, path); + ImGui::Text(anm2::SPRITESHEET_FORMAT_C, id, path); if (isReferenced) ImGui::PopFont(); context_menu(); @@ -196,10 +188,10 @@ namespace anm2ed::spritesheets auto rowOneWidgetSize = imgui::widget_size_with_row_get(4); imgui::shortcut(settings.shortcutAdd); - if (ImGui::Button("Add", rowOneWidgetSize)) dialog.spritesheet_open(); + if (ImGui::Button("Add", rowOneWidgetSize)) dialog.file_open(dialog::SPRITESHEET_OPEN); imgui::set_item_tooltip_shortcut("Add a new spritesheet.", settings.shortcutAdd); - if (dialog.is_selected_file(dialog::SPRITESHEET_OPEN)) + if (dialog.is_selected(dialog::SPRITESHEET_OPEN)) { document.spritesheet_add(dialog.path); dialog.reset(); @@ -213,7 +205,7 @@ namespace anm2ed::spritesheets { for (auto& id : multiSelect) { - Spritesheet& spritesheet = anm2.content.spritesheets[id]; + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; spritesheet.reload(document.directory_get()); toasts.info(std::format("Reloaded spritesheet #{}: {}", id, spritesheet.path.string())); } @@ -226,16 +218,16 @@ namespace anm2ed::spritesheets ImGui::BeginDisabled(multiSelect.size() != 1); { - if (ImGui::Button("Replace", rowOneWidgetSize)) dialog.spritesheet_replace(); + if (ImGui::Button("Replace", rowOneWidgetSize)) dialog.file_open(dialog::SPRITESHEET_REPLACE); ImGui::SetItemTooltip("Replace the selected spritesheet with a new one."); } ImGui::EndDisabled(); - if (dialog.is_selected_file(dialog::SPRITESHEET_REPLACE)) + if (dialog.is_selected(dialog::SPRITESHEET_REPLACE)) { auto& id = *multiSelect.begin(); - Spritesheet& spritesheet = anm2.content.spritesheets[id]; - spritesheet = Spritesheet(document.directory_get(), dialog.path); + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; + spritesheet = anm2::Spritesheet(document.directory_get(), dialog.path); toasts.info(std::format("Replaced spritesheet #{}: {}", id, spritesheet.path.string())); dialog.reset(); } @@ -249,12 +241,12 @@ namespace anm2ed::spritesheets { for (auto& id : unused) { - Spritesheet& spritesheet = anm2.content.spritesheets[id]; + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; toasts.info(std::format("Removed spritesheet #{}: {}", id, spritesheet.path.string())); anm2.spritesheet_remove(id); } unused.clear(); - document.change(change::SPRITESHEETS); + document.change(Document::SPRITESHEETS); } imgui::set_item_tooltip_shortcut("Remove all unused spritesheets (i.e., not used in any layer.).", settings.shortcutRemove); @@ -289,7 +281,7 @@ namespace anm2ed::spritesheets { for (auto& id : multiSelect) { - Spritesheet& spritesheet = anm2.content.spritesheets[id]; + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; if (spritesheet.save(document.directory_get())) toasts.info(std::format("Saved spritesheet #{}: {}", id, spritesheet.path.string())); else diff --git a/src/imgui/window/spritesheets.h b/src/imgui/window/spritesheets.h new file mode 100644 index 0000000..f012e8b --- /dev/null +++ b/src/imgui/window/spritesheets.h @@ -0,0 +1,16 @@ +#pragma once + +#include "clipboard.h" +#include "dialog.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Spritesheets + { + public: + void update(Manager&, Settings&, Resources&, Dialog&, Clipboard& clipboard); + }; +} diff --git a/src/timeline.cpp b/src/imgui/window/timeline.cpp similarity index 96% rename from src/timeline.cpp rename to src/imgui/window/timeline.cpp index dfdfeb0..f845b1a 100644 --- a/src/timeline.cpp +++ b/src/imgui/window/timeline.cpp @@ -4,17 +4,11 @@ #include -#include "imgui.h" - +using namespace anm2ed::resource; using namespace anm2ed::types; -using namespace anm2ed::manager; -using namespace anm2ed::resources; -using namespace anm2ed::settings; -using namespace anm2ed::playback; -using namespace anm2ed::clipboard; using namespace glm; -namespace anm2ed::timeline +namespace anm2ed::imgui { constexpr auto ROOT_COLOR = ImVec4(0.140f, 0.310f, 0.560f, 1.000f); constexpr auto ROOT_COLOR_ACTIVE = ImVec4(0.240f, 0.520f, 0.880f, 1.000f); @@ -60,20 +54,16 @@ namespace anm2ed::timeline auto copy = [&]() { - if (auto frame = document.anm2.frame_get(hoveredFrame)) clipboard.set(frame->to_string(hoveredFrame.itemType)); + if (auto frame = document.anm2.frame_get(hoveredFrame)) + { + clipboard.set(frame->to_string(hoveredFrame.itemType)); + } }; auto cut = [&]() { - if (auto frame = document.anm2.frame_get(hoveredFrame)) - { - if (auto item = document.anm2.item_get(hoveredFrame)) - { - clipboard.set(frame->to_string(hoveredFrame.itemType)); - document.frames_delete(item); - hoveredFrame = anm2::REFERENCE_DEFAULT; - } - } + copy(); + document.frames_delete(document.item_get()); }; auto paste = [&]() { document.frames_deserialize(clipboard.get()); }; @@ -104,9 +94,10 @@ namespace anm2ed::timeline { auto& anm2 = document.anm2; auto& reference = document.reference; + auto item = animation ? animation->item_get(type, id) : nullptr; - auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; auto isVisible = item ? item->isVisible : false; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; if (isOnlyShowLayers && type != anm2::LAYER) isVisible = false; auto isActive = reference.itemType == type && reference.itemID == id; std::string label = "##None"; @@ -179,6 +170,7 @@ namespace anm2ed::timeline ImGui::TextUnformatted(label.c_str()); anm2::Item* item = animation->item_get(type, id); + bool& isVisible = item->isVisible; ImGui::PushStyleColor(ImGuiCol_Button, ImVec4()); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4()); @@ -187,7 +179,7 @@ namespace anm2ed::timeline ImGui::SetCursorPos(ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); - int visibleIcon = item->isVisible ? icon::VISIBLE : icon::INVISIBLE; + int visibleIcon = isVisible ? icon::VISIBLE : icon::INVISIBLE; if (ImGui::ImageButton("##Visible Toggle", resources.icons[visibleIcon].id, imgui::icon_size_get())) document.item_visible_toggle(item); @@ -214,31 +206,33 @@ namespace anm2ed::timeline else { auto cursorPos = ImGui::GetCursorPos(); + auto& isShowUnused = settings.timelineIsShowUnused; + + ImGui::SetCursorPos(ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4()); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4()); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4()); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); - ImGui::SetCursorPos(ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, - (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); - auto& isShowUnused = settings.timelineIsShowUnused; auto unusedIcon = isShowUnused ? icon::SHOW_UNUSED : icon::HIDE_UNUSED; if (ImGui::ImageButton("##Unused Toggle", resources.icons[unusedIcon].id, imgui::icon_size_get())) isShowUnused = !isShowUnused; ImGui::SetItemTooltip(isShowUnused ? "Unused layers/nulls are shown. Press to hide." : "Unused layers/nulls are hidden. Press to show."); - auto onlyShowLayersIcon = isOnlyShowLayers ? icon::SHOW_LAYERS : icon::HIDE_LAYERS; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; + auto layersIcon = isOnlyShowLayers ? icon::SHOW_LAYERS : icon::HIDE_LAYERS; + ImGui::SetCursorPos( ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x, (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); - if (ImGui::ImageButton("##Layers Visibility Toggle", resources.icons[onlyShowLayersIcon].id, - imgui::icon_size_get())) + + if (ImGui::ImageButton("##Layers Toggle", resources.icons[layersIcon].id, imgui::icon_size_get())) isOnlyShowLayers = !isOnlyShowLayers; - ImGui::SetItemTooltip(isOnlyShowLayers - ? "Only layers are visible. Press to toggle visibility for all items." - : "Non-layer items are visible. Press to toggle visiblity only for layers."); + ImGui::SetItemTooltip(isOnlyShowLayers ? "Only layers are visible. Press to show all items." + : "All items are visible. Press to only show layers."); ImGui::PopStyleVar(); ImGui::PopStyleColor(3); @@ -368,8 +362,8 @@ namespace anm2ed::timeline auto& reference = document.reference; auto& hoveredFrame = document.hoveredFrame; auto item = animation ? animation->item_get(type, id) : nullptr; - auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; auto isVisible = item ? item->isVisible : false; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; if (isOnlyShowLayers && type != anm2::LAYER) isVisible = false; ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); @@ -521,8 +515,6 @@ namespace anm2ed::timeline auto isSelected = baseReference == frameReference; auto isFrameVisible = isVisible && frame.isVisible; - frameTime += frame.delay; - ImGui::PushID(i); auto size = ImVec2(frameSize.x * frame.delay, frameSize.y); @@ -564,6 +556,8 @@ namespace anm2ed::timeline drawList->AddImage(resources.icons[icon].id, imageMin, imageMax); + frameTime += frame.delay; + ImGui::PopID(); } @@ -703,7 +697,7 @@ namespace anm2ed::timeline ImGui::SetCursorPos( ImVec2(ImGui::GetStyle().WindowPadding.x, ImGui::GetCursorPos().y + ImGui::GetStyle().ItemSpacing.y)); - auto widgetSize = imgui::widget_size_with_row_get(9); + auto widgetSize = imgui::widget_size_with_row_get(10); ImGui::BeginDisabled(!animation); { @@ -749,8 +743,8 @@ namespace anm2ed::timeline ImGui::SameLine(); ImGui::SetNextItemWidth(widgetSize.x); - ImGui::InputInt("Animation Length", animation ? &animation->frameNum : &dummy_value(), step::NORMAL, - step::FAST, !animation ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); + ImGui::InputInt("Animation Length", animation ? &animation->frameNum : &dummy_value(), imgui::STEP, + imgui::STEP_FAST, !animation ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); if (animation) animation->frameNum = clamp(animation->frameNum, anm2::FRAME_NUM_MIN, anm2::FRAME_NUM_MAX); ImGui::SetItemTooltip("Set the animation's length."); @@ -775,6 +769,12 @@ namespace anm2ed::timeline imgui::input_text_string("Author", &anm2.info.createdBy); ImGui::SetItemTooltip("Set the author of the document."); + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + ImGui::Checkbox("Sound", &settings.timelineIsSound); + ImGui::SetItemTooltip("Toggle sounds playing with triggers.\nBind sounds to events in the Events window."); + ImGui::PopStyleVar(); } ImGui::EndChild(); @@ -961,9 +961,8 @@ namespace anm2ed::timeline auto frame = document.frame_get(); - ImGui::InputInt("Interval", &interval, step::NORMAL, step::FAST); + imgui::input_int_range("Interval", interval, anm2::FRAME_DELAY_MIN, frame ? frame->delay : anm2::FRAME_DELAY_MIN); ImGui::SetItemTooltip("Set the maximum delay of each frame that will be baked."); - interval = glm::clamp(interval, anm2::FRAME_DELAY_MIN, frame ? frame->delay : anm2::FRAME_DELAY_MIN); ImGui::Checkbox("Round Rotation", &isRoundRotation); ImGui::SetItemTooltip("Rotation will be rounded to the nearest whole number."); @@ -993,7 +992,6 @@ namespace anm2ed::timeline { auto& document = *manager.get(); auto& playback = document.playback; - auto& anm2 = document.anm2; auto& reference = document.reference; auto animation = document.animation_get(); diff --git a/src/imgui/window/timeline.h b/src/imgui/window/timeline.h new file mode 100644 index 0000000..3c0560d --- /dev/null +++ b/src/imgui/window/timeline.h @@ -0,0 +1,39 @@ +#pragma once + +#include "clipboard.h" +#include "document.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Timeline + { + bool isDragging{}; + bool isWindowHovered{}; + bool isHorizontalScroll{}; + PopupHelper propertiesPopup{PopupHelper("Item Properties", POPUP_NORMAL)}; + PopupHelper bakePopup{PopupHelper("Bake", POPUP_TO_CONTENT)}; + std::string addItemName{}; + int addItemSpritesheetID{}; + bool addItemIsRect{}; + int addItemID{-1}; + bool isUnusedItemsSet{}; + std::set unusedItems{}; + glm::vec2 scroll{}; + ImDrawList* pickerLineDrawList{}; + ImGuiStyle style{}; + + void context_menu(Document&, Settings&, Clipboard&); + void item_child(Manager&, Document&, anm2::Animation*, Settings&, Resources&, Clipboard&, anm2::Type, int, int&); + void items_child(Manager&, Document&, anm2::Animation*, Settings&, Resources&, Clipboard&); + void frame_child(Document&, anm2::Animation*, Settings&, Resources&, Clipboard&, anm2::Type, int, int&, float); + void frames_child(Document&, anm2::Animation*, Settings&, Resources&, Clipboard&); + + void popups(Document&, anm2::Animation*, Settings&); + + public: + void update(Manager&, Settings&, Resources&, Clipboard&); + }; +} diff --git a/src/tools.cpp b/src/imgui/window/tools.cpp similarity index 66% rename from src/tools.cpp rename to src/imgui/window/tools.cpp index c0d6073..608806d 100644 --- a/src/tools.cpp +++ b/src/imgui/window/tools.cpp @@ -3,20 +3,15 @@ #include -#include "imgui.h" #include "tool.h" #include "types.h" -using namespace anm2ed::settings; -using namespace anm2ed::manager; -using namespace anm2ed::resources; +using namespace anm2ed::resource; using namespace anm2ed::types; using namespace glm; -namespace anm2ed::tools +namespace anm2ed::imgui { - constexpr auto COLOR_EDIT_LABEL = "##Color Edit"; - void Tools::update(Manager& manager, Settings& settings, Resources& resources) { auto& document = *manager.get(); @@ -29,21 +24,18 @@ namespace anm2ed::tools auto size = vec2(ImGui::GetTextLineHeightWithSpacing() * 1.5f); auto usedWidth = ImGui::GetStyle().WindowPadding.x; - auto tool_switch = [&](tool::Type type) + auto tool_use = [&](tool::Type type) { switch (type) { case tool::UNDO: - if (document.is_undo()) document.undo(); + if (document.is_able_to_undo()) document.undo(); break; case tool::REDO: - if (document.is_redo()) document.redo(); + if (document.is_able_to_redo()) document.redo(); break; case tool::COLOR: - if (ImGui::IsPopupOpen(COLOR_EDIT_LABEL)) - ImGui::CloseCurrentPopup(); - else - isOpenColorEdit = true; + colorEditPopup.open(); break; default: settings.tool = type; @@ -60,23 +52,22 @@ namespace anm2ed::tools auto member = SHORTCUT_MEMBERS[info.shortcut]; - if (imgui::shortcut(settings.*member, shortcut::GLOBAL_SET)) tool_switch((tool::Type)i); + if (shortcut(settings.*member, shortcut::GLOBAL_SET)) tool_use((tool::Type)i); if (i == tool::COLOR) { size += to_vec2(ImGui::GetStyle().FramePadding) * 2.0f; if (ImGui::ColorButton(info.label, to_imvec4(settings.toolColor), ImGuiColorEditFlags_NoTooltip, to_imvec2(size))) - tool_switch((tool::Type)i); + tool_use((tool::Type)i); colorEditPosition = ImGui::GetCursorScreenPos(); } else { - if (i == tool::UNDO) ImGui::BeginDisabled(!document.is_undo()); - if (i == tool::REDO) ImGui::BeginDisabled(!document.is_redo()); - if (ImGui::ImageButton(info.label, resources.icons[info.icon].id, to_imvec2(size))) - tool_switch((tool::Type)i); + if (i == tool::UNDO) ImGui::BeginDisabled(!document.is_able_to_undo()); + if (i == tool::REDO) ImGui::BeginDisabled(!document.is_able_to_redo()); + if (ImGui::ImageButton(info.label, resources.icons[info.icon].id, to_imvec2(size))) tool_use((tool::Type)i); if (i == tool::UNDO) ImGui::EndDisabled(); if (i == tool::REDO) ImGui::EndDisabled(); } @@ -88,25 +79,18 @@ namespace anm2ed::tools ImGui::SameLine(); else usedWidth = ImGui::GetStyle().WindowPadding.x; - - imgui::set_item_tooltip_shortcut(info.tooltip, settings.*SHORTCUT_MEMBERS[info.shortcut]); + set_item_tooltip_shortcut(info.tooltip, settings.*SHORTCUT_MEMBERS[info.shortcut]); if (isSelected) ImGui::PopStyleColor(); } ImGui::PopStyleVar(); - if (isOpenColorEdit) - { - ImGui::OpenPopup(COLOR_EDIT_LABEL); - isOpenColorEdit = false; - } + colorEditPopup.trigger(); - ImGui::SetNextWindowPos(colorEditPosition, ImGuiCond_None); - - if (ImGui::BeginPopup(COLOR_EDIT_LABEL)) + if (ImGui::BeginPopup(colorEditPopup.label)) { - ImGui::ColorPicker4(COLOR_EDIT_LABEL, value_ptr(settings.toolColor)); + ImGui::ColorPicker4(colorEditPopup.label, value_ptr(settings.toolColor)); ImGui::EndPopup(); } } diff --git a/src/tools.h b/src/imgui/window/tools.h similarity index 51% rename from src/tools.h rename to src/imgui/window/tools.h index 377b636..ad1ea2c 100644 --- a/src/tools.h +++ b/src/imgui/window/tools.h @@ -4,14 +4,16 @@ #include "resources.h" #include "settings.h" -namespace anm2ed::tools +namespace anm2ed::imgui { class Tools { bool isOpenColorEdit{}; ImVec2 colorEditPosition{}; + PopupHelper colorEditPopup{PopupHelper("##Color Edit", POPUP_TO_CONTENT, POPUP_BY_ITEM)}; + public: - void update(manager::Manager&, settings::Settings&, resources::Resources&); + void update(Manager&, Settings&, Resources&); }; } diff --git a/src/welcome.cpp b/src/imgui/window/welcome.cpp similarity index 69% rename from src/welcome.cpp rename to src/imgui/window/welcome.cpp index 2114906..38c69c2 100644 --- a/src/welcome.cpp +++ b/src/imgui/window/welcome.cpp @@ -2,13 +2,9 @@ #include -using namespace anm2ed::dialog; -using namespace anm2ed::taskbar; -using namespace anm2ed::documents; -using namespace anm2ed::resources; -using namespace anm2ed::manager; +using namespace anm2ed::resource; -namespace anm2ed::welcome +namespace anm2ed::imgui { void Welcome::update(Manager& manager, Resources& resources, Dialog& dialog, Taskbar& taskbar, Documents& documents) { @@ -19,28 +15,28 @@ namespace anm2ed::welcome ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + taskbar.height + documents.height)); ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, windowHeight)); - if (ImGui::Begin("##Welcome", nullptr, + if (ImGui::Begin("Welcome", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) { ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE_LARGE); - ImGui::Text("Anm2Ed"); + ImGui::TextUnformatted("Anm2Ed"); ImGui::PopFont(); - ImGui::Text( - "Select a recent file or an option below. You can also drag and drop files into the window to open them."); + ImGui::TextUnformatted("Select a recent file or open a new or existing document. You can also drag and drop " + "files into the window to open them."); - auto widgetSize = imgui::widget_size_with_row_get(2); + auto widgetSize = widget_size_with_row_get(2); - if (ImGui::Button("New", widgetSize)) dialog.anm2_new(); // handled in taskbar.cpp + if (ImGui::Button("New", widgetSize)) dialog.file_open(dialog::ANM2_NEW); // handled in taskbar.cpp ImGui::SameLine(); - if (ImGui::Button("Open", widgetSize)) dialog.anm2_open(); // handled in taskbar.cpp + if (ImGui::Button("Open", widgetSize)) dialog.file_open(dialog::ANM2_OPEN); // handled in taskbar.cpp - if (ImGui::BeginChild("##Recent Child", ImVec2(), ImGuiChildFlags_Borders)) + if (ImGui::BeginChild("##Recent Files Child", ImVec2(), ImGuiChildFlags_Borders)) { for (auto [i, file] : std::views::enumerate(manager.recentFiles)) { @@ -68,11 +64,11 @@ namespace anm2ed::welcome if (ImGui::BeginPopupModal(restorePopup.label, &restorePopup.isOpen, ImGuiWindowFlags_NoResize)) { - ImGui::Text("Autosaved files detected. Would you like to restore them?"); + ImGui::TextUnformatted("Autosaved documents detected. Would you like to restore them?"); - auto childSize = imgui::child_size_get(5); + auto childSize = child_size_get(5); - if (ImGui::BeginChild("##Autosave Documents", childSize, ImGuiChildFlags_Borders, + if (ImGui::BeginChild("##Restore Files Child", childSize, ImGuiChildFlags_Borders, ImGuiWindowFlags_HorizontalScrollbar)) { for (auto& file : manager.autosaveFiles) @@ -83,7 +79,7 @@ namespace anm2ed::welcome } ImGui::EndChild(); - auto widgetSize = imgui::widget_size_with_row_get(2); + auto widgetSize = widget_size_with_row_get(2); if (ImGui::Button("Yes", widgetSize)) { diff --git a/src/imgui/window/welcome.h b/src/imgui/window/welcome.h new file mode 100644 index 0000000..5a7d3f7 --- /dev/null +++ b/src/imgui/window/welcome.h @@ -0,0 +1,16 @@ +#pragma once + +#include "documents.h" +#include "manager.h" +#include "taskbar.h" + +namespace anm2ed::imgui +{ + class Welcome + { + PopupHelper restorePopup{PopupHelper("Restore", imgui::POPUP_SMALL_NO_HEIGHT)}; + + public: + void update(Manager&, Resources&, Dialog&, Taskbar&, Documents&); + }; +}; \ No newline at end of file diff --git a/src/loader.cpp b/src/loader.cpp index bcb82d5..5113398 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -3,16 +3,17 @@ #include #include -#include "filesystem.h" +#include + +#include "filesystem_.h" #include "log.h" -using namespace anm2ed::log; -using namespace anm2ed::settings; using namespace anm2ed::types; +using namespace anm2ed::util; -namespace anm2ed::loader +namespace anm2ed { - std::string settings_path() + std::string Loader::settings_path() { return filesystem::path_preferences_get() + "settings.ini"; } @@ -22,6 +23,8 @@ namespace anm2ed::loader for (int i = 1; i < argc; i++) arguments.emplace_back(argv[i]); + settings = Settings(settings_path()); + if (!SDL_Init(SDL_INIT_VIDEO)) { logger.fatal(std::format("Could not initialize SDL! {}", SDL_GetError())); @@ -29,7 +32,12 @@ namespace anm2ed::loader return; } - settings = Settings(settings_path()); + logger.info("Initialized SDL"); + + if (!MIX_Init()) + logger.warning(std::format("Could not initialize SDL_mixer! {}", SDL_GetError())); + else + logger.info("Initialized SDL_mixer"); window = SDL_CreateWindow("Anm2Ed", settings.windowSize.x, settings.windowSize.y, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_HIGH_PIXEL_DENSITY); @@ -54,7 +62,7 @@ namespace anm2ed::loader return; } - logger.info(std::format("OpenGL {}", (const char*)glGetString(GL_VERSION))); + logger.info(std::format("Initialized OpenGL {}", (const char*)glGetString(GL_VERSION))); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -65,7 +73,15 @@ namespace anm2ed::loader glClearColor(color::BLACK.r, color::BLACK.g, color::BLACK.b, color::BLACK.a); IMGUI_CHECKVERSION(); - ImGui::CreateContext(); + if (!ImGui::CreateContext()) + { + logger.fatal("Could not initialize Dear ImGui!"); + isError = true; + return; + } + + logger.info("Initialized Dear ImGui"); + ImGui::StyleColorsDark(); ImGui_ImplSDL3_InitForOpenGL(window, glContext); @@ -81,13 +97,22 @@ namespace anm2ed::loader Loader::~Loader() { - settings.save(settings_path(), ImGui::SaveIniSettingsToMemory(nullptr)); + if (ImGui::GetCurrentContext()) + { + settings.save(settings_path(), ImGui::SaveIniSettingsToMemory(nullptr)); - ImGui_ImplSDL3_Shutdown(); - ImGui_ImplOpenGL3_Shutdown(); - ImGui::DestroyContext(); - SDL_GL_DestroyContext(glContext); - SDL_DestroyWindow(window); - SDL_Quit(); + ImGui_ImplSDL3_Shutdown(); + ImGui_ImplOpenGL3_Shutdown(); + ImGui::DestroyContext(); + } + + MIX_Quit(); + + if (SDL_WasInit(0)) + { + SDL_GL_DestroyContext(glContext); + SDL_DestroyWindow(window); + SDL_Quit(); + } } } \ No newline at end of file diff --git a/src/loader.h b/src/loader.h index d3cbbb1..31c751a 100644 --- a/src/loader.h +++ b/src/loader.h @@ -7,14 +7,16 @@ #include "settings.h" -namespace anm2ed::loader +namespace anm2ed { class Loader { + std::string settings_path(); + public: SDL_Window* window{}; SDL_GLContext glContext{}; - settings::Settings settings; + Settings settings; std::vector arguments; bool isError{}; diff --git a/src/log.cpp b/src/log.cpp index 3cdfba3..4aba110 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -2,13 +2,12 @@ #include -#include "filesystem.h" -#include "util.h" +#include "filesystem_.h" +#include "time_.h" -using namespace anm2ed::filesystem; using namespace anm2ed::util; -namespace anm2ed::log +namespace anm2ed { void Logger::write(const Level level, const std::string& message) { @@ -37,6 +36,11 @@ namespace anm2ed::log write(FATAL, message); } + void Logger::command(const std::string& message) + { + write(COMMAND, message); + } + void Logger::open(const std::filesystem::path& path) { file.open(path, std::ios::out | std::ios::app); @@ -44,7 +48,7 @@ namespace anm2ed::log Logger::Logger() { - open(path_preferences_get() + "log.txt"); + open(filesystem::path_preferences_get() + "log.txt"); info("Initializing Anm2Ed"); } @@ -54,5 +58,6 @@ namespace anm2ed::log if (file.is_open()) file.close(); } - Logger logger; } + +anm2ed::Logger logger; diff --git a/src/log.h b/src/log.h index 1870827..f1ee6fc 100644 --- a/src/log.h +++ b/src/log.h @@ -3,13 +3,14 @@ #include #include -namespace anm2ed::log +namespace anm2ed { #define LEVELS \ X(INFO, "[INFO]") \ X(WARNING, "[WARNING]") \ X(ERROR, "[ERROR]") \ - X(FATAL, "[FATAL]") + X(FATAL, "[FATAL]") \ + X(COMMAND, "[COMMAND]") enum Level { @@ -35,10 +36,12 @@ namespace anm2ed::log void warning(const std::string&); void error(const std::string&); void fatal(const std::string&); + void command(const std::string&); void open(const std::filesystem::path&); Logger(); ~Logger(); }; - extern Logger logger; } + +extern anm2ed::Logger logger; diff --git a/src/main.cpp b/src/main.cpp index ea5ef6a..ea7d4da 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,16 +1,13 @@ #include "loader.h" #include "state.h" -using namespace anm2ed::loader; -using namespace anm2ed::state; - int main(int argc, const char** argv) { - Loader loader(argc, argv); + anm2ed::Loader loader(argc, argv); if (loader.isError) return EXIT_FAILURE; - State state(loader.window, loader.arguments); + anm2ed::State state(loader.window, loader.arguments); while (!state.isQuit) state.loop(loader.window, loader.settings); diff --git a/src/manager.cpp b/src/manager.cpp index 7be966d..7d47128 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -2,17 +2,15 @@ #include -#include "filesystem.h" +#include "filesystem_.h" #include "log.h" #include "toast.h" -#include "util.h" +#include "vector_.h" -using namespace anm2ed::log; -using namespace anm2ed::toast; using namespace anm2ed::types; using namespace anm2ed::util; -namespace anm2ed::manager +namespace anm2ed { constexpr std::size_t RECENT_LIMIT = 10; @@ -121,7 +119,7 @@ namespace anm2ed::manager selected = std::clamp(selected, 0, (int)documents.size() - 1); pendingSelected = selected; - if (selected >= 0 && selected < (int)documents.size()) documents[selected].change(change::ALL); + if (selected >= 0 && selected < (int)documents.size()) documents[selected].change(Document::ALL); } void Manager::set(int index) @@ -136,7 +134,7 @@ namespace anm2ed::manager index = std::clamp(index, 0, (int)documents.size() - 1); selected = index; - if (auto document = get()) document->change(change::ALL); + if (auto document = get()) document->change(Document::ALL); } void Manager::layer_properties_open(int id) @@ -262,7 +260,7 @@ namespace anm2ed::manager { document->isForceDirty = true; document->path = restorePath; - document->change(change::ALL); + document->change(Document::ALL); } } diff --git a/src/manager.h b/src/manager.h index 4a4417c..549de70 100644 --- a/src/manager.h +++ b/src/manager.h @@ -3,11 +3,8 @@ #include #include "document.h" -#include "imgui.h" -using namespace anm2ed::document; - -namespace anm2ed::manager +namespace anm2ed { constexpr auto FILE_LABEL_FORMAT = "{} [{}]"; @@ -24,11 +21,17 @@ namespace anm2ed::manager int selected{-1}; int pendingSelected{-1}; + bool isRecording{}; + int recordingStart{}; + int recordingEnd{}; + anm2::Layer editLayer{}; - imgui::PopupHelper layerPropertiesPopup{imgui::PopupHelper("Layer Properties", imgui::POPUP_SMALL, true)}; + imgui::PopupHelper layerPropertiesPopup{imgui::PopupHelper("Layer Properties", imgui::POPUP_SMALL_NO_HEIGHT)}; anm2::Null editNull{}; - imgui::PopupHelper nullPropertiesPopup{imgui::PopupHelper("Null Properties", imgui::POPUP_SMALL, true)}; + imgui::PopupHelper nullPropertiesPopup{imgui::PopupHelper("Null Properties", imgui::POPUP_SMALL_NO_HEIGHT)}; + + imgui::PopupHelper progressPopup{imgui::PopupHelper("Rendering...", imgui::POPUP_SMALL_NO_HEIGHT)}; Manager(); ~Manager(); diff --git a/src/onionskin.cpp b/src/onionskin.cpp deleted file mode 100644 index 1ec35b6..0000000 --- a/src/onionskin.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "onionskin.h" - -#include - -#include "imgui.h" -#include "types.h" - -using namespace anm2ed::settings; -using namespace anm2ed::types; -using namespace glm; - -namespace anm2ed::onionskin -{ - void Onionskin::update(Settings& settings) - { - if (ImGui::Begin("Onionskin", &settings.windowIsOnionskin)) - { - auto order_configure = [&](const std::string& separator, int& frames, vec3& color) - { - ImGui::PushID(separator.c_str()); - ImGui::SeparatorText(separator.c_str()); - ImGui::InputInt("Frames", &frames, 1, 5); - frames = glm::clamp(frames, 0, 100); - ImGui::ColorEdit3("Color", value_ptr(color)); - ImGui::PopID(); - }; - - ImGui::Checkbox("Enabled", &settings.onionskinIsEnabled); - - order_configure("Before", settings.onionskinBeforeCount, settings.onionskinBeforeColor); - order_configure("After", settings.onionskinAfterCount, settings.onionskinAfterColor); - - ImGui::Text("Order"); - ImGui::SameLine(); - ImGui::RadioButton("Before", &settings.onionskinDrawOrder, draw_order::BELOW); - ImGui::SameLine(); - ImGui::RadioButton("After", &settings.onionskinDrawOrder, draw_order::ABOVE); - } - ImGui::End(); - - if (imgui::shortcut(settings.shortcutOnionskin, shortcut::GLOBAL)) - settings.onionskinIsEnabled = !settings.onionskinIsEnabled; - } - -} diff --git a/src/playback.cpp b/src/playback.cpp index 30c2413..03c2117 100644 --- a/src/playback.cpp +++ b/src/playback.cpp @@ -2,7 +2,7 @@ #include -namespace anm2ed::playback +namespace anm2ed { void Playback::toggle() { diff --git a/src/playback.h b/src/playback.h index 291c527..ad4034c 100644 --- a/src/playback.h +++ b/src/playback.h @@ -1,6 +1,6 @@ #pragma once -namespace anm2ed::playback +namespace anm2ed { class Playback { diff --git a/src/render.cpp b/src/render.cpp new file mode 100644 index 0000000..3258c2f --- /dev/null +++ b/src/render.cpp @@ -0,0 +1,96 @@ +#include "render.h" + +#include +#include + +#ifdef _WIN32 + #include "util.h" + #define POPEN _popen + #define PCLOSE _pclose + #define PWRITE_MODE "wb" + #define PREAD_MODE "r" +#else + #define POPEN popen + #define PCLOSE pclose + #define PWRITE_MODE "w" + #define PREAD_MODE "r" +#endif + +#include "log.h" + +using namespace anm2ed::resource; +using namespace glm; + +namespace anm2ed +{ + constexpr auto FFMPEG_POPEN_ERROR = "popen() (for FFmpeg) failed!\n{}"; + + constexpr auto GIF_FORMAT = "\"{0}\" -y " + "-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " + "-lavfi \"split[s0][s1];" + "[s0]palettegen=stats_mode=full[p];" + "[s1][p]paletteuse=dither=floyd_steinberg\" " + "-loop 0 \"{4}\""; + + constexpr auto WEBM_FORMAT = "\"{0}\" -y " + "-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " + "-c:v libvpx-vp9 -crf 30 -b:v 0 -pix_fmt yuva420p -row-mt 1 -threads 0 -speed 2 " + "-auto-alt-ref 0 -an \"{4}\""; + + constexpr auto* MP4_FORMAT = "\"{0}\" -y " + "-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " + "-vf \"format=yuv420p,scale=trunc(iw/2)*2:trunc(ih/2)*2\" " + "-c:v libx265 -crf 20 -preset slow " + "-tag:v hvc1 -movflags +faststart -an \"{4}\""; + + bool animation_render(const std::string& ffmpegPath, const std::string& path, std::vector& frames, + render::Type type, ivec2 size, int fps) + { + if (frames.empty() || size.x <= 0 || size.y <= 0 || fps <= 0 || ffmpegPath.empty() || path.empty()) return false; + + std::string command{}; + + switch (type) + { + case render::GIF: + command = std::format(GIF_FORMAT, ffmpegPath, size.x, size.y, fps, path); + break; + case render::WEBM: + command = std::format(WEBM_FORMAT, ffmpegPath, size.x, size.y, fps, path); + break; + case render::MP4: + command = std::format(MP4_FORMAT, ffmpegPath, size.x, size.y, fps, path); + break; + default: + break; + } + +#if _WIN32 + command = string::quote(command); +#endif + + logger.command(command); + + FILE* fp = POPEN(command.c_str(), PWRITE_MODE); + + if (!fp) + { + logger.error(std::format(FFMPEG_POPEN_ERROR, strerror(errno))); + return false; + } + + for (auto& frame : frames) + { + auto frameSize = frame.pixel_size_get(); + + if (fwrite(frame.pixels.data(), 1, frameSize, fp) != frameSize) + { + PCLOSE(fp); + return false; + } + } + + auto code = PCLOSE(fp); + return (code == 0); + } +} \ No newline at end of file diff --git a/src/render.h b/src/render.h new file mode 100644 index 0000000..6e9cdfb --- /dev/null +++ b/src/render.h @@ -0,0 +1,32 @@ +#pragma once + +#include "texture.h" + +namespace anm2ed::render +{ +#define RENDER_LIST \ + X(PNGS, "PNGs") \ + X(GIF, "GIF") \ + X(WEBM, "WebM") \ + X(MP4, "MP4") + + enum Type + { +#define X(symbol, string) symbol, + RENDER_LIST +#undef X + COUNT + }; + + constexpr const char* STRINGS[] = { +#define X(symbol, string) string, + RENDER_LIST +#undef X + }; +} + +namespace anm2ed +{ + bool animation_render(const std::string&, const std::string&, std::vector&, render::Type, + glm::ivec2, int); +} \ No newline at end of file diff --git a/src/resource/audio.cpp b/src/resource/audio.cpp new file mode 100644 index 0000000..11979f2 --- /dev/null +++ b/src/resource/audio.cpp @@ -0,0 +1,49 @@ +#include "audio.h" + +#include + +namespace anm2ed::resource +{ + MIX_Mixer* Audio::mixer_get() + { + static MIX_Mixer* mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, nullptr); + return mixer; + } + + Audio::Audio(const char* path) + { + if (path && *path) internal = MIX_LoadAudio(mixer_get(), path, true); + } + + void Audio::unload() + { + if (!internal) return; + MIX_DestroyAudio(internal); + internal = nullptr; + } + + void Audio::play() + { + MIX_PlayAudio(mixer_get(), internal); + } + + Audio::Audio(Audio&& other) noexcept + { + internal = std::exchange(other.internal, nullptr); + } + + Audio& Audio::operator=(Audio&& other) noexcept + { + if (this != &other) + { + unload(); + internal = std::exchange(other.internal, nullptr); + } + return *this; + } + + Audio::~Audio() + { + unload(); + } +} diff --git a/src/resource/audio.h b/src/resource/audio.h new file mode 100644 index 0000000..6c2cc52 --- /dev/null +++ b/src/resource/audio.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace anm2ed::resource +{ + class Audio + { + MIX_Audio* internal{nullptr}; + MIX_Mixer* mixer_get(); + void unload(); + + public: + Audio(const char*); + ~Audio(); + Audio() = default; + Audio(Audio&&) noexcept; + Audio& operator=(Audio&&) noexcept; + Audio(const Audio&) = delete; + Audio& operator=(const Audio&) = delete; + + void play(); + }; +} diff --git a/src/font.cpp b/src/resource/font.cpp similarity index 95% rename from src/font.cpp rename to src/resource/font.cpp index 39a58ee..5504b19 100644 --- a/src/font.cpp +++ b/src/resource/font.cpp @@ -1,6 +1,6 @@ #include "font.h" -namespace anm2ed::font +namespace anm2ed::resource { Font::Font() = default; diff --git a/src/font.h b/src/resource/font.h similarity index 99% rename from src/font.h rename to src/resource/font.h index f5e4802..a0708bb 100644 --- a/src/font.h +++ b/src/resource/font.h @@ -99,10 +99,10 @@ OTHER DEALINGS IN THE FONT SOFTWARE. #include #include -namespace anm2ed::font +namespace anm2ed::resource::font { - constexpr int SIZE = 16; - constexpr int SIZE_LARGE = 32; + constexpr auto SIZE = 16; + constexpr auto SIZE_LARGE = 32; enum Type { @@ -5224,6 +5224,10 @@ namespace anm2ed::font {.data = BOLD_DATA, .length = std::size(BOLD_DATA)}, {.data = BOLD_ITALICS_DATA, .length = std::size(BOLD_ITALICS_DATA)}}; +}; + +namespace anm2ed::resource +{ class Font { ImFont* pointer{}; @@ -5235,4 +5239,4 @@ namespace anm2ed::font ImFont* get(); Font& operator=(Font&&) noexcept; }; -}; +} diff --git a/src/icon.h b/src/resource/icon.h similarity index 99% rename from src/icon.h rename to src/resource/icon.h index 50ab178..147a884 100644 --- a/src/icon.h +++ b/src/resource/icon.h @@ -2,7 +2,7 @@ #include #include -namespace icon +namespace anm2ed::resource::icon { constexpr auto SIZE_SMALL = glm::ivec2(64, 64); constexpr auto SIZE_NORMAL = glm::ivec2(128, 128); diff --git a/src/shader.cpp b/src/resource/shader.cpp similarity index 96% rename from src/shader.cpp rename to src/resource/shader.cpp index b205363..ba1e234 100644 --- a/src/shader.cpp +++ b/src/resource/shader.cpp @@ -2,9 +2,7 @@ #include "log.h" -using namespace anm2ed::log; - -namespace anm2ed::shader +namespace anm2ed::resource { Shader::Shader() = default; diff --git a/src/shader.h b/src/resource/shader.h similarity index 98% rename from src/shader.h rename to src/resource/shader.h index ab7e0f4..9794080 100644 --- a/src/shader.h +++ b/src/resource/shader.h @@ -2,7 +2,7 @@ #include -namespace anm2ed::shader +namespace anm2ed::resource::shader { struct Info { @@ -202,7 +202,7 @@ namespace anm2ed::shader constexpr auto UNIFORM_DASH_GAP = "u_dash_gap"; constexpr auto UNIFORM_DASH_OFFSET = "u_dash_offset"; - enum Type + enum ShaderType { LINE, DASHED, @@ -217,7 +217,10 @@ namespace anm2ed::shader {VERTEX, TEXTURE_FRAGMENT}, {AXIS_VERTEX, FRAGMENT}, {GRID_VERTEX, GRID_FRAGMENT}}; +} +namespace anm2ed::resource +{ class Shader { public: diff --git a/src/texture.cpp b/src/resource/texture.cpp similarity index 64% rename from src/texture.cpp rename to src/resource/texture.cpp index f508c47..89170ec 100644 --- a/src/texture.cpp +++ b/src/resource/texture.cpp @@ -20,49 +20,32 @@ #pragma GCC diagnostic pop #endif -#include "math.h" +#include "math_.h" -using namespace anm2ed::math; +using namespace anm2ed::resource::texture; +using namespace anm2ed::util::math; using namespace glm; -namespace anm2ed::texture +namespace anm2ed::resource { bool Texture::is_valid() { return id != 0; } - std::vector Texture::pixels_get() + size_t Texture::pixel_size_get() { - ensure_pixels(); - return pixels; - } - - void Texture::download() - { - if (size.x <= 0 || size.y <= 0 || !is_valid()) return; - pixels.resize(static_cast(size.x) * static_cast(size.y) * CHANNELS); - glBindTexture(GL_TEXTURE_2D, id); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); - glBindTexture(GL_TEXTURE_2D, 0); - isPixelsDirty = false; + return size.x * size.y * CHANNELS; } void Texture::upload(const uint8_t* data) { if (!data || size.x <= 0 || size.y <= 0) return; - const size_t pixelCount = static_cast(size.x) * static_cast(size.y) * CHANNELS; - pixels.assign(data, data + pixelCount); - upload(); - } - - void Texture::upload() - { - if (pixels.empty() || size.x <= 0 || size.y <= 0) return; - if (!is_valid()) glGenTextures(1, &id); + pixels.assign(data, data + pixel_size_get()); + glBindTexture(GL_TEXTURE_2D, id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -74,7 +57,6 @@ namespace anm2ed::texture glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); - isPixelsDirty = false; } Texture::Texture() = default; @@ -94,35 +76,31 @@ namespace anm2ed::texture *this = std::move(other); } - Texture& Texture::operator=(const Texture& other) + Texture& Texture::operator=(const Texture& other) // Copy { if (this != &other) { if (is_valid()) glDeleteTextures(1, &id); - id = 0; - other.ensure_pixels(); size = other.size; filter = other.filter; channels = other.channels; pixels = other.pixels; - if (!pixels.empty()) upload(); + upload(pixels.data()); } return *this; } - Texture& Texture::operator=(Texture&& other) + Texture& Texture::operator=(Texture&& other) // Move { if (this != &other) { if (is_valid()) glDeleteTextures(1, &id); - id = std::exchange(other.id, 0); - size = std::exchange(other.size, {}); + id = other.id; + size = other.size; filter = other.filter; channels = other.channels; pixels = std::move(other.pixels); - isPixelsDirty = other.isPixelsDirty; - other.isPixelsDirty = true; - if (!pixels.empty()) upload(); + other.id = 0; } return *this; } @@ -159,7 +137,6 @@ namespace anm2ed::texture bool Texture::write_png(const std::string& path) { - ensure_pixels(); return stbi_write_png(path.c_str(), size.x, size.y, CHANNELS, this->pixels.data(), size.x * CHANNELS); } @@ -167,30 +144,26 @@ namespace anm2ed::texture { if (position.x < 0 || position.y < 0 || position.x >= size.x || position.y >= size.y) return; - ensure_pixels(); uint8 rgba8[4] = {(uint8)float_to_uint8(color.r), (uint8)float_to_uint8(color.g), (uint8)float_to_uint8(color.b), (uint8)float_to_uint8(color.a)}; - glBindTexture(GL_TEXTURE_2D, id); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexSubImage2D(GL_TEXTURE_2D, 0, position.x, position.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba8); - glBindTexture(GL_TEXTURE_2D, 0); - if (!pixels.empty()) + if (is_valid()) { - auto index = (position.y * size.x + position.x) * CHANNELS; - pixels[index + 0] = rgba8[0]; - pixels[index + 1] = rgba8[1]; - pixels[index + 2] = rgba8[2]; - pixels[index + 3] = rgba8[3]; - isPixelsDirty = false; + glBindTexture(GL_TEXTURE_2D, id); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, position.x, position.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba8); + glBindTexture(GL_TEXTURE_2D, 0); + } + + if (pixels.size() == pixel_size_get()) + { + size_t idx = (position.y * size.x + position.x) * CHANNELS; + memcpy(&pixels[idx], rgba8, 4); } - else - isPixelsDirty = true; } void Texture::pixel_line(ivec2 start, ivec2 end, vec4 color) { - ensure_pixels(); auto plot = [&](ivec2 pos) { pixel_set(pos, color); }; int x0 = start.x; @@ -221,23 +194,4 @@ namespace anm2ed::texture } } } - - void Texture::ensure_pixels() const - { - if (size.x <= 0 || size.y <= 0) return; - if (!pixels.empty() && !isPixelsDirty) return; - const_cast(this)->download(); - } - - void Texture::bind(GLuint unit) - { - glActiveTexture(GL_TEXTURE0 + unit); - glBindTexture(GL_TEXTURE_2D, id); - } - - void Texture::unbind(GLuint unit) - { - glActiveTexture(GL_TEXTURE0 + unit); - glBindTexture(GL_TEXTURE_2D, 0); - } } diff --git a/src/texture.h b/src/resource/texture.h similarity index 74% rename from src/texture.h rename to src/resource/texture.h index 419c64c..c73e138 100644 --- a/src/texture.h +++ b/src/resource/texture.h @@ -6,10 +6,13 @@ #include #include -namespace anm2ed::texture +namespace anm2ed::resource::texture { constexpr auto CHANNELS = 4; +} +namespace anm2ed::resource +{ class Texture { public: @@ -17,13 +20,12 @@ namespace anm2ed::texture glm::ivec2 size{}; GLint filter = GL_NEAREST; int channels{}; - mutable std::vector pixels{}; - mutable bool isPixelsDirty{true}; + std::vector pixels{}; bool is_valid(); - void download(); - void upload(const uint8_t*); + size_t pixel_size_get(); void upload(); + void upload(const uint8_t*); Texture(); ~Texture(); @@ -36,10 +38,6 @@ namespace anm2ed::texture Texture(const std::string&); bool write_png(const std::string&); void pixel_set(glm::ivec2, glm::vec4); - void ensure_pixels() const; - std::vector pixels_get(); void pixel_line(glm::ivec2, glm::ivec2, glm::vec4); - void bind(GLuint = 0); - void unbind(GLuint = 0); }; } diff --git a/src/resources.cpp b/src/resources.cpp index eec7ecf..d4bfa54 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -1,11 +1,10 @@ #include "resources.h" + #include -using namespace anm2ed::texture; -using namespace anm2ed::shader; -using namespace anm2ed::font; +using namespace anm2ed::resource; -namespace anm2ed::resources +namespace anm2ed { Resources::Resources() { diff --git a/src/resources.h b/src/resources.h index 3554be5..d703b4a 100644 --- a/src/resources.h +++ b/src/resources.h @@ -7,14 +7,14 @@ #include "shader.h" #include "texture.h" -namespace anm2ed::resources +namespace anm2ed { class Resources { public: - font::Font fonts[font::COUNT]{}; - texture::Texture icons[icon::COUNT]{}; - shader::Shader shaders[shader::COUNT]{}; + resource::Font fonts[resource::font::COUNT]{}; + resource::Texture icons[resource::icon::COUNT]{}; + resource::Shader shaders[resource::shader::COUNT]{}; Resources(); }; diff --git a/src/settings.cpp b/src/settings.cpp index d801dab..84e22f8 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1,13 +1,12 @@ #include "settings.h" -#include "filesystem.h" +#include "filesystem_.h" #include "log.h" -using namespace anm2ed::filesystem; -using namespace anm2ed::log; +using namespace anm2ed::util; using namespace glm; -namespace anm2ed::settings +namespace anm2ed { constexpr auto IMGUI_DEFAULT = R"( # Dear ImGui @@ -104,11 +103,9 @@ DockSpace ID=0xFC02A410 Window=0x0E46F4F7 Pos=8,40 Size=1584,852 Split=Y DockNode ID=0x00000004 Parent=0xFC02A410 SizeRef=1902,334 Selected=0x4F89F0DC )"; - Settings::Settings() = default; - Settings::Settings(const std::string& path) { - if (path_is_exist(path)) + if (filesystem::path_is_exist(path)) logger.info(std::format("Using settings from: {}", path)); else { diff --git a/src/settings.h b/src/settings.h index 9f9aa3d..61eba79 100644 --- a/src/settings.h +++ b/src/settings.h @@ -4,10 +4,11 @@ #include -#include "anm2.h" +#include "anm2/anm2.h" +#include "render.h" #include "types.h" -namespace anm2ed::settings +namespace anm2ed { #ifdef _WIN32 constexpr auto FFMPEG_PATH_DEFAULT = "C:\\ffmpeg\\bin\\ffmpeg.exe"; @@ -127,6 +128,7 @@ namespace anm2ed::settings X(TIMELINE_ADD_ITEM_SOURCE, timelineAddItemSource, "Add Item Source", INT, types::source::NEW) \ X(TIMELINE_IS_SHOW_UNUSED, timelineIsShowUnused, "##Show Unused", BOOL, true) \ X(TIMELINE_IS_ONLY_SHOW_LAYERS, timelineIsOnlyShowLayers, "##Only Show Layers", BOOL, true) \ + X(TIMELINE_IS_SOUND, timelineIsSound, "Sound", BOOL, true) \ \ X(ONIONSKIN_IS_ENABLED, onionskinIsEnabled, "Enabled", BOOL, false) \ X(ONIONSKIN_DRAW_ORDER, onionskinDrawOrder, "Draw Order", INT, 0) \ @@ -138,11 +140,12 @@ namespace anm2ed::settings X(TOOL, tool, "##Tool", INT, 0) \ X(TOOL_COLOR, toolColor, "##Color", VEC4, {1.0, 1.0, 1.0, 1.0}) \ \ - X(RENDER_TYPE, renderType, "Output", INT, 0) \ + X(RENDER_TYPE, renderType, "Output", INT, render::PNGS) \ X(RENDER_PATH, renderPath, "Path", STRING, ".") \ X(RENDER_FORMAT, renderFormat, "Format", STRING, "{}.png") \ X(RENDER_IS_USE_ANIMATION_BOUNDS, renderIsUseAnimationBounds, "Use Animation Bounds", BOOL, true) \ X(RENDER_IS_TRANSPARENT, renderIsTransparent, "Transparent", BOOL, true) \ + X(RENDER_IS_RANGE, renderIsRange, "Range", BOOL, false) \ X(RENDER_SCALE, renderScale, "Scale", FLOAT, 1.0f) \ X(RENDER_FFMPEG_PATH, renderFFmpegPath, "FFmpeg Path", STRING, FFMPEG_PATH_DEFAULT) @@ -197,6 +200,7 @@ namespace anm2ed::settings X(WINDOW_NULLS, windowIsNulls, "Nulls", BOOL, true) \ X(WINDOW_ONIONSKIN, windowIsOnionskin, "Onionskin", BOOL, true) \ X(WINDOW_PREVIEW, windowIsSpritesheets, "Spritesheets", BOOL, true) \ + X(WINDOW_SOUNDS, windowIsSounds, "Sounds", BOOL, true) \ X(WINDOW_SPRITESHEET_EDITOR, windowIsSpritesheetEditor, "Spritesheet Editor", BOOL, true) \ X(WINDOW_TIMELINE, windowIsTimeline, "Timeline", BOOL, true) \ X(WINDOW_TOOLS, windowIsTools, "Tools", BOOL, true) @@ -208,7 +212,7 @@ namespace anm2ed::settings SETTINGS_MEMBERS SETTINGS_SHORTCUTS SETTINGS_WINDOWS #undef X - Settings(); + Settings() = default; Settings(const std::string&); void save(const std::string&, const std::string&); diff --git a/src/snapshots.cpp b/src/snapshots.cpp index b473529..304624e 100644 --- a/src/snapshots.cpp +++ b/src/snapshots.cpp @@ -1,16 +1,9 @@ #include "snapshots.h" -namespace anm2ed::snapshots -{ - namespace - { - void textures_ensure(anm2::Anm2& anm2) - { - for (auto& [id, spritesheet] : anm2.content.spritesheets) - spritesheet.texture.ensure_pixels(); - } - } +using namespace anm2ed::snapshots; +namespace anm2ed +{ bool SnapshotStack::is_empty() { return top == 0; @@ -40,7 +33,6 @@ namespace anm2ed::snapshots void Snapshots::push(const anm2::Anm2& anm2, anm2::Reference reference, const std::string& message) { - textures_ensure(const_cast(anm2)); Snapshot snapshot = {anm2, reference, message}; undoStack.push(snapshot); redoStack.clear(); @@ -50,10 +42,8 @@ namespace anm2ed::snapshots { if (auto current = undoStack.pop()) { - textures_ensure(anm2); Snapshot snapshot = {anm2, reference, message}; redoStack.push(snapshot); - textures_ensure(current->anm2); anm2 = current->anm2; reference = current->reference; message = current->message; @@ -64,10 +54,8 @@ namespace anm2ed::snapshots { if (auto current = redoStack.pop()) { - textures_ensure(anm2); Snapshot snapshot = {anm2, reference, message}; undoStack.push(snapshot); - textures_ensure(current->anm2); anm2 = current->anm2; reference = current->reference; message = current->message; diff --git a/src/snapshots.h b/src/snapshots.h index e0f12ff..a18d4a7 100644 --- a/src/snapshots.h +++ b/src/snapshots.h @@ -1,24 +1,27 @@ #pragma once -#include "anm2.h" +#include "anm2/anm2.h" namespace anm2ed::snapshots { constexpr auto ACTION = "Action"; constexpr auto MAX = 100; +}; +namespace anm2ed +{ class Snapshot { public: anm2::Anm2 anm2{}; anm2::Reference reference{}; - std::string message = ACTION; + std::string message = snapshots::ACTION; }; class SnapshotStack { public: - Snapshot snapshots[MAX]; + Snapshot snapshots[snapshots::MAX]; int top{}; bool is_empty(); diff --git a/src/spritesheets.h b/src/spritesheets.h deleted file mode 100644 index 27a30d5..0000000 --- a/src/spritesheets.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "clipboard.h" -#include "dialog.h" -#include "manager.h" -#include "resources.h" -#include "settings.h" - -namespace anm2ed::spritesheets -{ - class Spritesheets - { - public: - void update(manager::Manager&, settings::Settings&, resources::Resources&, dialog::Dialog&, - clipboard::Clipboard& clipboard); - }; -} diff --git a/src/state.cpp b/src/state.cpp index fae94f2..ff0fb2a 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -3,15 +3,14 @@ #include #include -#include "filesystem.h" +#include "filesystem_.h" #include "toast.h" -using namespace anm2ed::settings; -using namespace anm2ed::dialog; -using namespace anm2ed::toast; +using namespace anm2ed::imgui; +using namespace anm2ed::util; using namespace anm2ed::types; -namespace anm2ed::state +namespace anm2ed { constexpr auto TICK_RATE = 30; constexpr auto TICK_INTERVAL = (1000 / TICK_RATE); @@ -28,11 +27,15 @@ namespace anm2ed::state void State::tick(Settings& settings) { + dockspace.tick(manager, settings); + if (auto document = manager.get()) + { if (auto animation = document->animation_get()) if (document->playback.isPlaying) document->playback.tick(document->anm2.info.fps, animation->frameNum, - animation->isLoop || settings.playbackIsLoop); + (animation->isLoop || settings.playbackIsLoop) && !manager.isRecording); + } } void State::update(SDL_Window*& window, Settings& settings) diff --git a/src/state.h b/src/state.h index 6f04633..07cc3f0 100644 --- a/src/state.h +++ b/src/state.h @@ -4,31 +4,31 @@ #include "dockspace.h" -namespace anm2ed::state +namespace anm2ed { class State { - void tick(settings::Settings&); - void update(SDL_Window*&, settings::Settings&); - void render(SDL_Window*&, settings::Settings&); + void tick(Settings&); + void update(SDL_Window*&, Settings&); + void render(SDL_Window*&, Settings&); public: bool isQuit{}; bool isQuitting{}; - manager::Manager manager; - resources::Resources resources; - dialog::Dialog dialog; - clipboard::Clipboard clipboard; + Manager manager; + Resources resources; + Dialog dialog; + Clipboard clipboard; - taskbar::Taskbar taskbar; - documents::Documents documents; - dockspace::Dockspace dockspace; + imgui::Taskbar taskbar; + imgui::Documents documents; + imgui::Dockspace dockspace; uint64_t previousTick{}; uint64_t previousUpdate{}; State(SDL_Window*&, std::vector&); - void loop(SDL_Window*&, settings::Settings&); + void loop(SDL_Window*&, Settings&); }; }; diff --git a/src/taskbar.h b/src/taskbar.h deleted file mode 100644 index 9549ae2..0000000 --- a/src/taskbar.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "canvas.h" -#include "dialog.h" -#include "imgui.h" -#include "manager.h" -#include "resources.h" -#include "settings.h" - -namespace anm2ed::taskbar -{ - class Taskbar - { - canvas::Canvas generate; - float generateTime{}; - imgui::PopupHelper generatePopup{imgui::PopupHelper("Generate Animation from Grid")}; - imgui::PopupHelper changePopup{imgui::PopupHelper("Change All Frame Properties", imgui::POPUP_SMALL, true)}; - imgui::PopupHelper renderPopup{imgui::PopupHelper("Render Animation")}; - imgui::PopupHelper configurePopup{imgui::PopupHelper("Configure")}; - imgui::PopupHelper aboutPopup{imgui::PopupHelper("About")}; - settings::Settings editSettings{}; - int selectedShortcut{-1}; - bool isQuittingMode{}; - - public: - float height{}; - - Taskbar(); - void update(manager::Manager&, settings::Settings&, resources::Resources&, dialog::Dialog&, bool&); - }; -}; diff --git a/src/timeline.h b/src/timeline.h deleted file mode 100644 index 9bb6f16..0000000 --- a/src/timeline.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "anm2.h" -#include "clipboard.h" -#include "document.h" -#include "manager.h" -#include "resources.h" -#include "settings.h" - -namespace anm2ed::timeline -{ - class Timeline - { - bool isDragging{}; - bool isWindowHovered{}; - bool isHorizontalScroll{}; - imgui::PopupHelper propertiesPopup{imgui::PopupHelper("Item Properties")}; - imgui::PopupHelper bakePopup{imgui::PopupHelper("Bake", imgui::POPUP_SMALL, true)}; - std::string addItemName{}; - int addItemSpritesheetID{}; - bool addItemIsRect{}; - int addItemID{-1}; - bool isUnusedItemsSet{}; - std::set unusedItems{}; - glm::vec2 scroll{}; - ImDrawList* pickerLineDrawList{}; - ImGuiStyle style{}; - - void context_menu(document::Document&, settings::Settings&, clipboard::Clipboard&); - void item_child(manager::Manager&, Document&, anm2::Animation*, settings::Settings&, resources::Resources&, - clipboard::Clipboard&, anm2::Type, int, int&); - void items_child(manager::Manager&, Document&, anm2::Animation*, settings::Settings&, resources::Resources&, - clipboard::Clipboard&); - void frame_child(document::Document&, anm2::Animation*, settings::Settings&, resources::Resources&, - clipboard::Clipboard&, anm2::Type, int, int&, float); - void frames_child(document::Document&, anm2::Animation*, settings::Settings&, resources::Resources&, - clipboard::Clipboard&); - - void popups(document::Document&, anm2::Animation*, settings::Settings&); - - public: - void update(manager::Manager&, settings::Settings&, resources::Resources&, clipboard::Clipboard&); - }; -} diff --git a/src/tool.h b/src/tool.h index 8814899..1c143cf 100644 --- a/src/tool.h +++ b/src/tool.h @@ -24,50 +24,50 @@ namespace anm2ed::tool struct Info { ImGuiMouseCursor cursor{ImGuiMouseCursor_None}; - icon::Type icon{}; - settings::ShortcutType shortcut{}; + resource::icon::Type icon{}; + ShortcutType shortcut{}; const char* label{}; const char* tooltip{}; }; constexpr Info INFO[] = { - {ImGuiMouseCursor_Hand, icon::PAN, settings::SHORTCUT_PAN, "##Pan", + {ImGuiMouseCursor_Hand, resource::icon::PAN, SHORTCUT_PAN, "##Pan", "Use the pan tool.\nWill shift the view as the cursor is dragged.\nYou can also use the middle mouse button to " "pan at any time."}, - {ImGuiMouseCursor_ResizeAll, icon::MOVE, settings::SHORTCUT_MOVE, "##Move", + {ImGuiMouseCursor_ResizeAll, resource::icon::MOVE, SHORTCUT_MOVE, "##Move", "Use the move tool.\nAnimation Preview: Will move the position of the frame." "\nSpritesheet Editor: Will move the pivot, and holding right click will use the Crop functionality instead." "\nUse mouse or directional keys to change the value."}, - {ImGuiMouseCursor_Arrow, icon::ROTATE, settings::SHORTCUT_ROTATE, "##Rotate", + {ImGuiMouseCursor_Arrow, resource::icon::ROTATE, SHORTCUT_ROTATE, "##Rotate", "Use the rotate tool.\nWill rotate the selected item as the cursor is dragged, or directional keys are " "pressed.\n(Animation Preview only.)"}, - {ImGuiMouseCursor_ResizeNWSE, icon::SCALE, settings::SHORTCUT_SCALE, "##Scale", + {ImGuiMouseCursor_ResizeNESW, resource::icon::SCALE, SHORTCUT_SCALE, "##Scale", "Use the scale tool.\nWill scale the selected item as the cursor is dragged, or directional keys are " "pressed.\n(Animation Preview only.)"}, - {ImGuiMouseCursor_ResizeAll, icon::CROP, settings::SHORTCUT_CROP, "##Crop", + {ImGuiMouseCursor_Arrow, resource::icon::CROP, SHORTCUT_CROP, "##Crop", "Use the crop tool.\nWill produce a crop rectangle based on how the cursor is dragged." "\nAlternatively, you can use the arrow keys and Ctrl/Shift to move the size/position, respectively." "\nHolding right click will use the Move tool's functionality." "\n(Spritesheet Editor only.)"}, - {ImGuiMouseCursor_Hand, icon::DRAW, settings::SHORTCUT_DRAW, "##Draw", + {ImGuiMouseCursor_Arrow, resource::icon::DRAW, SHORTCUT_DRAW, "##Draw", "Draws pixels onto the selected spritesheet, with the current color.\n(Spritesheet Editor only.)"}, - {ImGuiMouseCursor_Arrow, icon::ERASE, settings::SHORTCUT_ERASE, "##Erase", + {ImGuiMouseCursor_Arrow, resource::icon::ERASE, SHORTCUT_ERASE, "##Erase", "Erases pixels from the selected spritesheet.\n(Spritesheet Editor only.)"}, - {ImGuiMouseCursor_Arrow, icon::COLOR_PICKER, settings::SHORTCUT_COLOR_PICKER, "##Color Picker", + {ImGuiMouseCursor_Arrow, resource::icon::COLOR_PICKER, SHORTCUT_COLOR_PICKER, "##Color Picker", "Selects a color from the canvas.\n(Spritesheet Editor only.)"}, - {ImGuiMouseCursor_None, icon::UNDO, settings::SHORTCUT_UNDO, "##Undo", "Undoes the last action."}, + {ImGuiMouseCursor_None, resource::icon::UNDO, SHORTCUT_UNDO, "##Undo", "Undoes the last action."}, - {ImGuiMouseCursor_None, icon::REDO, settings::SHORTCUT_REDO, "##Redo", "Redoes the last action."}, + {ImGuiMouseCursor_None, resource::icon::REDO, SHORTCUT_REDO, "##Redo", "Redoes the last action."}, - {ImGuiMouseCursor_None, icon::NONE, settings::SHORTCUT_COLOR, "##Color", + {ImGuiMouseCursor_None, resource::icon::NONE, SHORTCUT_COLOR, "##Color", "Selects the color to be used for drawing.\n(Spritesheet Editor only.)"}, }; } \ No newline at end of file diff --git a/src/types.h b/src/types.h index acc12b3..80b58e7 100644 --- a/src/types.h +++ b/src/types.h @@ -4,22 +4,6 @@ #include #include -namespace anm2ed::types::change -{ - enum Type - { - LAYERS, - NULLS, - SPRITESHEETS, - EVENTS, - ANIMATIONS, - ITEMS, - FRAMES, - ALL, - COUNT - }; -} - namespace anm2ed::types::draw_order { enum Type @@ -69,16 +53,6 @@ namespace anm2ed::types::merge }; } -namespace anm2ed::types::frame_change -{ - enum Type - { - ADD, - SUBTRACT, - ADJUST - }; -} - namespace anm2ed::types::color { using namespace glm; @@ -88,17 +62,14 @@ namespace anm2ed::types::color constexpr auto RED = vec4(1.0, 0.0, 0.0, 1.0); constexpr auto GREEN = vec4(0.0, 1.0, 0.0, 1.0); constexpr auto BLUE = vec4(0.0, 0.0, 1.0, 1.0); + constexpr auto PINK = vec4(1.0, 0.0, 1.0, 1.0); constexpr auto TRANSPARENT = vec4(); } -namespace anm2ed::types::step -{ - constexpr auto NORMAL = 1; - constexpr auto FAST = 10; -} - namespace anm2ed::types { + constexpr auto ID_NONE = -1; + constexpr ImVec2 to_imvec2(const glm::vec2& v) noexcept { return {v.x, v.y}; diff --git a/src/filesystem.cpp b/src/util/filesystem_.cpp similarity index 87% rename from src/filesystem.cpp rename to src/util/filesystem_.cpp index c62dcaa..e3c3783 100644 --- a/src/filesystem.cpp +++ b/src/util/filesystem_.cpp @@ -1,16 +1,11 @@ -#include "filesystem.h" +#include "filesystem_.h" #include #include #include -namespace anm2ed::filesystem +namespace anm2ed::util::filesystem { - bool directories_create(const std::string& path) - { - return std::filesystem::create_directories(path); - } - std::string path_preferences_get() { char* preferencesPath = SDL_GetPrefPath("", "anm2ed"); diff --git a/src/filesystem.h b/src/util/filesystem_.h similarity index 82% rename from src/filesystem.h rename to src/util/filesystem_.h index 2c2db96..7a78ef3 100644 --- a/src/filesystem.h +++ b/src/util/filesystem_.h @@ -3,12 +3,11 @@ #include #include -namespace anm2ed::filesystem +namespace anm2ed::util::filesystem { std::string path_preferences_get(); bool path_is_exist(const std::string&); bool path_is_extension(const std::string&, const std::string&); - bool directories_create(const std::string&); class WorkingDirectory { diff --git a/src/util/map_.h b/src/util/map_.h new file mode 100644 index 0000000..6a75c89 --- /dev/null +++ b/src/util/map_.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace anm2ed::util::map +{ + template int next_id_get(std::map& map) + { + int id = 0; + + for (auto& [key, value] : map) + { + if (key != id) break; + ++id; + } + + return id; + } + + template T1* find(std::map& map, T0 index) + { + return map.contains(index) ? &map[index] : nullptr; + } +} diff --git a/src/math.cpp b/src/util/math_.cpp similarity index 98% rename from src/math.cpp rename to src/util/math_.cpp index edeca35..a34b62a 100644 --- a/src/math.cpp +++ b/src/util/math_.cpp @@ -5,7 +5,7 @@ using namespace glm; -namespace anm2ed::math +namespace anm2ed::util::math { constexpr auto FLOAT_FORMAT_MAX_DECIMALS = 7; constexpr auto FLOAT_FORMAT_EPSILON = 1e-7f; @@ -78,4 +78,4 @@ namespace anm2ed::math return glm::translate(mat4(1.0f), vec3(position, 0.0f)) * local; } -} +} \ No newline at end of file diff --git a/src/math.h b/src/util/math_.h similarity index 88% rename from src/math.h rename to src/util/math_.h index 6e928be..5a1beac 100644 --- a/src/math.h +++ b/src/util/math_.h @@ -1,9 +1,9 @@ #pragma once #include -#include +#include -namespace anm2ed::math +namespace anm2ed::util::math { template constexpr T percent_to_unit(T value) { @@ -39,7 +39,6 @@ namespace anm2ed::math const char* vec2_format_get(glm::vec2&); - glm::mat4 quad_model_get(glm::vec2 = {}, glm::vec2 = {}, glm::vec2 = {}, - glm::vec2 = glm::vec2(1.0f), float = {}); + glm::mat4 quad_model_get(glm::vec2 = {}, glm::vec2 = {}, glm::vec2 = {}, glm::vec2 = glm::vec2(1.0f), float = {}); glm::mat4 quad_model_parent_get(glm::vec2 = {}, glm::vec2 = {}, glm::vec2 = glm::vec2(1.0f), float = {}); -} +} \ No newline at end of file diff --git a/src/util.cpp b/src/util/string_.cpp similarity index 55% rename from src/util.cpp rename to src/util/string_.cpp index 110a494..c814326 100644 --- a/src/util.cpp +++ b/src/util/string_.cpp @@ -1,20 +1,6 @@ -#include "util.h" +#include "string_.h" #include -#include - -namespace anm2ed::util::time -{ - std::string get(const char* format) - { - auto now = std::chrono::system_clock::now(); - auto time = std::chrono::system_clock::to_time_t(now); - auto localTime = *std::localtime(&time); - std::ostringstream timeString; - timeString << std::put_time(&localTime, format); - return timeString.str(); - } -} namespace anm2ed::util::string { @@ -25,7 +11,7 @@ namespace anm2ed::util::string return transformed; } - std::string replace_backslash(const std::string& string) + std::string backslash_replace(const std::string& string) { std::string transformed = string; for (char& character : transformed) @@ -33,6 +19,18 @@ namespace anm2ed::util::string return transformed; } + std::string backslash_replace_to_lower(const std::string& string) + { + std::string transformed = string; + transformed = backslash_replace(transformed); + return to_lower(transformed); + } + + std::string quote(const std::string& string) + { + return "\"" + string + "\""; + } + bool to_bool(const std::string& string) { return to_lower(string) == "true"; diff --git a/src/util/string_.h b/src/util/string_.h new file mode 100644 index 0000000..ce4d623 --- /dev/null +++ b/src/util/string_.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace anm2ed::util::string +{ + std::string to_lower(const std::string&); + std::string backslash_replace(const std::string&); + std::string backslash_replace_to_lower(const std::string&); + bool to_bool(const std::string&); +} diff --git a/src/util/time_.cpp b/src/util/time_.cpp new file mode 100644 index 0000000..96021c4 --- /dev/null +++ b/src/util/time_.cpp @@ -0,0 +1,16 @@ +#include "time_.h" + +#include + +namespace anm2ed::util::time +{ + std::string get(const char* format) + { + auto now = std::chrono::system_clock::now(); + auto time = std::chrono::system_clock::to_time_t(now); + auto localTime = *std::localtime(&time); + std::ostringstream timeString; + timeString << std::put_time(&localTime, format); + return timeString.str(); + } +} \ No newline at end of file diff --git a/src/util/time_.h b/src/util/time_.h new file mode 100644 index 0000000..f2f716d --- /dev/null +++ b/src/util/time_.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace anm2ed::util::time +{ + constexpr auto SECOND_M = 60; + + std::string get(const char*); +} \ No newline at end of file diff --git a/src/util/unordered_map_.h b/src/util/unordered_map_.h new file mode 100644 index 0000000..2c37e77 --- /dev/null +++ b/src/util/unordered_map_.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace anm2ed::util::unordered_map +{ + template T1* find(std::unordered_map& map, T0 index) + { + return map.contains(index) ? &map[index] : nullptr; + } +} diff --git a/src/util.h b/src/util/vector_.h similarity index 67% rename from src/util.h rename to src/util/vector_.h index b66ac09..49d4cca 100644 --- a/src/util.h +++ b/src/util/vector_.h @@ -1,57 +1,10 @@ #pragma once #include -#include #include #include -#include -#include #include -namespace anm2ed::util::time -{ - constexpr auto SECOND_S = 1.0; - constexpr auto SECOND_M = 60.0; - - std::string get(const char*); -} - -namespace anm2ed::util::string -{ - std::string to_lower(const std::string&); - std::string replace_backslash(const std::string&); - bool to_bool(const std::string&); -} - -namespace anm2ed::util::map -{ - template int next_id_get(std::map& map) - { - int id = 0; - - for (auto& [key, value] : map) - { - if (key != id) break; - ++id; - } - - return id; - } - - template T1* find(std::map& map, T0 index) - { - return map.contains(index) ? &map[index] : nullptr; - } -} - -namespace anm2ed::util::unordered_map -{ - template T1* find(std::unordered_map& map, T0 index) - { - return map.contains(index) ? &map[index] : nullptr; - } -} - namespace anm2ed::util::vector { template T* find(std::vector& v, int index) diff --git a/src/util/xml_.cpp b/src/util/xml_.cpp new file mode 100644 index 0000000..47299db --- /dev/null +++ b/src/util/xml_.cpp @@ -0,0 +1,38 @@ +#include "xml_.h" + +#include "math_.h" + +using namespace tinyxml2; + +namespace anm2ed::util::xml +{ + std::string document_to_string(XMLDocument& self) + { + XMLPrinter printer{}; + self.Print(&printer); + return std::string(printer.CStr()); + } + + XMLError query_string_attribute(XMLElement* element, const char* attribute, std::string* out) + { + const char* temp = nullptr; + auto result = element->QueryStringAttribute(attribute, &temp); + if (result == XML_SUCCESS && temp) *out = temp; + return result; + } + + XMLError query_path_attribute(XMLElement* element, const char* attribute, std::filesystem::path* out) + { + std::string temp{}; + auto result = query_string_attribute(element, attribute, &temp); + if (result == XML_SUCCESS) *out = temp; + return result; + } + + void query_color_attribute(XMLElement* element, const char* attribute, float& out) + { + int value{}; + element->QueryIntAttribute(attribute, &value); + out = math::uint8_to_float(value); + } +} \ No newline at end of file diff --git a/src/xml.h b/src/util/xml_.h similarity index 93% rename from src/xml.h rename to src/util/xml_.h index 100ec82..0a4cf2b 100644 --- a/src/xml.h +++ b/src/util/xml_.h @@ -5,7 +5,7 @@ #include -namespace anm2ed::xml +namespace anm2ed::util::xml { std::string document_to_string(tinyxml2::XMLDocument&); tinyxml2::XMLError query_string_attribute(tinyxml2::XMLElement*, const char*, std::string*); diff --git a/src/welcome.h b/src/welcome.h deleted file mode 100644 index 238470f..0000000 --- a/src/welcome.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "documents.h" -#include "manager.h" -#include "taskbar.h" - -namespace anm2ed::welcome -{ - class Welcome - { - imgui::PopupHelper restorePopup{imgui::PopupHelper("Restore", imgui::POPUP_SMALL, true)}; - - public: - void update(manager::Manager&, resources::Resources&, dialog::Dialog&, taskbar::Taskbar&, documents::Documents&); - }; -}; \ No newline at end of file diff --git a/src/xml.cpp b/src/xml.cpp deleted file mode 100644 index c4ff81b..0000000 --- a/src/xml.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "xml.h" - -#include "math.h" - -namespace anm2ed::xml -{ - std::string document_to_string(tinyxml2::XMLDocument& self) - { - tinyxml2::XMLPrinter printer{}; - self.Print(&printer); - return std::string(printer.CStr()); - } - - tinyxml2::XMLError query_string_attribute(tinyxml2::XMLElement* element, const char* attribute, std::string* out) - { - const char* temp = nullptr; - auto result = element->QueryStringAttribute(attribute, &temp); - if (result == tinyxml2::XML_SUCCESS && temp) *out = temp; - return result; - } - - tinyxml2::XMLError query_path_attribute(tinyxml2::XMLElement* element, const char* attribute, - std::filesystem::path* out) - { - std::string temp{}; - auto result = query_string_attribute(element, attribute, &temp); - if (result == tinyxml2::XML_SUCCESS) *out = temp; - return result; - } - - void query_color_attribute(tinyxml2::XMLElement* element, const char* attribute, float& out) - { - int value{}; - element->QueryIntAttribute(attribute, &value); - out = math::uint8_to_float(value); - } -} \ No newline at end of file From 1e35910b0a907a4f31bf8ed41e66b4ce78bb0c7d Mon Sep 17 00:00:00 2001 From: shweet Date: Mon, 3 Nov 2025 00:16:05 -0500 Subject: [PATCH 12/15] Refactoring, FFmpeg updates --- src/anm2/animation.cpp | 55 +- src/anm2/animation.h | 3 +- src/anm2/animations.cpp | 112 ---- src/anm2/animations.h | 4 +- src/anm2/anm2.cpp | 371 ++----------- src/anm2/anm2.h | 54 +- src/anm2/anm2_animations.cpp | 137 +++++ src/anm2/anm2_events.cpp | 75 +++ src/anm2/anm2_items.cpp | 83 +++ src/anm2/anm2_layers.cpp | 66 +++ src/anm2/anm2_nulls.cpp | 66 +++ src/anm2/anm2_sounds.cpp | 75 +++ src/anm2/anm2_spritesheets.cpp | 87 ++++ src/anm2/content.cpp | 202 +------ src/anm2/content.h | 20 - src/anm2/event.h | 2 +- src/anm2/frame.cpp | 8 + src/anm2/frame.h | 2 + src/anm2/item.cpp | 54 +- src/anm2/item.h | 4 +- src/anm2/layer.cpp | 4 + src/anm2/layer.h | 2 + src/anm2/sound.cpp | 24 +- src/anm2/sound.h | 6 +- src/anm2/spritesheet.cpp | 7 +- src/canvas.h | 7 +- src/document.cpp | 666 ++++-------------------- src/document.h | 150 ++---- src/imgui/documents.h | 1 - src/imgui/imgui_.cpp | 32 +- src/imgui/imgui_.h | 196 ++++--- src/imgui/taskbar.cpp | 307 +++++------ src/imgui/window/animation_preview.cpp | 239 ++++++--- src/imgui/window/animation_preview.h | 4 + src/imgui/window/animations.cpp | 215 ++++++-- src/imgui/window/events.cpp | 120 ++--- src/imgui/window/events.h | 3 - src/imgui/window/frame_properties.cpp | 19 +- src/imgui/window/layers.cpp | 86 +-- src/imgui/window/nulls.cpp | 84 ++- src/imgui/window/sounds.cpp | 85 +-- src/imgui/window/spritesheet_editor.cpp | 221 ++++++-- src/imgui/window/spritesheet_editor.h | 1 + src/imgui/window/spritesheets.cpp | 138 ++--- src/imgui/window/timeline.cpp | 211 +++++--- src/imgui/window/timeline.h | 2 +- src/imgui/window/welcome.cpp | 4 +- src/manager.cpp | 19 +- src/manager.h | 2 + src/render.h | 18 +- src/resource/audio.cpp | 9 +- src/resource/audio.h | 3 +- src/resource/icon.h | 7 +- src/settings.h | 18 +- src/snapshots.cpp | 27 +- src/snapshots.h | 19 +- src/state.cpp | 11 +- src/storage.cpp | 12 + src/storage.h | 28 + src/tool.h | 36 +- src/util/filesystem_.cpp | 9 + src/util/filesystem_.h | 1 + src/util/string_.cpp | 7 - src/util/string_.h | 1 - src/util/vector_.h | 17 +- 65 files changed, 2322 insertions(+), 2236 deletions(-) create mode 100644 src/anm2/anm2_animations.cpp create mode 100644 src/anm2/anm2_events.cpp create mode 100644 src/anm2/anm2_items.cpp create mode 100644 src/anm2/anm2_layers.cpp create mode 100644 src/anm2/anm2_nulls.cpp create mode 100644 src/anm2/anm2_sounds.cpp create mode 100644 src/anm2/anm2_spritesheets.cpp create mode 100644 src/storage.cpp create mode 100644 src/storage.h diff --git a/src/anm2/animation.cpp b/src/anm2/animation.cpp index a275dbc..656a505 100644 --- a/src/anm2/animation.cpp +++ b/src/anm2/animation.cpp @@ -8,7 +8,6 @@ using namespace anm2ed::util; using namespace glm; - using namespace tinyxml2; namespace anm2ed::anm2 @@ -79,7 +78,7 @@ namespace anm2ed::anm2 } } - void Animation::serialize(XMLDocument& document, XMLElement* parent) + XMLElement* Animation::to_element(XMLDocument& document) { auto element = document.NewElement("Animation"); element->SetAttribute("Name", name.c_str()); @@ -103,7 +102,19 @@ namespace anm2ed::anm2 triggers.serialize(document, element, TRIGGER); - parent->InsertEndChild(element); + return element; + } + + void Animation::serialize(XMLDocument& document, XMLElement* parent) + { + parent->InsertEndChild(to_element(document)); + } + + std::string Animation::to_string() + { + XMLDocument document{}; + document.InsertEndChild(to_element(document)); + return xml::document_to_string(document); } int Animation::length() @@ -126,49 +137,16 @@ namespace anm2ed::anm2 return length; } - std::string Animation::to_string() - { - XMLDocument document{}; - - auto* element = document.NewElement("Animation"); - document.InsertFirstChild(element); - - element->SetAttribute("Name", name.c_str()); - element->SetAttribute("FrameNum", frameNum); - element->SetAttribute("Loop", isLoop); - - rootAnimation.serialize(document, element, ROOT); - - auto layerAnimationsElement = document.NewElement("LayerAnimations"); - for (auto& i : layerOrder) - { - Item& layerAnimation = layerAnimations.at(i); - layerAnimation.serialize(document, layerAnimationsElement, LAYER, i); - } - element->InsertEndChild(layerAnimationsElement); - - auto nullAnimationsElement = document.NewElement("NullAnimations"); - for (auto& [id, nullAnimation] : nullAnimations) - nullAnimation.serialize(document, nullAnimationsElement, NULL_, id); - element->InsertEndChild(nullAnimationsElement); - - triggers.serialize(document, element, TRIGGER); - - XMLPrinter printer; - document.Print(&printer); - return std::string(printer.CStr()); - } - vec4 Animation::rect(bool isRootTransform) { + constexpr ivec2 CORNERS[4] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; + float minX = std::numeric_limits::infinity(); float minY = std::numeric_limits::infinity(); float maxX = -std::numeric_limits::infinity(); float maxY = -std::numeric_limits::infinity(); bool any = false; - constexpr ivec2 CORNERS[4] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; - for (float t = 0.0f; t < (float)frameNum; t += 1.0f) { mat4 transform(1.0f); @@ -202,5 +180,4 @@ namespace anm2ed::anm2 if (!any) return vec4(-1.0f); return {minX, minY, maxX - minX, maxY - minY}; } - } \ No newline at end of file diff --git a/src/anm2/animation.h b/src/anm2/animation.h index dc47fc7..0cc68a8 100644 --- a/src/anm2/animation.h +++ b/src/anm2/animation.h @@ -26,10 +26,11 @@ namespace anm2ed::anm2 Animation(tinyxml2::XMLElement*); Item* item_get(Type, int = -1); void item_remove(Type, int = -1); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&); void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); + std::string to_string(); int length(); glm::vec4 rect(bool); - std::string to_string(); }; } \ No newline at end of file diff --git a/src/anm2/animations.cpp b/src/anm2/animations.cpp index 1ace1bb..1eaaed4 100644 --- a/src/anm2/animations.cpp +++ b/src/anm2/animations.cpp @@ -1,7 +1,5 @@ #include "animations.h" -#include - #include "xml_.h" using namespace tinyxml2; @@ -42,114 +40,4 @@ namespace anm2ed::anm2 return length; } - int Animations::merge(int target, std::set& sources, merge::Type type, bool isDeleteAfter) - { - Animation& animation = items.at(target); - - if (!animation.name.ends_with(MERGED_STRING)) animation.name = animation.name + " " + MERGED_STRING; - - auto merge_item = [&](Item& destination, Item& source) - { - switch (type) - { - case merge::APPEND: - destination.frames.insert(destination.frames.end(), source.frames.begin(), source.frames.end()); - break; - case merge::PREPEND: - destination.frames.insert(destination.frames.begin(), source.frames.begin(), source.frames.end()); - break; - case merge::REPLACE: - if (destination.frames.size() < source.frames.size()) destination.frames.resize(source.frames.size()); - for (int i = 0; i < (int)source.frames.size(); i++) - destination.frames[i] = source.frames[i]; - break; - case merge::IGNORE: - default: - break; - } - }; - - for (auto& i : sources) - { - if (i == target) continue; - if (i < 0 || i >= (int)items.size()) continue; - - auto& source = items.at(i); - - merge_item(animation.rootAnimation, source.rootAnimation); - - for (auto& [id, layerAnimation] : source.layerAnimations) - { - if (!animation.layerAnimations.contains(id)) - { - animation.layerAnimations[id] = layerAnimation; - animation.layerOrder.emplace_back(id); - } - merge_item(animation.layerAnimations[id], layerAnimation); - } - - for (auto& [id, nullAnimation] : source.nullAnimations) - { - if (!animation.nullAnimations.contains(id)) animation.nullAnimations[id] = nullAnimation; - merge_item(animation.nullAnimations[id], nullAnimation); - } - - merge_item(animation.triggers, source.triggers); - } - - if (isDeleteAfter) - { - for (auto& source : std::ranges::reverse_view(sources)) - { - if (source == target) continue; - items.erase(items.begin() + source); - } - } - - int finalIndex = target; - - if (isDeleteAfter) - { - int numDeletedBefore = 0; - for (auto& idx : sources) - { - if (idx == target) continue; - if (idx >= 0 && idx < target) ++numDeletedBefore; - } - finalIndex -= numDeletedBefore; - } - - return finalIndex; - } - - bool Animations::animations_deserialize(const std::string& string, int start, std::set& indices, - std::string* errorString) - { - XMLDocument document{}; - - if (document.Parse(string.c_str()) == XML_SUCCESS) - { - if (!document.FirstChildElement("Animation")) - { - if (errorString) *errorString = "No valid animation(s)."; - return false; - } - - int count{}; - for (auto element = document.FirstChildElement("Animation"); element; - element = element->NextSiblingElement("Animation")) - { - auto index = start + count; - items.insert(items.begin() + start + count, Animation(element)); - indices.insert(index); - count++; - } - - return true; - } - else if (errorString) - *errorString = document.ErrorStr(); - - return false; - } } \ No newline at end of file diff --git a/src/anm2/animations.h b/src/anm2/animations.h index ce377b2..a2c4fe5 100644 --- a/src/anm2/animations.h +++ b/src/anm2/animations.h @@ -14,9 +14,7 @@ namespace anm2ed::anm2 Animations() = default; Animations(tinyxml2::XMLElement*); tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&); - int length(); void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); - int merge(int, std::set&, types::merge::Type = types::merge::APPEND, bool = true); - bool animations_deserialize(const std::string&, int, std::set&, std::string* = nullptr); + int length(); }; } \ No newline at end of file diff --git a/src/anm2/anm2.cpp b/src/anm2/anm2.cpp index 0b53b9c..79963a5 100644 --- a/src/anm2/anm2.cpp +++ b/src/anm2/anm2.cpp @@ -1,12 +1,9 @@ #include "anm2.h" -#include - #include "filesystem_.h" -#include "map_.h" #include "time_.h" -#include "unordered_map_.h" #include "vector_.h" +#include "xml_.h" using namespace tinyxml2; using namespace anm2ed::types; @@ -20,41 +17,6 @@ namespace anm2ed::anm2 info.createdOn = time::get("%d-%B-%Y %I:%M:%S"); } - bool Anm2::serialize(const std::string& path, std::string* errorString) - { - XMLDocument document; - - auto* element = document.NewElement("AnimatedActor"); - document.InsertFirstChild(element); - - info.serialize(document, element); - content.serialize(document, element); - animations.serialize(document, element); - - if (document.SaveFile(path.c_str()) != XML_SUCCESS) - { - if (errorString) *errorString = document.ErrorStr(); - return false; - } - return true; - } - - std::string Anm2::to_string() - { - XMLDocument document; - - auto* element = document.NewElement("AnimatedActor"); - document.InsertFirstChild(element); - - info.serialize(document, element); - content.serialize(document, element); - animations.serialize(document, element); - - XMLPrinter printer; - document.Print(&printer); - return std::string(printer.CStr()); - } - Anm2::Anm2(const std::string& path, std::string* errorString) { XMLDocument document; @@ -75,302 +37,53 @@ namespace anm2ed::anm2 animations = Animations((XMLElement*)animationsElement); } + bool Anm2::serialize(const std::string& path, std::string* errorString) + { + XMLDocument document; + + auto* element = document.NewElement("AnimatedActor"); + document.InsertFirstChild(element); + + info.serialize(document, element); + content.serialize(document, element); + animations.serialize(document, element); + + if (document.SaveFile(path.c_str()) != XML_SUCCESS) + { + if (errorString) *errorString = document.ErrorStr(); + return false; + } + return true; + } + + XMLElement* Anm2::to_element(XMLDocument& document) + { + auto element = document.NewElement("AnimatedActor"); + document.InsertFirstChild(element); + + info.serialize(document, element); + content.serialize(document, element); + animations.serialize(document, element); + + return element; + } + + std::string Anm2::to_string() + { + XMLDocument document{}; + document.InsertEndChild(to_element(document)); + return xml::document_to_string(document); + } + uint64_t Anm2::hash() { return std::hash{}(to_string()); } - Animation* Anm2::animation_get(Reference reference) - { - return vector::find(animations.items, reference.animationIndex); - } - - std::vector Anm2::animation_names_get() - { - std::vector names{}; - for (auto& animation : animations.items) - names.push_back(animation.name); - return names; - } - - Item* Anm2::item_get(Reference reference) - { - if (Animation* animation = animation_get(reference)) - { - switch (reference.itemType) - { - case ROOT: - return &animation->rootAnimation; - case LAYER: - return unordered_map::find(animation->layerAnimations, reference.itemID); - case NULL_: - return map::find(animation->nullAnimations, reference.itemID); - case TRIGGER: - return &animation->triggers; - default: - return nullptr; - } - } - return nullptr; - } - Frame* Anm2::frame_get(Reference reference) { - Item* item = item_get(reference); - if (!item) return nullptr; - return vector::find(item->frames, reference.frameIndex); + if (auto item = item_get(reference); item) + if (vector::in_bounds(item->frames, reference.frameIndex)) return &item->frames[reference.frameIndex]; return nullptr; } - - bool Anm2::spritesheet_add(const std::string& directory, const std::string& path, int& id) - { - Spritesheet spritesheet(directory, path); - if (!spritesheet.is_valid()) return false; - id = map::next_id_get(content.spritesheets); - content.spritesheets[id] = std::move(spritesheet); - return true; - } - - void Anm2::spritesheet_remove(int id) - { - content.spritesheets.erase(id); - } - - Spritesheet* Anm2::spritesheet_get(int id) - { - return map::find(content.spritesheets, id); - } - - std::set Anm2::spritesheets_unused() - { - return content.spritesheets_unused(); - } - - std::vector Anm2::spritesheet_names_get() - { - std::vector names{}; - for (auto& [id, spritesheet] : content.spritesheets) - names.push_back(std::format(SPRITESHEET_FORMAT, id, spritesheet.path.c_str())); - return names; - } - - Reference Anm2::layer_add(Reference reference, std::string name, int spritesheetID, locale::Type locale) - { - auto id = reference.itemID == -1 ? map::next_id_get(content.layers) : reference.itemID; - auto& layer = content.layers[id]; - - layer.name = !name.empty() ? name : layer.name; - layer.spritesheetID = content.spritesheets.contains(spritesheetID) ? spritesheetID : 0; - - auto add = [&](Animation* animation, int id) - { - animation->layerAnimations[id] = Item(); - animation->layerOrder.push_back(id); - }; - - if (locale == locale::GLOBAL) - { - for (auto& animation : animations.items) - if (!animation.layerAnimations.contains(id)) add(&animation, id); - } - else if (locale == locale::LOCAL) - { - if (auto animation = animation_get(reference)) - if (!animation->layerAnimations.contains(id)) add(animation, id); - } - - return {reference.animationIndex, LAYER, id}; - } - - Reference Anm2::null_add(Reference reference, std::string name, locale::Type locale) - { - auto id = reference.itemID == -1 ? map::next_id_get(content.nulls) : reference.itemID; - auto& null = content.nulls[id]; - - null.name = !name.empty() ? name : null.name; - - auto add = [&](Animation* animation, int id) { animation->nullAnimations[id] = Item(); }; - - if (locale == locale::GLOBAL) - { - for (auto& animation : animations.items) - if (!animation.nullAnimations.contains(id)) add(&animation, id); - } - else if (locale == locale::LOCAL) - { - if (auto animation = animation_get(reference)) - if (!animation->nullAnimations.contains(id)) add(animation, id); - } - - return {reference.animationIndex, LAYER, id}; - } - - void Anm2::event_add(int& id) - { - content.event_add(id); - } - - std::set Anm2::events_unused(Reference reference) - { - std::set used{}; - std::set unused{}; - - if (auto animation = animation_get(reference); animation) - for (auto& frame : animation->triggers.frames) - used.insert(frame.eventID); - else - for (auto& animation : animations.items) - for (auto& frame : animation.triggers.frames) - used.insert(frame.eventID); - - for (auto& id : content.events | std::views::keys) - if (!used.contains(id)) unused.insert(id); - - return unused; - } - - std::set Anm2::layers_unused(Reference reference) - { - std::set used{}; - std::set unused{}; - - if (auto animation = animation_get(reference); animation) - for (auto& id : animation->layerAnimations | std::views::keys) - used.insert(id); - else - for (auto& animation : animations.items) - for (auto& id : animation.layerAnimations | std::views::keys) - used.insert(id); - - for (auto& id : content.layers | std::views::keys) - if (!used.contains(id)) unused.insert(id); - - return unused; - } - - std::set Anm2::nulls_unused(Reference reference) - { - std::set used{}; - std::set unused{}; - - if (auto animation = animation_get(reference); animation) - for (auto& id : animation->nullAnimations | std::views::keys) - used.insert(id); - else - for (auto& animation : animations.items) - for (auto& id : animation.nullAnimations | std::views::keys) - used.insert(id); - - for (auto& id : content.nulls | std::views::keys) - if (!used.contains(id)) unused.insert(id); - - return unused; - } - - std::vector Anm2::event_names_get() - { - std::vector names{}; - for (auto& event : content.events | std::views::values) - names.push_back(event.name); - return names; - } - - bool Anm2::sound_add(const std::string& directory, const std::string& path, int& id) - { - id = map::next_id_get(content.sounds); - content.sounds[id] = Sound(directory, path); - return true; - } - - std::set Anm2::sounds_unused() - { - std::set used; - for (auto& event : content.events | std::views::values) - used.insert(event.soundID); - - std::set unused; - for (auto& id : content.sounds | std::views::keys) - if (!used.contains(id)) unused.insert(id); - - return unused; - } - - std::vector Anm2::sound_names_get() - { - std::vector names{}; - for (auto& [id, sound] : content.sounds) - names.push_back(std::format(SOUND_FORMAT, id, sound.path.c_str())); - return names; - } - - void Anm2::bake(Reference reference, int interval, bool isRoundScale, bool isRoundRotation) - { - Item* item = item_get(reference); - if (!item) return; - - Frame* frame = frame_get(reference); - if (!frame) return; - - if (frame->delay == FRAME_DELAY_MIN) return; - - Reference referenceNext = reference; - referenceNext.frameIndex = reference.frameIndex + 1; - - Frame* frameNext = frame_get(referenceNext); - if (!frameNext) frameNext = frame; - - Frame baseFrame = *frame; - Frame baseFrameNext = *frameNext; - - int delay{}; - int index = reference.frameIndex; - - while (delay < baseFrame.delay) - { - float interpolation = (float)delay / baseFrame.delay; - - Frame baked = baseFrame; - baked.delay = std::min(interval, baseFrame.delay - delay); - baked.isInterpolated = (index == reference.frameIndex) ? baseFrame.isInterpolated : false; - - baked.rotation = glm::mix(baseFrame.rotation, baseFrameNext.rotation, interpolation); - baked.position = glm::mix(baseFrame.position, baseFrameNext.position, interpolation); - baked.scale = glm::mix(baseFrame.scale, baseFrameNext.scale, interpolation); - baked.colorOffset = glm::mix(baseFrame.colorOffset, baseFrameNext.colorOffset, interpolation); - baked.tint = glm::mix(baseFrame.tint, baseFrameNext.tint, interpolation); - - if (isRoundScale) baked.scale = vec2(ivec2(baked.scale)); - if (isRoundRotation) baked.rotation = (int)baked.rotation; - - if (index == reference.frameIndex) - item->frames[index] = baked; - else - item->frames.insert(item->frames.begin() + index, baked); - index++; - - delay += baked.delay; - } - } - - void Anm2::generate_from_grid(Reference reference, ivec2 startPosition, ivec2 size, ivec2 pivot, int columns, - int count, int delay) - { - auto item = item_get(reference); - if (!item) return; - - for (int i = 0; i < count; i++) - { - auto row = i / columns; - auto column = i % columns; - - Frame frame{}; - - frame.delay = delay; - frame.pivot = pivot; - frame.size = size; - frame.crop = startPosition + ivec2(size.x * column, size.y * row); - - item->frames.emplace_back(frame); - } - } -} +} \ No newline at end of file diff --git a/src/anm2/anm2.h b/src/anm2/anm2.h index 9ce3207..3f970ff 100644 --- a/src/anm2/anm2.h +++ b/src/anm2/anm2.h @@ -24,8 +24,6 @@ namespace anm2ed::anm2 auto operator<=>(const Reference&) const = default; }; - constexpr anm2::Reference REFERENCE_DEFAULT = {-1, anm2::NONE, -1, -1, -1}; - class Anm2 { public: @@ -34,39 +32,47 @@ namespace anm2ed::anm2 Animations animations{}; Anm2(); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&); bool serialize(const std::string&, std::string* = nullptr); std::string to_string(); Anm2(const std::string&, std::string* = nullptr); uint64_t hash(); - Animation* animation_get(Reference); - std::vector animation_names_get(); - Item* item_get(Reference); - - Frame* frame_get(Reference); - - bool spritesheet_add(const std::string&, const std::string&, int&); Spritesheet* spritesheet_get(int); + bool spritesheet_add(const std::string&, const std::string&, int&); void spritesheet_remove(int); + std::vector spritesheet_labels_get(); std::set spritesheets_unused(); - std::vector spritesheet_names_get(); + bool spritesheets_deserialize(const std::string&, const std::string&, types::merge::Type type, std::string*); - int layer_add(); - Reference layer_add(Reference = REFERENCE_DEFAULT, std::string = {}, int = 0, - types::locale::Type = types::locale::GLOBAL); - std::set layers_unused(Reference = REFERENCE_DEFAULT); + void layer_add(int&); + std::set layers_unused(Reference = {}); + bool layers_deserialize(const std::string&, types::merge::Type, std::string*); - Reference null_add(Reference = REFERENCE_DEFAULT, std::string = {}, types::locale::Type = types::locale::GLOBAL); - std::set nulls_unused(Reference = REFERENCE_DEFAULT); - - bool sound_add(const std::string& directory, const std::string& path, int& id); - std::vector sound_names_get(); - std::set sounds_unused(); + void null_add(int&); + std::set nulls_unused(Reference = {}); + bool nulls_deserialize(const std::string&, types::merge::Type, std::string*); void event_add(int&); - std::set events_unused(Reference = REFERENCE_DEFAULT); - std::vector event_names_get(); - void bake(Reference, int = 1, bool = true, bool = true); - void generate_from_grid(Reference, glm::ivec2, glm::ivec2, glm::ivec2, int, int, int); + std::vector event_labels_get(); + std::set events_unused(Reference = {}); + bool events_deserialize(const std::string&, types::merge::Type, std::string*); + + bool sound_add(const std::string& directory, const std::string& path, int& id); + std::vector sound_labels_get(); + std::set sounds_unused(); + bool sounds_deserialize(const std::string&, const std::string&, types::merge::Type, std::string*); + + Animation* animation_get(Reference); + std::vector animation_labels_get(); + int animations_merge(int, std::set&, types::merge::Type = types::merge::APPEND, bool = true); + bool animations_deserialize(const std::string&, int, std::set&, std::string* = nullptr); + + Item* item_get(Reference); + Reference layer_animation_add(Reference = {}, std::string = {}, int = 0, + types::locale::Type = types::locale::GLOBAL); + Reference null_animation_add(Reference = {}, std::string = {}, types::locale::Type = types::locale::GLOBAL); + + Frame* frame_get(Reference); }; } diff --git a/src/anm2/anm2_animations.cpp b/src/anm2/anm2_animations.cpp new file mode 100644 index 0000000..c4a5107 --- /dev/null +++ b/src/anm2/anm2_animations.cpp @@ -0,0 +1,137 @@ +#include "anm2.h" + +#include "vector_.h" + +using namespace anm2ed::util; +using namespace anm2ed::types; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Animation* Anm2::animation_get(Reference reference) + { + return vector::find(animations.items, reference.animationIndex); + } + + std::vector Anm2::animation_labels_get() + { + std::vector labels{}; + labels.emplace_back("None"); + for (auto& animation : animations.items) + labels.emplace_back(animation.name); + return labels; + } + + bool Anm2::animations_deserialize(const std::string& string, int start, std::set& indices, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + if (!document.FirstChildElement("Animation")) + { + if (errorString) *errorString = "No valid animation(s)."; + return false; + } + + int count{}; + for (auto element = document.FirstChildElement("Animation"); element; + element = element->NextSiblingElement("Animation")) + { + auto index = start + count; + animations.items.insert(animations.items.begin() + start + count, Animation(element)); + indices.insert(index); + count++; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + + int Anm2::animations_merge(int target, std::set& sources, merge::Type type, bool isDeleteAfter) + { + auto& items = animations.items; + auto& animation = animations.items.at(target); + + if (!animation.name.ends_with(MERGED_STRING)) animation.name = animation.name + " " + MERGED_STRING; + + auto merge_item = [&](Item& destination, Item& source) + { + switch (type) + { + case merge::APPEND: + destination.frames.insert(destination.frames.end(), source.frames.begin(), source.frames.end()); + break; + case merge::PREPEND: + destination.frames.insert(destination.frames.begin(), source.frames.begin(), source.frames.end()); + break; + case merge::REPLACE: + if (destination.frames.size() < source.frames.size()) destination.frames.resize(source.frames.size()); + for (int i = 0; i < (int)source.frames.size(); i++) + destination.frames[i] = source.frames[i]; + break; + case merge::IGNORE: + default: + break; + } + }; + + for (auto& i : sources) + { + if (i == target) continue; + if (i < 0 || i >= (int)items.size()) continue; + + auto& source = items.at(i); + + merge_item(animation.rootAnimation, source.rootAnimation); + + for (auto& [id, layerAnimation] : source.layerAnimations) + { + if (!animation.layerAnimations.contains(id)) + { + animation.layerAnimations[id] = layerAnimation; + animation.layerOrder.emplace_back(id); + } + merge_item(animation.layerAnimations[id], layerAnimation); + } + + for (auto& [id, nullAnimation] : source.nullAnimations) + { + if (!animation.nullAnimations.contains(id)) animation.nullAnimations[id] = nullAnimation; + merge_item(animation.nullAnimations[id], nullAnimation); + } + + merge_item(animation.triggers, source.triggers); + } + + if (isDeleteAfter) + { + for (auto& source : std::ranges::reverse_view(sources)) + { + if (source == target) continue; + items.erase(items.begin() + source); + } + } + + int finalIndex = target; + + if (isDeleteAfter) + { + int numDeletedBefore = 0; + for (auto& idx : sources) + { + if (idx == target) continue; + if (idx >= 0 && idx < target) ++numDeletedBefore; + } + finalIndex -= numDeletedBefore; + } + + return finalIndex; + } + +} \ No newline at end of file diff --git a/src/anm2/anm2_events.cpp b/src/anm2/anm2_events.cpp new file mode 100644 index 0000000..903e6d8 --- /dev/null +++ b/src/anm2/anm2_events.cpp @@ -0,0 +1,75 @@ +#include "anm2.h" + +#include + +#include "map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + void Anm2::event_add(int& id) + { + id = map::next_id_get(content.events); + content.events[id] = Event(); + } + + std::vector Anm2::event_labels_get() + { + std::vector labels{}; + labels.emplace_back("None"); + for (auto& event : content.events | std::views::values) + labels.emplace_back(event.name); + return labels; + } + + std::set Anm2::events_unused(Reference reference) + { + std::set used{}; + + if (auto animation = animation_get(reference); animation) + for (auto& frame : animation->triggers.frames) + used.insert(frame.eventID); + else + for (auto& animation : animations.items) + for (auto& frame : animation.triggers.frames) + used.insert(frame.eventID); + + std::set unused{}; + for (auto& id : content.events | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + bool Anm2::events_deserialize(const std::string& string, merge::Type type, std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Event")) + { + if (errorString) *errorString = "No valid event(s)."; + return false; + } + + for (auto element = document.FirstChildElement("Event"); element; element = element->NextSiblingElement("Event")) + { + auto event = Event(element, id); + if (type == merge::APPEND) id = map::next_id_get(content.events); + content.events[id] = event; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } +} diff --git a/src/anm2/anm2_items.cpp b/src/anm2/anm2_items.cpp new file mode 100644 index 0000000..b74df0e --- /dev/null +++ b/src/anm2/anm2_items.cpp @@ -0,0 +1,83 @@ +#include "anm2.h" + +#include "map_.h" +#include "types.h" +#include "unordered_map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; + +namespace anm2ed::anm2 +{ + Item* Anm2::item_get(Reference reference) + { + if (Animation* animation = animation_get(reference)) + { + switch (reference.itemType) + { + case ROOT: + return &animation->rootAnimation; + case LAYER: + return unordered_map::find(animation->layerAnimations, reference.itemID); + case NULL_: + return map::find(animation->nullAnimations, reference.itemID); + case TRIGGER: + return &animation->triggers; + default: + return nullptr; + } + } + return nullptr; + } + + Reference Anm2::layer_animation_add(Reference reference, std::string name, int spritesheetID, locale::Type locale) + { + auto id = reference.itemID == -1 ? map::next_id_get(content.layers) : reference.itemID; + auto& layer = content.layers[id]; + + layer.name = !name.empty() ? name : layer.name; + layer.spritesheetID = content.spritesheets.contains(spritesheetID) ? spritesheetID : 0; + + auto add = [&](Animation* animation, int id) + { + animation->layerAnimations[id] = Item(); + animation->layerOrder.push_back(id); + }; + + if (locale == locale::GLOBAL) + { + for (auto& animation : animations.items) + if (!animation.layerAnimations.contains(id)) add(&animation, id); + } + else if (locale == locale::LOCAL) + { + if (auto animation = animation_get(reference)) + if (!animation->layerAnimations.contains(id)) add(animation, id); + } + + return {reference.animationIndex, LAYER, id}; + } + + Reference Anm2::null_animation_add(Reference reference, std::string name, locale::Type locale) + { + auto id = reference.itemID == -1 ? map::next_id_get(content.nulls) : reference.itemID; + auto& null = content.nulls[id]; + + null.name = !name.empty() ? name : null.name; + + auto add = [&](Animation* animation, int id) { animation->nullAnimations[id] = Item(); }; + + if (locale == locale::GLOBAL) + { + for (auto& animation : animations.items) + if (!animation.nullAnimations.contains(id)) add(&animation, id); + } + else if (locale == locale::LOCAL) + { + if (auto animation = animation_get(reference)) + if (!animation->nullAnimations.contains(id)) add(animation, id); + } + + return {reference.animationIndex, LAYER, id}; + } +} \ No newline at end of file diff --git a/src/anm2/anm2_layers.cpp b/src/anm2/anm2_layers.cpp new file mode 100644 index 0000000..9a48ac1 --- /dev/null +++ b/src/anm2/anm2_layers.cpp @@ -0,0 +1,66 @@ +#include "anm2.h" + +#include + +#include "map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + void Anm2::layer_add(int& id) + { + id = map::next_id_get(content.layers); + content.layers[id] = Layer(); + } + + std::set Anm2::layers_unused(Reference reference) + { + std::set used{}; + std::set unused{}; + + if (auto animation = animation_get(reference); animation) + for (auto& id : animation->layerAnimations | std::views::keys) + used.insert(id); + else + for (auto& animation : animations.items) + for (auto& id : animation.layerAnimations | std::views::keys) + used.insert(id); + + for (auto& id : content.layers | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + bool Anm2::layers_deserialize(const std::string& string, merge::Type type, std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Layer")) + { + if (errorString) *errorString = "No valid layer(s)."; + return false; + } + + for (auto element = document.FirstChildElement("Layer"); element; element = element->NextSiblingElement("Layer")) + { + auto layer = Layer(element, id); + if (type == merge::APPEND) id = map::next_id_get(content.layers); + content.layers[id] = layer; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } +} diff --git a/src/anm2/anm2_nulls.cpp b/src/anm2/anm2_nulls.cpp new file mode 100644 index 0000000..49ed6ce --- /dev/null +++ b/src/anm2/anm2_nulls.cpp @@ -0,0 +1,66 @@ +#include "anm2.h" + +#include + +#include "map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + void Anm2::null_add(int& id) + { + id = map::next_id_get(content.nulls); + content.nulls[id] = Null(); + } + + std::set Anm2::nulls_unused(Reference reference) + { + std::set used{}; + std::set unused{}; + + if (auto animation = animation_get(reference); animation) + for (auto& id : animation->nullAnimations | std::views::keys) + used.insert(id); + else + for (auto& animation : animations.items) + for (auto& id : animation.nullAnimations | std::views::keys) + used.insert(id); + + for (auto& id : content.nulls | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + bool Anm2::nulls_deserialize(const std::string& string, merge::Type type, std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Null")) + { + if (errorString) *errorString = "No valid null(s)."; + return false; + } + + for (auto element = document.FirstChildElement("Null"); element; element = element->NextSiblingElement("Null")) + { + auto null = Null(element, id); + if (type == merge::APPEND) id = map::next_id_get(content.nulls); + content.nulls[id] = null; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } +} diff --git a/src/anm2/anm2_sounds.cpp b/src/anm2/anm2_sounds.cpp new file mode 100644 index 0000000..299d64c --- /dev/null +++ b/src/anm2/anm2_sounds.cpp @@ -0,0 +1,75 @@ +#include "anm2.h" + +#include + +#include "filesystem_.h" +#include "map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + bool Anm2::sound_add(const std::string& directory, const std::string& path, int& id) + { + id = map::next_id_get(content.sounds); + content.sounds[id] = Sound(directory, path); + return true; + } + + std::vector Anm2::sound_labels_get() + { + std::vector labels{}; + labels.emplace_back("None"); + for (auto& [id, sound] : content.sounds) + labels.emplace_back(sound.path.string()); + return labels; + } + + std::set Anm2::sounds_unused() + { + std::set used; + for (auto& animation : animations.items) + for (auto& trigger : animation.triggers.frames) + if (content.sounds.contains(trigger.soundID)) used.insert(trigger.soundID); + + std::set unused; + for (auto& id : content.sounds | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + bool Anm2::sounds_deserialize(const std::string& string, const std::string& directory, merge::Type type, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Sound")) + { + if (errorString) *errorString = "No valid sound(s)."; + return false; + } + + filesystem::WorkingDirectory workingDirectory(directory); + + for (auto element = document.FirstChildElement("Sound"); element; element = element->NextSiblingElement("Sound")) + { + auto sound = Sound(element, id); + if (type == merge::APPEND) id = map::next_id_get(content.sounds); + content.sounds[id] = std::move(sound); + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } +} diff --git a/src/anm2/anm2_spritesheets.cpp b/src/anm2/anm2_spritesheets.cpp new file mode 100644 index 0000000..9849db2 --- /dev/null +++ b/src/anm2/anm2_spritesheets.cpp @@ -0,0 +1,87 @@ +#include "anm2.h" + +#include + +#include "filesystem_.h" +#include "map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Spritesheet* Anm2::spritesheet_get(int id) + { + return map::find(content.spritesheets, id); + } + + void Anm2::spritesheet_remove(int id) + { + content.spritesheets.erase(id); + } + + bool Anm2::spritesheet_add(const std::string& directory, const std::string& path, int& id) + { + Spritesheet spritesheet(directory, path); + if (!spritesheet.is_valid()) return false; + id = map::next_id_get(content.spritesheets); + content.spritesheets[id] = std::move(spritesheet); + return true; + } + + std::set Anm2::spritesheets_unused() + { + std::set used{}; + for (auto& layer : content.layers | std::views::values) + if (layer.is_spritesheet_valid()) used.insert(layer.spritesheetID); + + std::set unused{}; + for (auto& id : content.spritesheets | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + std::vector Anm2::spritesheet_labels_get() + { + std::vector labels{}; + labels.emplace_back("None"); + for (auto& [id, spritesheet] : content.spritesheets) + labels.emplace_back(std::format(SPRITESHEET_FORMAT, id, spritesheet.path.c_str())); + return labels; + } + + bool Anm2::spritesheets_deserialize(const std::string& string, const std::string& directory, merge::Type type, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Spritesheet")) + { + if (errorString) *errorString = "No valid spritesheet(s)."; + return false; + } + + filesystem::WorkingDirectory workingDirectory(directory); + + for (auto element = document.FirstChildElement("Spritesheet"); element; + element = element->NextSiblingElement("Spritesheet")) + { + auto spritesheet = Spritesheet(element, id); + if (type == merge::APPEND) id = map::next_id_get(content.spritesheets); + content.spritesheets[id] = std::move(spritesheet); + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } +} diff --git a/src/anm2/content.cpp b/src/anm2/content.cpp index d2ca4f1..ff007ed 100644 --- a/src/anm2/content.cpp +++ b/src/anm2/content.cpp @@ -1,12 +1,5 @@ #include "content.h" -#include - -#include "filesystem_.h" -#include "map_.h" - -using namespace anm2ed::types; -using namespace anm2ed::util; using namespace tinyxml2; namespace anm2ed::anm2 @@ -60,197 +53,4 @@ namespace anm2ed::anm2 parent->InsertEndChild(element); } - std::set Content::spritesheets_unused() - { - std::set used; - for (auto& layer : layers | std::views::values) - if (layer.spritesheetID != -1) used.insert(layer.spritesheetID); - - std::set unused; - for (auto& id : spritesheets | std::views::keys) - if (!used.contains(id)) unused.insert(id); - - return unused; - } - - void Content::layer_add(int& id) - { - id = map::next_id_get(layers); - layers[id] = Layer(); - } - - void Content::null_add(int& id) - { - id = map::next_id_get(nulls); - nulls[id] = Null(); - } - - void Content::event_add(int& id) - { - id = map::next_id_get(events); - events[id] = Event(); - } - - bool Content::spritesheets_deserialize(const std::string& string, const std::string& directory, merge::Type type, - std::string* errorString) - { - XMLDocument document{}; - - if (document.Parse(string.c_str()) == XML_SUCCESS) - { - int id{}; - - if (!document.FirstChildElement("Spritesheet")) - { - if (errorString) *errorString = "No valid spritesheet(s)."; - return false; - } - - filesystem::WorkingDirectory workingDirectory(directory); - - for (auto element = document.FirstChildElement("Spritesheet"); element; - element = element->NextSiblingElement("Spritesheet")) - { - auto spritesheet = Spritesheet(element, id); - - if (type == merge::APPEND) id = map::next_id_get(spritesheets); - - spritesheets[id] = std::move(spritesheet); - } - - return true; - } - else if (errorString) - *errorString = document.ErrorStr(); - - return false; - } - - bool Content::layers_deserialize(const std::string& string, merge::Type type, std::string* errorString) - { - XMLDocument document{}; - - if (document.Parse(string.c_str()) == XML_SUCCESS) - { - int id{}; - - if (!document.FirstChildElement("Layer")) - { - if (errorString) *errorString = "No valid layer(s)."; - return false; - } - - for (auto element = document.FirstChildElement("Layer"); element; element = element->NextSiblingElement("Layer")) - { - auto layer = Layer(element, id); - - if (type == merge::APPEND) id = map::next_id_get(layers); - - layers[id] = layer; - } - - return true; - } - else if (errorString) - *errorString = document.ErrorStr(); - - return false; - } - - bool Content::nulls_deserialize(const std::string& string, merge::Type type, std::string* errorString) - { - XMLDocument document{}; - - if (document.Parse(string.c_str()) == XML_SUCCESS) - { - int id{}; - - if (!document.FirstChildElement("Null")) - { - if (errorString) *errorString = "No valid null(s)."; - return false; - } - - for (auto element = document.FirstChildElement("Null"); element; element = element->NextSiblingElement("Null")) - { - auto layer = Null(element, id); - - if (type == merge::APPEND) id = map::next_id_get(nulls); - - nulls[id] = layer; - } - - return true; - } - else if (errorString) - *errorString = document.ErrorStr(); - - return false; - } - - bool Content::events_deserialize(const std::string& string, merge::Type type, std::string* errorString) - { - XMLDocument document{}; - - if (document.Parse(string.c_str()) == XML_SUCCESS) - { - int id{}; - - if (!document.FirstChildElement("Event")) - { - if (errorString) *errorString = "No valid event(s)."; - return false; - } - - for (auto element = document.FirstChildElement("Event"); element; element = element->NextSiblingElement("Event")) - { - auto layer = Event(element, id); - - if (type == merge::APPEND) id = map::next_id_get(events); - - events[id] = layer; - } - - return true; - } - else if (errorString) - *errorString = document.ErrorStr(); - - return false; - } - - bool Content::sounds_deserialize(const std::string& string, const std::string& directory, merge::Type type, - std::string* errorString) - { - XMLDocument document{}; - - if (document.Parse(string.c_str()) == XML_SUCCESS) - { - int id{}; - - if (!document.FirstChildElement("Sound")) - { - if (errorString) *errorString = "No valid sound(s)."; - return false; - } - - filesystem::WorkingDirectory workingDirectory(directory); - - for (auto element = document.FirstChildElement("Sound"); element; element = element->NextSiblingElement("Sound")) - { - auto sound = Sound(element, id); - - if (type == merge::APPEND) id = map::next_id_get(sounds); - - sounds[id] = std::move(sound); - } - - return true; - } - else if (errorString) - *errorString = document.ErrorStr(); - - return false; - } - -} \ No newline at end of file +} diff --git a/src/anm2/content.h b/src/anm2/content.h index e97650b..330c433 100644 --- a/src/anm2/content.h +++ b/src/anm2/content.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include "event.h" #include "layer.h" @@ -9,8 +8,6 @@ #include "sound.h" #include "spritesheet.h" -#include "types.h" - namespace anm2ed::anm2 { struct Content @@ -25,22 +22,5 @@ namespace anm2ed::anm2 void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); Content(tinyxml2::XMLElement*); - - bool spritesheet_add(const std::string&, const std::string&, int&); - std::set spritesheets_unused(); - void spritesheet_remove(int&); - bool spritesheets_deserialize(const std::string&, const std::string&, types::merge::Type, std::string* = nullptr); - - void layer_add(int&); - bool layers_deserialize(const std::string&, types::merge::Type, std::string* = nullptr); - - void null_add(int&); - bool nulls_deserialize(const std::string&, types::merge::Type, std::string* = nullptr); - - void event_add(int&); - bool events_deserialize(const std::string&, types::merge::Type, std::string* = nullptr); - - void sound_add(int&); - bool sounds_deserialize(const std::string&, const std::string&, types::merge::Type, std::string* = nullptr); }; } \ No newline at end of file diff --git a/src/anm2/event.h b/src/anm2/event.h index 3f23d86..f86d35d 100644 --- a/src/anm2/event.h +++ b/src/anm2/event.h @@ -9,7 +9,7 @@ namespace anm2ed::anm2 { public: std::string name{"New Event"}; - int soundID{}; + int soundID{-1}; Event() = default; Event(tinyxml2::XMLElement*, int&); diff --git a/src/anm2/frame.cpp b/src/anm2/frame.cpp index 0ff462b..5e22172 100644 --- a/src/anm2/frame.cpp +++ b/src/anm2/frame.cpp @@ -123,4 +123,12 @@ namespace anm2ed::anm2 { delay = glm::clamp(++delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); } + + bool Frame::is_visible(Type type) + { + if (type == anm2::TRIGGER) + return isVisible && eventID > -1; + else + return isVisible; + } } \ No newline at end of file diff --git a/src/anm2/frame.h b/src/anm2/frame.h index b5a3f76..0e5648b 100644 --- a/src/anm2/frame.h +++ b/src/anm2/frame.h @@ -55,6 +55,7 @@ namespace anm2ed::anm2 X(delay, int, FRAME_DELAY_MIN) \ X(atFrame, int, -1) \ X(eventID, int, -1) \ + X(soundID, int, -1) \ X(pivot, glm::vec2, {}) \ X(crop, glm::vec2, {}) \ X(position, glm::vec2, {}) \ @@ -77,6 +78,7 @@ namespace anm2ed::anm2 void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, Type); void shorten(); void extend(); + bool is_visible(Type = NONE); }; struct FrameChange diff --git a/src/anm2/item.cpp b/src/anm2/item.cpp index 0b20ca5..d262bf4 100644 --- a/src/anm2/item.cpp +++ b/src/anm2/item.cpp @@ -1,10 +1,12 @@ #include "item.h" #include +#include "vector_.h" #include "xml_.h" using namespace anm2ed::util; using namespace tinyxml2; +using namespace glm; namespace anm2ed::anm2 { @@ -114,7 +116,7 @@ namespace anm2ed::anm2 return frame; } - void Item::frames_change(anm2::FrameChange& change, ChangeType type, int start, int numberFrames) + void Item::frames_change(FrameChange& change, ChangeType type, int start, int numberFrames) { auto useStart = numberFrames > -1 ? start : 0; auto end = numberFrames > -1 ? start + numberFrames : (int)frames.size(); @@ -197,4 +199,54 @@ namespace anm2ed::anm2 return false; } + + void Item::frames_bake(int index, int interval, bool isRoundScale, bool isRoundRotation) + { + if (!vector::in_bounds(frames, index)) return; + + Frame& frame = frames[index]; + if (frame.delay == FRAME_DELAY_MIN) return; + + Frame frameNext = vector::in_bounds(frames, index + 1) ? frames[index + 1] : frame; + + int delay{}; + int i = index; + + while (delay < frame.delay) + { + Frame baked = frame; + float interpolation = (float)delay / frame.delay; + baked.delay = std::min(interval, frame.delay - delay); + baked.isInterpolated = (i == index) ? frame.isInterpolated : false; + baked.rotation = glm::mix(frame.rotation, frameNext.rotation, interpolation); + baked.position = glm::mix(frame.position, frameNext.position, interpolation); + baked.scale = glm::mix(frame.scale, frameNext.scale, interpolation); + baked.colorOffset = glm::mix(frame.colorOffset, frameNext.colorOffset, interpolation); + baked.tint = glm::mix(frame.tint, frameNext.tint, interpolation); + if (isRoundScale) baked.scale = vec2(ivec2(baked.scale)); + if (isRoundRotation) baked.rotation = (int)baked.rotation; + + if (i == index) + frames[i] = baked; + else + frames.insert(frames.begin() + i, baked); + i++; + + delay += baked.delay; + } + } + + void Item::frames_generate_from_grid(ivec2 startPosition, ivec2 size, ivec2 pivot, int columns, int count, int delay) + { + for (int i = 0; i < count; i++) + { + Frame frame{}; + frame.delay = delay; + frame.pivot = pivot; + frame.size = size; + frame.crop = startPosition + ivec2(size.x * (i % columns), size.y * (i / columns)); + + frames.emplace_back(frame); + } + } } \ No newline at end of file diff --git a/src/anm2/item.h b/src/anm2/item.h index cb3b20c..9bf0228 100644 --- a/src/anm2/item.h +++ b/src/anm2/item.h @@ -20,7 +20,9 @@ namespace anm2ed::anm2 std::string to_string(Type, int = -1); int length(Type); Frame frame_generate(float, Type); - void frames_change(anm2::FrameChange&, ChangeType, int, int = 0); + void frames_change(FrameChange&, ChangeType, int, int = 0); bool frames_deserialize(const std::string&, Type, int, std::set&, std::string*); + void frames_bake(int, int, bool, bool); + void frames_generate_from_grid(glm::ivec2, glm::ivec2, glm::ivec2, int, int, int); }; } \ No newline at end of file diff --git a/src/anm2/layer.cpp b/src/anm2/layer.cpp index 4ca3106..5dbe7ba 100644 --- a/src/anm2/layer.cpp +++ b/src/anm2/layer.cpp @@ -36,4 +36,8 @@ namespace anm2ed::anm2 return xml::document_to_string(document); } + bool Layer::is_spritesheet_valid() + { + return spritesheetID > -1; + } } \ No newline at end of file diff --git a/src/anm2/layer.h b/src/anm2/layer.h index 715fe1b..0ebc1fc 100644 --- a/src/anm2/layer.h +++ b/src/anm2/layer.h @@ -6,6 +6,7 @@ namespace anm2ed::anm2 { constexpr auto LAYER_FORMAT = "#{} {} (Spritesheet: #{})"; + constexpr auto LAYER_NO_SPRITESHEET_FORMAT = "#{} {} (No Spritesheet)"; class Layer { @@ -18,5 +19,6 @@ namespace anm2ed::anm2 tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, int); void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); std::string to_string(int); + bool is_spritesheet_valid(); }; } \ No newline at end of file diff --git a/src/anm2/sound.cpp b/src/anm2/sound.cpp index eca9655..d6f9b8a 100644 --- a/src/anm2/sound.cpp +++ b/src/anm2/sound.cpp @@ -1,7 +1,6 @@ #include "sound.h" #include "filesystem_.h" -#include "string_.h" #include "xml_.h" using namespace anm2ed::resource; @@ -28,8 +27,8 @@ namespace anm2ed::anm2 Sound::Sound(const std::string& directory, const std::string& path) { filesystem::WorkingDirectory workingDirectory(directory); - this->path = !path.empty() ? std::filesystem::relative(path).string() : this->path.string(); - this->path = string::backslash_replace_to_lower(this->path); + this->path = !path.empty() ? std::filesystem::relative(path) : this->path; + this->path = filesystem::path_lower_case_backslash_handle(this->path); audio = Audio(this->path.c_str()); } @@ -38,8 +37,8 @@ namespace anm2ed::anm2 if (!element) return; element->QueryIntAttribute("Id", &id); xml::query_path_attribute(element, "Path", &path); - string::backslash_replace_to_lower(this->path); - audio = Audio(this->path.c_str()); + path = filesystem::path_lower_case_backslash_handle(path); + audio = Audio(path.c_str()); } XMLElement* Sound::to_element(XMLDocument& document, int id) @@ -56,4 +55,19 @@ namespace anm2ed::anm2 document.InsertEndChild(to_element(document, id)); return xml::document_to_string(document); } + + void Sound::reload(const std::string& directory) + { + *this = Sound(directory, this->path); + } + + bool Sound::is_valid() + { + return audio.is_valid(); + } + + void Sound::play() + { + audio.play(); + } } \ No newline at end of file diff --git a/src/anm2/sound.h b/src/anm2/sound.h index fc1e43f..951af67 100644 --- a/src/anm2/sound.h +++ b/src/anm2/sound.h @@ -7,8 +7,7 @@ namespace anm2ed::anm2 { - constexpr auto SOUND_FORMAT = "#{} {}"; - constexpr auto SOUND_FORMAT_C = "#%d %s"; + constexpr auto SOUND_FORMAT = "{}"; class Sound { @@ -26,5 +25,8 @@ namespace anm2ed::anm2 Sound(const std::string&, const std::string&); tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, int); std::string to_string(int); + void reload(const std::string&); + bool is_valid(); + void play(); }; } \ No newline at end of file diff --git a/src/anm2/spritesheet.cpp b/src/anm2/spritesheet.cpp index 309c40e..7f0ce56 100644 --- a/src/anm2/spritesheet.cpp +++ b/src/anm2/spritesheet.cpp @@ -1,7 +1,6 @@ #include "spritesheet.h" #include "filesystem_.h" -#include "string_.h" #include "xml_.h" using namespace anm2ed::resource; @@ -18,15 +17,15 @@ namespace anm2ed::anm2 // Spritesheet paths from Isaac Rebirth are made with the assumption that paths are case-insensitive // However when using the resource dumper, the spritesheet paths are all lowercase (on Linux anyway) // This will handle this case and make the paths OS-agnostic - this->path = string::backslash_replace_to_lower(this->path); + path = filesystem::path_lower_case_backslash_handle(path); texture = Texture(path); } Spritesheet::Spritesheet(const std::string& directory, const std::string& path) { filesystem::WorkingDirectory workingDirectory(directory); - this->path = !path.empty() ? std::filesystem::relative(path).string() : this->path.string(); - this->path = string::backslash_replace_to_lower(this->path); + this->path = !path.empty() ? std::filesystem::relative(path) : this->path; + this->path = filesystem::path_lower_case_backslash_handle(this->path); texture = Texture(this->path); } diff --git a/src/canvas.h b/src/canvas.h index b1955b8..8865d5a 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -12,7 +12,7 @@ namespace anm2ed::canvas constexpr auto PIVOT_SIZE = glm::vec2(8, 8); constexpr auto ZOOM_MIN = 1.0f; constexpr auto ZOOM_MAX = 2000.0f; - constexpr auto POSITION_FORMAT = "Position: ({:8} {:8})"; + constexpr auto POSITION_FORMAT = "Position: ({:8}, {:8})"; constexpr auto DASH_LENGTH = 4.0f; constexpr auto DASH_GAP = 1.0f; @@ -20,6 +20,11 @@ namespace anm2ed::canvas constexpr auto STEP = 1.0f; constexpr auto STEP_FAST = 5.0f; + + constexpr auto GRID_SIZE_MIN = 1; + constexpr auto GRID_SIZE_MAX = 10000; + constexpr auto GRID_OFFSET_MIN = 0; + constexpr auto GRID_OFFSET_MAX = 10000; } namespace anm2ed diff --git a/src/document.cpp b/src/document.cpp index a17f208..c602acb 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1,13 +1,10 @@ #include "document.h" -#include -#include +#include #include "filesystem_.h" #include "log.h" -#include "map_.h" #include "toast.h" -#include "vector_.h" using namespace anm2ed::anm2; using namespace anm2ed::imgui; @@ -35,6 +32,43 @@ namespace anm2ed change(Document::ALL); } + Document::Document(Document&& other) noexcept + : path(std::move(other.path)), snapshots(std::move(other.snapshots)), current(snapshots.current), + anm2(current.anm2), reference(current.reference), playback(current.playback), animation(current.animation), + merge(current.merge), event(current.event), layer(current.layer), null(current.null), sound(current.sound), + spritesheet(current.spritesheet), message(current.message), previewZoom(other.previewZoom), + previewPan(other.previewPan), editorPan(other.editorPan), editorZoom(other.editorZoom), + overlayIndex(other.overlayIndex), hoveredFrame(other.hoveredFrame), hash(other.hash), saveHash(other.saveHash), + autosaveHash(other.autosaveHash), lastAutosaveTime(other.lastAutosaveTime), isOpen(other.isOpen), + isForceDirty(other.isForceDirty), isAnimationPreviewSet(other.isAnimationPreviewSet), + isSpritesheetEditorSet(other.isSpritesheetEditorSet) + { + } + + Document& Document::operator=(Document&& other) noexcept + { + if (this != &other) + { + path = std::move(other.path); + snapshots = std::move(other.snapshots); + previewZoom = other.previewZoom; + previewPan = other.previewPan; + editorPan = other.editorPan; + editorZoom = other.editorZoom; + overlayIndex = other.overlayIndex; + hoveredFrame = other.hoveredFrame; + hash = other.hash; + saveHash = other.saveHash; + autosaveHash = other.autosaveHash; + lastAutosaveTime = other.lastAutosaveTime; + isOpen = other.isOpen; + isForceDirty = other.isForceDirty; + isAnimationPreviewSet = other.isAnimationPreviewSet; + isSpritesheetEditorSet = other.isSpritesheetEditorSet; + } + return *this; + } + bool Document::save(const std::string& path, std::string* errorString) { this->path = !path.empty() ? path : this->path.string(); @@ -51,18 +85,35 @@ namespace anm2ed return false; } - bool Document::autosave(const std::string& path, std::string* errorString) + std::filesystem::path Document::autosave_path_get() { - if (anm2.serialize(path, errorString)) + return directory_get() / std::string("." + filename_get().string() + ".autosave"); + } + + std::filesystem::path Document::path_from_autosave_get(std::filesystem::path& path) + { + auto fileName = path.filename().string(); + if (!fileName.empty() && fileName.front() == '.') fileName.erase(fileName.begin()); + + auto restorePath = path.parent_path() / fileName; + restorePath.replace_extension(""); + + return path; + } + + bool Document::autosave(std::string* errorString) + { + auto autosavePath = autosave_path_get(); + if (anm2.serialize(autosavePath, errorString)) { autosaveHash = hash; lastAutosaveTime = 0.0f; toasts.info("Autosaving..."); - logger.info(std::format("Autosaved document to: {}", path)); + logger.info(std::format("Autosaved document to: {}", autosavePath.string())); return true; } else if (errorString) - toasts.warning(std::format("Could not autosave document to: {} ({})", path, *errorString)); + toasts.warning(std::format("Could not autosave document to: {} ({})", autosavePath.string(), *errorString)); return false; } @@ -84,41 +135,30 @@ namespace anm2ed { hash_set(); - auto layers_set = [&]() { unusedLayerIDs = anm2.layers_unused(); }; - auto nulls_set = [&]() { unusedNullIDs = anm2.nulls_unused(); }; + auto layers_set = [&]() { layer.unused = anm2.layers_unused(); }; + auto nulls_set = [&]() { null.unused = anm2.nulls_unused(); }; auto events_set = [&]() { - unusedEventIDs = anm2.events_unused(); - eventNames = anm2.event_names_get(); - for (auto& name : eventNames) - eventNamesCStr.push_back(name.c_str()); + event.unused = anm2.events_unused(); + event.labels_set(anm2.event_labels_get()); }; - auto animations_set = [&]() - { - animationNames = anm2.animation_names_get(); - animationNamesCStr.clear(); - animationNames.insert(animationNames.begin(), "None"); - for (auto& name : animationNames) - animationNamesCStr.push_back(name.c_str()); - }; + auto animations_set = [&]() { animation.labels_set(anm2.animation_labels_get()); }; auto spritesheets_set = [&]() { - unusedSpritesheetIDs = anm2.spritesheets_unused(); - spritesheetNames = anm2.spritesheet_names_get(); - spritesheetNamesCStr.clear(); - for (auto& name : spritesheetNames) - spritesheetNamesCStr.push_back(name.c_str()); + spritesheet.unused = anm2.spritesheets_unused(); + spritesheet.labels_set(anm2.spritesheet_labels_get()); }; auto sounds_set = [&]() { - unusedSoundIDs = anm2.sounds_unused(); - soundNames = anm2.sound_names_get(); - soundNamesCStr.clear(); - for (auto& name : soundNames) - soundNamesCStr.push_back(name.c_str()); + sound.unused = anm2.sounds_unused(); + sound.labels_set(anm2.sound_labels_get()); + + for (auto& animation : anm2.animations.items) + for (auto& trigger : animation.triggers.frames) + if (!anm2.content.sounds.contains(trigger.soundID)) trigger.soundID = -1; }; switch (type) @@ -132,23 +172,21 @@ namespace anm2ed case EVENTS: events_set(); break; - case ANIMATIONS: - animations_set(); - break; case SPRITESHEETS: spritesheets_set(); break; case SOUNDS: sounds_set(); break; - case ITEMS: + case ANIMATIONS: + animations_set(); break; case ALL: layers_set(); nulls_set(); events_set(); - animations_set(); spritesheets_set(); + animations_set(); sounds_set(); break; default: @@ -186,569 +224,56 @@ namespace anm2ed return anm2.frame_get(reference); } - void Document::frames_bake(int interval, bool isRoundScale, bool isRoundRotation) - { - snapshot("Bake Frames"); - anm2.bake(reference, interval, isRoundScale, isRoundRotation); - change(Document::FRAMES); - } - - void Document::frames_add(anm2::Item* item) - { - if (!item) return; - - auto frame = frame_get(); - - if (frame) - { - item->frames.insert(item->frames.begin() + reference.frameIndex, *frame); - reference.frameIndex++; - } - else if (!item->frames.empty()) - { - auto frame = item->frames.back(); - item->frames.emplace_back(frame); - reference.frameIndex = item->frames.size() - 1; - } - } - - void Document::frames_delete(anm2::Item* item) - { - if (!item) return; - - snapshot("Delete Frames"); - item->frames.erase(item->frames.begin() + reference.frameIndex); - reference.frameIndex = glm::max(-1, --reference.frameIndex); - change(Document::FRAMES); - } - - void Document::frame_crop_set(anm2::Frame* frame, vec2 crop) - { - if (!frame) return; - snapshot("Frame Crop"); - frame->crop = crop; - change(Document::FRAMES); - } - - void Document::frame_size_set(anm2::Frame* frame, vec2 size) - { - if (!frame) return; - snapshot("Frame Size"); - frame->size = size; - change(Document::FRAMES); - } - - void Document::frame_position_set(anm2::Frame* frame, vec2 position) - { - if (!frame) return; - snapshot("Frame Position"); - frame->position = position; - change(Document::FRAMES); - } - - void Document::frame_pivot_set(anm2::Frame* frame, vec2 pivot) - { - if (!frame) return; - snapshot("Frame Pivot"); - frame->pivot = pivot; - change(Document::FRAMES); - } - - void Document::frame_scale_set(anm2::Frame* frame, vec2 scale) - { - if (!frame) return; - snapshot("Frame Scale"); - frame->scale = scale; - change(Document::FRAMES); - } - - void Document::frame_rotation_set(anm2::Frame* frame, float rotation) - { - if (!frame) return; - snapshot("Frame Rotation"); - frame->rotation = rotation; - change(Document::FRAMES); - } - - void Document::frame_delay_set(anm2::Frame* frame, int delay) - { - if (!frame) return; - snapshot("Frame Delay"); - frame->delay = delay; - change(Document::FRAMES); - } - - void Document::frame_tint_set(anm2::Frame* frame, vec4 tint) - { - if (!frame) return; - snapshot("Frame Tint"); - frame->tint = tint; - change(Document::FRAMES); - } - - void Document::frame_color_offset_set(anm2::Frame* frame, vec3 colorOffset) - { - if (!frame) return; - snapshot("Frame Color Offset"); - frame->colorOffset = colorOffset; - change(Document::FRAMES); - } - - void Document::frame_is_visible_set(anm2::Frame* frame, bool isVisible) - { - if (!frame) return; - snapshot("Frame Visibility"); - frame->isVisible = isVisible; - change(Document::FRAMES); - } - - void Document::frame_is_interpolated_set(anm2::Frame* frame, bool isInterpolated) - { - if (!frame) return; - snapshot("Frame Interpolation"); - frame->isInterpolated = isInterpolated; - change(Document::FRAMES); - } - - void Document::frame_flip_x(anm2::Frame* frame) - { - if (!frame) return; - snapshot("Frame Flip X"); - frame->scale.x = -frame->scale.x; - change(Document::FRAMES); - } - - void Document::frame_flip_y(anm2::Frame* frame) - { - if (!frame) return; - snapshot("Frame Flip Y"); - frame->scale.y = -frame->scale.y; - change(Document::FRAMES); - } - - void Document::frame_shorten() - { - auto frame = frame_get(); - if (!frame) return; - snapshot("Shorten Frame"); - frame->shorten(); - change(Document::FRAMES); - } - - void Document::frame_extend() - { - auto frame = frame_get(); - if (!frame) return; - snapshot("Extend Frame"); - frame->extend(); - change(Document::FRAMES); - } - - void Document::frames_change(anm2::FrameChange& frameChange, anm2::ChangeType type, bool isFromSelectedFrame, - int numberFrames) - { - auto item = item_get(); - if (!item) return; - snapshot("Change All Frame Properties"); - item->frames_change(frameChange, type, isFromSelectedFrame && frame_get() ? reference.frameIndex : 0, - isFromSelectedFrame ? numberFrames : -1); - change(Document::FRAMES); - } - - void Document::frames_deserialize(const std::string& string) - { - if (auto item = item_get()) - { - snapshot("Paste Frame(s)"); - std::set indices{}; - std::string errorString{}; - auto start = reference.frameIndex + 1; - if (item->frames_deserialize(string, reference.itemType, start, indices, &errorString)) - change(Document::FRAMES); - else - toasts.error(std::format("Failed to deserialize frame(s): {}", errorString)); - } - else - toasts.error(std::format("Failed to deserialize frame(s): select an item first!")); - } - anm2::Item* Document::item_get() { return anm2.item_get(reference); } - anm2::Spritesheet* Document::spritesheet_get() - { - return anm2.spritesheet_get(referenceSpritesheet); - } - - void Document::spritesheet_add(const std::string& path) - { - int id{}; - snapshot("Add Spritesheet"); - if (anm2.spritesheet_add(directory_get(), path, id)) - { - spritesheetMultiSelect = {id}; - toasts.info(std::format("Initialized spritesheet #{}: {}", id, path)); - change(Document::SPRITESHEETS); - } - else - toasts.error(std::format("Failed to initialize spritesheet: {}", path)); - } - - void Document::spritesheets_deserialize(const std::string& string, merge::Type type) - { - snapshot("Paste Spritesheet(s)"); - std::string errorString{}; - if (anm2.content.spritesheets_deserialize(string, directory_get(), type, &errorString)) - change(Document::SPRITESHEETS); - else - toasts.error(std::format("Failed to deserialize spritesheet(s): {}", errorString)); - } - - void Document::layers_deserialize(const std::string& string, merge::Type type) - { - snapshot("Paste Layer(s)"); - std::string errorString{}; - if (anm2.content.layers_deserialize(string, type, &errorString)) - change(Document::NULLS); - else - toasts.error(std::format("Failed to deserialize layer(s): {}", errorString)); - } - - void Document::layer_set(anm2::Layer& layer) - { - if (referenceLayer > -1) - { - snapshot("Set Layer"); - anm2.content.layers[referenceLayer] = layer; - layersMultiSelect = {referenceLayer}; - } - else - { - snapshot("Add Layer"); - auto id = map::next_id_get(anm2.content.layers); - anm2.content.layers[id] = layer; - layersMultiSelect = {id}; - } - change(Document::LAYERS); - } - - void Document::layers_remove_unused() - { - snapshot("Remove Unused Layers"); - for (auto& id : unusedLayerIDs) - anm2.content.layers.erase(id); - change(Document::LAYERS); - unusedLayerIDs.clear(); - } - - void Document::null_set(anm2::Null& null) - { - if (referenceNull > -1) - { - snapshot("Set Null"); - anm2.content.nulls[referenceNull] = null; - nullMultiSelect = {referenceNull}; - } - else - { - snapshot("Add Null"); - auto id = map::next_id_get(anm2.content.nulls); - anm2.content.nulls[id] = null; - nullMultiSelect = {id}; - } - change(Document::NULLS); - } - - void Document::null_rect_toggle(anm2::Null& null) - { - snapshot("Null Rect"); - null.isShowRect = !null.isShowRect; - change(Document::NULLS); - } - - void Document::nulls_remove_unused() - { - snapshot("Remove Unused Nulls"); - for (auto& id : unusedNullIDs) - anm2.content.nulls.erase(id); - change(Document::NULLS); - unusedNullIDs.clear(); - } - - void Document::nulls_deserialize(const std::string& string, merge::Type type) - { - snapshot("Paste Null(s)"); - std::string errorString{}; - if (anm2.content.nulls_deserialize(string, type, &errorString)) - change(Document::NULLS); - else - toasts.error(std::format("Failed to deserialize null(s): {}", errorString)); - } - - void Document::event_set(anm2::Event& event) - { - if (referenceEvent > -1) - { - snapshot("Set Event"); - anm2.content.events[referenceEvent] = event; - eventMultiSelect = {referenceEvent}; - } - else - { - snapshot("Add Event"); - auto id = map::next_id_get(anm2.content.events); - anm2.content.events[id] = event; - eventMultiSelect = {id}; - } - change(Document::EVENTS); - } - - void Document::events_remove_unused() - { - snapshot("Remove Unused Events"); - for (auto& id : unusedEventIDs) - anm2.content.events.erase(id); - change(Document::EVENTS); - unusedEventIDs.clear(); - } - - void Document::events_deserialize(const std::string& string, merge::Type type) - { - snapshot("Paste Event(s)"); - std::string errorString{}; - if (anm2.content.events_deserialize(string, type, &errorString)) - change(Document::EVENTS); - else - toasts.error(std::format("Failed to deserialize event(s): {}", errorString)); - } - - void Document::sound_add(const std::string& path) - { - int id{}; - snapshot("Add Sound"); - if (anm2.sound_add(directory_get(), path, id)) - { - soundMultiSelect = {id}; - toasts.info(std::format("Initialized sound #{}: {}", id, path)); - change(Document::SOUNDS); - } - else - toasts.error(std::format("Failed to initialize sound: {}", path)); - } - - void Document::sounds_remove_unused() - { - snapshot("Remove Unused Sounds"); - for (auto& id : unusedSoundIDs) - anm2.content.sounds.erase(id); - change(Document::LAYERS); - unusedSoundIDs.clear(); - } - - void Document::sounds_deserialize(const std::string& string, merge::Type type) - { - snapshot("Paste Sound(s)"); - std::string errorString{}; - if (anm2.content.sounds_deserialize(string, directory_get(), type, &errorString)) - change(Document::EVENTS); - else - toasts.error(std::format("Failed to deserialize event(s): {}", errorString)); - } - - void Document::item_add(anm2::Type type, int id, std::string& name, locale::Type locale, int spritesheetID) - { - snapshot("Add Item"); - - anm2::Reference addReference; - - if (type == anm2::LAYER) - addReference = - anm2.layer_add({reference.animationIndex, anm2::LAYER, id}, name, spritesheetID, (locale::Type)locale); - else if (type == anm2::NULL_) - addReference = anm2.null_add({reference.animationIndex, anm2::LAYER, id}, name, (locale::Type)locale); - - reference = addReference; - - change(Document::ITEMS); - } - - void Document::item_remove(anm2::Animation* animation) - { - if (!animation) return; - snapshot("Remove Item"); - animation->item_remove(reference.itemType, reference.itemID); - reference = {reference.animationIndex}; - change(Document::ITEMS); - } - - void Document::item_visible_toggle(anm2::Item* item) - { - if (!item) return; - snapshot("Item Visibility"); - item->isVisible = !item->isVisible; - change(Document::ITEMS); - } - anm2::Animation* Document::animation_get() { return anm2.animation_get(reference); } - void Document::animation_set(int index) + anm2::Spritesheet* Document::spritesheet_get() { - snapshot("Select Animation"); - reference = {index}; - change(Document::ITEMS); + return anm2.spritesheet_get(spritesheet.reference); } - void Document::animation_add() + void Document::spritesheet_add(const std::string& path) { - snapshot("Add Animation"); - anm2::Animation animation; - if (anm2::Animation* referenceAnimation = animation_get()) + auto add = [&]() { - for (auto [id, layerAnimation] : referenceAnimation->layerAnimations) - animation.layerAnimations[id] = anm2::Item(); - animation.layerOrder = referenceAnimation->layerOrder; - for (auto [id, nullAnimation] : referenceAnimation->nullAnimations) - animation.nullAnimations[id] = anm2::Item(); - } - animation.rootAnimation.frames.emplace_back(anm2::Frame()); + int id{}; + if (anm2.spritesheet_add(directory_get(), path, id)) + { + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; + this->spritesheet.selection = {id}; + toasts.info(std::format("Initialized spritesheet #{}: {}", id, spritesheet.path.string())); + } + else + toasts.error(std::format("Failed to initialize spritesheet: {}", path)); + }; - auto index = - animationMultiSelect.empty() ? (int)anm2.animations.items.size() - 1 : *animationMultiSelect.rbegin() + 1; - anm2.animations.items.insert(anm2.animations.items.begin() + index, animation); - animationMultiSelect = {index}; - reference = {index}; - change(Document::ANIMATIONS); - } - - void Document::animation_duplicate() - { - snapshot("Duplicate Animation(s)"); - auto duplicated = animationMultiSelect; - auto duplicatedEnd = std::ranges::max(duplicated); - for (auto& id : duplicated) - { - anm2.animations.items.insert(anm2.animations.items.begin() + duplicatedEnd, anm2.animations.items[id]); - animationMultiSelect.insert(++duplicatedEnd); - animationMultiSelect.erase(id); - } - change(Document::ANIMATIONS); - } - - void Document::animations_move(std::vector& indices, int index) - { - snapshot("Move Animation(s)"); - animationMultiSelect = vector::move_indices(anm2.animations.items, indices, index); - change(Document::ANIMATIONS); - } - - void Document::animations_remove() - { - snapshot("Remove Animation(s)"); - - if (!animationMultiSelect.empty()) - { - for (auto& i : animationMultiSelect | std::views::reverse) - anm2.animations.items.erase(anm2.animations.items.begin() + i); - animationMultiSelect.clear(); - } - else if (hoveredAnimation > -1) - { - anm2.animations.items.erase(anm2.animations.items.begin() + hoveredAnimation); - hoveredAnimation = -1; - } - - change(Document::ANIMATIONS); - } - - void Document::animation_default() - { - snapshot("Default Animation"); - anm2.animations.defaultAnimation = anm2.animations.items[*animationMultiSelect.begin()].name; - change(Document::ANIMATIONS); - } - - void Document::animations_deserialize(const std::string& string) - { - snapshot("Paste Animation(s)"); - auto& multiSelect = animationMultiSelect; - auto start = multiSelect.empty() ? anm2.animations.items.size() : *multiSelect.rbegin() + 1; - std::set indices{}; - std::string errorString{}; - if (anm2.animations.animations_deserialize(string, start, indices, &errorString)) - { - multiSelect = indices; - change(Document::ANIMATIONS); - } - else - toasts.error(std::format("Failed to deserialize animation(s): {}", errorString)); - } - - void Document::generate_animation_from_grid(ivec2 startPosition, ivec2 size, ivec2 pivot, int columns, int count, - int delay) - { - snapshot("Generate Animation from Grid"); - - anm2.generate_from_grid(reference, startPosition, size, pivot, columns, count, delay); - - if (auto animation = animation_get()) animation->frameNum = animation->length(); - - change(Document::ALL); - } - - void Document::animations_merge_quick() - { - snapshot("Merge Animation(s)"); - int merged{}; - if (animationMultiSelect.size() > 1) - merged = anm2.animations.merge(*animationMultiSelect.begin(), animationMultiSelect); - else if (animationMultiSelect.size() == 1 && *animationMultiSelect.begin() != (int)anm2.animations.items.size() - 1) - { - auto start = *animationMultiSelect.begin(); - auto next = *animationMultiSelect.begin() + 1; - std::set animationSet{}; - animationSet.insert(start); - animationSet.insert(next); - - merged = anm2.animations.merge(start, animationSet); - } - else - return; - - animationMultiSelect = {merged}; - reference = {merged}; - change(Document::ANIMATIONS); - } - - void Document::animations_merge(merge::Type type, bool isDeleteAnimationsAfter) - { - snapshot("Merge Animations"); - auto merged = anm2.animations.merge(mergeTarget, animationMergeMultiSelect, type, isDeleteAnimationsAfter); - animationMultiSelect = {merged}; - reference = {merged}; - change(Document::ANIMATIONS); + DOCUMENT_EDIT_PTR(this, "Add Spritesheet", Document::SPRITESHEETS, add()); } void Document::snapshot(const std::string& message) { - snapshots.push(anm2, reference, message); + this->message = message; + snapshots.push(current); } void Document::undo() { - snapshots.undo(anm2, reference, message); + snapshots.undo(); toasts.info(std::format("Undo: {}", message)); change(Document::ALL); } void Document::redo() { + snapshots.redo(); toasts.info(std::format("Redo: {}", message)); - snapshots.redo(anm2, reference, message); change(Document::ALL); } @@ -761,4 +286,5 @@ namespace anm2ed { return !snapshots.redoStack.is_empty(); } -} \ No newline at end of file + +} diff --git a/src/document.h b/src/document.h index 35ae5ef..545d153 100644 --- a/src/document.h +++ b/src/document.h @@ -1,18 +1,14 @@ #pragma once #include -#include -#include "anm2/anm2.h" -#include "imgui_.h" -#include "playback.h" #include "snapshots.h" -#include "types.h" #include namespace anm2ed { + class Document { public: @@ -31,58 +27,29 @@ namespace anm2ed }; std::filesystem::path path{}; - anm2::Anm2 anm2{}; - std::string message{}; - Playback playback{}; + Snapshots snapshots{}; + Snapshot& current = snapshots.current; + + anm2::Anm2& anm2 = current.anm2; + anm2::Reference& reference = current.reference; + Playback& playback = current.playback; + Storage& animation = current.animation; + Storage& merge = current.merge; + Storage& event = current.event; + Storage& layer = current.layer; + Storage& null = current.null; + Storage& sound = current.sound; + Storage& spritesheet = current.spritesheet; + std::string& message = current.message; float previewZoom{200}; glm::vec2 previewPan{}; glm::vec2 editorPan{}; float editorZoom{200}; + int overlayIndex{-1}; - int overlayIndex{}; - - anm2::Reference reference{}; - int hoveredAnimation{-1}; - int mergeTarget{-1}; - imgui::MultiSelectStorage animationMultiSelect; - imgui::MultiSelectStorage animationMergeMultiSelect; - std::vector animationNamesCStr{}; - std::vector animationNames{}; - - anm2::Reference hoveredFrame{anm2::REFERENCE_DEFAULT}; - - int referenceSpritesheet{-1}; - int hoveredSpritesheet{-1}; - std::set unusedSpritesheetIDs{}; - std::vector spritesheetNames{}; - std::vector spritesheetNamesCStr{}; - imgui::MultiSelectStorage spritesheetMultiSelect; - - int referenceLayer{-1}; - int hoveredLayer{-1}; - std::set unusedLayerIDs{}; - imgui::MultiSelectStorage layersMultiSelect; - - int referenceNull{-1}; - int hoveredNull{-1}; - std::set unusedNullIDs{}; - imgui::MultiSelectStorage nullMultiSelect; - - int referenceEvent{-1}; - int hoveredEvent{-1}; - std::set unusedEventIDs{}; - imgui::MultiSelectStorage eventMultiSelect; - std::vector eventNamesCStr{}; - std::vector eventNames{}; - - int referenceSound{-1}; - int hoveredSound{-1}; - std::set unusedSoundIDs{}; - imgui::MultiSelectStorage soundMultiSelect; - std::vector soundNamesCStr{}; - std::vector soundNames{}; + anm2::Reference hoveredFrame{}; uint64_t hash{}; uint64_t saveHash{}; @@ -90,10 +57,15 @@ namespace anm2ed double lastAutosaveTime{}; bool isOpen{true}; bool isForceDirty{false}; + bool isAnimationPreviewSet{false}; + bool isSpritesheetEditorSet{false}; Document(const std::string&, bool = false, std::string* = nullptr); + Document(const Document&) = delete; + Document& operator=(const Document&) = delete; + Document(Document&&) noexcept; + Document& operator=(Document&&) noexcept; bool save(const std::string& = {}, std::string* = nullptr); - bool autosave(const std::string&, std::string* = nullptr); void hash_set(); void clean(); void on_change(); @@ -105,83 +77,35 @@ namespace anm2ed bool is_valid(); anm2::Frame* frame_get(); - void frames_add(anm2::Item* item); - void frames_delete(anm2::Item* item); - void frames_bake(int, bool, bool); - void frame_crop_set(anm2::Frame*, glm::vec2); - void frame_size_set(anm2::Frame*, glm::vec2); - void frame_position_set(anm2::Frame*, glm::vec2); - void frame_pivot_set(anm2::Frame*, glm::vec2); - void frame_scale_set(anm2::Frame*, glm::vec2); - void frame_rotation_set(anm2::Frame*, float); - void frame_delay_set(anm2::Frame*, int); - void frame_tint_set(anm2::Frame*, glm::vec4); - void frame_color_offset_set(anm2::Frame*, glm::vec3); - void frame_is_visible_set(anm2::Frame*, bool); - void frame_is_interpolated_set(anm2::Frame*, bool); - void frame_flip_x(anm2::Frame* frame); - void frame_flip_y(anm2::Frame* frame); - void frame_shorten(); - void frame_extend(); - void frames_change(anm2::FrameChange&, anm2::ChangeType, bool, int = -1); - void frames_deserialize(const std::string&); - anm2::Item* item_get(); - void item_add(anm2::Type, int, std::string&, types::locale::Type, int); - void item_remove(anm2::Animation*); - void item_visible_toggle(anm2::Item*); - anm2::Spritesheet* spritesheet_get(); - void spritesheet_add(const std::string&); - void spritesheets_deserialize(const std::string&, types::merge::Type); - - void layer_set(anm2::Layer&); - void layers_remove_unused(); - void layers_deserialize(const std::string&, types::merge::Type); - - void null_set(anm2::Null&); - void null_rect_toggle(anm2::Null&); - void nulls_remove_unused(); - void nulls_deserialize(const std::string&, types::merge::Type); - - void event_set(anm2::Event&); - void events_remove_unused(); - void events_deserialize(const std::string&, types::merge::Type); - - void sound_add(const std::string& path); - void sounds_remove_unused(); - void sounds_deserialize(const std::string& string, types::merge::Type); - - void animation_add(); - void animation_set(int); - void animation_duplicate(); - void animation_default(); - void animations_remove(); - void animations_move(std::vector&, int); - void animations_merge(types::merge::Type, bool); - void animations_merge_quick(); anm2::Animation* animation_get(); - void animations_deserialize(const std::string& string); - void generate_animation_from_grid(glm::ivec2, glm::ivec2, glm::ivec2, int, int, int); + void spritesheet_add(const std::string&); + + bool autosave(std::string* = nullptr); + std::filesystem::path autosave_path_get(); + std::filesystem::path path_from_autosave_get(std::filesystem::path&); void snapshot(const std::string& message); void undo(); void redo(); - bool is_able_to_undo(); bool is_able_to_redo(); }; -#define DOCUMENT_SNAPSHOT(document, message) document.snapshot(message); -#define DOCUMENT_CHANGE(document, changeType) document.change(changeType); - #define DOCUMENT_EDIT(document, message, changeType, body) \ { \ - \ - DOCUMENT_SNAPSHOT(document, message) \ + document.snapshot(message); \ body; \ - DOCUMENT_CHANGE(document, changeType) \ + document.change(changeType); \ + } + +#define DOCUMENT_EDIT_PTR(document, message, changeType, body) \ + { \ + document->snapshot(message); \ + body; \ + document->change(changeType); \ } } diff --git a/src/imgui/documents.h b/src/imgui/documents.h index 0011f8b..7e9c039 100644 --- a/src/imgui/documents.h +++ b/src/imgui/documents.h @@ -1,6 +1,5 @@ #pragma once -#include "imgui.h" #include "manager.h" #include "resources.h" #include "settings.h" diff --git a/src/imgui/imgui_.cpp b/src/imgui/imgui_.cpp index ebcee70..0123551 100644 --- a/src/imgui/imgui_.cpp +++ b/src/imgui/imgui_.cpp @@ -28,17 +28,13 @@ namespace anm2ed::imgui return ImGui::InputText(label, string->data(), string->capacity() + 1, flags, input_text_callback, string); } - bool combo_strings(const std::string& label, int* index, std::vector& strings) + bool combo_negative_one_indexed(const std::string& label, int* index, std::vector& strings) { - std::vector items{}; - for (auto& string : strings) - items.push_back(string.c_str()); - return ImGui::Combo(label.c_str(), index, items.data(), (int)items.size()); - } + *index += 1; + bool isActivated = ImGui::Combo(label.c_str(), index, strings.data(), (int)strings.size()); + *index -= 1; - bool combo_strings(const std::string& label, int* index, std::vector& strings) - { - return ImGui::Combo(label.c_str(), index, strings.data(), (int)strings.size()); + return isActivated; } bool input_int_range(const char* label, int& value, int min, int max, int step, int stepFast, @@ -49,6 +45,21 @@ namespace anm2ed::imgui return isActivated; } + bool input_int2_range(const char* label, ivec2& value, ivec2 min, ivec2 max, ImGuiInputTextFlags flags) + { + auto isActivated = ImGui::InputInt2(label, value_ptr(value), flags); + value = glm::clamp(value, min, max); + return isActivated; + } + + bool input_float_range(const char* label, float& value, float min, float max, float step, float stepFast, + const char* format, ImGuiInputTextFlags flags) + { + auto isActivated = ImGui::InputFloat(label, &value, step, stepFast, format, flags); + value = glm::clamp(value, min, max); + return isActivated; + } + bool selectable_input_text(const std::string& label, const std::string& id, std::string& text, bool isSelected, ImGuiSelectableFlags flags, bool* isRenamed) { @@ -263,7 +274,8 @@ namespace anm2ed::imgui { internal.UserData = this; - auto io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape, this->size(), size); + auto io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect2d, + this->size(), size); internal.ApplyRequests(io); } diff --git a/src/imgui/imgui_.h b/src/imgui/imgui_.h index 0555b4f..4ff685d 100644 --- a/src/imgui/imgui_.h +++ b/src/imgui/imgui_.h @@ -46,108 +46,104 @@ namespace anm2ed::imgui #undef X }; - const std::unordered_map KEY_MAP = {{"A", ImGuiKey_A}, - {"B", ImGuiKey_B}, - {"C", ImGuiKey_C}, - {"D", ImGuiKey_D}, - {"E", ImGuiKey_E}, - {"F", ImGuiKey_F}, - {"G", ImGuiKey_G}, - {"H", ImGuiKey_H}, - {"I", ImGuiKey_I}, - {"J", ImGuiKey_J}, - {"K", ImGuiKey_K}, - {"L", ImGuiKey_L}, - {"M", ImGuiKey_M}, - {"N", ImGuiKey_N}, - {"O", ImGuiKey_O}, - {"P", ImGuiKey_P}, - {"Q", ImGuiKey_Q}, - {"R", ImGuiKey_R}, - {"S", ImGuiKey_S}, - {"T", ImGuiKey_T}, - {"U", ImGuiKey_U}, - {"V", ImGuiKey_V}, - {"W", ImGuiKey_W}, - {"X", ImGuiKey_X}, - {"Y", ImGuiKey_Y}, - {"Z", ImGuiKey_Z}, + const std::unordered_map KEY_MAP = { + {"A", ImGuiKey_A}, + {"B", ImGuiKey_B}, + {"C", ImGuiKey_C}, + {"D", ImGuiKey_D}, + {"E", ImGuiKey_E}, + {"F", ImGuiKey_F}, + {"G", ImGuiKey_G}, + {"H", ImGuiKey_H}, + {"I", ImGuiKey_I}, + {"J", ImGuiKey_J}, + {"K", ImGuiKey_K}, + {"L", ImGuiKey_L}, + {"M", ImGuiKey_M}, + {"N", ImGuiKey_N}, + {"O", ImGuiKey_O}, + {"P", ImGuiKey_P}, + {"Q", ImGuiKey_Q}, + {"R", ImGuiKey_R}, + {"S", ImGuiKey_S}, + {"T", ImGuiKey_T}, + {"U", ImGuiKey_U}, + {"V", ImGuiKey_V}, + {"W", ImGuiKey_W}, + {"X", ImGuiKey_X}, + {"Y", ImGuiKey_Y}, + {"Z", ImGuiKey_Z}, - {"0", ImGuiKey_0}, - {"1", ImGuiKey_1}, - {"2", ImGuiKey_2}, - {"3", ImGuiKey_3}, - {"4", ImGuiKey_4}, - {"5", ImGuiKey_5}, - {"6", ImGuiKey_6}, - {"7", ImGuiKey_7}, - {"8", ImGuiKey_8}, - {"9", ImGuiKey_9}, + {"0", ImGuiKey_0}, + {"1", ImGuiKey_1}, + {"2", ImGuiKey_2}, + {"3", ImGuiKey_3}, + {"4", ImGuiKey_4}, + {"5", ImGuiKey_5}, + {"6", ImGuiKey_6}, + {"7", ImGuiKey_7}, + {"8", ImGuiKey_8}, + {"9", ImGuiKey_9}, - {"Num0", ImGuiKey_Keypad0}, - {"Num1", ImGuiKey_Keypad1}, - {"Num2", ImGuiKey_Keypad2}, - {"Num3", ImGuiKey_Keypad3}, - {"Num4", ImGuiKey_Keypad4}, - {"Num5", ImGuiKey_Keypad5}, - {"Num6", ImGuiKey_Keypad6}, - {"Num7", ImGuiKey_Keypad7}, - {"Num8", ImGuiKey_Keypad8}, - {"Num9", ImGuiKey_Keypad9}, - {"NumAdd", ImGuiKey_KeypadAdd}, - {"NumSubtract", ImGuiKey_KeypadSubtract}, - {"NumMultiply", ImGuiKey_KeypadMultiply}, - {"NumDivide", ImGuiKey_KeypadDivide}, - {"NumEnter", ImGuiKey_KeypadEnter}, - {"NumDecimal", ImGuiKey_KeypadDecimal}, + {"Num0", ImGuiKey_Keypad0}, + {"Num1", ImGuiKey_Keypad1}, + {"Num2", ImGuiKey_Keypad2}, + {"Num3", ImGuiKey_Keypad3}, + {"Num4", ImGuiKey_Keypad4}, + {"Num5", ImGuiKey_Keypad5}, + {"Num6", ImGuiKey_Keypad6}, + {"Num7", ImGuiKey_Keypad7}, + {"Num8", ImGuiKey_Keypad8}, + {"Num9", ImGuiKey_Keypad9}, + {"NumAdd", ImGuiKey_KeypadAdd}, + {"NumSubtract", ImGuiKey_KeypadSubtract}, + {"NumMultiply", ImGuiKey_KeypadMultiply}, + {"NumDivide", ImGuiKey_KeypadDivide}, + {"NumEnter", ImGuiKey_KeypadEnter}, + {"NumDecimal", ImGuiKey_KeypadDecimal}, - {"F1", ImGuiKey_F1}, - {"F2", ImGuiKey_F2}, - {"F3", ImGuiKey_F3}, - {"F4", ImGuiKey_F4}, - {"F5", ImGuiKey_F5}, - {"F6", ImGuiKey_F6}, - {"F7", ImGuiKey_F7}, - {"F8", ImGuiKey_F8}, - {"F9", ImGuiKey_F9}, - {"F10", ImGuiKey_F10}, - {"F11", ImGuiKey_F11}, - {"F12", ImGuiKey_F12}, + {"F1", ImGuiKey_F1}, + {"F2", ImGuiKey_F2}, + {"F3", ImGuiKey_F3}, + {"F4", ImGuiKey_F4}, + {"F5", ImGuiKey_F5}, + {"F6", ImGuiKey_F6}, + {"F7", ImGuiKey_F7}, + {"F8", ImGuiKey_F8}, + {"F9", ImGuiKey_F9}, + {"F10", ImGuiKey_F10}, + {"F11", ImGuiKey_F11}, + {"F12", ImGuiKey_F12}, - {"Up", ImGuiKey_UpArrow}, - {"Down", ImGuiKey_DownArrow}, - {"Left", ImGuiKey_LeftArrow}, - {"Right", ImGuiKey_RightArrow}, + {"Up", ImGuiKey_UpArrow}, + {"Down", ImGuiKey_DownArrow}, + {"Left", ImGuiKey_LeftArrow}, + {"Right", ImGuiKey_RightArrow}, - {"Space", ImGuiKey_Space}, - {"Enter", ImGuiKey_Enter}, - {"Escape", ImGuiKey_Escape}, - {"Tab", ImGuiKey_Tab}, - {"Backspace", ImGuiKey_Backspace}, - {"Delete", ImGuiKey_Delete}, - {"Insert", ImGuiKey_Insert}, - {"Home", ImGuiKey_Home}, - {"End", ImGuiKey_End}, - {"PageUp", ImGuiKey_PageUp}, - {"PageDown", ImGuiKey_PageDown}, + {"Space", ImGuiKey_Space}, + {"Enter", ImGuiKey_Enter}, + {"Escape", ImGuiKey_Escape}, + {"Tab", ImGuiKey_Tab}, + {"Backspace", ImGuiKey_Backspace}, + {"Delete", ImGuiKey_Delete}, + {"Insert", ImGuiKey_Insert}, + {"Home", ImGuiKey_Home}, + {"End", ImGuiKey_End}, + {"PageUp", ImGuiKey_PageUp}, + {"PageDown", ImGuiKey_PageDown}, - {"Minus", ImGuiKey_Minus}, - {"Equal", ImGuiKey_Equal}, - {"LeftBracket", ImGuiKey_LeftBracket}, - {"RightBracket", ImGuiKey_RightBracket}, - {"Semicolon", ImGuiKey_Semicolon}, - {"Apostrophe", ImGuiKey_Apostrophe}, - {"Comma", ImGuiKey_Comma}, - {"Period", ImGuiKey_Period}, - {"Slash", ImGuiKey_Slash}, - {"Backslash", ImGuiKey_Backslash}, - {"GraveAccent", ImGuiKey_GraveAccent}, - - {"MouseLeft", ImGuiKey_MouseLeft}, - {"MouseRight", ImGuiKey_MouseRight}, - {"MouseMiddle", ImGuiKey_MouseMiddle}, - {"MouseX1", ImGuiKey_MouseX1}, - {"MouseX2", ImGuiKey_MouseX2}}; + {"Minus", ImGuiKey_Minus}, + {"Equal", ImGuiKey_Equal}, + {"LeftBracket", ImGuiKey_LeftBracket}, + {"RightBracket", ImGuiKey_RightBracket}, + {"Semicolon", ImGuiKey_Semicolon}, + {"Apostrophe", ImGuiKey_Apostrophe}, + {"Comma", ImGuiKey_Comma}, + {"Period", ImGuiKey_Period}, + {"Slash", ImGuiKey_Slash}, + {"Backslash", ImGuiKey_Backslash}, + {"GraveAccent", ImGuiKey_GraveAccent}, + }; const std::unordered_map MOD_MAP = { {"Ctrl", ImGuiMod_Ctrl}, @@ -167,15 +163,17 @@ namespace anm2ed::imgui int input_text_callback(ImGuiInputTextCallbackData*); bool input_text_string(const char*, std::string*, ImGuiInputTextFlags = 0); bool input_int_range(const char*, int&, int, int, int = STEP, int = STEP_FAST, ImGuiInputTextFlags = 0); - bool combo_strings(const std::string&, int*, std::vector&); - bool combo_strings(const std::string&, int*, std::vector&); + bool input_int2_range(const char*, glm::ivec2&, glm::ivec2, glm::ivec2, ImGuiInputTextFlags = 0); + bool input_float_range(const char*, float&, float, float, float = STEP, float = STEP_FAST, const char* = "%.3f", + ImGuiInputTextFlags = 0); + bool combo_negative_one_indexed(const std::string&, int*, std::vector&); bool selectable_input_text(const std::string&, const std::string&, std::string&, bool = false, ImGuiSelectableFlags = 0, bool* = nullptr); void set_item_tooltip_shortcut(const char*, const std::string& = {}); void external_storage_set(ImGuiSelectionExternalStorage*, int, bool); ImVec2 icon_size_get(); bool chord_held(ImGuiKeyChord); - bool chord_repeating(ImGuiKeyChord, float = 0.125f, float = 0.025f); + bool chord_repeating(ImGuiKeyChord, float = ImGui::GetIO().KeyRepeatDelay, float = ImGui::GetIO().KeyRepeatRate); bool shortcut(std::string, types::shortcut::Type = types::shortcut::FOCUSED_SET); class MultiSelectStorage : public std::set diff --git a/src/imgui/taskbar.cpp b/src/imgui/taskbar.cpp index e04b0fe..8d263ae 100644 --- a/src/imgui/taskbar.cpp +++ b/src/imgui/taskbar.cpp @@ -23,6 +23,9 @@ namespace anm2ed::imgui void Taskbar::update(Manager& manager, Settings& settings, Resources& resources, Dialog& dialog, bool& isQuitting) { auto document = manager.get(); + auto reference = document ? &document->reference : nullptr; + auto animation = document ? document->animation_get() : nullptr; + auto item = document ? document->item_get() : nullptr; if (ImGui::BeginMainMenuBar()) { @@ -30,43 +33,31 @@ namespace anm2ed::imgui if (ImGui::BeginMenu("File")) { - if (ImGui::MenuItem("New", settings.shortcutNew.c_str())) dialog.file_open(dialog::ANM2_NEW); - + if (ImGui::MenuItem("New", settings.shortcutNew.c_str())) dialog.file_save(dialog::ANM2_NEW); if (ImGui::MenuItem("Open", settings.shortcutOpen.c_str())) dialog.file_open(dialog::ANM2_NEW); - if (manager.recentFiles.empty()) + if (ImGui::BeginMenu("Open Recent", !manager.recentFiles.empty())) { - ImGui::BeginDisabled(); - ImGui::MenuItem("Open Recent"); - ImGui::EndDisabled(); - } - else - { - if (ImGui::BeginMenu("Open Recent")) + for (auto [i, file] : std::views::enumerate(manager.recentFiles)) { - for (auto [i, file] : std::views::enumerate(manager.recentFiles)) - { - auto label = std::format(FILE_LABEL_FORMAT, file.filename().string(), file.string()); + auto label = std::format(FILE_LABEL_FORMAT, file.filename().string(), file.string()); - ImGui::PushID(i); - if (ImGui::MenuItem(label.c_str())) manager.open(file); - ImGui::PopID(); - } - - if (!manager.recentFiles.empty()) - if (ImGui::MenuItem("Clear List")) manager.recent_files_clear(); - - ImGui::EndMenu(); + ImGui::PushID(i); + if (ImGui::MenuItem(label.c_str())) manager.open(file); + ImGui::PopID(); } + + if (!manager.recentFiles.empty()) + if (ImGui::MenuItem("Clear List")) manager.recent_files_clear(); + + ImGui::EndMenu(); } - ImGui::BeginDisabled(!document); - { - if (ImGui::MenuItem("Save", settings.shortcutSave.c_str())) manager.save(); - if (ImGui::MenuItem("Save As", settings.shortcutSaveAs.c_str())) dialog.file_save(dialog::ANM2_SAVE); - if (ImGui::MenuItem("Explore XML Location")) dialog.file_explorer_open(document->directory_get()); - } - ImGui::EndDisabled(); + if (ImGui::MenuItem("Save", settings.shortcutSave.c_str(), false, document)) manager.save(); + if (ImGui::MenuItem("Save As", settings.shortcutSaveAs.c_str(), false, document)) + dialog.file_save(dialog::ANM2_SAVE); + if (ImGui::MenuItem("Explore XML Location", nullptr, false, document)) + dialog.file_explorer_open(document->directory_get()); ImGui::Separator(); if (ImGui::MenuItem("Exit", settings.shortcutExit.c_str())) isQuitting = true; @@ -92,16 +83,12 @@ namespace anm2ed::imgui if (ImGui::BeginMenu("Wizard")) { - auto animation = document ? document->animation_get() : nullptr; - auto item = document ? document->item_get() : nullptr; ImGui::BeginDisabled(!item || document->reference.itemType != anm2::LAYER); if (ImGui::MenuItem("Generate Animation From Grid")) generatePopup.open(); if (ImGui::MenuItem("Change All Frame Properties")) changePopup.open(); ImGui::EndDisabled(); ImGui::Separator(); - ImGui::BeginDisabled(!animation); - if (ImGui::MenuItem("Render Animation")) renderPopup.open(); - ImGui::EndDisabled(); + if (ImGui::MenuItem("Render Animation", nullptr, false, animation)) renderPopup.open(); ImGui::EndMenu(); } @@ -158,20 +145,19 @@ namespace anm2ed::imgui auto& zoom = settings.generateZoom; auto& zoomStep = settings.viewZoomStep; - auto childSize = ImVec2(imgui::row_widget_width_get(2), imgui::size_without_footer_get().y); + auto childSize = ImVec2(row_widget_width_get(2), size_without_footer_get().y); if (ImGui::BeginChild("##Options Child", childSize, ImGuiChildFlags_Borders)) { ImGui::InputInt2("Start Position", value_ptr(startPosition)); ImGui::InputInt2("Frame Size", value_ptr(size)); ImGui::InputInt2("Pivot", value_ptr(pivot)); - ImGui::InputInt("Rows", &rows, imgui::STEP, imgui::STEP_FAST); - ImGui::InputInt("Columns", &columns, imgui::STEP, imgui::STEP_FAST); + ImGui::InputInt("Rows", &rows, STEP, STEP_FAST); + ImGui::InputInt("Columns", &columns, STEP, STEP_FAST); - ImGui::InputInt("Count", &count, imgui::STEP, imgui::STEP_FAST); - count = glm::min(count, rows * columns); + input_int_range("Count", count, anm2::FRAME_NUM_MIN, rows * columns); - ImGui::InputInt("Delay", &delay, imgui::STEP, imgui::STEP_FAST); + ImGui::InputInt("Delay", &delay, STEP, STEP_FAST); } ImGui::EndChild(); @@ -183,7 +169,7 @@ namespace anm2ed::imgui auto& time = generateTime; auto& shaderTexture = resources.shaders[resource::shader::TEXTURE]; - auto previewSize = ImVec2(ImGui::GetContentRegionAvail().x, imgui::size_without_footer_get(2).y); + auto previewSize = ImVec2(ImGui::GetContentRegionAvail().x, size_without_footer_get(2).y); generate.size_set(to_vec2(previewSize)); generate.bind(); @@ -196,7 +182,7 @@ namespace anm2ed::imgui .spritesheets[document->anm2.content.layers[document->reference.itemID].spritesheetID] .texture; - auto index = std::clamp((int)(time * count - 1), 0, count - 1); + auto index = std::clamp((int)(time * (count - 1)), 0, (count - 1)); auto row = index / columns; auto column = index % columns; auto crop = startPosition + ivec2(size.x * column, size.y * row); @@ -222,11 +208,18 @@ namespace anm2ed::imgui ImGui::EndChild(); - auto widgetSize = imgui::widget_size_with_row_get(2); + auto widgetSize = widget_size_with_row_get(2); if (ImGui::Button("Generate", widgetSize)) { - document->generate_animation_from_grid(startPosition, size, pivot, columns, count, delay); + auto generate_from_grid = [&]() + { + item->frames_generate_from_grid(startPosition, size, pivot, columns, count, delay); + animation->frameNum = animation->length(); + }; + + DOCUMENT_EDIT_PTR(document, "Generate Animation from Grid", Document::FRAMES, generate_from_grid()); + generatePopup.close(); } @@ -267,59 +260,36 @@ namespace anm2ed::imgui auto& isFromSelectedFrame = settings.changeIsFromSelectedFrame; auto& numberFrames = settings.changeNumberFrames; - auto propertiesSize = imgui::child_size_get(10); + auto propertiesSize = child_size_get(10); if (ImGui::BeginChild("##Properties", propertiesSize, ImGuiChildFlags_Borders)) { - auto start = [&](const char* checkboxLabel, bool& isEnabled) - { - ImGui::Checkbox(checkboxLabel, &isEnabled); - ImGui::SameLine(); - ImGui::BeginDisabled(!isEnabled); - }; - auto end = [&]() { ImGui::EndDisabled(); }; +#define PROPERTIES_WIDGET(body) \ + ImGui::Checkbox(checkboxLabel, &isEnabled); \ + ImGui::SameLine(); \ + ImGui::BeginDisabled(!isEnabled); \ + body; \ + ImGui::EndDisabled(); auto bool_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, bool& value) - { - start(checkboxLabel, isEnabled); - ImGui::Checkbox(valueLabel, &value); - end(); - }; + { PROPERTIES_WIDGET(ImGui::Checkbox(valueLabel, &value)); }; auto color3_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, vec3& value) - { - start(checkboxLabel, isEnabled); - ImGui::ColorEdit3(valueLabel, value_ptr(value)); - end(); - }; + { PROPERTIES_WIDGET(ImGui::ColorEdit3(valueLabel, value_ptr(value))); }; auto color4_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, vec4& value) - { - start(checkboxLabel, isEnabled); - ImGui::ColorEdit4(valueLabel, value_ptr(value)); - end(); - }; + { PROPERTIES_WIDGET(ImGui::ColorEdit4(valueLabel, value_ptr(value))); }; auto float2_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, vec2& value) - { - start(checkboxLabel, isEnabled); - ImGui::InputFloat2(valueLabel, value_ptr(value), math::vec2_format_get(value)); - end(); - }; + { PROPERTIES_WIDGET(ImGui::InputFloat2(valueLabel, value_ptr(value), math::vec2_format_get(value))); }; auto float_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, float& value) - { - start(checkboxLabel, isEnabled); - ImGui::InputFloat(valueLabel, &value, imgui::STEP, imgui::STEP_FAST, math::float_format_get(value)); - end(); - }; + { PROPERTIES_WIDGET(ImGui::InputFloat(valueLabel, &value, STEP, STEP_FAST, math::float_format_get(value))); }; auto int_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, int& value) - { - start(checkboxLabel, isEnabled); - ImGui::InputInt(valueLabel, &value, imgui::STEP, imgui::STEP_FAST); - end(); - }; + { PROPERTIES_WIDGET(ImGui::InputInt(valueLabel, &value, STEP, STEP_FAST)); }; + +#undef PROPERTIES_WIDGET float2_value("##Is Crop", "Crop", isCrop, crop); float2_value("##Is Size", "Size", isSize, size); @@ -336,67 +306,53 @@ namespace anm2ed::imgui } ImGui::EndChild(); - auto settingsSize = imgui::child_size_get(2); + auto settingsSize = child_size_get(2); if (ImGui::BeginChild("##Settings", settingsSize, ImGuiChildFlags_Borders)) { ImGui::Checkbox("From Selected Frame", &isFromSelectedFrame); ImGui::SetItemTooltip("The frames after the currently referenced frame will be changed with these values.\nIf" - "off, will use all frames."); + " off, will use all frames."); ImGui::BeginDisabled(!isFromSelectedFrame); - ImGui::InputInt("Number of Frames", &numberFrames, imgui::STEP, imgui::STEP_FAST); - numberFrames = glm::clamp(numberFrames, anm2::FRAME_NUM_MIN, - (int)document->item_get()->frames.size() - document->reference.frameIndex); + input_int_range("Number of Frames", numberFrames, anm2::FRAME_NUM_MIN, + item->frames.size() - reference->frameIndex); ImGui::SetItemTooltip("Set the number of frames that will be changed."); ImGui::EndDisabled(); } ImGui::EndChild(); - auto widgetSize = imgui::widget_size_with_row_get(4); + auto widgetSize = widget_size_with_row_get(4); auto frame_change = [&](anm2::ChangeType type) { anm2::FrameChange frameChange; - frameChange.crop = isCrop ? std::make_optional(crop) : std::nullopt; - frameChange.size = isSize ? std::make_optional(size) : std::nullopt; - frameChange.position = isPosition ? std::make_optional(position) : std::nullopt; - frameChange.pivot = isPivot ? std::make_optional(pivot) : std::nullopt; - frameChange.scale = isScale ? std::make_optional(scale) : std::nullopt; - frameChange.rotation = isRotation ? std::make_optional(rotation) : std::nullopt; - frameChange.delay = isDelay ? std::make_optional(delay) : std::nullopt; - frameChange.tint = isTint ? std::make_optional(tint) : std::nullopt; - frameChange.colorOffset = isColorOffset ? std::make_optional(colorOffset) : std::nullopt; - frameChange.isVisible = isVisibleSet ? std::make_optional(isVisible) : std::nullopt; - frameChange.isInterpolated = isInterpolatedSet ? std::make_optional(isInterpolated) : std::nullopt; + if (isCrop) frameChange.crop = std::make_optional(crop); + if (isSize) frameChange.size = std::make_optional(size); + if (isPosition) frameChange.position = std::make_optional(position); + if (isPivot) frameChange.pivot = std::make_optional(pivot); + if (isScale) frameChange.scale = std::make_optional(scale); + if (isRotation) frameChange.rotation = std::make_optional(rotation); + if (isDelay) frameChange.delay = std::make_optional(delay); + if (isTint) frameChange.tint = std::make_optional(tint); + if (isColorOffset) frameChange.colorOffset = std::make_optional(colorOffset); + if (isVisibleSet) frameChange.isVisible = std::make_optional(isVisible); + if (isInterpolatedSet) frameChange.isInterpolated = std::make_optional(isInterpolated); - document->frames_change(frameChange, type, isFromSelectedFrame, numberFrames); + DOCUMENT_EDIT_PTR(document, "Change Frame Properties", Document::FRAMES, + item->frames_change(frameChange, type, + isFromSelectedFrame && document->frame_get() ? reference->frameIndex : 0, + isFromSelectedFrame ? numberFrames : -1)); + + changePopup.close(); }; - if (ImGui::Button("Add", widgetSize)) - { - frame_change(anm2::ADD); - changePopup.close(); - } - + if (ImGui::Button("Add", widgetSize)) frame_change(anm2::ADD); ImGui::SameLine(); - - if (ImGui::Button("Subtract", widgetSize)) - { - frame_change(anm2::SUBTRACT); - changePopup.close(); - } - + if (ImGui::Button("Subtract", widgetSize)) frame_change(anm2::SUBTRACT); ImGui::SameLine(); - - if (ImGui::Button("Adjust", widgetSize)) - { - frame_change(anm2::ADJUST); - changePopup.close(); - } - + if (ImGui::Button("Adjust", widgetSize)) frame_change(anm2::ADJUST); ImGui::SameLine(); - if (ImGui::Button("Cancel", widgetSize)) changePopup.close(); ImGui::EndPopup(); @@ -406,7 +362,7 @@ namespace anm2ed::imgui if (ImGui::BeginPopupModal(configurePopup.label, &configurePopup.isOpen, ImGuiWindowFlags_NoResize)) { - auto childSize = imgui::size_without_footer_get(2); + auto childSize = size_without_footer_get(2); if (ImGui::BeginTabBar("##Configure Tabs")) { @@ -420,23 +376,32 @@ namespace anm2ed::imgui ImGui::SetItemTooltip("Enables autosaving of documents."); ImGui::BeginDisabled(!editSettings.fileIsAutosave); - ImGui::InputInt("Autosave Time (minutes", &editSettings.fileAutosaveTime, imgui::STEP, imgui::STEP_FAST); - editSettings.fileAutosaveTime = glm::clamp(editSettings.fileAutosaveTime, 0, 10); + input_int_range("Autosave Time (minutes)", editSettings.fileAutosaveTime, 0, 10); ImGui::SetItemTooltip("If changed, will autosave documents using this interval."); ImGui::EndDisabled(); - ImGui::SeparatorText("View"); + ImGui::SeparatorText("Keyboard"); - ImGui::InputFloat("Display Scale", &editSettings.displayScale, 0.25f, 0.25f, "%.2f"); - ImGui::SetItemTooltip("Change the scale of the display."); - editSettings.displayScale = glm::clamp(editSettings.displayScale, 0.5f, 2.0f); + input_float_range("Repeat Delay (seconds)", editSettings.keyboardRepeatDelay, 0.05f, 1.0f, 0.05f, 0.05f, + "%.2f"); + ImGui::SetItemTooltip("Set how often, after repeating begins, key inputs will be fired."); - ImGui::InputFloat("Zoom Step", &editSettings.viewZoomStep, 10.0f, 10.0f, "%.2f"); - ImGui::SetItemTooltip("When zooming in/out with mouse or shortcut, this value will be used."); - editSettings.viewZoomStep = glm::clamp(editSettings.viewZoomStep, 1.0f, 250.0f); + input_float_range("Repeat Rate (seconds)", editSettings.keyboardRepeatRate, 0.005f, 1.0f, 0.005f, 0.005f, + "%.3f"); + ImGui::SetItemTooltip("Set how often, after repeating begins, key inputs will be fired."); + + ImGui::SeparatorText("UI"); + + input_float_range("UI Scale", editSettings.uiScale, 0.5f, 2.0f, 0.25f, 0.25f, "%.2f"); + ImGui::SetItemTooltip("Change the scale of the UI."); ImGui::Checkbox("Vsync", &editSettings.isVsync); ImGui::SetItemTooltip("Toggle vertical sync; synchronizes program update rate with monitor refresh rate."); + + ImGui::SeparatorText("View"); + + input_float_range("Zoom Step", editSettings.viewZoomStep, 10.0f, 250.0f, 10.0f, 10.0f, "%.0f"); + ImGui::SetItemTooltip("When zooming in/out with mouse or shortcut, this value will be used."); } ImGui::EndChild(); @@ -445,12 +410,10 @@ namespace anm2ed::imgui if (ImGui::BeginTabItem("Shortcuts")) { - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); if (ImGui::BeginChild("##Tab Child", childSize, true)) { - if (ImGui::BeginTable("Shortcuts", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY)) { ImGui::TableSetupScrollFreeze(0, 1); @@ -485,12 +448,12 @@ namespace anm2ed::imgui if (ImGui::IsKeyDown(ImGuiMod_Alt)) chord |= ImGuiMod_Alt; if (ImGui::IsKeyDown(ImGuiMod_Super)) chord |= ImGuiMod_Super; - for (auto& key : imgui::KEY_MAP | std::views::values) + for (auto& key : KEY_MAP | std::views::values) { if (ImGui::IsKeyPressed(key)) { chord |= key; - *settingString = imgui::chord_to_string(chord); + *settingString = chord_to_string(chord); selectedShortcut = -1; break; } @@ -510,7 +473,7 @@ namespace anm2ed::imgui ImGui::EndTabBar(); } - auto widgetSize = imgui::widget_size_with_row_get(3); + auto widgetSize = widget_size_with_row_get(3); if (ImGui::Button("Save", widgetSize)) { @@ -543,23 +506,42 @@ namespace anm2ed::imgui auto& ffmpegPath = settings.renderFFmpegPath; auto& path = settings.renderPath; auto& format = settings.renderFormat; + auto& scale = settings.renderScale; + auto& isRaw = settings.renderIsRawAnimation; auto& type = settings.renderType; auto& start = manager.recordingStart; auto& end = manager.recordingEnd; - auto& isRange = settings.renderIsRange; - auto widgetSize = imgui::widget_size_with_row_get(2); + auto& isRange = manager.isRecordingRange; + auto widgetSize = widget_size_with_row_get(2); auto dialogType = type == render::PNGS ? dialog::PNG_DIRECTORY_SET : type == render::GIF ? dialog::GIF_PATH_SET : type == render::WEBM ? dialog::WEBM_PATH_SET : dialog::NONE; - if (ImGui::ImageButton("##FFmpeg Path Set", resources.icons[icon::FOLDER].id, imgui::icon_size_get())) + auto replace_extension = [&]() + { path = std::filesystem::path(path).replace_extension(render::EXTENSIONS[type]); }; + + auto range_to_length = [&]() + { + start = 0; + end = animation->frameNum; + }; + + if (renderPopup.isJustOpened) + { + replace_extension(); + if (!isRange) range_to_length(); + } + + if (ImGui::ImageButton("##FFmpeg Path Set", resources.icons[icon::FOLDER].id, icon_size_get())) dialog.file_open(dialog::FFMPEG_PATH_SET); ImGui::SameLine(); - imgui::input_text_string("FFmpeg Path", &ffmpegPath); + input_text_string("FFmpeg Path", &ffmpegPath); + ImGui::SetItemTooltip("Set the path where the FFmpeg installation is located.\nFFmpeg is required to render " + "animations.\nhttps://ffmpeg.org"); dialog.set_string_to_selected_path(ffmpegPath, dialog::FFMPEG_PATH_SET); - if (ImGui::ImageButton("##Path Set", resources.icons[icon::FOLDER].id, imgui::icon_size_get())) + if (ImGui::ImageButton("##Path Set", resources.icons[icon::FOLDER].id, icon_size_get())) { if (dialogType == dialog::PNG_DIRECTORY_SET) dialog.folder_open(dialogType); @@ -567,25 +549,44 @@ namespace anm2ed::imgui dialog.file_open(dialogType); } ImGui::SameLine(); - imgui::input_text_string(type == render::PNGS ? "Directory" : "Path", &path); + input_text_string(type == render::PNGS ? "Directory" : "Path", &path); + ImGui::SetItemTooltip("Set the output path or directory for the animation."); dialog.set_string_to_selected_path(path, dialogType); - ImGui::Combo("Type", &type, render::STRINGS, render::COUNT); + if (ImGui::Combo("Type", &type, render::STRINGS, render::COUNT)) replace_extension(); + ImGui::SetItemTooltip("Set the type of the output."); ImGui::BeginDisabled(type != render::PNGS); - imgui::input_text_string("Format", &format); + input_text_string("Format", &format); + ImGui::SetItemTooltip( + "For outputted images, each image will use this format.\n{} represents the index of each image."); ImGui::EndDisabled(); ImGui::BeginDisabled(!isRange); - imgui::input_int_range("Start", start, 0, animation->frameNum - 1); - ImGui::InputInt("End", &end, start, animation->frameNum); + input_int_range("Start", start, 0, animation->frameNum - 1); + ImGui::SetItemTooltip("Set the starting time of the animation."); + input_int_range("End", end, start + 1, animation->frameNum); + ImGui::SetItemTooltip("Set the ending time of the animation."); ImGui::EndDisabled(); - ImGui::Checkbox("Custom Range", &isRange); + ImGui::BeginDisabled(!isRaw); + input_float_range("Scale", scale, 1.0f, 100.0f, STEP, STEP_FAST, "%.1fx"); + ImGui::SetItemTooltip("Set the output scale of the animation."); + ImGui::EndDisabled(); + + if (ImGui::Checkbox("Custom Range", &isRange)) + if (!isRange) range_to_length(); + ImGui::SetItemTooltip("Toggle using a custom range for the animation."); + + ImGui::SameLine(); + + ImGui::Checkbox("Raw", &isRaw); + ImGui::SetItemTooltip("Record only the layers of the animation."); if (ImGui::Button("Render", widgetSize)) { manager.isRecording = true; + manager.isRecordingStart = true; playback.time = start; playback.isPlaying = true; renderPopup.close(); @@ -599,6 +600,8 @@ namespace anm2ed::imgui ImGui::EndPopup(); } + renderPopup.end(); + aboutPopup.trigger(); if (ImGui::BeginPopupModal(aboutPopup.label, &aboutPopup.isOpen, ImGuiWindowFlags_NoResize)) @@ -607,10 +610,10 @@ namespace anm2ed::imgui ImGui::EndPopup(); } - if (imgui::shortcut(settings.shortcutNew, shortcut::GLOBAL)) dialog.file_open(dialog::ANM2_NEW); - if (imgui::shortcut(settings.shortcutOpen, shortcut::GLOBAL)) dialog.file_open(dialog::ANM2_OPEN); - if (imgui::shortcut(settings.shortcutSave, shortcut::GLOBAL)) document->save(); - if (imgui::shortcut(settings.shortcutSaveAs, shortcut::GLOBAL)) dialog.file_save(dialog::ANM2_SAVE); - if (imgui::shortcut(settings.shortcutExit, shortcut::GLOBAL)) isQuitting = true; + if (shortcut(settings.shortcutNew, shortcut::GLOBAL)) dialog.file_save(dialog::ANM2_NEW); + if (shortcut(settings.shortcutOpen, shortcut::GLOBAL)) dialog.file_open(dialog::ANM2_OPEN); + if (shortcut(settings.shortcutSave, shortcut::GLOBAL)) document->save(); + if (shortcut(settings.shortcutSaveAs, shortcut::GLOBAL)) dialog.file_save(dialog::ANM2_SAVE); + if (shortcut(settings.shortcutExit, shortcut::GLOBAL)) isQuitting = true; } } diff --git a/src/imgui/window/animation_preview.cpp b/src/imgui/window/animation_preview.cpp index da3ae99..f798abf 100644 --- a/src/imgui/window/animation_preview.cpp +++ b/src/imgui/window/animation_preview.cpp @@ -32,6 +32,10 @@ namespace anm2ed::imgui { auto& anm2 = document.anm2; auto& playback = document.playback; + auto& zoom = document.previewZoom; + auto& pan = document.previewPan; + auto& isRootTransform = settings.previewIsRootTransform; + auto& scale = settings.renderScale; if (playback.isPlaying) { @@ -41,18 +45,52 @@ namespace anm2ed::imgui if (isSound && !anm2.content.sounds.empty()) if (auto animation = document.animation_get(); animation) if (animation->triggers.isVisible && !isOnlyShowLayers) - if (auto trigger = animation->triggers.frame_generate(playback.time, anm2::TRIGGER); trigger.isVisible) - anm2.content.sounds[anm2.content.events[trigger.eventID].soundID].audio.play(); + if (auto trigger = animation->triggers.frame_generate(playback.time, anm2::TRIGGER); + trigger.is_visible(anm2::TRIGGER)) + if (anm2.content.sounds.contains(trigger.soundID)) anm2.content.sounds[trigger.soundID].audio.play(); document.reference.frameTime = playback.time; } if (manager.isRecording) { + if (manager.isRecordingStart) + { + if (settings.renderIsRawAnimation) + { + savedSettings = settings; + settings.previewBackgroundColor = vec4(); + settings.previewIsGrid = false; + settings.previewIsAxes = false; + settings.timelineIsOnlyShowLayers = true; + + savedZoom = zoom; + savedPan = pan; + + if (auto animation = document.animation_get()) + { + auto rect = animation->rect(isRootTransform); + size = vec2(rect.z, rect.w) * scale; + set_to_rect(zoom, pan, rect); + } + + isSizeTrySet = false; + + bind(); + viewport_set(); + clear(settings.previewBackgroundColor); + unbind(); + } + + manager.isRecordingStart = false; + + return; // Need to wait an additional frame. Kind of hacky, but oh well. + } + auto pixels = pixels_get(); renderFrames.push_back(Texture(pixels.data(), size)); - if (playback.isFinished) + if (playback.time > manager.recordingEnd || playback.isFinished) { auto& ffmpegPath = settings.renderFFmpegPath; auto& path = settings.renderPath; @@ -72,7 +110,7 @@ namespace anm2ed::imgui isSuccess = false; break; } - logger.info(std::format("Saved frame to PNG: {}", outputPath.string())); + logger.info(std::format("Saved frame to: {}", outputPath.string())); } if (isSuccess) @@ -89,6 +127,12 @@ namespace anm2ed::imgui } renderFrames.clear(); + + pan = savedPan; + zoom = savedZoom; + settings = savedSettings; + isSizeTrySet = true; + playback.isPlaying = false; playback.isFinished = false; manager.isRecording = false; @@ -127,22 +171,26 @@ namespace anm2ed::imgui auto& shaderGrid = resources.shaders[shader::GRID]; auto& shaderTexture = resources.shaders[shader::TEXTURE]; - settings.previewPan = pan; - settings.previewZoom = zoom; + auto center_view = [&]() { pan = vec2(); }; if (ImGui::Begin("Animation Preview", &settings.windowIsAnimationPreview)) { - auto childSize = ImVec2(imgui::row_widget_width_get(4), + auto childSize = ImVec2(row_widget_width_get(4), (ImGui::GetTextLineHeightWithSpacing() * 4) + (ImGui::GetStyle().WindowPadding.y * 2)); if (ImGui::BeginChild("##Grid Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) { - ImGui::Checkbox("Grid", &isGrid); + ImGui::SetItemTooltip("Toggle the visibility of the grid."); ImGui::SameLine(); ImGui::ColorEdit4("Color", value_ptr(gridColor), ImGuiColorEditFlags_NoInputs); - ImGui::InputInt2("Size", value_ptr(gridSize)); - ImGui::InputInt2("Offset", value_ptr(gridOffset)); + ImGui::SetItemTooltip("Change the grid's color."); + + input_int2_range("Size", gridSize, ivec2(GRID_SIZE_MIN), ivec2(GRID_SIZE_MAX)); + ImGui::SetItemTooltip("Change the size of all cells in the grid."); + + input_int2_range("Offset", gridOffset, ivec2(GRID_OFFSET_MIN), ivec2(GRID_OFFSET_MAX)); + ImGui::SetItemTooltip("Change the offset of the grid."); } ImGui::EndChild(); @@ -151,19 +199,20 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##View Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) { ImGui::InputFloat("Zoom", &zoom, zoomStep, zoomStep, "%.0f%%"); + ImGui::SetItemTooltip("Change the zoom of the preview."); - auto widgetSize = imgui::widget_size_with_row_get(2); + auto widgetSize = widget_size_with_row_get(2); - imgui::shortcut(settings.shortcutCenterView); + shortcut(settings.shortcutCenterView); if (ImGui::Button("Center View", widgetSize)) pan = vec2(); - imgui::set_item_tooltip_shortcut("Centers the view.", settings.shortcutCenterView); + set_item_tooltip_shortcut("Centers the view.", settings.shortcutCenterView); ImGui::SameLine(); - imgui::shortcut(settings.shortcutFit); + shortcut(settings.shortcutFit); if (ImGui::Button("Fit", widgetSize)) if (animation) set_to_rect(zoom, pan, animation->rect(isRootTransform)); - imgui::set_item_tooltip_shortcut("Set the view to match the extent of the animation.", settings.shortcutFit); + set_item_tooltip_shortcut("Set the view to match the extent of the animation.", settings.shortcutFit); ImGui::TextUnformatted(std::format(POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y).c_str()); } @@ -174,14 +223,19 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##Background Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) { ImGui::ColorEdit4("Background", value_ptr(backgroundColor), ImGuiColorEditFlags_NoInputs); + ImGui::SetItemTooltip("Change the background color."); ImGui::SameLine(); ImGui::Checkbox("Axes", &isAxes); + ImGui::SetItemTooltip("Toggle the axes' visbility."); ImGui::SameLine(); ImGui::ColorEdit4("Color", value_ptr(axesColor), ImGuiColorEditFlags_NoInputs); + ImGui::SetItemTooltip("Set the color of the axes."); - imgui::combo_strings("Overlay", &overlayIndex, document.animationNamesCStr); + combo_negative_one_indexed("Overlay", &overlayIndex, document.animation.labels); + ImGui::SetItemTooltip("Set an animation to be drawn over the current animation."); ImGui::InputFloat("Alpha", &overlayTransparency, 0, 0, "%.0f"); + ImGui::SetItemTooltip("Set the alpha of the overlayed animation."); } ImGui::EndChild(); @@ -189,12 +243,14 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##Helpers Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) { - auto helpersChildSize = ImVec2(imgui::row_widget_width_get(2), ImGui::GetContentRegionAvail().y); + auto helpersChildSize = ImVec2(row_widget_width_get(2), ImGui::GetContentRegionAvail().y); if (ImGui::BeginChild("##Helpers Child 1", helpersChildSize)) { ImGui::Checkbox("Root Transform", &isRootTransform); + ImGui::SetItemTooltip("Root frames will transform the rest of the animation."); ImGui::Checkbox("Pivots", &isPivots); + ImGui::SetItemTooltip("Toggle the visibility of the animation's pivots."); } ImGui::EndChild(); @@ -203,7 +259,9 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##Helpers Child 2", helpersChildSize)) { ImGui::Checkbox("Alt Icons", &isAltIcons); + ImGui::SetItemTooltip("Toggle a different appearance of the target icons."); ImGui::Checkbox("Border", &isBorder); + ImGui::SetItemTooltip("Toggle the visibility of borders around layers."); } ImGui::EndChild(); } @@ -211,7 +269,7 @@ namespace anm2ed::imgui auto cursorScreenPos = ImGui::GetCursorScreenPos(); - size_set(to_vec2(ImGui::GetContentRegionAvail())); + if (isSizeTrySet) size_set(to_vec2(ImGui::GetContentRegionAvail())); bind(); viewport_set(); clear(backgroundColor); @@ -234,23 +292,23 @@ namespace anm2ed::imgui vec4 color = isOnionskin ? vec4(colorOffset, alphaOffset) : color::GREEN; - texture_render(shaderTexture, resources.icons[icon::TARGET].id, rootTransform, color); + auto icon = isAltIcons ? icon::TARGET_ALT : icon::TARGET; + texture_render(shaderTexture, resources.icons[icon].id, rootTransform, color); } for (auto& id : animation->layerOrder) { - auto& layerAnimation = animation->layerAnimations.at(id); + auto& layerAnimation = animation->layerAnimations[id]; if (!layerAnimation.isVisible) continue; auto& layer = anm2.content.layers.at(id); - if (auto frame = layerAnimation.frame_generate(time, anm2::LAYER); frame.isVisible) + if (auto frame = layerAnimation.frame_generate(time, anm2::LAYER); frame.is_visible()) { auto spritesheet = anm2.spritesheet_get(layer.spritesheetID); - if (!spritesheet) continue; + if (!spritesheet || !spritesheet->is_valid()) continue; auto& texture = spritesheet->texture; - if (!texture.is_valid()) continue; auto layerModel = math::quad_model_get(frame.size, frame.position, frame.pivot, math::percent_to_unit(frame.scale), frame.rotation); @@ -288,7 +346,8 @@ namespace anm2ed::imgui if (auto frame = nullAnimation.frame_generate(time, anm2::NULL_); frame.isVisible) { - auto icon = isShowRect ? icon::POINT : icon::TARGET; + auto icon = isShowRect ? icon::POINT : isAltIcons ? icon::TARGET_ALT : icon::TARGET; + auto& size = isShowRect ? POINT_SIZE : TARGET_SIZE; auto color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : id == reference.itemID && reference.itemType == anm2::NULL_ ? color::RED @@ -341,9 +400,8 @@ namespace anm2ed::imgui render(animation, frameTime); - if (overlayIndex > 0) - render(document.anm2.animation_get({overlayIndex - 1}), frameTime, {}, - 1.0f - math::uint8_to_float(overlayTransparency)); + if (auto overlayAnimation = anm2.animation_get({overlayIndex})) + render(overlayAnimation, frameTime, {}, 1.0f - math::uint8_to_float(overlayTransparency)); if (drawOrder == draw_order::ABOVE && isEnabled) onionskins_render(frameTime); } @@ -356,7 +414,8 @@ namespace anm2ed::imgui if (animation && animation->triggers.isVisible && !isOnlyShowLayers) { - if (auto trigger = animation->triggers.frame_generate(frameTime, anm2::TRIGGER); trigger.isVisible) + if (auto trigger = animation->triggers.frame_generate(frameTime, anm2::TRIGGER); + trigger.isVisible && trigger.eventID > -1) { auto clipMin = ImGui::GetItemRectMin(); auto clipMax = ImGui::GetItemRectMax(); @@ -374,45 +433,57 @@ namespace anm2ed::imgui if (isPreviewHovered) { - ImGui::SetKeyboardFocusHere(-1); - - mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos)); - - auto isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); + auto isMouseClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left); auto isMouseReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Left); auto isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); auto isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); - auto isLeftPressed = ImGui::IsKeyPressed(ImGuiKey_LeftArrow, false); - auto isRightPressed = ImGui::IsKeyPressed(ImGuiKey_RightArrow, false); - auto isUpPressed = ImGui::IsKeyPressed(ImGuiKey_UpArrow, false); - auto isDownPressed = ImGui::IsKeyPressed(ImGuiKey_DownArrow, false); + auto isMouseRightDown = ImGui::IsMouseDown(ImGuiMouseButton_Right); + auto mouseDelta = to_ivec2(ImGui::GetIO().MouseDelta); + auto mouseWheel = ImGui::GetIO().MouseWheel; + + auto isLeftJustPressed = ImGui::IsKeyPressed(ImGuiKey_LeftArrow, false); + auto isRightJustPressed = ImGui::IsKeyPressed(ImGuiKey_RightArrow, false); + auto isUpJustPressed = ImGui::IsKeyPressed(ImGuiKey_UpArrow, false); + auto isDownJustPressed = ImGui::IsKeyPressed(ImGuiKey_DownArrow, false); + auto isLeftPressed = ImGui::IsKeyPressed(ImGuiKey_LeftArrow); + auto isRightPressed = ImGui::IsKeyPressed(ImGuiKey_RightArrow); + auto isUpPressed = ImGui::IsKeyPressed(ImGuiKey_UpArrow); + auto isDownPressed = ImGui::IsKeyPressed(ImGuiKey_DownArrow); + auto isLeftDown = ImGui::IsKeyDown(ImGuiKey_LeftArrow); + auto isRightDown = ImGui::IsKeyDown(ImGuiKey_RightArrow); + auto isUpDown = ImGui::IsKeyDown(ImGuiKey_UpArrow); + auto isDownDown = ImGui::IsKeyDown(ImGuiKey_DownArrow); auto isLeftReleased = ImGui::IsKeyReleased(ImGuiKey_LeftArrow); auto isRightReleased = ImGui::IsKeyReleased(ImGuiKey_RightArrow); auto isUpReleased = ImGui::IsKeyReleased(ImGuiKey_UpArrow); auto isDownReleased = ImGui::IsKeyReleased(ImGuiKey_DownArrow); - auto isLeft = imgui::chord_repeating(ImGuiKey_LeftArrow); - auto isRight = imgui::chord_repeating(ImGuiKey_RightArrow); - auto isUp = imgui::chord_repeating(ImGuiKey_UpArrow); - auto isDown = imgui::chord_repeating(ImGuiKey_DownArrow); - auto isMouseRightDown = ImGui::IsMouseDown(ImGuiMouseButton_Right); - auto mouseDelta = to_ivec2(ImGui::GetIO().MouseDelta); - auto mouseWheel = ImGui::GetIO().MouseWheel; - auto isZoomIn = imgui::chord_repeating(imgui::string_to_chord(settings.shortcutZoomIn)); - auto isZoomOut = imgui::chord_repeating(imgui::string_to_chord(settings.shortcutZoomOut)); + auto isKeyJustPressed = isLeftJustPressed || isRightJustPressed || isUpJustPressed || isDownJustPressed; + auto isKeyDown = isLeftDown || isRightDown || isUpDown || isDownDown; + auto isKeyReleased = isLeftReleased || isRightReleased || isUpReleased || isDownReleased; + + auto isZoomIn = chord_repeating(string_to_chord(settings.shortcutZoomIn)); + auto isZoomOut = chord_repeating(string_to_chord(settings.shortcutZoomOut)); + + auto isBegin = isMouseClicked || isKeyJustPressed; + auto isDuring = isMouseDown || isKeyDown; + auto isEnd = isMouseReleased || isKeyReleased; + auto isMod = ImGui::IsKeyDown(ImGuiMod_Shift); + auto frame = document.frame_get(); auto useTool = tool; auto step = isMod ? canvas::STEP_FAST : canvas::STEP; - auto isKeyPressed = isLeftPressed || isRightPressed || isUpPressed || isDownPressed; - auto isKeyReleased = isLeftReleased || isRightReleased || isUpReleased || isDownReleased; - auto isBegin = isMouseClick || isKeyPressed; - auto isEnd = isMouseReleased || isKeyReleased; + mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos)); if (isMouseMiddleDown) useTool = tool::PAN; if (tool == tool::MOVE && isMouseRightDown) useTool = tool::SCALE; if (tool == tool::SCALE && isMouseRightDown) useTool = tool::MOVE; - ImGui::SetMouseCursor(tool::INFO[useTool].cursor); + auto& areaType = tool::INFO[useTool].areaType; + auto cursor = areaType == tool::ANIMATION_PREVIEW || areaType == tool::ALL ? tool::INFO[useTool].cursor + : ImGuiMouseCursor_NotAllowed; + ImGui::SetMouseCursor(cursor); + ImGui::SetKeyboardFocusHere(-1); switch (useTool) { @@ -423,28 +494,62 @@ namespace anm2ed::imgui if (!frame) break; if (isBegin) document.snapshot("Frame Position"); if (isMouseDown) frame->position = mousePos; - if (isLeft) frame->position.x -= step; - if (isRight) frame->position.x += step; - if (isUp) frame->position.y -= step; - if (isDown) frame->position.y += step; + if (isLeftPressed) frame->position.x -= step; + if (isRightPressed) frame->position.x += step; + if (isUpPressed) frame->position.y -= step; + if (isDownPressed) frame->position.y += step; if (isEnd) document.change(Document::FRAMES); + if (isDuring) + { + if (ImGui::BeginTooltip()) + { + auto positionFormat = math::vec2_format_get(frame->position); + auto positionString = std::format("Position: ({}, {})", positionFormat, positionFormat); + ImGui::Text(positionString.c_str(), frame->position.x, frame->position.y); + ImGui::EndTooltip(); + } + } break; case tool::SCALE: if (!frame) break; if (isBegin) document.snapshot("Frame Scale"); if (isMouseDown) frame->scale += mouseDelta; - if (isLeft) frame->scale.x -= step; - if (isRight) frame->scale.x += step; - if (isUp) frame->scale.y -= step; - if (isDown) frame->scale.y += step; + if (isLeftPressed) frame->scale.x -= step; + if (isRightPressed) frame->scale.x += step; + if (isUpPressed) frame->scale.y -= step; + if (isDownPressed) frame->scale.y += step; + + if (isDuring) + { + if (ImGui::BeginTooltip()) + { + auto scaleFormat = math::vec2_format_get(frame->scale); + auto scaleString = std::format("Scale: ({}, {})", scaleFormat, scaleFormat); + ImGui::Text(scaleString.c_str(), frame->scale.x, frame->scale.y); + ImGui::EndTooltip(); + } + } + if (isEnd) document.change(Document::FRAMES); break; case tool::ROTATE: if (!frame) break; if (isBegin) document.snapshot("Frame Rotation"); if (isMouseDown) frame->rotation += mouseDelta.y; - if (isLeft || isDown) frame->rotation -= step; - if (isUp || isRight) frame->rotation += step; + if (isLeftPressed || isDownPressed) frame->rotation -= step; + if (isUpPressed || isRightPressed) frame->rotation += step; + + if (isDuring) + { + if (ImGui::BeginTooltip()) + { + auto rotationFormat = math::float_format_get(frame->rotation); + auto rotationString = std::format("Rotation: {}", rotationFormat); + ImGui::Text(rotationString.c_str(), frame->rotation); + ImGui::EndTooltip(); + } + } + if (isEnd) document.change(Document::FRAMES); break; default: @@ -452,7 +557,8 @@ namespace anm2ed::imgui } if (mouseWheel != 0 || isZoomIn || isZoomOut) - zoom_set(zoom, pan, vec2(mousePos), (mouseWheel > 0 || isZoomIn) ? zoomStep : -zoomStep); + zoom_set(zoom, pan, mouseWheel != 0 ? vec2(mousePos) : vec2(), + (mouseWheel > 0 || isZoomIn) ? zoomStep : -zoomStep); } } ImGui::End(); @@ -478,5 +584,14 @@ namespace anm2ed::imgui ImGui::EndPopup(); } + + if (!document.isAnimationPreviewSet) + { + center_view(); + zoom = settings.previewStartZoom; + document.isAnimationPreviewSet = true; + } + + settings.previewStartZoom = zoom; } } diff --git a/src/imgui/window/animation_preview.h b/src/imgui/window/animation_preview.h index 486e174..33fb991 100644 --- a/src/imgui/window/animation_preview.h +++ b/src/imgui/window/animation_preview.h @@ -10,6 +10,10 @@ namespace anm2ed::imgui class AnimationPreview : public Canvas { bool isPreviewHovered{}; + bool isSizeTrySet{true}; + Settings savedSettings{}; + float savedZoom{}; + glm::vec2 savedPan{}; glm::ivec2 mousePos{}; std::vector renderFrames{}; diff --git a/src/imgui/window/animations.cpp b/src/imgui/window/animations.cpp index c3ed704..dcac6c1 100644 --- a/src/imgui/window/animations.cpp +++ b/src/imgui/window/animations.cpp @@ -2,6 +2,10 @@ #include +#include "toast.h" +#include "vector_.h" + +using namespace anm2ed::util; using namespace anm2ed::resource; using namespace anm2ed::types; @@ -12,10 +16,11 @@ namespace anm2ed::imgui auto& document = *manager.get(); auto& anm2 = document.anm2; auto& reference = document.reference; - auto& hovered = document.hoveredAnimation; - auto& multiSelect = document.animationMultiSelect; - auto& mergeMultiSelect = document.animationMergeMultiSelect; - auto& mergeTarget = document.mergeTarget; + auto& hovered = document.animation.hovered; + auto& selection = document.animation.selection; + auto& mergeSelection = document.merge.selection; + auto& mergeReference = document.merge.reference; + auto& overlayIndex = document.overlayIndex; hovered = -1; @@ -25,7 +30,7 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##Animations Child", childSize, ImGuiChildFlags_Borders)) { - multiSelect.start(anm2.animations.items.size()); + selection.start(anm2.animations.items.size()); for (auto [i, animation] : std::views::enumerate(anm2.animations.items)) { @@ -40,11 +45,11 @@ namespace anm2ed::imgui : font::REGULAR; ImGui::PushFont(resources.fonts[font].get(), font::SIZE); - ImGui::SetNextItemSelectionUserData(i); + ImGui::SetNextItemSelectionUserData((int)i); if (selectable_input_text(animation.name, std::format("###Document #{} Animation #{}", manager.selected, i), - animation.name, multiSelect.contains(i))) - document.animation_set(i); - if (ImGui::IsItemHovered()) hovered = i; + animation.name, selection.contains((int)i))) + reference = {(int)i}; + if (ImGui::IsItemHovered()) hovered = (int)i; ImGui::PopFont(); if (ImGui::BeginItemTooltip()) @@ -69,11 +74,12 @@ namespace anm2ed::imgui if (ImGui::BeginDragDropSource()) { - static std::vector selection; - selection.assign(multiSelect.begin(), multiSelect.end()); - ImGui::SetDragDropPayload("Animation Drag Drop", selection.data(), selection.size() * sizeof(int)); - for (auto& i : selection) - ImGui::TextUnformatted(anm2.animations.items[i].name.c_str()); + static std::vector dragDropSelection{}; + dragDropSelection.assign(selection.begin(), selection.end()); + ImGui::SetDragDropPayload("Animation Drag Drop", dragDropSelection.data(), + dragDropSelection.size() * sizeof(int)); + for (auto& i : dragDropSelection) + ImGui::Text("%s", anm2.animations.items[(int)i].name.c_str()); ImGui::EndDragDropSource(); } @@ -85,7 +91,8 @@ namespace anm2ed::imgui auto payloadCount = payload->DataSize / sizeof(int); std::vector indices(payloadIndices, payloadIndices + payloadCount); std::sort(indices.begin(), indices.end()); - document.animations_move(indices, i); + DOCUMENT_EDIT(document, "Move Animation(s)", Document::ANIMATIONS, + selection = vector::move_indices(anm2.animations.items, indices, i)); } ImGui::EndDragDropTarget(); } @@ -93,14 +100,14 @@ namespace anm2ed::imgui ImGui::PopID(); } - multiSelect.finish(); + selection.finish(); auto copy = [&]() { - if (!multiSelect.empty()) + if (!selection.empty()) { std::string clipboardText{}; - for (auto& i : multiSelect) + for (auto& i : selection) clipboardText += anm2.animations.items[i].to_string(); clipboard.set(clipboardText); } @@ -111,13 +118,41 @@ namespace anm2ed::imgui auto cut = [&]() { copy(); - document.animations_remove(); + + auto remove = [&]() + { + if (!selection.empty()) + { + for (auto& i : selection | std::views::reverse) + anm2.animations.items.erase(anm2.animations.items.begin() + i); + selection.clear(); + } + else if (hovered > -1) + { + anm2.animations.items.erase(anm2.animations.items.begin() + hovered); + hovered = -1; + } + }; + + DOCUMENT_EDIT(document, "Cut Animation(s)", Document::ANIMATIONS, remove()); }; auto paste = [&]() { auto clipboardText = clipboard.get(); - document.animations_deserialize(clipboardText); + + auto deserialize = [&]() + { + auto start = selection.empty() ? anm2.animations.items.size() : *selection.rbegin() + 1; + std::set indices{}; + std::string errorString{}; + if (anm2.animations_deserialize(clipboardText, start, indices, &errorString)) + selection = indices; + else + toasts.error(std::format("Failed to deserialize animation(s): {}", errorString)); + }; + + DOCUMENT_EDIT(document, "Paste Animation(s)", Document::ANIMATIONS, deserialize()); }; if (shortcut(settings.shortcutCut, shortcut::FOCUSED)) cut(); @@ -126,15 +161,9 @@ namespace anm2ed::imgui if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) { - ImGui::BeginDisabled(multiSelect.empty() && hovered == -1); - if (ImGui::MenuItem("Cut", settings.shortcutCut.c_str())) cut(); - if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); - ImGui::EndDisabled(); - - ImGui::BeginDisabled(clipboard.is_empty()); - if (ImGui::MenuItem("Paste", settings.shortcutPaste.c_str())) paste(); - ImGui::EndDisabled(); - + if (ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, !selection.empty() || hovered > -1)) cut(); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !selection.empty() || hovered > -1)) copy(); + if (ImGui::MenuItem("Paste", settings.shortcutPaste.c_str(), false, !clipboard.is_empty())) paste(); ImGui::EndPopup(); } } @@ -143,33 +172,98 @@ namespace anm2ed::imgui auto widgetSize = widget_size_with_row_get(5); shortcut(settings.shortcutAdd); - if (ImGui::Button("Add", widgetSize)) document.animation_add(); + if (ImGui::Button("Add", widgetSize)) + { + auto add = [&]() + { + anm2::Animation animation; + if (anm2::Animation* referenceAnimation = document.animation_get()) + { + for (auto [id, layerAnimation] : referenceAnimation->layerAnimations) + animation.layerAnimations[id] = anm2::Item(); + animation.layerOrder = referenceAnimation->layerOrder; + for (auto [id, nullAnimation] : referenceAnimation->nullAnimations) + animation.nullAnimations[id] = anm2::Item(); + } + animation.rootAnimation.frames.emplace_back(anm2::Frame()); + + auto index = 0; + if (!anm2.animations.items.empty()) + index = selection.empty() ? (int)anm2.animations.items.size() - 1 : *selection.rbegin() + 1; + + anm2.animations.items.insert(anm2.animations.items.begin() + index, animation); + selection = {index}; + reference = {index}; + }; + + DOCUMENT_EDIT(document, "Add Animation", Document::ANIMATIONS, add()); + } set_item_tooltip_shortcut("Add a new animation.", settings.shortcutAdd); ImGui::SameLine(); - ImGui::BeginDisabled(multiSelect.empty()); + ImGui::BeginDisabled(selection.empty()); { shortcut(settings.shortcutDuplicate); - if (ImGui::Button("Duplicate", widgetSize)) document.animation_duplicate(); + if (ImGui::Button("Duplicate", widgetSize)) + { + auto duplicate = [&]() + { + auto duplicated = selection; + auto end = std::ranges::max(duplicated); + for (auto& id : duplicated) + { + anm2.animations.items.insert(anm2.animations.items.begin() + end, anm2.animations.items[id]); + selection.insert(++end); + selection.erase(id); + } + }; + + DOCUMENT_EDIT(document, "Duplicate Animation(s)", Document::ANIMATIONS, duplicate()); + } set_item_tooltip_shortcut("Duplicate the selected animation(s).", settings.shortcutDuplicate); ImGui::SameLine(); - if (shortcut(settings.shortcutMerge, shortcut::FOCUSED)) - if (multiSelect.size() > 0) document.animations_merge_quick(); + if (shortcut(settings.shortcutMerge, shortcut::FOCUSED) && !selection.empty()) + { + auto merge_quick = [&]() + { + int merged{}; + if (selection.contains(overlayIndex)) overlayIndex = -1; - ImGui::BeginDisabled(multiSelect.size() != 1); + if (selection.size() > 1) + merged = anm2.animations_merge(*selection.begin(), selection); + else if (selection.size() == 1 && *selection.begin() != (int)anm2.animations.items.size() - 1) + { + auto start = *selection.begin(); + auto next = *selection.begin() + 1; + std::set animationSet{}; + animationSet.insert(start); + animationSet.insert(next); + + merged = anm2.animations_merge(start, animationSet); + } + else + return; + + selection = {merged}; + reference = {merged}; + }; + + DOCUMENT_EDIT(document, "Merge Animations", Document::ANIMATIONS, merge_quick()) + } + + ImGui::BeginDisabled(selection.size() != 1); { if (ImGui::Button("Merge", widgetSize)) { mergePopup.open(); - mergeMultiSelect.clear(); - mergeTarget = *multiSelect.begin(); + mergeSelection.clear(); + mergeReference = *selection.begin(); } } ImGui::EndDisabled(); - set_item_tooltip_shortcut("Open the merge popup.\nUsing the shortcut will merge the animations with\nthe last " "configured merge settings.", settings.shortcutMerge); @@ -177,14 +271,31 @@ namespace anm2ed::imgui ImGui::SameLine(); shortcut(settings.shortcutRemove); - if (ImGui::Button("Remove", widgetSize)) document.animations_remove(); + if (ImGui::Button("Remove", widgetSize)) + { + auto remove = [&]() + { + for (auto& i : selection | std::views::reverse) + { + if (i == overlayIndex) overlayIndex = -1; + anm2.animations.items.erase(anm2.animations.items.begin() + i); + } + selection.clear(); + }; + + DOCUMENT_EDIT(document, "Remove Animation(s)", Document::ANIMATIONS, remove()); + } set_item_tooltip_shortcut("Remove the selected animation(s).", settings.shortcutDuplicate); ImGui::SameLine(); shortcut(settings.shortcutDefault); - ImGui::BeginDisabled(multiSelect.size() != 1); - if (ImGui::Button("Default", widgetSize)) document.animation_default(); + ImGui::BeginDisabled(selection.size() != 1); + if (ImGui::Button("Default", widgetSize)) + { + DOCUMENT_EDIT(document, "Default Animation", Document::ANIMATIONS, + anm2.animations.defaultAnimation = anm2.animations.items[*selection.begin()].name); + } ImGui::EndDisabled(); set_item_tooltip_shortcut("Set the selected animation as the default.", settings.shortcutDefault); } @@ -196,7 +307,7 @@ namespace anm2ed::imgui { auto merge_close = [&]() { - mergeMultiSelect.clear(); + mergeSelection.clear(); mergePopup.close(); }; @@ -212,19 +323,21 @@ namespace anm2ed::imgui if (ImGui::BeginChild("Animations", animationsSize, ImGuiChildFlags_Borders)) { - mergeMultiSelect.start(anm2.animations.items.size()); + mergeSelection.start(anm2.animations.items.size()); for (auto [i, animation] : std::views::enumerate(anm2.animations.items)) { + if (i == mergeReference) continue; + ImGui::PushID(i); ImGui::SetNextItemSelectionUserData(i); - ImGui::Selectable(animation.name.c_str(), mergeMultiSelect.contains(i)); + ImGui::Selectable(animation.name.c_str(), mergeSelection.contains(i)); ImGui::PopID(); } - mergeMultiSelect.finish(); + mergeSelection.finish(); } ImGui::EndChild(); @@ -258,7 +371,17 @@ namespace anm2ed::imgui if (ImGui::Button("Merge", widgetSize)) { - document.animations_merge((merge::Type)type, isDeleteAnimationsAfter); + auto merge = [&]() + { + if (mergeSelection.contains(overlayIndex)) overlayIndex = -1; + auto merged = + anm2.animations_merge(mergeReference, mergeSelection, (merge::Type)type, isDeleteAnimationsAfter); + + selection = {merged}; + reference = {merged}; + }; + + DOCUMENT_EDIT(document, "Merge Animations", Document::ANIMATIONS, merge()); merge_close(); } ImGui::SameLine(); diff --git a/src/imgui/window/events.cpp b/src/imgui/window/events.cpp index fa3da45..e7f5843 100644 --- a/src/imgui/window/events.cpp +++ b/src/imgui/window/events.cpp @@ -2,6 +2,10 @@ #include +#include "map_.h" +#include "toast.h" + +using namespace anm2ed::util; using namespace anm2ed::resource; using namespace anm2ed::types; @@ -11,10 +15,10 @@ namespace anm2ed::imgui { auto& document = *manager.get(); auto& anm2 = document.anm2; - auto& unused = document.unusedEventIDs; - auto& hovered = document.hoveredEvent; - auto& reference = document.referenceEvent; - auto& multiSelect = document.eventMultiSelect; + auto& unused = document.event.unused; + auto& hovered = document.event.hovered; + auto& reference = document.event.reference; + auto& selection = document.event.selection; hovered = -1; @@ -24,23 +28,15 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##Events Child", childSize, true)) { - multiSelect.start(anm2.content.events.size()); + selection.start(anm2.content.events.size()); for (auto& [id, event] : anm2.content.events) { ImGui::PushID(id); ImGui::SetNextItemSelectionUserData(id); - ImGui::Selectable(event.name.c_str(), multiSelect.contains(id)); - if (ImGui::IsItemHovered()) - { - hovered = id; - if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) - { - reference = id; - editEvent = document.anm2.content.events[reference]; - propertiesPopup.open(); - } - } + if (selectable_input_text(event.name, std::format("###Document #{} Event #{}", manager.selected, id), + event.name, selection.contains(id))) + if (ImGui::IsItemHovered()) hovered = id; if (ImGui::BeginItemTooltip()) { @@ -52,14 +48,14 @@ namespace anm2ed::imgui ImGui::PopID(); } - multiSelect.finish(); + selection.finish(); auto copy = [&]() { - if (!multiSelect.empty()) + if (!selection.empty()) { std::string clipboardText{}; - for (auto& id : multiSelect) + for (auto& id : selection) clipboardText += anm2.content.events[id].to_string(id); clipboard.set(clipboardText); } @@ -69,8 +65,12 @@ namespace anm2ed::imgui auto paste = [&](merge::Type type) { - auto clipboardText = clipboard.get(); - document.events_deserialize(clipboardText, type); + std::string errorString{}; + document.snapshot("Paste Event(s)"); + if (anm2.events_deserialize(clipboard.get(), type, &errorString)) + document.change(Document::EVENTS); + else + toasts.error(std::format("Failed to deserialize event(s): {}", errorString)); }; if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); @@ -78,25 +78,16 @@ namespace anm2ed::imgui if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) { - ImGui::BeginDisabled(); - ImGui::MenuItem("Cut", settings.shortcutCut.c_str()); - ImGui::EndDisabled(); + ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, false); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !selection.empty() || hovered > -1)) copy(); - ImGui::BeginDisabled(multiSelect.empty() && hovered == -1); - if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); - ImGui::EndDisabled(); - - ImGui::BeginDisabled(clipboard.is_empty()); + if (ImGui::BeginMenu("Paste", !clipboard.is_empty())) { - if (ImGui::BeginMenu("Paste")) - { - if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); - if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); - ImGui::EndMenu(); - } + ImGui::EndMenu(); } - ImGui::EndDisabled(); ImGui::EndPopup(); } @@ -108,53 +99,36 @@ namespace anm2ed::imgui shortcut(settings.shortcutAdd); if (ImGui::Button("Add", widgetSize)) { - reference = -1; - editEvent = anm2::Event(); - propertiesPopup.open(); + auto add = [&]() + { + auto id = map::next_id_get(anm2.content.events); + anm2.content.events[id] = anm2::Event(); + selection = {id}; + reference = {id}; + }; + + DOCUMENT_EDIT(document, "Add Event", Document::EVENTS, add()); } set_item_tooltip_shortcut("Add an event.", settings.shortcutAdd); ImGui::SameLine(); shortcut(settings.shortcutRemove); ImGui::BeginDisabled(unused.empty()); - if (ImGui::Button("Remove Unused", widgetSize)) document.events_remove_unused(); + if (ImGui::Button("Remove Unused", widgetSize)) + { + auto remove_unused = [&]() + { + for (auto& id : unused) + anm2.content.events.erase(id); + unused.clear(); + }; + + DOCUMENT_EDIT(document, "Remove Unused Events", Document::EVENTS, remove_unused()); + } ImGui::EndDisabled(); set_item_tooltip_shortcut("Remove unused events (i.e., ones not used by any trigger in any animation.)", settings.shortcutRemove); } ImGui::End(); - - propertiesPopup.trigger(); - - if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) - { - auto childSize = child_size_get(2); - auto& event = editEvent; - - if (ImGui::BeginChild("Child", childSize, ImGuiChildFlags_Borders)) - { - if (propertiesPopup.isJustOpened) ImGui::SetKeyboardFocusHere(); - input_text_string("Name", &event.name); - ImGui::SetItemTooltip("Set the event's name."); - combo_strings("Sound", &event.soundID, document.soundNames); - ImGui::SetItemTooltip("Set the event sound; it will play when a trigger associated with this event activates."); - } - ImGui::EndChild(); - - auto widgetSize = widget_size_with_row_get(2); - - if (ImGui::Button(reference == -1 ? "Add" : "Confirm", widgetSize)) - { - document.event_set(event); - propertiesPopup.close(); - } - - ImGui::SameLine(); - - if (ImGui::Button("Cancel", widgetSize)) propertiesPopup.close(); - - propertiesPopup.end(); - ImGui::EndPopup(); - } } } diff --git a/src/imgui/window/events.h b/src/imgui/window/events.h index 25a3705..7d01fce 100644 --- a/src/imgui/window/events.h +++ b/src/imgui/window/events.h @@ -9,9 +9,6 @@ namespace anm2ed::imgui { class Events { - anm2::Event editEvent{}; - PopupHelper propertiesPopup{PopupHelper("Event Properties", POPUP_SMALL_NO_HEIGHT)}; - public: void update(Manager&, Settings&, Resources&, Clipboard&); }; diff --git a/src/imgui/window/frame_properties.cpp b/src/imgui/window/frame_properties.cpp index f83b002..5ffab31 100644 --- a/src/imgui/window/frame_properties.cpp +++ b/src/imgui/window/frame_properties.cpp @@ -1,7 +1,5 @@ #include "frame_properties.h" -#include - #include #include "math_.h" @@ -18,9 +16,7 @@ namespace anm2ed::imgui if (ImGui::Begin("Frame Properties", &settings.windowIsFrameProperties)) { auto& document = *manager.get(); - auto& anm2 = document.anm2; - auto& reference = document.reference; - auto& type = reference.itemType; + auto& type = document.reference.itemType; auto frame = document.frame_get(); auto useFrame = frame ? *frame : anm2::Frame(); @@ -28,13 +24,16 @@ namespace anm2ed::imgui { if (type == anm2::TRIGGER) { - std::vector eventNames{}; - for (auto& event : anm2.content.events | std::views::values) - eventNames.emplace_back(event.name); - - if (imgui::combo_strings("Event", frame ? &useFrame.eventID : &dummy_value(), eventNames)) + if (combo_negative_one_indexed("Event", frame ? &useFrame.eventID : &dummy_value(), + document.event.labels)) DOCUMENT_EDIT(document, "Trigger Event", Document::FRAMES, frame->eventID = useFrame.eventID); ImGui::SetItemTooltip("Change the event this trigger uses."); + + if (combo_negative_one_indexed("Sound", frame ? &useFrame.soundID : &dummy_value(), + document.sound.labels)) + DOCUMENT_EDIT(document, "Trigger Sound", Document::FRAMES, frame->soundID = useFrame.soundID); + ImGui::SetItemTooltip("Change the sound this trigger uses."); + if (ImGui::InputInt("At Frame", frame ? &useFrame.atFrame : &dummy_value(), imgui::STEP, imgui::STEP_FAST, !frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0)) DOCUMENT_EDIT(document, "Trigger At Frame", Document::FRAMES, frame->atFrame = useFrame.atFrame); diff --git a/src/imgui/window/layers.cpp b/src/imgui/window/layers.cpp index 1b12e34..b09d1e9 100644 --- a/src/imgui/window/layers.cpp +++ b/src/imgui/window/layers.cpp @@ -2,6 +2,10 @@ #include +#include "map_.h" +#include "toast.h" + +using namespace anm2ed::util; using namespace anm2ed::resource; using namespace anm2ed::types; @@ -11,10 +15,10 @@ namespace anm2ed::imgui { auto& document = *manager.get(); auto& anm2 = document.anm2; - auto& reference = document.referenceLayer; - auto& unused = document.unusedLayerIDs; - auto& hovered = document.hoveredLayer; - auto& multiSelect = document.layersMultiSelect; + auto& reference = document.layer.reference; + auto& unused = document.layer.unused; + auto& hovered = document.layer.hovered; + auto& selection = document.layer.selection; auto& propertiesPopup = manager.layerPropertiesPopup; hovered = -1; @@ -25,11 +29,11 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##Layers Child", childSize, true)) { - multiSelect.start(anm2.content.layers.size()); + selection.start(anm2.content.layers.size()); for (auto& [id, layer] : anm2.content.layers) { - auto isSelected = multiSelect.contains(id); + auto isSelected = selection.contains(id); ImGui::PushID(id); @@ -55,14 +59,14 @@ namespace anm2ed::imgui ImGui::PopID(); } - multiSelect.finish(); + selection.finish(); auto copy = [&]() { - if (!multiSelect.empty()) + if (!selection.empty()) { std::string clipboardText{}; - for (auto& id : multiSelect) + for (auto& id : selection) clipboardText += anm2.content.layers[id].to_string(id); clipboard.set(clipboardText); } @@ -72,8 +76,12 @@ namespace anm2ed::imgui auto paste = [&](merge::Type type) { - auto clipboardText = clipboard.get(); - document.layers_deserialize(clipboardText, type); + std::string errorString{}; + document.snapshot("Paste Layer(s)"); + if (anm2.layers_deserialize(clipboard.get(), type, &errorString)) + document.change(Document::NULLS); + else + toasts.error(std::format("Failed to deserialize layer(s): {}", errorString)); }; if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); @@ -81,25 +89,16 @@ namespace anm2ed::imgui if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) { - ImGui::BeginDisabled(); - ImGui::MenuItem("Cut", settings.shortcutCut.c_str()); - ImGui::EndDisabled(); + ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, false); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !selection.empty() || hovered > -1)) copy(); - ImGui::BeginDisabled(multiSelect.empty() && hovered == -1); - if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); - ImGui::EndDisabled(); - - ImGui::BeginDisabled(clipboard.is_empty()); + if (ImGui::BeginMenu("Paste", !clipboard.is_empty())) { - if (ImGui::BeginMenu("Paste")) - { - if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); - if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); - ImGui::EndMenu(); - } + ImGui::EndMenu(); } - ImGui::EndDisabled(); ImGui::EndPopup(); } @@ -115,7 +114,17 @@ namespace anm2ed::imgui shortcut(settings.shortcutRemove); ImGui::BeginDisabled(unused.empty()); - if (ImGui::Button("Remove Unused", widgetSize)) document.layers_remove_unused(); + if (ImGui::Button("Remove Unused", widgetSize)) + { + auto remove_unused = [&]() + { + for (auto& id : unused) + anm2.content.layers.erase(id); + unused.clear(); + }; + + DOCUMENT_EDIT(document, "Remove Unused Layers", Document::LAYERS, remove_unused()); + } ImGui::EndDisabled(); set_item_tooltip_shortcut("Remove unused layers (i.e., ones not used in any animation.)", settings.shortcutRemove); @@ -134,7 +143,7 @@ namespace anm2ed::imgui if (propertiesPopup.isJustOpened) ImGui::SetKeyboardFocusHere(); input_text_string("Name", &layer.name); ImGui::SetItemTooltip("Set the item's name."); - combo_strings("Spritesheet", &layer.spritesheetID, document.spritesheetNames); + combo_negative_one_indexed("Spritesheet", &layer.spritesheetID, document.spritesheet.labels); ImGui::SetItemTooltip("Set the layer item's spritesheet."); } ImGui::EndChild(); @@ -143,7 +152,26 @@ namespace anm2ed::imgui if (ImGui::Button(reference == -1 ? "Add" : "Confirm", widgetSize)) { - document.layer_set(layer); + auto add = [&]() + { + auto id = map::next_id_get(anm2.content.layers); + anm2.content.layers[id] = layer; + selection = {id}; + }; + + auto set = [&]() + { + anm2.content.layers[reference] = layer; + selection = {reference}; + }; + + if (reference == -1) + { + DOCUMENT_EDIT(document, "Add Layer", Document::LAYERS, add()); + } + else + DOCUMENT_EDIT(document, "Set Layer Properties", Document::LAYERS, set()); + manager.layer_properties_close(); } diff --git a/src/imgui/window/nulls.cpp b/src/imgui/window/nulls.cpp index 302674c..db776f0 100644 --- a/src/imgui/window/nulls.cpp +++ b/src/imgui/window/nulls.cpp @@ -2,7 +2,11 @@ #include +#include "map_.h" +#include "toast.h" + using namespace anm2ed::resource; +using namespace anm2ed::util; using namespace anm2ed::types; namespace anm2ed::imgui @@ -11,10 +15,10 @@ namespace anm2ed::imgui { auto& document = *manager.get(); auto& anm2 = document.anm2; - auto& reference = document.referenceNull; - auto& unused = document.unusedNullIDs; - auto& hovered = document.hoveredNull; - auto& multiSelect = document.nullMultiSelect; + auto& reference = document.null.reference; + auto& unused = document.null.unused; + auto& hovered = document.null.hovered; + auto& selection = document.null.selection; auto& propertiesPopup = manager.nullPropertiesPopup; hovered = -1; @@ -25,11 +29,11 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##Nulls Child", childSize, true)) { - multiSelect.start(anm2.content.nulls.size()); + selection.start(anm2.content.nulls.size()); for (auto& [id, null] : anm2.content.nulls) { - auto isSelected = multiSelect.contains(id); + auto isSelected = selection.contains(id); auto isReferenced = reference == id; ImGui::PushID(id); @@ -55,14 +59,14 @@ namespace anm2ed::imgui ImGui::PopID(); } - multiSelect.finish(); + selection.finish(); auto copy = [&]() { - if (!multiSelect.empty()) + if (!selection.empty()) { std::string clipboardText{}; - for (auto& id : multiSelect) + for (auto& id : selection) clipboardText += anm2.content.nulls[id].to_string(id); clipboard.set(clipboardText); } @@ -72,8 +76,12 @@ namespace anm2ed::imgui auto paste = [&](merge::Type type) { - auto clipboardText = clipboard.get(); - document.nulls_deserialize(clipboardText, type); + std::string errorString{}; + document.snapshot("Paste Null(s)"); + if (anm2.nulls_deserialize(clipboard.get(), type, &errorString)) + document.change(Document::NULLS); + else + toasts.error(std::format("Failed to deserialize null(s): {}", errorString)); }; if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); @@ -81,25 +89,16 @@ namespace anm2ed::imgui if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) { - ImGui::BeginDisabled(); - ImGui::MenuItem("Cut", settings.shortcutCut.c_str()); - ImGui::EndDisabled(); + ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, false); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, selection.empty() || hovered > -1)) copy(); - ImGui::BeginDisabled(multiSelect.empty() && hovered == -1); - if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); - ImGui::EndDisabled(); - - ImGui::BeginDisabled(clipboard.is_empty()); + if (ImGui::BeginMenu("Paste", !clipboard.is_empty())) { - if (ImGui::BeginMenu("Paste")) - { - if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); - if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); - ImGui::EndMenu(); - } + ImGui::EndMenu(); } - ImGui::EndDisabled(); ImGui::EndPopup(); } @@ -115,7 +114,17 @@ namespace anm2ed::imgui shortcut(settings.shortcutRemove); ImGui::BeginDisabled(unused.empty()); - if (ImGui::Button("Remove Unused", widgetSize)) document.nulls_remove_unused(); + if (ImGui::Button("Remove Unused", widgetSize)) + { + auto remove_unused = [&]() + { + for (auto& id : unused) + anm2.content.nulls.erase(id); + unused.clear(); + }; + + DOCUMENT_EDIT(document, "Remove Unused Events", Document::EVENTS, remove_unused()); + } ImGui::EndDisabled(); set_item_tooltip_shortcut("Remove unused nulls (i.e., ones not used in any animation.)", settings.shortcutRemove); } @@ -143,7 +152,26 @@ namespace anm2ed::imgui if (ImGui::Button(reference == -1 ? "Add" : "Confirm", widgetSize)) { - document.null_set(null); + auto add = [&]() + { + auto id = map::next_id_get(anm2.content.nulls); + anm2.content.nulls[id] = null; + selection = {id}; + }; + + auto set = [&]() + { + anm2.content.nulls[reference] = null; + selection = {reference}; + }; + + if (reference == -1) + { + DOCUMENT_EDIT(document, "Add Null", Document::NULLS, add()); + } + else + DOCUMENT_EDIT(document, "Set Null Properties", Document::NULLS, set()); + manager.null_properties_close(); } diff --git a/src/imgui/window/sounds.cpp b/src/imgui/window/sounds.cpp index c567d62..35f1cf4 100644 --- a/src/imgui/window/sounds.cpp +++ b/src/imgui/window/sounds.cpp @@ -2,6 +2,8 @@ #include +#include "toast.h" + using namespace anm2ed::dialog; using namespace anm2ed::types; using namespace anm2ed::resource; @@ -12,10 +14,10 @@ namespace anm2ed::imgui { auto& document = *manager.get(); auto& anm2 = document.anm2; - auto& reference = document.referenceNull; - auto& unused = document.unusedNullIDs; - auto& hovered = document.hoveredNull; - auto& multiSelect = document.soundMultiSelect; + auto& reference = document.sound.reference; + auto& unused = document.sound.unused; + auto& hovered = document.null.hovered; + auto& selection = document.sound.selection; hovered = -1; @@ -25,24 +27,18 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##Sounds Child", childSize, true)) { - multiSelect.start(anm2.content.sounds.size()); + selection.start(anm2.content.sounds.size()); for (auto& [id, sound] : anm2.content.sounds) { - auto isSelected = multiSelect.contains(id); + auto isSelected = selection.contains(id); auto isReferenced = reference == id; ImGui::PushID(id); ImGui::SetNextItemSelectionUserData(id); if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); - if (ImGui::Selectable(std::format(anm2::SOUND_FORMAT, id, sound.path.string()).c_str(), isSelected)) - sound.audio.play(); - if (ImGui::IsItemHovered()) - { - hovered = id; - if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) - ; - } + if (ImGui::Selectable(sound.path.c_str(), isSelected)) sound.play(); + if (ImGui::IsItemHovered()) hovered = id; if (isReferenced) ImGui::PopFont(); @@ -58,14 +54,14 @@ namespace anm2ed::imgui ImGui::PopID(); } - multiSelect.finish(); + selection.finish(); auto copy = [&]() { - if (!multiSelect.empty()) + if (!selection.empty()) { std::string clipboardText{}; - for (auto& id : multiSelect) + for (auto& id : selection) clipboardText += anm2.content.sounds[id].to_string(id); clipboard.set(clipboardText); } @@ -75,8 +71,12 @@ namespace anm2ed::imgui auto paste = [&](merge::Type type) { - auto clipboardText = clipboard.get(); - document.sounds_deserialize(clipboardText, type); + std::string errorString{}; + document.snapshot("Paste Sound(s)"); + if (anm2.sounds_deserialize(clipboard.get(), document.directory_get(), type, &errorString)) + document.change(Document::SOUNDS); + else + toasts.error(std::format("Failed to deserialize sound(s): {}", errorString)); }; if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); @@ -84,25 +84,16 @@ namespace anm2ed::imgui if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) { - ImGui::BeginDisabled(); - ImGui::MenuItem("Cut", settings.shortcutCut.c_str()); - ImGui::EndDisabled(); + ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, false); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), !selection.empty() && hovered > -1)) copy(); - ImGui::BeginDisabled(multiSelect.empty() && hovered == -1); - if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); - ImGui::EndDisabled(); - - ImGui::BeginDisabled(clipboard.is_empty()); + if (ImGui::BeginMenu("Paste", !clipboard.is_empty())) { - if (ImGui::BeginMenu("Paste")) - { - if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); - if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); - ImGui::EndMenu(); - } + ImGui::EndMenu(); } - ImGui::EndDisabled(); ImGui::EndPopup(); } @@ -119,7 +110,16 @@ namespace anm2ed::imgui imgui::shortcut(settings.shortcutRemove); ImGui::BeginDisabled(unused.empty()); if (ImGui::Button("Remove Unused", widgetSize)) - ; + { + auto remove_unused = [&]() + { + for (auto& id : unused) + anm2.content.sounds.erase(id); + unused.clear(); + }; + + DOCUMENT_EDIT(document, "Remove Unused Sounds", Document::SOUNDS, remove_unused()); + }; ImGui::EndDisabled(); imgui::set_item_tooltip_shortcut("Remove unused sounds (i.e., ones not used in any trigger.)", settings.shortcutRemove); @@ -128,7 +128,20 @@ namespace anm2ed::imgui if (dialog.is_selected(dialog::SOUND_OPEN)) { - document.sound_add(dialog.path); + auto add = [&]() + { + int id{}; + if (anm2.sound_add(document.directory_get(), dialog.path, id)) + { + selection = {id}; + toasts.info(std::format("Initialized sound #{}: {}", id, dialog.path)); + } + else + toasts.error(std::format("Failed to initialize sound: {}", dialog.path)); + }; + + DOCUMENT_EDIT(document, "Add Sound", Document::SOUNDS, add()); + dialog.reset(); } } diff --git a/src/imgui/window/spritesheet_editor.cpp b/src/imgui/window/spritesheet_editor.cpp index 8a0f9de..7d91fb5 100644 --- a/src/imgui/window/spritesheet_editor.cpp +++ b/src/imgui/window/spritesheet_editor.cpp @@ -1,5 +1,8 @@ #include "spritesheet_editor.h" +#include +#include + #include "math_.h" #include "tool.h" #include "types.h" @@ -20,17 +23,20 @@ namespace anm2ed::imgui void SpritesheetEditor::update(Manager& manager, Settings& settings, Resources& resources) { + auto& document = *manager.get(); auto& anm2 = document.anm2; auto& reference = document.reference; - auto& referenceSpritesheet = document.referenceSpritesheet; + auto& referenceSpritesheet = document.spritesheet.reference; auto& pan = document.editorPan; auto& zoom = document.editorZoom; auto& backgroundColor = settings.editorBackgroundColor; auto& gridColor = settings.editorGridColor; auto& gridSize = settings.editorGridSize; auto& gridOffset = settings.editorGridOffset; + auto& toolColor = settings.toolColor; auto& isGrid = settings.editorIsGrid; + auto& isGridSnap = settings.editorIsGridSnap; auto& zoomStep = settings.viewZoomStep; auto& isBorder = settings.editorIsBorder; auto spritesheet = document.spritesheet_get(); @@ -39,6 +45,8 @@ namespace anm2ed::imgui auto& shaderTexture = resources.shaders[shader::TEXTURE]; auto& dashedShader = resources.shaders[shader::DASHED]; + auto center_view = [&]() { pan = -size * 0.5f; }; + if (ImGui::Begin("Spritesheet Editor", &settings.windowIsSpritesheetEditor)) { auto childSize = ImVec2(imgui::row_widget_width_get(3), @@ -47,10 +55,19 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##Grid Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) { ImGui::Checkbox("Grid", &isGrid); + ImGui::SetItemTooltip("Toggle the visibility of the grid."); + ImGui::SameLine(); + ImGui::Checkbox("Snap", &isGridSnap); + ImGui::SetItemTooltip("Cropping will snap points to the grid."); ImGui::SameLine(); ImGui::ColorEdit4("Color", value_ptr(gridColor), ImGuiColorEditFlags_NoInputs); - ImGui::InputInt2("Size", value_ptr(gridSize)); - ImGui::InputInt2("Offset", value_ptr(gridOffset)); + ImGui::SetItemTooltip("Change the grid's color."); + + input_int2_range("Size", gridSize, ivec2(GRID_SIZE_MIN), ivec2(GRID_SIZE_MAX)); + ImGui::SetItemTooltip("Change the size of all cells in the grid."); + + input_int2_range("Offset", gridOffset, ivec2(GRID_OFFSET_MIN), ivec2(GRID_OFFSET_MAX)); + ImGui::SetItemTooltip("Change the offset of the grid."); } ImGui::EndChild(); @@ -59,11 +76,12 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##View Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) { ImGui::InputFloat("Zoom", &zoom, zoomStep, zoomStep, "%.0f%%"); + ImGui::SetItemTooltip("Change the zoom of the editor."); auto widgetSize = ImVec2(imgui::row_widget_width_get(2), 0); imgui::shortcut(settings.shortcutCenterView); - if (ImGui::Button("Center View", widgetSize)) pan = -size * 0.5f; + if (ImGui::Button("Center View", widgetSize)) center_view(); imgui::set_item_tooltip_shortcut("Centers the view.", settings.shortcutCenterView); ImGui::SameLine(); @@ -82,8 +100,10 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##Background Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) { ImGui::ColorEdit4("Background", value_ptr(backgroundColor), ImGuiColorEditFlags_NoInputs); + ImGui::SetItemTooltip("Change the background color."); ImGui::Checkbox("Border", &isBorder); + ImGui::SetItemTooltip("Toggle a border appearing around the spritesheet."); } ImGui::EndChild(); @@ -127,45 +147,85 @@ namespace anm2ed::imgui if (ImGui::IsItemHovered()) { - ImGui::SetKeyboardFocusHere(-1); - - previousMousePos = mousePos; - mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos)); - - auto isMouseClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left); - auto isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); + auto isMouseLeftClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left); + auto isMouseLeftReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Left); + auto isMouseLeftDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); auto isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); + auto isMouseRightClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Right); + auto isMouseRightDown = ImGui::IsMouseDown(ImGuiMouseButton_Right); + auto isMouseRightReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Right); auto mouseDelta = to_ivec2(ImGui::GetIO().MouseDelta); auto mouseWheel = ImGui::GetIO().MouseWheel; - auto& toolColor = settings.toolColor; - auto isZoomIn = imgui::chord_repeating(imgui::string_to_chord(settings.shortcutZoomIn)); - auto isZoomOut = imgui::chord_repeating(imgui::string_to_chord(settings.shortcutZoomOut)); - auto isLeft = imgui::chord_repeating(ImGuiKey_LeftArrow); - auto isRight = imgui::chord_repeating(ImGuiKey_RightArrow); - auto isUp = imgui::chord_repeating(ImGuiKey_UpArrow); - auto isDown = imgui::chord_repeating(ImGuiKey_DownArrow); - auto isMod = ImGui::IsKeyDown(ImGuiMod_Shift); - auto step = isMod ? canvas::STEP_FAST : canvas::STEP; - auto useTool = tool; - auto isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); - auto isMouseReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Left); - auto isLeftPressed = ImGui::IsKeyPressed(ImGuiKey_LeftArrow, false); - auto isRightPressed = ImGui::IsKeyPressed(ImGuiKey_RightArrow, false); - auto isUpPressed = ImGui::IsKeyPressed(ImGuiKey_UpArrow, false); - auto isDownPressed = ImGui::IsKeyPressed(ImGuiKey_DownArrow, false); + auto isMouseClicked = isMouseLeftClicked || isMouseRightClicked; + auto isMouseDown = isMouseLeftDown || isMouseRightDown; + auto isMouseReleased = isMouseLeftReleased || isMouseRightReleased; + + auto isLeftJustPressed = ImGui::IsKeyPressed(ImGuiKey_LeftArrow, false); + auto isRightJustPressed = ImGui::IsKeyPressed(ImGuiKey_RightArrow, false); + auto isUpJustPressed = ImGui::IsKeyPressed(ImGuiKey_UpArrow, false); + auto isDownJustPressed = ImGui::IsKeyPressed(ImGuiKey_DownArrow, false); + auto isLeftPressed = ImGui::IsKeyPressed(ImGuiKey_LeftArrow); + auto isRightPressed = ImGui::IsKeyPressed(ImGuiKey_RightArrow); + auto isUpPressed = ImGui::IsKeyPressed(ImGuiKey_UpArrow); + auto isDownPressed = ImGui::IsKeyPressed(ImGuiKey_DownArrow); + auto isLeftDown = ImGui::IsKeyDown(ImGuiKey_LeftArrow); + auto isRightDown = ImGui::IsKeyDown(ImGuiKey_RightArrow); + auto isUpDown = ImGui::IsKeyDown(ImGuiKey_UpArrow); + auto isDownDown = ImGui::IsKeyDown(ImGuiKey_DownArrow); auto isLeftReleased = ImGui::IsKeyReleased(ImGuiKey_LeftArrow); auto isRightReleased = ImGui::IsKeyReleased(ImGuiKey_RightArrow); auto isUpReleased = ImGui::IsKeyReleased(ImGuiKey_UpArrow); auto isDownReleased = ImGui::IsKeyReleased(ImGuiKey_DownArrow); - auto frame = document.frame_get(); - auto isKeyPressed = isLeftPressed || isRightPressed || isUpPressed || isDownPressed; + auto isKeyJustPressed = isLeftJustPressed || isRightJustPressed || isUpJustPressed || isDownJustPressed; + auto isKeyDown = isLeftDown || isRightDown || isUpDown || isDownDown; auto isKeyReleased = isLeftReleased || isRightReleased || isUpReleased || isDownReleased; - auto isBegin = isMouseClick || isKeyPressed; + + auto isZoomIn = chord_repeating(string_to_chord(settings.shortcutZoomIn)); + auto isZoomOut = chord_repeating(string_to_chord(settings.shortcutZoomOut)); + + auto isBegin = isMouseClicked || isKeyJustPressed; + auto isDuring = isMouseDown || isKeyDown; auto isEnd = isMouseReleased || isKeyReleased; - if (isMouseMiddleDown) useTool = tool::PAN; + auto isMod = ImGui::IsKeyDown(ImGuiMod_Shift); - ImGui::SetMouseCursor(tool::INFO[useTool].cursor); + auto frame = document.frame_get(); + auto useTool = tool; + auto step = isMod ? canvas::STEP_FAST : canvas::STEP; + auto stepX = isGridSnap ? step * gridSize.x : step; + auto stepY = isGridSnap ? step * gridSize.y : step; + previousMousePos = mousePos; + mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos)); + + auto snap_rect = [&](glm::vec2 minPoint, glm::vec2 maxPoint) + { + if (isGridSnap) + { + if (gridSize.x != 0) + { + minPoint.x = std::floor(minPoint.x / gridSize.x) * gridSize.x; + maxPoint.x = std::ceil(maxPoint.x / gridSize.x) * gridSize.x; + } + if (gridSize.y != 0) + { + minPoint.y = std::floor(minPoint.y / gridSize.y) * gridSize.y; + maxPoint.y = std::ceil(maxPoint.y / gridSize.y) * gridSize.y; + } + } + return std::pair{minPoint, maxPoint}; + }; + + if (isMouseMiddleDown) useTool = tool::PAN; + if (tool == tool::MOVE && isMouseRightDown) useTool = tool::CROP; + if (tool == tool::CROP && isMouseRightDown) useTool = tool::MOVE; + if (tool == tool::DRAW && isMouseRightDown) useTool = tool::ERASE; + if (tool == tool::ERASE && isMouseRightDown) useTool = tool::DRAW; + + auto& areaType = tool::INFO[useTool].areaType; + auto cursor = areaType == tool::SPRITESHEET_EDITOR || areaType == tool::ALL ? tool::INFO[useTool].cursor + : ImGuiMouseCursor_NotAllowed; + ImGui::SetMouseCursor(cursor); + ImGui::SetKeyboardFocusHere(-1); switch (useTool) { @@ -176,36 +236,84 @@ namespace anm2ed::imgui if (!frame) break; if (isBegin) document.snapshot("Frame Pivot"); if (isMouseDown) frame->pivot = ivec2(mousePos - frame->crop); - if (isLeft) frame->pivot.x -= step; - if (isRight) frame->pivot.x += step; - if (isUp) frame->pivot.y -= step; - if (isDown) frame->pivot.y += step; + if (isLeftPressed) frame->pivot.x -= step; + if (isRightPressed) frame->pivot.x += step; + if (isUpPressed) frame->pivot.y -= step; + if (isDownPressed) frame->pivot.y += step; + if (isDuring) + { + if (ImGui::BeginTooltip()) + { + auto pivotFormat = math::vec2_format_get(frame->pivot); + auto pivotString = std::format("Pivot: ({}, {})", pivotFormat, pivotFormat); + ImGui::Text(pivotString.c_str(), frame->pivot.x, frame->pivot.y); + ImGui::EndTooltip(); + } + } + if (isEnd) document.change(Document::FRAMES); break; case tool::CROP: if (!frame) break; - if (isBegin) document.snapshot(isMod ? "Frame Size" : "Frame Crop"); - if (isMouseClicked) frame->crop = ivec2(mousePos); - if (isMouseDown) frame->size = ivec2(mousePos - frame->crop); - if (isLeft) isMod ? frame->size.x -= step : frame->crop.x -= step; - if (isRight) isMod ? frame->size.x += step : frame->crop.x += step; - if (isUp) isMod ? frame->size.y -= step : frame->crop.y -= step; - if (isDown) isMod ? frame->size.y += step : frame->crop.y += step; + if (isBegin) document.snapshot("Frame Crop"); + + if (isMouseClicked) + { + cropAnchor = mousePos; + frame->crop = cropAnchor; + frame->size = vec2(); + } + if (isMouseDown) + { + auto [minPoint, maxPoint] = snap_rect(glm::min(cropAnchor, mousePos), glm::max(cropAnchor, mousePos)); + frame->crop = minPoint; + frame->size = maxPoint - minPoint; + } + if (isLeftPressed) frame->crop.x -= stepX; + if (isRightPressed) frame->crop.x += stepX; + if (isUpPressed) frame->crop.y -= stepY; + if (isDownPressed) frame->crop.y += stepY; + if (isDuring) + { + if (!isMouseDown) + { + auto minPoint = glm::min(frame->crop, frame->crop + frame->size); + auto maxPoint = glm::max(frame->crop, frame->crop + frame->size); + frame->crop = minPoint; + frame->size = maxPoint - minPoint; + if (isGridSnap) + { + auto [snapMin, snapMax] = snap_rect(frame->crop, frame->crop + frame->size); + frame->crop = snapMin; + frame->size = snapMax - snapMin; + } + } + if (ImGui::BeginTooltip()) + { + auto cropFormat = math::vec2_format_get(frame->crop); + auto sizeFormat = math::vec2_format_get(frame->size); + auto cropString = std::format("Crop: ({}, {})", cropFormat, cropFormat); + auto sizeString = std::format("Size: ({}, {})", sizeFormat, sizeFormat); + ImGui::Text(cropString.c_str(), frame->crop.x, frame->crop.y); + ImGui::Text(sizeString.c_str(), frame->size.x, frame->size.y); + ImGui::EndTooltip(); + } + } if (isEnd) document.change(Document::FRAMES); break; case tool::DRAW: case tool::ERASE: { if (!spritesheet) break; - auto color = tool == tool::DRAW ? toolColor : vec4(); - if (isMouseClicked) document.snapshot(tool == tool::DRAW ? "Draw" : "Erase"); + auto color = useTool == tool::DRAW ? toolColor : vec4(); + if (isMouseClicked) document.snapshot(useTool == tool::DRAW ? "Draw" : "Erase"); if (isMouseDown) spritesheet->texture.pixel_line(ivec2(previousMousePos), ivec2(mousePos), color); - if (isMouseReleased) document.change(Document::FRAMES); + if (isMouseReleased) document.change(Document::SPRITESHEETS); break; } case tool::COLOR_PICKER: { - if (isMouseDown) + if (isDuring) { auto position = to_vec2(ImGui::GetMousePos()); toolColor = pixel_read(position, {settings.windowSize.x, settings.windowSize.y}); @@ -222,9 +330,26 @@ namespace anm2ed::imgui } if (mouseWheel != 0 || isZoomIn || isZoomOut) - zoom_set(zoom, pan, mousePos, (mouseWheel > 0 || isZoomIn) ? zoomStep : -zoomStep); + { + auto focus = mouseWheel != 0 ? vec2(mousePos) : vec2(); + if (auto spritesheet = document.spritesheet_get(); spritesheet && mouseWheel == 0) + focus = spritesheet->texture.size / 2; + + zoom_set(zoom, pan, focus, (mouseWheel > 0 || isZoomIn) ? zoomStep : -zoomStep); + } } } ImGui::End(); + + if (!document.isSpritesheetEditorSet) + { + size = settings.editorSize; + zoom = settings.editorStartZoom; + center_view(); + document.isSpritesheetEditorSet = true; + } + + settings.editorSize = size; + settings.editorStartZoom = zoom; } } diff --git a/src/imgui/window/spritesheet_editor.h b/src/imgui/window/spritesheet_editor.h index 55db23d..8c992fe 100644 --- a/src/imgui/window/spritesheet_editor.h +++ b/src/imgui/window/spritesheet_editor.h @@ -11,6 +11,7 @@ namespace anm2ed::imgui { glm::vec2 mousePos{}; glm::vec2 previousMousePos{}; + glm::vec2 cropAnchor{}; public: SpritesheetEditor(); diff --git a/src/imgui/window/spritesheets.cpp b/src/imgui/window/spritesheets.cpp index 2d22b13..d271f1c 100644 --- a/src/imgui/window/spritesheets.cpp +++ b/src/imgui/window/spritesheets.cpp @@ -2,6 +2,7 @@ #include +#include "document.h" #include "toast.h" using namespace anm2ed::types; @@ -15,10 +16,10 @@ namespace anm2ed::imgui { auto& document = *manager.get(); auto& anm2 = document.anm2; - auto& multiSelect = document.spritesheetMultiSelect; - auto& unused = document.unusedSpritesheetIDs; - auto& hovered = document.hoveredSpritesheet; - auto& reference = document.referenceSpritesheet; + auto& selection = document.spritesheet.selection; + auto& unused = document.spritesheet.unused; + auto& hovered = document.spritesheet.hovered; + auto& reference = document.spritesheet.reference; hovered = -1; @@ -30,10 +31,10 @@ namespace anm2ed::imgui { auto copy = [&]() { - if (!multiSelect.empty()) + if (!selection.empty()) { std::string clipboardText{}; - for (auto& id : multiSelect) + for (auto& id : selection) clipboardText += anm2.content.spritesheets[id].to_string(id); clipboard.set(clipboardText); } @@ -43,43 +44,38 @@ namespace anm2ed::imgui auto paste = [&](merge::Type type) { - auto clipboardText = clipboard.get(); - document.spritesheets_deserialize(clipboardText, type); + std::string errorString{}; + document.snapshot("Paste Spritesheet(s)"); + if (anm2.spritesheets_deserialize(clipboard.get(), document.directory_get(), type, &errorString)) + document.change(Document::SPRITESHEETS); + else + toasts.error(std::format("Failed to deserialize spritesheet(s): {}", errorString)); }; - if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); - if (imgui::shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) { - ImGui::BeginDisabled(); - ImGui::MenuItem("Cut", settings.shortcutCut.c_str()); - ImGui::EndDisabled(); + ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, true); - ImGui::BeginDisabled(multiSelect.empty() && hovered == -1); - if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); - ImGui::EndDisabled(); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !selection.empty() || hovered > -1)) copy(); - ImGui::BeginDisabled(clipboard.is_empty()); + if (ImGui::BeginMenu("Paste", !clipboard.is_empty())) { - if (ImGui::BeginMenu("Paste")) - { - if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); - if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); - ImGui::EndMenu(); - } + ImGui::EndMenu(); } - ImGui::EndDisabled(); - ImGui::EndPopup(); } ImGui::PopStyleVar(2); }; - auto childSize = imgui::size_without_footer_get(2); + auto childSize = size_without_footer_get(2); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); @@ -89,7 +85,7 @@ namespace anm2ed::imgui ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2()); - multiSelect.start(anm2.content.spritesheets.size()); + selection.start(anm2.content.spritesheets.size()); for (auto& [id, spritesheet] : anm2.content.spritesheets) { @@ -97,7 +93,7 @@ namespace anm2ed::imgui if (ImGui::BeginChild("##Spritesheet Child", spritesheetChildSize, ImGuiChildFlags_Borders)) { - auto isSelected = multiSelect.contains(id); + auto isSelected = selection.contains(id); auto isReferenced = id == reference; auto cursorPos = ImGui::GetCursorPos(); auto& texture = spritesheet.texture.is_valid() ? spritesheet.texture : resources.icons[icon::NONE]; @@ -177,7 +173,7 @@ namespace anm2ed::imgui ImGui::PopID(); } - multiSelect.finish(); + selection.finish(); ImGui::PopStyleVar(2); @@ -185,11 +181,11 @@ namespace anm2ed::imgui } ImGui::EndChild(); - auto rowOneWidgetSize = imgui::widget_size_with_row_get(4); + auto rowOneWidgetSize = widget_size_with_row_get(4); - imgui::shortcut(settings.shortcutAdd); + shortcut(settings.shortcutAdd); if (ImGui::Button("Add", rowOneWidgetSize)) dialog.file_open(dialog::SPRITESHEET_OPEN); - imgui::set_item_tooltip_shortcut("Add a new spritesheet.", settings.shortcutAdd); + set_item_tooltip_shortcut("Add a new spritesheet.", settings.shortcutAdd); if (dialog.is_selected(dialog::SPRITESHEET_OPEN)) { @@ -199,16 +195,21 @@ namespace anm2ed::imgui ImGui::SameLine(); - ImGui::BeginDisabled(multiSelect.empty()); + ImGui::BeginDisabled(selection.empty()); { if (ImGui::Button("Reload", rowOneWidgetSize)) { - for (auto& id : multiSelect) + auto reload = [&]() { - anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; - spritesheet.reload(document.directory_get()); - toasts.info(std::format("Reloaded spritesheet #{}: {}", id, spritesheet.path.string())); - } + for (auto& id : selection) + { + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; + spritesheet.reload(document.directory_get()); + toasts.info(std::format("Reloaded spritesheet #{}: {}", id, spritesheet.path.string())); + } + }; + + DOCUMENT_EDIT(document, "Reload Spritesheet(s)", Document::SPRITESHEETS, reload()); } ImGui::SetItemTooltip("Reloads the selected spritesheets."); } @@ -216,7 +217,7 @@ namespace anm2ed::imgui ImGui::SameLine(); - ImGui::BeginDisabled(multiSelect.size() != 1); + ImGui::BeginDisabled(selection.size() != 1); { if (ImGui::Button("Replace", rowOneWidgetSize)) dialog.file_open(dialog::SPRITESHEET_REPLACE); ImGui::SetItemTooltip("Replace the selected spritesheet with a new one."); @@ -225,10 +226,15 @@ namespace anm2ed::imgui if (dialog.is_selected(dialog::SPRITESHEET_REPLACE)) { - auto& id = *multiSelect.begin(); - anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; - spritesheet = anm2::Spritesheet(document.directory_get(), dialog.path); - toasts.info(std::format("Replaced spritesheet #{}: {}", id, spritesheet.path.string())); + auto replace = [&]() + { + auto& id = *selection.begin(); + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; + spritesheet = anm2::Spritesheet(document.directory_get(), dialog.path); + toasts.info(std::format("Replaced spritesheet #{}: {}", id, spritesheet.path.string())); + }; + + DOCUMENT_EDIT(document, "Replace Spritesheet", Document::SPRITESHEETS, replace()); dialog.reset(); } @@ -236,50 +242,54 @@ namespace anm2ed::imgui ImGui::BeginDisabled(unused.empty()); { - imgui::shortcut(settings.shortcutRemove); + shortcut(settings.shortcutRemove); if (ImGui::Button("Remove Unused", rowOneWidgetSize)) { - for (auto& id : unused) + auto remove_unused = [&]() { - anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; - toasts.info(std::format("Removed spritesheet #{}: {}", id, spritesheet.path.string())); - anm2.spritesheet_remove(id); - } - unused.clear(); - document.change(Document::SPRITESHEETS); + for (auto& id : unused) + { + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; + toasts.info(std::format("Removed spritesheet #{}: {}", id, spritesheet.path.string())); + anm2.content.spritesheets.erase(id); + } + unused.clear(); + }; + + DOCUMENT_EDIT(document, "Remove Unused Spritesheets", Document::SPRITESHEETS, remove_unused()); } - imgui::set_item_tooltip_shortcut("Remove all unused spritesheets (i.e., not used in any layer.).", - settings.shortcutRemove); + set_item_tooltip_shortcut("Remove all unused spritesheets (i.e., not used in any layer.).", + settings.shortcutRemove); } ImGui::EndDisabled(); - auto rowTwoWidgetSize = imgui::widget_size_with_row_get(3); + auto rowTwoWidgetSize = widget_size_with_row_get(3); - imgui::shortcut(settings.shortcutSelectAll); - ImGui::BeginDisabled(multiSelect.size() == anm2.content.spritesheets.size()); + shortcut(settings.shortcutSelectAll); + ImGui::BeginDisabled(selection.size() == anm2.content.spritesheets.size()); { if (ImGui::Button("Select All", rowTwoWidgetSize)) for (auto& id : anm2.content.spritesheets | std::views::keys) - multiSelect.insert(id); + selection.insert(id); } ImGui::EndDisabled(); - imgui::set_item_tooltip_shortcut("Select all spritesheets.", settings.shortcutSelectAll); + set_item_tooltip_shortcut("Select all spritesheets.", settings.shortcutSelectAll); ImGui::SameLine(); - imgui::shortcut(settings.shortcutSelectNone); - ImGui::BeginDisabled(multiSelect.empty()); - if (ImGui::Button("Select None", rowTwoWidgetSize)) multiSelect.clear(); - imgui::set_item_tooltip_shortcut("Unselect all spritesheets.", settings.shortcutSelectNone); + shortcut(settings.shortcutSelectNone); + ImGui::BeginDisabled(selection.empty()); + if (ImGui::Button("Select None", rowTwoWidgetSize)) selection.clear(); + set_item_tooltip_shortcut("Unselect all spritesheets.", settings.shortcutSelectNone); ImGui::EndDisabled(); ImGui::SameLine(); - ImGui::BeginDisabled(multiSelect.empty()); + ImGui::BeginDisabled(selection.empty()); { if (ImGui::Button("Save", rowTwoWidgetSize)) { - for (auto& id : multiSelect) + for (auto& id : selection) { anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; if (spritesheet.save(document.directory_get())) diff --git a/src/imgui/window/timeline.cpp b/src/imgui/window/timeline.cpp index f845b1a..68b33c5 100644 --- a/src/imgui/window/timeline.cpp +++ b/src/imgui/window/timeline.cpp @@ -4,6 +4,8 @@ #include +#include "toast.h" + using namespace anm2ed::resource; using namespace anm2ed::types; using namespace glm; @@ -48,41 +50,59 @@ namespace anm2ed::imgui void Timeline::context_menu(Document& document, Settings& settings, Clipboard& clipboard) { auto& hoveredFrame = document.hoveredFrame; + auto& anm2 = document.anm2; + auto& reference = document.reference; ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); auto copy = [&]() { - if (auto frame = document.anm2.frame_get(hoveredFrame)) - { - clipboard.set(frame->to_string(hoveredFrame.itemType)); - } + if (auto frame = anm2.frame_get(hoveredFrame)) clipboard.set(frame->to_string(hoveredFrame.itemType)); }; auto cut = [&]() { copy(); - document.frames_delete(document.item_get()); + auto frames_delete = [&]() + { + if (auto item = anm2.item_get(reference); item) + { + item->frames.erase(item->frames.begin() + reference.frameIndex); + reference.frameIndex = glm::max(-1, --reference.frameIndex); + } + }; + + DOCUMENT_EDIT(document, "Cut Frame(s)", Document::FRAMES, frames_delete()); }; - auto paste = [&]() { document.frames_deserialize(clipboard.get()); }; + auto paste = [&]() + { + if (auto item = document.item_get()) + { + document.snapshot("Paste Frame(s)"); + std::set indices{}; + std::string errorString{}; + auto start = reference.frameIndex + 1; + if (item->frames_deserialize(clipboard.get(), reference.itemType, start, indices, &errorString)) + document.change(Document::FRAMES); + else + toasts.error(std::format("Failed to deserialize frame(s): {}", errorString)); + } + else + toasts.error(std::format("Failed to deserialize frame(s): select an item first!")); + }; - if (imgui::shortcut(settings.shortcutCut, shortcut::FOCUSED)) cut(); - if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); - if (imgui::shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(); + if (shortcut(settings.shortcutCut, shortcut::FOCUSED)) cut(); + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(); if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) { - ImGui::BeginDisabled(hoveredFrame == anm2::REFERENCE_DEFAULT); - if (ImGui::MenuItem("Cut", settings.shortcutCut.c_str())) cut(); - if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str())) copy(); - ImGui::EndDisabled(); - - ImGui::BeginDisabled(clipboard.is_empty()); - if (ImGui::MenuItem("Paste")) paste(); - ImGui::EndDisabled(); + if (ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, hoveredFrame != anm2::Reference{})) cut(); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, hoveredFrame != anm2::Reference{})) copy(); + if (ImGui::MenuItem("Paste", nullptr, false, !clipboard.is_empty())) paste(); ImGui::EndPopup(); } @@ -165,7 +185,7 @@ namespace anm2ed::imgui if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) reference = itemReference; } - ImGui::Image(resources.icons[icon].id, imgui::icon_size_get()); + ImGui::Image(resources.icons[icon].id, icon_size_get()); ImGui::SameLine(); ImGui::TextUnformatted(label.c_str()); @@ -181,8 +201,8 @@ namespace anm2ed::imgui (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); int visibleIcon = isVisible ? icon::VISIBLE : icon::INVISIBLE; - if (ImGui::ImageButton("##Visible Toggle", resources.icons[visibleIcon].id, imgui::icon_size_get())) - document.item_visible_toggle(item); + if (ImGui::ImageButton("##Visible Toggle", resources.icons[visibleIcon].id, icon_size_get())) + DOCUMENT_EDIT(document, "Item Visibility", Document::FRAMES, isVisible = !isVisible); ImGui::SetItemTooltip(isVisible ? "The item is shown. Press to hide." : "The item is hidden. Press to show."); if (type == anm2::NULL_) @@ -194,8 +214,8 @@ namespace anm2ed::imgui ImGui::SetCursorPos( ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x, (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); - if (ImGui::ImageButton("##Rect Toggle", resources.icons[rectIcon].id, imgui::icon_size_get())) - document.null_rect_toggle(null); + if (ImGui::ImageButton("##Rect Toggle", resources.icons[rectIcon].id, icon_size_get())) + DOCUMENT_EDIT(document, "Null Rect", Document::FRAMES, null.isShowRect = !null.isShowRect); ImGui::SetItemTooltip(isShowRect ? "The null's rect is shown. Press to hide." : "The null's rect is hidden. Press to show."); } @@ -217,7 +237,7 @@ namespace anm2ed::imgui ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); auto unusedIcon = isShowUnused ? icon::SHOW_UNUSED : icon::HIDE_UNUSED; - if (ImGui::ImageButton("##Unused Toggle", resources.icons[unusedIcon].id, imgui::icon_size_get())) + if (ImGui::ImageButton("##Unused Toggle", resources.icons[unusedIcon].id, icon_size_get())) isShowUnused = !isShowUnused; ImGui::SetItemTooltip(isShowUnused ? "Unused layers/nulls are shown. Press to hide." : "Unused layers/nulls are hidden. Press to show."); @@ -229,7 +249,7 @@ namespace anm2ed::imgui ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x, (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); - if (ImGui::ImageButton("##Layers Toggle", resources.icons[layersIcon].id, imgui::icon_size_get())) + if (ImGui::ImageButton("##Layers Toggle", resources.icons[layersIcon].id, icon_size_get())) isOnlyShowLayers = !isOnlyShowLayers; ImGui::SetItemTooltip(isOnlyShowLayers ? "Only layers are visible. Press to show all items." : "All items are visible. Press to only show layers."); @@ -329,21 +349,30 @@ namespace anm2ed::imgui ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + style.WindowPadding.x, ImGui::GetCursorPosY())); - auto widgetSize = imgui::widget_size_with_row_get(2, ImGui::GetContentRegionAvail().x - style.WindowPadding.x); + auto widgetSize = widget_size_with_row_get(2, ImGui::GetContentRegionAvail().x - style.WindowPadding.x); ImGui::BeginDisabled(!animation); { - imgui::shortcut(settings.shortcutAdd); + shortcut(settings.shortcutAdd); if (ImGui::Button("Add", widgetSize)) propertiesPopup.open(); - imgui::set_item_tooltip_shortcut("Add a new item to the animation.", settings.shortcutAdd); + set_item_tooltip_shortcut("Add a new item to the animation.", settings.shortcutAdd); ImGui::SameLine(); ImGui::BeginDisabled(!document.item_get() && reference.itemType != anm2::LAYER && reference.itemType != anm2::NULL_); { - imgui::shortcut(settings.shortcutRemove); - if (ImGui::Button("Remove", widgetSize)) document.item_remove(animation); - imgui::set_item_tooltip_shortcut("Remove the selected items from the animation.", settings.shortcutRemove); + shortcut(settings.shortcutRemove); + if (ImGui::Button("Remove", widgetSize)) + { + auto remove = [&]() + { + animation->item_remove(reference.itemType, reference.itemID); + reference = {reference.animationIndex}; + }; + + DOCUMENT_EDIT(document, "Remove Item", Document::ITEMS, remove()); + } + set_item_tooltip_shortcut("Remove the selected items from the animation.", settings.shortcutRemove); } ImGui::EndDisabled(); } @@ -534,11 +563,12 @@ namespace anm2ed::imgui if (ImGui::Button("##Frame Button", size)) { if (type != anm2::TRIGGER && ImGui::IsKeyDown(ImGuiMod_Alt)) - document.frame_is_interpolated_set(&frame, !frame.isInterpolated); + DOCUMENT_EDIT(document, "Frame Interpolation", Document::FRAMES, + frame.isInterpolated = !frame.isInterpolated); if (type == anm2::LAYER) { - document.referenceSpritesheet = anm2.content.layers[id].spritesheetID; - document.layersMultiSelect = {id}; + document.spritesheet.reference = anm2.content.layers[id].spritesheetID; + document.layer.selection = {id}; } reference = frameReference; reference.frameTime = frameTime; @@ -575,8 +605,8 @@ namespace anm2ed::imgui Clipboard& clipboard) { auto& anm2 = document.anm2; + auto& reference = document.reference; auto& playback = document.playback; - auto& hoveredFrame = document.hoveredFrame; auto itemsChildWidth = ImGui::GetTextLineHeightWithSpacing() * 15; @@ -697,16 +727,16 @@ namespace anm2ed::imgui ImGui::SetCursorPos( ImVec2(ImGui::GetStyle().WindowPadding.x, ImGui::GetCursorPos().y + ImGui::GetStyle().ItemSpacing.y)); - auto widgetSize = imgui::widget_size_with_row_get(10); + auto widgetSize = widget_size_with_row_get(10); ImGui::BeginDisabled(!animation); { auto label = playback.isPlaying ? "Pause" : "Play"; auto tooltip = playback.isPlaying ? "Pause the animation." : "Play the animation."; - imgui::shortcut(settings.shortcutPlayPause); + shortcut(settings.shortcutPlayPause); if (ImGui::Button(label, widgetSize)) playback.toggle(); - imgui::set_item_tooltip_shortcut(tooltip, settings.shortcutPlayPause); + set_item_tooltip_shortcut(tooltip, settings.shortcutPlayPause); ImGui::SameLine(); @@ -714,17 +744,45 @@ namespace anm2ed::imgui ImGui::BeginDisabled(!item); { - imgui::shortcut(settings.shortcutAdd); - if (ImGui::Button("Insert Frame", widgetSize)) document.frames_add(item); - imgui::set_item_tooltip_shortcut("Insert a frame, based on the current selection.", settings.shortcutAdd); + shortcut(settings.shortcutAdd); + if (ImGui::Button("Insert Frame", widgetSize)) + { + auto insert_frame = [&]() + { + auto frame = document.frame_get(); + if (frame) + { + item->frames.insert(item->frames.begin() + reference.frameIndex, *frame); + reference.frameIndex++; + } + else if (!item->frames.empty()) + { + auto frame = item->frames.back(); + item->frames.emplace_back(frame); + reference.frameIndex = item->frames.size() - 1; + } + }; + + DOCUMENT_EDIT(document, "Insert Frame", Document::FRAMES, insert_frame()); + } + set_item_tooltip_shortcut("Insert a frame, based on the current selection.", settings.shortcutAdd); ImGui::SameLine(); ImGui::BeginDisabled(!document.frame_get()); { - imgui::shortcut(settings.shortcutRemove); - if (ImGui::Button("Delete Frame", widgetSize)) document.frames_delete(item); - imgui::set_item_tooltip_shortcut("Delete the selected frames.", settings.shortcutRemove); + shortcut(settings.shortcutRemove); + if (ImGui::Button("Delete Frame", widgetSize)) + { + auto delete_frame = [&]() + { + item->frames.erase(item->frames.begin() + reference.frameIndex); + reference.frameIndex = glm::max(-1, --reference.frameIndex); + }; + + DOCUMENT_EDIT(document, "Delete Frame(s)", Document::FRAMES, delete_frame()); + } + set_item_tooltip_shortcut("Delete the selected frames.", settings.shortcutRemove); ImGui::SameLine(); @@ -743,8 +801,8 @@ namespace anm2ed::imgui ImGui::SameLine(); ImGui::SetNextItemWidth(widgetSize.x); - ImGui::InputInt("Animation Length", animation ? &animation->frameNum : &dummy_value(), imgui::STEP, - imgui::STEP_FAST, !animation ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); + ImGui::InputInt("Animation Length", animation ? &animation->frameNum : &dummy_value(), STEP, STEP_FAST, + !animation ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); if (animation) animation->frameNum = clamp(animation->frameNum, anm2::FRAME_NUM_MIN, anm2::FRAME_NUM_MAX); ImGui::SetItemTooltip("Set the animation's length."); @@ -766,7 +824,7 @@ namespace anm2ed::imgui ImGui::SameLine(); ImGui::SetNextItemWidth(widgetSize.x); - imgui::input_text_string("Author", &anm2.info.createdBy); + input_text_string("Author", &anm2.info.createdBy); ImGui::SetItemTooltip("Set the author of the document."); ImGui::SameLine(); @@ -818,8 +876,8 @@ namespace anm2ed::imgui isUnusedItemsSet = true; } - auto footerSize = imgui::footer_size_get(); - auto optionsSize = imgui::child_size_get(11); + auto footerSize = footer_size_get(); + auto optionsSize = child_size_get(11); auto itemsSize = ImVec2(0, ImGui::GetContentRegionAvail().y - (optionsSize.y + footerSize.y + ImGui::GetStyle().ItemSpacing.y * 4)); if (ImGui::BeginChild("Options", optionsSize, ImGuiChildFlags_Borders)) @@ -890,12 +948,11 @@ namespace anm2ed::imgui ImGui::BeginDisabled(source == source::EXISTING); { - imgui::input_text_string("Name", &addItemName); + input_text_string("Name", &addItemName); ImGui::SetItemTooltip("Set the item's name."); ImGui::BeginDisabled(type != anm2::LAYER); { - auto spritesheets = anm2.spritesheet_names_get(); - imgui::combo_strings("Spritesheet", &addItemSpritesheetID, spritesheets); + combo_negative_one_indexed("Spritesheet", &addItemSpritesheetID, document.spritesheet.labels); ImGui::SetItemTooltip("Set the layer item's spritesheet."); } ImGui::EndDisabled(); @@ -934,11 +991,24 @@ namespace anm2ed::imgui } ImGui::EndChild(); - auto widgetSize = imgui::widget_size_with_row_get(2); + auto widgetSize = widget_size_with_row_get(2); if (ImGui::Button("Add", widgetSize)) { - document.item_add((anm2::Type)type, addItemID, addItemName, (locale::Type)locale, addItemSpritesheetID); + anm2::Reference addReference{}; + + document.snapshot("Add Item"); + if (type == anm2::LAYER) + addReference = anm2.layer_animation_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName, + addItemSpritesheetID - 1, (locale::Type)locale); + else if (type == anm2::NULL_) + addReference = anm2.null_animation_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName, + (locale::Type)locale); + + document.change(Document::ITEMS); + + reference = addReference; + item_properties_close(); } ImGui::SetItemTooltip("Add the item, with the settings specified."); @@ -961,7 +1031,7 @@ namespace anm2ed::imgui auto frame = document.frame_get(); - imgui::input_int_range("Interval", interval, anm2::FRAME_DELAY_MIN, frame ? frame->delay : anm2::FRAME_DELAY_MIN); + input_int_range("Interval", interval, anm2::FRAME_DELAY_MIN, frame ? frame->delay : anm2::FRAME_DELAY_MIN); ImGui::SetItemTooltip("Set the maximum delay of each frame that will be baked."); ImGui::Checkbox("Round Rotation", &isRoundRotation); @@ -970,11 +1040,13 @@ namespace anm2ed::imgui ImGui::Checkbox("Round Scale", &isRoundScale); ImGui::SetItemTooltip("Scale will be rounded to the nearest whole number."); - auto widgetSize = imgui::widget_size_with_row_get(2); + auto widgetSize = widget_size_with_row_get(2); if (ImGui::Button("Bake", widgetSize)) { - document.frames_bake(interval, isRoundScale, isRoundRotation); + if (auto item = document.item_get()) + DOCUMENT_EDIT(document, "Bake Frames", Document::FRAMES, + item->frames_bake(reference.frameIndex, interval, isRoundScale, isRoundRotation)); bakePopup.close(); } ImGui::SetItemTooltip("Bake the selected frame(s) with the options selected."); @@ -1009,24 +1081,41 @@ namespace anm2ed::imgui popups(document, animation, settings); - if (imgui::shortcut(settings.shortcutPlayPause, shortcut::GLOBAL)) playback.toggle(); + if (shortcut(settings.shortcutPlayPause, shortcut::GLOBAL)) playback.toggle(); if (animation) { - if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutPreviousFrame))) + if (chord_repeating(string_to_chord(settings.shortcutPreviousFrame))) { playback.decrement(settings.playbackIsClampPlayhead ? animation->frameNum : anm2::FRAME_NUM_MAX); reference.frameTime = playback.time; } - if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutNextFrame))) + if (chord_repeating(string_to_chord(settings.shortcutNextFrame))) { playback.increment(settings.playbackIsClampPlayhead ? animation->frameNum : anm2::FRAME_NUM_MAX); reference.frameTime = playback.time; } } - if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutShortenFrame))) document.frame_shorten(); - if (imgui::chord_repeating(imgui::string_to_chord(settings.shortcutExtendFrame))) document.frame_extend(); + if (ImGui::IsKeyChordPressed(string_to_chord(settings.shortcutShortenFrame))) document.snapshot("Shorten Frame"); + if (chord_repeating(string_to_chord(settings.shortcutShortenFrame))) + { + if (auto frame = document.frame_get()) + { + frame->shorten(); + document.change(Document::FRAMES); + } + } + + if (ImGui::IsKeyChordPressed(string_to_chord(settings.shortcutExtendFrame))) document.snapshot("Extend Frame"); + if (chord_repeating(string_to_chord(settings.shortcutExtendFrame))) + { + if (auto frame = document.frame_get()) + { + frame->extend(); + document.change(Document::FRAMES); + } + } } } \ No newline at end of file diff --git a/src/imgui/window/timeline.h b/src/imgui/window/timeline.h index 3c0560d..94a9552 100644 --- a/src/imgui/window/timeline.h +++ b/src/imgui/window/timeline.h @@ -16,9 +16,9 @@ namespace anm2ed::imgui PopupHelper propertiesPopup{PopupHelper("Item Properties", POPUP_NORMAL)}; PopupHelper bakePopup{PopupHelper("Bake", POPUP_TO_CONTENT)}; std::string addItemName{}; - int addItemSpritesheetID{}; bool addItemIsRect{}; int addItemID{-1}; + int addItemSpritesheetID{-1}; bool isUnusedItemsSet{}; std::set unusedItems{}; glm::vec2 scroll{}; diff --git a/src/imgui/window/welcome.cpp b/src/imgui/window/welcome.cpp index 38c69c2..b9d997f 100644 --- a/src/imgui/window/welcome.cpp +++ b/src/imgui/window/welcome.cpp @@ -31,12 +31,10 @@ namespace anm2ed::imgui auto widgetSize = widget_size_with_row_get(2); if (ImGui::Button("New", widgetSize)) dialog.file_open(dialog::ANM2_NEW); // handled in taskbar.cpp - ImGui::SameLine(); - if (ImGui::Button("Open", widgetSize)) dialog.file_open(dialog::ANM2_OPEN); // handled in taskbar.cpp - if (ImGui::BeginChild("##Recent Files Child", ImVec2(), ImGuiChildFlags_Borders)) + if (ImGui::BeginChild("##Recent Files Child", {}, ImGuiChildFlags_Borders)) { for (auto [i, file] : std::views::enumerate(manager.recentFiles)) { diff --git a/src/manager.cpp b/src/manager.cpp index 7d47128..086d080 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -90,20 +90,23 @@ namespace anm2ed void Manager::autosave(Document& document) { - auto filename = "." + document.filename_get().string() + ".autosave"; - auto path = document.directory_get() / filename; std::string errorString{}; - document.autosave(path, &errorString); + auto autosavePath = document.autosave_path_get(); + document.autosave(&errorString); - autosaveFiles.erase(std::remove(autosaveFiles.begin(), autosaveFiles.end(), path), autosaveFiles.end()); - autosaveFiles.insert(autosaveFiles.begin(), path); + autosaveFiles.erase(std::remove(autosaveFiles.begin(), autosaveFiles.end(), autosavePath), autosaveFiles.end()); + autosaveFiles.insert(autosaveFiles.begin(), autosavePath); autosave_files_write(); } void Manager::close(int index) { - if (index < 0 || index >= (int)documents.size()) return; + if (!vector::in_bounds(documents, index)) return; + + autosaveFiles.erase(std::remove(autosaveFiles.begin(), autosaveFiles.end(), get()->autosave_path_get()), + autosaveFiles.end()); + autosave_files_write(); documents.erase(documents.begin() + index); @@ -146,7 +149,7 @@ namespace anm2ed else editLayer = document->anm2.content.layers.at(id); - document->referenceLayer = id; + document->layer.reference = id; layerPropertiesPopup.open(); } @@ -177,7 +180,7 @@ namespace anm2ed else editNull = document->anm2.content.nulls.at(id); - document->referenceNull = id; + document->null.reference = id; nullPropertiesPopup.open(); } diff --git a/src/manager.h b/src/manager.h index 549de70..485b309 100644 --- a/src/manager.h +++ b/src/manager.h @@ -22,8 +22,10 @@ namespace anm2ed int pendingSelected{-1}; bool isRecording{}; + bool isRecordingStart{}; int recordingStart{}; int recordingEnd{}; + bool isRecordingRange{}; anm2::Layer editLayer{}; imgui::PopupHelper layerPropertiesPopup{imgui::PopupHelper("Layer Properties", imgui::POPUP_SMALL_NO_HEIGHT)}; diff --git a/src/render.h b/src/render.h index 6e9cdfb..22f42d8 100644 --- a/src/render.h +++ b/src/render.h @@ -5,21 +5,27 @@ namespace anm2ed::render { #define RENDER_LIST \ - X(PNGS, "PNGs") \ - X(GIF, "GIF") \ - X(WEBM, "WebM") \ - X(MP4, "MP4") + X(PNGS, "PNGs", "") \ + X(GIF, "GIF", ".gif") \ + X(WEBM, "WebM", ".webm") \ + X(MP4, "MP4", ".mp4") enum Type { -#define X(symbol, string) symbol, +#define X(symbol, string, extension) symbol, RENDER_LIST #undef X COUNT }; constexpr const char* STRINGS[] = { -#define X(symbol, string) string, +#define X(symbol, string, extension) string, + RENDER_LIST +#undef X + }; + + constexpr const char* EXTENSIONS[] = { +#define X(symbol, string, extension) extension, RENDER_LIST #undef X }; diff --git a/src/resource/audio.cpp b/src/resource/audio.cpp index 11979f2..af04685 100644 --- a/src/resource/audio.cpp +++ b/src/resource/audio.cpp @@ -22,9 +22,9 @@ namespace anm2ed::resource internal = nullptr; } - void Audio::play() + void Audio::play(MIX_Mixer* mixer) { - MIX_PlayAudio(mixer_get(), internal); + MIX_PlayAudio(mixer ? mixer : mixer_get(), internal); } Audio::Audio(Audio&& other) noexcept @@ -46,4 +46,9 @@ namespace anm2ed::resource { unload(); } + + bool Audio::is_valid() + { + return internal; + } } diff --git a/src/resource/audio.h b/src/resource/audio.h index 6c2cc52..569ae8a 100644 --- a/src/resource/audio.h +++ b/src/resource/audio.h @@ -19,6 +19,7 @@ namespace anm2ed::resource Audio(const Audio&) = delete; Audio& operator=(const Audio&) = delete; - void play(); + bool is_valid(); + void play(MIX_Mixer* = nullptr); }; } diff --git a/src/resource/icon.h b/src/resource/icon.h index 147a884..4101ddf 100644 --- a/src/resource/icon.h +++ b/src/resource/icon.h @@ -129,6 +129,10 @@ namespace anm2ed::resource::icon )"; + constexpr auto TARGET_ALT_DATA = R"( + + )"; + constexpr auto INTERPOLATED_DATA = R"( )"; @@ -185,7 +189,8 @@ namespace anm2ed::resource::icon X(PLAYHEAD, PLAYHEAD_DATA, SIZE_NORMAL) \ X(PIVOT, PIVOT_DATA, SIZE_NORMAL) \ X(POINT, UNINTERPOLATED_DATA, SIZE_NORMAL) \ - X(TARGET, TARGET_DATA, SIZE_HUGE) + X(TARGET, TARGET_DATA, SIZE_HUGE) \ + X(TARGET_ALT, TARGET_ALT_DATA, SIZE_HUGE) enum Type { diff --git a/src/settings.h b/src/settings.h index 61eba79..e25bfd8 100644 --- a/src/settings.h +++ b/src/settings.h @@ -43,11 +43,14 @@ namespace anm2ed /* Symbol / Name / String / Type / Default */ \ X(WINDOW_SIZE, windowSize, "Window Size", IVEC2_WH, {1600, 900}) \ X(IS_VSYNC, isVsync, "Vsync", BOOL, true) \ - X(DISPLAY_SCALE, displayScale, "Display Scale", FLOAT, 1.0f) \ + X(UI_SCALE, uiScale, "UI Scale", FLOAT, 1.0f) \ \ X(FILE_IS_AUTOSAVE, fileIsAutosave, "Autosave", BOOL, true) \ X(FILE_AUTOSAVE_TIME, fileAutosaveTime, "Autosave Time", INT, 1) \ \ + X(KEYBOARD_REPEAT_DELAY, keyboardRepeatDelay, "Repeat Delay", FLOAT, 0.300f) \ + X(KEYBOARD_REPEAT_RATE, keyboardRepeatRate, "Repeat Rate", FLOAT, 0.050f) \ + \ X(VIEW_ZOOM_STEP, viewZoomStep, "Zoom Step", FLOAT, 50.0f) \ \ X(PLAYBACK_IS_LOOP, playbackIsLoop, "Loop", BOOL, true) \ @@ -87,8 +90,7 @@ namespace anm2ed X(PREVIEW_IS_BORDER, previewIsBorder, "Border", BOOL, false) \ X(PREVIEW_IS_ALT_ICONS, previewIsAltIcons, "Alt Icons", BOOL, false) \ X(PREVIEW_OVERLAY_TRANSPARENCY, previewOverlayTransparency, "Alpha", FLOAT, 255) \ - X(PREVIEW_ZOOM, previewZoom, "Zoom", FLOAT, 200.0f) \ - X(PREVIEW_PAN, previewPan, "Pan", VEC2, {}) \ + X(PREVIEW_START_ZOOM, previewStartZoom, "Start Zoom", FLOAT, 200.0f) \ X(PREVIEW_GRID_SIZE, previewGridSize, "Size", IVEC2, {32, 32}) \ X(PREVIEW_GRID_OFFSET, previewGridOffset, "Offset", IVEC2, {}) \ X(PREVIEW_GRID_COLOR, previewGridColor, "Color", VEC4, {1.0f, 1.0f, 1.0f, 0.125f}) \ @@ -109,9 +111,9 @@ namespace anm2ed X(EDITOR_IS_GRID, editorIsGrid, "Grid", BOOL, true) \ X(EDITOR_IS_GRID_SNAP, editorIsGridSnap, "Snap", BOOL, true) \ X(EDITOR_IS_BORDER, editorIsBorder, "Border", BOOL, true) \ - X(EDITOR_ZOOM, editorZoom, "Zoom", FLOAT, 200.0f) \ - X(EDITOR_PAN, editorPan, "Pan", VEC2, {0.0, 0.0}) \ - X(EDITOR_GRID_SIZE, editorGridSize, "Size", IVEC2, {32, 32}) \ + X(EDITOR_START_ZOOM, editorStartZoom, "Zoom", FLOAT, 200.0f) \ + X(EDITOR_SIZE, editorSize, "Size", IVEC2_WH, {1200, 600}) \ + X(EDITOR_GRID_SIZE, editorGridSize, "Grid Size", IVEC2, {32, 32}) \ X(EDITOR_GRID_OFFSET, editorGridOffset, "Offset", IVEC2, {32, 32}) \ X(EDITOR_GRID_COLOR, editorGridColor, "Color", VEC4, {1.0, 1.0, 1.0, 0.125}) \ X(EDITOR_BACKGROUND_COLOR, editorBackgroundColor, "Background Color", VEC4, {0.113, 0.184, 0.286, 1.0}) \ @@ -143,9 +145,7 @@ namespace anm2ed X(RENDER_TYPE, renderType, "Output", INT, render::PNGS) \ X(RENDER_PATH, renderPath, "Path", STRING, ".") \ X(RENDER_FORMAT, renderFormat, "Format", STRING, "{}.png") \ - X(RENDER_IS_USE_ANIMATION_BOUNDS, renderIsUseAnimationBounds, "Use Animation Bounds", BOOL, true) \ - X(RENDER_IS_TRANSPARENT, renderIsTransparent, "Transparent", BOOL, true) \ - X(RENDER_IS_RANGE, renderIsRange, "Range", BOOL, false) \ + X(RENDER_IS_RAW_ANIMATION, renderIsRawAnimation, "Raw Animation", BOOL, true) \ X(RENDER_SCALE, renderScale, "Scale", FLOAT, 1.0f) \ X(RENDER_FFMPEG_PATH, renderFFmpegPath, "FFmpeg Path", STRING, FFMPEG_PATH_DEFAULT) diff --git a/src/snapshots.cpp b/src/snapshots.cpp index 304624e..582b8ba 100644 --- a/src/snapshots.cpp +++ b/src/snapshots.cpp @@ -9,7 +9,7 @@ namespace anm2ed return top == 0; } - void SnapshotStack::push(Snapshot& snapshot) + void SnapshotStack::push(const Snapshot& snapshot) { if (top >= MAX) { @@ -31,34 +31,27 @@ namespace anm2ed top = 0; } - void Snapshots::push(const anm2::Anm2& anm2, anm2::Reference reference, const std::string& message) + void Snapshots::push(const Snapshot& snapshot) { - Snapshot snapshot = {anm2, reference, message}; undoStack.push(snapshot); redoStack.clear(); } - void Snapshots::undo(anm2::Anm2& anm2, anm2::Reference& reference, std::string& message) + void Snapshots::undo() { - if (auto current = undoStack.pop()) + if (auto snapshot = undoStack.pop()) { - Snapshot snapshot = {anm2, reference, message}; - redoStack.push(snapshot); - anm2 = current->anm2; - reference = current->reference; - message = current->message; + redoStack.push(current); + current = *snapshot; } } - void Snapshots::redo(anm2::Anm2& anm2, anm2::Reference& reference, std::string& message) + void Snapshots::redo() { - if (auto current = redoStack.pop()) + if (auto snapshot = redoStack.pop()) { - Snapshot snapshot = {anm2, reference, message}; - undoStack.push(snapshot); - anm2 = current->anm2; - reference = current->reference; - message = current->message; + undoStack.push(current); + current = *snapshot; } } diff --git a/src/snapshots.h b/src/snapshots.h index a18d4a7..3fefd20 100644 --- a/src/snapshots.h +++ b/src/snapshots.h @@ -1,6 +1,8 @@ #pragma once #include "anm2/anm2.h" +#include "playback.h" +#include "storage.h" namespace anm2ed::snapshots { @@ -15,6 +17,14 @@ namespace anm2ed public: anm2::Anm2 anm2{}; anm2::Reference reference{}; + Playback playback{}; + Storage animation{}; + Storage merge{}; + Storage event{}; + Storage layer{}; + Storage null{}; + Storage sound{}; + Storage spritesheet{}; std::string message = snapshots::ACTION; }; @@ -25,7 +35,7 @@ namespace anm2ed int top{}; bool is_empty(); - void push(Snapshot& snapshot); + void push(const Snapshot&); Snapshot* pop(); void clear(); }; @@ -35,11 +45,12 @@ namespace anm2ed public: SnapshotStack undoStack{}; SnapshotStack redoStack{}; + Snapshot current{}; Snapshot* get(); - void push(const anm2::Anm2&, anm2::Reference, const std::string&); - void undo(anm2::Anm2& anm2, anm2::Reference& reference, std::string&); - void redo(anm2::Anm2& anm2, anm2::Reference& reference, std::string&); + void push(const Snapshot&); + void undo(); + void redo(); void reset(); }; } diff --git a/src/state.cpp b/src/state.cpp index ff0fb2a..d6ea49b 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -27,7 +27,6 @@ namespace anm2ed void State::tick(Settings& settings) { - dockspace.tick(manager, settings); if (auto document = manager.get()) { @@ -36,6 +35,8 @@ namespace anm2ed document->playback.tick(document->anm2.info.fps, animation->frameNum, (animation->isLoop || settings.playbackIsLoop) && !manager.isRecording); } + + dockspace.tick(manager, settings); } void State::update(SDL_Window*& window, Settings& settings) @@ -57,10 +58,8 @@ namespace anm2ed if (auto document = manager.get()) document->spritesheet_add(droppedFile); else - toasts.warning(std::format("Could not open spritesheet: (open a document first!)", droppedFile)); + toasts.info("Failed to add spritesheet! Open a document first."); } - else - toasts.warning(std::format("Could not parse file: {} (must be .anm2 or .png)", droppedFile)); break; } case SDL_EVENT_QUIT: @@ -80,7 +79,9 @@ namespace anm2ed dockspace.update(taskbar, documents, manager, settings, resources, dialog, clipboard); toasts.update(); - ImGui::GetStyle().FontScaleMain = settings.displayScale; + ImGui::GetStyle().FontScaleMain = settings.uiScale; + ImGui::GetIO().KeyRepeatDelay = settings.keyboardRepeatDelay; + ImGui::GetIO().KeyRepeatRate = settings.keyboardRepeatRate; SDL_GetWindowSize(window, &settings.windowSize.x, &settings.windowSize.y); if (isQuitting && manager.documents.empty()) isQuit = true; diff --git a/src/storage.cpp b/src/storage.cpp new file mode 100644 index 0000000..95b9e79 --- /dev/null +++ b/src/storage.cpp @@ -0,0 +1,12 @@ +#include "storage.h" + +namespace anm2ed +{ + void Storage::labels_set(std::vector labels) + { + labelsString = labels; + this->labels.clear(); + for (auto& label : labelsString) + this->labels.emplace_back(label.c_str()); + } +} \ No newline at end of file diff --git a/src/storage.h b/src/storage.h new file mode 100644 index 0000000..db43cf3 --- /dev/null +++ b/src/storage.h @@ -0,0 +1,28 @@ +#pragma once + +#include "anm2/anm2.h" +#include "imgui_.h" + +namespace anm2ed +{ + class Storage + { + public: + int reference{-1}; + int hovered{-1}; + std::set unused{}; + std::vector labelsString{}; + std::vector labels{}; + imgui::MultiSelectStorage selection{}; + + void labels_set(std::vector); + }; + + class FrameStorage + { + public: + anm2::Type referenceType{anm2::NONE}; + int referenceID{-1}; + int referenceFrameIndex{-1}; + }; +} \ No newline at end of file diff --git a/src/tool.h b/src/tool.h index 1c143cf..109630e 100644 --- a/src/tool.h +++ b/src/tool.h @@ -21,53 +21,61 @@ namespace anm2ed::tool COUNT }; + enum AreaType + { + ANIMATION_PREVIEW, + SPRITESHEET_EDITOR, + ALL + }; + struct Info { ImGuiMouseCursor cursor{ImGuiMouseCursor_None}; resource::icon::Type icon{}; ShortcutType shortcut{}; + AreaType areaType; const char* label{}; const char* tooltip{}; }; constexpr Info INFO[] = { - {ImGuiMouseCursor_Hand, resource::icon::PAN, SHORTCUT_PAN, "##Pan", + {ImGuiMouseCursor_Hand, resource::icon::PAN, SHORTCUT_PAN, ALL, "##Pan", "Use the pan tool.\nWill shift the view as the cursor is dragged.\nYou can also use the middle mouse button to " "pan at any time."}, - {ImGuiMouseCursor_ResizeAll, resource::icon::MOVE, SHORTCUT_MOVE, "##Move", + {ImGuiMouseCursor_ResizeAll, resource::icon::MOVE, SHORTCUT_MOVE, ALL, "##Move", "Use the move tool.\nAnimation Preview: Will move the position of the frame." "\nSpritesheet Editor: Will move the pivot, and holding right click will use the Crop functionality instead." "\nUse mouse or directional keys to change the value."}, - {ImGuiMouseCursor_Arrow, resource::icon::ROTATE, SHORTCUT_ROTATE, "##Rotate", + {ImGuiMouseCursor_Arrow, resource::icon::ROTATE, SHORTCUT_ROTATE, ANIMATION_PREVIEW, "##Rotate", "Use the rotate tool.\nWill rotate the selected item as the cursor is dragged, or directional keys are " "pressed.\n(Animation Preview only.)"}, - {ImGuiMouseCursor_ResizeNESW, resource::icon::SCALE, SHORTCUT_SCALE, "##Scale", + {ImGuiMouseCursor_ResizeNESW, resource::icon::SCALE, SHORTCUT_SCALE, ANIMATION_PREVIEW, "##Scale", "Use the scale tool.\nWill scale the selected item as the cursor is dragged, or directional keys are " "pressed.\n(Animation Preview only.)"}, - {ImGuiMouseCursor_Arrow, resource::icon::CROP, SHORTCUT_CROP, "##Crop", - "Use the crop tool.\nWill produce a crop rectangle based on how the cursor is dragged." - "\nAlternatively, you can use the arrow keys and Ctrl/Shift to move the size/position, respectively." + {ImGuiMouseCursor_Arrow, resource::icon::CROP, SHORTCUT_CROP, SPRITESHEET_EDITOR, "##Crop", + "Use the crop tool.\nWill produce a crop rectangle based on how the cursor is dragged, or directional keys are " + "pressed.\nHold CTRL with arrow keys to change position." "\nHolding right click will use the Move tool's functionality." "\n(Spritesheet Editor only.)"}, - {ImGuiMouseCursor_Arrow, resource::icon::DRAW, SHORTCUT_DRAW, "##Draw", + {ImGuiMouseCursor_Arrow, resource::icon::DRAW, SHORTCUT_DRAW, SPRITESHEET_EDITOR, "##Draw", "Draws pixels onto the selected spritesheet, with the current color.\n(Spritesheet Editor only.)"}, - {ImGuiMouseCursor_Arrow, resource::icon::ERASE, SHORTCUT_ERASE, "##Erase", + {ImGuiMouseCursor_Arrow, resource::icon::ERASE, SHORTCUT_ERASE, SPRITESHEET_EDITOR, "##Erase", "Erases pixels from the selected spritesheet.\n(Spritesheet Editor only.)"}, - {ImGuiMouseCursor_Arrow, resource::icon::COLOR_PICKER, SHORTCUT_COLOR_PICKER, "##Color Picker", - "Selects a color from the canvas.\n(Spritesheet Editor only.)"}, + {ImGuiMouseCursor_Arrow, resource::icon::COLOR_PICKER, SHORTCUT_COLOR_PICKER, SPRITESHEET_EDITOR, + "##Color Picker", "Selects a color from the canvas.\n(Spritesheet Editor only.)"}, - {ImGuiMouseCursor_None, resource::icon::UNDO, SHORTCUT_UNDO, "##Undo", "Undoes the last action."}, + {ImGuiMouseCursor_None, resource::icon::UNDO, SHORTCUT_UNDO, ALL, "##Undo", "Undoes the last action."}, - {ImGuiMouseCursor_None, resource::icon::REDO, SHORTCUT_REDO, "##Redo", "Redoes the last action."}, + {ImGuiMouseCursor_None, resource::icon::REDO, SHORTCUT_REDO, ALL, "##Redo", "Redoes the last action."}, - {ImGuiMouseCursor_None, resource::icon::NONE, SHORTCUT_COLOR, "##Color", + {ImGuiMouseCursor_None, resource::icon::NONE, SHORTCUT_COLOR, ALL, "##Color", "Selects the color to be used for drawing.\n(Spritesheet Editor only.)"}, }; } \ No newline at end of file diff --git a/src/util/filesystem_.cpp b/src/util/filesystem_.cpp index e3c3783..7a665d6 100644 --- a/src/util/filesystem_.cpp +++ b/src/util/filesystem_.cpp @@ -4,6 +4,8 @@ #include #include +#include "string_.h" + namespace anm2ed::util::filesystem { std::string path_preferences_get() @@ -27,6 +29,13 @@ namespace anm2ed::util::filesystem return e == ("." + extension); } + std::filesystem::path path_lower_case_backslash_handle(std::filesystem::path& path) + { + if (path_is_exist(path)) return path; + if (path_is_exist(string::backslash_replace(path))) return path; + return string::to_lower(path); + } + WorkingDirectory::WorkingDirectory(const std::string& path, bool isFile) { previous = std::filesystem::current_path(); diff --git a/src/util/filesystem_.h b/src/util/filesystem_.h index 7a78ef3..c13fcf6 100644 --- a/src/util/filesystem_.h +++ b/src/util/filesystem_.h @@ -8,6 +8,7 @@ namespace anm2ed::util::filesystem std::string path_preferences_get(); bool path_is_exist(const std::string&); bool path_is_extension(const std::string&, const std::string&); + std::filesystem::path path_lower_case_backslash_handle(std::filesystem::path&); class WorkingDirectory { diff --git a/src/util/string_.cpp b/src/util/string_.cpp index c814326..2cef87f 100644 --- a/src/util/string_.cpp +++ b/src/util/string_.cpp @@ -19,13 +19,6 @@ namespace anm2ed::util::string return transformed; } - std::string backslash_replace_to_lower(const std::string& string) - { - std::string transformed = string; - transformed = backslash_replace(transformed); - return to_lower(transformed); - } - std::string quote(const std::string& string) { return "\"" + string + "\""; diff --git a/src/util/string_.h b/src/util/string_.h index ce4d623..c76668f 100644 --- a/src/util/string_.h +++ b/src/util/string_.h @@ -6,6 +6,5 @@ namespace anm2ed::util::string { std::string to_lower(const std::string&); std::string backslash_replace(const std::string&); - std::string backslash_replace_to_lower(const std::string&); bool to_bool(const std::string&); } diff --git a/src/util/vector_.h b/src/util/vector_.h index 49d4cca..eba0dd9 100644 --- a/src/util/vector_.h +++ b/src/util/vector_.h @@ -12,6 +12,15 @@ namespace anm2ed::util::vector return index >= 0 && index < (int)v.size() ? &v[index] : nullptr; } + template bool in_bounds(std::vector& v, int index) + { + return index >= 0 && index < (int)v.size(); + } + template void clamp_in_bounds(std::vector& v, int& index) + { + index = std::clamp(index, 0, (int)v.size() - 1); + } + template std::set move_indices(std::vector& v, std::vector& indices, int index) { if (indices.empty()) return {}; @@ -52,12 +61,4 @@ namespace anm2ed::util::vector return moveIndices; } - template bool in_bounds(std::vector& v, int& index) - { - return index >= 0 || index <= (int)v.size() - 1; - } - template void clamp_in_bounds(std::vector& v, int& index) - { - index = std::clamp(index, 0, (int)v.size() - 1); - } } From e2799b1e582ef448c15d29b35ec5ef06a22eb502 Mon Sep 17 00:00:00 2001 From: shweet Date: Sun, 9 Nov 2025 10:35:21 -0500 Subject: [PATCH 13/15] timeline refactor, bit broken rn --- .Icon.ico-autosave.kra | Bin 0 -> 31468 bytes .clang-format | 2 +- CMakeLists.txt | 23 +- src/anm2/animation.cpp | 9 +- src/anm2/anm2_animations.cpp | 2 + src/anm2/anm2_type.h | 84 + src/anm2/frame.cpp | 12 +- src/anm2/frame.h | 38 +- src/anm2/item.cpp | 2 +- src/dialog.cpp | 7 +- src/dialog.h | 4 +- src/imgui/documents.cpp | 5 +- src/imgui/imgui_.cpp | 30 +- src/imgui/imgui_.h | 4 +- src/imgui/taskbar.cpp | 261 +++- src/imgui/taskbar.h | 10 + src/imgui/toast.cpp | 11 +- src/imgui/window/animation_preview.cpp | 92 +- src/imgui/window/animation_preview.h | 3 + src/imgui/window/spritesheets.cpp | 6 +- src/imgui/window/timeline.cpp | 1960 +++++++++++------------- src/imgui/window/timeline.h | 9 - src/loader.cpp | 133 +- src/loader.h | 7 + src/manager.cpp | 57 +- src/render.cpp | 99 +- src/render.h | 5 +- src/resource/audio_stream.cpp | 26 + src/resource/audio_stream.h | 20 + src/resource/icon.h | 20 +- src/resource/texture.cpp | 20 +- src/resource/texture.h | 2 +- src/settings.cpp | 154 +- src/settings.h | 4 +- src/snapshots.cpp | 10 +- src/snapshots.h | 2 + src/socket.cpp | 161 ++ src/socket.h | 61 + src/state.cpp | 3 + src/util/filesystem_.cpp | 38 +- src/util/filesystem_.h | 12 + 41 files changed, 2034 insertions(+), 1374 deletions(-) create mode 100644 .Icon.ico-autosave.kra create mode 100644 src/anm2/anm2_type.h create mode 100644 src/resource/audio_stream.cpp create mode 100644 src/resource/audio_stream.h create mode 100644 src/socket.cpp create mode 100644 src/socket.h diff --git a/.Icon.ico-autosave.kra b/.Icon.ico-autosave.kra new file mode 100644 index 0000000000000000000000000000000000000000..fadfcfb999f494a03add6a2dd961570793427d9d GIT binary patch literal 31468 zcmeI5byOY8*5D8B?(Tu$gy8Nj!8N$MySoGl7Mwtk5G=TR0>Rzo;O@a~AotyQ@8-Qb zYu2}B)_iN$=|eTOtM}er-MhNF|M;!iiZT$8@POwnEyPUw<1s`b##8;dz&;fl3mX$> z4|@{>dwXjOBLim(J6k4q1}jGkX9LA2L(E@l&xVSFoj#@D0Du}40D$mpXkcM$Y-hyi zZetyyqH8zDjOlY!etg&2pAn4OTJQ;rp`>`u#yl_SVw>}YJ1$S99GKkwQImuJSd4`v zWyADkR)&}S{!h!M_uHuibk%+KJmJi%kvqaguexHZhK>Ep8JWgV*6cW{vd7^9dD8gb z3M?$)#;6O*FnrHM0-5CUUg zNWVQ(hvX<$n3Spy6SJX~r4e19d)4v%g=g?+3@-Be4U0J4n?eg!sg5FuV|$roXm@MT z6>OxUbIS%WymOqiZs{@zCLti zDK4C4wI(gVoEr_w#!agMm)lpO(L1Ft={14);@q)V7MN44eW#+&os!XjKbp$cv+~)$ zaPgfewVePJ(LIB;$YENgiN#N?`!iOqVN18~aaFEaRqL5fnR!y)oV^%nh>}dZ;*>i- zH;vnQ_})t_8l)>H`>Qh@LHW^bYuhzzSzO)hYkB5B$F-4`c_ zV%%L$&jLrJo9>De{1cy5VC%=?^XA4_XyXT?(?!Ayg z7b#}X(Jf|8N+!+TYObaRj;@*E>)nq$xK$8&CApZ`Ia5AfVDoeGC|Or$UXML%e1iSM z?_o$(EM9ygkIs|ARTMHF68#FxF^g1>nDPTQGe7pr{>z3@*xq znL7QlF<;~XRx(SXvA|vp*r$zmc!)1op0W_&y3o&ycCc48n4C`={85Re>~ey z+tOF|wpQC}r{b)6+=xNd*5M1GNg!S*7ipv+g=!_*k?<6F$GAW1_`<6<07uGO)*lBCy{i>n9KJfgfJskL$9WE{|9_NgI36gXbc>tzafP^s%1jI5L zs%b{?AoXB-`@-SQDy|aC)&WsZGZiv8A`FJywbRgqi5#mhHDWNuZ( zL`R}6S!{(mn^y@$0p~}%xcn3BHSmPayON5|v!pqg9b`r0on)Kcou%OlSKUW$`y{7E zW$9{s!}ZliJ`F9aJM6DyHSMUbIJYLQ-+K%XTAxN8noD9#1j@O0x>~v2_Rl-wq+F_2 z#9MS0v`O9YW#lP}^hv zvRNw%*LOt!4RjmlASH8{y2<%X|2#wZTHm-|Leq#@yTJ6Ol4t=-$EcLF>KHG zbn7{v3f5CmwY4>{F)?PcHt;ZUbo%4pD=hiV!I?{9i*(xGYKr_jDe}r$YXB=VLTBF*R_p zcDA>0H?anT1l&G8Y5vynwT@L}$R`i(6aWC;-#W4|GAd0|SHY62y7V&LLQK!#NR=Dn z+RC7UflJR|eV-6WL(3IOBLxWsDf&hbb09n?Ffu0>96H)Rx4p+Ht7^)Naj4h^GEZ2!{n3Iz z0qo~6FU6Tc*`wFuqh+w5xcAc}<*MKY)7?$Aztho@o|b`HRk(8Nb>D zbASa42)v42e$D|K zn}draV84$;&3j3WgN6SM))=yf1^473I(*xB)_+@)ivgcvjOn#-!o@I5&m%_BV_Run z|5%2I@R|j-xOnx4`t6*N7MlxV3SkJ`Hz(18T81j56fv6;tdT}nRKYJ;%*99J<450| zybcNuu2+2Q4j$R2!7D^<;|vuNHRlW}prlin$HBrNN~yrHzPH0p>lO(4ex!ghPM1to^P3y0EYN_QwHLT$DcKtr(;z%&YCn$DgYtwvPuxe(upIN=kQ3IHIp1 z0W}p(w<4GTSvw`nv?4>mWV*k;i$8L#ia6uoRVZS>8{&;Z!%{2gV;VyQ# z4c=cS3;^`Tj>Ap)SsuI7<_f_q2#zTTf!KbKNzu6^MGn!oBxBkRt^r1%50l}KU=Kmu zj&KzK$N>`~MHKa?L4`o~N2UyzAeN~VMD9I$lMk5~0IvwKD+pl@&X5D)96&s>yfzGr z3z5KwJ{SO10XfwUJp;}ItdJ|MvjakS2P_k(f{~&^9LKBf+g5%2{r3B|r2!~! zw>pMyhB|8ZssLB(fH{WqhSqCWKSsI(2y{TtK(@7GUqRG%AkT!5!iL77!gmU4z@ng$ zqKk&opt6dFXppgoL#zhZlM#obp!=K0p;9772ph&hiiUk6#goK-ABIUvC5fjLGC_tU zi7*!GOy<)Icois1s@zLh8C*h2(2HCdMo4C6PO=W)AVM66vkq|(c9#PP2ZItJQ^dst z6B8O$q{l>|5|&bgcLqp@z4}N`1Jf4-pCh7(=8Ve?o+Q}wQK^WqIJh_mzX;jVAOGWv zZNv%i8X>cfPKwmd#Ji!MANkDz_`zj@>K_fvG4X?Jg)v5Kwi%sC(t-bsyrY59ne>|K85|0g#{%FB_t1;Q9e$ zGxS;?Oam1=RLlTQ13fv^!~jYIPAy>4Ku&{TDg;TNVg`~ujKRQa2HDj=Qy*sr>B7Io zKyL;GIXDQY$VnIzYy{-wM3WCyUUBBc7z#K82HBJ8Ad-Z{cIDec=|D|)p4(F_Kyq}I z9&26^dJ`XpGIib`lk!691xc*1xD&P_Er*b_qpVn5!SNypgz0rg9TQwJG$Z=?3v}oK zkB+&U;p{r*j~T(mb5J!PiG_rj$uv-{VdWuF0!f5KU@5v$or7NsV}JBl6fYusjm8bj z7fjX(X%JH(JVQ>1Is}Uo%+ram5_K%Wj7k=6FN#Ty9q%tGPAF(hT8Y*W4lYWTi~A;! zGk``yg<=<#8ci~NyZi5ED81rRS8o{LYiVDPFhm+6SNY{ z=h)Z6X=DuX?2<5_SjVt-B7O?pP~i2V8biLq$BUH}E+A)(o9*>pCo^WLgw%{I5u763 zi!Y2bi?iuPUiUCYsU+bFZ;m7sS`w5eJtC)$kBw7^bL#b2r&~vN#JdJ-2)&EZk$4cd z%>%$kbmqd+z(+!Ti&+&v$qQD@rQw!_&i7Xm|D0F-=7xqM5w8#4B+OB?A%|CypTI{kS-7|2rek+ zsBA%LVl9FUxyg$CMX^OpMcGAqMQ!H(;<;bV$e`lEB*D3V!%CI17hEYT)r0hANA z6R{JT6Py#46A^1bLzG9jN3=(%M}$X^=6CN-@2(P~TIMDVO6)KygU=es^h|1~bfHO| zeFjNi@ilZy(548jf?T>A4O=RFXGpC%*`d?J`TPevH;tkysAgVSv(&PwD;yD%ixs9FZ5ULvRFg3 zFW|JwfEa?>ia6_nTIqE7T2HBi&j{m&svgY~@TGflCC$FH-l?8=0dPor$ZZSmMsf+u z5tZK4(!sFCzt+0uyHb0?OdLhMqIs<2?%NET6_e6Mx5jqj>5kD%wM2Xrc-eis5_F7q z#p(TuA0j)9sXGPOf5LVp?v2n2vHXstUGJM-&vK_g`!I0p7~!h!3gwFF%H@s(T(liE z9FjI5pW_hAedPgkt`xkzLyFUT^e>HSgZ4;Fx|(5 z5gA-cL=0Q>L-Ybz1-P?dj$qYJoKEf)6f|~gyl>B6^q^&Q?P^ZK9x&=Qu2)PzsLEJjVT@Zf+~JY%HtFHn1d44=YR>>UDES7 z#`sXFwNGB3EXG*J$ana5Fm_-pq7dU*j9;a`8xX-JAOGQKtXhdY`@veum9#0|=ZDZb ztRwF=fGbQ#l95b3ZtsU#FVQ;jDXGT?UinsqEHVM=wio4bZE+mE^O%$&f*+OYXtQzLBM6mu~`TS~!8IM(ym5arL`IsRW)l`7V_Jh^eM@~y zQ|=z;_#OCh+;O6Umjzq}Vg)7zYz0UKHl~=Y@u^9vVVWN_-)qKe2F?1ICe5aB zec+1Zir@-r@V};U;&S41Vm;&9j2aLbFdA@6Elka3X)}Fm^3Zn|1z)5=8`39)l@qCK z^0`<=xA^5`a%1eSoQWdE=ZFbJOa61%nhY%kn*vv*+amSP9G@>g$9`ril9`B|Aej)L zhs6d*KtMo=VvfR$LXX0ZVu@mlVvWL)A(erY0hi&H;qOOFc1(s&#!hBT_D!~;U!zCS z$f~5TXg1R{n$@2*`BtH%!KGnQf?jf3vReXOf?a}KLR|7tVo-8YVo~BzBB9Z*xu>bE z(WC*R5vED4K~gzX*=ne3aR2=#9m%k(>dmbCOz`Zd*~D4r8QB@@S)Ez$S>YMO8Kqgr z8RV*@uajTds$441tB|VXD)@}kjl90q_FZJ!L=kn!8=IMI8Q~bE7^xdgo7L&N8DHw7 z=*Q|S7!Ml@^!i4(q_sq}1l^P0qTb3~!0ao`;>@bgw0*U6Amt1vEFttJG$eE++$Dr2 zOeT~kd`pNJLla{hV;w^tqZH#AgB^25n8GQ}b!ac^)C_d*KS?!8z_4HC{G7p?L7q{W zVVQB0ft?YP@iqf-h-S!mh;XPY!zAN8qcj7D6NamY^T>gJQwONCdDqwQEd)sJ_|*x{ zezXCzp}JnS-nwC-{;s~W0lofJ1F}OVuz16Ab9c3|o2}0!#VT}u4u?{QT!$PB+4a*6ZXWi$ z^t|4@tGuVYX}sTgYk6&XA9&GtBX~7=#duA4k$7!*`FKTm*LYDpvQFqvyfW{Bo#kE0X*72S2+jr$)>U11w} zrzfWoXD^Q}PEwC&&peKyPQ}jhPd84Ij#bYxH}_VXy4^C5_?MMir@cw8r>?;Sva;Xl z`Rl#cOVvwR4qT2{4ig9#$Px%@i))K+3uw!1OL@e9WO%T6@OUtJIJ)zLVg^?Mdkf|O zCI)5$#tJ3@#uT6*z!~5iAOfBbjs$K4-U2=iX^S9>(2S{pc12bp(lw@Ge)pPNF10|S z>J!(vw}nBqs1|$a2Q?|HT$eG%(eLIc=1xzqJp6+?Ql&WZUIrRk8m1yDbJ}gvZ7N)P zT-SzC%j^6>zI`o7k$s$qf;)>#$<7(ql?|d?Knk>SsiB_yR^M zmL|F;#w@y6l#5N29Y6q#+g6_m_nF!SgByQQl5s#`C5e+u-diW{$2Y(5P2EnVmMLG-d2 zGb}MYF)*<#F)1+}Q-oHYR%SO`<(*2DO8G?igwJO)rK5abNs%#Q3t|g63oHu}3myxm z9mO5W9p0U_G3xwbDHQ2g83h?8X}{#9_Z__zeXxDKKg|0zdh2^3`?~v#`!M?_daL_% z5*rv)XQE^HLT2@1kA9DufFYgHOQTl0R;*UtRplaJA7K`27KtmE zu!^uPqdKD?BXxnF%dY{qLAJrL0l$I0fxm&J;blXLBguwuf8K`XM#%ccy32a$`r<~= z2FAM6Mr?m};!$E7y`RiO#NGQlj%!`0_uzGb!GXnrUjy?xeM4wMoI|?cC*e!sec+AY zmEjTKvoUKizeesyl1D~H-bB_$zKt}9{2UpENryR1b3qeB!>^d3ewTA416SHzOj+_N z=To6^-g-V}L1M16;%DKVXret|n+ER3;E6JSHR?up6&8$TuuE z)HZxK2>QnR$`jjY?7pC?)~jyQTGAHK4$*?qI?&G2_Nd^iaI1!@92O0HrvFm%gOu@T?6w`Xsv`vFS zt--3aptL$RGqw~qj_MIDYpq*b84q6Rb)YWO#jWyym1=ZL!t>y>j2{qR> zCe<$0Hq|ZF6xHK3Q8jzj!xnm@tzYhSZi6oDh%%54qFW}0Nm=|(e#mDQJ}m8F(_v8}MJJS1DBU1VRBX{>WLb4hXGIA``G^j!6{^fdJ> z^X%|^=^5fV>3QH8xsxP!Adz2~;8H|dx2sPtI% z5Cb;rzbrT;INUy@-zF3-6w?70G!ESY&4Fl&xP*WAS`@DmFA}d9KMk)DKNPnB7aMO1 z-xU`bZ;3U7YTYb0wQD=mj5`z}Wsa~hi#`;AF7>n3~htEpGD z>=*1YuZCXn+b$R{Sn-uvTA&-eH&8MhGas{YTr{3D{;^*8 zvM;eqrBkJAVr*jkb?57@pC5K!juVfwjN^^h6%d%>vdXhIrY5J>q}FLBYSzxeRgIha zn68;B45|(Irmqcp44Mp_4;&2M53CKI4blzH4=|-Kvt@HUTDMwt7?T-)G&V3?F+?+T zXwRL=?O1L8R`jjC70agwtc+)6)`1eYY1 z%9bva2$znP#AvZ;oog&scpBDNpU>ml4O%f+mD(Mc6Pafk>zeCYEn4td^O-z-mlPt+ zh4zd0iT8XT`ab+(si3`}Z?j}jHC-xQoqgFRzLv1oS(`zdKwEE~bKZMidcLYwq!z^* z$EIzb>|o|#+f~c8*7f#absv7ec%OT}Y))>jrS{e!wsxyJrE>afUEO7!LbZUgp4GC6 zfT4iR*jD=<>6ShaxR1IYw`<@1ar9%)N-S3scp#Gk2P<3{4U~-(Tk8Qf9^SoqFb^7Hr)wCQ(GeKK=V0uJ) zx^}R3t#+z*`aD*hR2_%y-XW(Oznh1fksHUQ{U!b7t4sDvy2FG+y9Ewjdtz^5c;Xkt zhs0>av&0+32gK@p1-wh1cc+x@@b0u8X&#=Q;$E8`Y93ihtD(IFj`hJ!xyz{&*JD$6l4Hgb{sTUs&#>3%Z5YZ_*tEn_&rHuE z^%(VZ;aFjpS-07Dv)Qe3riAjM^3d|q@;19lyRSztm-&}@TA6&>jwFt@W|``i-P`6L zdhZ)<=`OS91u7p;9wzVSeN_Y;1Q-Oo1VWd=+R)oreS>^a?%v+oTw&ZeRkN0{6yVWCACOwcxyQ-J87bN;iYrCcR_duKZsHa*MiDTd_(@z3YR;YLzZQLcYueUzl5fQr9@!gcIHdPJA1== z#d^lf}q@}0jDSlNGftNs{OfZh&L}yC2X+}?`Mx(|z#mG*>&R0ucOX2$3 zmEDyA8LtPU5Z8=&iy#Hl?R6Q~q4YvteNz3R`-S_Cd!Bpj)y!4r)%UA_E0`0zwL0_< z7?kKg(RI+tF-|dd(LFH^DVwEdWGSg5sdg#3sY9tZUrbTDQZGsCNG?c{Q$ovEL!FjNl~9&g1gsf{&twyoJt(*N6Y!44OrRQiP|Ai-Md& zAdf$fX-(*RQ}lsst!%1ng6z>i_ds4MLuyy50_$|;h~}N9rKYQ9ho+{cs^+3*UDaEY z`ytbz0y6?*FXJ8)k|F*CzQlXZTV>=|VN4QKJ?zvp)O3Zkg*;oXLwgy^4HG&)bn)I)u%U1hMRRJ{AFp@Fz!V~v5eK525GwH- zJJDPzUVKawX$dw{mVM{Z;g@vsMT|dbqaI| z#8`J?DPG5Y$=mp^6lW4su}U#xvG~O2+-c4~uSTmR>Ttzrt~r zBAykON{Oy-;Ux3kD|Y3Y39e5ri9 zjex$$zQewzq@!X%EQKWLBp+4x$&TWJ;*Z6Js>{U@ldF@VlS`97Ci5qCC+ohX6uVj0 zTP9lVTXtH)Tgp!&PV$ystI3pLm9v$cf0ip{C~r~ps=Lr7Dq1U5{^C>;RYF%{RYvgH z>uufJVI3x2J2eu;Y)w7oWjz7a$FE@Hq!T&gz@@km`{os$F43;^(1QdW>Li7^Y(xQ% z?e(36F6!)T9Xn&&MBCSPh~@*9C02yy8MZn+Av{!`eZa)&&xy(#g^db}JT(i!=IG{Q z){YjDRLo^v*xiCBnfU@JMR%Th5 zns%nP$riQdrmweNXIr<9-Bn+EAvB0pek-BMq56_vW>T@?&_AtaNY^s?X|kNHs;1T@ z$EDz0hTx-I?qI!*pSHNR+`Qnt^L&b{aFb}0LzAADxR=eX;H~U!N>z8&&#D(@_rs=H zr93?D7bmlJMC-^ukgHdIkTij%ytzP_QuB>!0djVlu4#09r=14&xYI6^^IY5SoLl7fig(lA8n2|ecMUj z=;lRuMbboUMWjTqL~z20k$hUDTWOspcP(coJHM2w_mng029=MN?dYDhCi|8i&TUvZ zO|ys2h9-p)g&Bp#B4v~KGT%8s3J8<15WwNT#I+#CBk&t z!z#m$wpv}M9Z~C~!`@Koheg|@N`e8Rlw9>#a!Cq=+F{do}*M};iotK+8QWaA;@W`#$xejhr9B?mQz zMF$8ochXWbG`(a!=pSbu9QN17dRk)5h#$Q>Z$vjD`V-cvRTZGKdA%yn6K_9HDVG=G zDJbw0c{Fk&m_nH$nL(JInQ5C+o2G14IQ``6Z#ZtCaME>3aMH_S;Zt_syrO^5ysmmM zQ^>ye96HxIYuGybxka5F%jrECH5fo=11z zd#YQR^OQrT@wZcLguV^+00vkFTqb60WQJ;{1>LJ^Nv%ZfYQ1P}dcA$U4Bfl?$lIg~ zx@>jL^0c>$?&pVWH#OZ>{nKdWv8}DgH=}zbb~8&wEe?K8K)L($6^`;`AXPlocz#@d zmrSNif{fm>(lTwEi%0rt?Zv@l9l}wLTj!DN5>y+Vr`zFTkelAJ@-khUn@9Fd>*0OP zWmNxhWpCw<GrV@AX5{!IvBL;qp|y^wt>hM9sZ07xdCI6ur%Uv-{b~XhP?sy_!k1_kacA6XzqY)rw`j(z^f0dS zax!%~!x?5;)O%<{e%QTYyWX3(t6j!#Yw_E z`{?kHa9a2PW$X~Zh3mX$mXVY&~?Fe<09!GgvedOyT_8+v(Vej z-pm(gKk`s(U;Hrn5P83KX7T>A?LD8!9cxA^R67?DU=Ic`F#%4BjR^R*_Xze^2Bm;f z>IL-^JW2jk{*HNJ1tW)Dy!@{*FD&rP^vv|KTH^Gtm|0lip8zM|H2_Eo0O&uJ$DF6? zYalp)lpk0mkaGxl6l@X%w4(sQr+}D%b|yidUlQiC%KwzW$^Z2j#_M(pAOw>j0uX~0 z2mt_o5deOvdaj7H0U^|ZBmf|UACTnNAvXcxWx*#o>}iLB0)%)vl_1@7ok@`3={zKY z&szVeBK$+=sRREvb$}2kKnws7fewg(0Yv%F6+sLj1po-64WxML3@}On2$RtMB$oqW zP@ZH2jAw!1zlrdxufOi&AH9WmzJJgC|4ZBR2>9a<40+8Uz-=D(M5fs3m!AD^N!hnMR|8^w&d!RwV2mX2j{=+N-dh&lfPiJ@x zKsbOP$I~1JM+C$JwEtTh($n+){AeRRD*|DDX}$#h=T@-i>EKBhj0}kN4_z!a;8W`_ z5C77N!S;vZAFqsGP9Z3sCgML7|Go98qZrgrv(2xLqWsc)?&!a@J-=>XWPl{ky}T9x zLIFB(o|~Yapwegg1%T`o5E1}Xf|8wQVFA)l`@`8T_R^VxVB>ivn zBYA>K|CienwER1i`oBZBvi_fxL3AsKZUxb; zAi5Pqw}R+a5Zwx*TS0Uyh;9YZtsuG;M7M(IRuJ6^qFX_9D~N6d(XAl56-2j!=vENj z3Zh#sQkI2n}MyZo%62+LYPr z1O$$Nz!4BQ0s==s;K=`n;D`pFjT1f?0D%9LC6?eX;E09IABkn3GRB&?|H>E}$6^;G zh#2DL8{&n4L8wAh3?H5-_^C*>PcSr^k#k*zbF7PUr|l>n-b8Z3HhKAS-%O&)X}&#P zww#+NY6Jx`j-tO_I&fM2j?C*+^ZZbbhsJ+z~uJrwuWR&Vc;U5#YSjid|F>mT4qu)raAkr?t+e|C+lh1^K+c0u}CcT{*&$V z5#P8}owx4Pxy?Utf6Rwb4?U$P1p_CB`1^dl&uhj!ZQ z#r16U&(yuY8~&aT^`C|)Ps`Q(o*ngf>)-QnK3hL;lmUZJ`5ONvJLm6)zh{yB!|d5m z5&EA5(qD2){_f)UrE~u2qW$k&{AD4X-~Ih728H*hvtQQ&2lF>wdR|ZGcQ?PU75Jwo z$^g-q|Je=e?=JrS%CcDg#>Ic}%C`R2-+#EWf4xD^oY6zbX literal 0 HcmV?d00001 diff --git a/.clang-format b/.clang-format index faa0e23..035c2f8 100644 --- a/.clang-format +++ b/.clang-format @@ -1,7 +1,7 @@ ColumnLimit: 120 PointerAlignment: Left ReferenceAlignment: Left -AllowShortFunctionsOnASingleLine: None +AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: true CommentPragmas: '^' BreakBeforeBraces: Allman diff --git a/CMakeLists.txt b/CMakeLists.txt index dd30ade..1781c6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,7 +102,7 @@ else () target_compile_options(${PROJECT_NAME} PRIVATE -O0 -pg) else () set(CMAKE_BUILD_TYPE "Release") - target_compile_options(${PROJECT_NAME} PRIVATE -O2) + target_compile_options(${PROJECT_NAME} PRIVATE -Os) endif () target_link_libraries(${PROJECT_NAME} PRIVATE m) @@ -135,4 +135,25 @@ target_link_libraries(${PROJECT_NAME} PRIVATE GL SDL3-static SDL3_mixer::SDL3_mi message(STATUS "System: ${CMAKE_SYSTEM_NAME}") message(STATUS "Project: ${PROJECT_NAME}") message(STATUS "Compiler: ${CMAKE_CXX_COMPILER}") + +get_target_property(PROJECT_COMPILE_OPTIONS ${PROJECT_NAME} COMPILE_OPTIONS) +if (NOT PROJECT_COMPILE_OPTIONS) + set(PROJECT_COMPILE_OPTIONS "") +endif () + +string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_UPPER) +set(EFFECTIVE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +if (BUILD_TYPE_UPPER) + set(CONFIG_FLAGS_VAR "CMAKE_CXX_FLAGS_${BUILD_TYPE_UPPER}") + if (DEFINED ${CONFIG_FLAGS_VAR}) + string(APPEND EFFECTIVE_CXX_FLAGS " ${${CONFIG_FLAGS_VAR}}") + endif () +endif () +string(STRIP "${EFFECTIVE_CXX_FLAGS}" EFFECTIVE_CXX_FLAGS) +if (EFFECTIVE_CXX_FLAGS STREQUAL "") + set(EFFECTIVE_CXX_FLAGS "") +endif () + +message(STATUS "Compiler Flags: ${EFFECTIVE_CXX_FLAGS}") +message(STATUS "Target Compile Options: ${PROJECT_COMPILE_OPTIONS}") message(STATUS "Build: ${CMAKE_BUILD_TYPE}") diff --git a/src/anm2/animation.cpp b/src/anm2/animation.cpp index 656a505..61d2bb6 100644 --- a/src/anm2/animation.cpp +++ b/src/anm2/animation.cpp @@ -105,10 +105,7 @@ namespace anm2ed::anm2 return element; } - void Animation::serialize(XMLDocument& document, XMLElement* parent) - { - parent->InsertEndChild(to_element(document)); - } + void Animation::serialize(XMLDocument& document, XMLElement* parent) { parent->InsertEndChild(to_element(document)); } std::string Animation::to_string() { @@ -153,13 +150,13 @@ namespace anm2ed::anm2 if (isRootTransform) { - auto root = rootAnimation.frame_generate(t, anm2::ROOT); + auto root = rootAnimation.frame_generate(t, ROOT); transform *= math::quad_model_parent_get(root.position, {}, math::percent_to_unit(root.scale), root.rotation); } for (auto& [id, layerAnimation] : layerAnimations) { - auto frame = layerAnimation.frame_generate(t, anm2::LAYER); + auto frame = layerAnimation.frame_generate(t, LAYER); if (frame.size == vec2() || !frame.isVisible) continue; diff --git a/src/anm2/anm2_animations.cpp b/src/anm2/anm2_animations.cpp index c4a5107..11762d9 100644 --- a/src/anm2/anm2_animations.cpp +++ b/src/anm2/anm2_animations.cpp @@ -131,6 +131,8 @@ namespace anm2ed::anm2 finalIndex -= numDeletedBefore; } + animation.frameNum = animation.length(); + return finalIndex; } diff --git a/src/anm2/anm2_type.h b/src/anm2/anm2_type.h new file mode 100644 index 0000000..e5d15d6 --- /dev/null +++ b/src/anm2/anm2_type.h @@ -0,0 +1,84 @@ +#pragma once + +#include "icon.h" + +#include +#include +#include + +namespace anm2ed::anm2 +{ + constexpr auto ROOT_COLOR = glm::vec4(0.140f, 0.310f, 0.560f, 1.000f); + constexpr auto ROOT_COLOR_ACTIVE = glm::vec4(0.240f, 0.520f, 0.880f, 1.000f); + constexpr auto ROOT_COLOR_HOVERED = glm::vec4(0.320f, 0.640f, 1.000f, 1.000f); + + constexpr auto LAYER_COLOR = glm::vec4(0.640f, 0.320f, 0.110f, 1.000f); + constexpr auto LAYER_COLOR_ACTIVE = glm::vec4(0.840f, 0.450f, 0.170f, 1.000f); + constexpr auto LAYER_COLOR_HOVERED = glm::vec4(0.960f, 0.560f, 0.240f, 1.000f); + + constexpr auto NULL_COLOR = glm::vec4(0.140f, 0.430f, 0.200f, 1.000f); + constexpr auto NULL_COLOR_ACTIVE = glm::vec4(0.250f, 0.650f, 0.350f, 1.000f); + constexpr auto NULL_COLOR_HOVERED = glm::vec4(0.350f, 0.800f, 0.480f, 1.000f); + + constexpr auto TRIGGER_COLOR = glm::vec4(0.620f, 0.150f, 0.260f, 1.000f); + constexpr auto TRIGGER_COLOR_ACTIVE = glm::vec4(0.820f, 0.250f, 0.380f, 1.000f); + constexpr auto TRIGGER_COLOR_HOVERED = glm::vec4(0.950f, 0.330f, 0.490f, 1.000f); + +#define TYPE_LIST \ + X(NONE, "", "", resource::icon::NONE, glm::vec4(), glm::vec4(), glm::vec4()) \ + X(ROOT, "Root", "RootAnimation", resource::icon::ROOT, ROOT_COLOR, ROOT_COLOR_ACTIVE, ROOT_COLOR_HOVERED) \ + X(LAYER, "Layer", "LayerAnimation", resource::icon::LAYER, LAYER_COLOR, LAYER_COLOR_ACTIVE, LAYER_COLOR_HOVERED) \ + X(NULL_, "Null", "NullAnimation", resource::icon::NULL_, NULL_COLOR, NULL_COLOR_ACTIVE, NULL_COLOR_HOVERED) \ + X(TRIGGER, "Triggers", "Triggers", resource::icon::TRIGGERS, TRIGGER_COLOR, TRIGGER_COLOR_ACTIVE, \ + TRIGGER_COLOR_HOVERED) + + enum Type + { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) symbol, + TYPE_LIST +#undef X + }; + + constexpr const char* TYPE_STRINGS[] = { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) string, + TYPE_LIST +#undef X + }; + + constexpr const char* TYPE_ITEM_STRINGS[] = { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) itemString, + TYPE_LIST +#undef X + }; + + constexpr resource::icon::Type TYPE_ICONS[] = { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) icon, + TYPE_LIST +#undef X + }; + + constexpr glm::vec4 TYPE_COLOR[] = { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) color, + TYPE_LIST +#undef X + }; + + constexpr glm::vec4 TYPE_COLOR_ACTIVE[] = { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) colorActive, + TYPE_LIST +#undef X + }; + + constexpr glm::vec4 TYPE_COLOR_HOVERED[] = { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) colorHovered, + TYPE_LIST +#undef X + }; + + enum ChangeType + { + ADD, + SUBTRACT, + ADJUST + }; +} \ No newline at end of file diff --git a/src/anm2/frame.cpp b/src/anm2/frame.cpp index 5e22172..746a308 100644 --- a/src/anm2/frame.cpp +++ b/src/anm2/frame.cpp @@ -114,19 +114,13 @@ namespace anm2ed::anm2 return xml::document_to_string(document); } - void Frame::shorten() - { - delay = glm::clamp(--delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); - } + void Frame::shorten() { delay = glm::clamp(--delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); } - void Frame::extend() - { - delay = glm::clamp(++delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); - } + void Frame::extend() { delay = glm::clamp(++delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); } bool Frame::is_visible(Type type) { - if (type == anm2::TRIGGER) + if (type == TRIGGER) return isVisible && eventID > -1; else return isVisible; diff --git a/src/anm2/frame.h b/src/anm2/frame.h index 0e5648b..f17a086 100644 --- a/src/anm2/frame.h +++ b/src/anm2/frame.h @@ -4,10 +4,7 @@ #include #include -#include -#include -#include - +#include "anm2_type.h" #include "types.h" namespace anm2ed::anm2 @@ -15,39 +12,6 @@ namespace anm2ed::anm2 constexpr auto FRAME_DELAY_MIN = 1; constexpr auto FRAME_DELAY_MAX = 100000; -#define TYPE_LIST \ - X(NONE, "None", "None") \ - X(ROOT, "Root", "RootAnimation") \ - X(LAYER, "Layer", "LayerAnimation") \ - X(NULL_, "Null", "NullAnimation") \ - X(TRIGGER, "Trigger", "Triggers") - - enum Type - { -#define X(symbol, string, animationString) symbol, - TYPE_LIST -#undef X - }; - - constexpr const char* TYPE_STRINGS[] = { -#define X(symbol, string, animationString) string, - TYPE_LIST -#undef X - }; - - constexpr const char* TYPE_ANIMATION_STRINGS[] = { -#define X(symbol, string, animationString) animationString, - TYPE_LIST -#undef X - }; - - enum ChangeType - { - ADD, - SUBTRACT, - ADJUST - }; - #define MEMBERS \ X(isVisible, bool, true) \ X(isInterpolated, bool, false) \ diff --git a/src/anm2/item.cpp b/src/anm2/item.cpp index d262bf4..c569091 100644 --- a/src/anm2/item.cpp +++ b/src/anm2/item.cpp @@ -24,7 +24,7 @@ namespace anm2ed::anm2 XMLElement* Item::to_element(XMLDocument& document, Type type, int id) { - auto element = document.NewElement(TYPE_ANIMATION_STRINGS[type]); + auto element = document.NewElement(TYPE_ITEM_STRINGS[type]); if (type == LAYER) element->SetAttribute("LayerId", id); if (type == NULL_) element->SetAttribute("NullId", id); diff --git a/src/dialog.cpp b/src/dialog.cpp index ddffb95..c46d064 100644 --- a/src/dialog.cpp +++ b/src/dialog.cpp @@ -2,6 +2,9 @@ #ifdef _WIN32 #include +#elif __unix__ +#else + #include "toast.h" #endif #include @@ -57,8 +60,10 @@ namespace anm2ed { #ifdef _WIN32 ShellExecuteA(NULL, "open", path.c_str(), NULL, NULL, SW_SHOWNORMAL); -#else +#elif __unix__ system(std::format("xdg-open \"{}\" &", path).c_str()); +#else + toasts.info("Operation not supported."); #endif } diff --git a/src/dialog.h b/src/dialog.h index 46f716a..dfd214e 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -9,9 +9,7 @@ namespace anm2ed::dialog #if defined(_WIN32) #define EXECUTABLE_FILTER {"Executable", "exe"} #else - #define EXECUTABLE_FILTER \ - { \ - } + #define EXECUTABLE_FILTER {"Executable", "*"} #endif #define FILTER_LIST \ diff --git a/src/imgui/documents.cpp b/src/imgui/documents.cpp index 9988778..49b611e 100644 --- a/src/imgui/documents.cpp +++ b/src/imgui/documents.cpp @@ -74,12 +74,9 @@ namespace anm2ed::imgui } auto isRequested = i == manager.pendingSelected; - auto font = isDirty ? font::ITALICS : font::REGULAR; - auto string = isDirty ? std::format("[Not Saved] {}", document.filename_get().string()) : document.filename_get().string(); - auto label = std::format("{}###Document{}", string, i); auto flags = isDirty ? ImGuiTabItemFlags_UnsavedDocument : 0; @@ -89,7 +86,9 @@ namespace anm2ed::imgui if (ImGui::BeginTabItem(label.c_str(), &document.isOpen, flags)) { manager.set(i); + if (isRequested) manager.pendingSelected = -1; + ImGui::EndTabItem(); } ImGui::PopFont(); diff --git a/src/imgui/imgui_.cpp b/src/imgui/imgui_.cpp index 0123551..c761f03 100644 --- a/src/imgui/imgui_.cpp +++ b/src/imgui/imgui_.cpp @@ -166,10 +166,7 @@ namespace anm2ed::imgui return (width - (ImGui::GetStyle().ItemSpacing.x * (float)(count - 1))) / (float)count; } - ImVec2 widget_size_with_row_get(int count, float width) - { - return ImVec2(row_widget_width_get(count, width), 0); - } + ImVec2 widget_size_with_row_get(int count, float width) { return ImVec2(row_widget_width_get(count, width), 0); } float footer_height_get(int itemCount) { @@ -265,17 +262,13 @@ namespace anm2ed::imgui return ImGui::Shortcut(string_to_chord(string), flags); } - MultiSelectStorage::MultiSelectStorage() - { - internal.AdapterSetItemSelected = external_storage_set; - } + MultiSelectStorage::MultiSelectStorage() { internal.AdapterSetItemSelected = external_storage_set; } - void MultiSelectStorage::start(size_t size) + void MultiSelectStorage::start(size_t size, ImGuiMultiSelectFlags flags) { internal.UserData = this; - auto io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect2d, - this->size(), size); + auto io = ImGui::BeginMultiSelect(flags, this->size(), size); internal.ApplyRequests(io); } @@ -299,10 +292,7 @@ namespace anm2ed::imgui isJustOpened = true; } - bool PopupHelper::is_open() - { - return isOpen; - } + bool PopupHelper::is_open() { return isOpen; } void PopupHelper::trigger() { @@ -322,13 +312,7 @@ namespace anm2ed::imgui ImGui::SetNextWindowSize(ImVec2(viewport->Size.x * POPUP_MULTIPLIERS[type], 0)); } - void PopupHelper::end() - { - isJustOpened = false; - } + void PopupHelper::end() { isJustOpened = false; } - void PopupHelper::close() - { - isOpen = false; - } + void PopupHelper::close() { isOpen = false; } } diff --git a/src/imgui/imgui_.h b/src/imgui/imgui_.h index 4ff685d..cef732f 100644 --- a/src/imgui/imgui_.h +++ b/src/imgui/imgui_.h @@ -190,7 +190,9 @@ namespace anm2ed::imgui using std::set::erase; MultiSelectStorage(); - void start(size_t); + void start(size_t, ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_BoxSelect2d | + ImGuiMultiSelectFlags_ClearOnEscape | + ImGuiMultiSelectFlags_ScopeWindow); void finish(); }; diff --git a/src/imgui/taskbar.cpp b/src/imgui/taskbar.cpp index 8d263ae..7d624d4 100644 --- a/src/imgui/taskbar.cpp +++ b/src/imgui/taskbar.cpp @@ -1,13 +1,23 @@ #include "taskbar.h" -#include +#include +#include +#include +#include +#include +#include #include +#include + #include "math_.h" #include "render.h" #include "shader.h" +#include "toast.h" #include "types.h" +#include "icon.h" + using namespace anm2ed::resource; using namespace anm2ed::types; using namespace anm2ed::canvas; @@ -16,10 +26,111 @@ using namespace glm; namespace anm2ed::imgui { - Taskbar::Taskbar() : generate(vec2()) +#ifdef __unix__ + + namespace { + constexpr std::array ICON_SIZES{16, 24, 32, 48, 64, 128, 256}; + + bool ensure_parent_directory_exists(const std::filesystem::path& path) + { + std::error_code ec; + std::filesystem::create_directories(path.parent_path(), ec); + if (ec) + { + toasts.warning(std::format("Could not create directory for {} ({})", path.string(), ec.message())); + return false; + } + return true; + } + + bool write_binary_blob(const std::filesystem::path& path, const std::uint8_t* data, size_t size) + { + if (!ensure_parent_directory_exists(path)) return false; + + std::ofstream file(path, std::ios::binary | std::ios::trunc); + if (!file.is_open()) + { + toasts.warning(std::format("Could not open {} for writing", path.string())); + return false; + } + + file.write(reinterpret_cast(data), static_cast(size)); + return true; + } + + bool run_command_checked(const std::string& command, const std::string& description) + { + auto result = std::system(command.c_str()); + if (result != 0) + { + toasts.warning(std::format("{} failed (exit code {})", description, result)); + return false; + } + return true; + } + + bool install_icon_set(const std::string& context, const std::string& iconName, const std::filesystem::path& path) + { + bool success = true; + for (auto size : ICON_SIZES) + { + auto command = std::format("xdg-icon-resource install --noupdate --novendor --context {} --size {} \"{}\" {}", + context, size, path.string(), iconName); + success &= run_command_checked(command, std::format("Install {} icon ({}px)", iconName, size)); + } + return success; + } + + bool uninstall_icon_set(const std::string& context, const std::string& iconName) + { + bool success = true; + for (auto size : ICON_SIZES) + { + auto command = + std::format("xdg-icon-resource uninstall --noupdate --context {} --size {} {}", context, size, iconName); + success &= run_command_checked(command, std::format("Remove {} icon ({}px)", iconName, size)); + } + return success; + } + + bool remove_file_if_exists(const std::filesystem::path& path) + { + std::error_code ec; + if (!std::filesystem::exists(path, ec)) return true; + std::filesystem::remove(path, ec); + if (ec) + { + toasts.warning(std::format("Could not remove {} ({})", path.string(), ec.message())); + return false; + } + return true; + } } + constexpr auto MIME_TYPE = R"( + + + Anm2 Animation + + +)"; + + constexpr auto DESKTOP_ENTRY_FORMAT = R"([Desktop Entry] +Type=Application +Name=Anm2Ed +Icon=anm2ed +Comment=Animation editor for .anm2 files +Exec={} +Terminal=false +Categories=Graphics;Development; +MimeType=application/x-anm2+xml; +)"; + +#endif + + Taskbar::Taskbar() : generate(vec2()) {} + void Taskbar::update(Manager& manager, Settings& settings, Resources& resources, Dialog& dialog, bool& isQuitting) { auto document = manager.get(); @@ -119,6 +230,141 @@ namespace anm2ed::imgui configurePopup.open(); } + ImGui::Separator(); + + if (ImGui::MenuItem("Associate .anm2 Files with Editor", nullptr, false, + !isAnm2Association || !isAbleToAssociateAnm2)) + { +#ifdef _WIN32 + +#elif __unix__ + auto cache_icons = []() + { + auto programIconPath = std::filesystem::path(filesystem::path_icon_get()); + auto fileIconPath = std::filesystem::path(filesystem::path_icon_file_get()); + auto iconBytes = std::size(resource::icon::PROGRAM); + + bool isSuccess = write_binary_blob(programIconPath, resource::icon::PROGRAM, iconBytes) && + write_binary_blob(fileIconPath, resource::icon::PROGRAM, iconBytes); + + if (isSuccess) + { + isSuccess = install_icon_set("apps", "anm2ed", programIconPath) && + install_icon_set("mimetypes", "application-x-anm2+xml", fileIconPath) && + run_command_checked("xdg-icon-resource forceupdate --theme hicolor", "Refresh icon cache"); + } + + remove_file_if_exists(programIconPath); + remove_file_if_exists(fileIconPath); + + if (isSuccess) toasts.info("Cached program and file icons."); + return isSuccess; + }; + + auto register_mime = []() + { + auto path = std::filesystem::path(filesystem::path_mime_get()); + if (!ensure_parent_directory_exists(path)) return false; + + std::ofstream file(path, std::ofstream::out | std::ofstream::trunc); + if (!file.is_open()) + { + toasts.warning(std::format("Could not write .anm2 MIME type: {}", path.string())); + return false; + } + + file << MIME_TYPE; + file.close(); + toasts.info(std::format("Wrote .anm2 MIME type to: {}", path.string())); + + auto mimeRoot = path.parent_path().parent_path(); + auto command = std::format("update-mime-database \"{}\"", mimeRoot.string()); + return run_command_checked(command, "Update MIME database"); + }; + + auto register_desktop_entry = []() + { + auto path = std::filesystem::path(filesystem::path_application_get()); + if (!ensure_parent_directory_exists(path)) return false; + + std::ofstream file(path, std::ofstream::out | std::ofstream::trunc); + if (!file.is_open()) + { + toasts.warning(std::format("Could not write desktop entry: {}", path.string())); + return false; + } + + auto desktopEntry = std::format(DESKTOP_ENTRY_FORMAT, filesystem::path_executable_get()); + file << desktopEntry; + file.close(); + toasts.info(std::format("Wrote desktop entry to: {}", path.string())); + + auto desktopDir = path.parent_path(); + auto desktopUpdate = + std::format("update-desktop-database \"{}\"", desktopDir.empty() ? "." : desktopDir.string()); + auto desktopFileName = path.filename().string(); + auto setDefault = std::format("xdg-mime default {} application/x-anm2+xml", + desktopFileName.empty() ? path.string() : desktopFileName); + + auto databaseUpdated = run_command_checked(desktopUpdate, "Update desktop database"); + auto defaultRegistered = run_command_checked(setDefault, "Set default handler for .anm2"); + return databaseUpdated && defaultRegistered; + }; + + auto iconsCached = cache_icons(); + auto mimeRegistered = register_mime(); + auto desktopRegistered = register_desktop_entry(); + + isAnm2Association = iconsCached && mimeRegistered && desktopRegistered; + if (isAnm2Association) + toasts.info("Associated .anm2 files with the editor."); + else + toasts.warning("Association incomplete. Please review the warnings above."); +#endif + } + ImGui::SetItemTooltip( + "Associate .anm2 files with the application (i.e., clicking on them in a file explorer will " + "open the application)."); + + if (ImGui::MenuItem("Remove .anm2 File Association", nullptr, false, + isAnm2Association || !isAbleToAssociateAnm2)) + { +#ifdef _WIN32 + +#elif __unix__ + { + auto iconsRemoved = + uninstall_icon_set("apps", "anm2ed") && uninstall_icon_set("mimetypes", "application-x-anm2+xml") && + run_command_checked("xdg-icon-resource forceupdate --theme hicolor", "Refresh icon cache"); + if (iconsRemoved) + toasts.info("Removed cached icons."); + else + toasts.warning("Could not remove all cached icons."); + } + + { + auto path = std::filesystem::path(filesystem::path_mime_get()); + auto removed = remove_file_if_exists(path); + if (removed) toasts.info(std::format("Removed .anm2 MIME type: {}", path.string())); + + auto mimeRoot = path.parent_path().parent_path(); + run_command_checked(std::format("update-mime-database \"{}\"", mimeRoot.string()), "Update MIME database"); + } + + { + auto path = std::filesystem::path(filesystem::path_application_get()); + if (remove_file_if_exists(path)) toasts.info(std::format("Removed desktop entry: {}", path.string())); + + auto desktopDir = path.parent_path(); + run_command_checked( + std::format("update-desktop-database \"{}\"", desktopDir.empty() ? "." : desktopDir.string()), + "Update desktop database"); + } +#endif + isAnm2Association = false; + } + ImGui::SetItemTooltip("Unassociate .anm2 files with the application."); + ImGui::EndMenu(); } @@ -546,7 +792,7 @@ namespace anm2ed::imgui if (dialogType == dialog::PNG_DIRECTORY_SET) dialog.folder_open(dialogType); else - dialog.file_open(dialogType); + dialog.file_save(dialogType); } ImGui::SameLine(); input_text_string(type == render::PNGS ? "Directory" : "Path", &path); @@ -581,11 +827,16 @@ namespace anm2ed::imgui ImGui::SameLine(); ImGui::Checkbox("Raw", &isRaw); - ImGui::SetItemTooltip("Record only the layers of the animation."); + ImGui::SetItemTooltip("Record only the raw animation; i.e., only its layers, to its bounds."); + + ImGui::SameLine(); + + ImGui::Checkbox("Sound", &settings.timelineIsSound); + ImGui::SetItemTooltip("Toggle sounds playing with triggers.\nBind sounds to events in the Events window.\nThe " + "output animation will use the played sounds."); if (ImGui::Button("Render", widgetSize)) { - manager.isRecording = true; manager.isRecordingStart = true; playback.time = start; playback.isPlaying = true; diff --git a/src/imgui/taskbar.h b/src/imgui/taskbar.h index 1785468..778683c 100644 --- a/src/imgui/taskbar.h +++ b/src/imgui/taskbar.h @@ -2,6 +2,7 @@ #include "canvas.h" #include "dialog.h" +#include "filesystem_.h" #include "imgui_.h" #include "manager.h" #include "resources.h" @@ -20,6 +21,15 @@ namespace anm2ed::imgui PopupHelper aboutPopup{PopupHelper("About")}; Settings editSettings{}; int selectedShortcut{-1}; + +#if defined(_WIN32) || defined(__unix__) + bool isAbleToAssociateAnm2 = true; +#else + bool isAbleToAssociateAnm2 = false; +#endif + + bool isAnm2Association = std::filesystem::exists(util::filesystem::path_application_get()); + bool isQuittingMode{}; public: diff --git a/src/imgui/toast.cpp b/src/imgui/toast.cpp index 8de56ec..76196d9 100644 --- a/src/imgui/toast.cpp +++ b/src/imgui/toast.cpp @@ -9,7 +9,8 @@ using namespace anm2ed::types; namespace anm2ed::imgui { - constexpr auto LIFETIME = 3.0f; + constexpr auto LIFETIME = 4.0f; + constexpr auto FADE_THRESHOLD = 1.0f; Toast::Toast(const std::string& message) { @@ -30,8 +31,6 @@ namespace anm2ed::imgui { Toast& toast = toasts[i]; - toast.lifetime -= ImGui::GetIO().DeltaTime; - if (toast.lifetime <= 0.0f) { toasts.erase(toasts.begin() + i); @@ -39,7 +38,9 @@ namespace anm2ed::imgui continue; } - auto alpha = toast.lifetime / LIFETIME; + toast.lifetime -= ImGui::GetIO().DeltaTime; + + auto alpha = toast.lifetime <= FADE_THRESHOLD ? toast.lifetime / FADE_THRESHOLD : 1.0f; borderColor.w = alpha; textColor.w = alpha; @@ -57,6 +58,8 @@ namespace anm2ed::imgui { ImGui::TextUnformatted(toast.message.c_str()); position.y -= ImGui::GetWindowSize().y + ImGui::GetStyle().ItemSpacing.y; + + if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) toast.lifetime = 0.0f; } ImGui::End(); ImGui::PopStyleColor(2); diff --git a/src/imgui/window/animation_preview.cpp b/src/imgui/window/animation_preview.cpp index f798abf..5960528 100644 --- a/src/imgui/window/animation_preview.cpp +++ b/src/imgui/window/animation_preview.cpp @@ -42,51 +42,22 @@ namespace anm2ed::imgui auto& isSound = settings.timelineIsSound; auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; - if (isSound && !anm2.content.sounds.empty()) - if (auto animation = document.animation_get(); animation) - if (animation->triggers.isVisible && !isOnlyShowLayers) - if (auto trigger = animation->triggers.frame_generate(playback.time, anm2::TRIGGER); - trigger.is_visible(anm2::TRIGGER)) - if (anm2.content.sounds.contains(trigger.soundID)) anm2.content.sounds[trigger.soundID].audio.play(); + if (!anm2.content.sounds.empty() && isSound) + { + if (auto animation = document.animation_get(); + animation && animation->triggers.isVisible && (!isOnlyShowLayers || manager.isRecording)) + { + if (auto trigger = animation->triggers.frame_generate(playback.time, anm2::TRIGGER); + trigger.is_visible(anm2::TRIGGER)) + if (anm2.content.sounds.contains(trigger.soundID)) anm2.content.sounds[trigger.soundID].audio.play(mixer); + } + } document.reference.frameTime = playback.time; } if (manager.isRecording) { - if (manager.isRecordingStart) - { - if (settings.renderIsRawAnimation) - { - savedSettings = settings; - settings.previewBackgroundColor = vec4(); - settings.previewIsGrid = false; - settings.previewIsAxes = false; - settings.timelineIsOnlyShowLayers = true; - - savedZoom = zoom; - savedPan = pan; - - if (auto animation = document.animation_get()) - { - auto rect = animation->rect(isRootTransform); - size = vec2(rect.z, rect.w) * scale; - set_to_rect(zoom, pan, rect); - } - - isSizeTrySet = false; - - bind(); - viewport_set(); - clear(settings.previewBackgroundColor); - unbind(); - } - - manager.isRecordingStart = false; - - return; // Need to wait an additional frame. Kind of hacky, but oh well. - } - auto pixels = pixels_get(); renderFrames.push_back(Texture(pixels.data(), size)); @@ -120,7 +91,7 @@ namespace anm2ed::imgui } else { - if (animation_render(ffmpegPath, path, renderFrames, (render::Type)type, size, anm2.info.fps)) + if (animation_render(ffmpegPath, path, renderFrames, audioStream, (render::Type)type, size, anm2.info.fps)) toasts.info(std::format("Exported rendered animation to: {}", path)); else toasts.warning(std::format("Could not output rendered animation: {}", path)); @@ -133,12 +104,49 @@ namespace anm2ed::imgui settings = savedSettings; isSizeTrySet = true; + if (settings.timelineIsSound) audioStream.capture_end(mixer); + playback.isPlaying = false; playback.isFinished = false; manager.isRecording = false; manager.progressPopup.close(); } } + if (manager.isRecordingStart) + { + savedSettings = settings; + + if (settings.timelineIsSound) audioStream.capture_begin(mixer); + + if (settings.renderIsRawAnimation) + { + settings.previewBackgroundColor = vec4(); + settings.previewIsGrid = false; + settings.previewIsAxes = false; + settings.timelineIsOnlyShowLayers = true; + + savedZoom = zoom; + savedPan = pan; + + if (auto animation = document.animation_get()) + { + if (auto rect = animation->rect(isRootTransform); rect != vec4(-1.0f)) + { + size_set(vec2(rect.w, rect.z) * scale); + set_to_rect(zoom, pan, rect); + } + } + + isSizeTrySet = false; + + bind(); + clear(settings.previewBackgroundColor); + unbind(); + } + + manager.isRecordingStart = false; + manager.isRecording = true; + } } void AnimationPreview::update(Manager& manager, Settings& settings, Resources& resources) @@ -270,8 +278,8 @@ namespace anm2ed::imgui auto cursorScreenPos = ImGui::GetCursorScreenPos(); if (isSizeTrySet) size_set(to_vec2(ImGui::GetContentRegionAvail())); - bind(); viewport_set(); + bind(); clear(backgroundColor); if (isAxes) axes_render(shaderAxes, zoom, pan, axesColor); if (isGrid) grid_render(shaderGrid, zoom, pan, gridSize, gridOffset, gridColor); @@ -412,7 +420,7 @@ namespace anm2ed::imgui isPreviewHovered = ImGui::IsItemHovered(); - if (animation && animation->triggers.isVisible && !isOnlyShowLayers) + if (animation && animation->triggers.isVisible && !isOnlyShowLayers && !manager.isRecording) { if (auto trigger = animation->triggers.frame_generate(frameTime, anm2::TRIGGER); trigger.isVisible && trigger.eventID > -1) diff --git a/src/imgui/window/animation_preview.h b/src/imgui/window/animation_preview.h index 33fb991..cbcf380 100644 --- a/src/imgui/window/animation_preview.h +++ b/src/imgui/window/animation_preview.h @@ -1,5 +1,6 @@ #pragma once +#include "audio_stream.h" #include "canvas.h" #include "manager.h" #include "resources.h" @@ -9,6 +10,8 @@ namespace anm2ed::imgui { class AnimationPreview : public Canvas { + MIX_Mixer* mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, nullptr); + AudioStream audioStream = AudioStream(mixer); bool isPreviewHovered{}; bool isSizeTrySet{true}; Settings savedSettings{}; diff --git a/src/imgui/window/spritesheets.cpp b/src/imgui/window/spritesheets.cpp index d271f1c..804690a 100644 --- a/src/imgui/window/spritesheets.cpp +++ b/src/imgui/window/spritesheets.cpp @@ -85,7 +85,7 @@ namespace anm2ed::imgui ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2()); - selection.start(anm2.content.spritesheets.size()); + selection.start(anm2.content.spritesheets.size(), ImGuiMultiSelectFlags_ClearOnEscape); for (auto& [id, spritesheet] : anm2.content.spritesheets) { @@ -168,16 +168,16 @@ namespace anm2ed::imgui context_menu(); } + ImGui::EndChild(); ImGui::PopID(); } - selection.finish(); - ImGui::PopStyleVar(2); context_menu(); + selection.finish(); } ImGui::EndChild(); diff --git a/src/imgui/window/timeline.cpp b/src/imgui/window/timeline.cpp index 68b33c5..0558eba 100644 --- a/src/imgui/window/timeline.cpp +++ b/src/imgui/window/timeline.cpp @@ -12,26 +12,8 @@ using namespace glm; namespace anm2ed::imgui { - constexpr auto ROOT_COLOR = ImVec4(0.140f, 0.310f, 0.560f, 1.000f); - constexpr auto ROOT_COLOR_ACTIVE = ImVec4(0.240f, 0.520f, 0.880f, 1.000f); - constexpr auto ROOT_COLOR_HOVERED = ImVec4(0.320f, 0.640f, 1.000f, 1.000f); - - constexpr auto LAYER_COLOR = ImVec4(0.640f, 0.320f, 0.110f, 1.000f); - constexpr auto LAYER_COLOR_ACTIVE = ImVec4(0.840f, 0.450f, 0.170f, 1.000f); - constexpr auto LAYER_COLOR_HOVERED = ImVec4(0.960f, 0.560f, 0.240f, 1.000f); - - constexpr auto NULL_COLOR = ImVec4(0.140f, 0.430f, 0.200f, 1.000f); - constexpr auto NULL_COLOR_ACTIVE = ImVec4(0.250f, 0.650f, 0.350f, 1.000f); - constexpr auto NULL_COLOR_HOVERED = ImVec4(0.350f, 0.800f, 0.480f, 1.000f); - - constexpr auto TRIGGER_COLOR = ImVec4(0.620f, 0.150f, 0.260f, 1.000f); - constexpr auto TRIGGER_COLOR_ACTIVE = ImVec4(0.820f, 0.250f, 0.380f, 1.000f); - constexpr auto TRIGGER_COLOR_HOVERED = ImVec4(0.950f, 0.330f, 0.490f, 1.000f); - constexpr auto COLOR_HIDDEN_MULTIPLIER = vec4(0.5f, 0.5f, 0.5f, 1.000f); - constexpr auto FRAME_TIMELINE_COLOR = ImVec4(0.106f, 0.184f, 0.278f, 1.000f); - constexpr auto FRAME_BORDER_COLOR = ImVec4(1.0f, 1.0f, 1.0f, 0.15f); constexpr auto FRAME_MULTIPLE_OVERLAY_COLOR = ImVec4(1.0f, 1.0f, 1.0f, 0.05f); constexpr auto PLAYHEAD_LINE_THICKNESS = 4.0f; @@ -47,1019 +29,6 @@ namespace anm2ed::imgui - Press {} to extend the selected frame, by one frame. - Hold Alt while clicking a non-trigger frame to toggle interpolation.)"; - void Timeline::context_menu(Document& document, Settings& settings, Clipboard& clipboard) - { - auto& hoveredFrame = document.hoveredFrame; - auto& anm2 = document.anm2; - auto& reference = document.reference; - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); - - auto copy = [&]() - { - if (auto frame = anm2.frame_get(hoveredFrame)) clipboard.set(frame->to_string(hoveredFrame.itemType)); - }; - - auto cut = [&]() - { - copy(); - auto frames_delete = [&]() - { - if (auto item = anm2.item_get(reference); item) - { - item->frames.erase(item->frames.begin() + reference.frameIndex); - reference.frameIndex = glm::max(-1, --reference.frameIndex); - } - }; - - DOCUMENT_EDIT(document, "Cut Frame(s)", Document::FRAMES, frames_delete()); - }; - - auto paste = [&]() - { - if (auto item = document.item_get()) - { - document.snapshot("Paste Frame(s)"); - std::set indices{}; - std::string errorString{}; - auto start = reference.frameIndex + 1; - if (item->frames_deserialize(clipboard.get(), reference.itemType, start, indices, &errorString)) - document.change(Document::FRAMES); - else - toasts.error(std::format("Failed to deserialize frame(s): {}", errorString)); - } - else - toasts.error(std::format("Failed to deserialize frame(s): select an item first!")); - }; - - if (shortcut(settings.shortcutCut, shortcut::FOCUSED)) cut(); - if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); - if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(); - - if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) - { - if (ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, hoveredFrame != anm2::Reference{})) cut(); - if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, hoveredFrame != anm2::Reference{})) copy(); - - if (ImGui::MenuItem("Paste", nullptr, false, !clipboard.is_empty())) paste(); - ImGui::EndPopup(); - } - - ImGui::PopStyleVar(2); - } - - void Timeline::item_child(Manager& manager, Document& document, anm2::Animation* animation, Settings& settings, - Resources& resources, Clipboard& clipboard, anm2::Type type, int id, int& index) - { - auto& anm2 = document.anm2; - auto& reference = document.reference; - - auto item = animation ? animation->item_get(type, id) : nullptr; - auto isVisible = item ? item->isVisible : false; - auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; - if (isOnlyShowLayers && type != anm2::LAYER) isVisible = false; - auto isActive = reference.itemType == type && reference.itemID == id; - std::string label = "##None"; - icon::Type icon{}; - ImVec4 color{}; - - switch (type) - { - case anm2::ROOT: - label = "Root"; - icon = icon::ROOT; - color = isActive ? ROOT_COLOR_ACTIVE : ROOT_COLOR; - break; - case anm2::LAYER: - label = std::format("#{} {} (Spritesheet: #{})", id, anm2.content.layers.at(id).name, - anm2.content.layers[id].spritesheetID); - icon = icon::LAYER; - color = isActive ? LAYER_COLOR_ACTIVE : LAYER_COLOR; - break; - case anm2::NULL_: - label = std::format("#{} {}", id, anm2.content.nulls[id].name); - icon = icon::NULL_; - color = isActive ? NULL_COLOR_ACTIVE : NULL_COLOR; - break; - case anm2::TRIGGER: - label = "Triggers"; - icon = icon::TRIGGERS; - color = isActive ? TRIGGER_COLOR_ACTIVE : TRIGGER_COLOR; - break; - default: - break; - } - - color = !isVisible ? to_imvec4(to_vec4(color) * COLOR_HIDDEN_MULTIPLIER) : color; - ImGui::PushStyleColor(ImGuiCol_ChildBg, color); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); - - auto itemSize = ImVec2(ImGui::GetContentRegionAvail().x, - ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2)); - - if (ImGui::BeginChild(label.c_str(), itemSize, ImGuiChildFlags_Borders)) - { - if (type != anm2::NONE) - { - anm2::Reference itemReference = {reference.animationIndex, type, id}; - - if (ImGui::IsWindowHovered()) - { - if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) - { - switch (type) - { - case anm2::LAYER: - manager.layer_properties_open(id); // Handled in layers.cpp - break; - case anm2::NULL_: - manager.null_properties_open(id); // Handled in layers.cpp - default: - break; - } - } - - if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) reference = itemReference; - } - - ImGui::Image(resources.icons[icon].id, icon_size_get()); - ImGui::SameLine(); - ImGui::TextUnformatted(label.c_str()); - - anm2::Item* item = animation->item_get(type, id); - bool& isVisible = item->isVisible; - - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4()); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4()); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4()); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); - - ImGui::SetCursorPos(ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, - (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); - int visibleIcon = isVisible ? icon::VISIBLE : icon::INVISIBLE; - - if (ImGui::ImageButton("##Visible Toggle", resources.icons[visibleIcon].id, icon_size_get())) - DOCUMENT_EDIT(document, "Item Visibility", Document::FRAMES, isVisible = !isVisible); - ImGui::SetItemTooltip(isVisible ? "The item is shown. Press to hide." : "The item is hidden. Press to show."); - - if (type == anm2::NULL_) - { - auto& null = anm2.content.nulls.at(id); - auto& isShowRect = null.isShowRect; - - auto rectIcon = isShowRect ? icon::SHOW_RECT : icon::HIDE_RECT; - ImGui::SetCursorPos( - ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x, - (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); - if (ImGui::ImageButton("##Rect Toggle", resources.icons[rectIcon].id, icon_size_get())) - DOCUMENT_EDIT(document, "Null Rect", Document::FRAMES, null.isShowRect = !null.isShowRect); - ImGui::SetItemTooltip(isShowRect ? "The null's rect is shown. Press to hide." - : "The null's rect is hidden. Press to show."); - } - - ImGui::PopStyleVar(); - ImGui::PopStyleColor(3); - } - else - { - auto cursorPos = ImGui::GetCursorPos(); - auto& isShowUnused = settings.timelineIsShowUnused; - - ImGui::SetCursorPos(ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, - (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); - - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4()); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4()); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4()); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); - - auto unusedIcon = isShowUnused ? icon::SHOW_UNUSED : icon::HIDE_UNUSED; - if (ImGui::ImageButton("##Unused Toggle", resources.icons[unusedIcon].id, icon_size_get())) - isShowUnused = !isShowUnused; - ImGui::SetItemTooltip(isShowUnused ? "Unused layers/nulls are shown. Press to hide." - : "Unused layers/nulls are hidden. Press to show."); - - auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; - auto layersIcon = isOnlyShowLayers ? icon::SHOW_LAYERS : icon::HIDE_LAYERS; - - ImGui::SetCursorPos( - ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x, - (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); - - if (ImGui::ImageButton("##Layers Toggle", resources.icons[layersIcon].id, icon_size_get())) - isOnlyShowLayers = !isOnlyShowLayers; - ImGui::SetItemTooltip(isOnlyShowLayers ? "Only layers are visible. Press to show all items." - : "All items are visible. Press to only show layers."); - - ImGui::PopStyleVar(); - ImGui::PopStyleColor(3); - - ImGui::SetCursorPos(cursorPos); - - ImGui::BeginDisabled(); - ImGui::Text("(?)"); - ImGui::SetItemTooltip("%s", std::format(HELP_FORMAT, settings.shortcutNextFrame, settings.shortcutPreviousFrame, - settings.shortcutShortenFrame, settings.shortcutExtendFrame) - .c_str()); - ImGui::EndDisabled(); - } - } - ImGui::EndChild(); - ImGui::PopStyleColor(); - ImGui::PopStyleVar(2); - index++; - } - - void Timeline::items_child(Manager& manager, Document& document, anm2::Animation* animation, Settings& settings, - Resources& resources, Clipboard& clipboard) - { - auto& reference = document.reference; - - auto itemsChildSize = ImVec2(ImGui::GetTextLineHeightWithSpacing() * 15, ImGui::GetContentRegionAvail().y); - - if (ImGui::BeginChild("##Items Child", itemsChildSize, ImGuiChildFlags_Borders)) - { - auto itemsListChildSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - - ImGui::GetTextLineHeightWithSpacing() - - ImGui::GetStyle().ItemSpacing.y * 2); - - if (ImGui::BeginChild("##Items List Child", itemsListChildSize, ImGuiChildFlags_Borders, - ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar)) - { - ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2()); - ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, 0.0f); - if (ImGui::BeginTable("##Item Table", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY)) - { - ImGui::GetCurrentWindow()->Flags |= ImGuiWindowFlags_NoScrollWithMouse; - ImGui::SetScrollY(scroll.y); - - int index{}; - - ImGui::TableSetupScrollFreeze(0, 1); - ImGui::TableSetupColumn("##Items"); - - auto item_child_row = [&](anm2::Type type, int id = -1) - { - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - item_child(manager, document, animation, settings, resources, clipboard, type, id, index); - }; - - item_child_row(anm2::NONE); - - if (animation) - { - item_child_row(anm2::ROOT); - - for (auto& id : animation->layerOrder) - { - if (anm2::Item* item = animation->item_get(anm2::LAYER, id); item) - if (!settings.timelineIsShowUnused && item->frames.empty()) continue; - - item_child_row(anm2::LAYER, id); - } - - for (auto& id : animation->nullAnimations | std::views::keys) - { - if (anm2::Item* item = animation->item_get(anm2::NULL_, id); item) - if (!settings.timelineIsShowUnused && item->frames.empty()) continue; - - item_child_row(anm2::NULL_, id); - } - - item_child_row(anm2::TRIGGER); - } - - if (isHorizontalScroll && ImGui::GetCurrentWindow()->ScrollbarY) - { - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::Dummy(ImVec2(0, style.ScrollbarSize)); - } - - ImGui::EndTable(); - } - ImGui::PopStyleVar(2); - } - ImGui::EndChild(); - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); - - ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + style.WindowPadding.x, ImGui::GetCursorPosY())); - auto widgetSize = widget_size_with_row_get(2, ImGui::GetContentRegionAvail().x - style.WindowPadding.x); - - ImGui::BeginDisabled(!animation); - { - shortcut(settings.shortcutAdd); - if (ImGui::Button("Add", widgetSize)) propertiesPopup.open(); - set_item_tooltip_shortcut("Add a new item to the animation.", settings.shortcutAdd); - ImGui::SameLine(); - - ImGui::BeginDisabled(!document.item_get() && reference.itemType != anm2::LAYER && - reference.itemType != anm2::NULL_); - { - shortcut(settings.shortcutRemove); - if (ImGui::Button("Remove", widgetSize)) - { - auto remove = [&]() - { - animation->item_remove(reference.itemType, reference.itemID); - reference = {reference.animationIndex}; - }; - - DOCUMENT_EDIT(document, "Remove Item", Document::ITEMS, remove()); - } - set_item_tooltip_shortcut("Remove the selected items from the animation.", settings.shortcutRemove); - } - ImGui::EndDisabled(); - } - ImGui::EndDisabled(); - - ImGui::PopStyleVar(); - } - ImGui::EndChild(); - } - - void Timeline::frame_child(Document& document, anm2::Animation* animation, Settings& settings, Resources& resources, - Clipboard& clipboard, anm2::Type type, int id, int& index, float width) - { - auto& anm2 = document.anm2; - auto& playback = document.playback; - auto& reference = document.reference; - auto& hoveredFrame = document.hoveredFrame; - auto item = animation ? animation->item_get(type, id) : nullptr; - auto isVisible = item ? item->isVisible : false; - auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; - if (isOnlyShowLayers && type != anm2::LAYER) isVisible = false; - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); - - auto childSize = ImVec2(width, ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2)); - ImVec4 color{}; - ImVec4 colorActive{}; - ImVec4 colorHovered{}; - ImVec4 colorHidden{}; - ImVec4 colorActiveHidden{}; - ImVec4 colorHoveredHidden{}; - - ImGui::PopStyleVar(2); - - ImGui::PushID(index); - - switch (type) - { - case anm2::ROOT: - color = ROOT_COLOR; - colorActive = ROOT_COLOR_ACTIVE; - colorHovered = ROOT_COLOR_HOVERED; - break; - case anm2::LAYER: - color = LAYER_COLOR; - colorActive = LAYER_COLOR_ACTIVE; - colorHovered = LAYER_COLOR_HOVERED; - break; - case anm2::NULL_: - color = NULL_COLOR; - colorActive = NULL_COLOR_ACTIVE; - colorHovered = NULL_COLOR_HOVERED; - break; - case anm2::TRIGGER: - color = TRIGGER_COLOR; - colorActive = TRIGGER_COLOR_ACTIVE; - colorHovered = TRIGGER_COLOR_HOVERED; - break; - default: - color = ImGui::GetStyleColorVec4(ImGuiCol_Button); - colorActive = ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive); - colorHovered = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); - break; - } - - colorHidden = to_imvec4(to_vec4(color) * COLOR_HIDDEN_MULTIPLIER); - colorActiveHidden = to_imvec4(to_vec4(colorActive) * COLOR_HIDDEN_MULTIPLIER); - colorHoveredHidden = to_imvec4(to_vec4(colorHovered) * COLOR_HIDDEN_MULTIPLIER); - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); - - if (ImGui::BeginChild("##Frames Child", childSize, ImGuiChildFlags_Borders)) - { - auto length = animation ? animation->frameNum : anm2.animations.length(); - 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 imageSize = vec2(ImGui::GetTextLineHeight()); - auto border = ImGui::GetStyle().FrameBorderSize; - auto borderLineLength = frameSize.y / 5; - auto scrollX = ImGui::GetScrollX(); - auto available = ImGui::GetContentRegionAvail(); - auto frameMin = std::max(0, (int)std::floor(scrollX / frameSize.x) - 1); - auto frameMax = std::min(anm2::FRAME_NUM_MAX, (int)std::ceil(scrollX + available.x / frameSize.x) + 1); - auto drawList = ImGui::GetWindowDrawList(); - pickerLineDrawList = drawList; - - if (type == anm2::NONE) - { - drawList->AddRectFilled(cursorScreenPos, - ImVec2(cursorScreenPos.x + framesSize.x, cursorScreenPos.y + framesSize.y), - ImGui::GetColorU32(FRAME_TIMELINE_COLOR)); - - for (int i = frameMin; i < frameMax; i++) - { - auto frameScreenPos = ImVec2(cursorScreenPos.x + frameSize.x * (float)i, cursorScreenPos.y); - - drawList->AddRect(frameScreenPos, ImVec2(frameScreenPos.x + border, frameScreenPos.y + borderLineLength), - ImGui::GetColorU32(FRAME_BORDER_COLOR)); - - drawList->AddRect(ImVec2(frameScreenPos.x, frameScreenPos.y + frameSize.y - borderLineLength), - ImVec2(frameScreenPos.x + border, frameScreenPos.y + frameSize.y), - ImGui::GetColorU32(FRAME_BORDER_COLOR)); - - if (i % FRAME_MULTIPLE == 0) - { - auto string = std::to_string(i); - auto textSize = ImGui::CalcTextSize(string.c_str()); - auto textPos = ImVec2(frameScreenPos.x + (frameSize.x - textSize.x) / 2, - frameScreenPos.y + (frameSize.y - textSize.y) / 2); - - drawList->AddRectFilled(frameScreenPos, - ImVec2(frameScreenPos.x + frameSize.x, frameScreenPos.y + frameSize.y), - ImGui::GetColorU32(FRAME_MULTIPLE_OVERLAY_COLOR)); - - drawList->AddText(textPos, ImGui::GetColorU32(TEXT_MULTIPLE_COLOR), string.c_str()); - } - } - - if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(0)) - isDragging = true; - - if (isDragging) - { - auto childPos = ImGui::GetWindowPos(); - auto mousePos = ImGui::GetIO().MousePos; - auto localMousePos = ImVec2(mousePos.x - childPos.x, mousePos.y - childPos.y); - playback.time = floorf(localMousePos.x / frameSize.x); - reference.frameTime = playback.time; - } - - playback.clamp(settings.playbackIsClampPlayhead ? length : anm2::FRAME_NUM_MAX); - - if (ImGui::IsMouseReleased(0)) isDragging = false; - - ImGui::SetCursorPos(ImVec2(cursorPos.x + frameSize.x * floorf(playback.time), cursorPos.y)); - ImGui::Image(resources.icons[icon::PLAYHEAD].id, frameSize); - } - else if (animation) - { - anm2::Reference itemReference = {reference.animationIndex, type, id}; - if (ImGui::IsWindowHovered() && ImGui::IsMouseReleased(0)) reference = itemReference; - - for (int i = frameMin; i < frameMax; i++) - { - auto frameScreenPos = ImVec2(cursorScreenPos.x + (frameSize.x * i), cursorScreenPos.y); - - if (i % FRAME_MULTIPLE == 0) - { - drawList->AddRectFilled(frameScreenPos, - ImVec2(frameScreenPos.x + frameSize.x, frameScreenPos.y + frameSize.y), - ImGui::GetColorU32(FRAME_MULTIPLE_OVERLAY_COLOR)); - } - drawList->AddRect(frameScreenPos, ImVec2(frameScreenPos.x + frameSize.x, frameScreenPos.y + frameSize.y), - ImGui::GetColorU32(FRAME_BORDER_COLOR)); - } - - auto item = animation->item_get(type, id); - - auto frameTime = 0; - anm2::Reference baseReference = {reference.animationIndex, reference.itemType, reference.itemID, - reference.frameIndex}; - - for (auto [i, frame] : std::views::enumerate(item->frames)) - { - anm2::Reference frameReference = {reference.animationIndex, type, id, (int)i}; - auto isSelected = baseReference == frameReference; - auto isFrameVisible = isVisible && frame.isVisible; - - ImGui::PushID(i); - auto size = ImVec2(frameSize.x * frame.delay, frameSize.y); - - auto icon = type == anm2::TRIGGER ? icon::TRIGGER - : frame.isInterpolated ? icon::INTERPOLATED - : icon::UNINTERPOLATED; - - if (type == anm2::TRIGGER) - ImGui::SetCursorPos(ImVec2(cursorPos.x + frameSize.x * frame.atFrame, cursorPos.y)); - - ImGui::PushStyleColor(ImGuiCol_Button, isFrameVisible ? color : colorHidden); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, isFrameVisible ? colorActive : colorActiveHidden); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, isFrameVisible ? colorHovered : colorHoveredHidden); - - if (isSelected) ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive)); - - if (ImGui::Button("##Frame Button", size)) - { - if (type != anm2::TRIGGER && ImGui::IsKeyDown(ImGuiMod_Alt)) - DOCUMENT_EDIT(document, "Frame Interpolation", Document::FRAMES, - frame.isInterpolated = !frame.isInterpolated); - if (type == anm2::LAYER) - { - document.spritesheet.reference = anm2.content.layers[id].spritesheetID; - document.layer.selection = {id}; - } - reference = frameReference; - reference.frameTime = frameTime; - } - if (ImGui::IsItemHovered()) hoveredFrame = frameReference; - - if (type != anm2::TRIGGER) ImGui::SameLine(); - - ImGui::PopStyleColor(3); - if (isSelected) ImGui::PopStyleColor(); - - auto imageMin = ImVec2(ImGui::GetItemRectMin().x, - ImGui::GetItemRectMax().y - (ImGui::GetItemRectSize().y / 2) - (imageSize.y / 2)); - auto imageMax = to_imvec2(to_vec2(imageMin) + imageSize); - - drawList->AddImage(resources.icons[icon].id, imageMin, imageMax); - - frameTime += frame.delay; - - ImGui::PopID(); - } - - context_menu(document, settings, clipboard); - } - } - ImGui::EndChild(); - ImGui::PopStyleVar(); - - index++; - ImGui::PopID(); - } - - void Timeline::frames_child(Document& document, anm2::Animation* animation, Settings& settings, Resources& resources, - Clipboard& clipboard) - { - auto& anm2 = document.anm2; - auto& reference = document.reference; - auto& playback = document.playback; - - auto itemsChildWidth = ImGui::GetTextLineHeightWithSpacing() * 15; - - auto cursorPos = ImGui::GetCursorPos(); - ImGui::SetCursorPos(ImVec2(cursorPos.x + itemsChildWidth, cursorPos.y)); - - auto framesChildSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y); - - if (ImGui::BeginChild("##Frames Child", framesChildSize, ImGuiChildFlags_Borders)) - { - auto viewListChildSize = - ImVec2(ImGui::GetContentRegionAvail().x, - ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeightWithSpacing() - style.ItemSpacing.y * 2); - - auto childWidth = ImGui::GetContentRegionAvail().x > anm2.animations.length() * ImGui::GetTextLineHeight() - ? ImGui::GetContentRegionAvail().x - : anm2.animations.length() * ImGui::GetTextLineHeight(); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2()); - if (ImGui::BeginChild("##Frames List Child", viewListChildSize, true, ImGuiWindowFlags_HorizontalScrollbar)) - { - auto cursorScreenPos = ImGui::GetCursorScreenPos(); - - ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2()); - if (ImGui::BeginTable("##Frames List Table", 1, - ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) - { - ImGuiWindow* window = ImGui::GetCurrentWindow(); - window->Flags |= ImGuiWindowFlags_NoScrollWithMouse; - - scroll.x = ImGui::GetScrollX(); - scroll.y = ImGui::GetScrollY(); - - isHorizontalScroll = window->ScrollbarX; - - if (isWindowHovered) - { - auto& io = ImGui::GetIO(); - auto lineHeight = ImGui::GetTextLineHeightWithSpacing() * 2; - - scroll.x -= io.MouseWheelH * lineHeight; - scroll.y -= io.MouseWheel * lineHeight; - } - - ImGui::SetScrollX(scroll.x); - ImGui::SetScrollY(scroll.y); - - int index{}; - - ImGui::TableSetupScrollFreeze(0, 1); - ImGui::TableSetupColumn("##Frames"); - - auto frames_child_row = [&](anm2::Type type, int id = -1) - { - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - frame_child(document, animation, settings, resources, clipboard, type, id, index, childWidth); - }; - - frames_child_row(anm2::NONE); - - //hoveredFrame = anm2::REFERENCE_DEFAULT; - - if (animation) - { - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f); - - frames_child_row(anm2::ROOT); - - for (auto& id : animation->layerOrder) - { - if (auto item = animation->item_get(anm2::LAYER, id); item) - if (!settings.timelineIsShowUnused && item->frames.empty()) continue; - - frames_child_row(anm2::LAYER, id); - } - - for (auto& id : animation->nullAnimations | std::views::keys) - { - if (auto item = animation->item_get(anm2::NULL_, id); item) - if (!settings.timelineIsShowUnused && item->frames.empty()) continue; - frames_child_row(anm2::NULL_, id); - } - - frames_child_row(anm2::TRIGGER); - - ImGui::PopStyleVar(); - } - ImGui::EndTable(); - } - - ImDrawList* windowDrawList = ImGui::GetWindowDrawList(); - - auto frameSize = ImVec2(ImGui::GetTextLineHeight(), - ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2)); - auto linePos = ImVec2(cursorScreenPos.x + frameSize.x * floorf(playback.time) + (frameSize.x / 2) - scroll.x, - cursorScreenPos.y + frameSize.y); - auto lineSize = - ImVec2((PLAYHEAD_LINE_THICKNESS / 2.0f), - viewListChildSize.y - frameSize.y - (isHorizontalScroll ? ImGui::GetStyle().ScrollbarSize : 0.0f)); - - auto rectMin = windowDrawList->GetClipRectMin(); - auto rectMax = windowDrawList->GetClipRectMax(); - pickerLineDrawList->PushClipRect(rectMin, rectMax); - pickerLineDrawList->AddRectFilled(linePos, ImVec2(linePos.x + lineSize.x, linePos.y + lineSize.y), - ImGui::GetColorU32(PLAYHEAD_LINE_COLOR)); - pickerLineDrawList->PopClipRect(); - - ImGui::PopStyleVar(); - - context_menu(document, settings, clipboard); - } - ImGui::EndChild(); - ImGui::PopStyleVar(); - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); - - ImGui::SetCursorPos( - ImVec2(ImGui::GetStyle().WindowPadding.x, ImGui::GetCursorPos().y + ImGui::GetStyle().ItemSpacing.y)); - - auto widgetSize = widget_size_with_row_get(10); - - ImGui::BeginDisabled(!animation); - { - auto label = playback.isPlaying ? "Pause" : "Play"; - auto tooltip = playback.isPlaying ? "Pause the animation." : "Play the animation."; - - shortcut(settings.shortcutPlayPause); - if (ImGui::Button(label, widgetSize)) playback.toggle(); - set_item_tooltip_shortcut(tooltip, settings.shortcutPlayPause); - - ImGui::SameLine(); - - auto item = document.item_get(); - - ImGui::BeginDisabled(!item); - { - shortcut(settings.shortcutAdd); - if (ImGui::Button("Insert Frame", widgetSize)) - { - auto insert_frame = [&]() - { - auto frame = document.frame_get(); - if (frame) - { - item->frames.insert(item->frames.begin() + reference.frameIndex, *frame); - reference.frameIndex++; - } - else if (!item->frames.empty()) - { - auto frame = item->frames.back(); - item->frames.emplace_back(frame); - reference.frameIndex = item->frames.size() - 1; - } - }; - - DOCUMENT_EDIT(document, "Insert Frame", Document::FRAMES, insert_frame()); - } - set_item_tooltip_shortcut("Insert a frame, based on the current selection.", settings.shortcutAdd); - - ImGui::SameLine(); - - ImGui::BeginDisabled(!document.frame_get()); - { - shortcut(settings.shortcutRemove); - if (ImGui::Button("Delete Frame", widgetSize)) - { - auto delete_frame = [&]() - { - item->frames.erase(item->frames.begin() + reference.frameIndex); - reference.frameIndex = glm::max(-1, --reference.frameIndex); - }; - - DOCUMENT_EDIT(document, "Delete Frame(s)", Document::FRAMES, delete_frame()); - } - set_item_tooltip_shortcut("Delete the selected frames.", settings.shortcutRemove); - - ImGui::SameLine(); - - if (ImGui::Button("Bake", widgetSize)) bakePopup.open(); - ImGui::SetItemTooltip("Turn interpolated frames into uninterpolated ones."); - } - ImGui::EndDisabled(); - } - ImGui::EndDisabled(); - - ImGui::SameLine(); - - if (ImGui::Button("Fit Animation Length", widgetSize)) animation->frameNum = animation->length(); - ImGui::SetItemTooltip("The animation length will be set to the effective length of the animation."); - - ImGui::SameLine(); - - ImGui::SetNextItemWidth(widgetSize.x); - ImGui::InputInt("Animation Length", animation ? &animation->frameNum : &dummy_value(), STEP, STEP_FAST, - !animation ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); - if (animation) animation->frameNum = clamp(animation->frameNum, anm2::FRAME_NUM_MIN, anm2::FRAME_NUM_MAX); - ImGui::SetItemTooltip("Set the animation's length."); - - ImGui::SameLine(); - - ImGui::SetNextItemWidth(widgetSize.x); - ImGui::Checkbox("Loop", animation ? &animation->isLoop : &dummy_value()); - ImGui::SetItemTooltip("Toggle the animation looping."); - } - ImGui::EndDisabled(); - - ImGui::SameLine(); - - ImGui::SetNextItemWidth(widgetSize.x); - ImGui::InputInt("FPS", &anm2.info.fps, 1, 5); - anm2.info.fps = clamp(anm2.info.fps, anm2::FPS_MIN, anm2::FPS_MAX); - ImGui::SetItemTooltip("Set the FPS of all animations."); - - ImGui::SameLine(); - - ImGui::SetNextItemWidth(widgetSize.x); - input_text_string("Author", &anm2.info.createdBy); - ImGui::SetItemTooltip("Set the author of the document."); - - ImGui::SameLine(); - - ImGui::SetNextItemWidth(widgetSize.x); - ImGui::Checkbox("Sound", &settings.timelineIsSound); - ImGui::SetItemTooltip("Toggle sounds playing with triggers.\nBind sounds to events in the Events window."); - - ImGui::PopStyleVar(); - } - ImGui::EndChild(); - - ImGui::SetCursorPos(cursorPos); - } - - void Timeline::popups(Document& document, anm2::Animation* animation, Settings& settings) - { - auto item_properties_reset = [&]() - { - addItemName.clear(); - addItemSpritesheetID = {}; - addItemID = -1; - isUnusedItemsSet = false; - }; - - auto& anm2 = document.anm2; - auto& reference = document.reference; - - propertiesPopup.trigger(); - - if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) - { - auto item_properties_close = [&]() - { - item_properties_reset(); - propertiesPopup.close(); - }; - - auto& type = settings.timelineAddItemType; - auto& locale = settings.timelineAddItemLocale; - auto& source = settings.timelineAddItemSource; - - if (!isUnusedItemsSet) - { - unusedItems = type == anm2::LAYER ? anm2.layers_unused(reference) - : type == anm2::NULL_ ? anm2.nulls_unused(reference) - : std::set{}; - - isUnusedItemsSet = true; - } - - auto footerSize = footer_size_get(); - auto optionsSize = child_size_get(11); - auto itemsSize = ImVec2(0, ImGui::GetContentRegionAvail().y - - (optionsSize.y + footerSize.y + ImGui::GetStyle().ItemSpacing.y * 4)); - if (ImGui::BeginChild("Options", optionsSize, ImGuiChildFlags_Borders)) - { - ImGui::SeparatorText("Type"); - - auto size = ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, ImGui::GetFrameHeightWithSpacing()); - - if (ImGui::BeginChild("Type Layer", size)) - { - ImGui::RadioButton("Layer", &type, anm2::LAYER); - ImGui::SetItemTooltip("Layers are a basic visual element in an animation, used for displaying spritesheets."); - } - ImGui::EndChild(); - - ImGui::SameLine(); - - if (ImGui::BeginChild("Type Null", size)) - { - ImGui::RadioButton("Null", &type, anm2::NULL_); - ImGui::SetItemTooltip( - "Nulls are invisible elements in an animation, used for interfacing with a game engine."); - } - ImGui::EndChild(); - - ImGui::SeparatorText("Source"); - - bool isNewOnly = unusedItems.empty(); - if (isNewOnly) source = source::NEW; - - if (ImGui::BeginChild("Source New", size)) - { - ImGui::RadioButton("New", &source, source::NEW); - ImGui::SetItemTooltip("Create a new item to be used."); - } - ImGui::EndChild(); - - ImGui::SameLine(); - - if (ImGui::BeginChild("Source Existing", size)) - { - ImGui::BeginDisabled(isNewOnly); - ImGui::RadioButton("Existing", &source, source::EXISTING); - ImGui::EndDisabled(); - ImGui::SetItemTooltip("Use a pre-existing, presently unused item."); - } - ImGui::EndChild(); - - ImGui::SeparatorText("Locale"); - - if (ImGui::BeginChild("Locale Global", size)) - { - ImGui::RadioButton("Global", &locale, locale::GLOBAL); - ImGui::SetItemTooltip("The item will be inserted into all animations, if not already present."); - } - ImGui::EndChild(); - - ImGui::SameLine(); - - if (ImGui::BeginChild("Locale Local", size)) - { - ImGui::RadioButton("Local", &locale, locale::LOCAL); - ImGui::SetItemTooltip("The item will only be inserted into this animation."); - } - ImGui::EndChild(); - - ImGui::SeparatorText("Options"); - - ImGui::BeginDisabled(source == source::EXISTING); - { - input_text_string("Name", &addItemName); - ImGui::SetItemTooltip("Set the item's name."); - ImGui::BeginDisabled(type != anm2::LAYER); - { - combo_negative_one_indexed("Spritesheet", &addItemSpritesheetID, document.spritesheet.labels); - ImGui::SetItemTooltip("Set the layer item's spritesheet."); - } - ImGui::EndDisabled(); - } - ImGui::EndDisabled(); - } - ImGui::EndChild(); - - if (ImGui::BeginChild("Items", itemsSize, ImGuiChildFlags_Borders)) - { - if (animation && source == source::EXISTING) - { - for (auto id : unusedItems) - { - auto isSelected = addItemID == id; - - ImGui::PushID(id); - - if (type == anm2::LAYER) - { - auto& layer = anm2.content.layers[id]; - if (ImGui::Selectable( - std::format("#{} {} (Spritesheet: #{})", id, layer.name, layer.spritesheetID).c_str(), - isSelected)) - addItemID = id; - } - else if (type == anm2::NULL_) - { - auto& null = anm2.content.nulls[id]; - if (ImGui::Selectable(std::format("#{} {}", id, null.name).c_str(), isSelected)) addItemID = id; - } - - ImGui::PopID(); - } - } - } - ImGui::EndChild(); - - auto widgetSize = widget_size_with_row_get(2); - - if (ImGui::Button("Add", widgetSize)) - { - anm2::Reference addReference{}; - - document.snapshot("Add Item"); - if (type == anm2::LAYER) - addReference = anm2.layer_animation_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName, - addItemSpritesheetID - 1, (locale::Type)locale); - else if (type == anm2::NULL_) - addReference = anm2.null_animation_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName, - (locale::Type)locale); - - document.change(Document::ITEMS); - - reference = addReference; - - item_properties_close(); - } - ImGui::SetItemTooltip("Add the item, with the settings specified."); - - ImGui::SameLine(); - - if (ImGui::Button("Cancel", widgetSize)) item_properties_close(); - ImGui::SetItemTooltip("Cancel adding an item."); - - ImGui::EndPopup(); - } - - bakePopup.trigger(); - - if (ImGui::BeginPopupModal(bakePopup.label, &bakePopup.isOpen, ImGuiWindowFlags_NoResize)) - { - auto& interval = settings.bakeInterval; - auto& isRoundRotation = settings.bakeIsRoundRotation; - auto& isRoundScale = settings.bakeIsRoundScale; - - auto frame = document.frame_get(); - - input_int_range("Interval", interval, anm2::FRAME_DELAY_MIN, frame ? frame->delay : anm2::FRAME_DELAY_MIN); - ImGui::SetItemTooltip("Set the maximum delay of each frame that will be baked."); - - ImGui::Checkbox("Round Rotation", &isRoundRotation); - ImGui::SetItemTooltip("Rotation will be rounded to the nearest whole number."); - - ImGui::Checkbox("Round Scale", &isRoundScale); - ImGui::SetItemTooltip("Scale will be rounded to the nearest whole number."); - - auto widgetSize = widget_size_with_row_get(2); - - if (ImGui::Button("Bake", widgetSize)) - { - if (auto item = document.item_get()) - DOCUMENT_EDIT(document, "Bake Frames", Document::FRAMES, - item->frames_bake(reference.frameIndex, interval, isRoundScale, isRoundRotation)); - bakePopup.close(); - } - ImGui::SetItemTooltip("Bake the selected frame(s) with the options selected."); - - ImGui::SameLine(); - - if (ImGui::Button("Cancel", widgetSize)) bakePopup.close(); - ImGui::SetItemTooltip("Cancel baking frames."); - - ImGui::EndPopup(); - } - } - void Timeline::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) { auto& document = *manager.get(); @@ -1069,17 +38,938 @@ namespace anm2ed::imgui style = ImGui::GetStyle(); + auto context_menu = [&]() + { + auto& hoveredFrame = document.hoveredFrame; + auto& anm2 = document.anm2; + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + + auto copy = [&]() + { + if (auto frame = anm2.frame_get(hoveredFrame)) clipboard.set(frame->to_string(hoveredFrame.itemType)); + }; + + auto cut = [&]() + { + copy(); + auto frames_delete = [&]() + { + if (auto item = anm2.item_get(reference); item) + { + item->frames.erase(item->frames.begin() + reference.frameIndex); + reference.frameIndex = glm::max(-1, --reference.frameIndex); + } + }; + + DOCUMENT_EDIT(document, "Cut Frame(s)", Document::FRAMES, frames_delete()); + }; + + auto paste = [&]() + { + if (auto item = document.item_get()) + { + document.snapshot("Paste Frame(s)"); + std::set indices{}; + std::string errorString{}; + auto start = reference.frameIndex + 1; + if (item->frames_deserialize(clipboard.get(), reference.itemType, start, indices, &errorString)) + document.change(Document::FRAMES); + else + toasts.error(std::format("Failed to deserialize frame(s): {}", errorString)); + } + else + toasts.error(std::format("Failed to deserialize frame(s): select an item first!")); + }; + + if (shortcut(settings.shortcutCut, shortcut::FOCUSED)) cut(); + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + if (ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, hoveredFrame != anm2::Reference{})) cut(); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, hoveredFrame != anm2::Reference{})) copy(); + if (ImGui::MenuItem("Paste", nullptr, false, !clipboard.is_empty())) paste(); + ImGui::EndPopup(); + } + + ImGui::PopStyleVar(2); + }; + + auto item_child = [&](anm2::Type type, int id, int& index) + { + auto& anm2 = document.anm2; + + auto item = animation ? animation->item_get(type, id) : nullptr; + auto isVisible = item ? item->isVisible : false; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; + if (isOnlyShowLayers && type != anm2::LAYER) isVisible = false; + auto isActive = reference.itemType == type && reference.itemID == id; + + auto label = type == anm2::LAYER ? std::format(anm2::LAYER_FORMAT, id, anm2.content.layers.at(id).name, + anm2.content.layers[id].spritesheetID) + : type == anm2::NULL_ ? std::format(anm2::NULL_FORMAT, id, anm2.content.nulls[id].name) + : anm2::TYPE_STRINGS[type]; + auto icon = anm2::TYPE_ICONS[type]; + auto color = to_imvec4(isActive ? anm2::TYPE_COLOR_ACTIVE[type] : anm2::TYPE_COLOR[type]); + color = !isVisible ? to_imvec4(to_vec4(color) * COLOR_HIDDEN_MULTIPLIER) : color; + ImGui::PushStyleColor(ImGuiCol_ChildBg, color); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + + auto itemSize = ImVec2(ImGui::GetContentRegionAvail().x, + ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2)); + + if (ImGui::BeginChild(label.c_str(), itemSize, ImGuiChildFlags_Borders)) + { + if (type != anm2::NONE) + { + anm2::Reference itemReference = {reference.animationIndex, type, id}; + + if (ImGui::IsWindowHovered()) + { + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + { + switch (type) + { + case anm2::LAYER: + manager.layer_properties_open(id); + break; + case anm2::NULL_: + manager.null_properties_open(id); + default: + break; + } + } + + if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) reference = itemReference; + } + + ImGui::Image(resources.icons[icon].id, icon_size_get()); + ImGui::SameLine(); + ImGui::TextUnformatted(label.c_str()); + + anm2::Item* itemPtr = animation->item_get(type, id); + bool& itemVisible = itemPtr->isVisible; + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4()); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); + + ImGui::SetCursorPos( + ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + int visibleIcon = itemVisible ? icon::VISIBLE : icon::INVISIBLE; + + if (ImGui::ImageButton("##Visible Toggle", resources.icons[visibleIcon].id, icon_size_get())) + DOCUMENT_EDIT(document, "Item Visibility", Document::FRAMES, itemVisible = !itemVisible); + ImGui::SetItemTooltip(itemVisible ? "The item is shown. Press to hide." + : "The item is hidden. Press to show."); + + if (type == anm2::NULL_) + { + auto& null = anm2.content.nulls.at(id); + auto& isShowRect = null.isShowRect; + + auto rectIcon = isShowRect ? icon::SHOW_RECT : icon::HIDE_RECT; + ImGui::SetCursorPos( + ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + if (ImGui::ImageButton("##Rect Toggle", resources.icons[rectIcon].id, icon_size_get())) + DOCUMENT_EDIT(document, "Null Rect", Document::FRAMES, null.isShowRect = !null.isShowRect); + ImGui::SetItemTooltip(isShowRect ? "The null's rect is shown. Press to hide." + : "The null's rect is hidden. Press to show."); + } + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(3); + } + else + { + auto cursorPos = ImGui::GetCursorPos(); + auto& isShowUnused = settings.timelineIsShowUnused; + + ImGui::SetCursorPos( + ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4()); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); + + auto unusedIcon = isShowUnused ? icon::SHOW_UNUSED : icon::HIDE_UNUSED; + if (ImGui::ImageButton("##Unused Toggle", resources.icons[unusedIcon].id, icon_size_get())) + isShowUnused = !isShowUnused; + ImGui::SetItemTooltip(isShowUnused ? "Unused layers/nulls are shown. Press to hide." + : "Unused layers/nulls are hidden. Press to show."); + + auto& showLayersOnly = settings.timelineIsOnlyShowLayers; + auto layersIcon = showLayersOnly ? icon::SHOW_LAYERS : icon::HIDE_LAYERS; + + ImGui::SetCursorPos( + ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + + if (ImGui::ImageButton("##Layers Toggle", resources.icons[layersIcon].id, icon_size_get())) + showLayersOnly = !showLayersOnly; + ImGui::SetItemTooltip(showLayersOnly ? "Only layers are visible. Press to show all items." + : "All items are visible. Press to only show layers."); + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(3); + + ImGui::SetCursorPos(cursorPos); + + ImGui::BeginDisabled(); + ImGui::Text("(?)"); + ImGui::SetItemTooltip("%s", + std::format(HELP_FORMAT, settings.shortcutNextFrame, settings.shortcutPreviousFrame, + settings.shortcutShortenFrame, settings.shortcutExtendFrame) + .c_str()); + ImGui::EndDisabled(); + } + } + ImGui::EndChild(); + ImGui::PopStyleColor(); + ImGui::PopStyleVar(2); + index++; + }; + + auto items_child = [&]() + { + auto itemsChildSize = ImVec2(ImGui::GetTextLineHeightWithSpacing() * 15, ImGui::GetContentRegionAvail().y); + + if (ImGui::BeginChild("##Items Child", itemsChildSize, ImGuiChildFlags_Borders)) + { + auto itemsListChildSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - + ImGui::GetTextLineHeightWithSpacing() - + ImGui::GetStyle().ItemSpacing.y * 2); + + if (ImGui::BeginChild("##Items List Child", itemsListChildSize, ImGuiChildFlags_Borders, + ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar)) + { + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2()); + ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, 0.0f); + if (ImGui::BeginTable("##Item Table", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY)) + { + ImGui::GetCurrentWindow()->Flags |= ImGuiWindowFlags_NoScrollWithMouse; + ImGui::SetScrollY(scroll.y); + + int index{}; + + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableSetupColumn("##Items"); + + auto item_child_row = [&](anm2::Type type, int id = -1) + { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + item_child(type, id, index); + }; + + item_child_row(anm2::NONE); + + if (animation) + { + item_child_row(anm2::ROOT); + + for (auto& id : animation->layerOrder) + { + if (!settings.timelineIsShowUnused && animation->layerAnimations[id].frames.empty()) continue; + item_child_row(anm2::LAYER, id); + } + + for (auto& [id, nullAnimation] : animation->nullAnimations) + { + if (!settings.timelineIsShowUnused && nullAnimation.frames.empty()) continue; + item_child_row(anm2::NULL_, id); + } + + item_child_row(anm2::TRIGGER); + } + + if (isHorizontalScroll && ImGui::GetCurrentWindow()->ScrollbarY) + { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Dummy(ImVec2(0, style.ScrollbarSize)); + } + + ImGui::EndTable(); + } + ImGui::PopStyleVar(2); + } + ImGui::EndChild(); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + + ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + style.WindowPadding.x, ImGui::GetCursorPosY())); + auto widgetSize = widget_size_with_row_get(2, ImGui::GetContentRegionAvail().x - style.WindowPadding.x); + + ImGui::BeginDisabled(!animation); + { + shortcut(settings.shortcutAdd); + if (ImGui::Button("Add", widgetSize)) propertiesPopup.open(); + set_item_tooltip_shortcut("Add a new item to the animation.", settings.shortcutAdd); + ImGui::SameLine(); + + ImGui::BeginDisabled(!document.item_get() && reference.itemType != anm2::LAYER && + reference.itemType != anm2::NULL_); + { + shortcut(settings.shortcutRemove); + if (ImGui::Button("Remove", widgetSize)) + { + auto remove = [&]() + { + animation->item_remove(reference.itemType, reference.itemID); + reference = {reference.animationIndex}; + }; + + DOCUMENT_EDIT(document, "Remove Item", Document::ITEMS, remove()); + } + set_item_tooltip_shortcut("Remove the selected item(s) from the animation.", settings.shortcutRemove); + } + ImGui::EndDisabled(); + } + ImGui::EndDisabled(); + + ImGui::PopStyleVar(); + } + ImGui::EndChild(); + }; + + auto frame_child = [&](anm2::Type type, int id, int& index, float width) + { + auto& anm2 = document.anm2; + auto& hoveredFrame = document.hoveredFrame; + + auto item = animation ? animation->item_get(type, id) : nullptr; + auto isVisible = item ? item->isVisible : false; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; + if (isOnlyShowLayers && type != anm2::LAYER) isVisible = false; + + auto color = to_imvec4(anm2::TYPE_COLOR[type]); + auto colorActive = to_imvec4(anm2::TYPE_COLOR_ACTIVE[type]); + auto colorHovered = to_imvec4(anm2::TYPE_COLOR_HOVERED[type]); + auto colorHidden = to_imvec4(to_vec4(color) * COLOR_HIDDEN_MULTIPLIER); + auto colorActiveHidden = to_imvec4(to_vec4(colorActive) * COLOR_HIDDEN_MULTIPLIER); + auto colorHoveredHidden = to_imvec4(to_vec4(colorHidden) * COLOR_HIDDEN_MULTIPLIER); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + + auto childSize = ImVec2(width, ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2)); + + ImGui::PopStyleVar(2); + + ImGui::PushID(index); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); + + if (ImGui::BeginChild("##Frames Child", childSize, ImGuiChildFlags_Borders)) + { + auto length = animation ? animation->frameNum : anm2.animations.length(); + 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 = ImGui::GetStyle().FrameBorderSize; + auto borderLineLength = frameSize.y / 5; + auto scrollX = ImGui::GetScrollX(); + auto available = ImGui::GetContentRegionAvail(); + auto frameMin = std::max(0, (int)std::floor(scrollX / frameSize.x) - 1); + auto frameMax = std::min(anm2::FRAME_NUM_MAX, (int)std::ceil(scrollX + available.x / frameSize.x) + 1); + auto drawList = ImGui::GetWindowDrawList(); + pickerLineDrawList = drawList; + + if (type == anm2::NONE) + { + drawList->AddRectFilled(cursorScreenPos, + ImVec2(cursorScreenPos.x + framesSize.x, cursorScreenPos.y + framesSize.y), + ImGui::GetColorU32(FRAME_TIMELINE_COLOR)); + + for (int i = frameMin; i < frameMax; i++) + { + auto frameScreenPos = ImVec2(cursorScreenPos.x + frameSize.x * (float)i, cursorScreenPos.y); + + drawList->AddRect(frameScreenPos, ImVec2(frameScreenPos.x + border, frameScreenPos.y + borderLineLength), + ImGui::GetColorU32(FRAME_BORDER_COLOR)); + + drawList->AddRect(ImVec2(frameScreenPos.x, frameScreenPos.y + frameSize.y - borderLineLength), + ImVec2(frameScreenPos.x + border, frameScreenPos.y + frameSize.y), + ImGui::GetColorU32(FRAME_BORDER_COLOR)); + + if (i % FRAME_MULTIPLE == 0) + { + auto string = std::to_string(i); + auto textSize = ImGui::CalcTextSize(string.c_str()); + auto textPos = ImVec2(frameScreenPos.x + (frameSize.x - textSize.x) / 2, + frameScreenPos.y + (frameSize.y - textSize.y) / 2); + + drawList->AddRectFilled(frameScreenPos, + ImVec2(frameScreenPos.x + frameSize.x, frameScreenPos.y + frameSize.y), + ImGui::GetColorU32(FRAME_MULTIPLE_OVERLAY_COLOR)); + + drawList->AddText(textPos, ImGui::GetColorU32(TEXT_MULTIPLE_COLOR), string.c_str()); + } + } + + if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(0)) + isDragging = true; + + if (isDragging) + { + auto childPos = ImGui::GetWindowPos(); + auto mousePos = ImGui::GetIO().MousePos; + auto localMousePos = ImVec2(mousePos.x - childPos.x, mousePos.y - childPos.y); + playback.time = floorf(localMousePos.x / frameSize.x); + reference.frameTime = playback.time; + } + + playback.clamp(settings.playbackIsClampPlayhead ? length : anm2::FRAME_NUM_MAX); + + if (ImGui::IsMouseReleased(0)) isDragging = false; + + ImGui::SetCursorPos(ImVec2(cursorPos.x + frameSize.x * floorf(playback.time), cursorPos.y)); + ImGui::Image(resources.icons[icon::PLAYHEAD].id, frameSize); + } + else if (animation) + { + anm2::Reference itemReference{reference.animationIndex, type, id}; + + ImGui::PushStyleColor(ImGuiCol_ButtonActive, isVisible ? colorActive : colorActiveHidden); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, isVisible ? colorHovered : colorHoveredHidden); + + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f); + + float frameTime{}; + + for (auto [i, frame] : std::views::enumerate(item->frames)) + { + ImGui::PushID(i); + + auto frameReference = + anm2::Reference(itemReference.animationIndex, itemReference.itemType, itemReference.itemID, i); + auto isSelected = reference == frameReference; + vec2 frameMin = {frameTime * frameSize.x, cursorPos.y}; + vec2 frameMax = {frameMin.x + frame.delay * frameSize.x, frameMin.y + frameSize.y}; + auto buttonSize = to_imvec2(frameMax - frameMin); + auto buttonPos = ImVec2(cursorPos.x + frameMin.x, cursorPos.y); + ImGui::SetCursorPos(buttonPos); + ImGui::PushStyleColor(ImGuiCol_Button, isSelected && isVisible ? colorActive + : isSelected && !isVisible ? colorActiveHidden + : isVisible ? color + : colorHidden); + if (ImGui::Button("##Frame Button", buttonSize)) + { + if (type == anm2::LAYER) + { + document.spritesheet.reference = anm2.content.layers[id].spritesheetID; + document.layer.selection = {id}; + } + reference = frameReference; + reference.frameTime = frameTime; + + if (ImGui::IsKeyDown(ImGuiMod_Alt)) + DOCUMENT_EDIT(document, "Frame Interpolation", Document::FRAMES, + frame.isInterpolated = !frame.isInterpolated); + } + if (ImGui::IsItemHovered()) hoveredFrame = frameReference; + ImGui::PopStyleColor(); + auto icon = type == anm2::TRIGGER ? icon::TRIGGER + : frame.isInterpolated ? icon::INTERPOLATED + : icon::UNINTERPOLATED; + auto iconPos = ImVec2(cursorPos.x + (frameTime * frameSize.x), + cursorPos.y + (frameSize.y / 2) - (icon_size_get().y / 2)); + ImGui::SetCursorPos(iconPos); + ImGui::Image(resources.icons[icon].id, icon_size_get()); + + frameTime += frame.delay; + + ImGui::PopID(); + } + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(2); + } + } + ImGui::EndChild(); + ImGui::PopStyleVar(); + + index++; + ImGui::PopID(); + }; + + auto frames_child = [&]() + { + auto& anm2 = document.anm2; + + auto itemsChildWidth = ImGui::GetTextLineHeightWithSpacing() * 15; + + auto cursorPos = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(cursorPos.x + itemsChildWidth, cursorPos.y)); + + auto framesChildSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y); + + if (ImGui::BeginChild("##Frames Child", framesChildSize, ImGuiChildFlags_Borders)) + { + auto viewListChildSize = + ImVec2(ImGui::GetContentRegionAvail().x, + ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeightWithSpacing() - style.ItemSpacing.y * 2); + + auto childWidth = ImGui::GetContentRegionAvail().x > anm2.animations.length() * ImGui::GetTextLineHeight() + ? ImGui::GetContentRegionAvail().x + : anm2.animations.length() * ImGui::GetTextLineHeight(); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2()); + if (ImGui::BeginChild("##Frames List Child", viewListChildSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + auto cursorScreenPos = ImGui::GetCursorScreenPos(); + + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2()); + if (ImGui::BeginTable("##Frames List Table", 1, + ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) + { + ImGuiWindow* window = ImGui::GetCurrentWindow(); + window->Flags |= ImGuiWindowFlags_NoScrollWithMouse; + + scroll.x = ImGui::GetScrollX(); + scroll.y = ImGui::GetScrollY(); + + isHorizontalScroll = window->ScrollbarX; + + if (isWindowHovered) + { + auto& io = ImGui::GetIO(); + auto lineHeight = ImGui::GetTextLineHeightWithSpacing() * 2; + + scroll.x -= io.MouseWheelH * lineHeight; + scroll.y -= io.MouseWheel * lineHeight; + } + + ImGui::SetScrollX(scroll.x); + ImGui::SetScrollY(scroll.y); + + int index{}; + + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableSetupColumn("##Frames"); + + auto frames_child_row = [&](anm2::Type type, int id = -1) + { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + frame_child(type, id, index, childWidth); + }; + + frames_child_row(anm2::NONE); + + if (animation) + { + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f); + + frames_child_row(anm2::ROOT); + + for (auto& id : animation->layerOrder) + { + if (auto itemPtr = animation->item_get(anm2::LAYER, id); itemPtr) + if (!settings.timelineIsShowUnused && itemPtr->frames.empty()) continue; + + frames_child_row(anm2::LAYER, id); + } + + for (auto& id : animation->nullAnimations | std::views::keys) + { + if (auto itemPtr = animation->item_get(anm2::NULL_, id); itemPtr) + if (!settings.timelineIsShowUnused && itemPtr->frames.empty()) continue; + frames_child_row(anm2::NULL_, id); + } + + frames_child_row(anm2::TRIGGER); + + ImGui::PopStyleVar(); + } + ImGui::EndTable(); + } + + ImDrawList* windowDrawList = ImGui::GetWindowDrawList(); + + auto frameSize = ImVec2(ImGui::GetTextLineHeight(), + ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2)); + auto linePos = ImVec2(cursorScreenPos.x + frameSize.x * floorf(playback.time) + (frameSize.x / 2) - scroll.x, + cursorScreenPos.y + frameSize.y); + auto lineSize = + ImVec2((PLAYHEAD_LINE_THICKNESS / 2.0f), + viewListChildSize.y - frameSize.y - (isHorizontalScroll ? ImGui::GetStyle().ScrollbarSize : 0.0f)); + + auto rectMin = windowDrawList->GetClipRectMin(); + auto rectMax = windowDrawList->GetClipRectMax(); + pickerLineDrawList->PushClipRect(rectMin, rectMax); + pickerLineDrawList->AddRectFilled(linePos, ImVec2(linePos.x + lineSize.x, linePos.y + lineSize.y), + ImGui::GetColorU32(PLAYHEAD_LINE_COLOR)); + pickerLineDrawList->PopClipRect(); + + ImGui::PopStyleVar(); + + context_menu(); + } + ImGui::EndChild(); + ImGui::PopStyleVar(); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + + ImGui::SetCursorPos( + ImVec2(ImGui::GetStyle().WindowPadding.x, ImGui::GetCursorPos().y + ImGui::GetStyle().ItemSpacing.y)); + + auto widgetSize = widget_size_with_row_get(10); + + ImGui::BeginDisabled(!animation); + { + auto label = playback.isPlaying ? "Pause" : "Play"; + auto tooltip = playback.isPlaying ? "Pause the animation." : "Play the animation."; + + shortcut(settings.shortcutPlayPause); + if (ImGui::Button(label, widgetSize)) playback.toggle(); + set_item_tooltip_shortcut(tooltip, settings.shortcutPlayPause); + + ImGui::SameLine(); + + auto itemPtr = document.item_get(); + + ImGui::BeginDisabled(!itemPtr); + { + shortcut(settings.shortcutAdd); + if (ImGui::Button("Insert Frame", widgetSize)) + { + auto insert_frame = [&]() + { + auto frame = document.frame_get(); + if (frame) + { + itemPtr->frames.insert(itemPtr->frames.begin() + reference.frameIndex, *frame); + reference.frameIndex++; + } + else if (!itemPtr->frames.empty()) + { + auto lastFrame = itemPtr->frames.back(); + itemPtr->frames.emplace_back(lastFrame); + reference.frameIndex = static_cast(itemPtr->frames.size()) - 1; + } + }; + + DOCUMENT_EDIT(document, "Insert Frame", Document::FRAMES, insert_frame()); + } + set_item_tooltip_shortcut("Insert a frame, based on the current selection.", settings.shortcutAdd); + + ImGui::SameLine(); + + ImGui::BeginDisabled(!document.frame_get()); + { + shortcut(settings.shortcutRemove); + if (ImGui::Button("Delete Frame", widgetSize)) + { + auto delete_frame = [&]() + { + itemPtr->frames.erase(itemPtr->frames.begin() + reference.frameIndex); + reference.frameIndex = glm::max(-1, --reference.frameIndex); + }; + + DOCUMENT_EDIT(document, "Delete Frame(s)", Document::FRAMES, delete_frame()); + } + set_item_tooltip_shortcut("Delete the selected frames.", settings.shortcutRemove); + + ImGui::SameLine(); + + if (ImGui::Button("Bake", widgetSize)) bakePopup.open(); + ImGui::SetItemTooltip("Turn interpolated frames into uninterpolated ones."); + } + ImGui::EndDisabled(); + } + ImGui::EndDisabled(); + + ImGui::SameLine(); + + if (ImGui::Button("Fit Animation Length", widgetSize)) animation->frameNum = animation->length(); + ImGui::SetItemTooltip("The animation length will be set to the effective length of the animation."); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + ImGui::InputInt("Animation Length", animation ? &animation->frameNum : &dummy_value(), STEP, STEP_FAST, + !animation ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); + if (animation) animation->frameNum = clamp(animation->frameNum, anm2::FRAME_NUM_MIN, anm2::FRAME_NUM_MAX); + ImGui::SetItemTooltip("Set the animation's length."); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + ImGui::Checkbox("Loop", animation ? &animation->isLoop : &dummy_value()); + ImGui::SetItemTooltip("Toggle the animation looping."); + } + ImGui::EndDisabled(); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + ImGui::InputInt("FPS", &anm2.info.fps, 1, 5); + anm2.info.fps = clamp(anm2.info.fps, anm2::FPS_MIN, anm2::FPS_MAX); + ImGui::SetItemTooltip("Set the FPS of all animations."); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + input_text_string("Author", &anm2.info.createdBy); + ImGui::SetItemTooltip("Set the author of the document."); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + ImGui::Checkbox("Sound", &settings.timelineIsSound); + ImGui::SetItemTooltip("Toggle sounds playing with triggers.\nBind sounds to events in the Events window."); + + ImGui::PopStyleVar(); + } + ImGui::EndChild(); + + ImGui::SetCursorPos(cursorPos); + }; + + auto popups_fn = [&]() + { + auto item_properties_reset = [&]() + { + addItemName.clear(); + addItemSpritesheetID = {}; + addItemID = -1; + isUnusedItemsSet = false; + }; + + auto& anm2 = document.anm2; + + propertiesPopup.trigger(); + + if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto item_properties_close = [&]() + { + item_properties_reset(); + propertiesPopup.close(); + }; + + auto& type = settings.timelineAddItemType; + auto& locale = settings.timelineAddItemLocale; + auto& source = settings.timelineAddItemSource; + + if (!isUnusedItemsSet) + { + unusedItems = type == anm2::LAYER ? anm2.layers_unused(reference) + : type == anm2::NULL_ ? anm2.nulls_unused(reference) + : std::set{}; + + isUnusedItemsSet = true; + } + + auto footerSize = footer_size_get(); + auto optionsSize = child_size_get(11); + auto itemsSize = ImVec2(0, ImGui::GetContentRegionAvail().y - + (optionsSize.y + footerSize.y + ImGui::GetStyle().ItemSpacing.y * 4)); + if (ImGui::BeginChild("Options", optionsSize, ImGuiChildFlags_Borders)) + { + ImGui::SeparatorText("Type"); + + auto size = ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, ImGui::GetFrameHeightWithSpacing()); + + if (ImGui::BeginChild("Type Layer", size)) + { + ImGui::RadioButton("Layer", &type, anm2::LAYER); + ImGui::SetItemTooltip( + "Layers are a basic visual element in an animation, used for displaying spritesheets."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("Type Null", size)) + { + ImGui::RadioButton("Null", &type, anm2::NULL_); + ImGui::SetItemTooltip( + "Nulls are invisible elements in an animation, used for interfacing with a game engine."); + } + ImGui::EndChild(); + + ImGui::SeparatorText("Source"); + + bool isNewOnly = unusedItems.empty(); + if (isNewOnly) source = source::NEW; + + if (ImGui::BeginChild("Source New", size)) + { + ImGui::RadioButton("New", &source, source::NEW); + ImGui::SetItemTooltip("Create a new item to be used."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("Source Existing", size)) + { + ImGui::BeginDisabled(isNewOnly); + ImGui::RadioButton("Existing", &source, source::EXISTING); + ImGui::EndDisabled(); + ImGui::SetItemTooltip("Use a pre-existing, presently unused item."); + } + ImGui::EndChild(); + + ImGui::SeparatorText("Locale"); + + if (ImGui::BeginChild("Locale Global", size)) + { + ImGui::RadioButton("Global", &locale, locale::GLOBAL); + ImGui::SetItemTooltip("The item will be inserted into all animations, if not already present."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("Locale Local", size)) + { + ImGui::RadioButton("Local", &locale, locale::LOCAL); + ImGui::SetItemTooltip("The item will only be inserted into this animation."); + } + ImGui::EndChild(); + + ImGui::SeparatorText("Options"); + + ImGui::BeginDisabled(source == source::EXISTING); + { + input_text_string("Name", &addItemName); + ImGui::SetItemTooltip("Set the item's name."); + ImGui::BeginDisabled(type != anm2::LAYER); + { + combo_negative_one_indexed("Spritesheet", &addItemSpritesheetID, document.spritesheet.labels); + ImGui::SetItemTooltip("Set the layer item's spritesheet."); + } + ImGui::EndDisabled(); + } + ImGui::EndDisabled(); + } + ImGui::EndChild(); + + if (ImGui::BeginChild("Items", itemsSize, ImGuiChildFlags_Borders)) + { + if (animation && source == source::EXISTING) + { + for (auto id : unusedItems) + { + auto isSelected = addItemID == id; + + ImGui::PushID(id); + + if (type == anm2::LAYER) + { + auto& layer = anm2.content.layers[id]; + if (ImGui::Selectable( + std::format("#{} {} (Spritesheet: #{})", id, layer.name, layer.spritesheetID).c_str(), + isSelected)) + addItemID = id; + } + else if (type == anm2::NULL_) + { + auto& null = anm2.content.nulls[id]; + if (ImGui::Selectable(std::format("#{} {}", id, null.name).c_str(), isSelected)) addItemID = id; + } + + ImGui::PopID(); + } + } + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + if (ImGui::Button("Add", widgetSize)) + { + anm2::Reference addReference{}; + + document.snapshot("Add Item"); + if (type == anm2::LAYER) + addReference = anm2.layer_animation_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName, + addItemSpritesheetID - 1, (locale::Type)locale); + else if (type == anm2::NULL_) + addReference = anm2.null_animation_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName, + (locale::Type)locale); + + document.change(Document::ITEMS); + + reference = addReference; + + item_properties_close(); + } + ImGui::SetItemTooltip("Add the item, with the settings specified."); + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) item_properties_close(); + ImGui::SetItemTooltip("Cancel adding an item."); + + ImGui::EndPopup(); + } + + bakePopup.trigger(); + + if (ImGui::BeginPopupModal(bakePopup.label, &bakePopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto& interval = settings.bakeInterval; + auto& isRoundRotation = settings.bakeIsRoundRotation; + auto& isRoundScale = settings.bakeIsRoundScale; + + auto frame = document.frame_get(); + + input_int_range("Interval", interval, anm2::FRAME_DELAY_MIN, frame ? frame->delay : anm2::FRAME_DELAY_MIN); + ImGui::SetItemTooltip("Set the maximum delay of each frame that will be baked."); + + ImGui::Checkbox("Round Rotation", &isRoundRotation); + ImGui::SetItemTooltip("Rotation will be rounded to the nearest whole number."); + + ImGui::Checkbox("Round Scale", &isRoundScale); + ImGui::SetItemTooltip("Scale will be rounded to the nearest whole number."); + + auto widgetSize = widget_size_with_row_get(2); + + if (ImGui::Button("Bake", widgetSize)) + { + if (auto itemPtr = document.item_get()) + DOCUMENT_EDIT(document, "Bake Frames", Document::FRAMES, + itemPtr->frames_bake(reference.frameIndex, interval, isRoundScale, isRoundRotation)); + bakePopup.close(); + } + ImGui::SetItemTooltip("Bake the selected frame(s) with the options selected."); + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) bakePopup.close(); + ImGui::SetItemTooltip("Cancel baking frames."); + + ImGui::EndPopup(); + } + }; + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); if (ImGui::Begin("Timeline", &settings.windowIsTimeline)) { isWindowHovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); - frames_child(document, animation, settings, resources, clipboard); - items_child(manager, document, animation, settings, resources, clipboard); + frames_child(); + items_child(); } ImGui::PopStyleVar(); ImGui::End(); - popups(document, animation, settings); + popups_fn(); if (shortcut(settings.shortcutPlayPause, shortcut::GLOBAL)) playback.toggle(); @@ -1118,4 +1008,4 @@ namespace anm2ed::imgui } } } -} \ No newline at end of file +} diff --git a/src/imgui/window/timeline.h b/src/imgui/window/timeline.h index 94a9552..e1b41cc 100644 --- a/src/imgui/window/timeline.h +++ b/src/imgui/window/timeline.h @@ -1,7 +1,6 @@ #pragma once #include "clipboard.h" -#include "document.h" #include "manager.h" #include "resources.h" #include "settings.h" @@ -25,14 +24,6 @@ namespace anm2ed::imgui ImDrawList* pickerLineDrawList{}; ImGuiStyle style{}; - void context_menu(Document&, Settings&, Clipboard&); - void item_child(Manager&, Document&, anm2::Animation*, Settings&, Resources&, Clipboard&, anm2::Type, int, int&); - void items_child(Manager&, Document&, anm2::Animation*, Settings&, Resources&, Clipboard&); - void frame_child(Document&, anm2::Animation*, Settings&, Resources&, Clipboard&, anm2::Type, int, int&, float); - void frames_child(Document&, anm2::Animation*, Settings&, Resources&, Clipboard&); - - void popups(Document&, anm2::Animation*, Settings&); - public: void update(Manager&, Settings&, Resources&, Clipboard&); }; diff --git a/src/loader.cpp b/src/loader.cpp index 5113398..f5ae413 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -1,5 +1,7 @@ #include "loader.h" +#include + #include #include @@ -8,11 +10,57 @@ #include "filesystem_.h" #include "log.h" +#include "socket.h" + using namespace anm2ed::types; using namespace anm2ed::util; namespace anm2ed { + constexpr auto SOCKET_ADDRESS = "127.0.0.1"; + constexpr auto SOCKET_PORT = 11414; + + namespace + { + bool socket_paths_send(Socket& socket, const std::vector& paths) + { + uint32_t count = htonl(static_cast(paths.size())); + if (!socket.send(&count, sizeof(count))) return false; + + for (const auto& path : paths) + { + uint32_t length = htonl(static_cast(path.size())); + if (!socket.send(&length, sizeof(length))) return false; + if (!path.empty() && !socket.send(path.data(), path.size())) return false; + } + + return true; + } + + std::vector socket_paths_receive(Socket& socket) + { + uint32_t count{}; + if (!socket.receive(&count, sizeof(count))) return {}; + count = ntohl(count); + + std::vector paths; + paths.reserve(count); + + for (uint32_t i = 0; i < count; ++i) + { + uint32_t length{}; + if (!socket.receive(&length, sizeof(length))) return {}; + length = ntohl(length); + + std::string path(length, '\0'); + if (length > 0 && !socket.receive(path.data(), length)) return {}; + paths.emplace_back(std::move(path)); + } + + return paths; + } + } + std::string Loader::settings_path() { return filesystem::path_preferences_get() + "settings.ini"; @@ -23,6 +71,45 @@ namespace anm2ed for (int i = 1; i < argc; i++) arguments.emplace_back(argv[i]); + Socket testSocket; + if (!testSocket.open(SERVER)) + logger.warning(std::format("Failed to open socket; single instancing will not work.")); + + bool isPrimaryInstance = false; + + if (testSocket.bind({SOCKET_ADDRESS, SOCKET_PORT})) + { + socket = std::move(testSocket); + + if (!socket.listen()) + logger.warning("Could not listen on socket; single instancing disabled."); + else + { + isPrimaryInstance = true; + isSocketThread = true; + logger.info(std::format("Opened socket at {}:{}", SOCKET_ADDRESS, SOCKET_PORT)); + } + } + else + { + logger.info(std::format("Existing instance of program exists; passing arguments...")); + Socket clientSocket; + if (!clientSocket.open(CLIENT)) + logger.warning("Could not open client socket to forward arguments."); + else if (!clientSocket.connect({SOCKET_ADDRESS, SOCKET_PORT})) + logger.warning("Could not connect to existing instance."); + else if (!socket_paths_send(clientSocket, arguments)) + logger.warning("Failed to transfer arguments to existing instance."); + else + logger.info("Sent arguments to existing instance. Exiting."); + + if (!isPrimaryInstance) + { + isError = true; + return; + } + } + settings = Settings(settings_path()); if (!SDL_Init(SDL_INIT_VIDEO)) @@ -93,10 +180,54 @@ namespace anm2ed io.ConfigWindowsMoveFromTitleBarOnly = true; ImGui::LoadIniSettingsFromDisk(settings_path().c_str()); + + if (isSocketThread) + { + isSocketRunning = true; + socketThread = std::thread( + [this]() + { + while (isSocketRunning) + { + auto client = socket.accept(); + if (!client.is_valid()) + { + if (!isSocketRunning) break; + continue; + } + + auto paths = socket_paths_receive(client); + for (auto& path : paths) + { + if (path.empty()) continue; + SDL_Event event{}; + event.type = SDL_EVENT_DROP_FILE; + event.drop.data = SDL_strdup(path.c_str()); + event.drop.windowID = window ? SDL_GetWindowID(window) : 0; + SDL_PushEvent(&event); + } + } + }); + } } Loader::~Loader() { + if (isSocketThread) + { + isSocketRunning = false; + + if (socket.is_valid()) + { + Socket wakeSocket; + if (wakeSocket.open(CLIENT) && wakeSocket.connect({SOCKET_ADDRESS, SOCKET_PORT})) + socket_paths_send(wakeSocket, {}); + } + + socket.close(); + if (socketThread.joinable()) socketThread.join(); + } + if (ImGui::GetCurrentContext()) { settings.save(settings_path(), ImGui::SaveIniSettingsToMemory(nullptr)); @@ -115,4 +246,4 @@ namespace anm2ed SDL_Quit(); } } -} \ No newline at end of file +} diff --git a/src/loader.h b/src/loader.h index 31c751a..3a2c1d5 100644 --- a/src/loader.h +++ b/src/loader.h @@ -1,11 +1,14 @@ #pragma once +#include #include +#include #include #include #include "settings.h" +#include "socket.h" namespace anm2ed { @@ -14,11 +17,15 @@ namespace anm2ed std::string settings_path(); public: + Socket socket{}; + std::thread socketThread{}; + std::atomic_bool isSocketRunning{}; SDL_Window* window{}; SDL_GLContext glContext{}; Settings settings; std::vector arguments; bool isError{}; + bool isSocketThread{}; Loader(int, const char**); ~Loader(); diff --git a/src/manager.cpp b/src/manager.cpp index 086d080..016730e 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -14,20 +14,9 @@ namespace anm2ed { constexpr std::size_t RECENT_LIMIT = 10; - std::filesystem::path Manager::recent_files_path_get() - { - return filesystem::path_preferences_get() + "recent.txt"; - } - - std::filesystem::path Manager::autosave_path_get() - { - return filesystem::path_preferences_get() + "autosave.txt"; - } - - std::filesystem::path Manager::autosave_directory_get() - { - return filesystem::path_preferences_get() + "autosave"; - } + std::filesystem::path Manager::recent_files_path_get() { return filesystem::path_preferences_get() + "recent.txt"; } + std::filesystem::path Manager::autosave_path_get() { return filesystem::path_preferences_get() + "autosave.txt"; } + std::filesystem::path Manager::autosave_directory_get() { return filesystem::path_preferences_get() + "autosave"; } Manager::Manager() { @@ -35,10 +24,7 @@ namespace anm2ed autosave_files_load(); } - Document* Manager::get(int index) - { - return vector::find(documents, index > -1 ? index : selected); - } + Document* Manager::get(int index) { return vector::find(documents, index > -1 ? index : selected); } void Manager::open(const std::string& path, bool isNew, bool isRecent) { @@ -68,10 +54,7 @@ namespace anm2ed toasts.info(std::format("Opened document: {}", path)); } - void Manager::new_(const std::string& path) - { - open(path, true); - } + void Manager::new_(const std::string& path) { open(path, true); } void Manager::save(int index, const std::string& path) { @@ -83,10 +66,7 @@ namespace anm2ed } } - void Manager::save(const std::string& path) - { - save(selected, path); - } + void Manager::save(const std::string& path) { save(selected, path); } void Manager::autosave(Document& document) { @@ -155,15 +135,9 @@ namespace anm2ed } } - void Manager::layer_properties_trigger() - { - layerPropertiesPopup.trigger(); - } + void Manager::layer_properties_trigger() { layerPropertiesPopup.trigger(); } - void Manager::layer_properties_end() - { - layerPropertiesPopup.end(); - } + void Manager::layer_properties_end() { layerPropertiesPopup.end(); } void Manager::layer_properties_close() { @@ -186,15 +160,9 @@ namespace anm2ed } } - void Manager::null_properties_trigger() - { - nullPropertiesPopup.trigger(); - } + void Manager::null_properties_trigger() { nullPropertiesPopup.trigger(); } - void Manager::null_properties_end() - { - nullPropertiesPopup.end(); - } + void Manager::null_properties_end() { nullPropertiesPopup.end(); } void Manager::null_properties_close() { @@ -313,8 +281,5 @@ namespace anm2ed autosave_files_write(); } - Manager::~Manager() - { - autosave_files_clear(); - } + Manager::~Manager() { autosave_files_clear(); } } diff --git a/src/render.cpp b/src/render.cpp index 3258c2f..5d43203 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -1,7 +1,10 @@ #include "render.h" +#include #include +#include #include +#include #ifdef _WIN32 #include "util.h" @@ -9,7 +12,7 @@ #define PCLOSE _pclose #define PWRITE_MODE "wb" #define PREAD_MODE "r" -#else +#elif __unix__ #define POPEN popen #define PCLOSE pclose #define PWRITE_MODE "w" @@ -25,44 +28,87 @@ namespace anm2ed { constexpr auto FFMPEG_POPEN_ERROR = "popen() (for FFmpeg) failed!\n{}"; - constexpr auto GIF_FORMAT = "\"{0}\" -y " - "-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " - "-lavfi \"split[s0][s1];" - "[s0]palettegen=stats_mode=full[p];" - "[s1][p]paletteuse=dither=floyd_steinberg\" " - "-loop 0 \"{4}\""; - - constexpr auto WEBM_FORMAT = "\"{0}\" -y " - "-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " - "-c:v libvpx-vp9 -crf 30 -b:v 0 -pix_fmt yuva420p -row-mt 1 -threads 0 -speed 2 " - "-auto-alt-ref 0 -an \"{4}\""; - - constexpr auto* MP4_FORMAT = "\"{0}\" -y " - "-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " - "-vf \"format=yuv420p,scale=trunc(iw/2)*2:trunc(ih/2)*2\" " - "-c:v libx265 -crf 20 -preset slow " - "-tag:v hvc1 -movflags +faststart -an \"{4}\""; - bool animation_render(const std::string& ffmpegPath, const std::string& path, std::vector& frames, - render::Type type, ivec2 size, int fps) + AudioStream& audioStream, render::Type type, ivec2 size, int fps) { if (frames.empty() || size.x <= 0 || size.y <= 0 || fps <= 0 || ffmpegPath.empty() || path.empty()) return false; + std::filesystem::path audioPath{}; + std::string audioInputArguments{}; + std::string audioOutputArguments{"-an"}; std::string command{}; + auto remove_audio_file = [&]() + { + if (!audioPath.empty()) + { + std::error_code ec; + std::filesystem::remove(audioPath, ec); + } + }; + + if (type != render::GIF && !audioStream.stream.empty() && audioStream.spec.freq > 0 && + audioStream.spec.channels > 0) + { + audioPath = std::filesystem::temp_directory_path() / std::format("{}.f32", path); + + std::ofstream audioFile(audioPath, std::ios::binary); + + if (audioFile) + { + auto data = (const char*)audioStream.stream.data(); + auto byteCount = audioStream.stream.size() * sizeof(float); + audioFile.write(data, byteCount); + audioFile.close(); + + audioInputArguments = std::format("-f f32le -ar {0} -ac {1} -i \"{2}\"", audioStream.spec.freq, + audioStream.spec.channels, audioPath.string()); + + switch (type) + { + case render::WEBM: + audioOutputArguments = "-c:a libopus -b:a 160k -shortest"; + break; + case render::MP4: + audioOutputArguments = "-c:a aac -b:a 192k -shortest"; + break; + default: + break; + } + } + else + { + logger.warning("Failed to open temporary audio file; exporting video without audio."); + remove_audio_file(); + } + } + + command = std::format("\"{0}\" -y -f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0", ffmpegPath, size.x, + size.y, fps); + + if (!audioInputArguments.empty()) command += " " + audioInputArguments; + switch (type) { case render::GIF: - command = std::format(GIF_FORMAT, ffmpegPath, size.x, size.y, fps, path); + command += + " -lavfi \"split[s0][s1];[s0]palettegen=stats_mode=full[p];[s1][p]paletteuse=dither=floyd_steinberg\"" + " -loop 0"; + command += std::format(" \"{}\"", path); break; case render::WEBM: - command = std::format(WEBM_FORMAT, ffmpegPath, size.x, size.y, fps, path); + command += " -c:v libvpx-vp9 -crf 30 -b:v 0 -pix_fmt yuva420p -row-mt 1 -threads 0 -speed 2 -auto-alt-ref 0"; + if (!audioOutputArguments.empty()) command += " " + audioOutputArguments; + command += std::format(" \"{}\"", path); break; case render::MP4: - command = std::format(MP4_FORMAT, ffmpegPath, size.x, size.y, fps, path); + command += " -vf \"format=yuv420p,scale=trunc(iw/2)*2:trunc(ih/2)*2\" -c:v libx265 -crf 20 -preset slow" + " -tag:v hvc1 -movflags +faststart"; + if (!audioOutputArguments.empty()) command += " " + audioOutputArguments; + command += std::format(" \"{}\"", path); break; default: - break; + return false; } #if _WIN32 @@ -75,6 +121,7 @@ namespace anm2ed if (!fp) { + remove_audio_file(); logger.error(std::format(FFMPEG_POPEN_ERROR, strerror(errno))); return false; } @@ -85,12 +132,14 @@ namespace anm2ed if (fwrite(frame.pixels.data(), 1, frameSize, fp) != frameSize) { + remove_audio_file(); PCLOSE(fp); return false; } } auto code = PCLOSE(fp); + remove_audio_file(); return (code == 0); } -} \ No newline at end of file +} diff --git a/src/render.h b/src/render.h index 22f42d8..22df9a7 100644 --- a/src/render.h +++ b/src/render.h @@ -1,5 +1,6 @@ #pragma once +#include "audio_stream.h" #include "texture.h" namespace anm2ed::render @@ -33,6 +34,6 @@ namespace anm2ed::render namespace anm2ed { - bool animation_render(const std::string&, const std::string&, std::vector&, render::Type, - glm::ivec2, int); + bool animation_render(const std::string&, const std::string&, std::vector&, AudioStream&, + render::Type, glm::ivec2, int); } \ No newline at end of file diff --git a/src/resource/audio_stream.cpp b/src/resource/audio_stream.cpp new file mode 100644 index 0000000..8c2c333 --- /dev/null +++ b/src/resource/audio_stream.cpp @@ -0,0 +1,26 @@ +#include "audio_stream.h" + +namespace anm2ed +{ + void AudioStream::callback(void* userData, MIX_Mixer* mixer, const SDL_AudioSpec* spec, float* pcm, int samples) + { + auto self = (AudioStream*)userData; + self->stream.insert(self->stream.end(), pcm, pcm + samples); + } + + AudioStream::AudioStream(MIX_Mixer* mixer) + { + MIX_GetMixerFormat(mixer, &spec); + } + + void AudioStream::capture_begin(MIX_Mixer* mixer) + { + MIX_SetPostMixCallback(mixer, callback, this); + } + + void AudioStream::capture_end(MIX_Mixer* mixer) + { + MIX_SetPostMixCallback(mixer, nullptr, this); + stream.clear(); + } +} \ No newline at end of file diff --git a/src/resource/audio_stream.h b/src/resource/audio_stream.h new file mode 100644 index 0000000..1cbb90f --- /dev/null +++ b/src/resource/audio_stream.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +namespace anm2ed +{ + class AudioStream + { + static void callback(void*, MIX_Mixer*, const SDL_AudioSpec*, float*, int); + + public: + std::vector stream{}; + SDL_AudioSpec spec{}; + + AudioStream(MIX_Mixer*); + void capture_begin(MIX_Mixer*); + void capture_end(MIX_Mixer*); + }; +} \ No newline at end of file diff --git a/src/resource/icon.h b/src/resource/icon.h index 4101ddf..784faf3 100644 --- a/src/resource/icon.h +++ b/src/resource/icon.h @@ -153,7 +153,7 @@ namespace anm2ed::resource::icon )"; -#define LIST \ +#define SVG_LIST \ X(NONE, NONE_DATA, SIZE_SMALL) \ X(FILE, FILE_DATA, SIZE_NORMAL) \ X(FOLDER, FOLDER_DATA, SIZE_NORMAL) \ @@ -195,7 +195,7 @@ namespace anm2ed::resource::icon enum Type { #define X(name, data, size) name, - LIST + SVG_LIST #undef X COUNT }; @@ -209,7 +209,21 @@ namespace anm2ed::resource::icon const Info ICONS[COUNT] = { #define X(name, data, size) {data, std::strlen(data) - 1, size}, - LIST + SVG_LIST #undef X }; + + constexpr uint8_t PROGRAM[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb9, 0x55, 0x00, 0x00, 0x00, 0x09, 0x70, + 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, + 0x8b, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xed, 0xd7, 0x3d, 0x0e, 0x80, 0x20, 0x0c, 0x86, 0x61, 0x7b, 0x53, 0x3c, + 0x99, 0xbd, 0x69, 0x1d, 0x8c, 0x83, 0x4d, 0xd0, 0x44, 0x29, 0x7f, 0xbe, 0x5d, 0x08, 0x30, 0xf4, 0x19, 0x80, 0x2f, + 0xc8, 0xd2, 0xb8, 0x04, 0xc0, 0xb4, 0x80, 0x64, 0xc7, 0xb8, 0xf9, 0x86, 0x02, 0x60, 0x36, 0x80, 0xd9, 0x75, 0xbe, + 0xba, 0x7d, 0x00, 0xf3, 0x00, 0x72, 0x8d, 0x7c, 0x83, 0x73, 0x5d, 0xa5, 0xf0, 0x43, 0x04, 0xa0, 0x1a, 0x20, 0xaa, + 0x11, 0x80, 0xf1, 0x01, 0x1a, 0x14, 0x5b, 0x00, 0xfa, 0x03, 0x24, 0xbb, 0x0f, 0x93, 0xa7, 0xb0, 0xf9, 0x1c, 0x46, + 0x00, 0x00, 0x00, 0xe8, 0x06, 0xa0, 0xa5, 0x3f, 0x2a, 0x99, 0x07, 0x0d, 0x40, 0xbf, 0x80, 0xa8, 0x02, 0x30, 0x0e, + 0x40, 0xdf, 0x1e, 0xb2, 0x56, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x07, 0x90, 0x86, 0xff, 0x05, 0xd4, + 0x2e, 0x00, 0x00, 0x00, 0x34, 0x07, 0xec, 0x94, 0x51, 0xac, 0x41, 0x55, 0x6e, 0xe4, 0x26, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82}; } \ No newline at end of file diff --git a/src/resource/texture.cpp b/src/resource/texture.cpp index 89170ec..fc75619 100644 --- a/src/resource/texture.cpp +++ b/src/resource/texture.cpp @@ -28,15 +28,9 @@ using namespace glm; namespace anm2ed::resource { - bool Texture::is_valid() - { - return id != 0; - } + bool Texture::is_valid() { return id != 0; } - size_t Texture::pixel_size_get() - { - return size.x * size.y * CHANNELS; - } + size_t Texture::pixel_size_get() { return size.x * size.y * CHANNELS; } void Texture::upload(const uint8_t* data) { @@ -66,15 +60,9 @@ namespace anm2ed::resource if (is_valid()) glDeleteTextures(1, &id); } - Texture::Texture(const Texture& other) - { - *this = other; - } + Texture::Texture(const Texture& other) { *this = other; } - Texture::Texture(Texture&& other) - { - *this = std::move(other); - } + Texture::Texture(Texture&& other) { *this = std::move(other); } Texture& Texture::operator=(const Texture& other) // Copy { diff --git a/src/resource/texture.h b/src/resource/texture.h index c73e138..87d9894 100644 --- a/src/resource/texture.h +++ b/src/resource/texture.h @@ -26,8 +26,8 @@ namespace anm2ed::resource size_t pixel_size_get(); void upload(); void upload(const uint8_t*); - Texture(); + Texture(); ~Texture(); Texture(const Texture&); Texture(Texture&&); diff --git a/src/settings.cpp b/src/settings.cpp index 84e22f8..7429bbb 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -10,97 +10,97 @@ namespace anm2ed { constexpr auto IMGUI_DEFAULT = R"( # Dear ImGui -[Window][## Window] -Pos=0,32 -Size=1600,868 +[Window][##DockSpace] +Pos=0,54 +Size=1918,1010 Collapsed=0 -[Window][Debug##Default] -Pos=60,60 -Size=400,400 -Collapsed=0 - -[Window][Tools] -Pos=8,40 -Size=38,516 -Collapsed=0 -DockId=0x0000000B,0 - -[Window][Animations] -Pos=1289,307 -Size=303,249 -Collapsed=0 -DockId=0x0000000A,0 - -[Window][Events] -Pos=957,264 -Size=330,292 -Collapsed=0 -DockId=0x00000008,2 - -[Window][Spritesheets] -Pos=1289,40 -Size=303,265 -Collapsed=0 -DockId=0x00000009,0 - [Window][Animation Preview] -Pos=48,40 -Size=907,516 +Pos=60,62 +Size=983,691 +Collapsed=0 +DockId=0x00000003,1 + +[Window][Animations] +Pos=1451,494 +Size=459,259 Collapsed=0 DockId=0x0000000C,0 -[Window][Spritesheet Editor] -Pos=48,40 -Size=907,516 -Collapsed=0 -DockId=0x0000000C,1 - -[Window][Timeline] -Pos=8,558 -Size=1584,334 -Collapsed=0 -DockId=0x00000004,0 - -[Window][Frame Properties] -Pos=957,40 -Size=330,222 -Collapsed=0 -DockId=0x00000007,0 - -[Window][Onionskin] -Pos=957,264 -Size=330,292 -Collapsed=0 -DockId=0x00000008,3 - -[Window][Layers] -Pos=957,264 -Size=330,292 +[Window][Events] +Pos=1045,463 +Size=404,290 Collapsed=0 DockId=0x00000008,0 -[Window][Nulls] -Pos=957,264 -Size=330,292 +[Window][Frame Properties] +Pos=1045,62 +Size=404,399 +Collapsed=0 +DockId=0x00000007,0 + +[Window][Layers] +Pos=1045,463 +Size=404,290 Collapsed=0 DockId=0x00000008,1 +[Window][Nulls] +Pos=1045,463 +Size=404,290 +Collapsed=0 +DockId=0x00000008,2 + +[Window][Onionskin] +Pos=8,755 +Size=1902,301 +Collapsed=0 +DockId=0x00000006,1 + +[Window][Spritesheet Editor] +Pos=60,62 +Size=983,691 +Collapsed=0 +DockId=0x00000003,0 + +[Window][Spritesheets] +Pos=1451,62 +Size=459,430 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][Tools] +Pos=8,62 +Size=50,691 +Collapsed=0 +DockId=0x00000001,0 + +[Window][Timeline] +Pos=8,755 +Size=1902,301 +Collapsed=0 +DockId=0x00000006,0 + +[Window][Sounds] +Pos=1045,463 +Size=404,290 +Collapsed=0 +DockId=0x00000008,3 [Docking][Data] -DockSpace ID=0xFC02A410 Window=0x0E46F4F7 Pos=8,40 Size=1584,852 Split=Y - DockNode ID=0x00000003 Parent=0xFC02A410 SizeRef=1902,680 Split=X - DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1017,1016 Split=X Selected=0x024430EF - DockNode ID=0x00000005 Parent=0x00000001 SizeRef=1264,654 Split=X Selected=0x024430EF - DockNode ID=0x0000000B Parent=0x00000005 SizeRef=38,654 Selected=0x18A5FDB9 - DockNode ID=0x0000000C Parent=0x00000005 SizeRef=1224,654 CentralNode=1 Selected=0x024430EF - DockNode ID=0x00000006 Parent=0x00000001 SizeRef=330,654 Split=Y Selected=0x754E368F - DockNode ID=0x00000007 Parent=0x00000006 SizeRef=631,293 Selected=0x754E368F - DockNode ID=0x00000008 Parent=0x00000006 SizeRef=631,385 Selected=0xCD8384B1 - DockNode ID=0x00000002 Parent=0x00000003 SizeRef=303,1016 Split=Y Selected=0x4EFD0020 - DockNode ID=0x00000009 Parent=0x00000002 SizeRef=634,349 Selected=0x4EFD0020 - DockNode ID=0x0000000A Parent=0x00000002 SizeRef=634,329 Selected=0xC1986EE2 - DockNode ID=0x00000004 Parent=0xFC02A410 SizeRef=1902,334 Selected=0x4F89F0DC +DockSpace ID=0x123F8F08 Window=0x6D581B32 Pos=8,62 Size=1902,994 Split=Y Selected=0x4EFD0020 + DockNode ID=0x00000005 Parent=0x123F8F08 SizeRef=1910,691 Split=X + DockNode ID=0x00000001 Parent=0x00000005 SizeRef=50,994 Selected=0x18A5FDB9 + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1850,994 Split=X Selected=0x4EFD0020 + DockNode ID=0x00000003 Parent=0x00000002 SizeRef=983,994 Selected=0x024430EF + DockNode ID=0x00000004 Parent=0x00000002 SizeRef=865,994 Split=X Selected=0x4EFD0020 + DockNode ID=0x00000009 Parent=0x00000004 SizeRef=404,497 Split=Y Selected=0xCD8384B1 + DockNode ID=0x00000007 Parent=0x00000009 SizeRef=181,399 Selected=0x754E368F + DockNode ID=0x00000008 Parent=0x00000009 SizeRef=181,290 Selected=0x8A65D963 + DockNode ID=0x0000000A Parent=0x00000004 SizeRef=459,497 Split=Y Selected=0x4EFD0020 + DockNode ID=0x0000000B Parent=0x0000000A SizeRef=710,430 CentralNode=1 Selected=0x4EFD0020 + DockNode ID=0x0000000C Parent=0x0000000A SizeRef=710,259 Selected=0xC1986EE2 + DockNode ID=0x00000006 Parent=0x123F8F08 SizeRef=1910,301 Selected=0x4F89F0DC )"; Settings::Settings(const std::string& path) diff --git a/src/settings.h b/src/settings.h index e25bfd8..db1ac02 100644 --- a/src/settings.h +++ b/src/settings.h @@ -153,8 +153,8 @@ namespace anm2ed /* Symbol / Name / String / Type / Default */ \ X(SHORTCUT_CENTER_VIEW, shortcutCenterView, "Center View", STRING, "Home") \ X(SHORTCUT_FIT, shortcutFit, "Fit", STRING, "F") \ - X(SHORTCUT_ZOOM_IN, shortcutZoomIn, "Zoom In", STRING, "Ctrl++") \ - X(SHORTCUT_ZOOM_OUT, shortcutZoomOut, "Zoom Out", STRING, "Ctrl+-") \ + X(SHORTCUT_ZOOM_IN, shortcutZoomIn, "Zoom In", STRING, "Ctrl+Equal") \ + X(SHORTCUT_ZOOM_OUT, shortcutZoomOut, "Zoom Out", STRING, "Ctrl+Minus") \ X(SHORTCUT_PLAY_PAUSE, shortcutPlayPause, "Play/Pause", STRING, "Space") \ X(SHORTCUT_ONIONSKIN, shortcutOnionskin, "Onionskin", STRING, "O") \ X(SHORTCUT_NEW, shortcutNew, "New", STRING, "Ctrl+N") \ diff --git a/src/snapshots.cpp b/src/snapshots.cpp index 582b8ba..c9df201 100644 --- a/src/snapshots.cpp +++ b/src/snapshots.cpp @@ -4,10 +4,7 @@ using namespace anm2ed::snapshots; namespace anm2ed { - bool SnapshotStack::is_empty() - { - return top == 0; - } + bool SnapshotStack::is_empty() { return top == 0; } void SnapshotStack::push(const Snapshot& snapshot) { @@ -26,10 +23,7 @@ namespace anm2ed return &snapshots[--top]; } - void SnapshotStack::clear() - { - top = 0; - } + void SnapshotStack::clear() { top = 0; } void Snapshots::push(const Snapshot& snapshot) { diff --git a/src/snapshots.h b/src/snapshots.h index 3fefd20..ee7382d 100644 --- a/src/snapshots.h +++ b/src/snapshots.h @@ -25,6 +25,8 @@ namespace anm2ed Storage null{}; Storage sound{}; Storage spritesheet{}; + Storage items{}; + std::map frames{}; std::string message = snapshots::ACTION; }; diff --git a/src/socket.cpp b/src/socket.cpp new file mode 100644 index 0000000..4b408e7 --- /dev/null +++ b/src/socket.cpp @@ -0,0 +1,161 @@ +#include "socket.h" + +namespace anm2ed +{ +#ifdef _WIN32 + namespace + { + struct WSAInitializer + { + WSAInitializer() + { + WSADATA data{}; + WSAStartup(MAKEWORD(2, 2), &data); + } + ~WSAInitializer() { WSACleanup(); } + }; + + WSAInitializer initializer{}; + } +#endif + + Socket::Socket() : handle(SOCKET_INVALID), role(CLIENT) {} + + Socket::Socket(Socket&& other) noexcept : handle(other.handle), role(other.role) { other.handle = SOCKET_INVALID; } + + Socket& Socket::operator=(Socket&& other) noexcept + { + if (this != &other) + { + close(); + handle = other.handle; + role = other.role; + other.handle = SOCKET_INVALID; + } + + return *this; + } + + Socket::~Socket() { close(); } + + bool Socket::open(SocketRole newRole) + { + close(); + role = newRole; + + handle = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (!is_valid()) return false; + + if (role == SERVER) + { +#ifdef _WIN32 + BOOL opt = TRUE; +#else + int opt = 1; +#endif + ::setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&opt), sizeof(opt)); + } + + return true; + } + + bool Socket::bind(const SocketAddress& address) + { + if (!is_valid()) return false; + + sockaddr_in addr{}; + addr.sin_family = AF_INET; + addr.sin_port = htons(address.port); + + if (address.host.empty()) + addr.sin_addr.s_addr = htonl(INADDR_ANY); + else + { + if (::inet_pton(AF_INET, address.host.c_str(), &addr.sin_addr) <= 0) return false; + } + + return ::bind(handle, reinterpret_cast(&addr), sizeof(addr)) == 0; + } + + bool Socket::listen() + { + if (!is_valid()) return false; + return ::listen(handle, SOMAXCONN) == 0; + } + + Socket Socket::accept() + { + Socket client{}; + if (!is_valid()) return client; + + auto accepted = ::accept(handle, nullptr, nullptr); + if (accepted == SOCKET_INVALID) return client; + + client.close(); + client.handle = accepted; + client.role = CLIENT; + return client; + } + + bool Socket::connect(const SocketAddress& address) + { + if (!is_valid()) return false; + + sockaddr_in addr{}; + addr.sin_family = AF_INET; + addr.sin_port = htons(address.port); + + if (::inet_pton(AF_INET, address.host.c_str(), &addr.sin_addr) <= 0) return false; + + return ::connect(handle, reinterpret_cast(&addr), sizeof(addr)) == 0; + } + + bool Socket::send(const void* data, size_t size) + { + if (!is_valid() || !data || size == 0) return false; + + auto bytes = reinterpret_cast(data); + size_t totalSent = 0; + + while (totalSent < size) + { + auto sent = ::send(handle, bytes + totalSent, static_cast(size - totalSent), 0); + if (sent <= 0) return false; + totalSent += static_cast(sent); + } + + return true; + } + + bool Socket::receive(void* buffer, size_t size) + { + if (!is_valid() || !buffer || size == 0) return false; + + auto* bytes = reinterpret_cast(buffer); + size_t totalReceived = 0; + + while (totalReceived < size) + { + auto received = ::recv(handle, bytes + totalReceived, static_cast(size - totalReceived), 0); + if (received <= 0) return false; + totalReceived += static_cast(received); + } + + return true; + } + + void Socket::close() + { + if (!is_valid()) return; + +#ifdef _WIN32 + ::closesocket(handle); +#else + ::close(handle); +#endif + handle = SOCKET_INVALID; + } + + bool Socket::is_valid() const { return handle != SOCKET_INVALID; } +} diff --git a/src/socket.h b/src/socket.h new file mode 100644 index 0000000..ee8e4ea --- /dev/null +++ b/src/socket.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include + +#ifdef _WIN32 + #include + #include +using socket_handle = SOCKET; +constexpr socket_handle SOCKET_INVALID = INVALID_SOCKET; +#else + #include + #include + #include + #include +using socket_handle = int; +constexpr socket_handle SOCKET_INVALID = -1; +#endif + +namespace anm2ed +{ + enum SocketRole + { + SERVER, + CLIENT + }; + + struct SocketAddress + { + std::string host{}; + unsigned short port{}; + }; + + class Socket + { + private: + socket_handle handle; + SocketRole role{}; + + public: + Socket(); + ~Socket(); + + Socket(const Socket&) = delete; + Socket& operator=(const Socket&) = delete; + Socket(Socket&& other) noexcept; + Socket& operator=(Socket&& other) noexcept; + + bool open(SocketRole role); + bool bind(const SocketAddress&); + bool listen(); + Socket accept(); + bool connect(const SocketAddress&); + + bool send(const void*, size_t); + bool receive(void*, size_t); + + void close(); + bool is_valid() const; + }; +} diff --git a/src/state.cpp b/src/state.cpp index d6ea49b..545b835 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -52,7 +52,10 @@ namespace anm2ed { auto droppedFile = event.drop.data; if (filesystem::path_is_extension(droppedFile, "anm2")) + { manager.open(std::string(droppedFile)); + SDL_FlashWindow(window, SDL_FLASH_UNTIL_FOCUSED); + } else if (filesystem::path_is_extension(droppedFile, "png")) { if (auto document = manager.get()) diff --git a/src/util/filesystem_.cpp b/src/util/filesystem_.cpp index 7a665d6..251df42 100644 --- a/src/util/filesystem_.cpp +++ b/src/util/filesystem_.cpp @@ -8,14 +8,37 @@ namespace anm2ed::util::filesystem { - std::string path_preferences_get() + std::string path_pref_get(const char* org, const char* app) { - char* preferencesPath = SDL_GetPrefPath("", "anm2ed"); - std::string preferencesPathString = preferencesPath; - SDL_free(preferencesPath); - return preferencesPathString; + auto path = SDL_GetPrefPath(org, app); + std::string string = path; + SDL_free(path); + return string; } + std::string path_preferences_get() { return path_pref_get(nullptr, "anm2ed"); } + std::string path_base_get() { return std::string(SDL_GetBasePath()); } + std::string path_executable_get() { return std::filesystem::path(path_base_get()) / "anm2ed"; } + +#ifdef __unix__ + std::string path_application_get() + { + return std::filesystem::path(path_pref_get(nullptr, "applications")) / "anm2ed.desktop"; + } + + std::string path_mime_get() + { + return std::filesystem::path(path_pref_get(nullptr, "mime/application")) / "x-anm2+xml.xml"; + } + + std::string path_icon_get() { return std::filesystem::path(path_preferences_get()) / "anm2ed.png"; } + std::string path_icon_file_get() + { + return std::filesystem::path(path_preferences_get()) / "application-x-anm2+xml.png"; + } + +#endif + bool path_is_exist(const std::string& path) { std::error_code errorCode; @@ -49,8 +72,5 @@ namespace anm2ed::util::filesystem std::filesystem::current_path(path); } - WorkingDirectory::~WorkingDirectory() - { - std::filesystem::current_path(previous); - } + WorkingDirectory::~WorkingDirectory() { std::filesystem::current_path(previous); } } \ No newline at end of file diff --git a/src/util/filesystem_.h b/src/util/filesystem_.h index c13fcf6..f9bf2e7 100644 --- a/src/util/filesystem_.h +++ b/src/util/filesystem_.h @@ -5,9 +5,21 @@ namespace anm2ed::util::filesystem { +#ifdef __unix__ + std::string path_application_get(); + std::string path_mime_get(); + std::string path_icon_get(); + std::string path_icon_file_get(); +#endif + + std::string path_pref_get(); std::string path_preferences_get(); + std::string path_base_get(); + std::string path_executable_get(); + bool path_is_exist(const std::string&); bool path_is_extension(const std::string&, const std::string&); + std::filesystem::path path_lower_case_backslash_handle(std::filesystem::path&); class WorkingDirectory From 48d873230b0b4c463c61616cc2e1a49b4257f299 Mon Sep 17 00:00:00 2001 From: shweet Date: Mon, 10 Nov 2025 23:59:18 -0500 Subject: [PATCH 14/15] Help -> About...almoooooooooost......... --- .gitmodules | 3 +++ external/libxm | 1 + 2 files changed, 4 insertions(+) create mode 160000 external/libxm diff --git a/.gitmodules b/.gitmodules index 39508a8..7172566 100644 --- a/.gitmodules +++ b/.gitmodules @@ -17,3 +17,6 @@ [submodule "external/SDL_mixer"] path = external/SDL_mixer url = https://github.com/libsdl-org/SDL_mixer +[submodule "external/libxm"] + path = external/libxm + url = https://github.com/Artefact2/libxm diff --git a/external/libxm b/external/libxm new file mode 160000 index 0000000..9f599c4 --- /dev/null +++ b/external/libxm @@ -0,0 +1 @@ +Subproject commit 9f599c4dd4079700e2d9b8af62dc1ab8d76808f5 From 4e5ee603f286eacd03bf87a1e956c0d52f726baf Mon Sep 17 00:00:00 2001 From: shweet Date: Tue, 11 Nov 2025 00:03:35 -0500 Subject: [PATCH 15/15] eh? --- src/resource/xm_music.h | 1744 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1744 insertions(+) create mode 100644 src/resource/xm_music.h diff --git a/src/resource/xm_music.h b/src/resource/xm_music.h new file mode 100644 index 0000000..9de74a0 --- /dev/null +++ b/src/resource/xm_music.h @@ -0,0 +1,1744 @@ +#pragma once + +#include +#include + +namespace anm2ed::resource::xm +{ + // Drozerix - Keygen Wraith + // https://modarchive.org/module.php?207854 + // Licensed under the Public Domain license (https://creativecommons.org/licenses/publicdomain/) + // .::~~Dr0ZERiX~~::. + // . . + // . Keygen Wraith . + // ----------------- + // + // A specter now + // for many years... + // ------------------2024 + // Drozerix_gmail.com + constexpr uint8_t ABOUT[] = { + 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x3a, 0x20, 0x4b, 0x65, + 0x79, 0x67, 0x65, 0x6e, 0x20, 0x57, 0x72, 0x61, 0x69, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, + 0x4d, 0x69, 0x6c, 0x6b, 0x79, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31, 0x2e, 0x30, 0x32, 0x2e, 0x30, + 0x30, 0x04, 0x01, 0x14, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x01, 0x00, + 0x07, 0x00, 0xf0, 0x00, 0x08, 0x0d, 0x00, 0x01, 0x04, 0x03, 0x05, 0x09, 0x0a, 0x0b, 0x0c, 0x01, 0x04, 0x03, 0x05, + 0x06, 0x02, 0x0e, 0x07, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x14, 0x03, 0x87, 0x33, 0x02, 0x20, 0x95, 0x33, 0x30, 0x37, 0x1b, 0x09, 0x50, 0x04, 0xa1, 0x83, 0x33, 0x07, + 0x80, 0x83, 0x25, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, + 0x8b, 0x22, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x30, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x98, 0x06, 0x01, 0x87, + 0x1b, 0x09, 0x30, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x27, 0x0b, 0x04, 0x80, 0x80, 0x83, 0x35, 0x05, 0x80, 0x94, + 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x22, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x22, 0x0c, 0x04, 0x80, 0x80, + 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x27, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x1e, 0x0c, + 0x04, 0x80, 0x80, 0x83, 0x46, 0x04, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x22, 0x80, 0x80, 0x94, + 0x81, 0x37, 0x8b, 0x1d, 0x0b, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x1e, + 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x19, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x2c, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, + 0x04, 0x88, 0x04, 0x81, 0x1d, 0x87, 0x2c, 0x05, 0x30, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x1b, 0x09, 0x04, 0x80, 0x80, + 0x83, 0x2c, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x19, 0x87, 0x2c, 0x05, 0x20, 0x80, 0x94, + 0x81, 0x37, 0x88, 0x04, 0x80, 0x80, 0x83, 0x36, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x1b, + 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x80, 0x80, 0x83, 0x36, 0x05, 0x80, 0x94, 0x81, 0x37, 0x98, 0x01, 0x08, + 0x88, 0x06, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x98, 0x02, 0x08, 0x80, 0x80, 0x83, 0x36, 0x05, 0x80, 0x94, 0x81, + 0x37, 0x98, 0x01, 0x08, 0x88, 0x04, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x27, 0x09, 0x04, 0x80, 0x80, 0x83, + 0x36, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x80, + 0x80, 0x9b, 0x3d, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x27, 0x88, 0x1b, 0x80, + 0x94, 0x81, 0x37, 0x88, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x80, 0x80, 0x80, + 0x94, 0x81, 0x37, 0x8b, 0x1b, 0x09, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x80, + 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, + 0x1b, 0x80, 0x87, 0x35, 0x02, 0x20, 0x22, 0x06, 0x18, 0x01, 0x04, 0x8b, 0x1d, 0x0c, 0x04, 0x83, 0x35, 0x07, 0x80, + 0x83, 0x41, 0x05, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x04, 0x80, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x8b, + 0x20, 0x0b, 0x04, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x06, 0x81, 0x1d, 0x80, + 0x84, 0x91, 0x8c, 0x91, 0x01, 0x8b, 0x24, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x8c, 0x91, 0x01, 0x88, + 0x04, 0x88, 0x04, 0x81, 0x20, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x8b, 0x29, 0x09, 0x04, 0x80, 0x80, 0x83, 0x41, + 0x05, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x06, 0x81, 0x24, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x8b, 0x20, + 0x09, 0x04, 0x80, 0x80, 0x83, 0x49, 0x04, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x04, 0x81, 0x29, 0x80, 0x84, + 0x91, 0x8c, 0x91, 0x01, 0x8b, 0x22, 0x0a, 0x04, 0x80, 0x80, 0x80, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x06, + 0x81, 0x20, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x8b, 0x1d, 0x0b, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, 0x8c, + 0x91, 0x01, 0x88, 0x04, 0x88, 0x04, 0x81, 0x22, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x8b, 0x1b, 0x0c, 0x04, 0x80, + 0x80, 0x9b, 0x46, 0x04, 0x1b, 0xc1, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x06, 0x81, 0x1d, 0x80, 0x84, 0x91, + 0x8c, 0x91, 0x01, 0x8b, 0x1d, 0x09, 0x04, 0x80, 0x80, 0x80, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x04, 0x81, + 0x1b, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, 0x8c, 0x91, 0x01, 0x88, + 0x04, 0x88, 0x06, 0x81, 0x1d, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, + 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x04, 0x80, 0x80, 0x84, 0x91, 0x8c, 0x82, 0x01, 0x88, 0x04, 0x80, 0x80, 0x83, + 0x46, 0x05, 0x80, 0x8c, 0x82, 0x01, 0x88, 0x04, 0x88, 0x06, 0x80, 0x80, 0x84, 0x91, 0x8c, 0x82, 0x01, 0x9b, 0x46, + 0x09, 0x02, 0x10, 0x83, 0x35, 0x07, 0x80, 0x83, 0x49, 0x04, 0x80, 0x8c, 0x82, 0x01, 0x9c, 0x61, 0x02, 0x12, 0x88, + 0x04, 0x80, 0x83, 0x49, 0x04, 0x84, 0x91, 0x8c, 0x82, 0x01, 0x9c, 0x61, 0x02, 0x12, 0x80, 0x80, 0x83, 0x49, 0x04, + 0x80, 0x8c, 0x82, 0x01, 0x8c, 0x61, 0x02, 0x88, 0x06, 0x46, 0x09, 0x20, 0x02, 0x10, 0x80, 0x84, 0x91, 0x8c, 0x82, + 0x01, 0x8c, 0x61, 0x02, 0x80, 0x98, 0x02, 0x12, 0x83, 0x49, 0x04, 0x80, 0x8c, 0x82, 0x01, 0x8c, 0x61, 0x02, 0x88, + 0x04, 0x98, 0x02, 0x12, 0x80, 0x84, 0x91, 0x8c, 0x82, 0x01, 0x8c, 0x61, 0x02, 0x80, 0x88, 0x02, 0x83, 0x49, 0x04, + 0x80, 0x8c, 0x82, 0x01, 0x8c, 0x61, 0x02, 0x88, 0x06, 0x88, 0x02, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x52, 0x03, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3a, 0x09, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x80, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x35, + 0x0a, 0x80, 0x80, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3a, 0x09, 0x30, 0x80, 0x8a, + 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x38, 0x0b, 0x80, 0x80, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa6, + 0x88, 0x04, 0x87, 0x35, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3a, 0x0c, 0x80, 0x80, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x38, 0x0b, 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, + 0x83, 0x3d, 0x09, 0x80, 0x98, 0x04, 0xa6, 0x83, 0x49, 0x04, 0x80, 0x80, 0x83, 0x3c, 0x09, 0x88, 0x04, 0x87, 0x3a, + 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3a, 0x09, 0x80, 0x80, 0x80, 0x88, 0x0a, 0x80, + 0x83, 0x38, 0x09, 0x88, 0x06, 0x87, 0x3d, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3a, 0x09, + 0x80, 0x87, 0x3c, 0x09, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x87, 0x3a, 0x09, + 0x30, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x87, 0x38, + 0x09, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x06, 0x87, 0x3a, 0x09, 0x30, 0x80, 0x8a, + 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x38, 0x09, 0x80, 0x98, 0x01, 0x08, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, + 0x88, 0x04, 0x98, 0x02, 0x08, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x35, 0x0a, 0x80, 0x98, 0x01, 0x08, + 0x81, 0x31, 0x80, 0x80, 0x80, 0x88, 0x06, 0x87, 0x38, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, + 0x33, 0x0b, 0x80, 0x80, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa6, 0x88, 0x04, 0x87, 0x35, 0x0a, 0x30, 0x80, + 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x31, 0x0c, 0x80, 0x80, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x80, 0x88, + 0x06, 0x87, 0x33, 0x0b, 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x30, 0x0c, 0x83, 0x3a, 0x07, 0x98, 0x04, + 0xa6, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x87, 0x31, 0x0c, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, + 0x18, 0x83, 0x2c, 0x0b, 0x80, 0x80, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x30, 0x0c, 0x30, + 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x31, 0x0b, 0x03, 0x20, 0x80, 0x80, 0x80, 0x88, 0x0a, 0x80, 0x88, + 0x03, 0x88, 0x04, 0x87, 0x2c, 0x0b, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x30, 0x09, 0x80, + 0x80, 0x81, 0x31, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x31, 0x0b, 0x30, 0x03, 0x20, 0x80, 0x9b, 0x3a, 0x02, 0x0a, + 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x2e, 0x0a, 0x83, 0x3a, 0x07, 0x88, 0x03, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x80, 0x88, + 0x04, 0x87, 0x30, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, 0x85, 0x3d, 0x18, + 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa2, 0x88, 0x06, 0x87, 0x2e, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, + 0x98, 0x04, 0xa4, 0x80, 0x80, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa8, 0x88, 0x04, 0x80, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x29, 0x09, 0x80, 0x98, 0x04, 0xa2, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x98, 0x04, 0xa2, 0x88, 0x06, 0x98, 0x04, 0xa4, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x2c, 0x09, 0x80, 0x98, + 0x04, 0xa8, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x87, 0x29, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x31, 0x09, 0x80, 0x98, 0x04, 0xa2, 0x80, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x2c, + 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x30, 0x09, 0x80, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, + 0x80, 0x98, 0x04, 0xa8, 0x88, 0x04, 0x87, 0x31, 0x09, 0x30, 0x9d, 0x3d, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x2c, 0x0a, 0x80, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x30, + 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x2e, 0x0c, 0x80, 0x98, 0x04, 0xa8, 0x81, 0x3d, 0x88, + 0x0a, 0x80, 0x80, 0x88, 0x04, 0x87, 0x2c, 0x0a, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, + 0x81, 0x31, 0x80, 0x80, 0x98, 0x04, 0xa1, 0x88, 0x06, 0x87, 0x2e, 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, + 0x08, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x80, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x98, 0x04, 0xa1, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, + 0x01, 0x08, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x35, 0x09, 0x83, 0x3a, 0x07, + 0x98, 0x01, 0x08, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x98, 0x02, 0x08, 0x80, 0x82, 0x02, 0x87, 0x3d, + 0x08, 0x18, 0x83, 0x38, 0x09, 0x80, 0x98, 0x01, 0x08, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, + 0x35, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3d, 0x0a, 0x80, 0x80, 0x83, 0x49, 0x04, 0x88, + 0x0a, 0x80, 0x80, 0x88, 0x04, 0x87, 0x38, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3c, + 0x0b, 0x80, 0x80, 0x81, 0x4b, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x3d, 0x0a, 0x30, 0x80, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x06, 0x04, 0x87, 0x3a, 0x02, 0x30, 0x97, 0x3a, 0x09, 0x30, 0x37, 0x9b, 0x2e, 0x0b, 0x04, + 0xa1, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, + 0x80, 0x80, 0x80, 0x94, 0x24, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, + 0x37, 0x98, 0x06, 0x01, 0x98, 0x06, 0x01, 0x2e, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, 0x0a, 0x30, 0x37, + 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, + 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, + 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, + 0x0b, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x94, 0x20, 0x37, + 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, + 0x01, 0x80, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, + 0x0c, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, + 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x24, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, + 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x84, + 0x81, 0x97, 0x3a, 0x0c, 0x30, 0x37, 0x9b, 0x29, 0x0c, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, + 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, 0x37, 0x9b, + 0x2e, 0x0b, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x37, 0x9c, 0x20, + 0x06, 0x01, 0x98, 0x06, 0x10, 0x29, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, 0x0b, 0x30, 0x37, 0x9b, + 0x31, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x37, 0x9c, 0x20, + 0x06, 0x01, 0x88, 0x04, 0x2e, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x37, 0x9b, 0x30, 0x09, 0x04, + 0xa1, 0x80, 0x9c, 0x14, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x98, + 0x06, 0x20, 0x31, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, 0x0a, 0x30, 0x37, 0x9b, 0x2c, 0x09, 0x04, + 0xa1, 0x80, 0x9c, 0x14, 0x06, 0x01, 0x83, 0x49, 0x04, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, + 0x30, 0x09, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, 0x37, 0x9b, 0x2e, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x06, + 0x01, 0x87, 0x49, 0x04, 0x30, 0x84, 0x81, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x2c, 0x09, 0x30, 0x04, + 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, 0x09, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, + 0x20, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x2e, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, + 0x94, 0x30, 0x37, 0x9b, 0x2c, 0x0b, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x18, 0x84, 0x81, 0x94, + 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x87, 0x38, 0x03, 0x30, 0x97, 0x38, 0x09, 0x30, + 0x47, 0x9b, 0x2e, 0x0c, 0x04, 0xa1, 0x83, 0x2c, 0x07, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, + 0x47, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, 0x2c, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x24, 0x47, 0x9b, 0x35, + 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, + 0x98, 0x06, 0x01, 0x2e, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x38, 0x0a, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, + 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x35, 0x0a, + 0x30, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, + 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x38, 0x0b, 0x30, + 0x47, 0x9b, 0x33, 0x0b, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x94, 0x20, 0x47, + 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, + 0x01, 0x80, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x33, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x80, + 0x97, 0x38, 0x0c, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, + 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x24, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, + 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, + 0x80, 0x84, 0x81, 0x97, 0x38, 0x0c, 0x30, 0x47, 0x9b, 0x31, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, + 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, + 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, + 0x01, 0x98, 0x06, 0x10, 0x31, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x38, 0x0b, 0x30, 0x47, 0x98, 0x04, + 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, + 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, + 0x14, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x20, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, + 0x38, 0x0a, 0x30, 0x47, 0x9b, 0x30, 0x0c, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x49, 0x04, 0x84, 0x81, 0x94, + 0x28, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, 0x47, 0x98, 0x04, 0xa1, + 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x30, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x30, + 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x38, 0x09, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, + 0x87, 0x49, 0x04, 0x20, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, + 0x81, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x18, 0x84, 0x81, 0x94, 0x20, + 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xaf, 0x03, + 0x9b, 0x36, 0x03, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3a, 0x09, 0x83, 0x2a, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, + 0x0a, 0x80, 0x80, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x36, 0x0a, 0x83, + 0x36, 0x07, 0x80, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3a, 0x09, 0x30, 0x80, 0x8a, + 0x03, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x2e, 0x0b, 0x83, 0x2a, 0x07, 0x80, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x98, + 0x04, 0xa3, 0x88, 0x04, 0x87, 0x36, 0x0a, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x04, 0xa6, + 0x83, 0x2a, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x87, 0x2e, 0x0b, 0x30, 0x80, + 0x82, 0x03, 0x83, 0x3d, 0x08, 0x83, 0x31, 0x0c, 0x83, 0x36, 0x07, 0x98, 0x04, 0xa3, 0x83, 0x49, 0x04, 0x80, 0x80, + 0x80, 0x88, 0x04, 0x98, 0x04, 0xa6, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x36, 0x0b, 0x83, 0x2a, + 0x07, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x31, 0x0c, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, + 0x3d, 0x01, 0x83, 0x3a, 0x0a, 0x83, 0x36, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa6, 0x88, + 0x04, 0x87, 0x36, 0x0b, 0x30, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3d, + 0x09, 0x83, 0x36, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa4, 0x88, 0x06, 0x87, 0x3a, 0x0a, + 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3c, 0x0a, 0x83, 0x2a, 0x07, 0x98, 0x04, 0xa6, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x04, 0x87, 0x3d, 0x09, 0x30, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x83, + 0x3a, 0x0b, 0x83, 0x36, 0x07, 0x98, 0x04, 0xa4, 0x81, 0x31, 0x80, 0x80, 0x98, 0x04, 0xa2, 0x88, 0x06, 0x87, 0x3c, + 0x0a, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x01, 0x9b, 0x36, 0x0b, 0x03, 0x10, 0x83, 0x2a, 0x07, 0x80, 0x81, + 0x3d, 0x88, 0x0a, 0x80, 0x88, 0x03, 0x88, 0x04, 0x87, 0x3a, 0x0b, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x98, 0x01, 0x08, 0x83, 0x2a, 0x07, 0x98, 0x04, 0xa2, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, 0x02, 0x08, 0x88, + 0x06, 0x36, 0x0b, 0x30, 0x03, 0x10, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x83, 0x3d, 0x0a, 0x83, 0x36, 0x07, 0x88, + 0x03, 0x83, 0x49, 0x04, 0x80, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x04, 0x98, 0x01, 0x08, 0x80, 0x82, 0x03, 0x87, 0x3d, + 0x08, 0x18, 0x98, 0x04, 0xa3, 0x83, 0x2a, 0x07, 0x98, 0x02, 0x08, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, + 0xa4, 0x88, 0x06, 0x87, 0x3d, 0x0a, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x3c, 0x0c, 0x83, 0x36, + 0x07, 0x98, 0x04, 0xa3, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x04, 0xa3, 0x80, 0x8a, 0x03, 0x0a, + 0x87, 0x3d, 0x08, 0x18, 0x88, 0x04, 0x83, 0x36, 0x07, 0x98, 0x04, 0xa4, 0x81, 0x31, 0x88, 0x0a, 0x80, 0x88, 0x04, + 0x88, 0x06, 0x87, 0x3c, 0x0c, 0x30, 0x80, 0x9b, 0x38, 0x03, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3a, 0x09, 0x83, + 0x2c, 0x07, 0x88, 0x04, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x38, 0x0a, 0x83, 0x38, 0x07, 0x88, 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x80, 0x88, + 0x06, 0x87, 0x3a, 0x09, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x3c, 0x0b, 0x83, 0x2c, 0x07, 0x80, + 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x84, 0x14, 0x88, 0x04, 0x87, 0x38, 0x0a, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x3f, 0x0a, 0x83, 0x2c, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x84, 0x14, 0x88, + 0x06, 0x87, 0x3c, 0x0b, 0x30, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x83, 0x3d, 0x0c, 0x83, 0x38, 0x07, 0x84, 0x10, + 0x83, 0x49, 0x04, 0x80, 0x80, 0x98, 0x04, 0xa2, 0x88, 0x04, 0x87, 0x3f, 0x0a, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x3c, 0x0a, 0x83, 0x2c, 0x07, 0x84, 0x10, 0x80, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, + 0x3d, 0x0c, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x38, 0x09, 0x83, 0x38, 0x07, 0x98, 0x04, 0xa2, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x04, 0x87, 0x3c, 0x0a, 0x30, 0x9d, 0x3d, 0x24, 0x02, + 0x10, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x04, 0xa3, 0x83, 0x38, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, + 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x06, 0x87, 0x38, 0x09, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x83, + 0x2c, 0x09, 0x83, 0x2c, 0x07, 0x98, 0x04, 0xa3, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x83, 0x30, 0x0a, 0x88, 0x04, 0x98, + 0x04, 0xa3, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x2c, 0x0b, 0x83, 0x38, 0x07, 0x98, 0x04, 0xa3, 0x81, + 0x31, 0x80, 0x80, 0x83, 0x30, 0x0c, 0x88, 0x06, 0x87, 0x2c, 0x09, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x01, + 0x83, 0x33, 0x0b, 0x83, 0x2c, 0x07, 0x87, 0x30, 0x0a, 0x30, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x83, 0x30, 0x09, 0x88, + 0x04, 0x87, 0x2c, 0x0b, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x33, 0x0a, 0x83, 0x2c, 0x07, + 0x87, 0x30, 0x0c, 0x30, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x83, 0x38, 0x0b, 0x88, 0x06, 0x87, 0x33, 0x0b, 0x30, 0x80, + 0x82, 0x03, 0x83, 0x3d, 0x08, 0x83, 0x33, 0x0c, 0x83, 0x38, 0x07, 0x87, 0x30, 0x09, 0x30, 0x83, 0x49, 0x04, 0x80, + 0x80, 0x83, 0x38, 0x0b, 0x88, 0x04, 0x87, 0x33, 0x0a, 0x30, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3c, + 0x09, 0x83, 0x2c, 0x07, 0x87, 0x38, 0x0b, 0x30, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x83, 0x3d, 0x0a, 0x88, 0x06, + 0x87, 0x33, 0x0c, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x3f, 0x0b, 0x83, 0x38, 0x07, 0x87, 0x38, + 0x0b, 0x30, 0x83, 0x49, 0x04, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa5, 0x88, 0x04, 0x87, 0x3c, 0x09, 0x30, 0x80, 0x8a, + 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x04, 0xa5, 0x83, 0x38, 0x07, 0x87, 0x3d, 0x0a, 0x30, 0x81, 0x4b, 0x88, + 0x0a, 0x80, 0x98, 0x04, 0xa5, 0x88, 0x06, 0x87, 0x3f, 0x0b, 0x30, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x52, 0x03, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3a, 0x09, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x80, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x35, + 0x0a, 0x80, 0x80, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3a, 0x09, 0x30, 0x80, 0x8a, + 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x38, 0x0b, 0x80, 0x80, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa6, + 0x88, 0x04, 0x87, 0x35, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3a, 0x0c, 0x80, 0x80, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x38, 0x0b, 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, + 0x83, 0x3d, 0x09, 0x80, 0x98, 0x04, 0xa6, 0x83, 0x49, 0x04, 0x80, 0x80, 0x83, 0x3c, 0x09, 0x88, 0x04, 0x87, 0x3a, + 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3a, 0x09, 0x80, 0x80, 0x80, 0x88, 0x0a, 0x80, + 0x83, 0x38, 0x09, 0x88, 0x06, 0x87, 0x3d, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3a, 0x09, + 0x80, 0x87, 0x3c, 0x09, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x87, 0x3a, 0x09, + 0x30, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x87, 0x38, + 0x09, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x06, 0x87, 0x3a, 0x09, 0x30, 0x80, 0x8a, + 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x38, 0x09, 0x80, 0x98, 0x01, 0x08, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, + 0x88, 0x04, 0x98, 0x02, 0x08, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x35, 0x0a, 0x80, 0x98, 0x01, 0x08, + 0x81, 0x31, 0x80, 0x80, 0x80, 0x88, 0x06, 0x87, 0x38, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, + 0x33, 0x0b, 0x80, 0x80, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa6, 0x88, 0x04, 0x87, 0x35, 0x0a, 0x30, 0x80, + 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x31, 0x0c, 0x80, 0x80, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x80, 0x88, + 0x06, 0x87, 0x33, 0x0b, 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x30, 0x0c, 0x83, 0x3a, 0x07, 0x98, 0x04, + 0xa6, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x87, 0x31, 0x0c, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, + 0x18, 0x83, 0x2c, 0x0b, 0x80, 0x80, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x30, 0x0c, 0x30, + 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x31, 0x0b, 0x03, 0x20, 0x80, 0x80, 0x80, 0x88, 0x0a, 0x80, 0x88, + 0x03, 0x88, 0x04, 0x87, 0x2c, 0x0b, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x30, 0x09, 0x80, + 0x80, 0x81, 0x31, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x31, 0x0b, 0x30, 0x03, 0x20, 0x80, 0x9b, 0x3a, 0x02, 0x0a, + 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x2e, 0x0a, 0x83, 0x3a, 0x07, 0x88, 0x03, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x80, 0x88, + 0x04, 0x87, 0x30, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, 0x85, 0x3d, 0x18, + 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa2, 0x88, 0x06, 0x87, 0x2e, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, + 0x98, 0x04, 0xa4, 0x80, 0x80, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa8, 0x88, 0x04, 0x80, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x29, 0x09, 0x80, 0x98, 0x04, 0xa2, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x98, 0x04, 0xa2, 0x88, 0x06, 0x98, 0x04, 0xa4, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x2c, 0x09, 0x80, 0x98, + 0x04, 0xa8, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x87, 0x29, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x31, 0x09, 0x80, 0x98, 0x04, 0xa2, 0x80, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x2c, + 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x30, 0x09, 0x80, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, + 0x80, 0x98, 0x04, 0xa8, 0x88, 0x04, 0x87, 0x31, 0x09, 0x30, 0x9d, 0x3d, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x2c, 0x0a, 0x80, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x30, + 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x2e, 0x0c, 0x80, 0x98, 0x04, 0xa8, 0x81, 0x3d, 0x88, + 0x0a, 0x80, 0x80, 0x88, 0x04, 0x87, 0x2c, 0x0a, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, + 0x81, 0x31, 0x80, 0x80, 0x98, 0x04, 0xa1, 0x88, 0x06, 0x87, 0x2e, 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, + 0x08, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x80, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x98, 0x04, 0xa1, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, + 0x01, 0x08, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x35, 0x09, 0x83, 0x3a, 0x07, + 0x98, 0x01, 0x08, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x98, 0x02, 0x08, 0x80, 0x82, 0x02, 0x87, 0x3d, + 0x08, 0x18, 0x83, 0x38, 0x09, 0x80, 0x98, 0x01, 0x08, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, + 0x35, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3d, 0x0a, 0x80, 0x80, 0x83, 0x49, 0x04, 0x88, + 0x0a, 0x80, 0x80, 0x88, 0x04, 0x87, 0x38, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3c, + 0x0b, 0x80, 0x80, 0x81, 0x4b, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x3d, 0x0a, 0x30, 0x80, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0xee, 0x03, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x46, 0x0c, 0x83, 0x3a, + 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x83, 0x41, 0x0c, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x02, 0x0a, + 0x87, 0x3d, 0x08, 0x18, 0x83, 0x44, 0x0c, 0x83, 0x2e, 0x07, 0x80, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x83, 0x3f, + 0x0c, 0x98, 0x06, 0x01, 0x87, 0x46, 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x41, 0x0c, 0x83, + 0x3a, 0x07, 0x87, 0x41, 0x0c, 0x30, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x83, 0x3d, 0x0c, 0x88, 0x04, 0x87, 0x44, + 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3f, 0x0c, 0x83, 0x3a, 0x07, 0x87, 0x3f, 0x0c, + 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x9b, 0x3d, 0x0c, 0x04, 0xa1, 0x88, 0x06, 0x87, 0x41, 0x0c, 0x30, 0x80, + 0x82, 0x02, 0x83, 0x3d, 0x08, 0x9b, 0x3c, 0x0b, 0x04, 0xa1, 0x83, 0x2e, 0x07, 0x87, 0x3d, 0x0c, 0x30, 0x83, 0x49, + 0x04, 0x80, 0x80, 0x9b, 0x38, 0x0b, 0x04, 0xa1, 0x88, 0x04, 0x87, 0x3f, 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x9b, 0x3a, 0x0b, 0x04, 0xa1, 0x83, 0x3a, 0x07, 0x3d, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x88, 0x0a, + 0x80, 0x9b, 0x38, 0x0b, 0x04, 0xa2, 0x88, 0x06, 0x3c, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, + 0x01, 0x9b, 0x3a, 0x0a, 0x04, 0xa2, 0x83, 0x2e, 0x07, 0x38, 0x0b, 0x30, 0x04, 0xa1, 0x83, 0x3d, 0x05, 0x88, 0x0a, + 0x80, 0x9b, 0x35, 0x0a, 0x04, 0xa2, 0x88, 0x04, 0x3a, 0x0b, 0x30, 0x04, 0xa1, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x38, 0x0a, 0x83, 0x2e, 0x07, 0x38, 0x0b, 0x30, 0x04, 0xa2, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x9b, 0x33, 0x0a, 0x04, 0xa3, 0x88, 0x06, 0x3a, 0x0a, 0x30, 0x04, 0xa2, 0x80, 0x8a, 0x02, + 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x35, 0x09, 0x83, 0x3a, 0x07, 0x35, 0x0a, 0x30, 0x04, 0xa2, 0x83, 0x3d, 0x05, 0x88, + 0x0a, 0x80, 0x9b, 0x31, 0x09, 0x04, 0xa3, 0x88, 0x04, 0x87, 0x38, 0x0a, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, + 0x18, 0x83, 0x33, 0x09, 0x83, 0x2e, 0x07, 0x33, 0x0a, 0x30, 0x04, 0xa3, 0x81, 0x31, 0x80, 0x80, 0x9b, 0x30, 0x0a, + 0x04, 0xa4, 0x88, 0x06, 0x87, 0x35, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x2c, 0x0a, 0x83, + 0x3a, 0x07, 0x31, 0x09, 0x30, 0x04, 0xa3, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x9b, 0x31, 0x0a, 0x04, 0xa5, 0x88, 0x04, + 0x87, 0x33, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x30, 0x0b, 0x83, 0x3a, 0x07, 0x30, + 0x0a, 0x30, 0x04, 0xa4, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x9b, 0x2c, 0x0b, 0x04, 0xa5, 0x88, 0x06, 0x87, 0x2c, 0x0a, + 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x2e, 0x0c, 0x83, 0x2e, 0x07, 0x31, 0x0a, 0x30, 0x04, 0xa5, 0x83, + 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x87, 0x30, 0x0b, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x80, + 0x83, 0x3a, 0x07, 0x2c, 0x0b, 0x30, 0x04, 0xa5, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x06, + 0x87, 0x2e, 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x98, 0x02, 0x08, 0x83, 0x2e, 0x07, 0x80, 0x80, + 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3a, + 0x0c, 0x83, 0x2e, 0x07, 0x98, 0x01, 0x08, 0x81, 0x31, 0x88, 0x0a, 0x80, 0x83, 0x35, 0x0c, 0x88, 0x06, 0x98, 0x02, + 0x08, 0x80, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x38, 0x0b, 0x83, 0x3a, 0x07, 0x98, 0x01, 0x08, + 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x83, 0x33, 0x0b, 0x88, 0x04, 0x87, 0x3a, 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x35, 0x0a, 0x83, 0x2e, 0x07, 0x87, 0x35, 0x0c, 0x30, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, + 0x83, 0x31, 0x0a, 0x88, 0x06, 0x87, 0x38, 0x0b, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x33, 0x09, + 0x83, 0x3a, 0x07, 0x87, 0x33, 0x0b, 0x30, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x83, 0x31, 0x09, 0x88, 0x04, 0x87, + 0x35, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x30, 0x0a, 0x83, 0x3a, 0x07, 0x87, 0x31, + 0x0a, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x83, 0x2c, 0x0b, 0x88, 0x06, 0x87, 0x33, 0x09, 0x30, 0x80, 0x82, + 0x02, 0x83, 0x3d, 0x08, 0x83, 0x2e, 0x0c, 0x83, 0x2e, 0x07, 0x87, 0x31, 0x09, 0x30, 0x83, 0x49, 0x04, 0x80, 0x80, + 0x80, 0x88, 0x04, 0x87, 0x30, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x2c, 0x0c, 0x83, + 0x3a, 0x07, 0x87, 0x2c, 0x0b, 0x30, 0x80, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x2e, 0x0c, 0x30, 0x80, 0x8a, + 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x2e, 0x0b, 0x83, 0x2e, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, + 0x04, 0xa8, 0x88, 0x04, 0x87, 0x2c, 0x0c, 0x30, 0x9d, 0x3d, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x83, 0x31, 0x0a, 0x83, 0x2e, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x84, 0x18, 0x88, 0x06, 0x87, + 0x2e, 0x0b, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x35, 0x09, 0x83, 0x3a, 0x07, 0x80, 0x81, 0x3d, + 0x88, 0x0a, 0x80, 0x9c, 0x18, 0x04, 0xa2, 0x88, 0x04, 0x87, 0x31, 0x0a, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, + 0x18, 0x9b, 0x38, 0x0a, 0x04, 0xa2, 0x83, 0x2e, 0x07, 0x84, 0x18, 0x81, 0x31, 0x80, 0x80, 0x84, 0x18, 0x88, 0x06, + 0x87, 0x35, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x3a, 0x0b, 0x83, 0x3a, 0x07, 0x84, 0x18, + 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x04, 0x87, 0x38, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x83, 0x3d, 0x0c, 0x83, 0x3a, 0x07, 0x84, 0x18, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x06, + 0x87, 0x3a, 0x0b, 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x3c, 0x0b, 0x83, 0x2e, 0x07, 0x80, 0x83, 0x49, + 0x04, 0x80, 0x80, 0x98, 0x04, 0xa8, 0x88, 0x04, 0x87, 0x3d, 0x0c, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, + 0x83, 0x38, 0x09, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x3c, 0x0b, + 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x3a, 0x0a, 0x83, 0x2e, 0x07, 0x98, 0x04, 0xa8, 0x83, 0x49, + 0x04, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x04, 0x87, 0x38, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, + 0x08, 0x18, 0x98, 0x04, 0xa3, 0x83, 0x2e, 0x07, 0x80, 0x81, 0x4b, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x06, + 0x87, 0x3a, 0x0a, 0x30, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xc3, 0x03, 0x87, 0x3a, 0x02, 0x30, 0x60, + 0x06, 0x30, 0x02, 0x08, 0x83, 0x3a, 0x0a, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x8c, 0x82, 0x02, + 0x98, 0x04, 0xa3, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x80, 0x8c, 0x82, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x80, 0x87, 0x3d, + 0x05, 0x20, 0x84, 0x81, 0x8c, 0x82, 0x02, 0x98, 0x06, 0x01, 0x98, 0x06, 0x01, 0x87, 0x3a, 0x0a, 0x30, 0x80, 0x80, + 0x8c, 0x82, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x98, 0x04, 0xa3, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x8c, 0x82, 0x02, + 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa3, 0x80, 0x80, 0x8c, 0x81, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x98, 0x06, + 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa3, 0x80, + 0x80, 0x8c, 0x81, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x8c, 0x81, + 0x02, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa3, 0x80, 0x80, 0x8c, 0x81, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x98, + 0x06, 0x01, 0x80, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa3, 0x80, 0x80, 0x8c, + 0x81, 0x02, 0x9b, 0x3d, 0x0a, 0x03, 0x03, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x8c, 0x81, 0x02, + 0x98, 0x03, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa3, 0x80, 0x80, 0x8c, 0x81, 0x02, 0x98, 0x03, 0x03, 0x80, 0x98, 0x06, + 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x03, 0x11, 0x88, 0x06, 0x3d, 0x0a, 0x30, 0x03, + 0x03, 0x80, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x03, 0xa3, 0x80, 0x98, 0x03, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, + 0x8c, 0x81, 0x02, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x03, 0x03, 0x80, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x04, + 0xa3, 0x80, 0x98, 0x03, 0x11, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x06, 0x01, 0x98, 0x06, + 0x10, 0x98, 0x03, 0xa3, 0x80, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, + 0x05, 0x18, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa3, 0x80, 0x84, 0x81, 0x8c, + 0x81, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x91, 0x8c, 0x81, 0x02, 0x98, + 0x06, 0x01, 0x98, 0x06, 0x20, 0x98, 0x04, 0xa3, 0x80, 0x84, 0x92, 0x97, 0x3a, 0x0b, 0x18, 0x37, 0x98, 0x04, 0x03, + 0x80, 0x98, 0x06, 0x01, 0x83, 0x49, 0x04, 0x84, 0x91, 0x94, 0x10, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, + 0xa3, 0x80, 0x84, 0x92, 0x94, 0x18, 0x37, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x30, 0x84, 0x91, + 0x94, 0x10, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0x03, 0x80, 0x84, 0x92, 0x97, 0x3a, 0x09, 0x20, 0x37, + 0x9b, 0x38, 0x0c, 0x0c, 0x20, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x20, 0x84, 0x91, 0x94, 0x18, 0x37, 0x98, + 0x06, 0x10, 0x88, 0x04, 0x88, 0x04, 0x80, 0x84, 0x92, 0x94, 0x15, 0x37, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, + 0x49, 0x04, 0x18, 0x84, 0x91, 0x94, 0x11, 0x37, 0x98, 0x06, 0x10, 0x88, 0x06, 0x38, 0x0c, 0x30, 0x0c, 0x20, 0x80, + 0x87, 0x38, 0x03, 0x30, 0x97, 0x38, 0x09, 0x30, 0x47, 0x8b, 0x38, 0x09, 0x04, 0x83, 0x2c, 0x07, 0x98, 0x06, 0x10, + 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, 0x88, 0x04, 0x80, 0x80, 0x94, + 0x24, 0x47, 0x88, 0x04, 0x80, 0x98, 0x06, 0x10, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, + 0x01, 0x98, 0x06, 0x01, 0x8f, 0x38, 0x09, 0x30, 0x04, 0x80, 0x80, 0x97, 0x38, 0x0a, 0x30, 0x47, 0x8b, 0x38, 0x0c, + 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, + 0x88, 0x04, 0x80, 0x80, 0x94, 0x30, 0x47, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, + 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x8f, 0x38, 0x0c, 0x30, 0x04, 0x80, 0x80, 0x97, 0x38, 0x0b, 0x30, + 0x47, 0x9b, 0x33, 0x0a, 0x03, 0x03, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x94, 0x20, 0x47, + 0x98, 0x03, 0x05, 0x88, 0x04, 0x88, 0x04, 0x80, 0x80, 0x94, 0x30, 0x47, 0x98, 0x03, 0x08, 0x80, 0x98, 0x06, 0x01, + 0x80, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x03, 0x10, 0x88, 0x06, 0x33, 0x0a, 0x30, 0x03, 0x03, 0x80, 0x80, 0x97, + 0x38, 0x0c, 0x30, 0x47, 0x80, 0x80, 0x98, 0x03, 0x05, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, + 0x01, 0x88, 0x04, 0x98, 0x03, 0x08, 0x80, 0x80, 0x94, 0x24, 0x47, 0x88, 0x04, 0x80, 0x98, 0x03, 0x10, 0x87, 0x3d, + 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x80, 0x80, 0x84, 0x81, 0x97, 0x38, 0x0c, + 0x30, 0x47, 0x8b, 0x30, 0x0b, 0x04, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, + 0x06, 0x01, 0x88, 0x04, 0x88, 0x04, 0x80, 0x84, 0x81, 0x94, 0x24, 0x47, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, + 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x10, 0x8f, 0x30, 0x0b, 0x30, 0x04, + 0x80, 0x84, 0x81, 0x97, 0x38, 0x0b, 0x30, 0x47, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, + 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x88, 0x04, 0x80, 0x84, 0x81, 0x94, 0x30, 0x47, 0x88, 0x04, + 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x91, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x20, + 0x88, 0x04, 0x80, 0x84, 0x92, 0x97, 0x38, 0x0a, 0x30, 0x47, 0x8b, 0x2c, 0x0c, 0x04, 0x80, 0x98, 0x06, 0x01, 0x83, + 0x49, 0x04, 0x84, 0x91, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x88, 0x04, 0x80, 0x84, 0x92, 0x94, 0x24, + 0x47, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x30, 0x84, 0x91, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, + 0x88, 0x06, 0x8f, 0x2c, 0x0c, 0x30, 0x04, 0x80, 0x84, 0x92, 0x97, 0x38, 0x09, 0x30, 0x47, 0x88, 0x04, 0x80, 0x98, + 0x06, 0x01, 0x87, 0x49, 0x04, 0x20, 0x84, 0x91, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x88, 0x04, 0x80, + 0x84, 0x92, 0x94, 0x30, 0x47, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x18, 0x84, 0x91, 0x94, 0x20, + 0x47, 0x90, 0x01, 0x88, 0x06, 0x88, 0x04, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x3c, 0x04, 0x87, 0x36, + 0x03, 0x30, 0x97, 0x36, 0x09, 0x30, 0x47, 0x9b, 0x31, 0x0a, 0x04, 0xa1, 0x83, 0x2a, 0x07, 0x80, 0x83, 0x3d, 0x05, + 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x80, 0x94, 0x24, 0x47, 0x98, 0x04, + 0xa1, 0x80, 0x80, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x01, 0x31, + 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x36, 0x0a, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, + 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, + 0x30, 0x47, 0x98, 0x04, 0xa4, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, + 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x36, 0x0b, 0x30, 0x47, 0x98, 0x04, 0xa4, 0x80, 0x98, + 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa4, + 0x80, 0x80, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa7, 0x80, 0x98, 0x06, 0x01, 0x80, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, + 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa4, 0x80, 0x80, 0x97, 0x36, 0x0c, 0x30, 0x47, 0x9b, 0x33, 0x0a, 0x03, 0x02, + 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x03, 0x02, 0x88, 0x04, 0x98, 0x04, + 0xa7, 0x80, 0x80, 0x94, 0x24, 0x47, 0x98, 0x03, 0x02, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, + 0x94, 0x22, 0x47, 0x98, 0x03, 0x02, 0x88, 0x06, 0x33, 0x0a, 0x30, 0x03, 0x02, 0x80, 0x84, 0x81, 0x97, 0x36, 0x0c, + 0x30, 0x47, 0x9b, 0x33, 0x0b, 0x04, 0x01, 0x80, 0x98, 0x03, 0x02, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, + 0x9c, 0x20, 0x06, 0x01, 0x88, 0x04, 0x98, 0x03, 0x02, 0x80, 0x84, 0x81, 0x94, 0x24, 0x47, 0x9c, 0x50, 0x04, 0xa1, + 0x80, 0x98, 0x03, 0x02, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x10, + 0x33, 0x0b, 0x30, 0x04, 0x01, 0x80, 0x84, 0x81, 0x97, 0x36, 0x0b, 0x30, 0x47, 0x9b, 0x2e, 0x0b, 0x04, 0xa1, 0x80, + 0x9c, 0x10, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x9c, + 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x47, 0x9b, 0x31, 0x0c, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, + 0x3c, 0x05, 0x14, 0x84, 0x91, 0x94, 0x20, 0x47, 0x9c, 0x20, 0x06, 0x01, 0x98, 0x06, 0x20, 0x2e, 0x0b, 0x30, 0x04, + 0xa1, 0x80, 0x84, 0x92, 0x97, 0x36, 0x0a, 0x30, 0x47, 0x9b, 0x36, 0x09, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, + 0x49, 0x04, 0x84, 0x91, 0x94, 0x28, 0x47, 0x9c, 0x20, 0x06, 0x01, 0x88, 0x04, 0x31, 0x0c, 0x30, 0x04, 0xa1, 0x80, + 0x84, 0x92, 0x94, 0x24, 0x47, 0x9b, 0x3a, 0x0c, 0x04, 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x87, 0x49, 0x04, 0x30, + 0x84, 0x91, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x36, 0x09, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x92, 0x97, + 0x36, 0x09, 0x30, 0x47, 0x9b, 0x38, 0x0a, 0x04, 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x87, 0x49, 0x04, 0x20, 0x84, + 0x91, 0x94, 0x20, 0x47, 0x9c, 0x20, 0x06, 0x01, 0x88, 0x04, 0x3a, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x92, 0x94, + 0x30, 0x47, 0x9b, 0x35, 0x0b, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x18, 0x84, 0x91, 0x94, 0x20, + 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x38, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x87, 0x3a, 0x02, 0x30, 0x97, 0x3a, 0x09, + 0x30, 0x37, 0x9b, 0x3a, 0x0a, 0x04, 0xa1, 0x83, 0x2e, 0x07, 0x9c, 0x10, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, + 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, 0x35, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x24, 0x37, + 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, + 0x98, 0x06, 0x01, 0x3a, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, 0x0a, 0x30, 0x37, 0x9c, 0x61, 0x01, 0x08, + 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x37, 0x9c, 0x61, 0x02, 0x08, 0x88, 0x04, + 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x37, 0x9c, 0x61, 0x01, 0x08, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, + 0x14, 0x84, 0x81, 0x94, 0x20, 0x37, 0x9c, 0x61, 0x02, 0x08, 0x88, 0x06, 0x9c, 0x61, 0x01, 0x08, 0x80, 0x80, 0x97, + 0x3a, 0x0b, 0x30, 0x37, 0x9b, 0x35, 0x09, 0x04, 0xa1, 0x80, 0x9c, 0x61, 0x02, 0x08, 0x87, 0x3c, 0x05, 0x12, 0x84, + 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x9c, 0x61, 0x01, 0x08, 0x80, 0x80, 0x94, 0x30, 0x37, 0x9b, + 0x31, 0x0a, 0x04, 0xa1, 0x80, 0x9c, 0x61, 0x02, 0x08, 0x80, 0x84, 0x81, 0x94, 0x20, 0x37, 0x9c, 0x20, 0x06, 0x01, + 0x88, 0x06, 0x35, 0x09, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, 0x0c, 0x30, 0x37, 0x9b, 0x31, 0x0b, 0x04, 0xa1, + 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x31, 0x0a, + 0x30, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x24, 0x37, 0x9b, 0x30, 0x0c, 0x04, 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x87, + 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x31, 0x0b, 0x30, 0x04, 0xa1, 0x80, + 0x84, 0x81, 0x97, 0x3a, 0x0c, 0x30, 0x37, 0x9b, 0x31, 0x0c, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, + 0x84, 0x81, 0x94, 0x28, 0x37, 0x9c, 0x20, 0x06, 0x01, 0x88, 0x04, 0x30, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, + 0x94, 0x24, 0x37, 0x9b, 0x2e, 0x0b, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, + 0x22, 0x37, 0x9c, 0x20, 0x06, 0x01, 0x98, 0x06, 0x10, 0x31, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, + 0x0b, 0x30, 0x37, 0x9b, 0x30, 0x0a, 0x04, 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, + 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x2e, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x37, + 0x9b, 0x27, 0x09, 0x04, 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x91, 0x94, 0x20, 0x37, + 0x9c, 0x20, 0x06, 0x01, 0x98, 0x06, 0x20, 0x30, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x92, 0x97, 0x3a, 0x0a, 0x30, + 0x37, 0x9b, 0x29, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x49, 0x04, 0x84, 0x91, 0x94, 0x28, 0x37, 0x9c, + 0x20, 0x06, 0x01, 0x88, 0x04, 0x27, 0x09, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x92, 0x94, 0x24, 0x37, 0x9b, 0x2c, 0x0b, + 0x04, 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x87, 0x49, 0x04, 0x30, 0x84, 0x91, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, + 0x88, 0x06, 0x29, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x92, 0x97, 0x3a, 0x09, 0x30, 0x37, 0x9b, 0x2e, 0x0c, 0x04, + 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x83, 0x49, 0x04, 0x84, 0x91, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, + 0x2c, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x92, 0x94, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, + 0x49, 0x04, 0x84, 0x91, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x2e, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x22, 0x03, 0x87, 0x3a, 0x02, 0x10, 0x95, 0x3a, 0x20, 0x37, 0x98, 0x0f, 0x07, + 0x83, 0x3a, 0x07, 0x98, 0x0f, 0xf0, 0x83, 0x25, 0x05, 0x80, 0x94, 0x18, 0x37, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, + 0x98, 0x06, 0x01, 0x80, 0x84, 0x91, 0x94, 0x20, 0x37, 0x98, 0x04, 0xa2, 0x80, 0x98, 0x04, 0xa2, 0x83, 0x30, 0x05, + 0x80, 0x94, 0x18, 0x37, 0x88, 0x06, 0x98, 0x06, 0x01, 0x88, 0x06, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, + 0x80, 0x88, 0x04, 0x83, 0x35, 0x05, 0x80, 0x94, 0x18, 0x37, 0x88, 0x06, 0x88, 0x04, 0x88, 0x06, 0x80, 0x84, 0x91, + 0x94, 0x14, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x80, 0x80, 0x94, 0x12, 0x37, 0x88, 0x06, 0x88, 0x06, 0x88, 0x06, + 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x9b, 0x46, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x18, + 0x37, 0x88, 0x06, 0x88, 0x04, 0x88, 0x06, 0x88, 0x1b, 0x84, 0x91, 0x94, 0x14, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, + 0x80, 0x80, 0x94, 0x12, 0x37, 0x88, 0x06, 0x88, 0x06, 0x88, 0x06, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, + 0x80, 0x88, 0x04, 0x83, 0x2c, 0x05, 0x80, 0x94, 0x18, 0x37, 0x88, 0x06, 0x88, 0x04, 0x88, 0x06, 0x87, 0x2c, 0x05, + 0x30, 0x84, 0x91, 0x94, 0x14, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x83, 0x2c, 0x05, 0x80, 0x94, 0x12, 0x37, 0x88, + 0x06, 0x88, 0x06, 0x88, 0x06, 0x87, 0x2c, 0x05, 0x20, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, + 0x83, 0x36, 0x05, 0x80, 0x94, 0x18, 0x37, 0x88, 0x06, 0x88, 0x04, 0x88, 0x06, 0x80, 0x84, 0x91, 0x94, 0x14, 0x37, + 0x88, 0x04, 0x80, 0x88, 0x04, 0x83, 0x36, 0x05, 0x80, 0x94, 0x12, 0x37, 0x88, 0x06, 0x88, 0x06, 0x88, 0x06, 0x80, + 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x83, 0x36, 0x05, 0x80, 0x94, 0x10, 0x37, 0x88, 0x06, + 0x88, 0x04, 0x88, 0x06, 0x80, 0x84, 0x91, 0x94, 0x20, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x83, 0x36, 0x05, 0x80, + 0x94, 0x10, 0x37, 0x88, 0x06, 0x88, 0x06, 0x88, 0x06, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, 0x80, 0x88, + 0x04, 0x9b, 0x3d, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x18, 0x37, 0x88, 0x06, 0x88, 0x04, 0x88, 0x06, 0x88, 0x1b, 0x84, + 0x91, 0x94, 0x14, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x80, 0x80, 0x94, 0x12, 0x37, 0x88, 0x06, 0x88, 0x06, 0x88, + 0x06, 0x88, 0x1b, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x3d, 0x04, 0x15, 0x1b, 0xc1, 0x80, + 0x94, 0x18, 0x37, 0x80, 0x88, 0x04, 0x80, 0x9c, 0x10, 0x1b, 0xc2, 0x84, 0x91, 0x94, 0x20, 0x37, 0x80, 0x80, 0x80, + 0x8f, 0x3d, 0x04, 0x15, 0x1b, 0x80, 0x94, 0x18, 0x37, 0x80, 0x88, 0x06, 0x80, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, + 0x87, 0x22, 0x09, 0x10, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, 0x18, 0x37, 0x84, 0x92, 0x88, 0x04, + 0x80, 0x80, 0x84, 0x91, 0x94, 0x20, 0x37, 0x84, 0x92, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, 0x18, 0x37, 0x84, + 0x92, 0x88, 0x06, 0x80, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x84, 0x92, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, + 0x18, 0x37, 0x84, 0x92, 0x88, 0x04, 0x80, 0x80, 0x84, 0x91, 0x94, 0x14, 0x37, 0x84, 0x92, 0x80, 0x80, 0x83, 0x41, + 0x05, 0x80, 0x94, 0x12, 0x37, 0x84, 0x92, 0x88, 0x06, 0x80, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x84, 0x92, 0x80, + 0x80, 0x9b, 0x49, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x18, 0x37, 0x84, 0x92, 0x88, 0x04, 0x80, 0x88, 0x1b, 0x84, 0x91, + 0x94, 0x14, 0x37, 0x84, 0x92, 0x80, 0x80, 0x80, 0x80, 0x94, 0x12, 0x37, 0x84, 0x92, 0x88, 0x06, 0x80, 0x80, 0x80, + 0x95, 0x3a, 0x20, 0x37, 0x84, 0x92, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, 0x94, 0x18, 0x37, 0x84, 0x92, 0x88, 0x04, + 0x80, 0x80, 0x84, 0x91, 0x94, 0x14, 0x37, 0x84, 0x92, 0x80, 0x80, 0x9b, 0x46, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x12, + 0x37, 0x84, 0x92, 0x88, 0x06, 0x80, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x84, 0x92, 0x80, 0x25, 0x06, 0x20, 0x01, + 0x08, 0x80, 0x80, 0x94, 0x18, 0x37, 0x84, 0x92, 0x88, 0x04, 0x8c, 0x92, 0x01, 0x80, 0x84, 0x91, 0x94, 0x14, 0x37, + 0x84, 0x92, 0x80, 0x8c, 0x92, 0x01, 0x83, 0x46, 0x05, 0x80, 0x94, 0x12, 0x37, 0x84, 0x92, 0x88, 0x06, 0x8c, 0x92, + 0x01, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x84, 0x92, 0x80, 0x8c, 0x92, 0x01, 0x83, 0x46, 0x05, 0x80, 0x94, 0x10, + 0x37, 0x84, 0x92, 0x88, 0x04, 0x9c, 0x91, 0x01, 0x10, 0x80, 0x84, 0x91, 0x94, 0x20, 0x37, 0x84, 0x92, 0x80, 0x8c, + 0x91, 0x01, 0x83, 0x46, 0x05, 0x80, 0x94, 0x10, 0x37, 0x84, 0x92, 0x88, 0x06, 0x8c, 0x91, 0x01, 0x80, 0x80, 0x95, + 0x3a, 0x20, 0x37, 0x84, 0x92, 0x80, 0x9c, 0x81, 0x02, 0x08, 0x9b, 0x42, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x18, 0x37, + 0x84, 0x92, 0x88, 0x04, 0x8c, 0x81, 0x02, 0x88, 0x1b, 0x84, 0x91, 0x94, 0x14, 0x37, 0x84, 0x92, 0x80, 0x8c, 0x81, + 0x02, 0x83, 0x3a, 0x05, 0x80, 0x94, 0x12, 0x37, 0x84, 0x92, 0x88, 0x06, 0x8c, 0x81, 0x02, 0x80, 0x80, 0x95, 0x3a, + 0x20, 0x37, 0x84, 0x92, 0x80, 0x8c, 0x81, 0x02, 0x83, 0x3a, 0x05, 0x80, 0x94, 0x18, 0x37, 0x84, 0x92, 0x88, 0x04, + 0x9c, 0x81, 0x02, 0x20, 0x80, 0x84, 0x91, 0x94, 0x20, 0x37, 0x84, 0x92, 0x80, 0x8c, 0x81, 0x02, 0x83, 0x3a, 0x05, + 0x80, 0x94, 0x18, 0x37, 0x84, 0x92, 0x88, 0x06, 0x8c, 0x81, 0x02, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x8c, 0x03, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x3a, 0x0a, 0x04, 0xa3, 0x83, 0x3a, 0x07, 0x80, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x98, 0x06, 0x01, 0x80, 0x80, 0x85, 0x3d, 0x20, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x06, 0x01, 0x3a, 0x0a, + 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x80, 0x88, 0x04, 0x85, 0x3d, 0x18, 0x88, + 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x06, 0x01, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, + 0x80, 0x88, 0x04, 0x85, 0x3d, 0x14, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x88, 0x06, 0x80, 0x82, 0x02, 0x83, + 0x3d, 0x08, 0x88, 0x06, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x88, 0x06, + 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x98, + 0x01, 0x08, 0x88, 0x06, 0x88, 0x06, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x35, 0x0a, 0x04, 0xa3, 0x80, + 0x98, 0x01, 0x08, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa1, 0x88, 0x04, 0x98, 0x02, 0x08, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x38, 0x0b, 0x04, 0x80, 0x98, 0x01, 0x08, 0x80, 0x88, 0x0a, 0x80, 0x8c, + 0x20, 0x04, 0x88, 0x06, 0x35, 0x0a, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x3a, 0x0c, + 0x04, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, 0x38, 0x0b, 0x30, + 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3d, 0x0b, 0x04, 0x80, 0x8c, 0x20, 0x04, 0x85, 0x3d, 0x20, + 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x3a, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, + 0x8b, 0x3c, 0x0a, 0x04, 0x80, 0x8c, 0x20, 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, + 0x3d, 0x0b, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x38, 0x0a, 0x04, 0x80, 0x8c, 0x20, + 0x04, 0x85, 0x3d, 0x14, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3c, 0x0a, 0x30, 0x04, 0x80, 0x82, 0x02, + 0x83, 0x3d, 0x08, 0x8b, 0x3a, 0x0b, 0x04, 0x83, 0x3a, 0x07, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, + 0x88, 0x04, 0x8f, 0x38, 0x0a, 0x30, 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x04, 0x46, 0x80, 0x88, + 0x04, 0x80, 0x88, 0x0a, 0x80, 0x98, 0x04, 0x48, 0x88, 0x06, 0x8f, 0x3a, 0x0b, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, + 0x83, 0x3d, 0x08, 0x9b, 0x35, 0x0a, 0x04, 0xa2, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, + 0x98, 0x04, 0x46, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x04, 0xa4, 0x80, 0x98, 0x04, 0x48, 0x83, + 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa4, 0x88, 0x06, 0x35, 0x0a, 0x30, 0x04, 0xa2, 0x80, 0x9b, 0x38, 0x03, + 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x38, 0x09, 0x04, 0xa1, 0x83, 0x2c, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, + 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x04, 0xa8, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x04, + 0x80, 0x98, 0x04, 0xa8, 0x85, 0x3d, 0x20, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x38, 0x09, 0x30, 0x04, 0xa1, + 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x88, 0x04, 0x80, 0x88, 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x98, + 0x01, 0x08, 0x88, 0x04, 0x88, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, + 0x04, 0x85, 0x3d, 0x14, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x06, 0x88, 0x04, 0x80, 0x82, 0x03, 0x83, 0x3d, + 0x08, 0x9b, 0x33, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x01, 0x08, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, + 0x98, 0x02, 0x08, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x06, 0x01, 0x80, 0x98, 0x01, 0x08, 0x80, + 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x33, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, + 0x98, 0x06, 0x01, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x06, 0x01, + 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x33, 0x0b, 0x04, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, + 0x88, 0x04, 0x88, 0x06, 0x98, 0x06, 0x01, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x31, 0x0c, 0x04, 0x80, + 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x33, 0x0b, 0x30, 0x04, 0x80, 0x82, + 0x03, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x30, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x85, 0x3d, 0x20, 0x80, 0x80, 0x8c, 0x20, + 0x04, 0x88, 0x06, 0x8f, 0x31, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x2c, 0x0b, 0x04, + 0x80, 0x88, 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, 0x30, 0x0c, 0x30, 0x04, + 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x31, 0x0a, 0x04, 0x80, 0x8c, 0x20, 0x04, 0x85, 0x3d, 0x14, + 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x2c, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, + 0x8b, 0x30, 0x09, 0x04, 0x83, 0x2c, 0x07, 0x8c, 0x20, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, + 0x04, 0x8f, 0x31, 0x0a, 0x30, 0x04, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x2e, 0x09, 0x04, 0x80, 0x8c, + 0x20, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x30, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, + 0x83, 0x3d, 0x08, 0x8b, 0x2c, 0x0a, 0x04, 0x80, 0x8c, 0x20, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, + 0x8f, 0x2e, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x2e, 0x0b, 0x04, 0x80, 0x88, + 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x2c, 0x0a, 0x30, 0x04, 0x80, 0x09, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x6d, 0x03, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x2e, 0x0c, 0x04, + 0xa1, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x06, 0x01, 0x80, 0x80, 0x85, 0x3d, 0x20, 0x88, 0x0a, 0x80, 0x88, 0x04, + 0x98, 0x06, 0x01, 0x2e, 0x0c, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x80, 0x88, + 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x06, 0x01, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x88, 0x04, 0x85, 0x3d, 0x14, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x88, + 0x06, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x98, 0x01, + 0x08, 0x88, 0x04, 0x88, 0x06, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, 0x04, + 0x80, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x06, 0x88, 0x06, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, + 0x35, 0x0a, 0x04, 0xa2, 0x80, 0x98, 0x01, 0x08, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, + 0x02, 0x08, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x31, 0x0c, 0x04, 0x80, 0x98, 0x01, 0x08, 0x80, + 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x35, 0x0a, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, + 0x08, 0x8b, 0x35, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, + 0x8f, 0x31, 0x0c, 0x30, 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3a, 0x0b, 0x04, 0x80, 0x8c, 0x20, + 0x04, 0x85, 0x3d, 0x20, 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x35, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x02, + 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x3c, 0x0a, 0x04, 0x80, 0x8c, 0x20, 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x88, + 0x04, 0x88, 0x04, 0x8f, 0x3a, 0x0b, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x38, 0x09, + 0x04, 0x80, 0x8c, 0x20, 0x04, 0x85, 0x3d, 0x14, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3c, 0x0a, 0x30, + 0x04, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x8b, 0x3a, 0x09, 0x04, 0x83, 0x2e, 0x07, 0x88, 0x04, 0x83, 0x49, 0x04, + 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, 0x38, 0x09, 0x30, 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, + 0x9b, 0x3c, 0x0a, 0x04, 0x46, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x9c, 0x20, 0x04, 0x48, 0x88, 0x06, 0x8f, + 0x3a, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x3d, 0x0b, 0x04, 0xa2, 0x80, 0x8c, 0x20, + 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x3c, 0x0a, 0x30, 0x04, 0x46, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x98, 0x04, 0xa8, 0x80, 0x9c, 0x20, 0x04, 0x48, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, + 0xa8, 0x88, 0x06, 0x3d, 0x0b, 0x30, 0x04, 0xa2, 0x80, 0x9b, 0x38, 0x03, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x3f, + 0x09, 0x04, 0xa1, 0x83, 0x2c, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, + 0x04, 0xa8, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x04, 0x80, 0x98, 0x04, 0xa8, 0x85, 0x3d, 0x20, + 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x3f, 0x09, 0x30, 0x04, 0xa1, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, + 0x88, 0x04, 0x80, 0x88, 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x88, 0x04, 0x80, + 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, 0x04, 0x85, 0x3d, 0x14, 0x88, 0x0a, 0x80, + 0x98, 0x01, 0x08, 0x88, 0x06, 0x88, 0x04, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x9b, 0x3c, 0x0c, 0x04, 0xa1, 0x80, + 0x98, 0x01, 0x08, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x02, 0x08, 0x80, 0x8a, 0x03, 0x0a, + 0x87, 0x3d, 0x08, 0x18, 0x98, 0x06, 0x01, 0x80, 0x98, 0x01, 0x08, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, + 0x3c, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x98, 0x06, 0x01, 0x80, 0x88, 0x04, 0x83, + 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x06, 0x01, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x88, 0x04, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x98, 0x06, 0x01, 0x80, 0x8a, + 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x38, 0x0c, 0x03, 0x08, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x88, 0x03, 0x88, 0x04, 0x88, 0x04, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x03, 0x80, 0x88, 0x04, 0x85, + 0x3d, 0x20, 0x80, 0x80, 0x88, 0x03, 0x88, 0x06, 0x38, 0x0c, 0x30, 0x03, 0x08, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, + 0x08, 0x88, 0x03, 0x83, 0x2c, 0x07, 0x88, 0x03, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x03, 0x88, 0x04, 0x88, + 0x03, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x03, 0x80, 0x88, 0x03, 0x85, 0x3d, 0x14, 0x88, 0x0a, + 0x80, 0x88, 0x04, 0x88, 0x06, 0x88, 0x03, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x9b, 0x33, 0x0c, 0x03, 0x10, 0x80, + 0x88, 0x03, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x03, 0x88, 0x04, 0x88, 0x03, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, + 0x18, 0x88, 0x03, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x03, 0x88, 0x06, 0x33, 0x0c, 0x30, 0x03, 0x10, + 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x88, 0x03, 0x80, 0x88, 0x03, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x03, 0x88, + 0x04, 0x88, 0x03, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x04, 0x80, 0x88, 0x03, 0x83, 0x3d, 0x05, + 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x88, 0x03, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xaf, 0x03, + 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x35, 0x0c, 0x04, 0xa3, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, + 0x06, 0x01, 0x80, 0x80, 0x87, 0x3d, 0x05, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x06, 0x01, 0x35, 0x0c, 0x30, + 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x80, 0x88, 0x04, 0x87, 0x3d, 0x05, 0x1c, 0x88, + 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x06, 0x01, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, + 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x88, 0x06, 0x80, 0x82, 0x02, 0x83, + 0x3d, 0x08, 0x88, 0x06, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x88, 0x06, + 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x98, + 0x01, 0x08, 0x88, 0x06, 0x88, 0x06, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x35, 0x0c, 0x04, 0xa3, 0x80, + 0x98, 0x01, 0x08, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x02, 0x08, 0x3d, 0x05, 0x24, + 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x31, 0x0b, 0x04, 0x80, 0x98, 0x01, 0x08, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x35, 0x0c, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x83, + 0x3d, 0x08, 0x8b, 0x31, 0x0a, 0x04, 0x83, 0x3a, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x8c, 0x20, + 0x04, 0x88, 0x04, 0x8f, 0x31, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x31, 0x09, 0x04, + 0x80, 0x8c, 0x10, 0x04, 0x83, 0x31, 0x05, 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x31, 0x0a, 0x30, 0x04, + 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x30, 0x0a, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, + 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x31, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, + 0x8b, 0x2c, 0x0b, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, + 0x30, 0x0a, 0x30, 0x04, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x8b, 0x27, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x83, 0x49, + 0x04, 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, 0x2c, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, + 0x18, 0x9b, 0x2e, 0x0b, 0x04, 0x46, 0x80, 0x88, 0x04, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x9c, 0x20, 0x04, 0x48, + 0x88, 0x06, 0x8f, 0x27, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x31, 0x0a, 0x04, 0xa2, + 0x80, 0x8c, 0x10, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x2e, 0x0b, 0x30, 0x04, 0x46, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x9b, 0x3a, 0x09, 0x04, 0xa3, 0x80, 0x9c, 0x10, 0x04, 0x48, 0x83, 0x31, 0x05, + 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x06, 0x31, 0x0a, 0x30, 0x04, 0xa2, 0x80, 0x9b, 0x36, 0x03, 0x0a, 0x0a, + 0x83, 0x3d, 0x08, 0x9b, 0x36, 0x09, 0x04, 0xa1, 0x83, 0x2a, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x88, 0x04, 0x88, 0x04, 0x3a, 0x09, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3a, + 0x0a, 0x04, 0x80, 0x98, 0x04, 0xa3, 0x87, 0x3d, 0x05, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x36, 0x09, + 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x36, 0x0b, 0x04, 0x80, 0x88, 0x04, 0x87, 0x3d, + 0x05, 0x1c, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x3a, 0x0a, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x8b, 0x31, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, + 0x06, 0x8f, 0x36, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x8b, 0x36, 0x0c, 0x04, 0x80, 0x88, 0x04, + 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x31, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x8b, 0x38, 0x0b, 0x04, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, + 0x36, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x3a, 0x0a, 0x04, 0x80, 0x88, 0x04, 0x83, + 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x38, 0x0b, 0x30, 0x04, 0x3d, 0x05, 0x24, 0x02, 0x10, + 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3d, 0x09, 0x04, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, + 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3a, 0x0a, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x42, + 0x09, 0x04, 0x83, 0x36, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x3d, + 0x09, 0x30, 0x04, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3d, 0x0a, 0x04, 0x80, 0x88, 0x04, 0x83, 0x31, + 0x05, 0x80, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x42, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, + 0x8b, 0x3a, 0x0b, 0x04, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x3d, + 0x0a, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x38, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x83, + 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3a, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x03, 0x83, 0x3d, + 0x08, 0x8b, 0x3a, 0x0c, 0x04, 0x83, 0x36, 0x07, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, + 0x8f, 0x38, 0x0c, 0x30, 0x04, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x36, 0x09, 0x04, 0x80, 0x88, 0x04, + 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3a, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, + 0x83, 0x3d, 0x08, 0x88, 0x04, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x04, + 0x8f, 0x36, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x04, 0x80, 0x88, 0x04, 0x83, + 0x4b, 0x04, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x88, 0x04, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0xc9, 0x03, 0x9b, 0x38, 0x03, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x44, 0x09, 0x04, 0xa3, 0x83, 0x2c, 0x07, 0x80, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x9b, 0x3f, 0x0a, 0x06, 0x01, 0x80, 0x80, 0x87, 0x3d, 0x05, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x06, + 0x01, 0x44, 0x09, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x3c, 0x0b, 0x06, 0x80, 0x88, + 0x04, 0x87, 0x3d, 0x05, 0x1c, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x3f, 0x0a, 0x30, 0x06, 0x01, 0x80, 0x8a, + 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3f, 0x0c, 0x06, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3c, 0x0b, 0x30, 0x06, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x8b, 0x44, 0x09, 0x06, + 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x8f, 0x3f, 0x0c, 0x30, 0x06, 0x80, + 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x98, 0x01, + 0x08, 0x88, 0x06, 0x8f, 0x44, 0x09, 0x30, 0x06, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x3f, 0x09, 0x04, + 0xa3, 0x80, 0x98, 0x01, 0x08, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x02, 0x08, 0x3d, + 0x05, 0x24, 0x02, 0x10, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3d, 0x0a, 0x04, 0x80, 0x98, 0x01, 0x08, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x3f, 0x09, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x03, + 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x3c, 0x0b, 0x04, 0x83, 0x2c, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, 0x3d, 0x0a, 0x30, 0x04, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x38, + 0x0c, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x31, 0x05, 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x3c, 0x0b, + 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x33, 0x0b, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x38, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, + 0x08, 0x18, 0x8b, 0x38, 0x0a, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, + 0x06, 0x8f, 0x33, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x8b, 0x31, 0x09, 0x04, 0x80, 0x88, 0x04, + 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x38, 0x0a, 0x30, 0x04, 0x80, 0x82, 0x03, 0x87, 0x3d, + 0x08, 0x18, 0x98, 0x04, 0x46, 0x80, 0x88, 0x04, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0x48, 0x88, 0x06, + 0x8f, 0x31, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x30, 0x09, 0x04, 0xa2, 0x80, 0x88, + 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x04, 0x46, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x9b, 0x2c, 0x0a, 0x04, 0xa3, 0x80, 0x98, 0x04, 0x48, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, + 0x88, 0x06, 0x30, 0x09, 0x30, 0x04, 0xa2, 0x80, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x2e, 0x0b, + 0x04, 0xa3, 0x83, 0x2e, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x2c, 0x0a, + 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x2c, 0x0c, 0x04, 0x80, 0x98, 0x04, 0xa3, + 0x87, 0x3d, 0x05, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x2e, 0x0b, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, + 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x31, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x87, 0x3d, 0x05, 0x1c, 0x88, 0x0a, 0x80, 0x88, + 0x04, 0x88, 0x04, 0x8f, 0x2c, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x30, 0x0b, + 0x04, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x31, 0x0c, 0x30, 0x04, + 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x8b, 0x2e, 0x0a, 0x04, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x8c, + 0x20, 0x04, 0x88, 0x04, 0x8f, 0x30, 0x0b, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x33, + 0x09, 0x04, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x2e, 0x0a, 0x30, 0x04, + 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x35, 0x0a, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, + 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, 0x33, 0x09, 0x30, 0x04, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, 0x02, + 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3a, 0x0b, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x88, 0x04, 0x88, 0x06, 0x8f, 0x35, 0x0a, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x38, 0x0c, + 0x04, 0x83, 0x2e, 0x07, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, + 0x3a, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3d, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x83, + 0x31, 0x05, 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x38, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x83, + 0x3d, 0x08, 0x8b, 0x3c, 0x0b, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, + 0x04, 0x8f, 0x3d, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3a, 0x0a, 0x04, 0x80, + 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3c, 0x0b, 0x30, 0x04, 0x80, + 0x82, 0x02, 0x83, 0x3d, 0x08, 0x9b, 0x3a, 0x09, 0x04, 0xa2, 0x83, 0x2e, 0x07, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, + 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x3a, 0x0a, 0x30, 0x04, 0x83, 0x49, 0x04, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, + 0x98, 0x06, 0x01, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x38, 0x09, + 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x98, 0x06, 0x01, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x88, + 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x8f, 0x3a, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x06, 0x88, + 0x04, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x0a, 0x03, 0x87, 0x3a, 0x02, 0x20, 0x95, 0x3a, 0x20, 0x37, + 0x22, 0x09, 0x50, 0x0f, 0x07, 0x9b, 0x3a, 0x07, 0x0f, 0xf0, 0x84, 0x61, 0x83, 0x25, 0x05, 0x80, 0x94, 0x81, 0x37, + 0x98, 0x04, 0xa1, 0x98, 0x04, 0xa2, 0x84, 0x61, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x25, 0x0a, 0x04, 0x80, 0x84, + 0x61, 0x83, 0x30, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x98, 0x06, 0x01, 0x87, 0x22, 0x09, 0x30, 0x80, 0x80, + 0x94, 0x81, 0x37, 0x8b, 0x29, 0x0b, 0x04, 0x80, 0x80, 0x83, 0x35, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, + 0x04, 0x81, 0x25, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8a, 0x0c, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, + 0x04, 0x88, 0x06, 0x81, 0x29, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x29, 0x0c, 0x04, 0x80, 0x80, 0x9b, 0x46, 0x04, + 0x1b, 0xc1, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x80, 0x88, 0x1b, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x25, + 0x0b, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x29, 0x80, 0x80, 0x94, 0x81, + 0x37, 0x8b, 0x24, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x2c, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, + 0x25, 0x87, 0x2c, 0x05, 0x30, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x20, 0x09, 0x04, 0x80, 0x80, 0x83, 0x2c, 0x05, 0x80, + 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x24, 0x87, 0x2c, 0x05, 0x20, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x22, + 0x09, 0x04, 0x80, 0x80, 0x83, 0x36, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x20, 0x80, 0x80, + 0x94, 0x81, 0x37, 0x8a, 0x09, 0x04, 0x80, 0x80, 0x83, 0x36, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, + 0x81, 0x22, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x27, 0x09, 0x04, 0x80, 0x80, 0x83, 0x36, 0x05, 0x80, 0x94, 0x81, + 0x37, 0x88, 0x04, 0x88, 0x04, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x25, 0x09, 0x04, 0x80, 0x80, 0x83, 0x36, + 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x27, 0x80, 0x80, 0x94, 0x91, 0x37, 0x8b, 0x24, 0x09, + 0x04, 0x80, 0x80, 0x9b, 0x46, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x91, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x25, 0x80, + 0x80, 0x94, 0x91, 0x37, 0x8b, 0x20, 0x0a, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x91, 0x37, 0x88, 0x04, 0x88, 0x06, + 0x81, 0x24, 0x80, 0x80, 0x94, 0x91, 0x37, 0x8b, 0x22, 0x0b, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x91, 0x37, 0x88, + 0x04, 0x88, 0x04, 0x81, 0x20, 0x80, 0x80, 0x94, 0x91, 0x37, 0x8a, 0x0c, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x91, + 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x22, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x8a, 0x0c, 0x04, 0x83, 0x3a, 0x07, + 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8a, + 0x0b, 0x04, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x80, 0x80, 0x80, 0x94, + 0x81, 0x37, 0x8b, 0x22, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, + 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x25, 0x09, 0x04, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, 0x81, 0x37, + 0x88, 0x04, 0x88, 0x06, 0x81, 0x22, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x29, 0x0a, 0x04, 0x80, 0x80, 0x9b, 0x46, + 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x25, 0x88, 0x1b, 0x80, 0x94, 0x81, 0x37, + 0x8b, 0x27, 0x0b, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x29, 0x80, 0x80, + 0x94, 0x81, 0x37, 0x8b, 0x25, 0x0c, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, + 0x04, 0x81, 0x27, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x29, 0x0c, 0x04, 0x80, 0x80, 0x9b, 0x46, 0x04, 0x1b, 0xc1, + 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x25, 0x88, 0x1b, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x24, 0x0b, + 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x29, 0x80, 0x80, 0x94, 0x81, 0x37, + 0x8b, 0x25, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x24, + 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x24, 0x09, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, + 0x04, 0x88, 0x04, 0x81, 0x25, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x20, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, + 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x24, 0x80, 0x80, 0x94, 0x91, 0x37, 0x8b, 0x22, 0x09, 0x04, + 0x80, 0x80, 0x9b, 0x46, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x91, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x20, 0x80, 0x80, + 0x94, 0x91, 0x37, 0x88, 0x04, 0x80, 0x80, 0x83, 0x3a, 0x05, 0x80, 0x94, 0x91, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, + 0x22, 0x80, 0x80, 0x94, 0x91, 0x37, 0x98, 0x01, 0x08, 0x80, 0x80, 0x83, 0x3a, 0x05, 0x80, 0x94, 0x91, 0x37, 0x98, + 0x02, 0x08, 0x88, 0x04, 0x80, 0x80, 0x80, 0x94, 0x91, 0x37, 0x98, 0x01, 0x08, 0x80, 0x80, 0x83, 0x3a, 0x05, 0x80, + 0x94, 0x91, 0x37, 0x98, 0x02, 0x08, 0x88, 0x06, 0x80, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x07, 0x04, + 0x87, 0x3a, 0x02, 0x30, 0x97, 0x3a, 0x09, 0x30, 0x37, 0x9b, 0x2e, 0x0b, 0x04, 0xa1, 0x83, 0x3a, 0x07, 0x80, 0x83, + 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x80, 0x94, 0x24, 0x37, + 0x98, 0x04, 0xa1, 0x80, 0x80, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, 0x98, 0x06, + 0x01, 0x2e, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, 0x0a, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, + 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, + 0x80, 0x94, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, + 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, 0x0b, 0x30, 0x37, 0x98, 0x04, 0xa1, + 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, + 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x80, 0x84, 0x81, 0x94, 0x20, + 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, 0x0c, 0x30, 0x37, 0x98, 0x04, 0xa1, + 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, + 0xa1, 0x80, 0x80, 0x94, 0x24, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, + 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, 0x0c, 0x30, 0x37, + 0x9b, 0x35, 0x0b, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, + 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, 0x37, 0x9b, 0x3a, 0x0b, 0x04, 0xa1, 0x80, 0x98, + 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x37, 0x9c, 0x20, 0x06, 0x01, 0x98, 0x06, 0x10, 0x35, + 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, 0x0b, 0x30, 0x37, 0x9b, 0x35, 0x0b, 0x04, 0xa1, 0x80, 0x98, + 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x37, 0x9c, 0x20, 0x06, 0x01, 0x88, 0x04, 0x3a, 0x0b, + 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x37, 0x9b, 0x30, 0x0b, 0x04, 0xa1, 0x80, 0x9c, 0x14, 0x06, 0x01, + 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x98, 0x06, 0x20, 0x35, 0x0a, 0x30, 0x04, + 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, 0x0a, 0x30, 0x37, 0x9b, 0x2c, 0x09, 0x04, 0xa1, 0x80, 0x9c, 0x14, 0x06, 0x01, + 0x83, 0x49, 0x04, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x30, 0x09, 0x30, 0x04, 0xa1, 0x80, + 0x84, 0x81, 0x94, 0x24, 0x37, 0x9b, 0x2e, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x30, 0x84, + 0x81, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x2c, 0x09, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, + 0x09, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x20, 0x84, 0x81, 0x94, 0x20, 0x37, + 0x98, 0x06, 0x01, 0x88, 0x04, 0x2e, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x37, 0x9b, 0x31, 0x0b, + 0x03, 0x11, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x18, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x03, 0x21, 0x88, + 0x06, 0x98, 0x04, 0xa1, 0x80, 0x87, 0x38, 0x03, 0x30, 0x97, 0x38, 0x09, 0x30, 0x47, 0x9b, 0x2e, 0x0c, 0x04, 0xa1, + 0x83, 0x2c, 0x07, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, 0x98, 0x04, + 0xa2, 0x31, 0x0b, 0x30, 0x03, 0x11, 0x80, 0x80, 0x94, 0x24, 0x47, 0x9b, 0x35, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x03, + 0x21, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x01, 0x2e, 0x0c, 0x30, + 0x04, 0xa1, 0x80, 0x80, 0x97, 0x38, 0x0a, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, + 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x35, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x94, + 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, + 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x38, 0x0b, 0x30, 0x47, 0x9b, 0x38, 0x0b, 0x04, 0xa1, + 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, + 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x80, 0x84, 0x81, 0x94, 0x20, + 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x38, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x38, 0x0c, 0x30, 0x47, 0x98, + 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, + 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x24, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, + 0x84, 0x81, 0x94, 0x22, 0x47, 0x9a, 0x0a, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x38, + 0x0c, 0x30, 0x47, 0x9b, 0x31, 0x0a, 0x03, 0x08, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, + 0x47, 0x98, 0x03, 0x08, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, 0x47, 0x98, 0x03, 0x08, 0x80, + 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x03, 0x08, 0x98, 0x06, 0x10, 0x31, + 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x38, 0x0b, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, + 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, + 0x81, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, + 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x20, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x38, 0x0a, 0x30, 0x47, 0x9b, + 0x30, 0x0c, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x49, 0x04, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, + 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, + 0x49, 0x04, 0x30, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x30, 0x0c, 0x30, 0x04, 0xa1, 0x80, + 0x84, 0x81, 0x97, 0x38, 0x09, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x20, 0x84, + 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x47, 0x98, + 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, + 0x06, 0x98, 0x04, 0xa1, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x26, 0x03, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, + 0x83, 0x3d, 0x08, 0x9b, 0x2e, 0x0c, 0x06, 0x01, 0x83, 0x3a, 0x07, 0x97, 0x3a, 0x09, 0x30, 0x37, 0x83, 0x3d, 0x05, + 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x98, 0x04, 0xa2, 0x94, 0x82, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x87, 0x3d, 0x05, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x06, 0x01, + 0x94, 0x82, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x14, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x87, 0x3d, + 0x05, 0x1c, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x94, 0x82, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x94, 0x82, + 0x37, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, + 0x04, 0x88, 0x04, 0x94, 0x82, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, + 0x37, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x94, 0x81, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x14, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x94, 0x81, + 0x37, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x94, 0x81, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, + 0x08, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x94, 0x81, + 0x37, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x83, 0x31, 0x05, 0x80, 0x80, + 0x88, 0x04, 0x88, 0x06, 0x94, 0x81, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x14, 0x88, 0x06, 0x80, 0x94, + 0x81, 0x37, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x94, 0x81, 0x37, 0x80, 0x8a, 0x02, 0x0a, + 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, + 0x06, 0x94, 0x81, 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x83, 0x3a, 0x07, 0x94, 0x81, 0x30, 0x83, + 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, 0x94, 0x81, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x88, + 0x06, 0x80, 0x94, 0x81, 0x30, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x94, 0x81, 0x30, 0x80, + 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x14, 0x88, 0x06, 0x80, 0x94, 0x81, 0x30, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x06, + 0x88, 0x04, 0x94, 0x81, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x30, + 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x06, 0x88, 0x06, 0x94, 0x81, 0x30, 0x80, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, + 0x83, 0x3d, 0x08, 0x88, 0x06, 0x83, 0x3a, 0x07, 0x94, 0x81, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x06, + 0x88, 0x04, 0x94, 0x81, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x30, + 0x87, 0x3d, 0x05, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x06, 0x88, 0x06, 0x94, 0x81, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x14, 0x88, 0x06, 0x80, 0x94, 0x81, 0x30, 0x87, 0x3d, 0x05, 0x1c, 0x88, 0x0a, 0x80, 0x88, 0x06, 0x88, + 0x04, 0x84, 0x81, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x84, 0x81, 0x83, 0x3d, 0x05, + 0x88, 0x0a, 0x80, 0x88, 0x06, 0x88, 0x06, 0x84, 0x81, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x80, 0x84, + 0x81, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x06, 0x88, 0x04, 0x84, 0x81, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x88, 0x06, 0x80, 0x84, 0x81, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x06, 0x88, 0x06, 0x84, 0x81, 0x80, 0x8a, 0x02, + 0x0a, 0x87, 0x3d, 0x08, 0x14, 0x88, 0x06, 0x80, 0x84, 0x81, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x06, 0x88, + 0x04, 0x84, 0x81, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, 0x83, + 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x80, 0x80, 0x80, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x04, 0x80, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, + 0x80, 0x83, 0x31, 0x05, 0x80, 0x80, 0x80, 0x88, 0x06, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x14, 0x80, + 0x80, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x04, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x80, 0x80, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x80, 0x80, 0x82, 0x02, 0x83, 0x3d, + 0x08, 0x80, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x80, 0x80, 0x82, 0x02, 0x87, + 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x80, 0x80, 0x8a, 0x02, + 0x0a, 0x87, 0x3d, 0x08, 0x14, 0x80, 0x80, 0x80, 0x83, 0x49, 0x04, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x04, 0x80, 0x80, + 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, 0x83, 0x4b, 0x04, 0x88, 0x0a, 0x82, 0x0c, 0x80, 0x88, + 0x06, 0x80, 0x80, 0x07, 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x3a, 0x3a, 0x7e, 0x7e, 0x44, 0x72, 0x30, + 0x5a, 0x45, 0x52, 0x69, 0x58, 0x7e, 0x7e, 0x3a, 0x3a, 0x2e, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x09, 0x00, 0x00, 0x40, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x0f, 0xf3, 0x28, 0xb8, 0x40, 0xa1, 0x77, 0xb1, 0xe5, 0x7b, 0x7f, 0x61, 0xe7, + 0xd1, 0x14, 0x37, 0xb5, 0x3f, 0xea, 0xf6, 0xc6, 0x77, 0x9b, 0x39, 0xb9, 0x76, 0xb1, 0xe8, 0x67, 0xb8, 0xed, 0x1b, + 0xf1, 0x26, 0x19, 0x8b, 0x45, 0x09, 0x1f, 0xb8, 0x39, 0xe1, 0x1e, 0x00, 0xa1, 0x95, 0x62, 0x8f, 0xa3, 0x0f, 0x30, + 0xcf, 0x25, 0xd0, 0x2c, 0xd7, 0x34, 0xcc, 0x19, 0xf4, 0x4a, 0x8f, 0x5d, 0xe5, 0xc7, 0x5a, 0xca, 0xe5, 0x21, 0x04, + 0x1b, 0xc5, 0x0c, 0x4f, 0x9c, 0x1d, 0x37, 0x99, 0x53, 0xe5, 0xef, 0x3e, 0xa3, 0x57, 0xde, 0xd6, 0x34, 0xf1, 0xf7, + 0xf9, 0x38, 0x9f, 0x59, 0xdf, 0x21, 0xc7, 0x21, 0xef, 0x08, 0x01, 0x00, 0x1b, 0xe4, 0xe1, 0x4b, 0xe9, 0xb7, 0x55, + 0xde, 0xf1, 0x19, 0xe8, 0x0f, 0x11, 0xcf, 0x7b, 0x5d, 0x4d, 0x27, 0xdd, 0xcc, 0x4c, 0xb7, 0x68, 0x91, 0x27, 0x4a, + 0x87, 0x37, 0x0c, 0xda, 0xfb, 0x56, 0xc9, 0xd9, 0x48, 0xc7, 0x59, 0x6b, 0x97, 0x93, 0x3b, 0x0f, 0xb4, 0x41, 0xd4, + 0x1c, 0x27, 0xa7, 0x43, 0x03, 0xb1, 0x77, 0xa0, 0xff, 0x61, 0x77, 0x79, 0xff, 0x80, 0x80, 0xbc, 0x35, 0xc7, 0x18, + 0xff, 0x12, 0xdf, 0x49, 0x6f, 0xa3, 0xa8, 0xf5, 0x39, 0xcf, 0xf7, 0x2a, 0x1c, 0xa3, 0x1b, 0x3a, 0xe7, 0x02, 0xc2, + 0x51, 0xbf, 0x29, 0x04, 0xe3, 0x43, 0x9b, 0x73, 0x79, 0x38, 0x4c, 0xab, 0xf7, 0x39, 0xf7, 0xd8, 0x34, 0xcd, 0x3a, + 0x91, 0x8f, 0xbd, 0xc8, 0x7b, 0xae, 0x09, 0xfe, 0x29, 0xdf, 0x08, 0xe8, 0x34, 0xc1, 0x21, 0x0b, 0xef, 0xf2, 0x0f, + 0x0a, 0xf5, 0xf5, 0x24, 0xb1, 0x7d, 0x91, 0x49, 0xbf, 0x53, 0x85, 0x79, 0xcb, 0xd6, 0x6f, 0xaf, 0xf3, 0x3d, 0xe5, + 0xdb, 0x21, 0x20, 0xdf, 0x01, 0xef, 0x3e, 0xa7, 0x4a, 0xe1, 0xd1, 0x5a, 0xc3, 0x12, 0xfc, 0x05, 0x13, 0xe4, 0x08, + 0x01, 0xf7, 0x32, 0xca, 0xe4, 0x3f, 0xea, 0x13, 0xd4, 0x2c, 0xfd, 0xb7, 0x64, 0xbc, 0x2d, 0xd4, 0x54, 0x83, 0x65, + 0xc7, 0x45, 0xaa, 0x25, 0x41, 0x76, 0x29, 0x53, 0xce, 0xff, 0x2d, 0xa8, 0x2b, 0x31, 0x9f, 0x51, 0x9f, 0x89, 0x98, + 0x1f, 0x20, 0xac, 0x40, 0x01, 0xe4, 0xff, 0x11, 0x2f, 0xc1, 0xeb, 0x5d, 0x9b, 0x22, 0x3f, 0x94, 0x5a, 0xf1, 0xfd, + 0xcf, 0x09, 0x1f, 0x05, 0x0c, 0xe7, 0xd1, 0x2f, 0x15, 0xf3, 0xe1, 0x27, 0xf1, 0x20, 0xcf, 0xed, 0x33, 0xf9, 0x0b, + 0x08, 0xb5, 0x2f, 0x0b, 0xe7, 0x2f, 0xb7, 0x45, 0xe3, 0x01, 0xfb, 0x10, 0xff, 0xdd, 0x29, 0xf0, 0xef, 0x11, 0x3f, + 0xa1, 0x07, 0x3c, 0xb1, 0x3c, 0xef, 0x21, 0xdf, 0xe1, 0x4f, 0xa5, 0x1b, 0x4e, 0xa7, 0x24, 0x10, 0xb3, 0x45, 0xef, + 0xff, 0x12, 0xc0, 0x4f, 0xf9, 0xc3, 0x37, 0xee, 0xdb, 0x65, 0xa4, 0xff, 0x15, 0x47, 0xc1, 0xff, 0xfc, 0xe5, 0x2a, + 0x10, 0xf5, 0xbd, 0x49, 0x2b, 0x83, 0x3d, 0xf7, 0x3a, 0xd2, 0xdb, 0x2a, 0xdf, 0x27, 0x12, 0xe8, 0xe7, 0x05, 0x23, + 0xdc, 0xf1, 0x22, 0x0e, 0x0b, 0xc6, 0xfb, 0x3f, 0xe3, 0xfd, 0x01, 0xfd, 0x17, 0xc1, 0x2b, 0x2f, 0x97, 0x89, 0x71, + 0x6a, 0xb5, 0x21, 0x1f, 0xc1, 0x3f, 0xe9, 0xe7, 0xf9, 0x37, 0xbe, 0x57, 0xb3, 0x29, 0xc1, 0x3f, 0x1b, 0xbd, 0x0a, + 0x3c, 0xcd, 0xe4, 0x31, 0xef, 0x0a, 0x02, 0xe0, 0x1d, 0xdf, 0x21, 0x27, 0xa5, 0x2f, 0x0d, 0xef, 0x0c, 0xbd, 0x42, + 0x46, 0x75, 0x4a, 0x00, 0xd9, 0x17, 0x11, 0xe0, 0x02, 0x55, 0x81, 0x3c, 0x13, 0xd1, 0x28, 0xe2, 0x12, 0x1b, 0xb1, + 0x2b, 0x4b, 0x7a, 0x5b, 0x05, 0xa3, 0x4c, 0x09, 0xd0, 0x37, 0xe1, 0xc7, 0x61, 0xb3, 0x42, 0xf1, 0xed, 0x0b, 0xe2, + 0xfc, 0x3b, 0xf9, 0xb4, 0x71, 0xc3, 0xef, 0xfb, 0x35, 0xe1, 0xf7, 0xfd, 0x37, 0x9d, 0x37, 0x11, 0x24, 0x77, 0x99, + 0xa7, 0xed, 0x3f, 0xf9, 0xdb, 0x24, 0x05, 0x9f, 0x93, 0x8e, 0x2b, 0x41, 0x80, 0x5f, 0xf9, 0xb7, 0x34, 0x2d, 0xc7, + 0x09, 0xee, 0x11, 0x23, 0xa1, 0x5d, 0x0f, 0x91, 0x77, 0x99, 0x2f, 0x26, 0xef, 0xd3, 0x2c, 0xc0, 0x2d, 0x3f, 0x95, + 0x23, 0x39, 0xbf, 0x11, 0xdb, 0x15, 0x5f, 0x89, 0x2c, 0xfb, 0x01, 0xbf, 0xa6, 0x9b, 0xbf, 0x81, 0x80, 0x5f, 0xcf, + 0x01, 0x31, 0xf4, 0xd3, 0x0f, 0xf2, 0x17, 0x29, 0xd8, 0xdb, 0x4f, 0xae, 0x1d, 0x3a, 0xb9, 0x27, 0xe1, 0x1f, 0xd1, + 0x38, 0xc2, 0x65, 0xa1, 0x0f, 0x35, 0xa7, 0x44, 0x15, 0xdb, 0xf9, 0x07, 0xcd, 0x5b, 0xf9, 0x9f, 0x70, 0xd1, 0xef, + 0x2b, 0x9a, 0x8b, 0xf1, 0x9b, 0x1d, 0x37, 0xbc, 0x58, 0xad, 0x1f, 0x26, 0xbb, 0x1f, 0x09, 0xbf, 0x78, 0xd9, 0xcb, + 0x04, 0x2a, 0xcf, 0x57, 0xad, 0x1a, 0x19, 0xd1, 0x27, 0xc9, 0x27, 0x29, 0xd2, 0xdb, 0x43, 0xde, 0xee, 0x43, 0x0d, + 0x87, 0x3c, 0x29, 0xd3, 0x0c, 0x01, 0x15, 0xfb, 0xaf, 0x65, 0xc4, 0x17, 0x1e, 0xf3, 0xbf, 0x4e, 0xc3, 0x37, 0x0a, + 0xde, 0xed, 0x18, 0xfc, 0xe1, 0x4e, 0xa9, 0x47, 0xe3, 0xd6, 0x4f, 0x99, 0x6b, 0x05, 0xbc, 0xeb, 0x5b, 0x9a, 0x4b, + 0x0c, 0xb2, 0x2b, 0x29, 0xce, 0x09, 0xc6, 0x79, 0xef, 0x82, 0x76, 0xf0, 0xb9, 0x42, 0x07, 0xe7, 0x14, 0xbc, 0x60, + 0xb1, 0x10, 0x27, 0x09, 0xcf, 0xf1, 0x27, 0x1b, 0xbf, 0x2b, 0xf7, 0xed, 0x1f, 0xf3, 0xf1, 0x11, 0xfb, 0x23, 0xa6, + 0x4b, 0xfc, 0xf9, 0xcf, 0x6d, 0x86, 0x2d, 0x49, 0x8f, 0x31, 0x1c, 0xc9, 0x4a, 0x99, 0x4e, 0xf1, 0xf1, 0x03, 0x39, + 0x8c, 0x5f, 0xe1, 0xf7, 0x0d, 0x20, 0xc5, 0x06, 0x1e, 0xf2, 0xec, 0x0c, 0x49, 0xb2, 0xe9, 0x2d, 0x12, 0xb6, 0x4f, + 0xe9, 0xed, 0xf6, 0x49, 0x85, 0x76, 0xe1, 0xda, 0x25, 0xcc, 0x3c, 0xf1, 0xe7, 0x39, 0xd0, 0x05, 0xfb, 0x0b, 0xe9, + 0x43, 0xc9, 0x11, 0xd6, 0x33, 0xdc, 0x26, 0xea, 0xfe, 0x19, 0xe1, 0xe2, 0x27, 0x31, 0x97, 0x59, 0xd7, 0x19, 0xdb, + 0x15, 0x17, 0xe6, 0xed, 0x36, 0xe0, 0xbf, 0x75, 0xc8, 0x1f, 0xd5, 0xd5, 0x7b, 0xa9, 0x12, 0x21, 0xc8, 0x2b, 0x11, + 0xb4, 0x23, 0x25, 0xec, 0xd7, 0x49, 0xa4, 0x53, 0xf1, 0xcf, 0x20, 0x21, 0xbb, 0x45, 0xc5, 0x1b, 0xff, 0x38, 0xa1, + 0x1b, 0x13, 0x21, 0xad, 0x46, 0xdc, 0x27, 0xcb, 0x27, 0xe3, 0xe2, 0x63, 0xf9, 0x7f, 0x71, 0xdb, 0x0d, 0x02, 0xfc, + 0xf4, 0xf3, 0x31, 0xd9, 0xe9, 0x2f, 0x15, 0xdb, 0xcb, 0x7a, 0x64, 0x87, 0x01, 0xc0, 0xcf, 0x81, 0xb0, 0x0b, 0x22, + 0xcb, 0x32, 0xb8, 0x4e, 0xd0, 0x06, 0x19, 0x06, 0xeb, 0xef, 0x11, 0xf1, 0x1d, 0x11, 0xd1, 0xff, 0x01, 0x2f, 0xe9, + 0xcf, 0x50, 0xd9, 0xef, 0x31, 0xb7, 0x19, 0x4f, 0xb1, 0x0c, 0xfb, 0x09, 0x07, 0x19, 0xdf, 0xe2, 0x4f, 0xa7, 0x29, + 0xf1, 0x25, 0xf6, 0xfd, 0xcf, 0x4f, 0xdb, 0xbd, 0x87, 0xb1, 0xe9, 0x3d, 0xe3, 0xf7, 0x19, 0xde, 0x11, 0x2b, 0x9e, + 0x39, 0x12, 0xf1, 0xfb, 0x02, 0x0b, 0xdb, 0x28, 0xf5, 0xe0, 0x29, 0x19, 0xb5, 0x11, 0x43, 0xb1, 0x0f, 0x51, 0xa0, + 0x1f, 0xf9, 0x07, 0x15, 0xd0, 0x37, 0xdb, 0xf5, 0x25, 0xfb, 0xf5, 0xbf, 0xa1, 0x70, 0x0e, 0x39, 0x02, 0xc1, 0x36, + 0xfe, 0xe1, 0x1d, 0xfe, 0xfe, 0xd7, 0x16, 0x4b, 0x8b, 0x50, 0xc5, 0x4f, 0xbb, 0x25, 0xd9, 0x27, 0xf1, 0xec, 0x33, + 0xc4, 0x3b, 0xe2, 0xd7, 0x58, 0x95, 0x4b, 0x11, 0xcd, 0x17, 0x07, 0xee, 0xef, 0x27, 0xf9, 0xf8, 0x0a, 0xeb, 0xf2, + 0x3b, 0xc5, 0x21, 0xf7, 0x11, 0xbf, 0x45, 0xf0, 0xfb, 0x0c, 0xf9, 0xea, 0x05, 0x08, 0x25, 0xdf, 0xe9, 0x35, 0xe7, + 0xbf, 0x7d, 0x8f, 0x63, 0xb8, 0x19, 0xea, 0x12, 0x29, 0x9f, 0x68, 0xc7, 0xff, 0x04, 0xf7, 0x42, 0xa1, 0x55, 0xac, + 0x37, 0x04, 0xe9, 0x00, 0x12, 0xf5, 0x01, 0xfc, 0x08, 0xfb, 0x06, 0xfb, 0x0f, 0xcb, 0x35, 0x11, 0xd0, 0xf0, 0x3c, + 0xe3, 0xe9, 0x2d, 0xe3, 0xff, 0x09, 0x30, 0x9b, 0x23, 0x47, 0xcb, 0xdf, 0x4d, 0xb1, 0x27, 0x0b, 0x03, 0xe1, 0xcc, + 0x9f, 0x8a, 0xf7, 0x3a, 0xee, 0xf1, 0xef, 0x4d, 0xa3, 0x3f, 0xd2, 0x2a, 0xe5, 0x09, 0x1d, 0xd1, 0x0b, 0x07, 0x00, + 0xff, 0x21, 0xad, 0x63, 0xca, 0xcf, 0x6e, 0xcb, 0xfe, 0xdf, 0x51, 0xbb, 0x15, 0x12, 0xd7, 0x3c, 0xcf, 0x04, 0x07, + 0xe9, 0x47, 0xd1, 0xe3, 0x25, 0xf6, 0x01, 0x21, 0xbf, 0x30, 0xec, 0x15, 0xe7, 0xde, 0x5f, 0xaf, 0x39, 0xc8, 0x38, + 0xbf, 0x3f, 0x0a, 0x97, 0x44, 0x21, 0xf0, 0xbf, 0x5d, 0xcc, 0xef, 0x28, 0x15, 0x99, 0x52, 0x15, 0xcc, 0xea, 0x4d, + 0xd9, 0xfd, 0xf0, 0x57, 0x6c, 0x5f, 0x19, 0xc8, 0xef, 0x41, 0xd3, 0x01, 0x2b, 0xcb, 0x16, 0xff, 0x0d, 0xee, 0xee, + 0x2d, 0xd6, 0x43, 0xc1, 0x11, 0xcf, 0x91, 0x79, 0x13, 0x10, 0x21, 0xd7, 0x0b, 0x01, 0xf7, 0x19, 0xf7, 0x09, 0xcb, + 0x25, 0x32, 0xab, 0x2e, 0xdd, 0x30, 0xe7, 0x01, 0xff, 0xf4, 0x1c, 0xe1, 0x21, 0xe2, 0x11, 0xf3, 0x29, 0xdd, 0xe3, + 0x3f, 0xe1, 0x0f, 0xd1, 0x3f, 0xc5, 0x21, 0x02, 0x09, 0xd9, 0x0e, 0x3c, 0xb1, 0xff, 0x38, 0xed, 0xd3, 0x50, 0xd5, + 0xdc, 0x20, 0x2f, 0xd5, 0xdb, 0x41, 0xd9, 0x13, 0xfd, 0xf5, 0xf5, 0x19, 0x2f, 0x99, 0x2b, 0x01, 0x2e, 0xc5, 0x19, + 0xe0, 0x17, 0x28, 0xc9, 0x05, 0xfe, 0x44, 0xb1, 0x07, 0x1e, 0xd7, 0x3f, 0xdd, 0x0c, 0xb7, 0x68, 0xed, 0xc8, 0x17, + 0x29, 0xdd, 0xf2, 0x13, 0xf9, 0x17, 0xdd, 0x19, 0xf6, 0xf8, 0x19, 0xf1, 0x00, 0xef, 0x21, 0xfb, 0xe5, 0x10, 0x07, + 0x01, 0xe5, 0x2b, 0xda, 0x11, 0xff, 0x06, 0xeb, 0x13, 0xeb, 0x21, 0x02, 0xb3, 0x6b, 0xce, 0xf9, 0xec, 0x5a, 0x95, + 0x15, 0x55, 0x8b, 0x56, 0xd9, 0x09, 0xf8, 0x07, 0x13, 0xe4, 0xf9, 0x0f, 0x29, 0xb9, 0x17, 0x1d, 0xd8, 0x36, 0xbd, + 0x27, 0xf8, 0x21, 0xb8, 0x1f, 0x34, 0xc9, 0xeb, 0x3c, 0xfd, 0xa1, 0x82, 0xcd, 0xc8, 0x2b, 0x4d, 0x8b, 0x24, 0x21, + 0xe8, 0xe9, 0x2a, 0xf3, 0xea, 0x1f, 0xe0, 0x2b, 0xc6, 0x1f, 0x31, 0xb4, 0x1b, 0xf4, 0x2f, 0xad, 0x67, 0xa2, 0x37, + 0xf7, 0xf5, 0xfb, 0x10, 0x01, 0x00, 0xf9, 0x0e, 0xcf, 0x3e, 0xe5, 0x0f, 0xd1, 0x3f, 0xd3, 0x0b, 0x0b, 0xf0, 0x0f, + 0xfb, 0xfb, 0x03, 0xfb, 0xfe, 0x1f, 0xe9, 0xef, 0x23, 0xdd, 0x0b, 0x1b, 0xe7, 0xed, 0x23, 0xf3, 0xf3, 0x1d, 0xdf, + 0x21, 0xfa, 0xe6, 0xf7, 0x43, 0xbc, 0x2f, 0xea, 0xf9, 0xf3, 0x36, 0xe9, 0xda, 0x17, 0x2a, 0xcf, 0xed, 0x2a, 0x1c, + 0xa5, 0x57, 0xd8, 0x0c, 0xd9, 0x3b, 0xf7, 0xde, 0xef, 0x50, 0xd1, 0xdb, 0x4b, 0xe9, 0xc5, 0x49, 0xe3, 0x07, 0xed, + 0x1b, 0xe5, 0x17, 0xf5, 0xff, 0x09, 0xea, 0x05, 0x39, 0xb0, 0x0f, 0x34, 0xd5, 0x08, 0xf3, 0x0d, 0x17, 0xf1, 0xcf, + 0x3a, 0x07, 0xbd, 0x4e, 0xdf, 0xd5, 0x4f, 0xd9, 0x01, 0xd7, 0x40, 0x09, 0xd8, 0xdb, 0x50, 0xdd, 0x08, 0xe7, 0x19, + 0xf7, 0x01, 0xff, 0x01, 0xdf, 0x4a, 0xd2, 0x09, 0xd1, 0x46, 0xfd, 0xdc, 0x03, 0xf6, 0x42, 0xb3, 0x23, 0xff, 0xfb, + 0xe9, 0x37, 0xe1, 0xed, 0x08, 0x33, 0xda, 0xd8, 0x3d, 0xd2, 0x45, 0xa8, 0x46, 0xd0, 0x23, 0xde, 0x38, 0xbe, 0x1d, + 0xff, 0x11, 0xe4, 0xf7, 0x36, 0xdf, 0xdf, 0x41, 0xea, 0xd5, 0x23, 0x1e, 0xd8, 0xe3, 0x58, 0xa5, 0x4f, 0xb9, 0x3f, + 0xc1, 0x33, 0x03, 0xdf, 0xf2, 0x25, 0x03, 0xdd, 0x23, 0xe1, 0x0f, 0x11, 0xdc, 0x09, 0x1e, 0xf2, 0xf3, 0x13, 0xf5, + 0xe4, 0x3b, 0xd1, 0x1a, 0xf1, 0x0f, 0xee, 0x05, 0x00, 0x08, 0x08, 0xe5, 0x0d, 0x0d, 0xec, 0xfb, 0x26, 0xdb, 0x0b, + 0xfb, 0x10, 0xee, 0x05, 0x11, 0xee, 0x01, 0x03, 0xff, 0x01, 0xff, 0x08, 0xf3, 0x0c, 0xf2, 0x16, 0xe6, 0x0b, 0x01, + 0x09, 0xfe, 0xe4, 0x21, 0xf8, 0xf0, 0x11, 0x0a, 0xe9, 0xfb, 0x20, 0xed, 0xf7, 0x0c, 0x03, 0xfe, 0xf6, 0x0c, 0xe9, + 0x20, 0xfc, 0xf5, 0xf0, 0x0b, 0x14, 0xf9, 0xe6, 0x1d, 0xf4, 0x09, 0xf8, 0xe6, 0x29, 0x07, 0xdc, 0x05, 0x0b, 0xed, + 0x2c, 0xe8, 0xfd, 0xed, 0x1d, 0x0b, 0xdb, 0xff, 0x31, 0xea, 0xea, 0xef, 0x3c, 0xd1, 0x1b, 0xfe, 0xfb, 0xd5, 0x3a, + 0x07, 0xb9, 0x4c, 0xe9, 0xed, 0x05, 0xef, 0x43, 0xbe, 0x28, 0xe2, 0x0b, 0xf3, 0x27, 0xd7, 0x1b, 0xfd, 0xf3, 0xf2, + 0x2f, 0xcb, 0x2b, 0xfb, 0xe7, 0xfb, 0x1b, 0x0e, 0xc7, 0x28, 0x05, 0xf8, 0xe7, 0x26, 0xdf, 0x1b, 0xf9, 0x04, 0xd7, + 0x38, 0xf5, 0xf4, 0xe2, 0x1d, 0x21, 0xe4, 0xf1, 0xf5, 0x2f, 0xd9, 0x29, 0xd5, 0x0f, 0x09, 0xf8, 0xfb, 0xfb, 0x09, + 0x0b, 0x11, 0xc5, 0x13, 0x31, 0xc2, 0x32, 0xe7, 0x01, 0xed, 0x28, 0xfa, 0xd9, 0x1c, 0x02, 0x16, 0xb6, 0x35, 0xfd, + 0x09, 0xec, 0x13, 0xec, 0xfa, 0x11, 0x11, 0xe5, 0x03, 0x03, 0x05, 0xf7, 0x05, 0x03, 0x00, 0xf6, 0x17, 0xdb, 0x1f, + 0xf5, 0xfa, 0x26, 0xd1, 0xf3, 0x24, 0x21, 0xae, 0x41, 0xe4, 0x02, 0xfc, 0x1e, 0xd6, 0xfe, 0x42, 0xd3, 0xeb, 0x05, + 0x27, 0xf9, 0xda, 0x19, 0xfa, 0x1b, 0xc7, 0x3c, 0xd9, 0xf1, 0x4f, 0xba, 0x0a, 0xf7, 0x3a, 0xaf, 0x4a, 0xcc, 0x15, + 0x06, 0xf7, 0xee, 0x29, 0xe6, 0x03, 0xff, 0x01, 0xf7, 0x0f, 0x01, 0x01, 0xec, 0x17, 0xea, 0x17, 0xd7, 0x3f, 0xe0, + 0xf3, 0x06, 0x0e, 0xfb, 0xdb, 0x55, 0xae, 0x23, 0x02, 0x01, 0xdb, 0x30, 0xfd, 0xd9, 0x2a, 0xdd, 0x1f, 0xf1, 0x03, + 0xdd, 0x4f, 0xc9, 0xe7, 0x32, 0xff, 0xdb, 0x32, 0xce, 0x19, 0xeb, 0x3d, 0xb4, 0x1d, 0x0d, 0x06, 0xef, 0xe6, 0x2a, + 0xf3, 0x13, 0xc5, 0x45, 0xd9, 0x07, 0xf9, 0x17, 0xd2, 0x3f, 0xeb, 0xd1, 0x35, 0xeb, 0x09, 0xff, 0xff, 0xe5, 0x37, + 0xe1, 0xef, 0x20, 0xf7, 0xec, 0x21, 0xdd, 0x0f, 0xfe, 0x19, 0xde, 0x10, 0xe9, 0x26, 0xed, 0xeb, 0x24, 0xfb, 0xf7, + 0xdf, 0x47, 0xb9, 0x3b, 0xe9, 0xf8, 0xf4, 0x1f, 0xf3, 0xf1, 0x16, 0xf9, 0xf9, 0x12, 0xe4, 0x04, 0x1e, 0xf9, 0xe1, + 0x20, 0xe8, 0x0a, 0x12, 0xdd, 0x17, 0x0f, 0xe5, 0xe7, 0x3d, 0xdb, 0x0d, 0xf7, 0x08, 0x03, 0xe9, 0x1d, 0xe6, 0x1d, + 0xf8, 0xee, 0x04, 0x05, 0x0a, 0xf9, 0xf3, 0x06, 0x19, 0xdb, 0x1d, 0xe7, 0x0c, 0x09, 0x08, 0xe4, 0xf9, 0x2c, 0xda, + 0x21, 0xd9, 0x15, 0xfd, 0x0e, 0xf3, 0xd7, 0x50, 0xd9, 0x02, 0xfb, 0xf3, 0x0f, 0x1b, 0xce, 0x17, 0x11, 0xd7, 0x39, + 0xc4, 0x1b, 0x03, 0x0d, 0xe3, 0x0d, 0x05, 0xff, 0xef, 0x1d, 0xf5, 0xef, 0x19, 0xe5, 0x0a, 0x1d, 0xdd, 0xfb, 0x23, + 0xf7, 0xe1, 0x0d, 0x15, 0xfe, 0xf1, 0x06, 0xe8, 0x11, 0x25, 0xe8, 0xe9, 0x02, 0x29, 0xd6, 0x08, 0x0d, 0xf7, 0x0d, + 0x06, 0xdb, 0xeb, 0x58, 0xd1, 0xf7, 0x11, 0xef, 0x04, 0x0c, 0x0d, 0xc1, 0x40, 0x03, 0xc7, 0x31, 0xdf, 0x2a, 0xd6, + 0x39, 0xb3, 0x23, 0xf9, 0x25, 0xe4, 0xed, 0x26, 0xed, 0xff, 0x07, 0xe7, 0x1e, 0x0e, 0xcf, 0x27, 0xdd, 0x1b, 0x03, + 0xfc, 0xe9, 0x25, 0xe3, 0xff, 0x21, 0xe9, 0xe7, 0x3d, 0xda, 0x01, 0xf4, 0x19, 0xeb, 0x08, 0x23, 0xbe, 0x0f, 0x2b, + 0xf2, 0xcb, 0x4f, 0xc2, 0x27, 0xf7, 0xf1, 0xf6, 0x1d, 0x18, 0xca, 0x0b, 0x21, 0xcc, 0x31, 0xf6, 0xd9, 0x33, 0xe9, + 0x00, 0xf3, 0x0c, 0x15, 0xf5, 0xe6, 0x25, 0xc9, 0x2c, 0x00, 0x07, 0xd9, 0x16, 0x07, 0xf7, 0x13, 0xdd, 0x12, 0x13, + 0xd9, 0x13, 0xf9, 0x21, 0xdb, 0x15, 0xf7, 0x01, 0xf6, 0x19, 0xe9, 0x17, 0xe2, 0x14, 0xf0, 0x0a, 0x29, 0xb2, 0x49, + 0xbf, 0x33, 0xf1, 0xce, 0x4b, 0xf1, 0xe7, 0xf3, 0x32, 0xcc, 0x23, 0x0f, 0xca, 0x19, 0x11, 0xfc, 0xc5, 0x5c, 0xdd, + 0xe3, 0x28, 0xd7, 0x1d, 0xff, 0x05, 0xd7, 0x2d, 0xf1, 0xff, 0xfa, 0x09, 0x08, 0xe5, 0x24, 0xed, 0xf7, 0x04, 0x1b, + 0xe2, 0xf5, 0x25, 0xee, 0xf6, 0xff, 0x31, 0xba, 0x1f, 0x11, 0xe7, 0xff, 0x12, 0xfa, 0xfd, 0x01, 0xf3, 0x1f, 0xd4, + 0x37, 0xdb, 0x01, 0x15, 0xe0, 0x22, 0xd7, 0x3d, 0xd7, 0xeb, 0x30, 0xea, 0x04, 0xf3, 0x11, 0xef, 0x19, 0xe4, 0x0e, + 0xfb, 0x19, 0xd2, 0x23, 0x05, 0xc7, 0x40, 0x01, 0xd5, 0x07, 0x1b, 0xf1, 0xef, 0x31, 0xc0, 0x1f, 0x19, 0xdb, 0xfd, + 0x0b, 0x1e, 0xe2, 0x05, 0x05, 0xe4, 0x34, 0xd3, 0x1b, 0xf5, 0x01, 0xf4, 0x1b, 0xdb, 0x26, 0xe3, 0x26, 0xe8, 0xe1, + 0x20, 0x14, 0xdd, 0xfb, 0x2d, 0xdd, 0xfc, 0x13, 0x03, 0xd9, 0x2b, 0xf9, 0xf3, 0xf9, 0x05, 0x20, 0xcf, 0x27, 0xf2, + 0xfe, 0x01, 0xf7, 0x1d, 0xde, 0x05, 0x35, 0xac, 0x23, 0x18, 0xe5, 0x13, 0xef, 0x1d, 0xd1, 0x0b, 0x1a, 0xfd, 0xf5, + 0x01, 0xfb, 0x07, 0x01, 0xed, 0x23, 0xe6, 0x0e, 0xfd, 0xf0, 0x11, 0xef, 0x1f, 0xfd, 0xdb, 0x04, 0x25, 0xfb, 0xd9, + 0x27, 0xea, 0x14, 0xed, 0x00, 0x06, 0xf3, 0x22, 0x0b, 0xbb, 0x25, 0xff, 0x11, 0xef, 0xfc, 0x01, 0x0c, 0x02, 0x07, + 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x06, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xd3, 0x06, 0x00, 0x00, 0x40, 0x00, 0x02, 0x80, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, + 0x16, 0x09, 0x12, 0x21, 0xfb, 0xa9, 0x0c, 0x0d, 0xd4, 0x00, 0x0f, 0x0e, 0x0e, 0xcb, 0x1b, 0x13, 0xb8, 0x10, 0xcb, + 0x00, 0x11, 0x14, 0xe5, 0xf9, 0x16, 0xf5, 0xe6, 0x11, 0x2b, 0x17, 0xfa, 0x0a, 0x0c, 0x08, 0x05, 0xc0, 0x03, 0x29, + 0x11, 0x05, 0x18, 0x0f, 0xe0, 0xba, 0x18, 0x0f, 0x0a, 0x0e, 0x0f, 0x1c, 0x05, 0xc1, 0x0f, 0x14, 0x29, 0x0a, 0x0b, + 0x0a, 0x07, 0x00, 0x0a, 0x03, 0xef, 0x11, 0x0a, 0x05, 0xe2, 0xe6, 0x0e, 0x0e, 0xf9, 0xcb, 0xa9, 0x0b, 0x19, 0x11, + 0x16, 0x04, 0xf2, 0xd9, 0x16, 0x1f, 0x1e, 0xf9, 0xbc, 0x04, 0x08, 0x09, 0x0a, 0xba, 0xcf, 0x14, 0x10, 0x03, 0x1f, + 0x0c, 0xb8, 0x04, 0x0b, 0xcd, 0x00, 0x07, 0x13, 0x19, 0x06, 0x27, 0xde, 0x0d, 0x15, 0x16, 0xfc, 0x13, 0x18, 0x0e, + 0x0b, 0xf1, 0xf4, 0x0a, 0xbb, 0xeb, 0xdd, 0x1c, 0x06, 0x0a, 0x0f, 0x07, 0x07, 0x08, 0x07, 0x2b, 0x16, 0x0c, 0x0a, + 0x05, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x16, 0x08, 0xc2, 0x11, 0x11, 0x08, 0x07, 0x0d, 0xe4, 0xba, 0xa2, + 0xc7, 0x14, 0x16, 0x13, 0x16, 0xeb, 0xbc, 0x00, 0x09, 0x16, 0x1f, 0x22, 0x01, 0x00, 0x09, 0x0a, 0x0c, 0xd0, 0x02, + 0x0e, 0xfe, 0xd7, 0x2b, 0x0f, 0x05, 0x0c, 0x0c, 0x08, 0xc7, 0x17, 0x1a, 0x13, 0x0d, 0xb7, 0xe5, 0x00, 0x11, 0x16, + 0x07, 0x0f, 0x0a, 0x09, 0x08, 0x0c, 0x1a, 0xce, 0x0b, 0x08, 0x00, 0x05, 0x1f, 0xab, 0x03, 0x02, 0x05, 0xa9, 0x15, + 0x0d, 0x16, 0x1d, 0x11, 0x0e, 0x2a, 0x18, 0x13, 0x03, 0x05, 0xe7, 0xcf, 0x1b, 0x02, 0xda, 0x0f, 0xca, 0xc4, 0x15, + 0x0c, 0x05, 0x1b, 0xa6, 0x0a, 0x13, 0x0d, 0x13, 0x0e, 0x0a, 0xbe, 0x01, 0x1c, 0x19, 0x29, 0xfe, 0xfb, 0x0c, 0x1b, + 0x15, 0x11, 0x12, 0x04, 0xb3, 0xb9, 0x07, 0x1b, 0x08, 0xd9, 0xd7, 0x10, 0x03, 0xf1, 0xd2, 0x13, 0x17, 0x37, 0x16, + 0xfe, 0xd7, 0x13, 0x27, 0x10, 0x06, 0x0b, 0x05, 0xbd, 0xfb, 0xe7, 0xf9, 0x0c, 0xc6, 0x13, 0x12, 0x1c, 0x0d, 0x07, + 0x05, 0x09, 0xd5, 0xde, 0x18, 0x16, 0x18, 0xf4, 0xe0, 0x2a, 0x13, 0x07, 0x12, 0x10, 0x05, 0x0a, 0x0f, 0x11, 0x0a, + 0xf6, 0xc5, 0x07, 0x05, 0x22, 0x0a, 0x93, 0xa4, 0x11, 0x1f, 0x1d, 0x11, 0x19, 0xf4, 0xd4, 0xc5, 0x16, 0x01, 0x10, + 0x16, 0x0c, 0x0f, 0x0e, 0x0d, 0x0a, 0x09, 0xc8, 0x27, 0xc4, 0x07, 0x22, 0x13, 0x13, 0x08, 0x04, 0x00, 0x01, 0xab, + 0xb2, 0x1f, 0x12, 0x1d, 0x0e, 0xde, 0x1d, 0x1e, 0x07, 0x0f, 0x0c, 0x0e, 0x0c, 0xd2, 0xef, 0x13, 0xf5, 0xc7, 0xd5, + 0x05, 0x09, 0xd7, 0xeb, 0x10, 0x00, 0x0a, 0x07, 0x12, 0x1c, 0x14, 0x13, 0x0a, 0x18, 0x07, 0x22, 0x00, 0x0a, 0x11, + 0x16, 0x0d, 0x00, 0x00, 0xf8, 0xc5, 0xb8, 0x16, 0x05, 0x05, 0x07, 0xa6, 0x0f, 0x15, 0x0d, 0x0e, 0x0c, 0xbe, 0x19, + 0x22, 0x0a, 0x0c, 0x10, 0x1c, 0x0e, 0x07, 0x0f, 0x07, 0x05, 0x97, 0x1d, 0x06, 0xe3, 0xde, 0x35, 0x15, 0x01, 0xa4, + 0x04, 0x07, 0x08, 0x07, 0xc9, 0xc7, 0x08, 0x1d, 0x22, 0xe1, 0xcd, 0x13, 0x0a, 0x0b, 0x2a, 0x07, 0x07, 0x11, 0x0f, + 0xd4, 0xd4, 0xed, 0x13, 0x08, 0x03, 0x00, 0x22, 0x06, 0x08, 0x0f, 0x18, 0x15, 0x16, 0x11, 0xf0, 0xdb, 0x1b, 0xff, + 0x11, 0x05, 0x0c, 0x12, 0x13, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x7d, 0x09, 0x0f, 0x07, + 0x0a, 0xb3, 0xbc, 0x13, 0x18, 0x19, 0x0e, 0x13, 0x11, 0x1b, 0x14, 0x0c, 0x0e, 0x08, 0x06, 0x03, 0x63, 0xd1, 0x2f, + 0x22, 0xd9, 0xf3, 0x0a, 0xfe, 0x1a, 0x01, 0x06, 0x0f, 0xc4, 0x0c, 0x16, 0x16, 0x1a, 0xcf, 0x14, 0x03, 0x1c, 0x19, + 0x0e, 0x16, 0x1f, 0x12, 0x04, 0x0d, 0xef, 0xa3, 0xde, 0x05, 0xfb, 0xb0, 0x0a, 0x0a, 0x0f, 0x10, 0x18, 0x14, 0x0f, + 0x04, 0x33, 0x18, 0x0a, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xc6, 0x2c, 0x18, 0x18, 0x0d, 0x0a, + 0xa8, 0x05, 0x11, 0x0a, 0x09, 0xdc, 0xe1, 0x17, 0xbf, 0x13, 0x12, 0x11, 0xcf, 0x13, 0x18, 0x20, 0x13, 0x03, 0x05, + 0x02, 0x0a, 0x0e, 0x1b, 0xdc, 0xe3, 0x02, 0xb3, 0xde, 0x16, 0x10, 0x16, 0x20, 0x13, 0xc8, 0x1d, 0xf2, 0xde, 0xd9, + 0x0a, 0x1b, 0x13, 0x0e, 0x08, 0x11, 0x13, 0x11, 0x08, 0x84, 0x0a, 0x32, 0x0d, 0x0e, 0x0c, 0x00, 0x11, 0x02, 0x00, + 0x06, 0x0b, 0x08, 0x9d, 0xfd, 0x2e, 0x22, 0x1b, 0x1b, 0x0b, 0x0f, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xdd, 0xf4, 0xe0, 0x50, 0x00, 0x00, 0x1d, 0x04, 0xdf, 0x00, 0x06, 0x0d, 0x07, 0x0f, 0x15, 0x12, 0x04, 0x1b, + 0x0a, 0x1b, 0x11, 0x13, 0x15, 0xb8, 0xdc, 0x00, 0xde, 0x05, 0x06, 0x05, 0xfc, 0x04, 0x03, 0x0f, 0x13, 0x0c, 0x00, + 0xd4, 0x11, 0x20, 0x13, 0xfc, 0x1c, 0x11, 0x0c, 0x0b, 0x07, 0x04, 0x00, 0x0f, 0xcb, 0xd4, 0x11, 0x29, 0xcb, 0xf4, + 0xb5, 0xf4, 0x18, 0x15, 0x0f, 0x0c, 0x0a, 0x0a, 0x00, 0x1d, 0x09, 0xc1, 0x29, 0x0f, 0xc8, 0x03, 0x07, 0x25, 0x09, + 0x0e, 0xce, 0xdb, 0x0c, 0x11, 0x0d, 0x02, 0x03, 0xaf, 0xfb, 0x06, 0x06, 0x19, 0xcd, 0x1f, 0x12, 0x0b, 0xd7, 0xe1, + 0x24, 0x20, 0x0a, 0x07, 0x18, 0x0a, 0x04, 0x0d, 0x13, 0x13, 0x03, 0x0e, 0x19, 0x03, 0xe2, 0xe0, 0xae, 0x07, 0x11, + 0x07, 0x08, 0x09, 0x12, 0xdb, 0x7b, 0x1d, 0x1b, 0x00, 0x1c, 0x14, 0x0c, 0x0f, 0x11, 0x13, 0x11, 0xd0, 0xf1, 0xdb, + 0x14, 0x11, 0xfb, 0xb8, 0x0e, 0xed, 0xdd, 0x08, 0x20, 0x0e, 0x09, 0x0a, 0xfc, 0x1c, 0x12, 0x0e, 0x22, 0x0a, 0x07, + 0x07, 0x0c, 0x05, 0x0c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x05, 0xce, 0x52, 0xe1, 0x1a, 0x0e, 0xe3, 0xf5, 0x10, + 0x0d, 0x0c, 0x0a, 0x0b, 0x3b, 0x32, 0x06, 0x05, 0x0b, 0x0f, 0x07, 0x0a, 0xea, 0xdc, 0xf1, 0x98, 0x0e, 0x0c, 0x0b, + 0x10, 0x03, 0x07, 0x07, 0x0a, 0x11, 0x14, 0x10, 0x00, 0xcb, 0x00, 0x1d, 0xf9, 0xf8, 0xd3, 0x13, 0xd4, 0xf7, 0x21, + 0x1b, 0x05, 0x0e, 0x0f, 0x0e, 0x0b, 0x06, 0x00, 0x98, 0xb2, 0x14, 0x19, 0x0c, 0x05, 0x1c, 0x16, 0x08, 0x1a, 0xcb, + 0xed, 0x29, 0x16, 0x02, 0x0a, 0x0a, 0x10, 0x12, 0x00, 0xd8, 0x16, 0xdf, 0x04, 0x0f, 0x2e, 0x0e, 0xbc, 0xe1, 0x0a, + 0x0a, 0xc5, 0x07, 0x08, 0x04, 0x0f, 0xe0, 0xd3, 0x21, 0x22, 0x23, 0x0b, 0x00, 0x16, 0x0c, 0x1b, 0x0f, 0x07, 0xf9, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x56, 0xc5, 0x11, 0xd5, 0x0e, 0x25, 0x0b, 0x05, 0x11, 0xc6, 0x0e, 0x0d, 0xe8, 0x21, + 0x0a, 0x0d, 0x17, 0x14, 0x02, 0xbd, 0x2b, 0x1b, 0xdb, 0xc4, 0xf6, 0x0f, 0x0a, 0x00, 0x00, 0x0b, 0x0c, 0x11, 0x0a, + 0x07, 0xfe, 0x18, 0x12, 0x11, 0x37, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xb7, 0x5d, 0x20, 0x0c, 0xca, 0x14, 0x11, 0x10, 0x0a, 0x0d, 0x10, 0x0f, 0x20, 0x17, 0x11, 0xce, 0xe5, 0xf6, + 0xed, 0xd9, 0x08, 0x02, 0x09, 0xeb, 0x0c, 0x09, 0x00, 0x01, 0x05, 0x0c, 0x10, 0x14, 0x07, 0x03, 0x07, 0x29, 0x0a, + 0x7b, 0x0c, 0xf4, 0x10, 0x0f, 0x07, 0x13, 0x14, 0x0e, 0x11, 0x16, 0x0a, 0x0c, 0x0c, 0x0c, 0x17, 0x05, 0xb6, 0xac, + 0x04, 0x14, 0x09, 0x0a, 0x05, 0x00, 0x24, 0x11, 0xac, 0xf6, 0x18, 0x14, 0x11, 0x1c, 0x14, 0x0e, 0xce, 0x0c, 0x13, + 0x11, 0xd4, 0x0a, 0x0e, 0x03, 0xd5, 0xd4, 0x11, 0x9a, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x15, 0x14, 0x15, 0x16, 0x0c, + 0x11, 0x0f, 0x0e, 0x19, 0x0e, 0x08, 0x02, 0x00, 0x20, 0x13, 0xba, 0x00, 0x15, 0xce, 0xc5, 0xc6, 0x14, 0x11, 0x0c, + 0x10, 0x11, 0x0f, 0x07, 0xfe, 0xd9, 0x0a, 0x00, 0x1d, 0x11, 0x0e, 0x12, 0xcf, 0x00, 0x11, 0x1a, 0x0a, 0xdc, 0xf1, + 0xb3, 0x0f, 0x07, 0x05, 0x04, 0x11, 0x14, 0x09, 0x0a, 0x03, 0x1d, 0x05, 0x07, 0x15, 0x14, 0x02, 0x19, 0x03, 0x00, + 0xe0, 0xdd, 0xf4, 0x1b, 0x07, 0x0f, 0x0c, 0x03, 0x0c, 0xe5, 0x62, 0x0d, 0xb0, 0x00, 0x00, 0x04, 0x0f, 0x15, 0x0b, + 0x0b, 0xc6, 0x19, 0x16, 0x0e, 0x20, 0x11, 0x04, 0xe3, 0xea, 0x0f, 0x09, 0x23, 0xd7, 0xff, 0x14, 0xfd, 0x16, 0x07, + 0x0d, 0x0c, 0x04, 0x0c, 0x0b, 0x0b, 0x11, 0x11, 0x16, 0xe3, 0x89, 0xcb, 0x13, 0x27, 0x11, 0x16, 0x1a, 0x12, 0x10, + 0x12, 0x0e, 0x08, 0x0a, 0x00, 0x00, 0xe4, 0xd9, 0xfa, 0xbb, 0x11, 0xbf, 0xbf, 0x1a, 0x14, 0x00, 0x02, 0x13, 0x1d, + 0x0f, 0x11, 0x1f, 0x16, 0xed, 0xde, 0x14, 0x0e, 0x13, 0x0c, 0xbf, 0xc8, 0x0d, 0xf5, 0xc1, 0x03, 0xf2, 0x00, 0x00, + 0x13, 0x11, 0x11, 0x13, 0x0c, 0x16, 0x1b, 0xfd, 0x1b, 0x1b, 0x1a, 0x05, 0x01, 0x13, 0x05, 0x05, 0x0a, 0x00, 0x00, + 0x00, 0xfb, 0xd3, 0xa9, 0x0f, 0xfb, 0xc4, 0x21, 0x19, 0x0e, 0x0c, 0x0a, 0x03, 0x11, 0xe5, 0xcf, 0x00, 0x18, 0x23, + 0x02, 0xcb, 0x0e, 0xa8, 0xed, 0x19, 0xf6, 0xe5, 0x11, 0x0a, 0x0c, 0x0e, 0x01, 0x05, 0x0b, 0x16, 0x05, 0x05, 0x0c, + 0x00, 0x07, 0xbd, 0x21, 0x12, 0x0e, 0x14, 0x1c, 0x0f, 0x11, 0x11, 0x0c, 0x0a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x8b, + 0xbe, 0x00, 0xfb, 0xda, 0x21, 0x12, 0x11, 0x13, 0x0c, 0x05, 0x1d, 0x0c, 0xa7, 0x15, 0x16, 0x11, 0xb7, 0x0a, 0x18, + 0x0c, 0x1b, 0x0e, 0xd7, 0xfe, 0x0c, 0x0a, 0x11, 0x02, 0x05, 0x0e, 0x0d, 0x09, 0xfb, 0x8f, 0xfb, 0x10, 0x08, 0x1d, + 0xbe, 0xd5, 0x1d, 0x22, 0x20, 0x10, 0x14, 0x0f, 0x0c, 0x0c, 0x10, 0x16, 0xbc, 0x00, 0x0c, 0x9f, 0x0b, 0x10, 0xeb, + 0xdb, 0x14, 0x02, 0x0e, 0x0a, 0x0c, 0x19, 0x1a, 0x05, 0xfe, 0x1b, 0x17, 0xcb, 0x0f, 0x15, 0x11, 0x0f, 0x14, 0x07, + 0xd4, 0x0c, 0x01, 0x47, 0xe1, 0x00, 0x06, 0x19, 0x11, 0x0e, 0x1b, 0x0c, 0x0c, 0x05, 0x16, 0x20, 0x0c, 0x09, 0x0c, + 0x14, 0x0f, 0xfb, 0x0a, 0xfd, 0x08, 0x86, 0x0e, 0x0f, 0x0e, 0x0b, 0xb9, 0xf2, 0x18, 0x0e, 0xef, 0xdf, 0x13, 0x09, + 0x00, 0xfe, 0x11, 0xdb, 0x08, 0x9d, 0x00, 0x1d, 0xe3, 0x0b, 0x16, 0x12, 0x11, 0x1c, 0x19, 0xf3, 0xed, 0x0c, 0x03, + 0xec, 0x14, 0x0e, 0x11, 0x07, 0x03, 0x0a, 0x13, 0x0f, 0x02, 0x0e, 0x20, 0x0c, 0xd4, 0xc7, 0x1a, 0x1f, 0x16, 0x12, + 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f, 0x22, 0x1b, 0x14, 0xe2, 0xe4, 0x0e, 0x02, 0xd9, 0xc2, 0x00, + 0x24, 0x0f, 0x10, 0x0f, 0xd2, 0x04, 0x16, 0x00, 0x11, 0x14, 0x05, 0x09, 0xd3, 0xc2, 0x0d, 0x00, 0x11, 0x11, 0x15, + 0x16, 0x08, 0x09, 0x08, 0x07, 0x0f, 0x13, 0x24, 0x0a, 0xcf, 0xa2, 0x22, 0x1b, 0x21, 0x17, 0x10, 0x1b, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x86, 0x1b, 0x1d, 0x08, 0xbe, 0xf2, 0x0e, 0x0f, 0x09, 0x11, 0x20, 0x09, 0x0a, 0x0e, + 0xe3, 0xe8, 0x27, 0x0e, 0x00, 0x0b, 0x04, 0x14, 0x92, 0x98, 0x19, 0xcd, 0x00, 0x00, 0x00, 0x04, 0x16, 0x0a, 0x0c, + 0x03, 0xfd, 0x13, 0x1e, 0xd2, 0x0e, 0x0f, 0x02, 0x13, 0x0f, 0x18, 0xf9, 0x18, 0x13, 0x11, 0x1b, 0x16, 0x03, 0xfd, + 0xea, 0xa9, 0x11, 0x1f, 0x0a, 0x0e, 0xce, 0xf6, 0x1d, 0x07, 0x0a, 0x22, 0x11, 0x03, 0xad, 0x78, 0xe6, 0x07, 0x2c, + 0x15, 0x18, 0x16, 0x0a, 0x18, 0xe1, 0xf1, 0x07, 0x0a, 0x0c, 0x14, 0x15, 0x05, 0xf0, 0x07, 0x05, 0xf6, 0x0a, 0xf1, + 0xc1, 0xe5, 0x19, 0x13, 0x0e, 0x14, 0x15, 0x16, 0x14, 0x0e, 0x08, 0x02, 0x0a, 0x05, 0xc1, 0x62, 0xe1, 0x00, 0x06, + 0x1e, 0x0f, 0x0e, 0xc8, 0xfe, 0x1d, 0x1a, 0x20, 0x1b, 0x02, 0x03, 0xf6, 0xb0, 0x1b, 0x11, 0x10, 0x0a, 0x24, 0x19, + 0x15, 0x0b, 0xc3, 0x05, 0x10, 0x11, 0xeb, 0xc0, 0x17, 0x0e, 0x0c, 0x05, 0x07, 0x0a, 0x09, 0x25, 0x0f, 0x04, 0xde, + 0xcd, 0x00, 0x19, 0x18, 0x24, 0x16, 0x06, 0x00, 0x00, 0x00, 0xdd, 0xc6, 0xd0, 0xd1, 0x1e, 0x10, 0x0d, 0xfb, 0x07, + 0xc3, 0xfb, 0x03, 0x0e, 0x19, 0xc6, 0x15, 0x0f, 0xc3, 0x0c, 0x08, 0x18, 0x1a, 0x11, 0x14, 0x16, 0x15, 0xed, 0xc8, + 0xa0, 0x00, 0x00, 0x07, 0x1d, 0x0f, 0x0c, 0x10, 0x16, 0x19, 0x0e, 0x13, 0x22, 0x0a, 0x0a, 0x0a, 0x04, 0x9d, 0x0c, + 0x16, 0x1f, 0x0c, 0x14, 0x0f, 0x05, 0x02, 0x08, 0x00, 0xbd, 0x05, 0x16, 0x0c, 0x0d, 0x07, 0x05, 0xc0, 0xf2, 0xfd, + 0x25, 0x02, 0xcb, 0xc3, 0xa0, 0x00, 0x00, 0x00, 0x09, 0x25, 0x13, 0x0e, 0x11, 0x03, 0xc1, 0xdc, 0x07, 0x18, 0x0f, + 0x11, 0x04, 0xfb, 0x03, 0xfd, 0x16, 0x11, 0x0f, 0x24, 0x0f, 0x05, 0x05, 0x07, 0xf8, 0x0d, 0x18, 0x18, 0x12, 0x07, + 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x20, 0x20, 0x4b, 0x65, 0x79, 0x67, 0x65, 0x6e, 0x20, 0x57, 0x72, + 0x61, 0x69, 0x74, 0x68, 0x20, 0x2e, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x63, 0x06, 0x00, 0x00, 0x40, 0x00, 0x02, 0x80, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, + 0xc4, 0xfa, 0x39, 0xfd, 0x37, 0xf9, 0x00, 0xe3, 0xf0, 0xef, 0xee, 0xef, 0xe6, 0x13, 0x2c, 0xed, 0x17, 0x34, 0x3f, + 0x0c, 0xf6, 0xe8, 0xea, 0xf1, 0xea, 0xde, 0x40, 0x1d, 0xf6, 0xf4, 0xf4, 0xf3, 0xed, 0xea, 0xf0, 0xf3, 0xfc, 0x6d, + 0xf3, 0xdc, 0x0c, 0x1e, 0xf5, 0xfc, 0xf9, 0xf8, 0xf1, 0xf9, 0x3d, 0x1b, 0x15, 0xf7, 0xf1, 0xf2, 0xf3, 0xf0, 0xdd, + 0xdc, 0xf6, 0x05, 0xf4, 0xef, 0xf2, 0xe5, 0xf7, 0x04, 0x35, 0x3d, 0xf6, 0xf4, 0x51, 0xe9, 0xef, 0xe9, 0xe3, 0x13, + 0x22, 0xf3, 0xef, 0xf0, 0xf3, 0xfb, 0xf2, 0x0f, 0x22, 0xea, 0xf4, 0xf3, 0xe6, 0x3c, 0xea, 0xef, 0xf2, 0xed, 0x27, + 0xfd, 0xea, 0xf4, 0xf9, 0x3c, 0x3a, 0x2a, 0xef, 0x0c, 0x11, 0xef, 0xe8, 0x0f, 0x09, 0xf9, 0xec, 0x00, 0x53, 0xf4, + 0xf4, 0xf4, 0xea, 0xf6, 0xf4, 0xf8, 0x28, 0xf6, 0xe7, 0x20, 0x3a, 0xf1, 0xf7, 0xf1, 0xed, 0x1d, 0x16, 0xe8, 0xf1, + 0xf9, 0xf6, 0xe1, 0xef, 0xef, 0xf3, 0x00, 0xf0, 0xf3, 0xef, 0xe3, 0xfb, 0xfe, 0xef, 0xf2, 0x1f, 0xef, 0xf2, 0x00, + 0x1a, 0xf4, 0xf2, 0x00, 0x26, 0x22, 0x02, 0xeb, 0xf4, 0xf4, 0xe5, 0x27, 0x8f, 0x04, 0xf7, 0xe1, 0xee, 0xeb, 0xe8, + 0xfa, 0xf9, 0x38, 0xfd, 0xf4, 0x51, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xec, 0xed, 0xf1, 0x1d, 0xf2, + 0xf1, 0xf2, 0xee, 0x33, 0x00, 0xf2, 0xe8, 0xfa, 0x00, 0xe8, 0xe6, 0x13, 0x14, 0xf4, 0xfa, 0xf9, 0xea, 0xf0, 0xff, + 0xed, 0xdc, 0x24, 0x07, 0xef, 0xf2, 0x1f, 0x0c, 0xf4, 0xf9, 0x02, 0xf2, 0xe5, 0xeb, 0xef, 0x00, 0x00, 0x0e, 0x27, + 0x4d, 0xef, 0x29, 0x16, 0xef, 0xea, 0xf4, 0x0c, 0x34, 0xf3, 0xea, 0xed, 0x4c, 0xf6, 0xf4, 0x30, 0xf6, 0x05, 0xfe, + 0xd9, 0xe5, 0xe5, 0xe8, 0xf4, 0xf4, 0xf1, 0xeb, 0x30, 0xfc, 0x3e, 0xf0, 0xfd, 0x13, 0x28, 0xf1, 0xdc, 0xe9, 0x2a, + 0xfd, 0xea, 0x1d, 0xf5, 0xf4, 0xfb, 0xf3, 0xea, 0xef, 0xf2, 0xe8, 0xe8, 0x1f, 0x5f, 0x10, 0xed, 0xf6, 0xf5, 0x46, + 0x00, 0xfb, 0xf8, 0xf0, 0xe8, 0xea, 0x61, 0x07, 0xf4, 0xf6, 0xe1, 0xef, 0xfb, 0xf9, 0xff, 0xf0, 0xf1, 0xe7, 0xdc, + 0x4b, 0x05, 0xf2, 0xed, 0xfa, 0x2f, 0xe8, 0xdd, 0xed, 0xea, 0xe6, 0xfd, 0x3c, 0xeb, 0xec, 0x34, 0x00, 0x2e, 0x0c, + 0x24, 0xfd, 0x01, 0x02, 0xe0, 0xeb, 0xe8, 0xde, 0xf1, 0x18, 0x1f, 0xfc, 0xec, 0xea, 0x33, 0x1e, 0x04, 0xeb, 0x35, + 0x4c, 0xf0, 0xf4, 0xf0, 0xea, 0xe3, 0x04, 0x12, 0xf1, 0xf1, 0xef, 0xea, 0x00, 0x5d, 0xee, 0xf4, 0x01, 0xee, 0xfc, + 0xf4, 0x11, 0x10, 0xeb, 0xf4, 0xfd, 0xe8, 0x30, 0x0f, 0xed, 0xf4, 0xf5, 0x3e, 0xe0, 0xf1, 0xef, 0xeb, 0xf6, 0x00, + 0xf3, 0xf2, 0xf1, 0xda, 0x02, 0x41, 0x2e, 0xf9, 0xf7, 0xec, 0x03, 0x3c, 0xef, 0xed, 0xe8, 0xf8, 0x40, 0xf4, 0xec, + 0xf1, 0xea, 0xe8, 0x2f, 0xfb, 0xff, 0x58, 0xef, 0xec, 0xe8, 0xe6, 0xe0, 0xf7, 0xfa, 0xf7, 0xf1, 0xef, 0x20, 0xea, + 0x53, 0x39, 0xed, 0xea, 0x3a, 0xf7, 0xf1, 0xea, 0xeb, 0x38, 0xfb, 0x1d, 0xe8, 0xe9, 0x23, 0x24, 0xf9, 0xef, 0xef, + 0xe0, 0xf6, 0x3b, 0xf6, 0xf9, 0xec, 0xea, 0x42, 0x13, 0xf9, 0xf7, 0x15, 0x16, 0xf9, 0xf6, 0xf6, 0xf7, 0xf6, 0xe1, + 0xea, 0xee, 0xf4, 0xfa, 0xe9, 0xe3, 0xf4, 0xe3, 0xf4, 0xf4, 0xfe, 0x00, 0x3c, 0xfd, 0x08, 0xf4, 0xea, 0xe8, 0xf9, + 0x00, 0x2b, 0xef, 0xed, 0xf9, 0x00, 0x1d, 0xb6, 0xf4, 0xf6, 0x00, 0x07, 0xec, 0xe8, 0xeb, 0xde, 0xfa, 0x3d, 0xf1, + 0xf5, 0xee, 0x0b, 0x4b, 0x3d, 0x00, 0x00, 0xe9, 0xe8, 0x2f, 0xfb, 0xf1, 0xf4, 0xea, 0xef, 0x1b, 0xfb, 0xe8, 0x2b, + 0x00, 0xf4, 0xf4, 0xf3, 0xef, 0x01, 0xe8, 0xf3, 0xf0, 0xea, 0x13, 0xf4, 0xfd, 0xf6, 0xf4, 0xf2, 0xf4, 0xe8, 0x44, + 0x16, 0xe4, 0xf2, 0x31, 0xea, 0xf3, 0xf9, 0xfb, 0xef, 0xeb, 0xec, 0xeb, 0x00, 0x43, 0x4c, 0xfa, 0x03, 0x00, 0xe8, + 0x33, 0x09, 0xef, 0xea, 0xf0, 0x44, 0xef, 0xec, 0xe8, 0x02, 0x66, 0x17, 0xfb, 0xee, 0xe1, 0xe8, 0xef, 0xfa, 0xef, + 0xe8, 0xfb, 0xf9, 0xf6, 0xef, 0xeb, 0x3d, 0x2e, 0x04, 0x00, 0xef, 0xed, 0xf1, 0xe8, 0x2a, 0xf1, 0xec, 0xe3, 0xf2, + 0x44, 0x16, 0xf3, 0xf0, 0xea, 0x2b, 0x2f, 0xe2, 0xd5, 0x2d, 0x05, 0xfc, 0xff, 0xf2, 0xed, 0xf9, 0x44, 0xf5, 0xef, + 0xf4, 0x6b, 0x06, 0x00, 0x00, 0xfa, 0xf6, 0xe8, 0xed, 0xef, 0xf1, 0xeb, 0xee, 0xeb, 0xf4, 0xe5, 0xf4, 0x4b, 0xf7, + 0xfa, 0xd7, 0xe5, 0x11, 0x0a, 0xf4, 0xea, 0xed, 0xef, 0x4b, 0xf1, 0xe3, 0xf2, 0x41, 0x38, 0x03, 0x38, 0xf5, 0xf4, + 0xf0, 0xe0, 0xf4, 0xe8, 0xcf, 0x1f, 0x22, 0xf9, 0xfb, 0xfb, 0xef, 0x0f, 0x8f, 0x17, 0xdd, 0xe1, 0xef, 0xf4, 0x0c, + 0x24, 0xed, 0xee, 0xe9, 0xee, 0x22, 0xe8, 0x00, 0x61, 0x00, 0xfe, 0xf1, 0xeb, 0x07, 0xea, 0xef, 0xec, 0xea, 0xef, + 0x27, 0xef, 0xf5, 0xe5, 0xf8, 0x57, 0xf5, 0xee, 0xf0, 0xf6, 0xf2, 0xee, 0xf9, 0x33, 0xfd, 0xf5, 0xef, 0xef, 0xe5, + 0xea, 0x49, 0x2c, 0xf5, 0xf9, 0xf7, 0xf3, 0xf4, 0xfc, 0x24, 0xe8, 0xe8, 0xf3, 0x4c, 0xf8, 0xed, 0xec, 0x0c, 0x83, + 0x0a, 0xe1, 0xd9, 0xec, 0xef, 0xf5, 0xf4, 0xfa, 0xde, 0xf9, 0xf4, 0xf4, 0xef, 0xef, 0x53, 0x3a, 0x2e, 0xf3, 0xef, + 0xef, 0xfa, 0xe5, 0xe3, 0x1b, 0x0c, 0xf1, 0xf2, 0xe4, 0x17, 0x43, 0xeb, 0x4d, 0x00, 0xe0, 0xe3, 0xf0, 0x3a, 0xf9, + 0xf6, 0xfe, 0xf6, 0xf4, 0xee, 0x45, 0xe9, 0x20, 0x1e, 0xff, 0xf6, 0xfc, 0xf6, 0xf4, 0xfe, 0xd9, 0xe7, 0xe6, 0xf4, + 0xff, 0xf4, 0xf0, 0xec, 0xe8, 0x49, 0xf9, 0xef, 0xd8, 0xf2, 0xf4, 0xf4, 0x1a, 0xfe, 0xe1, 0x00, 0x00, 0x11, 0xfd, + 0xf2, 0x00, 0x9b, 0x21, 0xf4, 0xe8, 0x07, 0x2a, 0xf9, 0xe2, 0xe8, 0xeb, 0xe9, 0x40, 0xf8, 0xf6, 0xfe, 0xf4, 0xec, + 0x4a, 0x24, 0x25, 0xee, 0xf2, 0xf1, 0xf4, 0xf4, 0xec, 0x31, 0x00, 0xef, 0xe3, 0xe8, 0x5e, 0x0a, 0xf4, 0xf4, 0xf4, + 0xef, 0xe5, 0xf9, 0xe0, 0xe8, 0xf3, 0xfa, 0xfa, 0xf2, 0x2b, 0xe4, 0x3f, 0xfd, 0xf7, 0xef, 0xf6, 0xf8, 0xf5, 0xf8, + 0xef, 0xea, 0xe8, 0x0f, 0x2b, 0xf4, 0xe8, 0xea, 0x27, 0x83, 0xf9, 0xf6, 0xf8, 0xfb, 0xf2, 0xf6, 0xdf, 0x4b, 0xec, + 0xeb, 0xe9, 0x34, 0x04, 0xef, 0xed, 0x30, 0x4e, 0xfb, 0xe6, 0xf1, 0xef, 0xf2, 0xf3, 0xf6, 0xf5, 0xee, 0xf4, 0xeb, + 0xf1, 0xf7, 0x48, 0xfb, 0xf0, 0x12, 0x1e, 0xd9, 0xe1, 0xfa, 0xe8, 0xf2, 0xef, 0xfb, 0x3c, 0xef, 0xe6, 0x2c, 0x2b, + 0x18, 0x28, 0xe4, 0xe9, 0xe9, 0x2a, 0x04, 0xf0, 0xf4, 0xfd, 0xf4, 0xf2, 0xee, 0x23, 0x33, 0x49, 0x00, 0x00, 0x00, + 0x00, 0xfb, 0xf3, 0x00, 0xe3, 0xed, 0xf4, 0xf6, 0xf4, 0xec, 0xed, 0xf1, 0xe5, 0xe1, 0x24, 0x0d, 0xf4, 0xf3, 0xf4, + 0xef, 0xf2, 0x26, 0xf7, 0xdc, 0xef, 0x21, 0x0c, 0xf7, 0x4e, 0x32, 0xf7, 0xf3, 0xe3, 0xe3, 0xed, 0x27, 0x0a, 0xea, + 0xf3, 0x22, 0x11, 0xf2, 0x26, 0x28, 0xee, 0x06, 0xe5, 0xf4, 0x54, 0xf4, 0xe1, 0xef, 0xf3, 0xf4, 0xf0, 0xef, 0xfb, + 0x38, 0xe9, 0x05, 0x70, 0x01, 0x00, 0x00, 0xf0, 0xf2, 0xde, 0xfe, 0xee, 0xf5, 0xf3, 0xef, 0xf0, 0xee, 0xf4, 0x25, + 0xec, 0xe3, 0x13, 0x2c, 0xf9, 0xf9, 0xf8, 0xf7, 0xf8, 0xed, 0xef, 0xf9, 0xea, 0x18, 0x0a, 0xfd, 0x50, 0x11, 0xf5, + 0xea, 0xee, 0xf5, 0xf4, 0x00, 0xe0, 0x27, 0x2b, 0xea, 0xcd, 0x44, 0x55, 0xe1, 0x29, 0x1d, 0xe1, 0xea, 0xef, 0xf8, + 0xf0, 0xef, 0xf4, 0xf6, 0xf3, 0xe3, 0xfe, 0xfd, 0xef, 0x5a, 0x1e, 0xf6, 0xf4, 0xf4, 0x11, 0x07, 0xec, 0x00, 0xed, + 0xed, 0xf3, 0xed, 0xea, 0xfe, 0x1b, 0xe7, 0xfe, 0x13, 0xf9, 0x6f, 0x00, 0x06, 0x1d, 0xf6, 0xf9, 0xf6, 0xfb, 0xf1, + 0xef, 0xef, 0xf2, 0x79, 0x12, 0x00, 0xdd, 0xed, 0xf6, 0xfe, 0xf9, 0xfd, 0xec, 0xfb, 0xf5, 0xf4, 0xfa, 0x3f, 0xe8, + 0xf4, 0xfc, 0xd1, 0xe8, 0xef, 0xf1, 0xf4, 0xf2, 0xf3, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x6d, 0x3d, 0xf9, + 0xf1, 0xec, 0xea, 0xf7, 0xfe, 0x00, 0xdd, 0x27, 0x0c, 0x28, 0xe9, 0xfb, 0xf4, 0xf5, 0x09, 0xdc, 0xfd, 0x46, 0x31, + 0x13, 0xf7, 0xef, 0xed, 0xfb, 0xef, 0xe8, 0xea, 0xe8, 0x17, 0x51, 0x05, 0x0c, 0x02, 0xf2, 0xef, 0xef, 0xdd, 0x06, + 0xf3, 0xfb, 0xef, 0xea, 0x44, 0xed, 0xf1, 0x03, 0x2b, 0xe9, 0xe3, 0xe5, 0xf9, 0xfa, 0xf9, 0xf1, 0xf2, 0xf6, 0xfe, + 0xfb, 0xf4, 0xf2, 0x15, 0x85, 0x42, 0xe1, 0xef, 0xf3, 0xf9, 0x00, 0xf4, 0x00, 0xe1, 0xee, 0x45, 0xec, 0xe6, 0x0e, + 0x14, 0x0c, 0x24, 0xdc, 0xf4, 0x4d, 0xf6, 0xf9, 0xf7, 0xf6, 0xf9, 0xf1, 0xec, 0xe1, 0xec, 0xf5, 0xfb, 0x3c, 0xf4, + 0xf2, 0xef, 0xfb, 0xf1, 0x19, 0x0c, 0x0b, 0xe9, 0xea, 0xe5, 0x38, 0xf8, 0xea, 0xe8, 0x40, 0xef, 0xee, 0x18, 0xe9, + 0xe9, 0x84, 0xee, 0xef, 0x00, 0xfc, 0xfd, 0xf6, 0xf0, 0xef, 0x68, 0x2a, 0x00, 0x00, 0x00, 0xfa, 0xf6, 0xf4, 0xf9, + 0x05, 0xe8, 0xf4, 0xea, 0xfd, 0xf4, 0xf1, 0xee, 0xfb, 0xdb, 0xd7, 0xed, 0x4f, 0xf4, 0xf4, 0xf4, 0xf1, 0xf0, 0xe9, + 0xfa, 0x15, 0xf1, 0x0b, 0x18, 0x63, 0x07, 0xf0, 0xf4, 0xf5, 0xf5, 0xf4, 0xf8, 0x08, 0xee, 0xda, 0x65, 0x61, 0xed, + 0xf2, 0xfd, 0x05, 0xec, 0xef, 0xef, 0xfb, 0xfa, 0x46, 0xf3, 0x00, 0x00, 0xe4, 0xee, 0xeb, 0xe8, 0x10, 0x53, 0xf2, + 0x35, 0xf6, 0x1e, 0x00, 0xf0, 0xf2, 0xe6, 0x00, 0xe9, 0xeb, 0xf1, 0xf1, 0xf0, 0xef, 0x00, 0xee, 0xf9, 0x11, 0xea, + 0x4e, 0xf1, 0xf0, 0xf4, 0xff, 0xf5, 0xe7, 0xe5, 0x00, 0xf9, 0xe6, 0x00, 0x54, 0x0d, 0x2b, 0xf7, 0xf6, 0xf8, 0xf7, + 0xf8, 0x06, 0xd6, 0x05, 0x77, 0x04, 0xe4, 0x04, 0x49, 0x12, 0xe7, 0xef, 0xf4, 0xf6, 0xf4, 0xf9, 0x00, 0xf8, 0xf7, + 0xf3, 0xf4, 0xea, 0xd8, 0x5b, 0x11, 0xfb, 0xf9, 0xfb, 0xf5, 0xff, 0xf6, 0xe9, 0x26, 0x13, 0xe9, 0xec, 0xdc, 0xec, + 0xed, 0xef, 0xfd, 0xdf, 0x00, 0x11, 0xfd, 0x58, 0x23, 0x22, 0xe4, 0x3a, 0xf3, 0xe8, 0xfc, 0xfa, 0xed, 0xea, 0x0f, + 0x33, 0x46, 0xf4, 0xf9, 0xf9, 0xf1, 0xe0, 0xf7, 0x00, 0xf9, 0x3f, 0xf4, 0xfd, 0xef, 0xf9, 0xf4, 0xe8, 0xef, 0xde, + 0xf3, 0xea, 0xf7, 0xf8, 0xf2, 0xef, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x60, 0x51, 0x22, 0xec, 0xf7, 0xfa, 0xf0, 0xef, + 0xf1, 0xf4, 0x09, 0xe8, 0x00, 0x2e, 0xe4, 0xde, 0x4f, 0xeb, 0xef, 0xfb, 0xed, 0xe9, 0x3d, 0x0f, 0x48, 0x08, 0xf1, + 0xed, 0xef, 0xe8, 0xde, 0xee, 0xed, 0x2e, 0x0c, 0xef, 0x05, 0x29, 0x1e, 0xf4, 0xf1, 0xe0, 0x00, 0x44, 0xf2, 0xef, + 0xef, 0xed, 0x10, 0xef, 0xea, 0xe4, 0x11, 0x0c, 0xf6, 0xfe, 0xea, 0xec, 0xf1, 0xfc, 0xea, 0xef, 0xf2, 0x35, 0x30, + 0x00, 0x46, 0xf4, 0xda, 0xf9, 0x35, 0xf3, 0xf2, 0xf2, 0x04, 0xea, 0xe8, 0x05, 0x33, 0xe5, 0x01, 0x68, 0xfd, 0xe5, + 0xe4, 0xec, 0x25, 0x2b, 0xf9, 0xf2, 0xec, 0xed, 0xf4, 0xef, 0xee, 0xdf, 0xf1, 0x3f, 0xfd, 0xfa, 0xfa, 0xfb, 0xfc, + 0xf1, 0xe3, 0xef, 0x9e, 0xf6, 0xed, 0xec, 0xe1, 0xf9, 0xf6, 0xe5, 0xe8, 0xe8, 0xe9, 0x12, 0x43, 0x45, 0xf8, 0xe6, + 0xe7, 0xfb, 0x33, 0xef, 0xf2, 0x74, 0x03, 0xfb, 0xef, 0x2a, 0x00, 0x00, 0x00, 0xf8, 0xf1, 0xe8, 0x00, 0xec, 0xf5, + 0xf3, 0xf4, 0x00, 0xeb, 0xef, 0xf3, 0xef, 0xdc, 0xe5, 0x11, 0x33, 0xea, 0xf2, 0xec, 0xf2, 0xed, 0x00, 0x00, 0x00, + 0x00, 0xb8, 0xf8, 0xf7, 0xed, 0xee, 0xea, 0xde, 0xf2, 0x52, 0x16, 0xe8, 0x36, 0xfa, 0xe8, 0xfc, 0xe2, 0xfc, 0x2e, + 0xf8, 0x00, 0xfb, 0xf9, 0xeb, 0x15, 0x31, 0xf3, 0xeb, 0xf3, 0xe8, 0x16, 0x50, 0xf9, 0xf4, 0xf4, 0xed, 0xe9, 0x07, + 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x04, + 0x00, 0x40, 0x00, 0x1e, 0x00, 0x01, 0x00, 0x1e, 0x00, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, + 0x3c, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x0a, 0x00, 0x28, 0x00, 0x1e, 0x00, 0x18, 0x00, 0x32, 0x00, + 0x20, 0x00, 0x3c, 0x00, 0x20, 0x00, 0x46, 0x00, 0x20, 0x00, 0x50, 0x00, 0x20, 0x00, 0x5a, 0x00, 0x20, 0x00, 0x64, + 0x00, 0x20, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x78, 0x00, 0x20, 0x00, 0x82, 0x00, 0x20, 0x00, 0x03, 0x06, 0x01, 0x01, + 0x01, 0x02, 0x03, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x07, 0x00, 0x00, + 0x70, 0x03, 0x00, 0x00, 0x86, 0x04, 0x00, 0x00, 0x40, 0x00, 0x02, 0x80, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x05, + 0x03, 0x05, 0x02, 0xe8, 0x22, 0xe2, 0xf7, 0xfd, 0xfb, 0xfb, 0xfd, 0xf9, 0x6b, 0xd3, 0xef, 0xfe, 0x02, 0x05, 0x03, + 0x09, 0xa6, 0x3d, 0x0e, 0x08, 0x0a, 0x07, 0x08, 0x0e, 0x44, 0xfe, 0x05, 0x0a, 0x04, 0x00, 0x05, 0x06, 0x8b, 0x33, + 0x01, 0xfb, 0xfb, 0xfb, 0xf8, 0xf4, 0xd8, 0xf9, 0xfd, 0xfb, 0xf4, 0x07, 0x07, 0x05, 0x0d, 0x22, 0xf4, 0x03, 0x02, + 0x05, 0x05, 0x03, 0xe5, 0xff, 0x11, 0x01, 0x04, 0xeb, 0xfa, 0xf6, 0x10, 0x8a, 0xb4, 0xf5, 0xf9, 0xf8, 0xf9, 0xf4, + 0xd0, 0xd8, 0x1e, 0xfe, 0xfe, 0xff, 0x00, 0x0f, 0x08, 0x4a, 0xe5, 0x08, 0x09, 0x06, 0x0a, 0x0a, 0x09, 0xfe, 0x0d, + 0x0a, 0xec, 0xfd, 0xfd, 0xfe, 0xfb, 0xdf, 0x0d, 0xf9, 0xfd, 0xf9, 0xfb, 0xfb, 0xfd, 0xca, 0x11, 0x0d, 0x0e, 0x01, + 0x02, 0x00, 0x00, 0x83, 0xcf, 0x03, 0x04, 0x06, 0x07, 0x07, 0x06, 0xe6, 0x0b, 0xfb, 0xf5, 0xf6, 0xf9, 0xf6, 0xf9, + 0x07, 0xf4, 0xf6, 0xf6, 0xfa, 0xf6, 0xf4, 0x07, 0x80, 0x29, 0x05, 0xf9, 0x00, 0x05, 0x02, 0x03, 0x57, 0x21, 0xe6, + 0x08, 0x07, 0x0d, 0x05, 0x08, 0x80, 0x23, 0x05, 0xf9, 0xf8, 0xfb, 0xf9, 0xfe, 0x1d, 0x0d, 0xea, 0xfa, 0xfc, 0xfa, + 0xfc, 0xfb, 0x0f, 0x1b, 0xfe, 0x05, 0x09, 0x08, 0x09, 0x08, 0x17, 0x23, 0xfb, 0x05, 0xfd, 0x02, 0x01, 0x04, 0x00, + 0x3e, 0x53, 0xfb, 0xfa, 0xf4, 0xf8, 0xf6, 0xf2, 0xc9, 0x90, 0xef, 0xf8, 0xfb, 0xfe, 0x07, 0x08, 0xd0, 0x1e, 0x05, + 0x05, 0x00, 0x06, 0x05, 0x05, 0xad, 0x32, 0x05, 0x05, 0x00, 0x00, 0xf4, 0xf6, 0x6b, 0xc6, 0xf6, 0xfc, 0x00, 0xfa, + 0xfc, 0x00, 0x9f, 0x06, 0x01, 0xf9, 0x00, 0x04, 0x08, 0x07, 0x0a, 0x05, 0x07, 0x03, 0x0a, 0x08, 0x07, 0x07, 0x55, + 0xec, 0xf6, 0x02, 0x03, 0x05, 0x03, 0x04, 0x1f, 0x16, 0xe7, 0xfb, 0xfd, 0xfc, 0xfa, 0xf9, 0x8d, 0x24, 0x05, 0xf6, + 0x27, 0x0b, 0x60, 0x45, 0x37, 0x03, 0x2a, 0xf9, 0xd1, 0x8d, 0xbb, 0xf5, 0x30, 0x02, 0x30, 0x75, 0x68, 0x16, 0xd4, + 0xe6, 0x9f, 0xe3, 0x6b, 0x1e, 0xa1, 0x0a, 0xf4, 0x56, 0x05, 0x0a, 0x01, 0x18, 0x08, 0xf3, 0xef, 0xd6, 0xef, 0xee, + 0xd8, 0x70, 0xe4, 0x1f, 0x77, 0x79, 0x41, 0x98, 0x36, 0x3f, 0x0f, 0xb3, 0xe7, 0x39, 0xd0, 0x8e, 0x2f, 0x03, 0x16, + 0x95, 0xcc, 0xb3, 0x0f, 0xf8, 0x00, 0x7a, 0xa0, 0xa4, 0x92, 0xc2, 0xec, 0xf4, 0xef, 0x07, 0x46, 0x8f, 0x17, 0x39, + 0x26, 0x46, 0x29, 0xb3, 0xcf, 0x95, 0x4f, 0x1e, 0x92, 0x10, 0x23, 0x1f, 0x21, 0x1e, 0x5e, 0x7a, 0xf3, 0x3f, 0xa9, + 0xdd, 0x87, 0x45, 0x1e, 0x40, 0x0a, 0x0f, 0xd1, 0x13, 0x0f, 0xf2, 0xf1, 0x0c, 0xd1, 0x5e, 0xcf, 0xa9, 0x56, 0xf4, + 0x48, 0x87, 0x1d, 0x70, 0x75, 0x34, 0x3a, 0xce, 0x22, 0xd9, 0x7c, 0xc4, 0xc2, 0xba, 0x1c, 0x28, 0x55, 0xb2, 0x03, + 0xd3, 0x2c, 0xf2, 0xda, 0x3c, 0x2b, 0xba, 0x07, 0x62, 0xaf, 0xf7, 0xf4, 0x04, 0xf7, 0x00, 0xf3, 0x5c, 0x25, 0xcf, + 0x14, 0xd3, 0x55, 0xec, 0xf4, 0xce, 0xf5, 0xcc, 0x67, 0x7b, 0xe8, 0x7c, 0xe7, 0x02, 0x30, 0xe7, 0x0d, 0xa5, 0x3f, + 0x23, 0xa5, 0x15, 0xf8, 0x41, 0xb7, 0xd3, 0xc0, 0xac, 0x10, 0xa8, 0x37, 0x0a, 0xf4, 0x1e, 0xee, 0x2d, 0xc6, 0xef, + 0xc1, 0x56, 0xd9, 0xec, 0xf4, 0x08, 0x35, 0xd5, 0x16, 0x50, 0x01, 0xf3, 0x5d, 0x58, 0x37, 0x5c, 0x74, 0xf6, 0xcc, + 0x1e, 0x04, 0xa7, 0x70, 0x14, 0x42, 0xfd, 0x11, 0xc0, 0xd4, 0x0f, 0x3d, 0xb4, 0xe2, 0xb7, 0x6c, 0xde, 0xee, 0x34, + 0x18, 0x4f, 0x76, 0x28, 0xde, 0x2d, 0xfb, 0xbc, 0x74, 0xb7, 0xda, 0xf3, 0x1c, 0x19, 0x11, 0x17, 0x19, 0x00, 0xfc, + 0x49, 0x4f, 0x1a, 0xf8, 0x60, 0xd7, 0x82, 0x79, 0xe0, 0xbc, 0x2f, 0x0b, 0xf0, 0xc0, 0xb9, 0x8d, 0x02, 0x2d, 0x4b, + 0x8b, 0x1e, 0x14, 0xd5, 0x38, 0x41, 0x8e, 0x30, 0xe9, 0x8e, 0xbb, 0xe0, 0xdc, 0x0b, 0x3e, 0xbd, 0xd0, 0xcb, 0xd4, + 0xa3, 0xa7, 0x47, 0x26, 0x1e, 0xfa, 0x06, 0xe4, 0x08, 0xfa, 0xfb, 0x03, 0xf4, 0xdc, 0x14, 0xfc, 0xff, 0xc6, 0x10, + 0xfb, 0xf8, 0x51, 0xcf, 0xfc, 0x02, 0x58, 0xd8, 0xfb, 0xfe, 0xe9, 0x9b, 0x3a, 0x03, 0x05, 0x5d, 0xd3, 0xff, 0x06, + 0x50, 0xdc, 0x05, 0x08, 0x61, 0x4a, 0x02, 0xf9, 0x48, 0xd6, 0xf6, 0xff, 0xfb, 0xc2, 0x19, 0xfd, 0xfe, 0x0d, 0xf1, + 0xff, 0xfe, 0x34, 0xe3, 0xff, 0x00, 0x03, 0xfe, 0x07, 0x03, 0xfa, 0x08, 0x05, 0x03, 0x00, 0x4b, 0xe4, 0x05, 0x08, + 0x55, 0x5b, 0x0a, 0x00, 0x78, 0xbf, 0xfb, 0x00, 0x26, 0xec, 0xff, 0xfc, 0x00, 0xff, 0x00, 0xfe, 0x00, 0x05, 0xf8, + 0x00, 0x01, 0xb9, 0x1c, 0x04, 0x06, 0xa7, 0x2b, 0x06, 0x00, 0x25, 0xf8, 0xfc, 0x02, 0x19, 0x06, 0xfb, 0x00, 0x04, + 0x53, 0xd3, 0xfe, 0x04, 0xb8, 0x25, 0x03, 0xfe, 0xb4, 0x11, 0x05, 0xfe, 0x56, 0x04, 0xe3, 0xfa, 0x00, 0xfe, 0xfe, + 0xfb, 0xff, 0x94, 0x2d, 0x00, 0x03, 0x28, 0xee, 0xfe, 0x00, 0xd5, 0x05, 0x0b, 0x00, 0x0e, 0x05, 0xfb, 0x05, 0x03, + 0x0c, 0xfb, 0x03, 0x02, 0xf2, 0xff, 0x00, 0xfb, 0xfe, 0xfe, 0xfb, 0xfd, 0x03, 0x00, 0xfa, 0xfc, 0xf6, 0xe6, 0x0a, + 0x01, 0xff, 0xdf, 0x10, 0x00, 0x02, 0x32, 0xf2, 0x00, 0x02, 0x17, 0x09, 0xfb, 0x08, 0x08, 0x12, 0xfc, 0x06, 0x02, + 0xd1, 0x22, 0x01, 0x07, 0xdb, 0x14, 0xfb, 0xff, 0x4f, 0xd5, 0x00, 0xfe, 0xf2, 0xf1, 0x0a, 0xfe, 0x02, 0xef, 0x05, + 0x00, 0xfe, 0x11, 0xf4, 0xfd, 0x07, 0x61, 0xd5, 0x04, 0x05, 0x69, 0x51, 0x0a, 0x02, 0x0b, 0x5a, 0xd3, 0x05, 0x03, + 0x2b, 0xed, 0xfc, 0x05, 0x6e, 0x49, 0x05, 0xfb, 0x74, 0xc8, 0xf8, 0x01, 0x9d, 0x2b, 0x05, 0xf7, 0x04, 0x44, 0xd5, + 0xfe, 0xfb, 0xb2, 0x21, 0x00, 0x00, 0x3c, 0xe2, 0x00, 0x00, 0x0a, 0xfd, 0x00, 0x01, 0xb6, 0x1a, 0x07, 0x00, 0x00, + 0x53, 0xd6, 0x00, 0x05, 0xaa, 0x28, 0x00, 0xf8, 0x5d, 0xcf, 0xf8, 0xfe, 0x00, 0xff, 0xfe, 0xfd, 0xcb, 0xfe, 0x0a, + 0xfd, 0xfb, 0x19, 0xf2, 0xff, 0xfe, 0x1b, 0xf4, 0x03, 0x04, 0x26, 0xf1, 0x02, 0x06, 0x1e, 0x00, 0x23, 0x3c, 0x5f, + 0x0b, 0x00, 0x00, 0x05, 0x00, 0x04, 0xf9, 0x00, 0xfe, 0xff, 0x00, 0xfe, 0x02, 0xf9, 0x00, 0xfe, 0x02, 0x00, 0xfd, + 0x01, 0xfd, 0x02, 0x00, 0xfe, 0x00, 0xfe, 0xfd, 0x02, 0x03, 0x9f, 0xb6, 0x00, 0x05, 0x03, 0x02, 0x05, 0x00, 0x06, + 0x00, 0x07, 0x02, 0x00, 0x06, 0x00, 0x03, 0x04, 0x00, 0x05, 0x00, 0x01, 0x02, 0x00, 0x03, 0x04, 0xfe, 0x03, 0xff, + 0xfc, 0x02, 0x58, 0x4d, 0x03, 0xfb, 0xf9, 0xfb, 0xfc, 0xfb, 0xfb, 0xfb, 0xfb, 0xf7, 0xfd, 0xfb, 0xfb, 0xfb, 0x00, + 0xfa, 0xfe, 0xfb, 0xfe, 0x00, 0xfd, 0x00, 0xff, 0xfe, 0xfe, 0x02, 0x00, 0xfe, 0x04, 0x99, 0xb4, 0xfe, 0x04, 0x03, + 0x05, 0x03, 0x04, 0x03, 0x05, 0x03, 0x03, 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, + 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x6f, 0x42, 0x03, 0xfb, 0xfb, 0xfb, 0xfa, 0xfd, 0xfb, 0xfc, 0xfb, 0xfb, 0xfd, + 0xfb, 0xff, 0xfe, 0x02, 0xfb, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x04, 0x89, + 0xbc, 0xfe, 0x05, 0x05, 0x03, 0x05, 0x04, 0x03, 0x05, 0x03, 0x02, 0x03, 0x02, 0x01, 0x02, 0x03, 0x02, 0x02, 0x01, + 0x02, 0x02, 0x01, 0xff, 0xfe, 0xfe, 0x02, 0xfe, 0xff, 0x01, 0x7c, 0x3c, 0x05, 0xf9, 0xfd, 0xfb, 0xfb, 0xfd, 0xfc, + 0xfd, 0xfb, 0xfd, 0x00, 0xfe, 0xfd, 0xfe, 0x02, 0xfd, 0x00, 0xfe, 0xfe, 0x02, 0xfe, 0x00, 0x00, 0x04, 0x00, 0x01, + 0x02, 0x00, 0x03, 0x7c, 0xc4, 0xff, 0x05, 0x05, 0x01, 0x05, 0x04, 0x05, 0x03, 0x00, 0x02, 0x03, 0xfe, 0x02, 0x00, + 0x01, 0x04, 0xfc, 0x04, 0x01, 0xff, 0x01, 0xff, 0x01, 0x02, 0xfd, 0xfe, 0x00, 0x00, 0x8d, 0x34, 0x04, 0xfc, 0xfa, + 0xfd, 0xfc, 0xfb, 0x05, 0xfd, 0xfe, 0x00, 0xfd, 0x00, 0x00, 0xfe, 0xff, 0x00, 0xfe, 0x02, 0xfe, 0xfe, 0x04, 0xfc, + 0x02, 0x05, 0xfd, 0x00, 0x00, 0x00, 0x05, 0x70, 0xc9, 0x00, 0x02, 0x03, 0x02, 0xfe, 0x04, 0x03, 0xfd, 0x03, 0x02, + 0xfe, 0x03, 0x02, 0xfe, 0x04, 0xfc, 0xf6, 0x0f, 0x00, 0xff, 0x01, 0x00, 0xfa, 0xe7, 0x10, 0xff, 0x00, 0x15, 0xf6, + 0xfb, 0x05, 0xfd, 0xc6, 0x20, 0x00, 0x01, 0x14, 0xfd, 0xfb, 0x01, 0xfd, 0x11, 0xf9, 0x00, 0x00, 0x9d, 0x33, 0x02, + 0x00, 0x01, 0x1e, 0xee, 0x00, 0x00, 0x0a, 0xfb, 0x02, 0xfc, 0xfd, 0x6d, 0xc8, 0xfb, 0x06, 0x83, 0x3d, 0x05, 0xfe, + 0xf3, 0xec, 0x0a, 0xfd, 0xfe, 0x58, 0xd5, 0xf9, 0x00, 0x04, 0x10, 0xf8, 0x00, 0x03, 0x8d, 0x38, 0x05, 0x01, 0x3c, + 0x1d, 0xe6, 0x03, 0x04, 0x17, 0xf6, 0x00, 0x05, 0xfc, 0xf3, 0x09, 0x04, 0xff, 0xa7, 0x22, 0x09, 0xfc, 0x16, 0xfc, + 0xfc, 0x00, 0x01, 0xf5, 0x05, 0x05, 0xfe, 0x0d, 0x11, 0xf2, 0xff, 0x01, 0x95, 0x33, 0x04, 0xfc, 0xdf, 0x09, 0x00, + 0xfb, 0xfc, 0xc8, 0x9a, 0xf4, 0x02, 0xb1, 0xed, 0x1b, 0xfc, 0xfd, 0xf3, 0x05, 0x00, 0xfe, 0x56, 0xd4, 0xfc, 0x02, + 0x0b, 0x37, 0xe4, 0x01, 0x04, 0xb1, 0x17, 0x0f, 0xfe, 0xfe, 0x33, 0xe9, 0x00, 0x04, 0x24, 0x19, 0xf2, 0x02, 0xf9, + 0xe4, 0x13, 0x01, 0x00, 0x3c, 0xe7, 0xfe, 0x04, 0xfe, 0x9f, 0x2f, 0x00, 0x00, 0xee, 0xff, 0x05, 0xfb, 0xea, 0xf1, + 0x0a, 0xfd, 0x00, 0xfe, 0xfb, 0xff, 0x00, 0x0a, 0x52, 0xd3, 0xfd, 0x00, 0xbd, 0x12, 0x06, 0xff, 0xdd, 0x02, 0x06, + 0x02, 0xfe, 0xfd, 0x03, 0x02, 0x03, 0x1c, 0x51, 0xd8, 0xff, 0x05, 0xd5, 0x15, 0x09, 0x01, 0x02, 0x0d, 0xfb, 0x03, + 0x04, 0xe7, 0x10, 0x04, 0x03, 0x29, 0x11, 0xf1, 0x05, 0x05, 0x8e, 0x3a, 0x03, 0x00, 0xfd, 0xf6, 0x06, 0xfc, 0x03, + 0x26, 0xe9, 0x01, 0xfd, 0xf6, 0x03, 0xff, 0xfe, 0x02, 0x03, 0xfe, 0x02, 0x00, 0x21, 0x29, 0xe6, 0x00, 0xf6, 0xd2, + 0x1a, 0x00, 0x00, 0x19, 0xf9, 0xfd, 0x05, 0x00, 0xb9, 0x28, 0x00, 0x01, 0x02, 0x03, 0xfd, 0x02, 0x00, 0xf7, 0x0a, + 0xfd, 0x00, 0x6a, 0xd0, 0xfb, 0x01, 0x04, 0x0a, 0xf9, 0x02, 0x00, 0x7f, 0x17, 0x16, 0xf9, 0xf6, 0x90, 0xc7, 0xf9, + 0x05, 0x41, 0x5d, 0x07, 0xf9, 0x05, 0x14, 0xef, 0xfd, 0xfd, 0xf4, 0x03, 0x02, 0x00, 0x70, 0xea, 0xf0, 0x02, 0x01, + 0x02, 0x05, 0xfe, 0x00, 0x00, 0x02, 0x01, 0xff, 0x01, 0x00, 0x05, 0xff, 0x00, 0x03, 0xfe, 0x05, 0xff, 0x03, 0xfe, + 0x03, 0xff, 0xfe, 0xfd, 0x00, 0xfe, 0xdc, 0x85, 0x40, 0xff, 0xfc, 0xfd, 0xfd, 0xfe, 0xfd, 0xf9, 0x00, 0xfd, 0xfe, + 0xff, 0xf9, 0x00, 0xfd, 0xfd, 0xfe, 0xfe, 0xff, 0xfe, 0xfb, 0x03, 0x00, 0xff, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x05, 0xff, 0x0d, 0xa0, 0xb2, 0x03, 0x00, 0x05, 0x03, 0x03, 0x02, 0x07, 0x01, 0x04, 0x03, 0x03, + 0x03, 0x04, 0x03, 0x02, 0x03, 0x01, 0x02, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfd, 0x00, 0xfe, 0x00, + 0x00, 0xfe, 0x00, 0xff, 0xfd, 0x95, 0x07, 0x13, 0xfb, 0xfd, 0xfb, 0xfb, 0xff, 0xfc, 0xfd, 0xfb, 0xfe, 0xff, 0xfc, + 0xfd, 0xff, 0xfe, 0x02, 0xfb, 0x05, 0xfb, 0x00, 0x00, 0xfe, 0x03, 0xfd, 0x00, 0x02, 0x00, 0x00, 0x03, 0xfe, 0x02, + 0x03, 0xff, 0x03, 0xfe, 0xfd, 0xae, 0xaa, 0xff, 0x03, 0x05, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, + 0xff, 0x03, 0x02, 0x00, 0x03, 0xfe, 0x03, 0x02, 0xfd, 0x03, 0x00, 0xfd, 0x03, 0x00, 0xfb, 0x02, 0xfd, 0xfe, 0x00, + 0xfe, 0xff, 0xfe, 0xf9, 0xe5, 0xa9, 0x2c, 0xfe, 0xfd, 0xfd, 0xfe, 0xfd, 0xfd, 0xfe, 0xfd, 0xfe, 0x00, 0xfd, 0x00, + 0xfe, 0xfd, 0x00, 0x00, 0xfc, 0x02, 0xfe, 0xff, 0x01, 0x02, 0xfe, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x02, 0x00, 0x79, 0xd4, 0xf8, 0x03, 0x05, 0x03, 0x03, 0x02, 0x03, 0x02, 0x00, 0x02, 0x03, 0x01, 0x00, + 0x02, 0x02, 0xfe, 0x03, 0x02, 0xfe, 0x02, 0x02, 0x00, 0xfc, 0x02, 0x00, 0xfd, 0x01, 0x00, 0xfd, 0x02, 0xfe, 0x00, + 0xfe, 0xff, 0xfe, 0xa9, 0x0a, 0x0f, 0xfd, 0xfb, 0x00, 0xfc, 0xfd, 0xfe, 0x00, 0xff, 0xfd, 0x01, 0xfd, 0xfe, 0x00, + 0xff, 0xfe, 0xfe, 0x00, 0x00, 0xff, 0x00, 0x01, 0xff, 0x00, 0x03, 0xfe, 0xff, 0x05, 0xfe, 0x00, 0x00, 0x02, 0x00, + 0xfe, 0x00, 0xfd, 0x4b, 0xc7, 0x3b, 0xe7, 0x02, 0xd8, 0x2d, 0xd3, 0x05, 0x26, 0xf0, 0x1d, 0xff, 0xda, 0x1c, 0xc0, + 0x53, 0x1e, 0xa9, 0x52, 0xf0, 0xae, 0x69, 0xe0, 0x09, 0xbe, 0x24, 0x17, 0xf5, 0xe4, 0x20, 0x07, 0xb5, 0x4d, 0xf9, + 0xe1, 0x4f, 0x9c, 0x15, 0x34, 0xdb, 0x21, 0xcb, 0x30, 0xbc, 0x1b, 0x55, 0xc3, 0x05, 0xd9, 0x48, 0xcd, 0x05, 0xd5, + 0x76, 0xba, 0xfd, 0xfb, 0xd7, 0x31, 0x0a, 0xf4, 0x1f, 0xbf, 0x2f, 0xc4, 0x73, 0xb1, 0x34, 0xd2, 0x26, 0xd1, 0xf7, + 0x00, 0x24, 0xed, 0x05, 0x01, 0xc9, 0x44, 0x09, 0xef, 0x14, 0xb1, 0x52, 0xd2, 0xf6, 0x21, 0xd9, 0x15, 0x05, 0xf3, + 0xf6, 0xf8, 0x55, 0xdf, 0xc5, 0x3a, 0xda, 0x02, 0x4d, 0x94, 0x31, 0x06, 0xf2, 0xd7, 0x4d, 0xee, 0xe2, 0x07, 0x05, + 0xe7, 0x1c, 0x22, 0xe8, 0xbc, 0x6e, 0xdf, 0xff, 0xfd, 0xda, 0xfe, 0x42, 0xd0, 0x05, 0xd4, 0x55, 0x91, 0x5d, 0x14, + 0xca, 0x13, 0xcc, 0x0d, 0x15, 0x04, 0x18, 0xba, 0x57, 0xcd, 0x0a, 0xd2, 0x41, 0x0a, 0xd2, 0x19, 0xf3, 0xec, 0x10, + 0x0f, 0x24, 0xc5, 0xfd, 0xeb, 0x2e, 0x10, 0xf1, 0xfd, 0x0d, 0xfe, 0xbf, 0x5a, 0xcf, 0xef, 0x17, 0x1e, 0xd7, 0x15, + 0xe4, 0x3f, 0xd5, 0xf4, 0x14, 0x0a, 0xe4, 0xe6, 0x21, 0xf9, 0x0f, 0xf8, 0xf6, 0x27, 0xcf, 0x39, 0xde, 0xd7, 0x3e, + 0xf8, 0xfe, 0xf3, 0x30, 0xc2, 0xf1, 0x3e, 0xc4, 0x18, 0xfd, 0xf9, 0x34, 0xcc, 0x14, 0xfd, 0x10, 0xcd, 0x17, 0x1c, + 0xeb, 0x1a, 0xdc, 0xf8, 0x27, 0xee, 0xe4, 0x0c, 0x31, 0xae, 0x49, 0xd8, 0x2d, 0xe5, 0xfe, 0x0a, 0xe6, 0x13, 0xf8, + 0x02, 0x1f, 0xd0, 0x04, 0x15, 0x02, 0xea, 0xf7, 0x23, 0xf5, 0x0b, 0x0a, 0xc9, 0x2f, 0x03, 0x07, 0xf0, 0xd0, 0x55, + 0xc7, 0x00, 0xf0, 0x10, 0x34, 0xee, 0xc9, 0x2a, 0x0f, 0xe1, 0xfd, 0xee, 0x44, 0xde, 0xe6, 0x1f, 0x0d, 0xec, 0xee, + 0x0f, 0xf3, 0x00, 0x18, 0xf3, 0x05, 0xf8, 0x33, 0xa8, 0x1b, 0xff, 0x0d, 0x06, 0xf6, 0x1b, 0xd2, 0x17, 0x18, 0xd3, + 0x2a, 0xcf, 0x3b, 0xf8, 0xe9, 0x17, 0xe4, 0xfe, 0x33, 0xb3, 0x50, 0xb7, 0x3a, 0xe1, 0xeb, 0x26, 0xdd, 0x19, 0x1c, + 0xd8, 0xff, 0x12, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x03, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x7f, 0x01, 0xff, 0x00, 0x01, 0x00, 0x80, 0x7f, 0x01, 0xff, 0x01, 0xff, 0x00, 0x01, 0xff, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00, 0xff, 0x01, 0x00, + 0xff, 0x01, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x01, 0x00, + 0x80, 0x7f, 0x01, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, + 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0xf5, 0x00, 0xff, 0xfe, + 0xfa, 0x00, 0xfd, 0xf2, 0xf7, 0xff, 0xfc, 0xfd, 0x34, 0x00, 0x0c, 0x0b, 0x08, 0x01, 0x05, 0x04, 0x03, 0x01, 0x00, + 0x02, 0x01, 0x04, 0x00, 0x01, 0x06, 0xc2, 0x00, 0xff, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xfa, 0xfd, + 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfe, 0xff, 0x00, 0x00, 0xfe, 0x20, 0x03, 0x01, 0x05, 0x0e, 0x13, 0x0a, 0x01, + 0x05, 0x06, 0x05, 0x00, 0x04, 0x05, 0x05, 0x00, 0x03, 0x03, 0x05, 0x01, 0x03, 0x03, 0x04, 0x01, 0x02, 0x00, 0x0e, + 0x01, 0x00, 0x03, 0x81, 0xfe, 0xff, 0x00, 0xfd, 0xfe, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xfd, 0xfb, 0xfd, 0x00, 0xfe, + 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x00, 0x00, 0x29, 0x03, 0x05, 0x00, 0x03, 0x05, 0x01, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x03, 0x05, 0x00, 0x05, + 0x05, 0x03, 0x04, 0x00, 0x03, 0x04, 0x03, 0x00, 0x01, 0x02, 0x03, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfd, 0xff, 0xfe, + 0xfd, 0xfe, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0xfd, 0xff, 0xff, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x07, 0x01, 0x02, + 0x01, 0x03, 0x01, 0x01, 0x03, 0x02, 0x04, 0x00, 0x02, 0x01, 0x04, 0x01, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x00, 0x03, 0x02, 0x03, 0x00, 0x01, 0x05, 0x03, 0x03, 0x01, 0x04, 0x03, 0x03, 0x01, 0x02, 0x03, 0x02, 0x01, 0x01, + 0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x9a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfa, 0xff, 0xfc, 0xfb, 0x00, 0xff, 0xff, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x02, 0x04, 0x07, + 0x01, 0x05, 0x08, 0x04, 0x01, 0x06, 0x06, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x00, 0x00, 0x01, 0x03, 0x01, 0x01, + 0x03, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01, 0x02, 0x01, 0x07, 0x01, 0x00, 0x05, 0x06, 0x03, 0x01, 0x02, 0x04, 0x01, + 0x00, 0x02, 0x06, 0x06, 0x00, 0x02, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfd, 0x00, 0xfe, 0xfd, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x13, 0xff, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x01, 0x03, 0x05, 0x05, 0x01, 0x05, 0x05, 0x03, 0x05, 0x00, 0x03, 0x01, 0x02, + 0x01, 0x02, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00, + 0x03, 0x02, 0x01, 0x00, 0x04, 0x01, 0x01, 0x04, 0x01, 0x00, 0x00, 0x04, 0x03, 0x01, 0x00, 0x00, 0x03, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, + 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xfe, 0xfd, 0xfd, 0xff, 0x00, 0xfb, + 0xfd, 0xff, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3d, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x04, 0x00, 0x26, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, + 0x15, 0x00, 0x02, 0x80, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x91, 0x95, 0x01, 0x81, 0x2a, 0xe5, 0x11, 0xfe, 0x89, 0x58, + 0x5a, 0x14, 0x01, 0xed, 0x26, 0x3f, 0x23, 0xb6, 0x30, 0xa0, 0x29, 0xc6, 0xc3, 0xbc, 0x2c, 0x1e, 0x07, 0x6e, 0x59, + 0xe6, 0xf8, 0xed, 0x57, 0x3a, 0xa1, 0xae, 0xbf, 0xce, 0x30, 0x02, 0xe3, 0xe8, 0x68, 0x16, 0xda, 0xc5, 0x06, 0x64, + 0xe0, 0xe1, 0xa9, 0x30, 0x28, 0x6b, 0xd1, 0xed, 0x2d, 0x22, 0x7e, 0x7c, 0x81, 0x03, 0xfe, 0xdb, 0x42, 0x12, 0x87, + 0x4a, 0x38, 0x7a, 0x1a, 0x92, 0xab, 0x74, 0x55, 0x52, 0x03, 0x2e, 0xab, 0x16, 0x49, 0x0c, 0xa4, 0x0f, 0x94, 0x84, + 0xba, 0x3e, 0x5e, 0x09, 0x45, 0xd7, 0x03, 0x22, 0x2f, 0xb6, 0x41, 0x30, 0xd8, 0xb5, 0xef, 0x07, 0xda, 0xb2, 0xec, + 0xc9, 0x32, 0x0a, 0x5c, 0x49, 0x4b, 0x70, 0x38, 0x40, 0xa0, 0xdc, 0x56, 0xa9, 0x62, 0x68, 0xe0, 0x99, 0xca, 0xf6, + 0x58, 0xda, 0x9b, 0x52, 0x42, 0x97, 0x6a, 0xc6, 0x67, 0x84, 0x2f, 0xd3, 0xe3, 0xa2, 0xc4, 0xec, 0xf7, 0x1d, 0xd3, + 0x01, 0xb2, 0x77, 0xcb, 0xa0, 0x91, 0x60, 0x5c, 0x98, 0x07, 0x89, 0x23, 0xc4, 0x2a, 0xaa, 0x04, 0xf6, 0x65, 0x37, + 0xc6, 0xbf, 0x55, 0xf3, 0x81, 0xd8, 0xfb, 0xb1, 0x77, 0x1b, 0x17, 0xa7, 0xd8, 0xc8, 0xf0, 0x98, 0x04, 0xdc, 0x8d, + 0x22, 0xee, 0x67, 0x56, 0x7c, 0x1d, 0x99, 0x52, 0x08, 0xd8, 0x5b, 0xf6, 0xf4, 0x1d, 0x58, 0x9e, 0x44, 0xef, 0x13, + 0xcd, 0x90, 0x75, 0x27, 0x2a, 0xd2, 0xa3, 0x33, 0x58, 0x82, 0xd7, 0x79, 0xc9, 0x57, 0x0b, 0xe0, 0x7f, 0x0b, 0x30, + 0x3c, 0xd8, 0x59, 0x38, 0xa7, 0x77, 0x9d, 0x5b, 0xb1, 0x5a, 0x51, 0x45, 0x47, 0x28, 0xce, 0x8a, 0x11, 0xd1, 0x7d, + 0x2c, 0x22, 0x80, 0xfa, 0x84, 0xd6, 0xf3, 0x54, 0x58, 0x7c, 0x68, 0xb8, 0x8a, 0xe6, 0xf8, 0xee, 0xf2, 0x6f, 0x98, + 0xf3, 0x13, 0x64, 0xca, 0xf0, 0xfe, 0xa6, 0x05, 0xe7, 0x3c, 0x48, 0xe1, 0x6e, 0x1b, 0xe4, 0x2f, 0xbd, 0xf8, 0xbe, + 0xe7, 0x65, 0x27, 0x28, 0x23, 0xfa, 0x00, 0x42, 0x18, 0x0c, 0x8a, 0xba, 0x35, 0xac, 0x89, 0x73, 0x64, 0xe0, 0x45, + 0xd6, 0x8e, 0x4b, 0xbc, 0xac, 0x59, 0x64, 0xc8, 0x36, 0x5f, 0x72, 0xd1, 0x6e, 0xb4, 0xbd, 0x7f, 0x3f, 0xf0, 0x39, + 0x1f, 0x65, 0xd3, 0xe6, 0x2f, 0xfe, 0x5f, 0x66, 0xb9, 0x50, 0xd0, 0xcc, 0xf9, 0xe6, 0x1f, 0x58, 0xe9, 0x91, 0x69, + 0x0d, 0x3a, 0x47, 0x34, 0xb4, 0x5f, 0x94, 0x93, 0x86, 0x14, 0x89, 0x47, 0xc6, 0x21, 0xdb, 0xf0, 0xa1, 0xc0, 0x22, + 0x58, 0xb0, 0x46, 0xe3, 0xe1, 0x58, 0xa5, 0x5a, 0x42, 0x59, 0x5a, 0xb6, 0x73, 0xff, 0x2d, 0xb6, 0x07, 0x0c, 0x9d, + 0x4c, 0xf5, 0xd8, 0x47, 0x42, 0xc8, 0xea, 0xf0, 0x9b, 0x6b, 0x50, 0xcc, 0x7e, 0x89, 0x14, 0x82, 0x81, 0x9d, 0x11, + 0x86, 0x22, 0xb6, 0x8d, 0x4e, 0x4b, 0x07, 0xcb, 0x05, 0x91, 0x5f, 0xf4, 0x3c, 0x20, 0x77, 0xb9, 0x30, 0x14, 0x47, + 0xda, 0x26, 0x0e, 0x6a, 0xf6, 0x96, 0xd9, 0x94, 0xfb, 0x7b, 0xed, 0x37, 0x77, 0x88, 0xa5, 0x61, 0x22, 0xb8, 0xf2, + 0xe9, 0xe8, 0xdb, 0x58, 0xf3, 0xd5, 0x99, 0x10, 0xe4, 0x23, 0x8f, 0x1c, 0xc6, 0xbb, 0x0d, 0x0d, 0x49, 0x86, 0x0b, + 0x69, 0x49, 0xcd, 0xe0, 0x5c, 0x16, 0xfd, 0x43, 0xb4, 0x61, 0x36, 0x39, 0xbb, 0x07, 0xc5, 0x79, 0xf8, 0xa9, 0x0a, + 0xc2, 0x88, 0x3a, 0xfb, 0xdb, 0xe2, 0x7a, 0xa4, 0x9f, 0xdf, 0x8f, 0xe7, 0xce, 0xd1, 0xa7, 0xd7, 0x1c, 0x73, 0xce, + 0xff, 0x08, 0x91, 0x01, 0xd5, 0x26, 0x25, 0x85, 0xbb, 0x56, 0xd0, 0x9a, 0xdc, 0x75, 0x64, 0xa6, 0x1a, 0x37, 0x61, + 0xc7, 0x99, 0x85, 0x3e, 0xf7, 0xe8, 0x2e, 0x2e, 0xdb, 0x5e, 0x43, 0x46, 0x26, 0xcd, 0xd1, 0xee, 0xbd, 0xfd, 0x7e, + 0x23, 0xb1, 0x1a, 0x98, 0xb0, 0x0c, 0x83, 0x21, 0xf0, 0x86, 0x48, 0x77, 0x06, 0x3c, 0x90, 0x1c, 0x54, 0x69, 0x4f, + 0x2c, 0xff, 0x49, 0x90, 0x1a, 0x5c, 0x12, 0xa8, 0x4a, 0xef, 0x3d, 0x9d, 0xf6, 0x15, 0x0e, 0x18, 0x1b, 0xd5, 0x75, + 0x2a, 0xe4, 0xea, 0x67, 0x3b, 0x22, 0xa8, 0x9e, 0x70, 0x6c, 0xb6, 0xfe, 0xd1, 0x75, 0x42, 0x7b, 0x92, 0x1a, 0xa6, + 0xb6, 0xbf, 0xd0, 0x26, 0x60, 0x90, 0xee, 0xcb, 0x4e, 0xe3, 0x65, 0xef, 0x7f, 0xeb, 0x8b, 0x7d, 0x04, 0x9e, 0x67, + 0x95, 0xe2, 0x0c, 0x31, 0x6e, 0x00, 0x0e, 0x6e, 0x5a, 0x30, 0x76, 0x68, 0x8a, 0x68, 0x31, 0x71, 0x94, 0x2f, 0xa7, + 0x79, 0x85, 0x4f, 0x9a, 0xae, 0x1b, 0xfe, 0xd0, 0x94, 0x48, 0x4d, 0x04, 0x2f, 0x84, 0x2a, 0x2c, 0xd2, 0xf7, 0xe7, + 0x9d, 0x22, 0x1e, 0x5d, 0x39, 0xdb, 0xdb, 0xae, 0x0f, 0xe5, 0xb0, 0xe4, 0x9f, 0x57, 0xf5, 0x26, 0x42, 0xdf, 0xe9, + 0xfc, 0xd2, 0x2f, 0x53, 0x5f, 0xf7, 0x0c, 0xa1, 0xc9, 0x86, 0x6c, 0x36, 0x5e, 0x00, 0x55, 0xd5, 0x19, 0xd3, 0xf5, + 0xe3, 0x3d, 0x56, 0x9b, 0x58, 0xec, 0x23, 0xfe, 0x3b, 0x12, 0xdc, 0x8f, 0x57, 0xae, 0xd9, 0x39, 0x21, 0x84, 0xf0, + 0x41, 0x89, 0x42, 0xbb, 0xc9, 0x88, 0x3a, 0xac, 0x74, 0x36, 0xba, 0x20, 0xf1, 0x50, 0xfa, 0xf8, 0xae, 0xe2, 0xe2, + 0xd2, 0x8e, 0xe8, 0x83, 0x53, 0x07, 0xd3, 0x7c, 0xc1, 0x3f, 0x9c, 0x3b, 0x53, 0xc5, 0x45, 0x48, 0x67, 0x5f, 0xb2, + 0x89, 0x03, 0xa2, 0x67, 0xba, 0xf4, 0xb4, 0x4c, 0xf8, 0xd5, 0xea, 0x0f, 0x90, 0x3a, 0xd9, 0xfd, 0x1c, 0x7e, 0x40, + 0x3e, 0xfd, 0x52, 0x82, 0x1e, 0x32, 0x7c, 0x39, 0x50, 0xbd, 0x0c, 0x5d, 0xed, 0x82, 0x59, 0xae, 0xfe, 0xcc, 0x13, + 0xd0, 0x6a, 0x7e, 0xbb, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xed, 0x0d, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xeb, 0x0d, 0x00, 0x00, 0x20, 0x00, 0x02, 0x80, 0xfc, 0x00, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xfc, 0x13, 0xe3, 0xe0, + 0x06, 0x48, 0x22, 0x6a, 0x10, 0x9e, 0x56, 0x8a, 0x85, 0xbb, 0x1b, 0xd5, 0x25, 0x99, 0xd0, 0x40, 0x8c, 0x46, 0xec, + 0x14, 0x84, 0x92, 0x5a, 0x13, 0xd5, 0x6c, 0xfe, 0x34, 0x7a, 0x12, 0xde, 0x80, 0x37, 0xcd, 0xee, 0x1e, 0x30, 0xd7, + 0xbb, 0x77, 0x89, 0x0a, 0xe5, 0x8f, 0x3d, 0x15, 0x98, 0xcc, 0x6a, 0x41, 0x79, 0x7a, 0xc6, 0x3c, 0x6a, 0x80, 0x28, + 0x95, 0xb9, 0xe0, 0x10, 0x9a, 0x14, 0xbc, 0xee, 0x6c, 0x44, 0x92, 0x4a, 0x24, 0x16, 0xf2, 0x2f, 0xdb, 0x30, 0xb2, + 0x9e, 0x21, 0x2d, 0xb2, 0x12, 0x8e, 0xc2, 0x44, 0xbe, 0x24, 0xf6, 0x82, 0x77, 0xfd, 0x17, 0x25, 0xd6, 0xc0, 0x84, + 0x97, 0xe0, 0x9f, 0x5e, 0x2e, 0x7c, 0x30, 0x80, 0x08, 0xa1, 0x4f, 0x0e, 0xae, 0x4a, 0x28, 0x85, 0x6d, 0x9e, 0x60, + 0xc2, 0x26, 0xfa, 0x2c, 0xba, 0xf6, 0x4a, 0xca, 0x18, 0xbc, 0x53, 0x1d, 0x84, 0x56, 0x26, 0x82, 0x64, 0xc2, 0x3f, + 0xb3, 0xee, 0x54, 0xbc, 0x3c, 0xb2, 0x55, 0x11, 0xaa, 0x20, 0xeb, 0x09, 0x02, 0x26, 0x00, 0x9c, 0x9a, 0xff, 0x6b, + 0x6a, 0xc1, 0x49, 0xd0, 0x26, 0xe0, 0x10, 0x06, 0xe1, 0xf0, 0x3d, 0xd4, 0x2e, 0x1a, 0x7e, 0x10, 0x3c, 0x22, 0xb6, + 0xcf, 0x9f, 0xb0, 0xe4, 0x02, 0x54, 0xb0, 0x3a, 0x9a, 0x66, 0xd0, 0x31, 0xf7, 0xea, 0x34, 0x9a, 0x5c, 0xce, 0x12, + 0x28, 0x86, 0x92, 0xac, 0xbe, 0x90, 0x8c, 0xee, 0x62, 0xe9, 0xe3, 0x09, 0x45, 0x8a, 0x84, 0x9a, 0x22, 0xd8, 0x2a, + 0xd3, 0x61, 0x82, 0x78, 0x90, 0x1c, 0x68, 0x73, 0x5d, 0xce, 0x54, 0x90, 0x36, 0x0a, 0xf2, 0xfe, 0x30, 0x86, 0x96, + 0x5a, 0x8a, 0xa4, 0x2e, 0x0e, 0x00, 0x0a, 0xb6, 0x66, 0xae, 0x4c, 0x8c, 0x94, 0x76, 0x22, 0x66, 0x6c, 0x64, 0xc0, + 0x26, 0x20, 0xbc, 0x3e, 0xd6, 0x22, 0xab, 0x31, 0x3e, 0xc6, 0xee, 0xfb, 0x51, 0xad, 0x25, 0xea, 0x24, 0xee, 0x08, + 0x20, 0xb2, 0x46, 0xd1, 0x25, 0xe0, 0x1a, 0x00, 0x2c, 0xa1, 0x3b, 0xea, 0xd8, 0x56, 0xc2, 0x0a, 0x34, 0xc8, 0xf8, + 0x2f, 0xd3, 0x00, 0x50, 0x79, 0x5d, 0xf2, 0x0d, 0xad, 0x84, 0x86, 0x72, 0x98, 0x3a, 0xf6, 0xd2, 0x68, 0x8e, 0x62, + 0x8a, 0x54, 0x2c, 0x7e, 0x4a, 0x1c, 0xd0, 0x1f, 0xdb, 0x0d, 0x15, 0x06, 0xfa, 0xe4, 0x42, 0x9a, 0x43, 0x01, 0x02, + 0xee, 0xac, 0xa0, 0xab, 0x09, 0x06, 0x04, 0xd6, 0x40, 0x02, 0x81, 0x8c, 0xb1, 0x40, 0xca, 0x48, 0xba, 0x16, 0x08, + 0x22, 0xb4, 0x2e, 0xec, 0x08, 0x04, 0xe8, 0x44, 0xc0, 0x1c, 0x19, 0xd5, 0xee, 0x1e, 0x04, 0x0e, 0x00, 0xc6, 0x1c, + 0x1a, 0x16, 0xb6, 0x46, 0xc2, 0x38, 0xe2, 0x08, 0xe0, 0x55, 0xa7, 0x2f, 0xc7, 0x0c, 0x22, 0x46, 0x6e, 0x1e, 0x64, + 0xa9, 0x15, 0xfa, 0x00, 0x18, 0x00, 0xf8, 0xf5, 0x1f, 0xc0, 0x26, 0x2e, 0xb4, 0x34, 0xf2, 0xec, 0x1a, 0xef, 0xe6, + 0x33, 0xe6, 0x1a, 0xd0, 0x5c, 0x72, 0x68, 0xd6, 0xf8, 0x32, 0xf0, 0xfa, 0x26, 0xca, 0x12, 0xf2, 0xe6, 0x63, 0x99, + 0x04, 0x3b, 0x13, 0x9c, 0x3a, 0xe6, 0x1b, 0xfd, 0x1a, 0xba, 0x46, 0xf0, 0x08, 0xd8, 0x14, 0x0e, 0xf6, 0x0a, 0xf6, + 0xe2, 0x45, 0xd9, 0xe0, 0x44, 0xc4, 0x14, 0xfe, 0xf4, 0x2a, 0xd8, 0x1a, 0xe0, 0x1a, 0x04, 0x10, 0xc4, 0x44, 0xd4, + 0x06, 0xe0, 0x4c, 0xba, 0x1e, 0xec, 0x3e, 0xb8, 0x1e, 0x06, 0xec, 0x06, 0xfa, 0x08, 0x0c, 0xec, 0x14, 0xe8, 0x28, + 0xd2, 0x1c, 0xe0, 0x2e, 0x00, 0xde, 0x0e, 0x02, 0xef, 0x17, 0x04, 0xe0, 0x30, 0xcc, 0x24, 0xd8, 0x56, 0xa2, 0x11, + 0x39, 0xb9, 0x33, 0xfa, 0xe0, 0x2c, 0xd6, 0x08, 0x26, 0xe4, 0xee, 0x04, 0x28, 0xd4, 0x18, 0x08, 0xd8, 0x16, 0x06, + 0x0c, 0xe8, 0x0b, 0x25, 0xba, 0x3a, 0xc5, 0x2b, 0xde, 0x2e, 0xc8, 0x3c, 0xcc, 0x36, 0xdf, 0x19, 0xdc, 0x14, 0xe8, + 0x1e, 0xfc, 0xe3, 0x2d, 0xdc, 0x01, 0x1f, 0xe8, 0x0a, 0xee, 0x09, 0x13, 0xe6, 0x0a, 0x0a, 0x1a, 0xc0, 0x2c, 0xf4, + 0xf2, 0xfe, 0x14, 0xf8, 0xfe, 0x18, 0xd4, 0x2d, 0xdf, 0x02, 0x12, 0x06, 0xee, 0xe3, 0x45, 0xca, 0x00, 0x24, 0xf4, + 0xf6, 0x0a, 0xec, 0x12, 0x00, 0x06, 0xee, 0x00, 0x06, 0x0a, 0xea, 0x2a, 0xd6, 0x14, 0xf8, 0xfe, 0x11, 0xee, 0x05, + 0x1c, 0xd6, 0x24, 0xbe, 0x34, 0x00, 0x01, 0xf3, 0x0a, 0xde, 0x30, 0xd6, 0x34, 0xd8, 0x06, 0x04, 0x23, 0xb5, 0x28, + 0xfc, 0x0e, 0xfa, 0xf2, 0x14, 0xea, 0x2a, 0xd0, 0x1a, 0xf8, 0xfe, 0x10, 0xe6, 0x14, 0xee, 0x14, 0xf3, 0x05, 0x11, + 0xdd, 0x12, 0x02, 0xf2, 0x0a, 0xf8, 0x10, 0xfc, 0xfc, 0x0e, 0xe5, 0x31, 0xb4, 0x2e, 0x12, 0xd6, 0x16, 0x02, 0x04, + 0xe0, 0x1a, 0xfe, 0x0c, 0xe2, 0x0a, 0x04, 0x26, 0xc2, 0x24, 0xf9, 0xf1, 0x0f, 0x0f, 0xd6, 0x18, 0x0e, 0xef, 0xfb, + 0x06, 0x04, 0x0c, 0xd6, 0x24, 0xea, 0x2c, 0xd0, 0x12, 0xfe, 0x0a, 0xef, 0x07, 0x00, 0xee, 0x22, 0xdf, 0x2f, 0xbe, + 0x34, 0xe8, 0x18, 0xe6, 0x14, 0xfa, 0xfa, 0x0e, 0xf0, 0x0a, 0x04, 0xf6, 0xf2, 0x0a, 0x0e, 0x0c, 0xe4, 0x14, 0xe2, + 0x20, 0xee, 0x11, 0xf1, 0xf6, 0x16, 0xf6, 0x00, 0x0c, 0xf8, 0xf2, 0x16, 0xdc, 0x26, 0xea, 0x0a, 0xf6, 0x10, 0xf5, + 0x05, 0x20, 0xbd, 0x21, 0x16, 0xdc, 0x02, 0x18, 0xe6, 0x38, 0xaa, 0x35, 0x05, 0xee, 0x02, 0x0c, 0xec, 0x07, 0x03, + 0x08, 0xe2, 0x24, 0xf4, 0xec, 0x17, 0xfb, 0xfb, 0x0d, 0xea, 0x20, 0xdb, 0x29, 0xe0, 0xf6, 0x22, 0xfc, 0xe4, 0x0c, + 0x14, 0xed, 0x0b, 0xf8, 0x02, 0xf4, 0x16, 0x0a, 0xc4, 0x36, 0x06, 0xd5, 0x1f, 0xef, 0x0f, 0xfe, 0xfe, 0xf8, 0xfc, + 0x14, 0xf8, 0xf4, 0x18, 0xe4, 0x1c, 0xe3, 0x1d, 0xf0, 0xfd, 0x05, 0xf0, 0x13, 0xfb, 0x0a, 0xec, 0x17, 0xe3, 0x1a, + 0xfc, 0x02, 0xf0, 0x12, 0xf4, 0xfe, 0x0a, 0x06, 0xfe, 0xf4, 0x01, 0x01, 0x06, 0x07, 0xe8, 0x29, 0xca, 0x28, 0xec, + 0x14, 0xe8, 0x0d, 0x02, 0xfb, 0xf6, 0x08, 0x02, 0x06, 0xfa, 0x04, 0x02, 0xf8, 0x10, 0xe4, 0x12, 0xfa, 0x02, 0x08, + 0xf2, 0x12, 0xf6, 0xfc, 0xfc, 0x0a, 0x02, 0xf8, 0x06, 0xf6, 0x14, 0xe0, 0x27, 0xd7, 0x1a, 0xf4, 0x06, 0x06, 0xf8, + 0xfe, 0x02, 0x08, 0xf4, 0x02, 0x08, 0x02, 0xf5, 0x13, 0xe5, 0x0b, 0x0e, 0xf4, 0xfa, 0xfb, 0x0b, 0x08, 0xec, 0x1a, + 0xea, 0x10, 0xfa, 0xfa, 0x06, 0xfe, 0x00, 0x00, 0x08, 0x06, 0xe8, 0x0e, 0xf0, 0x19, 0xe9, 0x0e, 0x10, 0xd6, 0x1b, + 0xff, 0x0a, 0xe8, 0x14, 0xf0, 0x04, 0x04, 0xfa, 0x12, 0xe0, 0x25, 0xe1, 0x14, 0xf6, 0x10, 0xe8, 0x16, 0xf6, 0xfc, + 0xfd, 0x0c, 0xf7, 0x04, 0x06, 0xf2, 0x10, 0xf1, 0x03, 0x06, 0x00, 0xfe, 0x08, 0xfa, 0xef, 0x11, 0x08, 0xf2, 0xfc, + 0x1a, 0xd4, 0x22, 0xf4, 0x06, 0xfa, 0x07, 0x01, 0x00, 0x00, 0x41, 0x20, 0x73, 0x70, 0x65, 0x63, 0x74, 0x65, 0x72, + 0x20, 0x6e, 0x6f, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x01, 0x80, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x02, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x02, 0x00, 0x03, 0x35, 0x5a, + 0xfb, 0x7c, 0xf2, 0xfb, 0xff, 0x01, 0x05, 0x00, 0xfa, 0xfb, 0xff, 0xfe, 0x00, 0x08, 0x03, 0xfd, 0xfd, 0x00, 0x07, + 0x01, 0x00, 0x00, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2e, 0x2e, + 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x01, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x02, + 0x03, 0x03, 0x06, 0x03, 0x02, 0x00, 0x00, 0x03, 0x0a, 0x25, 0x5e, 0x00, 0x00, 0x02, 0x00, 0x05, 0xd6, 0x88, 0x00, + 0x00, 0xff, 0xfc, 0xff, 0x05, 0x01, 0x00, 0xff, 0xfe, 0xfe, 0x00, 0x07, 0x01, 0x00, 0x00, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x32, 0x30, 0x32, 0x34, 0x00, + 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x01, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xfb, 0x43, + 0x5d, 0x02, 0x05, 0x00, 0xfe, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x07, 0xfe, 0xfd, 0xc5, 0xa3, 0xfe, 0x00, 0xfd, 0x00, + 0x00, 0xfd, 0xfb, 0xfd, 0x07, 0x01, 0x00, 0x00, 0x44, 0x72, 0x6f, 0x7a, 0x65, 0x72, 0x69, 0x78, 0x40, 0x67, 0x6d, + 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x01, 0x80, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa9, 0x00, 0xfe, 0x05, 0x08, 0x03, 0x0b, 0x84, 0x0b, 0x09, 0x01, 0x02, 0x03, 0x03, 0x00, 0xff, + 0xfe, 0xfe, 0xfc, 0xfb, 0xfd, 0xff, 0xfc, 0x00, 0x00, 0x89, 0xfa, 0xf5, 0x0f, 0xf8, 0xf6, 0x00}; +} \ No newline at end of file