/******************************************************************************\ Ring widget event function. \******************************************************************************/ static int ring_event(i_widget_t *widget, i_event_t event) { float radius; /* Calculate mouse radius for mouse events */ if (event == I_EV_MOUSE_MOVE || event == I_EV_MOUSE_DOWN) radius = C_vec2_len(C_vec2_sub(i_mouse, screen_origin)); switch (event) { case I_EV_CONFIGURE: R_sprite_cleanup(&ring_sprite); R_sprite_init(&ring_sprite, ring_texture); ring_widget.size = ring_sprite.size; I_widget_propagate(widget, I_EV_CONFIGURE); position_and_pack(); return FALSE; case I_EV_MOVED: ring_sprite.origin = ring_widget.origin; break; case I_EV_MOUSE_OUT: I_close_ring(); break; case I_EV_MOUSE_MOVE: if (radius > RING_OUTER_RADIUS) I_close_ring(); else detail_hover(); break; case I_EV_MOUSE_DOWN: if (i_mouse_button != SDL_BUTTON_LEFT) I_close_ring(); if (radius <= RING_INNER_RADIUS) { I_close_ring(); return FALSE; } break; case I_EV_CLEANUP: R_sprite_cleanup(&ring_sprite); break; case I_EV_RENDER: ring_sprite.modulate.a = ring_widget.fade; R_sprite_render(&ring_sprite); detail_update(); break; default: break; } return TRUE; }
/******************************************************************************\ Move a widget and all of its children. Will not generate move events if the origin did not change. \******************************************************************************/ void I_widget_move(i_widget_t *widget, c_vec2_t origin) { i_widget_t *child; c_vec2_t diff; diff = C_vec2_sub(origin, widget->origin); if (!diff.x && !diff.y) return; widget->origin = origin; child = widget->child; while (child) { I_widget_move(child, C_vec2_add(child->origin, diff)); child = child->next; } if (widget->event_func) widget->event_func(widget, I_EV_MOVED); }
/******************************************************************************\ Position a ring on its world origin. \******************************************************************************/ static void position_and_pack(void) { c_vec2_t origin, size; float angle; int i, j; /* Position the ring */ size = C_vec2_scalef(ring_widget.size, 0.5f); I_widget_move(&ring_widget, C_vec2_sub(screen_origin, size)); /* Pack the visible buttons */ for (j = i = 0; i < I_RING_ICONS; i++) { if (!button_widgets[i].widget.shown) continue; angle = 2.f * C_PI * ((float)j++ / buttons - 0.25f); origin = C_vec2_scalef(C_vec2(cosf(angle), sinf(angle)), RING_INNER_RADIUS + RING_ICON_SIZE / 2.f); origin = C_vec2_add(screen_origin, origin); origin = C_vec2(origin.x - RING_ICON_SIZE / 2.f, origin.y - RING_ICON_SIZE / 2.f); I_widget_move(&button_widgets[i].widget, origin); } }