瀏覽代碼

Add support for TEXS0001 animated texture format and auto orthographic projection (#560)

Co-authored-by: Alexis Maiquez <wpengine@alma.mu>
ZZBaron 4 月之前
父節點
當前提交
a8ce9b6aa1

+ 1 - 0
src/WallpaperEngine/Data/Assets/Texture.h

@@ -19,6 +19,7 @@ enum ContainerVersion {
 
 enum AnimatedVersion {
     AnimatedVersion_UNKNOWN = 0,
+    AnimatedVersion_TEXS0001 = 1,
     AnimatedVersion_TEXS0002 = 2,
     AnimatedVersion_TEXS0003 = 3,
 };

+ 1 - 1
src/WallpaperEngine/Data/Parsers/ObjectParser.cpp

@@ -240,7 +240,7 @@ ObjectParser::parseImage (const JSON& it, const Project& project, ObjectData bas
 	    .alpha = it.user ("alpha", properties, 1.0f),
 	    .color = it.user ("color", properties, glm::vec4 (1.0f)),
 	    .alignment = it.optional ("horizontalalign", it.optional ("alignment", std::string ("center"))),
-	    .size = it.optional ("size", glm::vec2 (0.0f)),
+	    .size = it.user ("size", project.properties, glm::vec2 (0.0f))->value->getVec2 (),
 	    .parallaxDepth = it.user ("parallaxDepth", properties, glm::vec2 (0.0f)),
 	    .colorBlendMode = it.user ("colorBlendMode", properties, 0),
 	    .brightness = it.user ("brightness", properties, 1.0f),

+ 25 - 4
src/WallpaperEngine/Data/Parsers/TextureParser.cpp

@@ -92,6 +92,21 @@ MipmapSharedPtr TextureParser::parseMipmap (const BinaryReader& file, const Text
     return result;
 }
 
+FrameSharedPtr TextureParser::parseFrameV1 (const BinaryReader& file) {
+    auto result = std::make_shared<Frame> ();
+
+    result->frameNumber = file.nextUInt32 ();
+    result->frametime = file.nextFloat ();
+    result->x = static_cast<float> (file.nextUInt32 ());
+    result->y = static_cast<float> (file.nextUInt32 ());
+    result->width1 = static_cast<float> (file.nextUInt32 ());
+    std::ignore = file.nextUInt32 (); // unknown
+    std::ignore = file.nextUInt32 (); // unknown
+    result->height1 = static_cast<float> (file.nextUInt32 ());
+
+    return result;
+}
+
 FrameSharedPtr TextureParser::parseFrame (const BinaryReader& file) {
     auto result = std::make_shared<Frame> ();
 
@@ -195,7 +210,9 @@ void TextureParser::parseAnimations (Texture& header, const BinaryReader& file)
     // image is animated, keep parsing the rest of the image info
     file.next (magic, 9);
 
-    if (strncmp (magic, "TEXS0002", 9) == 0) {
+    if (strncmp (magic, "TEXS0001", 9) == 0) {
+	header.animatedVersion = AnimatedVersion_TEXS0001;
+    } else if (strncmp (magic, "TEXS0002", 9) == 0) {
 	header.animatedVersion = AnimatedVersion_TEXS0002;
     } else if (strncmp (magic, "TEXS0003", 9) == 0) {
 	header.animatedVersion = AnimatedVersion_TEXS0003;
@@ -211,11 +228,15 @@ void TextureParser::parseAnimations (Texture& header, const BinaryReader& file)
     }
 
     while (frameCount-- > 0) {
-	header.frames.push_back (parseFrame (file));
+	if (header.animatedVersion == AnimatedVersion_TEXS0001) {
+	    header.frames.push_back (parseFrameV1 (file));
+	} else {
+	    header.frames.push_back (parseFrame (file));
+	}
     }
 
-    // ensure gif width and height is right for TEXS0002
-    if (header.animatedVersion == AnimatedVersion_TEXS0002) {
+    // ensure gif width and height is right for TEXS0001, TEXS0002
+    if (header.animatedVersion == AnimatedVersion_TEXS0001 || header.animatedVersion == AnimatedVersion_TEXS0002) {
 	header.gifWidth = (*header.frames.begin ())->width1;
 	header.gifHeight = (*header.frames.begin ())->height1;
     }

+ 1 - 0
src/WallpaperEngine/Data/Parsers/TextureParser.h

@@ -21,6 +21,7 @@ public:
     );
     static MipmapSharedPtr parseMipmap (const BinaryReader& file, const Texture& header);
     static FrameSharedPtr parseFrame (const BinaryReader& file);
+    static FrameSharedPtr parseFrameV1 (const BinaryReader& file);
 
 private:
     static void parseTextureHeader (Texture& header, const BinaryReader& file);

+ 2 - 2
src/WallpaperEngine/Data/Parsers/WallpaperParser.cpp

@@ -69,8 +69,8 @@ SceneUniquePtr WallpaperParser::parseScene (const JSON& file, Project& project)
                     .up = camera.require <glm::vec3> ("up", "Camera must have an up position"),
                 },
                 .projection = {
-                    .width = projection.require <int> ("width", "Projection must have a width"),
-                    .height = projection.require <int> ("height", "Projection must have a height"),
+                    .width  = projection.optional ("auto", false) ? 0 : projection.require <int> ("width",  "Projection must have a width"),
+                    .height = projection.optional ("auto", false) ? 0 : projection.require <int> ("height", "Projection must have a height"),
                     .isAuto = projection.optional ("auto", false),
                     .nearz = camera.optional <float> ("nearz", 0.0f),
                     .farz = camera.optional <float> ("farz", 1000.0f),

+ 28 - 2
src/WallpaperEngine/Render/Wallpapers/CScene.cpp

@@ -36,7 +36,33 @@ CScene::CScene (
 
     // detect size if the orthogonal project is auto
     if (scene->camera.projection.isAuto) {
-	// TODO: CALCULATE ORTHOGONAL PROJECTION BASED ON CONTENT'S SIZE HERE
+	glm::vec2 maxExtent = { 0.0f, 0.0f };
+
+	for (const auto& object : scene->objects) {
+	    if (!object->is<Image> ()) {
+		continue;
+	    }
+
+	    const auto* image = object->as<Image> ();
+	    if (!image->origin || !image->origin->value) {
+		continue;
+	    }
+
+	    const glm::vec3 origin = image->origin->value->getVec3 ();
+	    const glm::vec2 halfSize = image->size / 2.0f;
+
+	    maxExtent.x = glm::max (maxExtent.x, glm::abs (origin.x) + halfSize.x);
+	    maxExtent.y = glm::max (maxExtent.y, glm::abs (origin.y) + halfSize.y);
+	}
+
+	if (maxExtent.x > 0.0f && maxExtent.y > 0.0f) {
+	    width = maxExtent.x * 2.0f;
+	    height = maxExtent.y * 2.0f;
+	} else {
+	    width = this->getContext ().getOutput ().getFullWidth ();
+	    height = this->getContext ().getOutput ().getFullHeight ();
+	    sLog.debug ("Auto projection: falling back to screen resolution ", width, "x", height);
+	}
     }
 
     this->m_parallaxDisplacement = { 0, 0 };
@@ -360,7 +386,7 @@ void CScene::updateMouse (const glm::ivec4& viewport) {
     this->m_mousePositionNormalized.y = uvs.vstart + normalizedMouseY * (uvs.vend - uvs.vstart);
 
     // Invert previous normalization of Y to match what the shader expects
-    double mouseY = 1.0 - normalizedMouseY; 
+    double mouseY = 1.0 - normalizedMouseY;
 
     this->m_mousePosition.x = this->m_mousePositionNormalized.x;
     this->m_mousePosition.y = uvs.vstart + mouseY * (uvs.vend - uvs.vstart);