Nine Patch


Tweet graphics gui monkey-x code-archives
(Posted 5 months ago) RonTek

NinePatch is a class I wrote sometime last year to deal with buttons for a game I was working on at the time. It takes a base image and stretches it selectively to make scaling artifacts less apparent. (This version of NinePatch doesn't have tiling capabilities.) Border thicknesses can be specified independently, in case you wish the center graphic to have higher resolution than the edges.

Author: Nobuyuki

' Some notes about this routine:
' in HTML5, if you use SetColor() on a NinePatch in Firefox, it changes how the texture is scaled.
' as a result, the pieces of the NinePatch will not fit together seamlessly.  You will see seams.
' This doesn't happen on Android or GLFW.  I haven't tested it on any other platforms.  Sorry..
' Let me know if you get seams on Chrome, ios, or anything else, I'm interested!
' -Nobuyuki  (nobu[at]subsoap.com),  05 September 2012.

Import mojo 

Class NinePatch
    Field img:Image
    Field x:Int, y:Int,w:Int, h:Int 
    Field borderwidth:Int, borderheight:Int

    Method New(x:Int, y:Int, w:Int, h:Int, img:Image=Null, borderwidth:Int=0, borderheight:Int=0)
        Self.img = img 
        Self.x = x; Self.y = y; Self.w = w; Self.h = h

        If img = Null Then Return 
        If borderwidth = 0 Then Self.borderwidth = Ceil(img.Width / 3) Else Self.borderwidth = borderwidth 
        If borderheight = 0 Then Self.borderheight = Ceil(img.Height / 3) Else Self.borderheight = borderheight 
    End Method

    Method Draw:Void(frame:Int=0, xOffset:Int=0, yOffset:Int=0,wOffset:Int=0, hOffset:Int=0)
        DrawNinePatch(img,x+xOffset,y+yOffset,w+wOffset,h+hOffset, Self.borderwidth, Self.borderheight, frame)  
    End Method

    Method Set:Void(x:Int, y:Int, w:Int, h:Int)
        Self.x = x; Self.y = y; Self.w = w; Self.h = h      
    End Method

    'Draw separately from instance
    Function DrawNinePatch:Void(img:Image, x:Int, y:Int, w:Int, h:Int, borderwidth:Int=0, borderheight:Int=0, frame:Int=0)
        If borderwidth = 0 Then borderwidth = Floor(img.Width / 3) 
        If borderheight = 0 Then borderheight = Floor(img.Height / 3)

        'Draw the corners.
        DrawImageRect(img,x,y,0,0,borderwidth,borderheight,frame)
        DrawImageRect(img,x+w-borderwidth,y+h-borderheight,img.Width-borderwidth,img.Height-borderheight,borderwidth,borderheight,frame)
        DrawImageRect(img,x+w - borderwidth,y,img.Width-borderwidth,0,borderwidth,borderheight,frame)
        DrawImageRect(img,x,y+h - borderheight,0,img.Height-borderheight,borderwidth,borderheight,frame)

        'Draw the borders.
        Local wRatio:Float = (w - borderwidth * 2.0) / (img.Width - borderwidth * 2.0)  'Width stretch ratio for top/bottom
        Local hRatio:Float = (h - borderheight * 2.0) / (img.Height - borderheight * 2.0)  'Height stretch ratio for l/r

        if wRatio <> 0 
            DrawImageRect(img,x+borderwidth,y, borderwidth, 0, img.Width - borderwidth*2, borderheight,0,wRatio,1,frame) 'top
            DrawImageRect(img,x+borderwidth,y+h-borderheight, borderwidth, img.Height-borderheight, img.Width - borderwidth*2, borderheight,0,wRatio,1,frame) 'bottom
        End if 

        if hRatio <> 0
            DrawImageRect(img,x,y + borderheight,0,borderheight, borderwidth, img.Height - borderheight*2, 0, 1, hRatio,frame) 'Left 
            DrawImageRect(img,x+w-borderwidth,y + borderheight,img.Width-borderwidth,borderheight, borderwidth, img.Height - borderheight*2, 0, 1, hRatio,frame) 'Right
        End if 

        'Draw the center.
        If hRatio <> 0 And wRatio <> 0
            DrawImageRect(img,x+borderwidth,y+borderheight, borderwidth,borderheight,img.Width - borderwidth*2, img.Height - borderheight*2,0,wRatio,hRatio,frame)
        End If
    End Function
End Class

Reply To Topic (minimum 10 characters)

Please log in to reply