//二次元の座標を扱うメタ関数

//代入
__fn V2_set $d $x $y {
    v[0 + __id($d)..1 + __id($d)] = [$x, $y]

}

__fn V2_copy $d $s1 {
    v[0 + __id($d)..1 + __id($d)] = [v[0 + __id($s1)], v[1 + __id($s1)]]

}

//加算
__fn V2_add $d $s1 $s2 {
    __loop 2 $i {
        v[$i + __id($d)] = v[$i + __id($s1)] + v[$i + __id($s2)]

    }

}

__fn V2_asAdd $d $s1 {
    __loop 2 $i {
        v[$i + __id($d)] += v[$i + __id($s1)]

    }

}

__fn V2_addScalar $d $s1 $m {
    __loop 2 $i {
        v[$i + __id($d)] = v[$i + __id($s1)] + ($m)

    }

}

__fn V2_asAddScalar $d $m {
    v[0 + __id($d)..1 + __id($d)] += $m

}


//減算
__fn V2_sub $d $s1 $s2 {
    __loop 2 $i {
        v[$i + __id($d)] = v[$i + __id($s1)] - v[$i + __id($s2)]

    }

}

__fn V2_asSub $d $s1 {
    __loop 2 $i {
        v[$i + __id($d)] -= v[$i + __id($s1)]

    }

}

__fn V2_subScalar $d $s1 $m {
    __loop 2 $i {
        v[$i + __id($d)] = v[$i + __id($s1)] - ($m)

    }

}

__fn V2_asSubScalar $d $m {
    v[0 + __id($d)..1 + __id($d)] -= $m

}

//乗算
__fn V2_mul $d $s1 $s2 {
    __loop 2 $i {
        v[$i + __id($d)] = v[$i + __id($s1)] * v[$i + __id($s2)]

    }

}

__fn V2_asMul $d $s1 {
    __loop 2 $i {
        v[$i + __id($d)] *= v[$i + __id($s1)]

    }

}

__fn V2_mulScalar $d $s1 $m {
    __loop 2 $i {
        v[$i + __id($d)] = v[$i + __id($s1)] * ($m)

    }

}

__fn V2_asMulScalar $d $m {
    v[0 + __id($d)..1 + __id($d)] *= $m

}

//除算
__fn V2_div $d $s1 $s2 {
    __loop 2 $i {
        v[$i + __id($d)] = v[$i + __id($s1)] / v[$i + __id($s2)]

    }

}

__fn V2_asDiv $d $s1 {
    __loop 2 $i {
        v[$i + __id($d)] /= v[$i + __id($s1)]

    }

}

__fn V2_divScalar $d $s1 $m {
    __loop 2 $i {
        v[$i + __id($d)] = v[$i + __id($s1)] / ($m)

    }

}

__fn V2_asDivScalar $d $m {
    v[0 + __id($d)..1 + __id($d)] /= $m

}

//ベクトルの大きさ
__fn V2_mag $d $s1 {
    v[__id($d)] = sqrt(v[0 + __id($s1)] * v[0 + __id($s1)] + v[1 + __id($s1)] * v[1 + __id($s1)], 1)

}

__fn V2_magSq $d $s1 {
    v[__id($d)] = v[0 + __id($s1)] * v[0 + __id($s1)] + v[1 + __id($s1)] * v[1 + __id($s1)]

}

__fn V2_magById $d $s1 {
    v[__id($d)] = sqrt(v[0 + $s1] * v[0 + $s1] + v[1 + $s1] * v[1 + $s1], 1)

}

__fn V2_magSqById $d $s1 {
    v[__id($d)] = v[0 + $s1] * v[0 + $s1] + v[1 + $s1] * v[1 + $s1]

}

//距離
__fn V2_dist $d $s1 $s2 {
    $dx = (v[0 + __id($s2)] - v[0 + __id($s1)])
    $dy = (v[1 + __id($s2)] - v[1 + __id($s1)])

    v[__id($d)] = sqrt($dx * $dx + $dy * $dy, 1)

}

