So - I want a rectangle with rounded corners. Before I write my own nasty version with lines and quarter ellipses and such - is there some more elegant way to do it I’m missing? Or has someone perhaps already done this?

Nasty way is the only way, for now. (Or custom sprites.)

Once the image class is available you could compute them in an image. Though it would be nice to have them available as a primitive shape.

FWIW - after futzing around a bit, a rectangle with a circle on either end is close enough to a rounded rectangle for my purposes (ie. it looks good and can be an extended key).

now to figure out a better/faster way to do the math.

I did this by filling a rectangle and then drawing the edges (one by one) with the line end mode set to ROUND.

That’s a pretty good solution.

I really liked Andrew’s idea. So I wrote a function to draw them:

``````function roundRect(x, y, w, h, r)
pushStyle()
insetPos = vec2(x+r,y+r)
insetSize = vec2(w-2*r,h-2*r)

rectMode(CORNER)
rect(insetPos.x,insetPos.y,insetSize.x,insetSize.y)

if r > 0 then
smooth()
lineCapMode(ROUND)
strokeWidth(r*2)

line(insetPos.x, insetPos.y,
insetPos.x + insetSize.x, insetPos.y)
line(insetPos.x, insetPos.y,
insetPos.x, insetPos.y + insetSize.y)
line(insetPos.x, insetPos.y + insetSize.y,
insetPos.x + insetSize.x, insetPos.y + insetSize.y)
line(insetPos.x + insetSize.x, insetPos.y,
insetPos.x + insetSize.x, insetPos.y + insetSize.y)
end
popStyle()
end
``````

``````-- Main
function setup()
end

function draw()
-- This sets the background color to black
background(0, 0, 0)

-- Stroke and fill must be the same
stroke(255,0,0)
fill(255,0,0)

end
``````

Cute! It suffers the “balls!” issue a bit, but that’s me being nitpicky - this is, dare I say, elegant.

It does, we hope to resolve the ‘balls’ issue on the line shader itself.

It suffers the what issue a bit?

Hah. BALLS.

\cleans out ears\

Nope, still not any the wiser. Will it become obvious if I run that code?

Thin smooth() lines with ROUND end caps look like they have balls on either end. It’s due to the way the line shader draws lines (the caps are something like half a pixel bigger than the line itself, or using a different antialiasing width, to be determined).

Ah, now I understand. Thanks.

In Codea 1.3 you can retrieve the style information from all style functions by calling without arguments. So I’ve updated this code to correctly use only the fill colour, as a normal rect would.

It could even be updated to respect the current rectMode.

``````    function roundRect(x, y, w, h, r)
pushStyle()
insetPos = vec2(x+r,y+r)
insetSize = vec2(w-2*r,h-2*r)

rectMode(CORNER)
rect(insetPos.x,insetPos.y,insetSize.x,insetSize.y)

r,g,b,a = fill()
stroke(r,g,b,a)

if r > 0 then
smooth()
lineCapMode(ROUND)
strokeWidth(r*2)

line(insetPos.x, insetPos.y,
insetPos.x + insetSize.x, insetPos.y)
line(insetPos.x, insetPos.y,
insetPos.x, insetPos.y + insetSize.y)
line(insetPos.x, insetPos.y + insetSize.y,
insetPos.x + insetSize.x, insetPos.y + insetSize.y)
line(insetPos.x + insetSize.x, insetPos.y,
insetPos.x + insetSize.x, insetPos.y + insetSize.y)
end
popStyle()
end
``````

``````    -- Main
function setup()
end

function draw()
-- This sets the background color to black
background(0, 0, 0)

-- Set the fill color
fill(255,0,0)

end
``````

Here’s my version of it (I had to rewire `clip()` for this)

``````_clip = clip
function clip(x, y, w, h)
if x ~= nil then
local m = modelMatrix()
x = x * m[1] + m[13]
y = y * m[6] + m[14]
w = w * m[1]
h = h * m[6]
_clip(x, y, w, h)
else
_clip()
end
end

function roundRect(x, y, w, h, r)
r = r or math.min(w, h) / 8
pushStyle()
noSmooth()
if rectMode() == CORNERS then
w = w - x
h = h - y
elseif rectMode() == CENTER then
x = x - w / 2
y = y - h / 2
x = x - w
y = y - h
w = w * 2
h = h * 2
end
if r > math.min(w, h) / 2 then
r = math.min(w, h) / 2
end
rectMode(CORNER)
pushMatrix()
translate(x, y)
clip(r, 0, w - r * 2, h)
rect(0, 0, w, h)
clip(0, r, w, h - r * 2)
rect(0, 0, w, h)
r = r + .25
if strokeWidth() + .25 > r then
fill(stroke())
noStroke()
end
clip(0, 0, r + 1, r + 1)
ellipse(r, r, r + 1)
clip(w - r - 1, 0, r + 2, r + 1)
ellipse(w - r, r, r + 1)
clip(0, h - r - 1, r + 1, r + 2)
ellipse(r, h - r, r + 1)
clip(w - r - 1, h - r - 1, r + 2, r + 2)
ellipse(w - r, h - r, r + 1)
clip()
popMatrix()
popStyle()
end

function draw()
rectMode(CORNER)
fill(255, 0, 0, 255)
stroke(255, 255, 255, 255)
strokeWidth(20)
roundRect(10, 10, WIDTH / 2 - 20, HEIGHT / 2 - 20, 100)
fill(0, 255, 0, 255)
stroke(255, 127, 0, 255)
strokeWidth(55)
rectMode(CORNERS)
roundRect(WIDTH / 2 + 10, 10, WIDTH - 10, HEIGHT / 2 - 10, 50)
fill(0, 0, 255, 255)
noStroke()
rectMode(CENTER)
roundRect(WIDTH / 4, HEIGHT * .75, WIDTH / 2 - 20, HEIGHT / 2 - 20, 75)
strokeWidth(10)
stroke(127, 0, 127, 255)
noFill()