{
    "QEN": {
        "description": "Effect node for animating sprite sequences.",
        "fragmentCode": [
            "@main",
            "{",
            "    vec4 sprite = vec4(0.0);",
            "if (spriteAnimationInterpolate) {",
            "    vec2 spriteUV;",
            "    spriteUV.x = spriteArea.x + texCoord.x * spriteArea.z;",
            "    spriteUV.y = spriteArea.y + texCoord.y * spriteArea.w;",
            "    vec4 sprite1 = texture(spriteAnimationImage, spriteUV);",
            "",
            "    vec2 spriteUV2;",
            "    spriteUV2.x = spriteArea2.x + texCoord.x * spriteArea2.z;",
            "    spriteUV2.y = spriteArea2.y + texCoord.y * spriteArea2.w;",
            "    vec4 sprite2 = texture(spriteAnimationImage, spriteUV2);",
            "",
            "    float anim = clamp(mod(iTime * (1.0 / spriteAnimationFrameDuration), 1.0), 0.0, 1.0);",
            "    sprite = mix(sprite1, sprite2, anim);",
            "} else {",
            "    vec2 spriteUV;",
            "    spriteUV.x = spriteArea.x + texCoord.x * spriteArea.z;",
            "    spriteUV.y = spriteArea.y + texCoord.y * spriteArea.w;",
            "    sprite = texture(spriteAnimationImage, spriteUV);",
            "}",
            "    fragColor = mix(fragColor, sprite, sprite.a);",
            "}"
        ],
        "name": "Sprite Animation",
        "properties": [
            {
                "defaultValue": "false",
                "description": "If set to true, interpolation will occur between sprite frames to make the animation appear smoother. Interpolation requires two texture lookups.",
                "name": "spriteAnimationInterpolate",
                "displayName": "Interpolate",
                "type": "bool"
            },
            {
                "defaultValue": "../images/qt-logo-sheet.png",
                "description": "Sets the sprite sheet Image.",
                "name": "spriteAnimationImage",
                "displayName": "Image",
                "type": "image"
            },
            {
                "defaultValue": "4",
                "description": "Sets the amount of rows in the sprite image.",
                "maxValue": "16",
                "minValue": "1",
                "name": "spriteAnimationRows",
                "displayName": "Rows",
                "type": "int"
            },
            {
                "defaultValue": "4",
                "description": "Sets the amount of columns in the sprite image.",
                "maxValue": "16",
                "minValue": "1",
                "name": "spriteAnimationColumns",
                "displayName": "Columns",
                "type": "int"
            },
            {
                "defaultValue": "16",
                "description": "Sets the total amount of frames in the image sequence. This is often rows * columns, but can be also smaller if the grid is not full of images or you only want to animate a part of the sprite images.",
                "maxValue": "256",
                "minValue": "1",
                "name": "spriteAnimationFrameCount",
                "displayName": "Frame Count",
                "type": "int"
            },
            {
                "defaultValue": "0.1",
                "description": "Sets how long a single frame is shown in seconds.",
                "maxValue": "1",
                "minValue": "0.01",
                "name": "spriteAnimationFrameDuration",
                "displayName": "Frame Duration",
                "type": "float"
            }
        ],
        "version": 1,
        "vertexCode": [
            "out vec4 spriteArea;",
            "out vec4 spriteArea2;",
            "@main",
            "{",
            "    float columnSize = 1.0 / spriteAnimationColumns;",
            "    float rowSize  = 1.0 / spriteAnimationRows;    ",
            "    float frameIndexF = mod(iTime / spriteAnimationFrameDuration, spriteAnimationFrameCount);",
            "    ",
            "    float frameIndex = floor(frameIndexF);",
            "    float frameColumn = mod(frameIndex, spriteAnimationColumns);",
            "    float frameRow = floor(float(frameIndex) / spriteAnimationColumns);",
            "    spriteArea = vec4(frameColumn * columnSize,",
            "                      frameRow * rowSize,",
            "                      columnSize,",
            "                      rowSize);",
            "    if (spriteAnimationInterpolate) {",
            "       float frameIndex2 = mod(ceil(frameIndexF), spriteAnimationFrameCount);",
            "       float frameColumn2 = mod(frameIndex2, spriteAnimationColumns);",
            "       float frameRow2 = floor(float(frameIndex2) / spriteAnimationColumns);",
            "       spriteArea2 = vec4(frameColumn2 * columnSize,",
            "                          frameRow2 * rowSize,",
            "                          columnSize,",
            "                          rowSize);",
            "    }",
            "}"
        ]
    }
}