__fn V2_distSq $d $s1 $s2 {
    $dx = (v[0 + __id($s2)] - v[0 + __id($s1)])
    $dy = (v[1 + __id($s2)] - v[1 + __id($s1)])

    v[__id($d)] = $dx * $dx + $dy * $dy
}


//内積
__fn V2_dot $d $s1 $s2 $div {
    v[__id($d)] = (v[0 + __id($s1)] * v[0 + __id($s2)] +  v[1 + __id($s1)] * v[1 + __id($s2)]) / ($div)

}

//外積
__fn V2_cross $d $s1 $s2 $div {
    v[__id($d)] = (v[0 + __id($s1)] * v[1 + __id($s2)] -  v[1 + __id($s1)] * v[0 + __id($s2)]) / ($div)

}

//回転
__fn V2_rotate $d $s1 $ang $div {
    v[0 + __id($d)] = cos($ang, $div, v[0 + __id($s1)]) - sin($ang, $div, v[1 + __id($s1)])
    v[1 + __id($d)] = sin($ang, $div, v[0 + __id($s1)]) + cos($ang, $div, v[1 + __id($s1)])

}

//回転(定数)
__fn V2_rotateFromConst $d $x $y $ang $div {
    v[0 + __id($d)] = cos($ang, $div, $x) - sin($ang, $div, $y)
    v[1 + __id($d)] = sin($ang, $div, $x) + cos($ang, $div, $y)

}

//回転(sin,cosを変数で指定)
__fn V2_rotateFromTrigon $d $s1 $cs $div {
    v[0 + __id($d)] = muldiv(v[0 + __id($s1)], v[0 + $cs], $div) - muldiv(v[1 + __id($s1)], v[1 + $cs], $div)
    v[1 + __id($d)] = muldiv(v[0 + __id($s1)], v[1 + $cs], $div) + muldiv(v[1 + __id($s1)], v[0 + $cs], $div)

}

//cosとsinを取得する
__fn V2_getCosSin $d $ang $div $mul {
    v[0 + __id($d)] = cos($ang, $div, $mul)
    v[1 + __id($d)] = sin($ang, $div, $mul)

}

//周速度を取得する
__fn V2_getCircumSpeed $d $rad $ang $unit {
    v[__id($d)] = muldiv($rad * $ang, 2 * 314, $unit * 100)
}

//muldiv
__fn V2_muldiv $d $s1 $mul $div {
    __loop 2 $i {
        v[$i + __id($d)] = muldiv(v[$i + __id($s1)], $mul, $div)

    }

}

__fn V2_addMuldiv $d $s1 $s2 $mul $div {
    __loop 2 $i {
        v[$i + __id($d)] = v[$i + __id($s1)] + muldiv(v[$i + __id($s2)], $mul, $div)

    }

}

__fn V2_asAddMuldiv $d $s1 $mul $div {
    __loop 2 $i {
        v[$i + __id($d)] += muldiv(v[$i + __id($s1)], $mul, $div)

    }

}

//lerp
__fn V2_lerp $d $s1 $s2 $time $unit {
    __loop 2 $i {
        v[$i + __id($d)] = lerp(v[$i + __id($s1)], v[$i + __id($s2)], $time, $unit)
    }

}

//clamp
__fn V2_clampPointInsideRect $d $s1 $s2 {
    v[0 + __id($d)] = clamp(v[0 + __id($d)], v[0 + __id($s1)], v[0 + __id($s2)])
    v[1 + __id($d)] = clamp(v[1 + __id($d)], v[1 + __id($s1)], v[1 + __id($s2)])

}

__fn V2_clampPointInsideRect2 $d $left $top $right $bottom {
    v[0 + __id($d)] = clamp(v[0 + __id($d)], $left, $right)
    v[1 + __id($d)] = clamp(v[1 + __id($d)],  $top, $bottom)

}

//ブロックを渡して二次元座標を使った計算を行う
//返って記述量が増える
__fn V2_math $_block $_def {
    __loop 2 $i {
        $_def
        $_block

    }

}


//以下の関数では一時変数を使用している

