// DreamyZoom — MSL, generated from https://github.com/gl-transitions/gl-transitions/blob/master/transitions/DreamyZoom.glsl
// Author: Zeh Fernando
// License: MIT
// Description: Zooms and rotates into a bright flash, then out to the incoming image
// Bindings and uniform layout: see the gl-transitions package README

// language: metal1.0
#include <metal_stdlib>
#include <simd/simd.h>

using metal::uint;

struct Uniforms {
    float progress;
    float ratio;
    float rotation;
    float scale;
};

metal::float4 getToColor(
    thread metal::float2& uv,
    metal::sampler _sampler,
    metal::texture2d<float, metal::access::sample> _to
) {
    float _e21 = uv[0u];
    float _e23 = uv[1u];
    metal::float4 _e26 = _to.sample(_sampler, metal::float2(_e21, 1.0 - _e23), metal::level(0.0));
    return _e26;
}

metal::float4 getFromColor(
    thread metal::float2& uv_1,
    metal::texture2d<float, metal::access::sample> _from,
    metal::sampler _sampler
) {
    float _e21 = uv_1[0u];
    float _e23 = uv_1[1u];
    metal::float4 _e26 = _from.sample(_sampler, metal::float2(_e21, 1.0 - _e23), metal::level(0.0));
    return _e26;
}

metal::float4 transition(
    thread metal::float2& uv_2,
    metal::texture2d<float, metal::access::sample> _from,
    metal::sampler _sampler,
    metal::texture2d<float, metal::access::sample> _to,
    constant Uniforms& uniforms
) {
    float phase = {};
    float local = {};
    float angleOffset = {};
    float local_1 = {};
    float newScale = {};
    float local_2 = {};
    metal::float2 center = {};
    metal::float2 assumedCenter = {};
    metal::float2 p = {};
    float angle = {};
    float dist = {};
    metal::float4 c = {};
    metal::float4 local_3 = {};
    metal::float2 param = {};
    metal::float2 param_1 = {};
    float local_4 = {};
    float _e37 = uniforms.progress;
    if (_e37 < 0.5) {
        float _e40 = uniforms.progress;
        local = _e40 * 2.0;
    } else {
        float _e43 = uniforms.progress;
        local = (_e43 - 0.5) * 2.0;
    }
    float _e46 = local;
    phase = _e46;
    float _e48 = uniforms.progress;
    if (_e48 < 0.5) {
        float _e51 = uniforms.rotation;
        float _e53 = phase;
        local_1 = metal::mix(0.0, _e51 * 0.03926991, _e53);
    } else {
        float _e56 = uniforms.rotation;
        float _e59 = phase;
        local_1 = metal::mix(-(_e56) * 0.03926991, 0.0, _e59);
    }
    float _e61 = local_1;
    angleOffset = _e61;
    float _e63 = uniforms.progress;
    if (_e63 < 0.5) {
        float _e66 = uniforms.scale;
        float _e67 = phase;
        local_2 = metal::mix(1.0, _e66, _e67);
    } else {
        float _e70 = uniforms.scale;
        float _e71 = phase;
        local_2 = metal::mix(_e70, 1.0, _e71);
    }
    float _e73 = local_2;
    newScale = _e73;
    center = metal::float2(0.0, 0.0);
    assumedCenter = metal::float2(0.5, 0.5);
    metal::float2 _e74 = uv_2;
    float _e76 = newScale;
    float _e80 = uniforms.ratio;
    p = ((_e74 - metal::float2(0.5, 0.5)) / metal::float2(_e76)) * metal::float2(_e80, 1.0);
    float _e84 = p[1u];
    float _e86 = p[0u];
    float _e88 = angleOffset;
    angle = metal::atan2(_e84, _e86) + _e88;
    metal::float2 _e90 = center;
    metal::float2 _e91 = p;
    dist = metal::distance(_e90, _e91);
    float _e93 = angle;
    float _e95 = dist;
    float _e98 = uniforms.ratio;
    p[0u] = ((metal::cos(_e93) * _e95) / _e98) + 0.5;
    float _e102 = angle;
    float _e104 = dist;
    p[1u] = (metal::sin(_e102) * _e104) + 0.5;
    float _e109 = uniforms.progress;
    if (_e109 < 0.5) {
        metal::float2 _e111 = p;
        param = _e111;
        metal::float4 _e112 = getFromColor(param, _from, _sampler);
        local_3 = _e112;
    } else {
        metal::float2 _e113 = p;
        param_1 = _e113;
        metal::float4 _e114 = getToColor(param_1, _sampler, _to);
        local_3 = _e114;
    }
    metal::float4 _e115 = local_3;
    c = _e115;
    metal::float4 _e116 = c;
    float _e118 = uniforms.progress;
    if (_e118 < 0.5) {
        float _e120 = phase;
        local_4 = metal::mix(0.0, 1.0, _e120);
    } else {
        float _e122 = phase;
        local_4 = metal::mix(1.0, 0.0, _e122);
    }
    float _e124 = local_4;
    return _e116 + metal::float4(_e124);
}

void main_1(
    metal::texture2d<float, metal::access::sample> _from,
    metal::sampler _sampler,
    metal::texture2d<float, metal::access::sample> _to,
    constant Uniforms& uniforms,
    thread metal::float4& _fragColor,
    thread metal::float2& _uv_1
) {
    metal::float2 param_2 = {};
    metal::float2 _e20 = _uv_1;
    param_2 = _e20;
    metal::float4 _e21 = transition(param_2, _from, _sampler, _to, uniforms);
    _fragColor = _e21;
    return;
}

struct main_Input {
    metal::float2 _uv [[user(loc0), center_perspective]];
};
struct main_Output {
    metal::float4 member [[color(0)]];
};
fragment main_Output main_(
  main_Input varyings [[stage_in]]
, metal::texture2d<float, metal::access::sample> _from [[texture(0)]]
, metal::sampler _sampler [[sampler(0)]]
, metal::texture2d<float, metal::access::sample> _to [[texture(1)]]
, constant Uniforms& uniforms [[buffer(0)]]
) {
    metal::float4 _fragColor = {};
    metal::float2 _uv_1 = {};
    const auto _uv = varyings._uv;
    _uv_1 = _uv;
    main_1(_from, _sampler, _to, uniforms, _fragColor, _uv_1);
    metal::float4 _e3 = _fragColor;
    return main_Output { _e3 };
}
