--# RoundedRect
-- A cheap rounded rect: one mesh and one shader, built once and restyled on
-- every call rather than rebuilt. The original version of this shader mixed
-- fillColor and strokeColor backwards, so the interior painted as the stroke
-- and the border painted as the fill; the mix() arguments below are swapped
-- to fix that.

RoundedRectVertexShader = [[
precision highp float;
uniform mat4 modelViewProjection;
attribute vec4 position;
attribute vec2 texCoord;
varying highp vec2 vTexCoord;
void main() {
vTexCoord = texCoord;
gl_Position = modelViewProjection * position;
}
]]

RoundedRectFragmentShader = [[
precision highp float;
uniform lowp vec4 fillColor;
uniform lowp vec4 strokeColor;
uniform vec2 rectSize;
uniform float cornerRadius;
uniform float strokeWidth;
uniform float edgeSoftness;
varying highp vec2 vTexCoord;
float sdRoundedRect(vec2 p, vec2 halfSize, float r) {
vec2 q = abs(p) - (halfSize - vec2(r));
return length(max(q, vec2(0.0))) + min(max(q.x, q.y), 0.0) - r;
}
void main() {
vec2 halfSize = rectSize * 0.5;
vec2 p = (vTexCoord - 0.5) * rectSize;
float d = sdRoundedRect(p, halfSize, cornerRadius);
float aa = max(edgeSoftness, 0.75);
float shapeAlpha = 1.0 - smoothstep(0.0, aa, d);
// 0 in the deep interior, 1 once within strokeWidth of the edge
float towardEdge = smoothstep(-strokeWidth - aa, -strokeWidth + aa, d);
lowp vec4 c = mix(fillColor, strokeColor, towardEdge);
gl_FragColor = vec4(c.rgb, c.a * shapeAlpha);
}
]]

local sharedMesh = nil

function roundedRectMesh()
  if sharedMesh then return sharedMesh end
  sharedMesh = mesh()
  local rect = sharedMesh:addRect(0, 0, 1, 1)
  sharedMesh:setRectTex(rect, 0, 0, 1, 1)
  sharedMesh.shader = shader(RoundedRectVertexShader, RoundedRectFragmentShader)
  return sharedMesh
end

function drawRoundedRect(x, y, w, h, radius, fillCol, strokeCol, strokeW)
  local m = roundedRectMesh()
  m.shader.fillColor = fillCol
  m.shader.strokeColor = strokeCol or color(0, 0, 0, 0)
  m.shader.rectSize = vec2(w, h)
  m.shader.cornerRadius = radius or 0
  m.shader.strokeWidth = strokeW or 0
  m.shader.edgeSoftness = 1.0
  pushMatrix()
  translate(x + w * 0.5, y + h * 0.5)
  scale(w, h)
  m:draw()
  popMatrix()
end
