Need some advice around generating/drawing polygons

Hello all,
I’ve been working on a UI library lately, and i want my buttons to have a specific look. Rectangle based, but with beveled corners, so they look more like a wide octagon.

I was thinking of using a mesh and triangulating it, but i don’t know how to format the data for that, and was also wondering if there might be a better way to do it than that.

Thank you in advance!

@DJMoffinz - A crude way of doing it would be to make an image using rectangles. Two for a cross like image and then smaller rotated rectangles for the corners. Then use the image as a sprite. Alternatively you could save the as a png.

A mesh would be a better way of doing it and more programmable for scale and shape.

Alternatively you could make the UI in a grphics package.

Not near my iPad at mo so can’t put together a mesh for you. May get chance later.

Thanks! A mesh seems like the best way to do it for my needs, so I’ll try and figure out how those work.
Btw is “Bri” in your username short for anything?

@DJMoffinz - meanwhile, some to play with



Edit: Bri is short for Brian, Bri-G is tongue in cheek reference to Ali-G who I thought, in an odd way, was quite funny.

Here’s a demo using a mesh with a polygon where you can change its size. You can use this to make fixed size polygons.


function setup()
    w1,w2,h1,h2=50,50,50,50
    fill(255)
    x,y=WIDTH/1.5,HEIGHT/2
    tab={}    
    img=readImage(asset.builtin.Cargo_Bot.Startup_Screen)
    m=mesh()
    m.texture=img  
    xmin,xmax,ymin,ymax=9999,0,9999,0
    parameter.integer("w1",20,400,150,change)
    parameter.integer("w2",20,400,350,change)
    parameter.integer("h1",20,400,140,change)
    parameter.integer("h2",20,400,280,change)
    change(w1,w2,h1,h2)
end

function draw()
    background(0)
    m.draw(m)  
end

function change() 
    if w1>w2 and h1>h2 then return end
    tab,tab2={},{}
    xmin,xmax,ymin,ymax=9999,0,999,0
    table.insert(tab2,vec2(x+w1/2,y+h2/2))
    table.insert(tab2,vec2(x-w1/2,y+h2/2))
    table.insert(tab2,vec2(x-w2/2,y+h1/2))
    table.insert(tab2,vec2(x-w2/2,y-h1/2))
    table.insert(tab2,vec2(x-w1/2,y-h2/2))
    table.insert(tab2,vec2(x+w1/2,y-h2/2))
    table.insert(tab2,vec2(x+w2/2,y-h1/2))
    table.insert(tab2,vec2(x+w2/2,y+h1/2))   
    for z=1,#tab2 do
        calcCoords(tab2[z].x,tab2[z].y)
    end
end

function calcCoords(cx,cy)
    table.insert(tab,vec2(cx,cy))
    if cx<xmin then xmin=cx end
    if cx>xmax then xmax=cx end
    if cy<ymin then ymin=cy end
    if cy>ymax then ymax=cy end
    if #tab<3 then return end
    xwid,yhei=xmax-xmin,ymax-ymin
    tab1=triangulate(tab)
    texTab={}
    for a,b in pairs(tab1) do
        table.insert(texTab,vec2((b.x-xmin)/xwid,(b.y-ymin)/yhei))
    end  
    m.texCoords=texTab
    m.vertices=tab1 
end

@Bri_G @dave1707 Thank you both! Especially Dave for that demo program :)

@dave1707 is it possible to set the mesh texture to a colour? I would prefer that to an image.

Just create/find whatever image you want and input it at the line near the top

Img=readimage…

1 Like

gotcha. thanks again!

found out about the image function after a bit of digging, so i figure i can use that to dynamically generate solid colour fills for my mesh buttons.
one more thing, do either of you know how i can check for touches on my mesh without a whole bunch of if statements?

Here’s a modified version of my code that checks for a touch. It only does 1 button, but needs to be changed to a class to handle multiple buttons. I’ll work on that when I have time.


viewer.mode=FULLSCREEN

function setup()
    m1=mesh()
    msg=""
    
    polyButton(WIDTH/2,HEIGHT/2,180,280,60,120,m1)
    
    p=physics.body(POLYGON,tab2[1],tab2[2],tab2[3],
            tab2[4],tab2[5],tab2[6],tab2[7],tab2[8])
    p.type=STATIC
end

function draw()
    background(0)
    m1.draw(m1)  
    text(msg,WIDTH/2,HEIGHT-200) 
end

function touched(t)
    msg=""
    if t.state==BEGAN then        
        if p:testPoint(vec2(t.x,t.y)) then 
            msg="Touched"
        end
    end
end

