Here's a way to draw a clickable up or down triangle button of arbitrary size (square shaped) using a bit of banker's rounding in Lua.
(examples: http://i.imgur.com/ESxEdYp.png )
Premise:
Drawing a rotated right isosceles triangle (like an arrow pointing up or down) on a square button of arbitrary sizing is kind of a weird thing. Height depends on width. Placement depends on height and width. Width depends on the size of the box, and rounding is always fighting against you unless you can round both up and down!
So I came up with a cute way of drawing these triangles using Banker's Rounding. (see: http://www.mushclient.com/forum/?id=7805&reply=2#reply2 ) ...
-- round normally, but when a number ends in exactly .5 round to the nearest even value.
function round_banker(x)
if x == 0 then return 0 end -- prevent returning -0
if (x + 0.5) % 2 == 0 then
return math.floor(x + 0.5)
else
return math.ceil(x - 0.5)
end
end
local midpoint = (BUTTON_WIDTH_int - 2)/2
local button_style = miniwin.rect_edge_at_all + miniwin.rect_option_fill_middle
local button_edge = miniwin.rect_edge_raised
local points = ""
if (BUTTON_IS_PRESSED_bool) then
button_edge = miniwin.rect_edge_sunken
points = string.format("%i,%i,%i,%i,%i,%i,%i,%i", BUTTON_X_POSITION_int + math.floor(midpoint) + 1,
BUTTON_Y_POSITION_int + math.ceil(BUTTON_WIDTH_int/4 + 0.5) + 2,
BUTTON_X_POSITION_int + math.floor(midpoint) - math.floor(midpoint/2) + 1,
BUTTON_Y_POSITION_int + round_banker(BUTTON_WIDTH_int/2) + 2,
BUTTON_X_POSITION_int + math.ceil(midpoint) + math.floor(midpoint/2) + 1,
BUTTON_Y_POSITION_int + round_banker(BUTTON_WIDTH_int/2) + 2,
BUTTON_X_POSITION_int + math.ceil(midpoint) + 1,
BUTTON_Y_POSITION_int + math.ceil(BUTTON_WIDTH_int/4 + 0.5) + 2 )
else
points = string.format("%i,%i,%i,%i,%i,%i,%i,%i", BUTTON_X_POSITION_int + math.floor(midpoint),
BUTTON_Y_POSITION_int + math.ceil(BUTTON_WIDTH_int/4 + 0.5) + 1,
BUTTON_X_POSITION_int + math.floor(midpoint) - math.floor(midpoint/2),
BUTTON_Y_POSITION_int + round_banker(BUTTON_WIDTH_int/2) + 1,
BUTTON_X_POSITION_int + math.ceil(midpoint) + math.floor(midpoint/2),
BUTTON_Y_POSITION_int + round_banker(BUTTON_WIDTH_int/2) + 1,
BUTTON_X_POSITION_int + math.ceil(midpoint),
BUTTON_Y_POSITION_int + math.ceil(BUTTON_WIDTH_int/4 + 0.5) + 1)
end
WindowRectOp(self.window_name, 5, BUTTON_X_POSITION_int, BUTTON_Y_POSITION_int,
BUTTON_X_POSITION_int + BUTTON_WIDTH_int, BUTTON_Y_POSITION_int + BUTTON_WIDTH_int,
button_edge, button_style)
WindowPolygon(self.window_name, points, 0x000000, miniwin.pen_solid + miniwin.pen_join_miter, 1,
0x000000, 0, true, false)
You might be wondering why I explicitly floor/ceil/banker all my numbers before stuffing them into string.format %i. The conversion behavior from float to int used by string.format is unspecified and therefore implementation and hardware dependent! ( http://www.freelists.org/post/luajit/stringformat-i-with-float-input-does-bankers-rounding,1 )
So you have to be extra careful. |