/* Copyright (C) 2011 ezQuake team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /** HUD Editor module Initial concept code jogihoogi, rewritten by Cokeman, Feb 2007 */ #include "../plugin.h" #include "ezquakeisms.h" //#include "qsound.h" //#include "utils.h" //#include "menu.h" //#include "keys.h" //#include "Ctrl.h" //#include "ez_controls.h" //#include "ez_button.h" //#include "ez_label.h" //#include "ez_scrollbar.h" //#include "ez_scrollpane.h" //#include "ez_slider.h" //#include "ez_listview.h" //#include "ez_window.h" #include "hud.h" #include "hud_editor.h" extern unsigned int keydown[]; #define isShiftDown() (keydown[K_LSHIFT]||keydown[K_RSHIFT]) #define isCtrlDown() (keydown[K_LCTRL]||keydown[K_RCTRL]) #define isAltDown() (keydown[K_LALT]||keydown[K_RALT]) #ifdef HAXX ez_tree_t help_control_tree; #endif extern mpic_t *scr_cursor_icon; // cl_screen.c extern cvar_t *hud_planmode; // hud_common.c mpic_t *hud_editor_move_icon = NULL; mpic_t *hud_editor_resize_icon = NULL; mpic_t *hud_editor_align_icon = NULL; mpic_t *hud_editor_place_icon = NULL; cvar_t *hud_editor_allowresize;// = {"hud_editor_allowresize", "1"}; // Show resize handles / allow resizing. cvar_t *hud_editor_allowmove;// = {"hud_editor_allowmove", "1"}; // Allow moving... cvar_t *hud_editor_allowplace;// = {"hud_editor_allowplace", "1"}; // Allow placing HUDs. cvar_t *hud_editor_allowalign;// = {"hud_editor_allowalign", "1"}; // Allow aligning HUDs. extern hud_t *hud_huds; // The list of HUDs.. hud_t *selected_hud = NULL; // The currently selected HUD. qbool hud_editor = false; // If we're in HUD editor mode or not. hud_editor_mode_t hud_editor_mode = hud_editmode_off; // The current mode the HUD editor is in. hud_editor_mode_t hud_editor_prevmode = hud_editmode_off; // The previous mode the HUD editor was in. qbool hud_editor_showhelp = false; // Show the help plaque or not? qbool hud_editor_showoutlines = true; // Show guidelines around the HUD elements. float hud_mouse_x; // The screen coordinates of the mouse cursor. float hud_mouse_y; // Macros for what mouse buttons are clicked. #define MOUSEDOWN ( keydown[K_MOUSE1] || keydown[K_MOUSE2]|| keydown[K_MOUSE3]) #define MOUSEDOWN_1_2 ( keydown[K_MOUSE1] && keydown[K_MOUSE2]) #define MOUSEDOWN_1_3 ( keydown[K_MOUSE1] && keydown[K_MOUSE3]) #define MOUSEDOWN_1_2_3 ( keydown[K_MOUSE1] && keydown[K_MOUSE2] && keydown[K_MOUSE3]) #define MOUSEDOWN_1_ONLY ( keydown[K_MOUSE1] && !keydown[K_MOUSE2] && !keydown[K_MOUSE3]) #define MOUSEDOWN_2_ONLY (!keydown[K_MOUSE1] && keydown[K_MOUSE2] && !keydown[K_MOUSE3]) #define MOUSEDOWN_3_ONLY (!keydown[K_MOUSE1] && !keydown[K_MOUSE2] && keydown[K_MOUSE3]) #define MOUSEDOWN_1_2_ONLY ( keydown[K_MOUSE1] && keydown[K_MOUSE2] && !keydown[K_MOUSE3]) #define MOUSEDOWN_1_3_ONLY ( keydown[K_MOUSE1] && !keydown[K_MOUSE2] && keydown[K_MOUSE3]) #define MOUSEDOWN_2_3_ONLY (!keydown[K_MOUSE1] && keydown[K_MOUSE2] && keydown[K_MOUSE3]) #define MOUSEDOWN_NONE (!keydown[K_MOUSE1] && !keydown[K_MOUSE2] && !keydown[K_MOUSE3]) #define HUD_CENTER_X(h) ((h)->lx + (h)->lw / 2) // Gets the coordinates for the center point of the specified hud. #define HUD_CENTER_Y(h) ((h)->ly + (h)->lh / 2) // // HUD align polygons. // #define HUD_ALIGN_POLYCOUNT_CORNER 5 #define HUD_ALIGN_POLYCOUNT_EDGE 4 #define HUD_ALIGN_POLYCOUNT_CENTER 8 #define HUD_ALIGN_POLYCOUNT_CONSOLE 4 vec3_t *hud_align_current_poly = NULL; // The current alignment polygon when in alignment mode. int hud_align_current_polycount = 0; // Number of vertices in teh polygon. vec3_t hud_align_topright_poly[HUD_ALIGN_POLYCOUNT_CORNER]; vec3_t hud_align_top_poly[HUD_ALIGN_POLYCOUNT_EDGE]; vec3_t hud_align_topleft_poly[HUD_ALIGN_POLYCOUNT_CORNER]; vec3_t hud_align_left_poly[HUD_ALIGN_POLYCOUNT_EDGE]; vec3_t hud_align_bottomleft_poly[HUD_ALIGN_POLYCOUNT_CORNER]; vec3_t hud_align_bottom_poly[HUD_ALIGN_POLYCOUNT_EDGE]; vec3_t hud_align_bottomright_poly[HUD_ALIGN_POLYCOUNT_CORNER]; vec3_t hud_align_right_poly[HUD_ALIGN_POLYCOUNT_EDGE]; vec3_t hud_align_center_poly[HUD_ALIGN_POLYCOUNT_CENTER]; vec3_t hud_align_consoleleft_poly[HUD_ALIGN_POLYCOUNT_CONSOLE]; vec3_t hud_align_console_poly[HUD_ALIGN_POLYCOUNT_CONSOLE]; vec3_t hud_align_consoleright_poly[HUD_ALIGN_POLYCOUNT_CONSOLE]; typedef enum hud_alignmode_s { hud_align_center, hud_align_top, hud_align_topleft, hud_align_left, hud_align_bottomleft, hud_align_bottom, hud_align_bottomright, hud_align_right, hud_align_topright, hud_align_consoleleft, hud_align_consoleright, hud_align_console // Not including before/after for now. } hud_alignmode_t; hud_alignmode_t hud_alignmode = hud_align_center; // Possible positions for a grep handle. typedef enum hud_greppos_s { pos_visible, // On screen. pos_top, pos_left, pos_bottom, pos_right } hud_greppos_t; // A Grep handle for when a HUD goes offscreen. typedef struct hud_grephandle_s { hud_t *hud; // HUD associated with this grep handle. int x; // The position in screen coordinates for the grephandle. int y; int width; int height; qbool highlighted; // Should this grephandle be drawn highlighted? hud_greppos_t pos; // The offscreen position of the HUD associated with this handle. struct hud_grephandle_s *next; struct hud_grephandle_s *previous; } hud_grephandle_t; hud_grephandle_t *hud_greps = NULL; // The list of "grep handles" that are shown if a HUD element is moved offscreen. hud_grephandle_t *hud_hoverlist = NULL; // The list of HUDs the mouse is hovering. int hud_hoverlist_count = 0; // The number of hovered HUDs... qbool hud_hoverlist_pos_is_set = false; // Has the coordinates been set for the hoverlist yet? float hud_hoverlist_x; // The x position of the hover list. float hud_hoverlist_y; // The y position of the hover list. hud_grephandle_t hud_containers[MAX_HUD_ELEMENTS]; // List of HUDs which have been hovered. // // Adds a new HUD to the list of HUDs that are being hovered. // static void HUD_Editor_AddHoverHud(hud_grephandle_t *hud_container) { // Nothing to add. if(!hud_container) { return; } hud_container->next = hud_hoverlist; if(hud_hoverlist) { hud_hoverlist->previous = hud_container; } hud_hoverlist = hud_container; hud_hoverlist_count++; } // // Associates ("Creates") a HUD with a HUD container. // static hud_grephandle_t *HUD_Editor_CreateHoverHud(hud_t *hud) { static int i = 0; int j = 0; if(i >= MAX_HUD_ELEMENTS - 1) { return NULL; } // Check if the HUD already exists and use that one if that's the case... for(j = 0; j < MAX_HUD_ELEMENTS && hud_containers[j].hud; j++) { if(hud_containers[j].hud == hud) { hud_containers[j].next = NULL; hud_containers[j].previous = NULL; return &hud_containers[j]; } } // The HUD wasn't found so add it to the end of the list. hud_containers[i].hud = hud; hud_containers[i].next = NULL; hud_containers[i].previous = NULL; i++; return &hud_containers[i - 1]; } // // Find the HUD that is being selected in the hover list. // static hud_t *HUD_Editor_FindHoverListSelection(hud_grephandle_t *list) { hud_t *match = NULL; hud_grephandle_t *hud_iter = list; while(hud_iter) { if(hud_iter->hud && hud_mouse_x > hud_iter->x && hud_mouse_x < (hud_iter->x + hud_iter->width) && hud_mouse_y > hud_iter->y && hud_mouse_y < (hud_iter->y + hud_iter->height)) { hud_iter->highlighted = true; match = hud_iter->hud; } else { hud_iter->highlighted = false; } hud_iter = hud_iter->next; } return match; } // // Draw the hover list... // static qbool HUD_Editor_DrawHoverList(int x, int y, hud_grephandle_t *list) { #define PADDING 5 #define LINEGAP 1 int width = 0; int height = 0; int i = 0; clrinfo_t color, highlight; hud_grephandle_t *hud_iter = list; // No point in showing a list if there's only one hud under the cursor // or if the user hasn't right-clicked. if (hud_hoverlist_count <= 1 || hud_editor_mode != hud_editmode_hoverlist) { return false; } // Get the width of to draw with. while (hud_iter) { width = max(width, (PADDING + 2 + strlen(hud_iter->hud->name)) * 8); hud_iter = hud_iter->next; } // Draw the background fill. height = ((hud_hoverlist_count - 1) * (8 + LINEGAP)) + (2 * PADDING); Draw_AlphaFillRGB(x, y - height, width, height, 0, 0, 0, 255); hud_iter = list; // Highlight color (yellow)... Vector4Set(highlight.c, 0, 255, 0, 255); // Orange. Vector4Set(color.c, 255, 150, 0, 255); // Draw the list items. while(hud_iter) { // Calculate the size and position of the HUD in the list. hud_iter->x = x; hud_iter->y = y - height + (i * 8) + LINEGAP; hud_iter->width = width; hud_iter->height = 8; // Draw the z-order + name of the HUD. Draw_ColoredString3(hud_iter->x, hud_iter->y, va("%2d - %s", hud_iter->hud->order->ival, hud_iter->hud->name), (hud_iter->highlighted ? &highlight : &color), 1, 0); hud_iter = hud_iter->next; i++; } return true; } // // Sets a new HUD Editor mode (and saves the previous one). // static void HUD_Editor_SetMode(hud_editor_mode_t newmode) { hud_editor_prevmode = hud_editor_mode; hud_editor_mode = newmode; } // // Draws a tool tip with a background next to the cursor. // static void HUD_Editor_DrawTooltip(int x, int y, char *string, float r, float g, float b, float a) { int len = strlen(string) * 8; y -= 9; // Make sure we're drawing within the screen. if (x + len > vid.width) { x -= len; } if (y + 9 > vid.height) { y -= 9; } Draw_AlphaFillRGB(x, y, len, 8, r, g, b, a); Draw_String(x, y, string); } // // Gets an alignment string for a specified alignmode enum. // static char *HUD_Editor_GetAlignmentString(hud_alignmode_t align) { switch(hud_alignmode) { case hud_align_center : return "center center"; case hud_align_top : return "center top"; case hud_align_topleft : return "left top"; case hud_align_left : return "left center"; case hud_align_bottomleft : return "left bottom"; case hud_align_bottom : return "center bottom"; case hud_align_bottomright :return "right bottom"; case hud_align_right : return "right center"; case hud_align_topright : return "right top"; case hud_align_consoleleft :return "left console"; case hud_align_console : return "center console"; case hud_align_consoleright:return "right console"; default : return ""; } } // // Returns an alignment enum based on a specified alignment string. // static hud_alignmode_t HUD_Editor_GetAlignmentFromString(char *alignstr) { if(!strcmp(alignstr, "center center")) { return hud_align_center; } else if(!strcmp(alignstr, "center top")) { return hud_align_top; } else if(!strcmp(alignstr, "left top")) { return hud_align_topleft; } else if(!strcmp(alignstr, "left center")) { return hud_align_left; } else if(!strcmp(alignstr, "left bottom")) { return hud_align_bottomleft; } else if(!strcmp(alignstr, "center bottom")) { return hud_align_bottom; } else if(!strcmp(alignstr, "right bottom")) { return hud_align_bottomright; } else if(!strcmp(alignstr, "right center")) { return hud_align_right; } else if(!strcmp(alignstr, "right top")) { return hud_align_topright; } else if(!strcmp(alignstr, "left console")) { return hud_align_consoleleft; } else if(!strcmp(alignstr, "center console")) { return hud_align_console; } else if(!strcmp(alignstr, "right console")) { return hud_align_consoleright; } return hud_align_center; } qbool IsPointInPolygon(int points, vec3_t planes[], float x, float y) { return false; } // // Returns the alignment we are trying to align the selected HUD to at it's placement // when in alignment mode. // static hud_alignmode_t HUD_Editor_GetAlignment(int x, int y, hud_t *hud_element) { // For less clutter. float mid_x = 0.0; float mid_y = 0.0; int offset_x = 0; int offset_y = 0; if(hud_element) { // Aligns for HUD elements. offset_x = hud_element->lx; offset_y = hud_element->ly; mid_x = hud_element->lw / 2.0; mid_y = hud_element->lh / 2.0; } else { // Aligns for Screen. offset_x = 0; offset_y = (int)(vid.height * 0.05); mid_x = vid.width / 2.0; mid_y = (vid.height + offset_y) / 2.0; } if(!hud_element) { // Console left. { hud_align_consoleleft_poly[0][0] = 0; hud_align_consoleleft_poly[0][1] = 0; hud_align_consoleleft_poly[0][2] = 0; hud_align_consoleleft_poly[1][0] = 0; hud_align_consoleleft_poly[1][1] = offset_y; hud_align_consoleleft_poly[1][2] = 0; hud_align_consoleleft_poly[2][0] = mid_x / 2.0; hud_align_consoleleft_poly[2][1] = offset_y; hud_align_consoleleft_poly[2][2] = 0; hud_align_consoleleft_poly[3][0] = mid_x / 2.0; hud_align_consoleleft_poly[3][1] = 0; hud_align_consoleleft_poly[3][2] = 0; if (IsPointInPolygon(HUD_ALIGN_POLYCOUNT_CONSOLE, hud_align_consoleleft_poly, x, y)) { hud_align_current_poly = hud_align_consoleleft_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_CONSOLE; return hud_align_consoleleft; } } // Console. { hud_align_console_poly[0][0] = mid_x / 2.0; hud_align_console_poly[0][1] = 0; hud_align_console_poly[0][2] = 0; hud_align_console_poly[1][0] = mid_x / 2.0; hud_align_console_poly[1][1] = offset_y; hud_align_console_poly[1][2] = 0; hud_align_console_poly[2][0] = mid_x + (mid_x / 2.0); hud_align_console_poly[2][1] = offset_y; hud_align_console_poly[2][2] = 0; hud_align_console_poly[3][0] = mid_x + (mid_x / 2.0); hud_align_console_poly[3][1] = 0; hud_align_console_poly[3][2] = 0; if (IsPointInPolygon(HUD_ALIGN_POLYCOUNT_CONSOLE, hud_align_console_poly, x, y)) { hud_align_current_poly = hud_align_console_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_CONSOLE; return hud_align_console; } } // Console right. { hud_align_consoleright_poly[0][0] = mid_x + (mid_x / 2.0); hud_align_consoleright_poly[0][1] = 0; hud_align_consoleright_poly[0][2] = 0; hud_align_consoleright_poly[1][0] = mid_x + (mid_x / 2.0); hud_align_consoleright_poly[1][1] = offset_y; hud_align_consoleright_poly[1][2] = 0; hud_align_consoleright_poly[2][0] = 2 * mid_x; hud_align_consoleright_poly[2][1] = offset_y; hud_align_consoleright_poly[2][2] = 0; hud_align_consoleright_poly[3][0] = 2 * mid_x; hud_align_consoleright_poly[3][1] = 0; hud_align_consoleright_poly[3][2] = 0; if (IsPointInPolygon(HUD_ALIGN_POLYCOUNT_CONSOLE, hud_align_consoleright_poly, x, y)) { hud_align_current_poly = hud_align_consoleright_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_CONSOLE; return hud_align_consoleright; } } } // Top right. { hud_align_topright_poly[0][0] = mid_x + (mid_x / 2.0); hud_align_topright_poly[0][1] = 0; hud_align_topright_poly[0][2] = 0; hud_align_topright_poly[1][0] = mid_x + (mid_x / 4.0); hud_align_topright_poly[1][1] = mid_y - (mid_y / 2.0); hud_align_topright_poly[1][2] = 0; hud_align_topright_poly[2][0] = mid_x + (mid_x / 2.0); hud_align_topright_poly[2][1] = mid_y - (mid_y / 4.0); hud_align_topright_poly[2][2] = 0; hud_align_topright_poly[3][0] = 2 * mid_x; hud_align_topright_poly[3][1] = mid_y - (mid_y / 2.0); hud_align_topright_poly[3][2] = 0; hud_align_topright_poly[4][0] = 2 * mid_x; hud_align_topright_poly[4][1] = 0; hud_align_topright_poly[4][2] = 0; if (IsPointInPolygon(HUD_ALIGN_POLYCOUNT_CORNER, hud_align_topright_poly, x - offset_x, y - offset_y)) { hud_align_current_poly = hud_align_topright_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_CORNER; return hud_align_topright; } } // Top. { hud_align_top_poly[0][0] = mid_x / 2.0; hud_align_top_poly[0][1] = 0; hud_align_top_poly[0][2] = 0; hud_align_top_poly[1][0] = mid_x - (mid_x / 4.0); hud_align_top_poly[1][1] = mid_y - (mid_y / 2.0); hud_align_top_poly[1][2] = 0; hud_align_top_poly[2][0] = mid_x + (mid_x / 4.0); hud_align_top_poly[2][1] = mid_y - (mid_y / 2.0); hud_align_top_poly[2][2] = 0; hud_align_top_poly[3][0] = mid_x + (mid_x / 2.0); hud_align_top_poly[3][1] = 0; hud_align_top_poly[3][2] = 0; if (IsPointInPolygon(HUD_ALIGN_POLYCOUNT_EDGE, hud_align_top_poly, x - offset_x, y - offset_y)) { hud_align_current_poly = hud_align_top_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_EDGE; return hud_align_top; } } // Top Left. { hud_align_topleft_poly[0][0] = 0; hud_align_topleft_poly[0][1] = 0; hud_align_topleft_poly[0][2] = 0; hud_align_topleft_poly[1][0] = 0; hud_align_topleft_poly[1][1] = mid_y - (mid_y / 2.0); hud_align_topleft_poly[1][2] = 0; hud_align_topleft_poly[2][0] = mid_x - (mid_x / 2.0); hud_align_topleft_poly[2][1] = mid_y - (mid_y / 4.0); hud_align_topleft_poly[2][2] = 0; hud_align_topleft_poly[3][0] = mid_x - (mid_x / 4.0); hud_align_topleft_poly[3][1] = mid_y - (mid_y / 2.0); hud_align_topleft_poly[3][2] = 0; hud_align_topleft_poly[4][0] = mid_x - (mid_x / 2.0); hud_align_topleft_poly[4][1] = 0; hud_align_topleft_poly[4][2] = 0; if (IsPointInPolygon(HUD_ALIGN_POLYCOUNT_CORNER, hud_align_topleft_poly, x - offset_x, y - offset_y)) { hud_align_current_poly = hud_align_topleft_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_CORNER; return hud_align_topleft; } } // Left. { hud_align_left_poly[0][0] = 0; hud_align_left_poly[0][1] = mid_y / 2.0; hud_align_left_poly[0][2] = 0; hud_align_left_poly[1][0] = 0; hud_align_left_poly[1][1] = mid_y + (mid_y / 2.0); hud_align_left_poly[1][2] = 0; hud_align_left_poly[2][0] = mid_x / 2.0; hud_align_left_poly[2][1] = mid_y + (mid_y / 4.0); hud_align_left_poly[2][2] = 0; hud_align_left_poly[3][0] = mid_x / 2.0; hud_align_left_poly[3][1] = mid_y - (mid_y / 4.0); hud_align_left_poly[3][2] = 0; if (IsPointInPolygon(HUD_ALIGN_POLYCOUNT_EDGE, hud_align_left_poly, x - offset_x, y - offset_y)) { hud_align_current_poly = hud_align_left_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_EDGE; return hud_align_left; } } // Bottom Left. { hud_align_bottomleft_poly[0][0] = 0; hud_align_bottomleft_poly[0][1] = mid_y + (mid_y / 2.0); hud_align_bottomleft_poly[0][2] = 0; hud_align_bottomleft_poly[1][0] = 0; hud_align_bottomleft_poly[1][1] = 2 * mid_y; hud_align_bottomleft_poly[1][2] = 0; hud_align_bottomleft_poly[2][0] = mid_x / 2.0; hud_align_bottomleft_poly[2][1] = 2 * mid_y; hud_align_bottomleft_poly[2][2] = 0; hud_align_bottomleft_poly[3][0] = mid_x - (mid_x / 4.0); hud_align_bottomleft_poly[3][1] = mid_y + (mid_y / 2.0); hud_align_bottomleft_poly[3][2] = 0; hud_align_bottomleft_poly[4][0] = mid_x / 2.0; hud_align_bottomleft_poly[4][1] = mid_y + (mid_y / 4.0); hud_align_bottomleft_poly[4][2] = 0; if (IsPointInPolygon(HUD_ALIGN_POLYCOUNT_CORNER, hud_align_bottomleft_poly, x - offset_x, y - offset_y)) { hud_align_current_poly = hud_align_bottomleft_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_CORNER; return hud_align_bottomleft; } } // Bottom. { hud_align_bottom_poly[0][0] = mid_x - (mid_x / 2.0); hud_align_bottom_poly[0][1] = 2 * mid_y; hud_align_bottom_poly[0][2] = 0; hud_align_bottom_poly[1][0] = mid_x + (mid_x / 2.0); hud_align_bottom_poly[1][1] = 2 * mid_y; hud_align_bottom_poly[1][2] = 0; hud_align_bottom_poly[2][0] = mid_x + (mid_x / 4.0); hud_align_bottom_poly[2][1] = mid_y + (mid_y / 2.0); hud_align_bottom_poly[2][2] = 0; hud_align_bottom_poly[3][0] = mid_x - (mid_x / 4.0); hud_align_bottom_poly[3][1] = mid_y + (mid_y / 2.0); hud_align_bottom_poly[3][2] = 0; if (IsPointInPolygon(HUD_ALIGN_POLYCOUNT_EDGE, hud_align_bottom_poly, x - offset_x, y - offset_y)) { hud_align_current_poly = hud_align_bottom_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_EDGE; return hud_align_bottom; } } // Bottom Right. { hud_align_bottomright_poly[0][0] = mid_x + (mid_x / 2.0); hud_align_bottomright_poly[0][1] = 2 * mid_y; hud_align_bottomright_poly[0][2] = 0; hud_align_bottomright_poly[1][0] = 2 * mid_x; hud_align_bottomright_poly[1][1] = 2 * mid_y; hud_align_bottomright_poly[1][2] = 0; hud_align_bottomright_poly[2][0] = 2 * mid_x; hud_align_bottomright_poly[2][1] = mid_y + (mid_y / 2.0); hud_align_bottomright_poly[2][2] = 0; hud_align_bottomright_poly[3][0] = mid_x + (mid_x / 2.0); hud_align_bottomright_poly[3][1] = mid_y + (mid_y / 4.0); hud_align_bottomright_poly[3][2] = 0; hud_align_bottomright_poly[4][0] = mid_x + (mid_x / 4.0); hud_align_bottomright_poly[4][1] = mid_y + (mid_y / 2.0); hud_align_bottomright_poly[4][2] = 0; if (IsPointInPolygon(HUD_ALIGN_POLYCOUNT_CORNER, hud_align_bottomright_poly, x - offset_x, y - offset_y)) { hud_align_current_poly = hud_align_bottomright_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_CORNER; return hud_align_bottomright; } } // Right. { hud_align_right_poly[0][0] = 2 * mid_x; hud_align_right_poly[0][1] = mid_y + (mid_y / 2.0); hud_align_right_poly[0][2] = 0; hud_align_right_poly[1][0] = 2 * mid_x; hud_align_right_poly[1][1] = mid_y / 2.0; hud_align_right_poly[1][2] = 0; hud_align_right_poly[2][0] = mid_x + (mid_x / 2.0); hud_align_right_poly[2][1] = mid_y - (mid_y / 4.0); hud_align_right_poly[2][2] = 0; hud_align_right_poly[3][0] = mid_x + (mid_x / 2.0); hud_align_right_poly[3][1] = mid_y + (mid_y / 4.0); hud_align_right_poly[3][2] = 0; if (IsPointInPolygon(HUD_ALIGN_POLYCOUNT_EDGE, hud_align_right_poly, x - offset_x, y - offset_y)) { hud_align_current_poly = hud_align_right_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_EDGE; return hud_align_right; } } // Center. { hud_align_center_poly[0][0] = mid_x - (mid_x / 4.0); hud_align_center_poly[0][1] = mid_y / 2.0; hud_align_center_poly[0][2] = 0; hud_align_center_poly[1][0] = mid_x / 2.0; hud_align_center_poly[1][1] = mid_y - (mid_y / 4.0); hud_align_center_poly[1][2] = 0; hud_align_center_poly[2][0] = mid_x / 2.0; hud_align_center_poly[2][1] = mid_y + (mid_y / 4.0); hud_align_center_poly[2][2] = 0; hud_align_center_poly[3][0] = mid_x - (mid_x / 4.0); hud_align_center_poly[3][1] = mid_y + (mid_y / 2.0); hud_align_center_poly[3][2] = 0; hud_align_center_poly[4][0] = mid_x + (mid_x / 4.0); hud_align_center_poly[4][1] = mid_y + (mid_y / 2.0); hud_align_center_poly[4][2] = 0; hud_align_center_poly[5][0] = mid_x + (mid_x / 2.0); hud_align_center_poly[5][1] = mid_y + (mid_y / 4.0); hud_align_center_poly[5][2] = 0; hud_align_center_poly[6][0] = mid_x + (mid_x / 2.0); hud_align_center_poly[6][1] = mid_y - (mid_y / 4.0); hud_align_center_poly[6][2] = 0; hud_align_center_poly[7][0] = mid_x + (mid_x / 4.0); hud_align_center_poly[7][1] = mid_y / 2.0; hud_align_center_poly[7][2] = 0; if (IsPointInPolygon(HUD_ALIGN_POLYCOUNT_CENTER, hud_align_center_poly, x - offset_x, y - offset_y)) { hud_align_current_poly = hud_align_center_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_CENTER; return hud_align_center; } } // Default to center. hud_align_current_poly = hud_align_center_poly; hud_align_current_polycount = HUD_ALIGN_POLYCOUNT_CENTER; return hud_align_center; } // // Finds the next child of the specified HUD element. // static hud_t *HUD_Editor_FindNextChild(hud_t *hud_element) { static hud_t *hud_it = NULL; static hud_t *parent = NULL; hud_t *hud_result = NULL; // Reset everything if we're given a NULL argument. if(!hud_element) { hud_it = NULL; parent = NULL; return NULL; } // There's a new parent so start searching from the beginning. if(!parent || strcmp(parent->name, hud_element->name)) { parent = hud_element; hud_it = hud_huds; } while(hud_it) { // Check if this HUD is placed at the parent, if so we've found a child. if(hud_it->place_hud && !strcmp(hud_it->place_hud->name, parent->name)) { hud_result = hud_it; hud_it = hud_it->next; return hud_result; } hud_it = hud_it->next; } parent = NULL; // No children found. return NULL; } // // Moves a HUD element. // static void HUD_Editor_Move(float dx, float dy, hud_t *hud_element) { if(!hud_element) { return; } Cvar_SetValue(hud_element->pos_x, hud_element->pos_x->value + dx); Cvar_SetValue(hud_element->pos_y, hud_element->pos_y->value + dy); } // // Draw the current alignment. // static void HUD_Editor_DrawAlignment(hud_t *hud_parent) { if(hud_parent) { //Draw_Polygon(hud_parent->lx, hud_parent->ly, hud_align_current_poly, hud_align_current_polycount, true, RGBA_TO_COLOR(255, 255, 0, 50)); Draw_Polygon(hud_parent->lx, hud_parent->ly, hud_align_current_poly, hud_align_current_polycount, true, 255, 255, 0, 50); } else { //Draw_Polygon(0, 0, hud_align_current_poly, hud_align_current_polycount, true, RGBA_TO_COLOR(255, 255, 0, 50)); Draw_Polygon(0, 0, hud_align_current_poly, hud_align_current_polycount, true, 255, 255, 0, 50); } } typedef struct hud_resize_handle_s { int x; int y; int width; int height; } hud_resize_handle_t; #define HUD_RESIZEHANDLE_THICKNESS 5 #define HUD_RESIZEHANDLE_SIZEFACTOR 0.3 #define HUD_RESIZEHANDLE_COUNT 8 #define HUD_RESIZE_MAGICSCALE 200 // HACK : This seems to work nice though... #define HUD_RESIZEHANDLE_NONE -1 #define HUD_RESIZEHANDLE_TOPLEFT 0 #define HUD_RESIZEHANDLE_TOP 1 #define HUD_RESIZEHANDLE_TOPRIGHT 2 #define HUD_RESIZEHANDLE_RIGHT 3 #define HUD_RESIZEHANDLE_BOTTOMRIGHT 4 #define HUD_RESIZEHANDLE_BOTTOM 5 #define HUD_RESIZEHANDLE_BOTTOMLEFT 6 #define HUD_RESIZEHANDLE_LEFT 7 // // Resizes the height/width of a HUD element by a delta size and alignment. // static void HUD_Editor_ResizeDelta(cvar_t *size, float delta_size, hud_alignmode_t alignment) { if(!size) { return; } switch(alignment) { case hud_align_right : case hud_align_bottom : Cvar_SetValue(size, size->value + delta_size); break; case hud_align_left : case hud_align_top : Cvar_SetValue(size, size->value - delta_size); break; // unhandled case hud_align_center: case hud_align_topleft: case hud_align_bottomleft: case hud_align_bottomright: case hud_align_topright: case hud_align_consoleleft: case hud_align_consoleright: case hud_align_console: break; } } // // Scales a HUD element. // static void HUD_EditorScaleDelta(cvar_t *scale, float delta_scale, hud_alignmode_t alignment) { if(!scale) { return; } switch(alignment) { case hud_align_topleft : case hud_align_bottomleft : Cvar_SetValue(scale, scale->value - delta_scale); break; case hud_align_topright : case hud_align_bottomright : Cvar_SetValue(scale, scale->value + delta_scale); break; // unhandled case hud_align_center: case hud_align_top: case hud_align_left: case hud_align_bottom: case hud_align_right: case hud_align_consoleleft: case hud_align_consoleright: case hud_align_console: break; } if(scale->value < 0) { Cvar_SetValue(scale, 0); } } // // Checks if the HUD element we're hovering has any dimension variables // and handles resizing for it if it does by drawing resize handles // that the user can click. // static qbool HUD_Editor_Resizing(hud_t *hud_hover) { extern float mouse_x, mouse_y; // in_win.c, delta mouse. int i = 0; qbool found_handle = false; // Did we find any handle under the cursor? static cvar_t *width = NULL; static cvar_t *height = NULL; static cvar_t *scale = NULL; hud_resize_handle_t *resize_handles[HUD_RESIZEHANDLE_COUNT]; static int last_resize_handle = HUD_RESIZEHANDLE_NONE; // Is this mode turned on? if(!hud_editor_allowresize->value) { return false; } // Select a HUD if it hasn't already been done. if(hud_hover && hud_editor_mode == hud_editmode_move_resize && !selected_hud && hud_hover) { selected_hud = hud_hover; return true; } memset(resize_handles, 0, sizeof(resize_handles)); // Try getting any available dimension variables // that are available for this HUD element, these // aren't mandatory for all HUD elements, so only // some will have them. if(hud_hover) { width = HUD_FindVar(hud_hover, "width"); height = HUD_FindVar(hud_hover, "height"); scale = HUD_FindVar(hud_hover, "scale"); if(width) { // Right & left. static hud_resize_handle_t right; static hud_resize_handle_t left; right.width = HUD_RESIZEHANDLE_THICKNESS; right.height = hud_hover->lh * HUD_RESIZEHANDLE_SIZEFACTOR; right.x = hud_hover->lw - right.width; right.y = (hud_hover->lh - right.height) / 2; resize_handles[HUD_RESIZEHANDLE_RIGHT] = &right; left.width = HUD_RESIZEHANDLE_THICKNESS; left.height = hud_hover->lh * HUD_RESIZEHANDLE_SIZEFACTOR; left.x = 0; left.y = (hud_hover->lh - left.height) / 2; resize_handles[HUD_RESIZEHANDLE_LEFT] = &left; } if(height) { // Top & bottom static hud_resize_handle_t top; static hud_resize_handle_t bottom; top.width = hud_hover->lw * HUD_RESIZEHANDLE_SIZEFACTOR; top.height = HUD_RESIZEHANDLE_THICKNESS; top.x = (hud_hover->lw - top.width) / 2; top.y = 0; resize_handles[HUD_RESIZEHANDLE_TOP] = ⊤ bottom.width = hud_hover->lw * HUD_RESIZEHANDLE_SIZEFACTOR; bottom.height = HUD_RESIZEHANDLE_THICKNESS; bottom.x = (hud_hover->lw - bottom.width) / 2; bottom.y = hud_hover->lh - bottom.height; resize_handles[HUD_RESIZEHANDLE_BOTTOM] = ⊥ } if(scale) { // Top left, top right, bottom left & bottom right. static hud_resize_handle_t topleft; static hud_resize_handle_t bottomleft; static hud_resize_handle_t topright; static hud_resize_handle_t bottomright; topleft.width = HUD_RESIZEHANDLE_THICKNESS; topleft.height = HUD_RESIZEHANDLE_THICKNESS; topleft.x = 0; topleft.y = 0; resize_handles[HUD_RESIZEHANDLE_TOPLEFT] = &topleft; bottomleft.width = HUD_RESIZEHANDLE_THICKNESS; bottomleft.height = HUD_RESIZEHANDLE_THICKNESS; bottomleft.x = 0; bottomleft.y = hud_hover->lh - bottomleft.height; resize_handles[HUD_RESIZEHANDLE_BOTTOMLEFT] = &bottomleft; topright.width = HUD_RESIZEHANDLE_THICKNESS; topright.height = HUD_RESIZEHANDLE_THICKNESS; topright.x = hud_hover->lw - topright.width; topright.y = 0; resize_handles[HUD_RESIZEHANDLE_TOPRIGHT] = &topright; bottomright.width = HUD_RESIZEHANDLE_THICKNESS; bottomright.height = HUD_RESIZEHANDLE_THICKNESS; bottomright.x = hud_hover->lw - bottomright.width; bottomright.y = hud_hover->lh - bottomright.height; resize_handles[HUD_RESIZEHANDLE_BOTTOMRIGHT] = &bottomright; } } for(i = 0; i < HUD_RESIZEHANDLE_COUNT; i++) { // Non existant for this HUD element. if(!resize_handles[i]) { continue; } if(hud_editor_mode == hud_editmode_move_resize) { // We're in resize mode, so check if we're clicking any of the // resize handles. if((selected_hud && (last_resize_handle == i)) || (hud_mouse_x >= (selected_hud->lx + resize_handles[i]->x) && (hud_mouse_x <= (selected_hud->lx + resize_handles[i]->x + resize_handles[i]->width)) && (hud_mouse_y >= (selected_hud->ly + resize_handles[i]->y)) && (hud_mouse_y <= (selected_hud->ly + resize_handles[i]->y + resize_handles[i]->height)))) { // Keep track of which resize handle we're grabbing // so that it doesn't matter if the mouse "slips" outside // it's bounding box as long as the mouse is still pressed. if(last_resize_handle < 0 || last_resize_handle != i) { last_resize_handle = i; } found_handle = true; // Draw the resize handle highlighted. Draw_AlphaFillRGB( selected_hud->lx + resize_handles[last_resize_handle]->x, selected_hud->ly + resize_handles[last_resize_handle]->y, resize_handles[last_resize_handle]->width, resize_handles[last_resize_handle]->height, 255, 255, 0, 125); // Check which resize handle that has been selected // and resize the HUD element accordingly. switch(i) { case HUD_RESIZEHANDLE_RIGHT : HUD_Editor_ResizeDelta(width, mouse_x, hud_align_right); break; case HUD_RESIZEHANDLE_LEFT : HUD_Editor_ResizeDelta(width, mouse_x, hud_align_left); break; case HUD_RESIZEHANDLE_TOP : HUD_Editor_ResizeDelta(height, mouse_y, hud_align_top); break; case HUD_RESIZEHANDLE_BOTTOM : HUD_Editor_ResizeDelta(height, mouse_y, hud_align_bottom); break; case HUD_RESIZEHANDLE_TOPRIGHT : // HACK : Dividing by 200 seems to work fine, but this could probably be done a lot nicer. HUD_EditorScaleDelta(scale, (mouse_x - mouse_y) / HUD_RESIZE_MAGICSCALE, hud_align_topright); break; case HUD_RESIZEHANDLE_BOTTOMRIGHT : HUD_EditorScaleDelta(scale, (mouse_x + mouse_y) / HUD_RESIZE_MAGICSCALE, hud_align_bottomright); break; case HUD_RESIZEHANDLE_TOPLEFT : HUD_EditorScaleDelta(scale, (mouse_x + mouse_y) / HUD_RESIZE_MAGICSCALE, hud_align_topleft); break; case HUD_RESIZEHANDLE_BOTTOMLEFT : HUD_EditorScaleDelta(scale, (mouse_x - mouse_y) / HUD_RESIZE_MAGICSCALE, hud_align_bottomleft); break; } // Recalculate all HUD elements. HUD_Recalculate(); return true; } } else if(hud_editor_prevmode == hud_editmode_move_resize) { // We left resize mode. selected_hud = NULL; last_resize_handle = HUD_RESIZEHANDLE_NONE; } else if(hud_hover) { // If we're hovering a HUD, always draw all it's resize handles. if((hud_mouse_x >= (hud_hover->lx + resize_handles[i]->x) && hud_mouse_x <= (hud_hover->lx + resize_handles[i]->x + resize_handles[i]->width) && hud_mouse_y >= (hud_hover->ly + resize_handles[i]->y) && hud_mouse_y <= (hud_hover->ly + resize_handles[i]->y + resize_handles[i]->height))) { // Highlight the resize handle under the cursor. Draw_AlphaFillRGB(hud_hover->lx + resize_handles[i]->x, hud_hover->ly + resize_handles[i]->y, resize_handles[i]->width, resize_handles[i]->height, 255, 255, 0, 125); // Set the resize cursor icon since we're hovering a resize handle. scr_cursor_icon = hud_editor_resize_icon; found_handle = true; } else { // Normal resize handle. Draw_AlphaFillRGB(hud_hover->lx + resize_handles[i]->x, hud_hover->ly + resize_handles[i]->y, resize_handles[i]->width, resize_handles[i]->height, 255, 255, 0, 50); } } } // We didn't hover any resize handle so show no icon. if(!found_handle) { scr_cursor_icon = NULL; } // We didn't perform any action, so let others try. return false; } static qbool hud_editor_locked_axis_is_x = true; // Are we locking X- or Y-axis movement? static qbool hud_editor_lockaxis_found= false; // Have we found what axist to lock on to? static qbool hud_editor_finding_lockaxis = false; // Are we in the process of finding the lock axis? // // Check if we're supposed to be moving anything. // static qbool HUD_Editor_Moving(hud_t *hud_hover) { // Mouse delta (in_win.c) extern float mouse_x, mouse_y; // Is this mode allowed? if(!hud_editor_allowmove->value) { return false; } // Set the move cursor icon if we're hovering a HUD element // unless it's not already set (resize may have set it if // a resize handle is being hovered). if(hud_hover && !scr_cursor_icon) { scr_cursor_icon = hud_editor_move_icon; } else if(!hud_hover) { // Not hovering anything so show no cursor. scr_cursor_icon = NULL; } // Left mousebutton down = lets move it ! if (hud_editor_mode == hud_editmode_move_resize || hud_editor_mode == hud_editmode_move_lockedaxis) { // If we just entered movement mode, nothing is selected // so select the hud we're hovering to start with. if(!selected_hud && hud_hover) { selected_hud = hud_hover; return true; } if(selected_hud) { // Move using the mouse delta instead of the absolute // mouse cursor coordinates on the screen. // Lock the movement to the axis that the user starts // dragging the HUD element along if we're in locked-axis mode. if(hud_editor_mode == hud_editmode_move_lockedaxis) { // We haven't found the axis. if(!hud_editor_lockaxis_found) { static float last_mouse_x = 0.0; static float last_mouse_y = 0.0; if(!hud_editor_finding_lockaxis) { // Start trying to find the lock axis. hud_editor_finding_lockaxis = true; last_mouse_x = 0; last_mouse_y = 0; } else { // Get the delta of the mouse movement from when the // user clicked the mouse button and started dragging. float mouse_delta_x = fabs(last_mouse_x - mouse_x); float mouse_delta_y = fabs(last_mouse_y - mouse_y); // Increment the mouse movement since last frame. last_mouse_x += mouse_x; last_mouse_y += mouse_y; // If the mouse has moved more than 5 pixels in any // direction we decide to lock onto that axis. if(mouse_delta_x > 5 || mouse_delta_y > 5) { hud_editor_locked_axis_is_x = (mouse_delta_x > mouse_delta_y); hud_editor_lockaxis_found = true; } } } // Move while locked to the axis. if(hud_editor_locked_axis_is_x) { // Move only along X-axis. HUD_Editor_Move(mouse_x, 0, hud_hover); } else { // Move only along Y-axis. HUD_Editor_Move(0, mouse_y, hud_hover); } } else { // Ordinary move. HUD_Editor_Move(mouse_x, mouse_y, hud_hover); } HUD_Recalculate(); return true; } } else if((hud_editor_prevmode == hud_editmode_move_resize && hud_editor_mode != hud_editmode_move_lockedaxis) || (hud_editor_prevmode == hud_editmode_move_lockedaxis && hud_editor_mode != hud_editmode_move_resize)) { // Only deselect if we're going from a move mode to a non-move mode (Such as align/place). // We've left move mode, so deselect. selected_hud = NULL; hud_editor_lockaxis_found = false; hud_editor_finding_lockaxis = false; } // We haven't handled the input. return false; } // // Handles input from mouse if in alignment mode. // static qbool HUD_Editor_Aligning(hud_t *hud_hover) { // Is this mode allowed? if(!hud_editor_allowalign->value) { return false; } if(hud_editor_mode == hud_editmode_align) { // If we just entered alignment mode, nothing is selected // so select the hud we're hovering to start with. if(!selected_hud && hud_hover) { selected_hud = hud_hover; return true; } // Set the align icon for the cursor. scr_cursor_icon = hud_editor_align_icon; // We have something selected so show some visual // feedback for when aligning to the user. if(selected_hud) { if(selected_hud->place_hud) { // Placed at another HUD, so align onto that. hud_alignmode = HUD_Editor_GetAlignment(hud_mouse_x, hud_mouse_y, selected_hud->place_hud); HUD_Editor_DrawAlignment(selected_hud->place_hud); } else { // Placed on the screen. hud_alignmode = HUD_Editor_GetAlignment(hud_mouse_x, hud_mouse_y, NULL); HUD_Editor_DrawAlignment(NULL); } } } else if(hud_editor_prevmode == hud_editmode_align && isAltDown()) { // The user just released the mousebutton but is still holding // down ALT. If the user releases ALT before the mouse button // the operation will be cancelled. So commit the users actions. // We must have something to align. if(selected_hud) { // Reset position. Cvar_Set(selected_hud->pos_x, "0"); Cvar_Set(selected_hud->pos_y, "0"); // Align to the area the mouse is placed over (previously set in hud_alignmode). Cbuf_AddText(va("align %s %s\n", selected_hud->name, HUD_Editor_GetAlignmentString(hud_alignmode))); HUD_Recalculate(); // Free selection. selected_hud = NULL; return true; } } return false; } // // Handles feedback/commiting of actions when in placement mode. // static qbool HUD_Editor_Placing(hud_t *hud_hover) { // Is this mode allowed? if(!hud_editor_allowplace->value) { return false; } // Show the place icon at the cursor if ctrl is pressed // while hovering a HUD element. if(hud_hover && isCtrlDown()) { // Set the place cursor icon. scr_cursor_icon = hud_editor_place_icon; } else if(!hud_hover) { scr_cursor_icon = NULL; } if(hud_editor_mode == hud_editmode_place) { // If we just entered placement mode, nothing is selected // so select the hud we're hovering to start with. if(!selected_hud && hud_hover) { selected_hud = hud_hover; return true; } // Set the place cursor icon. scr_cursor_icon = hud_editor_place_icon; if(selected_hud) { // Find the center of the selected HUD so we know where // to draw the line from. if(hud_hover) { // We're trying to place the HUD on itself or on the HUD it's already placed at. if(hud_hover == selected_hud || (selected_hud->place_hud && selected_hud->place_hud == hud_hover)) { // Red "not allowed". Draw_AlphaRectangleRGB(hud_hover->lx, hud_hover->ly, hud_hover->lw, hud_hover->lh, 1, true, 255, 0, 0, 25); Draw_AlphaRectangleRGB(hud_hover->lx, hud_hover->ly, hud_hover->lw, hud_hover->lh, 1, false, 255, 0, 0, 255); } else { // Green "allowed" placement. Draw_AlphaRectangleRGB(hud_hover->lx, hud_hover->ly, hud_hover->lw, hud_hover->lh, 1, true, 0, 255, 0, 25); } return true; } // Placement at the screen (We don't care about stuff like IFREE, HBAR, SBAR and so on). if(!strcmp(selected_hud->place->string, "screen")) { // Not allowed, already placed there. Draw_AlphaRectangleRGB(0, 0, vid.width, vid.height, 1, true, 255, 0, 0, 25); } else { // Allowed. Draw_AlphaRectangleRGB(0, 0, vid.width, vid.height, 1, true, 0, 255, 0, 25); } } } else if(hud_editor_prevmode == hud_editmode_place && isCtrlDown()) { // We've just exited placement mode, but control is still pressed, // that means we should place the selected_hud. // (If you release ctrl before you release Mouse 1, you cancel the place operation). if(selected_hud) { // If we're hovering a HUD place it there. if(hud_hover) { // We're trying to place the HUD on itself or on the HUD it's already placed at so do nothing. if(hud_hover == selected_hud || (selected_hud->place_hud && selected_hud->place_hud == hud_hover)) { return true; } // Place at other HUD. Cvar_Set(selected_hud->align_x, "center"); Cvar_Set(selected_hud->align_y, "center"); Cvar_Set(selected_hud->pos_x, "0"); Cvar_Set(selected_hud->pos_y, "0"); Cvar_Set(selected_hud->place, hud_hover->name); // Make sure the child has a higher order. if((int)selected_hud->order->value <= (int)hud_hover->order->value) { Cvar_SetValue(selected_hud->order, hud_hover->order->value + 1); } HUD_Recalculate(); // Free selection. selected_hud = NULL; return true; } else { // Mouse button was released on on the "screen". if(!strcmp(selected_hud->place->string, "screen")) { return false; } // Place at other HUD. Cvar_Set(selected_hud->align_x, "center"); Cvar_Set(selected_hud->align_y, "center"); Cvar_Set(selected_hud->pos_x, "0"); Cvar_Set(selected_hud->pos_y, "0"); Cvar_Set(selected_hud->place, "screen"); HUD_Recalculate(); // Free selection. selected_hud = NULL; return true; } } } // We weren't placing something so check other states also. return false; } // ============================================================================= // HUD Editor Grep Handles. // ============================================================================= // These show up when a HUD element is moved completly offscreen (by accident // most likely), so that the user can still grab it and move it back onto the // screen again. // ============================================================================= // // Finds a HUD grephandle (if the hud element has gone offscreen). // static hud_grephandle_t *HUD_Editor_FindGrep(hud_t *hud_element) { hud_grephandle_t *greps_it = NULL; greps_it = hud_greps; while(greps_it) { if(!strcmp(greps_it->hud->name, hud_element->name)) { return greps_it; } greps_it = greps_it->next; } return NULL; } // // Returns an "offscreen" arrow in the correct direction based on where // offscreen the HUD element is located. // static char *HUD_Editor_GetGrepArrow(hud_grephandle_t *grep) { switch(grep->pos) { case pos_top : return "/\\"; case pos_bottom : return "\\/"; case pos_left : return "<<<"; case pos_right : return ">>>"; default : return ""; } } // // Draws the grephandles. // static void HUD_Editor_DrawGreps() { clrinfo_t color, highlight; hud_grephandle_t *greps_it = NULL; greps_it = hud_greps; // Highlight color (yellow). Vector4Set(highlight.c, 0, 255, 0, 255); // Orange. Vector4Set(color.c, 255, 150, 0, 255); while(greps_it) { Draw_ColoredString3(greps_it->x, greps_it->y, va("%s %s", HUD_Editor_GetGrepArrow(greps_it), greps_it->hud->name), (greps_it->highlighted ? &highlight : &color), 1, 0); greps_it = greps_it->next; } } // // Get's the position offscreen for a HUD element // left/right/top/bottom or visible if it's not offscreen. // static hud_greppos_t HUD_Editor_GetHudGrepPosition(hud_t *hud) { if(hud->lx + hud->lw <= 0) { return pos_left; } else if(hud->lx >= (signed)vid.width) { return pos_right; } else if(hud->ly + hud->lh <= 0) { return pos_top; } else if(hud->ly >= (signed)vid.height) { return pos_bottom; } return pos_visible; } // // Positions a grephandle based on it's position and where the HUD element // it's associated with is located. // static void HUD_Editor_PositionGrep(hud_t *hud_element, hud_grephandle_t *grep) { // Get the position of the grephandle. grep->pos = HUD_Editor_GetHudGrepPosition(hud_element); // Position the grephandle on screen. switch(grep->pos) { case pos_top : grep->x = hud_element->lx; grep->y = 5; break; case pos_bottom : grep->x = hud_element->lx; grep->y = vid.height - grep->height - 5; break; case pos_left : grep->x = 5; grep->y = hud_element->ly; break; case pos_right : grep->x = vid.width - grep->width - 5; grep->y = hud_element->ly; break; default : grep->x = hud_element->lx; grep->y = hud_element->ly; break; } } // // Creates a new grephandle and associates it with a HUD element that is offscreen. // static hud_grephandle_t *HUD_Editor_CreateGrep(hud_t *hud_element) { hud_grephandle_t *grep = NULL; grep = Q_malloc(sizeof(hud_grephandle_t)); memset(grep, 0, sizeof(*grep)); grep->width = 8 * (4 + strlen(hud_element->name)); grep->height = 8; grep->hud = hud_element; grep->previous = NULL; grep->next = hud_greps; if(hud_greps) { hud_greps->previous = grep; } hud_greps = grep; HUD_Editor_PositionGrep(hud_element, grep); return grep; } // // Destroys a grephandle (called if it's no longer offscreen). // static void HUD_Editor_DestroyGrep(hud_grephandle_t *grep) { // Already destroyed. if(!grep) { return; } // Relink any neighbours in the list. if(grep->next && grep->previous) { grep->previous->next = grep->next; grep->next->previous = grep->previous; } else if(grep->next) { grep->next->previous = NULL; hud_greps = grep->next; } else if(grep->previous) { grep->previous->next = NULL; } else { hud_greps = NULL; } memset(grep, 0, sizeof(*grep)); Q_free(grep); } // // Finds a HUD element associated with the grephandle under the mouse cursor. // static hud_t *HUD_Editor_FindHudByGrep() { hud_grephandle_t *greps_it = NULL; greps_it = hud_greps; while(greps_it) { if (greps_it->hud && hud_mouse_x >= greps_it->x && hud_mouse_x <= (greps_it->x + greps_it->width) && hud_mouse_y >= greps_it->y && hud_mouse_y <= (greps_it->y + greps_it->height)) { greps_it->highlighted = true; return greps_it->hud; } greps_it->highlighted = false; greps_it = greps_it->next; } return NULL; } // // Draws the outline of the visible HUD elements. // static void HUD_Editor_DrawOutlines(void) { hud_t *temp_hud = hud_huds; if(!temp_hud || !hud_editor_showoutlines) { return; } while(temp_hud->next) { // Check if the item is visible. if (!temp_hud->show->value || (temp_hud->place_hud && !temp_hud->place_hud->show->value)) { temp_hud = temp_hud->next; continue; } // Draw an outline for all hud elements (faint). Draw_AlphaRectangleRGB(temp_hud->lx, temp_hud->ly, temp_hud->lw, temp_hud->lh, 1, false, 0, 255, 0, 25); temp_hud = temp_hud->next; } } // // Finds if there's any HUD under the cursor and draws outlines for all HUD elements. // static qbool HUD_Editor_FindHudUnderCursor(hud_t **hud) { hud_grephandle_t *grep = NULL; hud_greppos_t pos = pos_visible; hud_t *temp_hud = hud_huds; qbool found = false; if(!temp_hud) { return false; } // Check if we already had something selected since last time and was moving. if(selected_hud && (hud_editor_mode == hud_editmode_move_resize || hud_editor_mode == hud_editmode_move_lockedaxis)) { found = true; (*hud) = selected_hud; } // If the hover list is being showed, only look for HUDs in that // not the HUD's that are below the cursor. if(hud_editor_mode == hud_editmode_hoverlist && hud_hoverlist_count > 0) { (*hud) = HUD_Editor_FindHoverListSelection(hud_hoverlist); return (hud != NULL); } // Reset the hoverlist since we might be hovering something new. hud_hoverlist_count = 0; hud_hoverlist = NULL; while(temp_hud) { // Not visible. if (!temp_hud->show->value || (temp_hud->place_hud && !temp_hud->place_hud->show->value)) { temp_hud = temp_hud->next; continue; } // We found one. if (hud_mouse_x >= temp_hud->lx && hud_mouse_x <= (temp_hud->lx + temp_hud->lw) && hud_mouse_y >= temp_hud->ly && hud_mouse_y <= (temp_hud->ly + temp_hud->lh)) { // If we're moving/resizing something only continue checking for // more HUD elements we have the mouse over if we haven't already // found one. If we don't do this when you drag a HUD element // over another HUD element that has a greater Z-order the selection // will jump to that HUD element, and you'll start moving that instead. // // Vice versa if we would skip any HUD item after we've found one // when not already moving an item, it would mean that we could only // select HUD elements that are topmost in the Z-order, so an item // placed within another item would not be selectable. if(((hud_editor_mode == hud_editmode_move_resize || hud_editor_mode == hud_editmode_move_lockedaxis) && !found) || (hud_editor_mode != hud_editmode_move_resize && hud_editor_mode != hud_editmode_move_lockedaxis)) { found = true; (*hud) = temp_hud; // Add this HUD to the list of HUDs under the cursor. HUD_Editor_AddHoverHud(HUD_Editor_CreateHoverHud(temp_hud)); } } // Check if the hud element is offscreen and // if there's any grep handle for this hud element { pos = HUD_Editor_GetHudGrepPosition(temp_hud); grep = HUD_Editor_FindGrep(temp_hud); if(pos != pos_visible) { // We didn't find any grep handle so create one. if(!grep) { grep = HUD_Editor_CreateGrep(temp_hud); } // Position the grep if we got one. if(grep) { HUD_Editor_PositionGrep(temp_hud, grep); } } else { // The HUD element is visbile, so no need for a grep handle for it. HUD_Editor_DestroyGrep(grep); } } temp_hud = temp_hud->next; } // We didn't find any HUD's under the cursor, but // what about "grep handles" (for offscreen HUDs). if(!found) { temp_hud = HUD_Editor_FindHudByGrep(); if(temp_hud) { found = true; (*hud) = temp_hud; } } // Nothing found, make sure result is NULL. if (!found) { (*hud) = NULL; } return found; } // // Returns the point a HUD is aligned to on it's parent in screen coordinates. // static void HUD_Editor_GetAlignmentPoint(hud_t *hud, int *x, int *y) { extern float scr_con_current; // Console height. console.c int parent_x = 0; int parent_y = 0; int parent_w = 0; int parent_h = 0; hud_alignmode_t alignmode = HUD_Editor_GetAlignmentFromString(va("%s %s", hud->align_x->string, hud->align_y->string)); if(hud->place_hud) { // Placed at another HUD. parent_x = hud->place_hud->lx; parent_y = hud->place_hud->ly; parent_w = hud->place_hud->lw; parent_h = hud->place_hud->lh; (*x) = HUD_CENTER_X(hud->place_hud); (*y) = HUD_CENTER_Y(hud->place_hud); } else { // Placed at "screen". parent_x = 0; parent_y = 0; parent_w = vid.width; parent_h = vid.height; (*x) = vid.width / 2; (*y) = vid.height / 2; } switch(alignmode) { default: case hud_align_center: // Already set. break; case hud_align_right: (*x) = parent_x + parent_w; (*y) = parent_y + (parent_h / 2); break; case hud_align_topright: (*x) = parent_x + parent_w; (*y) = parent_y; break; case hud_align_top: (*x) = parent_x + (parent_w / 2); (*y) = parent_y; break; case hud_align_topleft: (*x) = parent_x; (*y) = parent_y; break; case hud_align_left: (*x) = parent_x; (*y) = parent_y + (parent_h / 2); break; case hud_align_bottomleft: (*x) = parent_x; (*y) = parent_y + parent_h; break; case hud_align_bottom: (*x) = parent_x + (parent_w / 2); (*y) = parent_y + parent_h; break; case hud_align_bottomright: (*x) = parent_x + parent_w; (*y) = parent_y + parent_h; break; case hud_align_consoleleft: (*x) = parent_x; (*y) = scr_con_current; break; case hud_align_console: (*x) = parent_x + (parent_w / 2); (*y) = scr_con_current; break; case hud_align_consoleright: (*x) = parent_x + parent_w; (*y) = scr_con_current; break; } } // // Draws a green line to each corner of a HUD element from a specified point. // /* static void HUD_Editor_DrawLinesToEachCorner(hud_t *hud, int x, int y) { Draw_AlphaLineRGB(hud->lx, hud->ly, x, y, 1, RGBA_TO_COLOR(0, 255, 0, 25)); Draw_AlphaLineRGB(hud->lx, hud->ly + hud->lh, x, y, 1, RGBA_TO_COLOR(0, 255, 0, 25)); Draw_AlphaLineRGB(hud->lx + hud->lw, hud->ly, x, y, 1, RGBA_TO_COLOR(0, 255, 0, 25)); Draw_AlphaLineRGB(hud->lx + hud->lw, hud->ly + hud->lh, x, y, 1, RGBA_TO_COLOR(0, 255, 0, 25)); } */ // // Draws connections to/from a HUD element. // static void HUD_Editor_DrawConnections(hud_t *hud_hover) { hud_t *child = NULL; int align_x = 0.0; int align_y = 0.0; if (!hud_hover || !hud_editor_showoutlines) { return; } // Get the alignment point at the parent in screen coordinates. HUD_Editor_GetAlignmentPoint(hud_hover, &align_x, &align_y); // Draw a line to the parent of the HUD we're hovering. Draw_AlphaLineRGB(HUD_CENTER_X(hud_hover), HUD_CENTER_Y(hud_hover), align_x, align_y, 1, 0, 255, 0, 25); // Draw a line to all children of the HUD we're hovering. while((child = HUD_Editor_FindNextChild(hud_hover))) { // Don't bother with hidden children. if(!child->show->value) { continue; } // Draw a line from the alignment point on the parent to the child. HUD_Editor_GetAlignmentPoint(child, &align_x, &align_y); Draw_AlphaLineRGB(align_x, align_y, HUD_CENTER_X(child), HUD_CENTER_Y(child), 1, 0, 255, 0, 25); } } // // Evaluates the current mouse/keyboard state and sets the appropriate mode. // static void HUD_Editor_EvaluateState(hud_t *hud_hover) { // Mouse 1 = Move + Resize // Mouse 2 = Toggle menu // Ctrl + Mouse 1 = Place // Alt + Mouse 1 = Align // Shift + Mouse 1 = Lock moving to one axis (If you start dragging along x-axis, it will stick to that) if (MOUSEDOWN) { // Turn of help on mouse click. hud_editor_showhelp = false; } if (hud_editor_mode == hud_editmode_hoverlist) { if (!MOUSEDOWN) { // Stay in hoverlist mode until the user clicks something. return; } } if (hud_hover && MOUSEDOWN_1_ONLY && isShiftDown()) { // Move (Locked to an axis). HUD_Editor_SetMode(hud_editmode_move_lockedaxis); } else if ((hud_hover || hud_editor_prevmode == hud_editmode_place) && MOUSEDOWN_1_ONLY && isCtrlDown()) { // Place. HUD_Editor_SetMode(hud_editmode_place); } else if ((hud_hover || hud_editor_prevmode == hud_editmode_align) && MOUSEDOWN_1_ONLY && isAltDown()) { // Align. HUD_Editor_SetMode(hud_editmode_align); } else if ((hud_hover || selected_hud) && MOUSEDOWN_1_ONLY) { // Move + resize. HUD_Editor_SetMode(hud_editmode_move_resize); } else if (hud_hoverlist_count > 1 && MOUSEDOWN_2_ONLY) { // Hover list for when hovering more than one HUD. HUD_Editor_SetMode(hud_editmode_hoverlist); } else if (hud_hover && MOUSEDOWN_2_ONLY) { // HUD element menu for the HUD element we have the mouse over. HUD_Editor_SetMode(hud_editmode_hudmenu); } else if (MOUSEDOWN_2_ONLY) { // Main menu for adding HUDs if we right click non-occupied space. HUD_Editor_SetMode(hud_editmode_menu); } else { // Nothing special happening. HUD_Editor_SetMode(hud_editmode_normal); } } // // Draws the tooltips for a HUD element based on the state we're in. // static void HUD_Editor_DrawTooltips(hud_t *hud_hover) { char *message = NULL; byte color[4] = {0, 0, 0, 0}; if(!hud_hover) { return; } if (selected_hud) { switch(hud_editor_mode) { case hud_editmode_move_lockedaxis : case hud_editmode_move_resize : { message = va("(%d, %d) moving %s", (int)selected_hud->pos_x->value, (int)selected_hud->pos_y->value, selected_hud->name); color[0] = 255; color[3] = 125; break; } case hud_editmode_align : { char *align = NULL; align = HUD_Editor_GetAlignmentString(hud_alignmode); message = va("align %s to %s", selected_hud->name, align); color[1] = 255; color[2] = 255; color[3] = 125; break; } case hud_editmode_place : { message = va("placing %s", selected_hud->name); color[0] = 255; color[3] = 125; break; } case hud_editmode_normal : { message = hud_hover->name; color[2] = 255; color[3] = 125; break; } // unhandled case hud_editmode_off: case hud_editmode_resize: case hud_editmode_hudmenu: case hud_editmode_menu: case hud_editmode_hoverlist: break; } } if(!message) { message = hud_hover->name; color[2] = 255; color[3] = 125; } HUD_Editor_DrawTooltip(hud_mouse_x, hud_mouse_y, message, color[0], color[1], color[2], color[3]); } // // Draws a help window. // static void HUD_Editor_DrawHelp() { #define HUD_EDITOR_HELP_BORDER 32 #define HUD_EDITOR_HELP_WIDTH min(vid.width - (2 * HUD_EDITOR_HELP_BORDER), 500) #define HUD_EDITOR_HELP_HEIGHT (vid.height - (2 * HUD_EDITOR_HELP_BORDER)) #define HUD_EDITOR_HELP_X ((vid.width - HUD_EDITOR_HELP_WIDTH) / 2) #define HUD_EDITOR_HELP_Y HUD_EDITOR_HELP_BORDER #define HUD_EDITOR_HELP_TITLE "&cfd0HUD EDITOR HELP" Draw_TextBox(HUD_EDITOR_HELP_X, HUD_EDITOR_HELP_Y, HUD_EDITOR_HELP_WIDTH / 8, HUD_EDITOR_HELP_HEIGHT / 8); Draw_ColoredString( HUD_EDITOR_HELP_X + ((HUD_EDITOR_HELP_WIDTH - strlen(HUD_EDITOR_HELP_TITLE) * 8) / 2), HUD_EDITOR_HELP_Y + 10, HUD_EDITOR_HELP_TITLE, 1); UI_PrintTextBlock( HUD_EDITOR_HELP_X + 10, HUD_EDITOR_HELP_Y + 30, HUD_EDITOR_HELP_WIDTH, HUD_EDITOR_HELP_HEIGHT - 30, "The HUD Editor helps you to customize your Heads Up Display. " "When you move the cursor over a HUD element it will be " "highlighted and it's name will be shown. When hovering a HUD " "you can perform the following actions:\n" "\n" "&cfd0MOVE&r relative to the HUD elements parent/alignment by " "holding down &c0dfMOUSE 1&r and &c0dfdragging&r.\n" "(Lock movement to a specific axis by holding down &c0dfSHIFT&r).\n" "\n" "&cfd0RESIZE&r the HUD element by clicking on one of the " "&c0dfresize handles&r that appears when hovering and item and " "&c0dfdragging&r. (Not all HUD elements are resizeable/scaleable).\n" "\n" "&cfd0PLACE&r the HUD element at another HUD element or a location " "such as the screen/console by holding down &c0dfCTRL&r when " "dragging. The target that the element will be placed in " "will turn green if you can place it there, red otherwise.\n" "\n" "&cfd0ALIGN&r the HUD element in different ways to it's parent by " "holding down &c0dfALT&r when dragging. Doing this will show " "yellow highlights at the position you're about to align to.\n" "\n" " &cfd0Keyboard shortcuts:\n" " &c0dfP&r Toggle HUD planmode on/off (default on).\n" " &c0dfH&r Toggle this help.\n" " &c0dfF1&r Toggle if moving should be allowed.\n" " &c0dfF2&r Toggle resizing.\n" " &c0dfF3&r Toggle aligning.\n" " &c0dfF4&r Toggle placing.\n" " &c0dfSPACE&r Toggle outlines/guidelines.\n", 0); } #ifdef HAXX int Test_OnGotFocus(ez_control_t *self, void *payload, void *ext_event_info) { EZ_control_SetBackgroundColor(self, self->background_color[0], self->background_color[1], self->background_color[2], 200); return 0; } int Test_OnLostFocus(ez_control_t *self, void *payload, void *ext_event_info) { EZ_control_SetBackgroundColor(self, self->background_color[0], self->background_color[1], self->background_color[2], 100); return 0; } ez_control_t *root = NULL; ez_control_t *child1 = NULL; ez_control_t *child2 = NULL; ez_button_t *button = NULL; ez_label_t *label = NULL; ez_label_t *label2 = NULL; ez_slider_t *slider = NULL; ez_scrollbar_t *scrollbar = NULL; ez_scrollpane_t *scrollpane = NULL; ez_listview_t *listview = NULL; ez_window_t *window = NULL; int Test_OnButtonDraw(ez_control_t *self, void *payload, void *ext_event_info) { int x, y; EZ_control_GetDrawingPosition(self, &x, &y); return 0; } int Test_OnSliderPositionChanged(ez_control_t *self, void *payload, void *ext_event_info) { ez_slider_t *slider = (ez_slider_t *)self; int slider_pos = EZ_slider_GetPosition(slider); EZ_label_SetText(label2, va("%i", slider_pos)); return 0; } int Test_OnControlDraw(ez_control_t *self, void *payload, void *ext_event_info) { int x, y; //, i; EZ_control_GetDrawingPosition(self, &x, &y); /*for (i = 0; i < 30; i++) { Draw_String(x, y + i*8, va("%d%d%d%d", i, i, i, i)); }*/ /* { char str[] = "Hello this is a sentence that's supposed to fit within a box of stuff, I hope this works..."; char line[1024]; int last_index = 0; int i = 0; while (Util_GetNextWordwrapString(str, line, last_index, &last_index, sizeof(str) / sizeof(char), self->width, 8)) { Draw_String(x, y + i*8, line); i++; } } */ /*{ clrinfo_t color; color.i = 0; color.c = RGBA_TO_COLOR(0, 255, 0, 255); Draw_BigString(x, y, "Hej", &color, 1, 1, 1, 0); }*/ return 0; } #endif static hud_t *hud_hover = NULL; // // Main HUD Editor function. // static void HUD_Editor(void) { qbool found = false; // If we just entered hoverlist mode we want to keep the mouse coordinates // so we know where to draw the list until the user has picked a HUD. if (!hud_hoverlist_pos_is_set && hud_editor_mode == hud_editmode_hoverlist && hud_editor_prevmode != hud_editmode_hoverlist) { hud_hoverlist_x = cursor_x; hud_hoverlist_y = cursor_y; hud_hoverlist_pos_is_set = true; } else if (hud_editor_mode != hud_editmode_hoverlist) { hud_hoverlist_pos_is_set = false; } // Find the HUD we're moving or have the cursor over. found = HUD_Editor_FindHudUnderCursor(&hud_hover); // Draw faint outlines for all visible hud elements. HUD_Editor_DrawOutlines(); // Draw the "grep handles" for offscreen HUDs. HUD_Editor_DrawGreps(); // Draw a rectangle around the currently active HUD element. if(found && hud_hover) { Draw_AlphaRectangleRGB(hud_hover->lx, hud_hover->ly, hud_hover->lw, hud_hover->lh, 1, false, 0, 255, 0, 255); } // If we are realigning draw a green outline for the selected hud element. if (selected_hud) { Draw_AlphaRectangleRGB(selected_hud->lx, selected_hud->ly, selected_hud->lw, selected_hud->lh, 2, false, 0, 255, 0, 255); } // Check the mouse/keyboard states and if we're hovering above a hud or not. HUD_Editor_EvaluateState(hud_hover); // Draw the child/parent connections the hud we're hovering has. HUD_Editor_DrawConnections(hud_hover); // Draw a red line from selected hud to cursor. if (selected_hud) { Draw_AlphaLineRGB(hud_mouse_x, hud_mouse_y, HUD_CENTER_X(selected_hud), HUD_CENTER_Y(selected_hud), 1, 255, 0, 0, 255); } // Check if we're performing any action. // (Only perform one at any given time). (void) (HUD_Editor_DrawHoverList(hud_hoverlist_x, hud_hoverlist_y, hud_hoverlist) || HUD_Editor_Resizing(hud_hover) || HUD_Editor_Moving(hud_hover) || HUD_Editor_Placing(hud_hover) || HUD_Editor_Aligning(hud_hover)); // Draw tooltips for the HUD. HUD_Editor_DrawTooltips(hud_hover); // Show the help window? if(hud_editor_showhelp) { HUD_Editor_DrawHelp(); } #ifdef HAXX EZ_tree_EventLoop(&help_control_tree); #endif } // // Toggles the HUD Editor on or off. // void HUD_Editor_Toggle_f(void) { // static keydest_t key_dest_prev = key_game; static int old_hud_planmode = 0; if (cls.state != ca_active) { // We can't turn on the hud editor when disconnected. if(!hud_editor) { Com_Printf("You need to be in game to use the HUD editor.\n"); } // If the hud editor managed to still be on while disconnected. hud_editor = false; } #ifdef HAXX else if (!scr_newHud->value) { Com_Printf("You have to have scr_newHud turned on to use the HUD editor.\n"); hud_editor = false; } #endif else { // Toggle. hud_editor = !hud_editor; // S_LocalSound("misc/basekey.wav"); } if (hud_editor) { // Start HUD Editor. inputfuncs->SetMenuFocus(true, "", 0, 0, 0); HUD_Editor_SetMode(hud_editmode_normal); // Set planmode by default. old_hud_planmode = hud_planmode->value; Cvar_SetValue(hud_planmode, 1.0); // Start showing the help plaque so the user learns the controls. hud_editor_showhelp = true; } else { // Exit the HUD Editor. inputfuncs->SetMenuFocus(false, "", 0, 0, 0); HUD_Editor_SetMode(hud_editmode_off); scr_cursor_icon = NULL; // Reset to the old value for HUD planmode. Cvar_SetValue(hud_planmode, old_hud_planmode); } } // // Handles mouse events sent to the HUD editor. // qbool HUD_Editor_MouseEvent(float x, float y) { // Updating cursor location. if(hud_editor_mode == hud_editmode_move_lockedaxis) { // Don't update the HUD Editor cursor if the axis is locked // so that we avoid explicit checks for that. // The cursor will still move around the screen properly. if(hud_editor_locked_axis_is_x) { hud_mouse_x = x; // Draw a line that indicates that the movement is locked to the X-axis. if (selected_hud) { Draw_AlphaLineRGB(0, HUD_CENTER_Y(selected_hud), vid.width, HUD_CENTER_Y(selected_hud), 1, 255, 0, 0, 75); } } else { hud_mouse_y = y; if (selected_hud) { Draw_AlphaLineRGB(HUD_CENTER_X(selected_hud), 0, HUD_CENTER_X(selected_hud), vid.height, 1, 255, 0, 0, 75); } } } else { // Normal operation, always update cursor. hud_mouse_x = x; hud_mouse_y = y; } #ifdef HAXX return EZ_tree_MouseEvent(&help_control_tree, ms); #else return true; #endif } // // Handles key events sent to the HUD editor. // void HUD_Editor_Key(int key, int unichar, qbool down) { static int planmode = 1; #ifdef HAXX int togglekeys[2]; EZ_tree_KeyEvent(&help_control_tree, key, unichar, down); M_FindKeysForCommand("toggleconsole", togglekeys); if ((key == togglekeys[0]) || (key == togglekeys[1])) { Con_ToggleConsole_f(); return; } #endif if (down) { switch (key) { case K_ESCAPE: case K_GP_BACK: HUD_Editor_Toggle_f(); break; case 'p' : // Toggle HUD plan mode. planmode = !planmode; Cvar_SetValue(hud_planmode, planmode); break; case 'h' : // Toggle the help window. hud_editor_showhelp = !hud_editor_showhelp; break; case K_SPACE : // Toggle hud element outlines. hud_editor_showoutlines = !hud_editor_showoutlines; break; case K_F1 : // Toggle moving. Cvar_SetValue(hud_editor_allowmove, !hud_editor_allowmove->value); break; case K_F2 : // Toggle resizing. Cvar_SetValue(hud_editor_allowresize, !hud_editor_allowresize->value); break; case K_F3 : // Toggle aligning. Cvar_SetValue(hud_editor_allowalign, !hud_editor_allowalign->value); break; case K_F4 : // Toggle placing. Cvar_SetValue(hud_editor_allowplace, !hud_editor_allowplace->value); break; case K_UPARROW : case K_KP_UPARROW: case K_GP_DPAD_UP: // TODO : Add "nudging" in hud editor. break; case K_DOWNARROW : case K_KP_DOWNARROW: case K_GP_DPAD_DOWN: // TODO : Add "nudging" in hud editor. break; case K_LEFTARROW : case K_KP_LEFTARROW: case K_GP_DPAD_LEFT: // TODO : Add "nudging" in hud editor. break; case K_RIGHTARROW : case K_KP_RIGHTARROW: case K_GP_DPAD_RIGHT: // TODO : Add "nudging" in hud editor. break; } } } // // Inits HUD Editor. // void HUD_Editor_Init(void) { extern mpic_t *SCR_LoadCursorImage(char *cursorimage); #if 0 clrinfo_t color; color.c = RGBA_TO_COLOR(255, 255, 255, 255); color.i = 0; // Root { root = EZ_control_Create(&help_control_tree, NULL, "Test window", "Test", 50, 50, 400, 400, control_focusable | control_movable | control_resize_h | control_resize_v); EZ_control_SetBackgroundColor(root, 0, 0, 0, 100); EZ_control_SetSize(root, 400, 400); } // Child 1 { child1 = EZ_control_Create(&help_control_tree, root, "Child 1", "Test", 10, 10, 50, 50, control_focusable | control_movable | control_contained | control_scrollable | control_resizeable); EZ_control_AddOnGotFocus(child1, Test_OnGotFocus, NULL); EZ_control_AddOnLostFocus(child1, Test_OnLostFocus, NULL); EZ_control_AddOnDraw(child1, Test_OnControlDraw, NULL); EZ_control_SetMinVirtualSize(child1, child1->width * 3, child1->height * 3); //EZ_control_SetVirtualSize(child1, child1->width * 4, child1->height * 2); EZ_control_SetBackgroundColor(child1, 150, 150, 0, 100); } // Child 2 { child2 = EZ_control_Create(&help_control_tree, root, "Child 2", "Test", 30, 50, 50, 20, control_focusable | control_contained); EZ_control_AddOnGotFocus(child2, Test_OnGotFocus, NULL); EZ_control_AddOnLostFocus(child2, Test_OnLostFocus, NULL); EZ_control_SetBackgroundColor(child2, 150, 150, 200, 100); } // Button. { button = EZ_button_Create(&help_control_tree, child1, "button", "A crazy button!", 15, -15, 80, 60, control_contained | control_resizeable); EZ_control_AddOnDraw((ez_control_t *)button, Test_OnButtonDraw, NULL); EZ_button_SetFocusedColor(button, 255, 0, 0, 255); EZ_button_SetNormalColor(button, 255, 255, 0, 100); EZ_button_SetPressedColor(button, 255, 255, 0, 255); EZ_button_SetHoverColor(button, 255, 0, 0, 150); EZ_button_SetToggleable(button, true); EZ_button_SetText(button, "Button"); EZ_button_SetTextAlignment(button, middle_center); EZ_control_SetAnchor((ez_control_t *)button, (anchor_left | anchor_right | anchor_bottom)); } // Label. { label = EZ_label_Create(&help_control_tree, root, "label", "A crazy label!", 200, 200, 250, 80, control_focusable | control_contained | control_resizeable | control_scrollable /*| control_movable */ | control_resize_h | control_resize_v, label_wraptext | label_autosize, "Hello\nthis is a test are you fine because I am bla bla bla this is a very long string and it's plenty of fun haha!"); EZ_label_SetTextScale(label, 2.0); //EZ_label_SetTextFlags(label, LABEL_READONLY); EZ_control_SetBackgroundColor((ez_control_t *)label, 150, 150, 0, 50); //EZ_control_SetAnchor((ez_control_t *)label, anchor_top | anchor_right | anchor_bottom); } // Label 2. { label2 = EZ_label_Create(&help_control_tree, root, "label2", "A crazy label!", 100, 50, 32, 16, control_focusable | control_contained | control_resizeable, 0, ""); } // Slider. { slider = EZ_slider_Create(&help_control_tree, root, "slider", "Slider omg", 50, 100, 150, 8, control_focusable | control_contained | control_resizeable); EZ_control_SetAnchor((ez_control_t *)slider, anchor_left | anchor_right); EZ_slider_SetMax(slider, 100); EZ_slider_SetMin(slider, 50); EZ_slider_SetPosition(slider, 5); EZ_slider_SetScale(slider, 1.0); EZ_slider_AddOnSliderPositionChanged(slider, Test_OnSliderPositionChanged, NULL); } /* // Scrollbar. { ez_control_t *label_ctrl = (ez_control_t *)label; scrollbar = EZ_scrollbar_Create(&help_control_tree, root, "Scrollbar", "", 30, 150, 10, 150, control_anchor_viewport); EZ_scrollbar_SetTargetParent(scrollbar, false); //EZ_control_SetContained((ez_control_t *)scrollbar, false); EZ_control_SetAnchor((ez_control_t *)scrollbar, anchor_right | anchor_top | anchor_bottom); EZ_control_SetMovable((ez_control_t *)scrollbar, false); } */ // Listview { listview = EZ_listview_Create(&help_control_tree, root, "Listview", "", 50, 50, 200, 200, control_resize_h | control_resize_v | control_resizeable); EZ_listview_SetHeaderText(listview, 0, "Hej"); EZ_listview_SetHeaderText(listview, 1, "Hej 2"); EZ_listview_SetColumnWidth(listview, 0, 80); EZ_listview_SetColumnWidth(listview, 1, 50); } // Scrollpane { scrollpane = EZ_scrollpane_Create(&help_control_tree, root, "Scrollpane", "", -10, -20, 150, 150, control_resize_h | control_resize_v | control_resizeable); EZ_control_SetBackgroundColor((ez_control_t *)scrollpane, 255, 0, 0, 100); //EZ_scrollpane_SetTarget(scrollpane, child1); EZ_scrollpane_SetTarget(scrollpane, (ez_control_t *)listview); } // Window. { window = EZ_window_Create(&help_control_tree, root, "Window", NULL, 20, 20, 150, 150, control_movable | control_focusable | control_resize_h | control_resize_v | control_contained); EZ_control_SetBackgroundColor((ez_control_t *)window, 0, 100, 0, 100); EZ_window_SetWindowAreaMinVirtualSize(window, 200, 200); //EZ_window_AddChild(window, (ez_control_t *)scrollpane); } /* // Test. { ez_control_t *c = EZ_control_Create(&help_control_tree, root, "C test 1", "Test", 10, 10, 150, 150, control_resize_h | control_focusable | control_movable | control_contained | control_scrollable | control_resizeable); ez_control_t *c2 = EZ_control_Create(&help_control_tree, c, "C test 1", "Test", 0, 10, 30, 10, control_focusable | control_movable | control_contained | control_scrollable | control_resizeable); EZ_control_SetAnchor(c2, anchor_top | anchor_right); EZ_control_SetBackgroundColor(c2, 150, 0, 20, 100); EZ_control_SetBackgroundColor(c, 50, 40, 50, 100); } */ EZ_tree_Refresh(&help_control_tree); #endif // Register commands. Cmd_AddCommand("hud_editor", HUD_Editor_Toggle_f); // Register variables. hud_editor_allowresize = cvarfuncs->GetNVFDG("hud_editor_allowresize", "1", 0, NULL, "hud"); hud_editor_allowmove = cvarfuncs->GetNVFDG("hud_editor_allowmove", "1", 0, NULL, "hud"); hud_editor_allowplace = cvarfuncs->GetNVFDG("hud_editor_allowplace", "1", 0, NULL, "hud"); hud_editor_allowalign = cvarfuncs->GetNVFDG("hud_editor_allowalign", "1", 0, NULL, "hud"); // Load HUD editor cursor icons. hud_editor_move_icon = SCR_LoadCursorImage("gfx/hud_move_icon"); hud_editor_resize_icon = SCR_LoadCursorImage("gfx/hud_resize_icon"); hud_editor_align_icon = SCR_LoadCursorImage("gfx/hud_align_icon"); hud_editor_place_icon = SCR_LoadCursorImage("gfx/hud_place_icon"); hud_editor = false; HUD_Editor_SetMode(hud_editmode_off); } // // Draws the HUD Editor if it's on. // void HUD_Editor_Draw(void) { if (!hud_editor) return; HUD_Editor(); } // // Should this HUD element be fully drawn or not when in align mode // when using the HUD editor? // qbool HUD_Editor_ConfirmDraw(hud_t *hud) { if(hud_editor_mode == hud_editmode_align || hud_editor_mode == hud_editmode_place) { // If this is the selected hud, or the parent of the selected hud then draw it. if((selected_hud && !strcmp(selected_hud->name, hud->name)) || (selected_hud && hud->place_hud && !strcmp(selected_hud->name, hud->place_hud->name))) { return true; } return false; } return true; }