Код: Избери всички
typedef struct {
v2_t position, size;
int handle;
} uiRect_t;
typedef enum {
UIMBS_NONE,
UIMBS_DOWN = 1 << 0,
UIMBS_UP = 1 << 1,
} uiMouseButtonState;
static uiMouseButtonState ui_mouseButton;
// a stack of rects to check for hits
#define MAX_RECTS 256
static int ui_numRects;
static uiRect_t ui_rects[MAX_RECTS];
// this widget is rolled over
static int ui_hotWidget;
// this widget is usually pressed but not released yet
static int ui_activeWidget;
static bool_t UI_CursorInRect( v2_t position, v2_t size ) {
v2_t mouse = v2c2( SYS_MousePos() );
return mouse.x >= position.x &&
mouse.y >= position.y &&
mouse.x < position.x + size.x &&
mouse.y < position.y + size.y;
}
// this callback might be called multiple times inside a single frame
bool_t UI_OnMouseButton( bool_t down ) {
if ( down ) {
ui_mouseButton |= UIMBS_DOWN;
} else {
ui_mouseButton |= UIMBS_UP;
}
return ( ui_hotWidget || ui_activeWidget );
}
void UI_TestHits( void ) {
if ( ui_activeWidget ) {
int i;
// check if <active> widget is still present on screen
for ( i = 0; i < ui_numRects; i++ ) {
if ( ui_rects[i].handle == ui_activeWidget ) {
break;
}
}
// <active> is no longer drawn/tested
if ( i == ui_numRects ) {
ui_activeWidget = 0;
}
}
// <hot> widgets are obtained each frame
ui_hotWidget = 0;
#define BUTTON_RELEASED() ((ui_mouseButton & UIMBS_UP)||ui_mouseButton==UIMBS_NONE)
// go back to front in the rectangles stack and check for hits
for ( int i = ui_numRects - 1; i >= 0; i-- ) {
uiRect_t *r = &ui_rects[i];
if ( UI_CursorInRect( r->position, r->size ) ) {
if ( BUTTON_RELEASED() ) {
// there is only one hot widget
ui_activeWidget = 0;
ui_hotWidget = r->handle;
} else if ( ! ui_activeWidget ) {
ui_activeWidget = r->handle;
}
break;
}
}
if ( BUTTON_RELEASED() ) {
ui_activeWidget = 0;
}
// clear rects stack
ui_numRects = 0;
// handle mouse buttons specially
if ( ui_mouseButton & UIMBS_UP ) {
ui_mouseButton = UIMBS_NONE;
}
}
static void UI_PushRect( v2_t position, v2_t size, int handle ) {
uiRect_t *r;
if ( ui_numRects == MAX_RECTS ) {
CON_Printf( "UI_PushRect: out of widgets\n" );
return;
}
r = &ui_rects[ui_numRects];
r->position = position;
r->size = size;
r->handle = handle;
ui_numRects++;
}
typedef enum {
BR_IDLE,
BR_HOT,
BR_ACTIVE,
BR_RELEASED,
BR_NUM_RESULTS,
} buttonResult_t;
buttonResult_t UI_ClickRect_wg( v2_t position, v2_t size, int handle ) {
UI_PushRect( position, size, handle );
buttonResult_t res = BR_IDLE;
if ( ui_activeWidget == handle ) {
if ( ( ui_mouseButton & UIMBS_UP ) && UI_CursorInRect( position, size ) ) {
res = BR_RELEASED;
} else {
res = BR_ACTIVE;
}
} else if ( handle == ui_hotWidget ) {
res = BR_HOT;
}
return res;
}