#pragma once #include #include #include #include "anm2_type.h" #include "types.h" namespace anm2ed::anm2 { constexpr auto FRAME_DURATION_MIN = 1; constexpr auto FRAME_DURATION_MAX = 1000000; #define MEMBERS \ X(isVisible, bool, true) \ X(isInterpolated, bool, false) \ X(rotation, float, 0.0f) \ X(duration, int, FRAME_DURATION_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, {}) \ X(size, glm::vec2, {}) \ X(scale, glm::vec2, glm::vec2(100.0f)) \ X(colorOffset, glm::vec3, glm::vec3()) \ X(tint, glm::vec4, types::color::WHITE) class Frame { public: #define X(name, type, ...) type name = __VA_ARGS__; MEMBERS #undef X #undef MEMBERS 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 { std::optional isVisible{}; std::optional isInterpolated{}; std::optional rotation{}; std::optional duration{}; std::optional atFrame{}; std::optional eventID{}; std::optional pivotX{}; std::optional pivotY{}; std::optional cropX{}; std::optional cropY{}; std::optional positionX{}; std::optional positionY{}; std::optional sizeX{}; std::optional sizeY{}; std::optional scaleX{}; std::optional scaleY{}; std::optional colorOffsetR{}; std::optional colorOffsetG{}; std::optional colorOffsetB{}; std::optional tintR{}; std::optional tintG{}; std::optional tintB{}; std::optional tintA{}; }; }