garrysmod icon indicating copy to clipboard operation
garrysmod copied to clipboard

Add draw.ComplexRoundedBox

Open alexsnowrun opened this issue 2 years ago • 5 comments

Description

Draws a rounded rectangle. This function allows you to set a specific rounding radius for each corner of a rectangle.

Arguments

  1. number x The x coordinate of the top left of the rectangle.
  2. number y The y coordinate of the top left of the rectangle.
  3. number width The width of the rectangle.
  4. number height The height of the rectangle.
  5. table color The color to fill the rectangle with.
  6. number roundTopLeft = 0 Rounding radius for top left corner.
  7. number roundTopRight = 0 Rounding radius for top right corner.
  8. number roundBottomLeft = 0 Rounding radius for bottom left corner.
  9. number roundBottomRight = 0 Rounding radius for bottom right corner.

Demo

Demo gif

I hope this feature will be useful for UI coders.

alexsnowrun avatar Apr 06 '22 19:04 alexsnowrun

Just support nil for bordersize in RoundedBoxEx. No need for more aliases.

Kefta avatar Apr 06 '22 21:04 Kefta

Just support nil for bordersize in RoundedBoxEx. No need for more aliases.

Do you mean something like this?

function RoundedBoxEx( bordersize, x, y, w, h, color, tl, tr, bl, br )

	surface.SetDrawColor( color.r, color.g, color.b, color.a )

	if bordersize then
		bordersize = math.min( math.Round( bordersize ), math.floor( w * 0.5 ), math.floor( h * 0.5 ) )
		tl = tl and bordersize or 0
		tr = tr and bordersize or 0
		bl = bl and bordersize or 0
		br = br and bordersize or 0
	else
		local half_w, half_h = math.floor( w * 0.5 ), math.floor( h * 0.5 )
		tl = tl and math.min( math.Round( tl ), half_w, half_h ) or 0
		tr = tr and math.min( math.Round( tr ), half_w, half_h ) or 0
		bl = bl and math.min( math.Round( bl ), half_w, half_h ) or 0
		br = br and math.min( math.Round( br ), half_w, half_h ) or 0
		
		bordersize = math.max( tl, tr, br, bl )
	end

	-- Do not waste performance if they don't want rounded corners
	if ( tl + tr + bl + br ) <= 0 then
		surface.DrawRect( x, y, w, h )
		return
	end

	x = math.Round( x )
	y = math.Round( y )
	w = math.Round( w )
	h = math.Round( h )

	surface.DrawRect( x + bl, y + tl, w - bl - tr, h - tl - br )

	local tex = tex_corner8
	if ( bordersize > 8 ) then tex = tex_corner16 end
	if ( bordersize > 16 ) then tex = tex_corner32 end
	if ( bordersize > 32 ) then tex = tex_corner64 end
	if ( bordersize > 64 ) then tex = tex_corner512 end

	surface.SetTexture( tex )

	if tl > 0 then
		surface.DrawTexturedRectUV( x, y, tl, tl, 0, 0, 1, 1 )
		surface.DrawRect( x + tl, y, w - tl - tr, tl )
	end

	if tr > 0 then
		surface.DrawTexturedRectUV( x + w - tr, y, tr, tr, 1, 0, 0, 1 )
		surface.DrawRect( x + w - tr, y + tr, tr, h - br - tr )
	end

	if bl > 0 then
		surface.DrawTexturedRectUV( x, y + h - bl, bl, bl, 0, 1, 1, 0 )
		surface.DrawRect( x, y + tl, bl, h - tl - bl )
	end

	if br > 0 then
		surface.DrawTexturedRectUV( x + w - br, y + h - br, br, br, 1, 1, 0, 0 )
		surface.DrawRect( x + bl, y + h - br, w - bl - br, br )
	end

end

alexsnowrun avatar Apr 07 '22 07:04 alexsnowrun

Yeah, use a bordersize == nil check though so false values will still error.

Kefta avatar Apr 09 '22 11:04 Kefta

Yeah, use a bordersize == nil check though so false values will still error.

false works the same as nil without additional checks. With any of these values, the function will use arguments for each corner separately.

alexsnowrun avatar Apr 11 '22 20:04 alexsnowrun

That's the point - false should error. Only numerical or nil values should operate without erroring.

Kefta avatar Apr 11 '22 21:04 Kefta

I agree with @Kefta , it could be added as an option to RoundedBoxEx in the way described.

robotboy655 avatar Apr 17 '23 17:04 robotboy655