//ローカル座標を取得する
//$s1:点 $s2:原点
__fn V2_getLocal $d $s1 $s2 $ang $div {
    __loop 2 $i {
        v[$i + __id(localA)] = v[$i + __id($s1)] - v[$i + __id($s2)]

    }

    v[0 + __id($d)] = cos(-($ang), $div, v[0 + __id(localA)]) - sin(-($ang), $div, v[1 + __id(localA)])
    v[1 + __id($d)] = sin(-($ang), $div, v[0 + __id(localA)]) + cos(-($ang), $div, v[1 + __id(localA)])

}

//ワールド座標を取得する
//$s1:点 $s2:原点
__fn V2_getWorld $d $s1 $s2 $ang $div {
    v[0 + __id(localA)] = cos($ang, $div, v[0 + __id($s1)]) - sin($ang, $div, v[1 + __id($s1)])
    v[1 + __id(localA)] = sin($ang, $div, v[0 + __id($s1)]) + cos($ang, $div, v[1 + __id($s1)])

    __loop 2 $i {
        v[$i + __id($d)] = v[$i + __id(localA)] + v[$i + __id($s2)]

    }

}


//速度を制限する
//$magがゼロだとゼロ除算になる
__fn V2_clampMag $d $max {
    localA = v[0 + __id($d)] * v[0 + __id($d)] + v[1 + __id($d)] * v[1 + __id($d)]

    @if `localA > ($max) * ($max) bl {
        localA = sqrt(localA, 1)

        __loop 2 $i {
            v[$i + __id($d)] = divmul(v[$i + __id($d)], localA, $max)
            
        }

    }

}

//id番号で指定する
__fn V2_clampMagByID $id $max {
    localA = v[0 + $id] * v[0 + $id] + v[1 + $id] * v[1 + $id]

    @if `localA > ($max) * ($max) bl {
        localA = sqrt(localA, 1)

        __loop 2 $i {
            v[$i + $id] = divmul(v[$i + $id], localA, $max)
            
        }

    }

}

//点の位置が同じ場合、ブロック内の処理を実行する
__fn V2_ifEqual $s1 $s2 $hit {
    @if `v[0 + __id($s1)] == v[0 + __id($s2)] && v[1 + __id($s1)] == v[1 + __id($s2)] $hit

}

//矩形同士の衝突判定を行う。境界を含む
__fn V2_ifRectOverlap $lt1 $rb1 $lt2 $rb2 $ex $hit $else {
    $lx1 = v[0 + __id($lt1)] - $ex
    $ly1 = v[1 + __id($lt1)] - $ex
    $rx1 = v[0 + __id($rb1)] + $ex
    $ry1 = v[1 + __id($rb1)] + $ex
    $lx2 = v[0 + __id($lt2)]
    $ly2 = v[1 + __id($lt2)]
    $rx2 = v[0 + __id($rb2)]
    $ry2 = v[1 + __id($rb2)]

    @if `$lx2 <= $rx1 && $lx1 <= $rx2 && $ly2 <= $ry1 && $ly1 <= $ry2 bl {
        $hit

    } .else bl {
        $else

    }

}

//ltrbで指定し、最大値や最小値は必要ない。範囲を拡張できる。
__fn V2_ifRectOverlap_ex $lt1 $rb1 $lt2 $rb2 $ex $hit $else {
    $lx1 = v[0 + __id($lt1)]
    $ly1 = v[1 + __id($lt1)]
    $rx1 = v[0 + __id($rb1)]
    $ry1 = v[1 + __id($rb1)]
    $lx2 = v[0 + __id($lt2)]
    $ly2 = v[1 + __id($lt2)]
    $rx2 = v[0 + __id($rb2)]
    $ry2 = v[1 + __id($rb2)]

    @if `abs(($lx2 + $rx2) - ($lx1 + $rx1)) / 2 <= (abs($rx1 - $lx1) + abs($rx2 - $lx2)) / 2 + $ex &&
         abs(($ly2 + $ry2) - ($ly1 + $ry1)) / 2 <= (abs($ry1 - $ly1) + abs($ry2 - $ly2)) / 2 + $ex bl {
        $hit

    } .else bl {
        $else

    }

}