function polyButton(x,y,w1,w2,h1,h2,m) 
    if w1>w2 and h1>h2 then return end
    fill(255)
    img=readImage(asset.builtin.Cargo_Bot.Startup_Screen)
    tab={} 
    m.texture=img
    tab,tab2={},{}
    xmin,xmax,ymin,ymax=9999,0,999,0
    table.insert(tab2,vec2(x+w1/2,y+h2/2))
    table.insert(tab2,vec2(x-w1/2,y+h2/2))
    table.insert(tab2,vec2(x-w2/2,y+h1/2))
    table.insert(tab2,vec2(x-w2/2,y-h1/2))
    table.insert(tab2,vec2(x-w1/2,y-h2/2))
    table.insert(tab2,vec2(x+w1/2,y-h2/2))
    table.insert(tab2,vec2(x+w2/2,y-h1/2))
    table.insert(tab2,vec2(x+w2/2,y+h1/2))   
    for z=1,#tab2 do
        polyCalc(tab2[z].x,tab2[z].y,m)
    end
    
end

function polyCalc(cx,cy,m)
    table.insert(tab,vec2(cx,cy))
    if cx<xmin then xmin=cx end
    if cx>xmax then xmax=cx end
    if cy<ymin then ymin=cy end
    if cy>ymax then ymax=cy end
    if #tab<3 then return end
    xwid,yhei=xmax-xmin,ymax-ymin
    tab1=triangulate(tab)
    texTab={}
    for a,b in pairs(tab1) do
        table.insert(texTab,vec2((b.x-xmin)/xwid,(b.y-ymin)/yhei))
    end  
    m.texCoords=texTab
    m.vertices=tab1 
end

1 Like

@dave1707 i can adapt it into a class, dw
i’ll take things from here but thank you so much!

Here’s a class version for anyone else that can use this.


viewer.mode=FULLSCREEN

function setup()
    fill(255)
    msg=""
    
    img1=readImage(asset.builtin.Cargo_Bot.Startup_Screen)
    img2=readImage(asset.builtin.Cargo_Bot.Starry_Background)
    
    b1=polyButton(WIDTH/2,HEIGHT/2,180,280,20,150,img1,"BUTTON 1")
    b2=polyButton(WIDTH/2,HEIGHT/4,180,280,60,120,img2,"BUTTON 2")    
end

function draw()
    background(0)
    b1:draw() 
    b2:draw() 
    text(msg,WIDTH/2,HEIGHT-200)
end

function touched(t)
    msg=""
    if t.state==BEGAN then   
        b1:touched(t)
        b2:touched(t)
    end
end

polyButton=class()

function polyButton:init(x,y,w1,w2,h1,h2,img,txt)
    self.m=mesh()
    self.x=x
    self.y=y
    self.w1=w1  -- small width
    self.w2=w2  -- large width
    self.h1=h1  -- small height
    self.h2=h2  -- large height
    self.tab1={}
    self.tab2={}
    self.tab3={}
    self.img=img
    self.m.texture=self.img
    self.xmin=9999
    self.xmax=0
    self.ymin=9999
    self.ymax=0
    self.text=txt
    polyButton:button(self)
end

function polyButton:draw()
    self.m:draw()
    text(self.text,self.x,self.y)
end

function polyButton:touched(t)
    if t.state==BEGAN then        
        if self.p:testPoint(vec2(t.x,t.y)) then 
            msg=self.text
        end
    end
end

function polyButton:button(self)
    if self.w1>self.w2 and self.h1>self.h2 then return end
    table.insert(self.tab3,vec2(self.x+self.w1/2,self.y+self.h2/2))
    table.insert(self.tab3,vec2(self.x-self.w1/2,self.y+self.h2/2))
    table.insert(self.tab3,vec2(self.x-self.w2/2,self.y+self.h1/2))
    table.insert(self.tab3,vec2(self.x-self.w2/2,self.y-self.h1/2))
    table.insert(self.tab3,vec2(self.x-self.w1/2,self.y-self.h2/2))
    table.insert(self.tab3,vec2(self.x+self.w1/2,self.y-self.h2/2))
    table.insert(self.tab3,vec2(self.x+self.w2/2,self.y-self.h1/2))
    table.insert(self.tab3,vec2(self.x+self.w2/2,self.y+self.h1/2))   
    for z=1,#self.tab3 do
        polyButton:calc(self,self.tab3[z].x,self.tab3[z].y)
    end
    self.p=physics.body(POLYGON,self.tab3[1],self.tab3[2],self.tab3[3],
    self.tab3[4],self.tab3[5],self.tab3[6],self.tab3[7],self.tab3[8])
    self.p.type=STATIC
end


function polyButton:calc(self,cx,cy)
    table.insert(self.tab1,vec2(cx,cy))
    if cx<self.xmin then self.xmin=cx end
    if cx>self.xmax then self.xmax=cx end
    if cy<self.ymin then self.ymin=cy end
    if cy>self.ymax then self.ymax=cy end
    if #self.tab1<3 then return end
    self.xwid,self.yhei=self.xmax-self.xmin,self.ymax-self.ymin
    self.tab2=triangulate(self.tab1)
    self.texTab={}
    for a,b in pairs(self.tab2) do
        table.insert(self.texTab,vec2((b.x-self.xmin)/self.xwid,(b.y-self.ymin)/self.yhei))
    end  
    self.m.texCoords=self.texTab
    self.m.vertices=self.tab2 
end