From 60777154becba0ad64bd69a981b69c102664fc47 Mon Sep 17 00:00:00 2001 From: Mike Nelson Date: Sat, 22 Mar 2025 21:47:38 -0500 Subject: [PATCH] Hud config upgrades (#6581) * base working version * localization and minor tweaks * add retail UI controls * Add way to hide gauges from Config view * convert hud config from index matching to id matching * clang --- code/hud/hud.cpp | 215 +++- code/hud/hud.h | 19 +- code/hud/hudconfig.cpp | 1639 +++++++++++-------------- code/hud/hudconfig.h | 277 +++-- code/hud/hudescort.cpp | 2 +- code/hud/hudets.cpp | 10 +- code/hud/hudlock.cpp | 2 +- code/hud/hudmessage.cpp | 6 +- code/hud/hudobserver.cpp | 9 +- code/hud/hudparse.cpp | 102 +- code/hud/hudreticle.cpp | 12 +- code/hud/hudshield.cpp | 6 +- code/hud/hudsquadmsg.cpp | 2 +- code/hud/hudtarget.cpp | 32 +- code/hud/hudtargetbox.cpp | 4 +- code/hud/hudwingmanstatus.cpp | 2 +- code/localization/localize.cpp | 2 +- code/mission/missiontraining.cpp | 4 +- code/parse/sexp.cpp | 3 +- code/pilotfile/csg.cpp | 108 +- code/pilotfile/plr.cpp | 107 +- code/radar/radar.cpp | 2 +- code/radar/radarorb.cpp | 2 +- code/scripting/api/libs/hud.cpp | 12 +- code/scripting/api/libs/ui.cpp | 60 +- code/scripting/api/objs/hudconfig.cpp | 64 +- code/scripting/api/objs/hudconfig.h | 11 +- 27 files changed, 1507 insertions(+), 1207 deletions(-) diff --git a/code/hud/hud.cpp b/code/hud/hud.cpp index 6e96d7d384..9547810a73 100644 --- a/code/hud/hud.cpp +++ b/code/hud/hud.cpp @@ -198,6 +198,49 @@ void hud_maybe_display_subspace_notify(); int hud_maybe_render_emp_icon(); void hud_init_emp_icon(); +static bool hud_config_use_iff_color(int gauge_index) +{ + switch (gauge_index) { + case HUD_LEAD_INDICATOR: + case HUD_ORIENTATION_TEE: + case HUD_HOSTILE_TRIANGLE: + case HUD_TARGET_TRIANGLE: + case HUD_OFFSCREEN_INDICATOR: + case HUD_MISSILE_WARNING_ARROW: + return true; + default: + return false; + } +} + +static bool hud_config_can_popup(int gauge_index) +{ + switch (gauge_index) { + case HUD_ETS_GAUGE: + case HUD_AUTO_TARGET: + case HUD_AUTO_SPEED: + case HUD_WEAPONS_GAUGE: + case HUD_ESCORT_VIEW: + case HUD_TARGET_MINI_ICON: + case HUD_DAMAGE_GAUGE: + case HUD_CMEASURE_GAUGE: + case HUD_KILLS_GAUGE: + return true; + default: + return false; + } +} + +static bool hud_config_use_tag_color(int gauge_index) +{ + switch (gauge_index) { + case HUD_MISSILE_WARNING_ARROW: + return true; + default: + return false; + } +} + // Saturate a value in minv..maxv. void saturate(int *i, int minv, int maxv) { @@ -247,7 +290,7 @@ static int Damage_flash_bright; static int Damage_flash_timer; HudGauge::HudGauge(): -base_w(0), base_h(0), gauge_config(-1), font_num(font::FONT1), lock_color(false), sexp_lock_color(false), reticle_follow(false), +base_w(0), base_h(0), gauge_type(-1), font_num(font::FONT1), lock_color(false), sexp_lock_color(false), reticle_follow(false), active(false), off_by_default(false), sexp_override(false), pop_up(false), disabled_views(0), only_render_in_chase_view(false), render_for_cockpit_toggle(0), custom_gauge(false), texture_target(-1), canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1) { @@ -259,6 +302,13 @@ texture_target(-1), canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1) flash_next = timestamp(1); flash_status = false; + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + + gauge_config_id = ""; //gauge_map.get_string_id_from_numeric_id(_gauge_config); + can_popup = hud_config_can_popup(gauge_map.get_numeric_id_from_string_id(gauge_config_id)); + use_iff_color = hud_config_use_iff_color(gauge_map.get_numeric_id_from_string_id(gauge_config_id)); + use_tag_color = hud_config_use_tag_color(gauge_map.get_numeric_id_from_string_id(gauge_config_id)); + popup_timer = timestamp(1); texture_target_fname[0] = '\0'; @@ -271,12 +321,12 @@ texture_target(-1), canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1) } HudGauge::HudGauge(int _gauge_object, int _gauge_config, bool _slew, bool _message, int _disabled_views, int r, int g, int b): -base_w(0), base_h(0), gauge_config(_gauge_config), gauge_object(_gauge_object), font_num(font::FONT1), lock_color(false), sexp_lock_color(false), +base_w(0), base_h(0), gauge_type(_gauge_config), gauge_object(_gauge_object), font_num(font::FONT1), lock_color(false), sexp_lock_color(false), reticle_follow(_slew), active(false), off_by_default(false), sexp_override(false), pop_up(false), message_gauge(_message), disabled_views(_disabled_views), only_render_in_chase_view(false), render_for_cockpit_toggle(0), custom_gauge(false), textoffset_x(0), textoffset_y(0), texture_target(-1), canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1) { - Assert(gauge_config <= NUM_HUD_GAUGES && gauge_config >= 0); + Assertion(_gauge_config <= NUM_HUD_GAUGES && _gauge_config >= 0, "Gauge has an invalid config ID!"); position[0] = 0; position[1] = 0; @@ -297,6 +347,14 @@ canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1) texture_target_fname[0] = '\0'; + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + + gauge_config_id = gauge_map.get_string_id_from_numeric_id(_gauge_config); + config_name = gauge_map.get_hcf_name_from_string_id(gauge_config_id); + can_popup = hud_config_can_popup(gauge_map.get_numeric_id_from_string_id(gauge_config_id)); + use_iff_color = hud_config_use_iff_color(gauge_map.get_numeric_id_from_string_id(gauge_config_id)); + use_tag_color = hud_config_use_tag_color(gauge_map.get_numeric_id_from_string_id(gauge_config_id)); + custom_name[0] = '\0'; custom_text = ""; default_text = ""; @@ -307,10 +365,10 @@ canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1) // constructor for custom gauges HudGauge::HudGauge(int _gauge_config, bool _slew, int r, int g, int b, char* _custom_name, char* _custom_text, char* frame_fname, int txtoffset_x, int txtoffset_y): -base_w(0), base_h(0), gauge_config(_gauge_config), gauge_object(HUD_OBJECT_CUSTOM), font_num(font::FONT1), lock_color(false), sexp_lock_color(false), +base_w(0), base_h(0), gauge_type(_gauge_config), gauge_object(HUD_OBJECT_CUSTOM), font_num(font::FONT1), lock_color(false), sexp_lock_color(false), reticle_follow(_slew), active(false), off_by_default(false), sexp_override(false), pop_up(false), message_gauge(false), -disabled_views(VM_EXTERNAL | VM_DEAD_VIEW | VM_WARP_CHASE | VM_PADLOCK_ANY), only_render_in_chase_view(false), render_for_cockpit_toggle(0), custom_gauge(true), textoffset_x(txtoffset_x), -textoffset_y(txtoffset_y), texture_target(-1), canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1) +disabled_views(VM_EXTERNAL | VM_DEAD_VIEW | VM_WARP_CHASE | VM_PADLOCK_ANY), can_popup(false), use_iff_color(false), use_tag_color(false), only_render_in_chase_view(false), +render_for_cockpit_toggle(0), custom_gauge(true), textoffset_x(txtoffset_x), textoffset_y(txtoffset_y), texture_target(-1), canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1) { position[0] = 0; position[1] = 0; @@ -325,6 +383,13 @@ textoffset_y(txtoffset_y), texture_target(-1), canvas_w(-1), canvas_h(-1), targe flash_next = timestamp(1); flash_status = false; + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + + gauge_config_id = ""; // gauge_map.get_string_id_from_numeric_id(_gauge_config); + can_popup = hud_config_can_popup(gauge_map.get_numeric_id_from_string_id(gauge_config_id)); + use_iff_color = hud_config_use_iff_color(gauge_map.get_numeric_id_from_string_id(gauge_config_id)); + use_tag_color = hud_config_use_tag_color(gauge_map.get_numeric_id_from_string_id(gauge_config_id)); + popup_timer = timestamp(1); texture_target_fname[0] = '\0'; @@ -335,6 +400,8 @@ textoffset_y(txtoffset_y), texture_target(-1), canvas_w(-1), canvas_h(-1), targe custom_name[0] = '\0'; } + config_name = custom_name; + if(_custom_text) { custom_text = _custom_text; default_text = _custom_text; @@ -390,6 +457,36 @@ void HudGauge::initFont(int input_font_num) } } +SCP_string HudGauge::getConfigName() const +{ + return config_name; +} + +SCP_string HudGauge::getConfigId() const +{ + return gauge_config_id; +} + +bool HudGauge::getConfigUseIffColor() const +{ + return use_iff_color; +} + +bool HudGauge::getConfigCanPopup() const +{ + return can_popup; +} + +bool HudGauge::getConfigUseTagColor() const +{ + return use_tag_color; +} + +bool HudGauge::getVisibleInConfig() const +{ + return visible_in_config; +} + int HudGauge::getFont() const { return font_num; @@ -485,34 +582,43 @@ void HudGauge::setGaugeColor(int bright_index, bool config) int alpha; if (config) { - color* use_color; - use_color = &HUD_config.clr[gauge_config]; + color use_color; + if (custom_gauge) { + // Custom gauges currently use the color based on their gauge type + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + use_color = HUD_config.get_gauge_color(gauge_map.get_string_id_from_numeric_id(gauge_type)); + } else { + use_color = HUD_config.get_gauge_color(gauge_config_id); + } - if (hud_config_show_flag_is_set(gauge_config)) { - // Eventually we should allow custom gauges to use IFF colors maybe? Then we can unhardcode this - // and rely on the gauge data itself. But for now only specific gauges use iff and that's hard coded here - if (HC_gauge_regions[gr_screen.res][gauge_config].use_iff) { + if (!custom_gauge && HUD_config.is_gauge_visible(gauge_config_id)) { + if (use_iff_color) { // Ditto for target tagging color - if (HC_gauge_regions[gr_screen.res][gauge_config].color == 1) { - use_color = iff_get_color(IFF_COLOR_TAGGED, 0); + if (use_tag_color) { + use_color = *iff_get_color(IFF_COLOR_TAGGED, 0); } else { - use_color = &Color_bright_red; + use_color = Color_bright_red; } } - if ((HC_gauge_selected == gauge_config) || HC_select_all) { + if ((HC_gauge_selected == gauge_config_id) || HC_select_all) { alpha = 255; - } else if (HC_gauge_hot == gauge_config) { + } else if (HC_gauge_hot == gauge_config_id) { alpha = 200; } else { alpha = 150; } - gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha); - gr_set_color_fast(use_color); + gr_init_alphacolor(&use_color, use_color.red, use_color.green, use_color.blue, alpha); + gr_set_color_fast(&use_color); + } else if (custom_gauge) { + // Custom gauges currently use the current color but alpha dimmed since they are not selectable + alpha = MAX(use_color.alpha - 50, 25); + gr_init_alphacolor(&use_color, use_color.red, use_color.green, use_color.blue, alpha); + gr_set_color_fast(&use_color); } else { // if its off, make it dark gray - gr_init_alphacolor(use_color, 127, 127, 127, 64); - gr_set_color_fast(use_color); + gr_init_alphacolor(&use_color, 127, 127, 127, 64); + gr_set_color_fast(&use_color); } } else { // if we're drawing it as bright @@ -603,7 +709,7 @@ float HudGauge::getAspectQuotient() const int HudGauge::getConfigType() const { - return gauge_config; + return gauge_type; } int HudGauge::getObjectType() const @@ -654,6 +760,11 @@ void HudGauge::initCockpit_view_choice(int cockpit_view_choice) render_for_cockpit_toggle = cockpit_view_choice; } +void HudGauge::initVisible_in_config(bool visible) +{ + visible_in_config = visible; +} + bool HudGauge::isOffbyDefault() const { return off_by_default; @@ -763,7 +874,7 @@ void HudGauge::render(float /*frametime*/, bool config) // The following code will be used to allow custom coloring of custom HUD gauges. This will be implemented in the future. /*int bmw, bmh; bm_get_info(custom_frame.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + static_cast(bmw * scale), y, y + static_cast(bmh * scale));*/ + hud_config_set_mouse_coords(gauge_config_id, x, x + static_cast(bmw * scale), y, y + static_cast(bmh * scale));*/ } setGaugeColor(HUD_C_NONE, config); @@ -1295,7 +1406,7 @@ bool HudGauge::canRender() const } } - if (gauge_config == HUD_ETS_GAUGE) { + if (gauge_type == HUD_ETS_GAUGE) { if (Ships[Player_obj->instance].flags[Ship::Ship_Flags::No_ets]) { return false; } @@ -1893,7 +2004,7 @@ void HudGaugeMissionTime::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(time_gauge.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } setGaugeColor(HUD_C_NONE, config); @@ -2494,7 +2605,7 @@ void HudGaugeDamage::render(float /*frametime*/, bool config) int bmw, bmh; bm_get_info(damage_top.first_frame, &bmw, nullptr); bm_get_info(damage_bottom.first_frame, nullptr, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, last_by + fl2i((bottom_bg_offset + bmh) * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, last_by + fl2i((bottom_bg_offset + bmh) * scale)); } } @@ -2704,7 +2815,7 @@ void HudGaugeTextWarnings::render(float /*frametime*/, bool config) gr_get_string_size(&w, &h, config ? XSTR("Collision", 1431) : Hud_text_flash, scale); if (config) { - hud_config_set_mouse_coords(gauge_config, fl2i(i2fl(x) - (i2fl(w) / 2.0f) - 1.0f), x + fl2i(i2fl(w) / 2.0f) + 2, y - 1, y + h + 1); + hud_config_set_mouse_coords(gauge_config_id, fl2i(i2fl(x) - (i2fl(w) / 2.0f) - 1.0f), x + fl2i(i2fl(w) / 2.0f) + 2, y - 1, y + h + 1); } // set color @@ -2767,7 +2878,7 @@ void HudGaugeKills::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Kills_gauge.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } setGaugeColor(HUD_C_NONE, config); @@ -2855,7 +2966,7 @@ void HudGaugeLag::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Netlag_icon.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } int lag_status = config ? 0 : multi_query_lag_status(); @@ -3170,7 +3281,7 @@ void HudGaugeSupport::render(float /*frametime*/, bool config) if (config) { std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(w * scale), y, y + fl2i(h * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(w * scale), y, y + fl2i(h * scale)); } // Set hud color @@ -3421,7 +3532,9 @@ int hud_gauge_active(int gauge_index) return 0; } - return hud_config_show_flag_is_set(gauge_index); + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + + return HUD_config.is_gauge_visible(gauge_map.get_string_id_from_numeric_id(gauge_index)); } /** @@ -3430,7 +3543,9 @@ int hud_gauge_active(int gauge_index) int hud_gauge_is_popup(int gauge_index) { Assert(gauge_index >=0 && gauge_index < NUM_HUD_GAUGES); - return hud_config_popup_flag_is_set(gauge_index); + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + SCP_string gauge = gauge_map.get_string_id_from_numeric_id(gauge_index); + return HUD_config.is_gauge_popup(gauge); } /** @@ -3498,8 +3613,10 @@ void hud_gauge_start_flash(int gauge_index) */ void hud_set_gauge_color(int gauge_index, int bright_index) { + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + int flash_status = hud_gauge_maybe_flash(gauge_index); - color *use_color = &HUD_config.clr[gauge_index]; + color use_color = HUD_config.get_gauge_color(gauge_map.get_string_id_from_numeric_id(gauge_index)); int alpha; // If we're drawing it as bright @@ -3507,17 +3624,17 @@ void hud_set_gauge_color(int gauge_index, int bright_index) switch(bright_index){ case HUD_C_DIM: alpha = HUD_high_contrast ? HUD_NEW_ALPHA_DIM_HI : HUD_NEW_ALPHA_DIM; - gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha); + gr_init_alphacolor(&use_color, use_color.red, use_color.green, use_color.blue, alpha); break; case HUD_C_NORMAL: alpha = HUD_high_contrast ? HUD_NEW_ALPHA_NORMAL_HI : HUD_NEW_ALPHA_NORMAL; - gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha); + gr_init_alphacolor(&use_color, use_color.red, use_color.green, use_color.blue, alpha); break; case HUD_C_BRIGHT: alpha = HUD_high_contrast ? HUD_NEW_ALPHA_BRIGHT_HI : HUD_NEW_ALPHA_BRIGHT; - gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha); + gr_init_alphacolor(&use_color, use_color.red, use_color.green, use_color.blue, alpha); break; // Intensity @@ -3540,27 +3657,27 @@ void hud_set_gauge_color(int gauge_index, int bright_index) if(alpha < 0){ alpha = 0; } - gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha); + gr_init_alphacolor(&use_color, use_color.red, use_color.green, use_color.blue, alpha); break; } } else { switch(flash_status) { case 0: alpha = HUD_high_contrast ? HUD_NEW_ALPHA_DIM_HI : HUD_NEW_ALPHA_DIM; - gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha); + gr_init_alphacolor(&use_color, use_color.red, use_color.green, use_color.blue, alpha); break; case 1: alpha = HUD_high_contrast ? HUD_NEW_ALPHA_BRIGHT_HI : HUD_NEW_ALPHA_BRIGHT; - gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha); + gr_init_alphacolor(&use_color, use_color.red, use_color.green, use_color.blue, alpha); break; default: alpha = HUD_high_contrast ? HUD_NEW_ALPHA_NORMAL_HI : HUD_NEW_ALPHA_NORMAL; - gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha); + gr_init_alphacolor(&use_color, use_color.red, use_color.green, use_color.blue, alpha); break; } } - gr_set_color_fast(use_color); + gr_set_color_fast(&use_color); } /** @@ -3761,7 +3878,7 @@ void HudGaugeObjectiveNotify::renderSubspace(bool config) /*std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Objective_display_gauge.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + static_cast(bmw * scale), y, y + static_cast(bmh * scale));*/ + hud_config_set_mouse_coords(gauge_config_id, x, x + static_cast(bmw * scale), y, y + static_cast(bmh * scale));*/ } bool warp_aborted = false; @@ -3818,7 +3935,7 @@ void HudGaugeObjectiveNotify::renderRedAlert(bool config) /*std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Objective_display_gauge.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + static_cast(bmw * scale), y, y + static_cast(bmh * scale));*/ + hud_config_set_mouse_coords(gauge_config_id, x, x + static_cast(bmw * scale), y, y + static_cast(bmh * scale));*/ } if (!config && !red_alert_in_progress() ) { @@ -3870,10 +3987,10 @@ void HudGaugeObjectiveNotify::renderObjective(bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Objective_display_gauge.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } - if ( timestamp_elapsed(Objective_display.display_timer) ) { + if (!config && timestamp_elapsed(Objective_display.display_timer) ) { return; } @@ -4264,7 +4381,7 @@ void HudGaugeMultiMsg::render(float /*frametime*/, bool config) /*strcpy(txt, "This is a multiplayer message"); int w, h; gr_get_string_size(&w, &h, txt, scale); - hud_config_set_mouse_coords(gauge_config, x, x + w, y, y + h); + hud_config_set_mouse_coords(gauge_config_id, x, x + w, y, y + h); setGaugeColor(HUD_C_NONE, config);*/ return; @@ -4292,7 +4409,7 @@ void HudGaugeVoiceStatus::render(float /*frametime*/, bool config) int w, h; gr_get_string_size(&w, &h, XSTR("[playing voice]", 245), scale); - hud_config_set_mouse_coords(gauge_config, x, x + w, y, y + h); + hud_config_set_mouse_coords(gauge_config_id, x, x + w, y, y + h); setGaugeColor(HUD_C_NONE, config); @@ -4352,7 +4469,7 @@ void HudGaugePing::render(float /*frametime*/, bool config) int w, h; gr_get_string_size(&w, &h, XSTR("> 1 sec",628), scale); - hud_config_set_mouse_coords(gauge_config, x, x + w, y, y + h); + hud_config_set_mouse_coords(gauge_config_id, x, x + w, y, y + h); setGaugeColor(HUD_C_NONE, config); @@ -4411,7 +4528,7 @@ void HudGaugeSupernova::render(float /*frametime*/, bool config) int w, h; gr_get_string_size(&w, &h, txt.c_str(), 245), scale); - hud_config_set_mouse_coords(gauge_config, x, x + w, y, y + h);*/ + hud_config_set_mouse_coords(gauge_config_id, x, x + w, y, y + h);*/ } if (!config && !supernova_active()) { diff --git a/code/hud/hud.h b/code/hud/hud.h index 259670acba..62c6c79447 100644 --- a/code/hud/hud.h +++ b/code/hud/hud.h @@ -217,8 +217,9 @@ protected: int position[2]; int base_w, base_h; color gauge_color; - int gauge_config; + int gauge_type; // Used to be the gauge_config numeric ID but now more accurately is used as the type. Will be one of the HUD_ defines from hudgauges.h int gauge_object; + SCP_string gauge_config_id; int font_num; @@ -241,6 +242,13 @@ protected: bool message_gauge; int disabled_views; + // Config stuff + SCP_string config_name; + bool can_popup; + bool use_iff_color; + bool use_tag_color; + bool visible_in_config; + int flash_duration; int flash_next; bool flash_status; @@ -295,6 +303,14 @@ public: bool isOffbyDefault() const; bool isActive() const; + // Config getters + SCP_string getConfigName() const; + SCP_string getConfigId() const; + bool getConfigUseIffColor() const; + bool getConfigCanPopup() const; + bool getConfigUseTagColor() const; + bool getVisibleInConfig() const; + int getFont() const; void getOriginAndOffset(float *originX, float *originY, int *offsetX, int *offsetY) const; void getCoords(bool* use_coords, int* coordsX, int* coordsY) const; @@ -308,6 +324,7 @@ public: void updateSexpOverride(bool sexp); void initChase_view_only(bool chase_view_only); void initCockpit_view_choice(int cockpit_view_choice); + void initVisible_in_config(bool visible); // SEXP interfacing functions // For flashing gauges in training missions diff --git a/code/hud/hudconfig.cpp b/code/hud/hudconfig.cpp index 66f796fe8b..fcf80ad6a7 100644 --- a/code/hud/hudconfig.cpp +++ b/code/hud/hudconfig.cpp @@ -19,6 +19,7 @@ #include "hud/hudobserver.h" #include "iff_defs/iff_defs.h" #include "io/key.h" +#include "io/mouse.h" #include "parse/parselo.h" #include "playerman/player.h" #include "popup/popup.h" @@ -35,7 +36,6 @@ int HC_current_file = -1; // current hcf file SCP_vector HC_preset_filenames; -char HC_fname[MAX_FILENAME_LEN+1] = ""; UI_INPUTBOX HC_fname_input; int HC_fname_coords[GR_NUM_RESOLUTIONS][4] = { { // GR_640 @@ -75,122 +75,74 @@ const char *Radar_range_text(int n) return NULL; } -// default flags for observer HUD -int HUD_observer_default_flags = -{ - (1< observer_visible_gauges = { + "Builtin::CenterOfReticle", + "Builtin::OffscreenIndicator", + "Builtin::MessageOutput", + "Builtin::ClosestAttackingHostile", + "Builtin::CurrentTargetDirection", + "Builtin::TargetHullShieldIcon", + "Builtin::TargetMonitor", + "Builtin::OffscreenRange" }; -int HUD_observer_default_flags2 = { - (1<<(HUD_OFFSCREEN_RANGE - 32)) -}; - -// default flags for regular HUD -int HUD_config_default_flags = -{ - (1< default_visible_gauges = { + "Builtin::LeadIndicator", + "Builtin::TargetOrientation", + "Builtin::ClosestAttackingHostile", + "Builtin::CurrentTargetDirection", + "Builtin::MissionTime", + "Builtin::Reticle", + "Builtin::Throttle", + "Builtin::Radar", + "Builtin::TargetMonitor", + "Builtin::CenterOfReticle", + "Builtin::ExtraTargetInfo", + "Builtin::TargetShield", + "Builtin::PlayerShield", + "Builtin::PowerManagement", + "Builtin::AutoTargetIcon", + "Builtin::AutoSpeedMatchIcon", + "Builtin::WeaponsDisplay", + "Builtin::MonitoringView", + "Builtin::DirectivesView", + "Builtin::ThreatGauge", + "Builtin::AfterburnerEnergy", + "Builtin::WeaponsEnergy", + "Builtin::WeaponLinking", + "Builtin::TargetHullShieldIcon", + "Builtin::OffscreenIndicator", + "Builtin::CommVideo", + "Builtin::DamageDisplay", + "Builtin::MessageOutput", + "Builtin::LockedMissileDirection", + "Builtin::Countermeasures", + "Builtin::ObjectiveNotify", + "Builtin::WingmenStatus", + "Builtin::OffscreenRange", + "Builtin::KillsGauge", + "Builtin::AttackingTargetCount", + "Builtin::SupportGauge", + "Builtin::LagGauge", + "Builtin::WarningFlash", + "Builtin::CommMenu" }; // Can be customized in hud_gauges.tbl char HC_wingam_gauge_status_names[MAX_SQUADRON_WINGS][32] = {"Alpha", "Beta", "Gamma", "Delta", "Epsilon"}; -int HC_select_all = 0; +bool HC_select_all = false; ////////////////////////////////////////////////////////////////////////////// // Module Globals ////////////////////////////////////////////////////////////////////////////// +// Coordinates for the new HUD configuration menu +const int HC_gauge_config_coords[GR_NUM_RESOLUTIONS][4] = { + {121, 615, 6, 371}, // Coordinates for 640x480 + {195, 985, 10, 595} // Coordinates for 1024x768 +}; const char *Hud_config_fname[GR_NUM_RESOLUTIONS] = { "HUDConfig", @@ -202,109 +154,9 @@ const char *Hud_config_mask_fname[GR_NUM_RESOLUTIONS] = { "2_HUDConfig-m" }; -// hud config gauges -struct HC_gauge_region HC_gauge_regions[GR_NUM_RESOLUTIONS][NUM_HUD_GAUGES] = -{ - { // GR_640 - //XSTR:OFF - HC_gauge_region("HCB_35", 407, 69, 35, 1, 0, -1, 0, 2), // lead indicator - HC_gauge_region("HCB_36", 305, 119, 36, 1, 0, -1, 0, 2), // orientation tee - HC_gauge_region("none", 1, 1, -1, 1, 0, -1, 0, 0), // hostile triangle - HC_gauge_region("HCB_37", 391, 107, 37, 1, 0, -1, 0, 2), // target triangle - HC_gauge_region("HCB_63", 575, 352, 63, 0, 0, -1, 0, 0), // mission time - HC_gauge_region("none", 1, 1, 1, 0, 0, -1, 0, 0), // reticle circle? - HC_gauge_region("HCB_40", 285, 146, 40, 0, 0, -1, 0, 0), // throttle gauge - HC_gauge_region("HCB_50", 317, 291, 50, 0, 0, -1, 0, 0), // radar - HC_gauge_region("HCB_31", 123, 249, 31, 0, 0, -1, 0, 0), // target monitor - HC_gauge_region("HCB_41", 361, 188, 41, 0, 0, -1, 0, 0), // center of reticle - HC_gauge_region("HCB_30", 123, 221, 30, 0, 0, -1, 0, 0), // extra target data - HC_gauge_region("HCB_49", 237, 303, 49, 0, 0, -1, 0, 0), // target shield icon - HC_gauge_region("HCB_51", 435, 304, 51, 0, 0, -1, 0, 0), // player shield icon - HC_gauge_region("HCB_58", 524, 299, 58, 0, 1, -1, 0, 0), // ets gauge - HC_gauge_region("HCB_61", 566, 299, 61, 0, 1, -1, 0, 0), // auto target - HC_gauge_region("HCB_62", 566, 317, 62, 0, 1, -1, 0, 0), // auto speed - HC_gauge_region("HCB_55", 504, 216, 55, 0, 1, -1, 0, 0), // weapons gauge - HC_gauge_region("HCB_54", 496, 166, 54, 0, 1, -1, 0, 0), // escort view - HC_gauge_region("HCB_29", 123, 142, 29, 0, 0, -1, 0, 0), // directives view - HC_gauge_region("HCB_43", 398, 147, 43, 0, 0, -1, 0, 0), // threat gauge - HC_gauge_region("HCB_39", 250, 212, 39, 0, 0, -1, 0, 0), // afterburner energy - HC_gauge_region("HCB_44", 449, 212, 44, 0, 0, -1, 0, 0), // weapons energy - HC_gauge_region("none", 1, 1, -1, 0, 0, -1, 0, 0), // weapon linking - HC_gauge_region("HCB_42", 356, 232, 42, 0, 1, -1, 0, 0), // target mini icon (shield) - HC_gauge_region("HCB_34", 438, 5, 34, 1, 0, -1, 0, 2), // offscreen indicator - HC_gauge_region("HCB_28", 123, 31, 28, 0, 0, -1, 0, 0), // talking head - HC_gauge_region("HCB_32", 309, 33, 32, 0, 1, -1, 0, 0), // damage gauge - HC_gauge_region("HCB_27", 124, 19, 27, 0, 0, -1, 0, 0), // message lines - HC_gauge_region("HCB_45", 307, 249, 45, 1, 0, -1, 0, 1), // missile warnings - HC_gauge_region("HCB_56", 505, 271, 56, 0, 1, -1, 0, 0), // cmeasure gauge - HC_gauge_region("HCB_33", 309, 87, 33, 0, 0, -1, 0, 0), // objectives notify gauge - HC_gauge_region("HCB_53", 546, 117, 53, 0, 0, -1, 0, 0), // wingman status gauge - HC_gauge_region("none", 1, 1, -1, 0, 0, -1, 0, 0), // offscreen indicator range - HC_gauge_region("HCB_57", 505, 285, 57, 0, 1, -1, 0, 0), // kills gauge - HC_gauge_region("none", 1, 1, -1, 0, 0, -1, 0, 0), // attacking target count - HC_gauge_region("HCB_38", 342, 138, 38, 0, 0, -1, 0, 0), // text flash gauge - HC_gauge_region("HCB_52", 465, 8, 52, 0, 0, -1, 0, 0), // comm menu - HC_gauge_region("HCB_46", 324, 264, 46, 0, 0, -1, 0, 0), // support view gauge - HC_gauge_region("HCB_47", 418, 262, 47, 0, 0, -1, 0, 0), // netlag icon gauge - //XSTR:ON - }, - { // GR_1024 - //XSTR:OFF - HC_gauge_region("2_HCB_35", 652, 112, 35, 1, 0, -1, 0, 2), // lead indicator - HC_gauge_region("2_HCB_36", 489, 191, 36, 1, 0, -1, 0, 2), // orientation tee - HC_gauge_region("none", 1, 1, -1, 1, 0, -1, 0, 0), // hostile triangle - HC_gauge_region("2_HCB_37", 626, 173, 37, 1, 0, -1, 0, 2), // target triangle - HC_gauge_region("2_HCB_63", 920, 564, 63, 0, 0, -1, 0, 0), // mission time - HC_gauge_region("none", 1, 1, 1, 0, 0, -1, 0, 0), // reticle circle? - HC_gauge_region("2_HCB_40", 456, 235, 40, 0, 0, -1, 0, 0), // throttle gauge - HC_gauge_region("2_HCB_50", 508, 466, 50, 0, 0, -1, 0, 0), // radar - HC_gauge_region("2_HCB_31", 198, 399, 31, 0, 0, -1, 0, 0), // target monitor - HC_gauge_region("2_HCB_41", 578, 302, 41, 0, 0, -1, 0, 0), // center of reticle - HC_gauge_region("2_HCB_30", 198, 354, 30, 0, 0, -1, 0, 0), // extra target data - HC_gauge_region("2_HCB_49", 380, 485, 49, 0, 0, -1, 0, 0), // target shield icon - HC_gauge_region("2_HCB_51", 696, 486, 51, 0, 0, -1, 0, 0), // player shield icon - HC_gauge_region("2_HCB_58", 839, 479, 58, 0, 1, -1, 0, 0), // ets gauge - HC_gauge_region("2_HCB_61", 906, 479, 61, 0, 1, -1, 0, 0), // auto target - HC_gauge_region("2_HCB_62", 906, 508, 62, 0, 1, -1, 0, 0), // auto speed - HC_gauge_region("2_HCB_55", 807, 346, 55, 0, 1, -1, 0, 0), // weapons gauge - HC_gauge_region("2_HCB_54", 794, 265, 54, 0, 1, -1, 0, 0), // escort view - HC_gauge_region("2_HCB_29", 198, 228, 29, 0, 0, -1, 0, 0), // directives view - HC_gauge_region("2_HCB_43", 637, 237, 43, 0, 0, -1, 0, 0), // threat gauge - HC_gauge_region("2_HCB_39", 403, 339, 39, 0, 0, -1, 0, 0), // afterburner energy - HC_gauge_region("2_HCB_44", 719, 339, 44, 0, 0, -1, 0, 0), // weapons energy - HC_gauge_region("none", 1, 1, -1, 0, 0, -1, 0, 0), // weapon linking - HC_gauge_region("2_HCB_42", 569, 371, 42, 0, 1, -1, 0, 0), // target mini icon (shield) - HC_gauge_region("2_HCB_34", 701, 9, 34, 1, 0, -1, 0, 2), // offscreen indicator - HC_gauge_region("2_HCB_28", 198, 50, 28, 0, 0, -1, 0, 0), // talking head - HC_gauge_region("2_HCB_32", 495, 55, 32, 0, 1, -1, 0, 0), // damage gauge - HC_gauge_region("2_HCB_27", 199, 30, 27, 0, 0, -1, 0, 0), // message lines - HC_gauge_region("2_HCB_45", 491, 399, 45, 1, 0, -1, 0, 1), // missile warnings - HC_gauge_region("2_HCB_56", 808, 433, 56, 0, 1, -1, 0, 0), // cmeasure gauge - HC_gauge_region("2_HCB_33", 495, 141, 33, 0, 0, -1, 0, 0), // objectives notify gauge - HC_gauge_region("2_HCB_53", 873, 188, 53, 0, 0, -1, 0, 0), // wingman status gauge - HC_gauge_region("none", 1, 1, -1, 0, 0, -1, 0, 0), // offscreen indicator range - HC_gauge_region("2_HCB_57", 808, 456, 57, 0, 1, -1, 0, 0), // kills gauge - HC_gauge_region("none", 1, 1, -1, 0, 0, -1, 0, 0), // attacking target count - HC_gauge_region("2_HCB_38", 548, 222, 38, 0, 0, -1, 0, 0), // text flash gauge - HC_gauge_region("2_HCB_52", 744, 14, 52, 0, 0, -1, 0, 0), // comm menu - HC_gauge_region("2_HCB_46", 520, 422, 46, 0, 0, -1, 0, 0), // support view gauge - HC_gauge_region("2_HCB_47", 670, 419, 47, 0, 0, -1, 0, 0), // netlag icon gauge - //XSTR:ON - } -}; - -/** - * @brief x y coordinates of gauges for hud preview display - * - * @note used for scaling the positions properly when the preview display is scaled - */ -struct gauge_coords { - int x; // x coordinate position - int y; // y coordinate position -}; - -SCP_vector HC_gauge_coords; - +// keep a list of gauge pointers so we can easily get information from them +SCP_vector> HC_gauge_map; +bool HC_gauge_list_clear = true; int HC_gauge_description_coords[GR_NUM_RESOLUTIONS][3] = { { // GR_640 @@ -318,212 +170,149 @@ int HC_gauge_description_coords[GR_NUM_RESOLUTIONS][3] = { int HC_talking_head_frame = -1; SCP_string HC_head_anim_filename; SCP_string HC_shield_gauge_ship; +bool HC_show_default_hud = true; +std::unordered_set HC_ignored_huds; int HC_resize_mode = GR_RESIZE_MENU; -const char *HC_gauge_descriptions(int n) -{ - switch(n) { - case 0: - return XSTR( "lead indicator", 249); - case 1: - return XSTR( "target orientation", 250); - case 2: - return XSTR( "closest attacking hostile", 251); - case 3: - return XSTR( "current target direction", 252); - case 4: - return XSTR( "mission time", 253); - case 5: - return XSTR( "reticle", 254); - case 6: - return XSTR( "throttle", 255); - case 7: - return XSTR( "radar", 256); - case 8: - return XSTR( "target monitor", 257); - case 9: - return XSTR( "center of reticle", 258); - case 10: - return XSTR( "extra target info", 259); - case 11: - return XSTR( "target shield", 260); - case 12: - return XSTR( "player shield", 261); - case 13: - return XSTR( "power management", 262); - case 14: - return XSTR( "auto-target icon", 263); - case 15: - return XSTR( "auto-speed-match icon", 264); - case 16: - return XSTR( "weapons display", 265); - case 17: - return XSTR( "monitoring view", 266); - case 18: - return XSTR( "directives view", 267); - case 19: - return XSTR( "threat gauge", 268); - case 20: - return XSTR( "afterburner energy", 269); - case 21: - return XSTR( "weapons energy", 270); - case 22: - return XSTR( "weapon linking", 271); - case 23: - return XSTR( "target hull/shield icon", 272); - case 24: - return XSTR( "offscreen indicator", 273); - case 25: - return XSTR( "comm video", 274); - case 26: - return XSTR( "damage display", 275); - case 27: - return XSTR( "message output", 276); - case 28: - return XSTR( "locked missile direction", 277); - case 29: - return XSTR( "countermeasures", 278); - case 30: - return XSTR( "objective notify", 279); - case 31: - return XSTR( "wingmen status", 280); - case 32: - return XSTR( "offscreen range", 281); - case 33: - return XSTR( "kills gauge", 282); - case 34: - return XSTR( "attacking target count", 283); - case 35: - return XSTR("warning flash", 1459); - case 36: - return XSTR("comm menu", 1460); - case 37: - return XSTR("support gauge", 1461); - case 38: - return XSTR("lag gauge", 1462); + +SCP_vector> HC_available_huds; +int HC_chosen_hud = -1; + +SCP_string HC_arrow_bitmaps[2][2][2] = { + {{"BAB_030001", "BAB_030002"}, {"BAB_040001", "BAB_040002"}}, + {{"2_BAB_030001", "2_BAB_030002"}, {"2_BAB_040001", "2_BAB_040002"}} +}; +int HC_arrow_bm_handles[2][2] = {{-1, -1}, {-1, -1}}; +std::pair HC_arrow_coords[2][2] = { + { + {566, 368}, + {603, 368}, + }, + { + {911, 581}, + {967, 581}, } - return NULL; -} +}; +int HC_arrow_hot = -1; -#define NUM_HUD_BUTTONS 20 +#define NUM_HUD_BUTTONS 20 -#define HCB_RED_UP 0 -#define HCB_GREEN_UP 1 -#define HCB_BLUE_UP 2 -#define HCB_I_UP 3 -#define HCB_RED_DOWN 4 -#define HCB_GREEN_DOWN 5 -#define HCB_BLUE_DOWN 6 -#define HCB_I_DOWN 7 -#define HCB_ON 8 -#define HCB_OFF 9 -#define HCB_POPUP 10 -#define HCB_SAVE_HCF 11 -#define HCB_PREV_HCF 12 -#define HCB_NEXT_HCF 13 -#define HCB_AMBER 14 -#define HCB_BLUE 15 -#define HCB_GREEN 16 -#define HCB_SELECT_ALL 17 -#define HCB_RESET 18 -#define HCB_ACCEPT 19 +#define HCB_RED_UP 0 +#define HCB_GREEN_UP 1 +#define HCB_BLUE_UP 2 +#define HCB_I_UP 3 +#define HCB_RED_DOWN 4 +#define HCB_GREEN_DOWN 5 +#define HCB_BLUE_DOWN 6 +#define HCB_I_DOWN 7 +#define HCB_ON 8 +#define HCB_OFF 9 +#define HCB_POPUP 10 +#define HCB_SAVE_HCF 11 +#define HCB_PREV_HCF 12 +#define HCB_NEXT_HCF 13 +#define HCB_AMBER 14 +#define HCB_BLUE 15 +#define HCB_GREEN 16 +#define HCB_SELECT_ALL 17 +#define HCB_RESET 18 +#define HCB_ACCEPT 19 ui_button_info HC_buttons[GR_NUM_RESOLUTIONS][NUM_HUD_BUTTONS] = { - { // GR_640 - ui_button_info("HCB_00", 6, 27, -1, -1, 0), - ui_button_info("HCB_01", 30, 27, -1, -1, 1), - ui_button_info("HCB_02", 55, 27, -1, -1, 2), - ui_button_info("HCB_03", 80, 27, -1, -1, 3), - ui_button_info("HCB_08", 6, 291, -1, -1, 8), - ui_button_info("HCB_09", 30, 291, -1, -1, 9), - ui_button_info("HCB_10", 55, 291, -1, -1, 10), - ui_button_info("HCB_11", 80, 291, -1, -1, 11), - ui_button_info("HCB_12", 4, 329, -1, -1, 12), - ui_button_info("HCB_13", 4, 348, -1, -1, 13), - ui_button_info("HCB_14", 4, 367, -1, -1, 14), - ui_button_info("HCB_15", 2, 439, -1, -1, 15), - ui_button_info("HCB_16", 266, 456, -1, -1, 16), - ui_button_info("HCB_17", 292, 456, -1, -1, 17), - ui_button_info("HCB_18", 327, 421, -1, -1, 18), - ui_button_info("HCB_19", 327, 440, -1, -1, 19), - ui_button_info("HCB_20", 327, 459, -1, -1, 20), - ui_button_info("HCB_24", 472, 436, -1, -1, 24), - ui_button_info("HCB_25", 523, 433, -1, -1, 25), - ui_button_info("HCB_26", 576, 434, -1, -1, 26), - }, - { // GR_1024 - ui_button_info("2_HCB_00", 9, 44, -1, -1, 0), - ui_button_info("2_HCB_01", 48, 44, -1, -1, 1), - ui_button_info("2_HCB_02", 88, 44, -1, -1, 2), - ui_button_info("2_HCB_03", 127, 44, -1, -1, 3), - ui_button_info("2_HCB_08", 9, 466, -1, -1, 8), - ui_button_info("2_HCB_09", 48, 466, -1, -1, 9), - ui_button_info("2_HCB_10", 88, 466, -1, -1, 10), - ui_button_info("2_HCB_11", 127, 466, -1, -1, 11), - ui_button_info("2_HCB_12", 6, 526, -1, -1, 12), - ui_button_info("2_HCB_13", 6, 556, -1, -1, 13), - ui_button_info("2_HCB_14", 6, 586, -1, -1, 14), - ui_button_info("2_HCB_15", 3, 703, -1, -1, 15), - ui_button_info("2_HCB_16", 426, 730, -1, -1, 16), - ui_button_info("2_HCB_17", 467, 730, -1, -1, 17), - ui_button_info("2_HCB_18", 524, 674, -1, -1, 18), - ui_button_info("2_HCB_19", 524, 704, -1, -1, 19), - ui_button_info("2_HCB_20", 524, 734, -1, -1, 20), - ui_button_info("2_HCB_24", 755, 698, -1, -1, 24), - ui_button_info("2_HCB_25", 837, 693, -1, -1, 25), - ui_button_info("2_HCB_26", 922, 695, -1, -1, 26), - }, + { // GR_640 + ui_button_info("HCB_00", 6, 27, -1, -1, 0), + ui_button_info("HCB_01", 30, 27, -1, -1, 1), + ui_button_info("HCB_02", 55, 27, -1, -1, 2), + ui_button_info("HCB_03", 80, 27, -1, -1, 3), + ui_button_info("HCB_08", 6, 291, -1, -1, 8), + ui_button_info("HCB_09", 30, 291, -1, -1, 9), + ui_button_info("HCB_10", 55, 291, -1, -1, 10), + ui_button_info("HCB_11", 80, 291, -1, -1, 11), + ui_button_info("HCB_12", 4, 329, -1, -1, 12), + ui_button_info("HCB_13", 4, 348, -1, -1, 13), + ui_button_info("HCB_14", 4, 367, -1, -1, 14), + ui_button_info("HCB_15", 2, 439, -1, -1, 15), + ui_button_info("HCB_16", 266, 456, -1, -1, 16), + ui_button_info("HCB_17", 292, 456, -1, -1, 17), + ui_button_info("HCB_18", 327, 421, -1, -1, 18), + ui_button_info("HCB_19", 327, 440, -1, -1, 19), + ui_button_info("HCB_20", 327, 459, -1, -1, 20), + ui_button_info("HCB_24", 472, 436, -1, -1, 24), + ui_button_info("HCB_25", 523, 433, -1, -1, 25), + ui_button_info("HCB_26", 576, 434, -1, -1, 26), + }, + { // GR_1024 + ui_button_info("2_HCB_00", 9, 44, -1, -1, 0), + ui_button_info("2_HCB_01", 48, 44, -1, -1, 1), + ui_button_info("2_HCB_02", 88, 44, -1, -1, 2), + ui_button_info("2_HCB_03", 127, 44, -1, -1, 3), + ui_button_info("2_HCB_08", 9, 466, -1, -1, 8), + ui_button_info("2_HCB_09", 48, 466, -1, -1, 9), + ui_button_info("2_HCB_10", 88, 466, -1, -1, 10), + ui_button_info("2_HCB_11", 127, 466, -1, -1, 11), + ui_button_info("2_HCB_12", 6, 526, -1, -1, 12), + ui_button_info("2_HCB_13", 6, 556, -1, -1, 13), + ui_button_info("2_HCB_14", 6, 586, -1, -1, 14), + ui_button_info("2_HCB_15", 3, 703, -1, -1, 15), + ui_button_info("2_HCB_16", 426, 730, -1, -1, 16), + ui_button_info("2_HCB_17", 467, 730, -1, -1, 17), + ui_button_info("2_HCB_18", 524, 674, -1, -1, 18), + ui_button_info("2_HCB_19", 524, 704, -1, -1, 19), + ui_button_info("2_HCB_20", 524, 734, -1, -1, 20), + ui_button_info("2_HCB_24", 755, 698, -1, -1, 24), + ui_button_info("2_HCB_25", 837, 693, -1, -1, 25), + ui_button_info("2_HCB_26", 922, 695, -1, -1, 26), + }, }; // text #define NUM_HUD_TEXT 15 UI_XSTR HC_text[GR_NUM_RESOLUTIONS][NUM_HUD_TEXT] = { - { // GR_640 - { "R", 1512, 14, 8, UI_XSTR_COLOR_GREEN, -1, NULL }, - { "G", 1513, 37, 8, UI_XSTR_COLOR_GREEN, -1, NULL }, - { "B", 1514, 62, 8, UI_XSTR_COLOR_GREEN, -1, NULL }, - { "I", 1515, 90, 8, UI_XSTR_COLOR_GREEN, -1, NULL }, - { "On", 1285, 36, 334, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_ON].button }, - { "Off", 1286, 36, 353, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_OFF].button }, - { "Popup", 1453, 36, 372, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_POPUP].button }, - { "Save", 1454, 51, 428, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_SAVE_HCF].button }, - { "Amber", 1455, 364, 426, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_AMBER].button }, - { "Blue", 1456, 364, 445, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_BLUE].button }, - { "Green", 1457, 364, 464, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_GREEN].button }, - { "Select", 1550, 442, 413, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_SELECT_ALL].button }, - { "All", 1551, 442, 424, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_SELECT_ALL].button }, - { "Reset", 1337, 515, 413, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_RESET].button }, - { "Accept", 1035, 573, 413, UI_XSTR_COLOR_PINK, -1, &HC_buttons[0][HCB_ACCEPT].button }, - }, - { // GR_1024 - { "R", 1512, 23, 14, UI_XSTR_COLOR_GREEN, -1, NULL }, - { "G", 1513, 60, 14, UI_XSTR_COLOR_GREEN, -1, NULL }, - { "B", 1514, 100, 14, UI_XSTR_COLOR_GREEN, -1, NULL }, - { "I", 1515, 144, 14, UI_XSTR_COLOR_GREEN, -1, NULL }, - { "On", 1285, 58, 536, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_ON].button }, - { "Off", 1286, 58, 566, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_OFF].button }, - { "Popup", 1453, 58, 596, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_POPUP].button }, - { "Save", 1454, 82, 688, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_SAVE_HCF].button }, - { "Amber", 1455, 582, 685, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_AMBER].button }, - { "Blue", 1456, 582, 715, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_BLUE].button }, - { "Green", 1457, 582, 745, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_GREEN].button }, - { "Select", 1550, 760, 671, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_SELECT_ALL].button }, - { "All", 1551, 760, 682, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_SELECT_ALL].button }, - { "Reset", 1337, 850, 669, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_RESET].button }, - { "Accept", 1035, 930, 670, UI_XSTR_COLOR_PINK, -1, &HC_buttons[1][HCB_ACCEPT].button }, - } + { // GR_640 + { "R", 1512, 14, 8, UI_XSTR_COLOR_GREEN, -1, nullptr }, + { "G", 1513, 37, 8, UI_XSTR_COLOR_GREEN, -1, nullptr }, + { "B", 1514, 62, 8, UI_XSTR_COLOR_GREEN, -1, nullptr }, + { "I", 1515, 90, 8, UI_XSTR_COLOR_GREEN, -1, nullptr }, + { "On", 1285, 36, 334, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_ON].button }, + { "Off", 1286, 36, 353, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_OFF].button }, + { "Popup", 1453, 36, 372, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_POPUP].button }, + { "Save", 1454, 51, 428, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_SAVE_HCF].button }, + { "Amber", 1455, 364, 426, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_AMBER].button }, + { "Blue", 1456, 364, 445, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_BLUE].button }, + { "Green", 1457, 364, 464, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_GREEN].button }, + { "Select", 1550, 442, 413, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_SELECT_ALL].button }, + { "All", 1551, 442, 424, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_SELECT_ALL].button }, + { "Reset", 1337, 515, 413, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[0][HCB_RESET].button }, + { "Accept", 1035, 573, 413, UI_XSTR_COLOR_PINK, -1, &HC_buttons[0][HCB_ACCEPT].button }, + }, + { // GR_1024 + { "R", 1512, 23, 14, UI_XSTR_COLOR_GREEN, -1, nullptr }, + { "G", 1513, 60, 14, UI_XSTR_COLOR_GREEN, -1, nullptr }, + { "B", 1514, 100, 14, UI_XSTR_COLOR_GREEN, -1, nullptr }, + { "I", 1515, 144, 14, UI_XSTR_COLOR_GREEN, -1, nullptr }, + { "On", 1285, 58, 536, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_ON].button }, + { "Off", 1286, 58, 566, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_OFF].button }, + { "Popup", 1453, 58, 596, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_POPUP].button }, + { "Save", 1454, 82, 688, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_SAVE_HCF].button }, + { "Amber", 1455, 582, 685, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_AMBER].button }, + { "Blue", 1456, 582, 715, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_BLUE].button }, + { "Green", 1457, 582, 745, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_GREEN].button }, + { "Select", 1550, 760, 671, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_SELECT_ALL].button }, + { "All", 1551, 760, 682, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_SELECT_ALL].button }, + { "Reset", 1337, 850, 669, UI_XSTR_COLOR_GREEN, -1, &HC_buttons[1][HCB_RESET].button }, + { "Accept", 1035, 930, 670, UI_XSTR_COLOR_PINK, -1, &HC_buttons[1][HCB_ACCEPT].button }, + } }; static int HC_background_bitmap; static int HC_background_bitmap_mask; static UI_WINDOW HC_ui_window; -int HC_gauge_hot; // mouse is over this gauge -int HC_gauge_selected; // gauge is selected -float HC_gauge_scale; // scale used for drawing the hud gauges +SCP_string HC_gauge_hot; // mouse is over this gauge +SCP_string HC_gauge_selected; // gauge is selected int HC_gauge_coordinates[6]; // x1, x2, y1, y1, w, h of the example HUD render area. Used for calculating new gauge coordinates -BoundingBox HC_gauge_mouse_coords[NUM_HUD_GAUGES]; +SCP_vector> HC_gauge_mouse_coords; // HUD colors typedef struct hc_col { @@ -538,7 +327,7 @@ hc_col HC_colors[HUD_COLOR_SIZE] = }; static HUD_CONFIG_TYPE HUD_config_backup; // backup HUD config, used to restore old config if changes not applied -static int HUD_config_inited = 0; +static int HUD_config_inited = 0; // rgba slider stuff void hud_config_red_slider(); @@ -556,10 +345,10 @@ void hud_config_process_colors(); UI_SLIDER2 HC_color_sliders[NUM_HC_SLIDERS]; int HC_slider_coords[GR_NUM_RESOLUTIONS][NUM_HC_SLIDERS][4] = { { // GR_640 - { 8, 53, 15, 225 }, - { 33, 53, 15, 225 }, - { 58, 53, 15, 225 }, - { 83, 53, 15, 225 }, + { 8, 53, 15, 225 }, + { 33, 53, 15, 225 }, + { 58, 53, 15, 225 }, + { 83, 53, 15, 225 }, }, { // GR_1024 { 13, 85, 32, 350 }, @@ -575,14 +364,28 @@ const char *HC_slider_fname[GR_NUM_RESOLUTIONS] = { "2_slider" }; -// sync sliders -void hud_config_synch_sliders(int i) +// Used throughout this file to map from retail gauge ids (numeric or HCF) to the newer internal string format +const auto& gauge_map = HC_gauge_mappings::get_instance(); + +HudGauge* hud_config_get_gauge_pointer(const SCP_string& gauge_id) { - if(i >= 0){ - HC_color_sliders[HCS_RED].force_currentItem( HCS_CONV(HUD_config.clr[i].red) ); - HC_color_sliders[HCS_GREEN].force_currentItem( HCS_CONV(HUD_config.clr[i].green) ); - HC_color_sliders[HCS_BLUE].force_currentItem( HCS_CONV(HUD_config.clr[i].blue) ); - HC_color_sliders[HCS_ALPHA].force_currentItem( HCS_CONV(HUD_config.clr[i].alpha) ); + for (auto& pair : HC_gauge_map) { + if (pair.first == gauge_id) { + return pair.second; + } + } + return nullptr; +} + +// sync sliders +void hud_config_synch_sliders(const SCP_string& gauge) +{ + if(!gauge.empty()){ + color clr = HUD_config.get_gauge_color(gauge); + HC_color_sliders[HCS_RED].force_currentItem( HCS_CONV(clr.red) ); + HC_color_sliders[HCS_GREEN].force_currentItem(HCS_CONV(clr.green)); + HC_color_sliders[HCS_BLUE].force_currentItem(HCS_CONV(clr.blue)); + HC_color_sliders[HCS_ALPHA].force_currentItem(HCS_CONV(clr.alpha)); } } @@ -602,6 +405,50 @@ void hud_config_synch_ui(bool API_Access) } } +void hud_config_init_dimensions(int x1, int x2, int y1, int y2) +{ + // Calculate the menu width and height + int menuWidth = x2 - x1; + int menuHeight = y2 - y1; + + HC_gauge_coordinates[0] = x1; + HC_gauge_coordinates[1] = x2; + HC_gauge_coordinates[2] = y1; + HC_gauge_coordinates[3] = y2; + HC_gauge_coordinates[4] = menuWidth; + HC_gauge_coordinates[5] = menuHeight; +} + +void hud_config_get_unique_huds() +{ + std::unordered_set seenHuds; // Tracks HUDs we've already encountered + + for (const auto& pair : Hud_parsed_ships) { + const auto& hudName = pair.first; // Extract the HUD name + if (seenHuds.find(hudName) == seenHuds.end()) { + // If this HUD hasn't been encountered, maybe add it to the result + if (HC_ignored_huds.find(hudName) != HC_ignored_huds.end()) { + // Skip ignored HUDs + continue; + } + + std::pair newPair; + newPair.second = hudName; + + // Get the ship index associated + for (size_t i = 0; i < Ship_info.size(); i++) { + if (!stricmp(Ship_info[i].name, pair.second.c_str())) { + newPair.first = i; + break; + } + } + + HC_available_huds.push_back(newPair); + seenHuds.insert(hudName); + } + } +} + /*! * @brief init the UI components * @@ -610,53 +457,39 @@ void hud_config_synch_ui(bool API_Access) * param[in] y the y coord to render the preview display * param[in] w the width of the preview display */ -void hud_config_init_ui(bool API_Access, int x, int y, int w) +void hud_config_init_ui(bool API_Access, int x, int y, int w, int h) { int i; struct ui_button_info *hb; - HC_gauge_coords.clear(); - HC_gauge_coords.resize(NUM_HUD_GAUGES); + HC_gauge_mouse_coords.clear(); - // Clear the mouse coords array - for (auto& coord : HC_gauge_mouse_coords) { - coord = {-1, -1, -1, -1}; + hud_config_get_unique_huds(); + + if (!HC_show_default_hud) { + if (HC_available_huds.empty()) { + HC_show_default_hud = true; + HC_chosen_hud = -1; + } else { + HC_chosen_hud = 0; + } } - if (w < 0) { - HC_gauge_scale = 1.0f; + if (!HC_show_default_hud && HC_available_huds.empty()) { + HC_show_default_hud = true; + } + + if (w < 0 || h < 0) { + hud_config_init_dimensions(HC_gauge_config_coords[gr_screen.res][0], + HC_gauge_config_coords[gr_screen.res][1], + HC_gauge_config_coords[gr_screen.res][2], + HC_gauge_config_coords[gr_screen.res][3]); + HC_resize_mode = GR_RESIZE_MENU; } else { - float sw = 0; // will be highest w value - - // this is probably not the most efficient way to do this, but I - // can't find a better one. Need to get the furthest right and bottom - // pixels to be rendered to calculate the percent change. That is then - // used to rescale each gauge correctly for the rendering size and position. - Mjn - for (const auto& gauge : HC_gauge_regions[gr_screen.res]) { - if (!stricmp(gauge.filename, NOX("none"))) { - continue; - } - - int bm = bm_load(gauge.filename); - - int bw; - bm_get_info(bm, &bw); - bm_release(bm); - - bw += gauge.x; - - if (bw > sw) { - sw = (float)bw; - } - } - - // calculate the percent change - HC_gauge_scale = (float)w / sw; - - // we don't work with negative scales here, so reverse if it is - if (HC_gauge_scale < 0) { - HC_gauge_scale *= -1; + hud_config_init_dimensions(x, x + w, y, y + h); + if (API_Access) { + HC_resize_mode = GR_RESIZE_NONE; } } @@ -677,61 +510,11 @@ void hud_config_init_ui(bool API_Access, int x, int y, int w) } else { HC_ui_window.set_mask_bmap(Hud_config_mask_fname[gr_screen.res]); } - } - - // this is kinda dumb, but the retail gauge coords are hardcoded to - // to offset from the left and top of the screen. This exists - // for the api to render the gauge view at 0,0 without having to compensate - // for this dumb hardcoded way of doing things. - int x_offset = 0 + x; - int y_offset = 0 + y; - if (API_Access) { - int sx = HC_gauge_regions[gr_screen.res][0].x; // will be lowest x value - int sy = HC_gauge_regions[gr_screen.res][0].y; // will be lowest y value - for (auto gauge : HC_gauge_regions[gr_screen.res]) { - if (!stricmp(gauge.filename, NOX("none"))) { - continue; - } - if (gauge.x < sx) { - sx = gauge.x; - } - if (gauge.y < sy) { - sy = gauge.y; - } - } - - // now add the offsets with the correct scaling - x_offset += ((int)(sx * HC_gauge_scale) * -1); // the furthest left gauge - y_offset += ((int)(sy * HC_gauge_scale) * -1); // the furthest top gauge - } - - for (i=0; ifilename, NOX("none"))) { - continue; - } - - // scale the x/y coords - int gx = (int)(hg->x * HC_gauge_scale); - int gy = (int)(hg->y * HC_gauge_scale); - - // apply the offset - gx += x_offset; - gy += y_offset; - - // save the values and drop the decimals - HC_gauge_coords[i] = {gx, gy}; - - hg->button.create(&HC_ui_window, "", gx, gy, 60, 30, 0, 1); - // set up callback for when a mouse first goes over a button - // hg->button.set_highlight_action(common_play_highlight_sound); - hg->button.hide(); - hg->button.link_hotspot(hg->hotspot); - - hg->bitmap = bm_load(hg->filename); - hg->nframes = 1; + HC_arrow_bm_handles[0][0] = bm_load(HC_arrow_bitmaps[gr_screen.res][0][0]); + HC_arrow_bm_handles[0][1] = bm_load(HC_arrow_bitmaps[gr_screen.res][0][1]); + HC_arrow_bm_handles[1][0] = bm_load(HC_arrow_bitmaps[gr_screen.res][1][0]); + HC_arrow_bm_handles[1][1] = bm_load(HC_arrow_bitmaps[gr_screen.res][1][1]); } if (!API_Access){ @@ -751,7 +534,18 @@ void hud_config_init_ui(bool API_Access, int x, int y, int w) 255, HC_slider_fname[gr_screen.res], hud_config_blue_slider, hud_config_blue_slider, hud_config_blue_slider); HC_color_sliders[HCS_ALPHA].create(&HC_ui_window, HC_slider_coords[gr_screen.res][HCS_ALPHA][0], HC_slider_coords[gr_screen.res][HCS_ALPHA][1], HC_slider_coords[gr_screen.res][HCS_ALPHA][2], HC_slider_coords[gr_screen.res][HCS_ALPHA][3], - 255, HC_slider_fname[gr_screen.res], hud_config_alpha_slider_up, hud_config_alpha_slider_down, NULL); + 255, HC_slider_fname[gr_screen.res], hud_config_alpha_slider_up, hud_config_alpha_slider_down, nullptr); + + // now disable them until the player clicks on something + HC_color_sliders[HCS_RED].hide(); + HC_color_sliders[HCS_GREEN].hide(); + HC_color_sliders[HCS_BLUE].hide(); + HC_color_sliders[HCS_ALPHA].hide(); + + HC_color_sliders[HCS_RED].disable(); + HC_color_sliders[HCS_GREEN].disable(); + HC_color_sliders[HCS_BLUE].disable(); + HC_color_sliders[HCS_ALPHA].disable(); } hud_config_preset_init(); @@ -776,131 +570,55 @@ void hud_config_init_ui(bool API_Access, int x, int y, int w) UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_ESC_FOC); HC_fname_input.set_text(""); - /* - for (i=0; i& item) { return item.first == gauge_id; }); + + if (it != HC_gauge_mouse_coords.end()) { + if (it->second == newBox) { + return; // No change, early exit + } + it->second = newBox; // Replace existing + return; } -} -// ETS gauge can render as one unified gauge or as three separate gauges using separate drawing functions -// So this function provides a way to min/max the coords to make sure no matter what method is used, the -// mouse box inclues all the relevant areas -void hud_config_set_mouse_coords_ets(int gauge_config, int x1, int x2, int y1, int y2) -{ - HC_gauge_mouse_coords[gauge_config].x1 = std::min(HC_gauge_mouse_coords[gauge_config].x1, x1); - HC_gauge_mouse_coords[gauge_config].x2 = std::max(HC_gauge_mouse_coords[gauge_config].x2, x2); - HC_gauge_mouse_coords[gauge_config].y1 = std::min(HC_gauge_mouse_coords[gauge_config].y1, y1); - HC_gauge_mouse_coords[gauge_config].y2 = std::max(HC_gauge_mouse_coords[gauge_config].y2, y2); - - // temporary stuff to show boxes - color clr = gr_screen.current_color; - color thisColor; - gr_init_alphacolor(&thisColor, 255, 255, 255, 80); - gr_set_color_fast(&thisColor); - // hud_config_draw_box(x1, x2, y1, y2); - gr_set_color_fast(&clr); + HC_gauge_mouse_coords.emplace_back(std::make_pair(gauge_id, newBox)); } std::pair hud_config_convert_coords(int x, int y, float scale) @@ -964,7 +682,7 @@ std::pair hud_config_calc_coords_from_angle(float angle_degrees, i return {screenX, screenY}; } -float hud_config_find_valid_angle(int gauge_index, float initial_angle, int centerX, int centerY, float radius) +float hud_config_find_valid_angle(const SCP_string& gauge, float initial_angle, int centerX, int centerY, float radius) { const int max_iterations = 360; // Prevent infinite loops float angle = initial_angle; @@ -982,7 +700,7 @@ float hud_config_find_valid_angle(int gauge_index, float initial_angle, int cent BoundingBox newBox = {x1, x2, y1, y2}; // Check for overlap - if (!BoundingBox::isOverlappingAny(HC_gauge_mouse_coords, newBox, gauge_index)) { + if (!BoundingBox::isOverlappingAny(HC_gauge_mouse_coords, newBox, gauge)) { return angle; } @@ -1003,142 +721,80 @@ float hud_config_find_valid_angle(int gauge_index, float initial_angle, int cent */ void hud_config_render_gauges(bool API_Access) { - int i; + // Check if this ship has its own HUD gauges. + SCP_string hud_name; + if (SCP_vector_inbounds(HC_available_huds, HC_chosen_hud)) { + ship_info* sip = &Ship_info[HC_available_huds[HC_chosen_hud].first]; + hud_name = HC_available_huds[HC_chosen_hud].second; - for ( i=0; i& gauge : sip->hud_gauges) { + GR_DEBUG_SCOPE("Render HUD gauge"); + if (gauge->getVisibleInConfig()) { + gauge->setFont(); + gauge->render(0, true); } - - if ( (HC_gauge_selected == i) || HC_select_all ) { - alpha = 255; - } else if ( HC_gauge_hot == i ) { - alpha = 200; - } else { - alpha = 150; + if (HC_gauge_list_clear) { + HC_gauge_map.emplace_back(std::make_pair(gauge->getConfigId(), gauge.get())); } - gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha); - gr_set_color_fast(use_color); - } else { - // if its off, make it dark gray - use_color = &HUD_config.clr[i]; - gr_init_alphacolor(use_color, 127, 127, 127, 64); - gr_set_color_fast(use_color); } - - // draw - if ( HC_gauge_regions[gr_screen.res][i].bitmap >= 0 ) { - gr_set_bitmap(HC_gauge_regions[gr_screen.res][i].bitmap); - - int resize = GR_RESIZE_MENU; - if (API_Access) { - resize = GR_RESIZE_NONE; + } else { + hud_name = XSTR("Default HUD", 1876); + + for (const std::unique_ptr& gauge : default_hud_gauges) { + GR_DEBUG_SCOPE("Render HUD gauge"); + if (gauge->getVisibleInConfig()) { + gauge->setFont(); + gauge->render(0, true); } - - gr_aabitmap(HC_gauge_coords[i].x, HC_gauge_coords[i].y, resize, false, HC_gauge_scale); - } - - /* - else { - - int offset=0; - // set correct frame if using iff - if ( HC_gauge_regions[i].use_iff ) { - if ( HC_gauge_selected == i ) { - offset=2; - } else if ( HC_gauge_hot == i ) { - offset=1; - } - - // If gauge is disabled, then draw disabled frame - if ( !(hud_config_show_flag_is_set(i)) ) { - offset=3; - } - } - - if ( HC_gauge_regions[i].bitmap >= 0 ) { - Assert(offset < HC_gauge_regions[i].nframes); - gr_set_bitmap(HC_gauge_regions[i].bitmap+offset); - gr_bitmap(HC_gauge_regions[i].x, HC_gauge_regions[i].y, GR_RESIZE_MENU); + if (HC_gauge_list_clear) { + HC_gauge_map.emplace_back(std::make_pair(gauge->getConfigId(), gauge.get())); } } - */ } + + // DEBUGGING ONLY + /*gr_set_color_fast(&Color_normal); + for (auto& box : HC_gauge_mouse_coords) { + hud_config_draw_box(box.second.x1, box.second.x2, box.second.y1, box.second.y2); + }*/ + + HC_gauge_list_clear = false; + + // Render the name of the HUD + if (!API_Access) { + gr_set_color_fast(&Color_normal); + int w; + gr_get_string_size(&w, nullptr, hud_name.c_str()); + int x = HC_gauge_coordinates[0] + ((HC_gauge_coordinates[4] / 2) - (w / 2)); + gr_string(x, HC_gauge_coordinates[3] + 10, hud_name.c_str(), GR_RESIZE_MENU); + } + + hud_name.clear(); } -void hud_config_init(bool API_Access, int x, int y, int w) +void hud_config_init(bool API_Access, int x, int y, int w, int h) { - hud_config_init_ui(API_Access, x, y, w); + hud_config_init_ui(API_Access, x, y, w, h); hud_config_backup(); // save the HUD configuration in case the player decides to cancel changes HUD_config_inited = 1; } -/*! - * @brief check mouse position against all ui buttons using the ui mask - * - */ -void hud_config_check_regions() +bool hud_config_check_mouse_in_hud_area(int mx, int my) { - int i; - UI_BUTTON *b; - - for ( i=0; ibutton_hilighted() ) { - HC_gauge_hot = i; - } - - if ( b->pressed() ) { - gamesnd_play_iface(InterfaceSounds::USER_SELECT); - HC_gauge_selected = i; - - // turn off select all - hud_config_select_all_toggle(0); - - // maybe setup rgb sliders - if(HC_gauge_regions[gr_screen.res][i].use_iff){ - HC_color_sliders[HCS_RED].hide(); - HC_color_sliders[HCS_GREEN].hide(); - HC_color_sliders[HCS_BLUE].hide(); - HC_color_sliders[HCS_ALPHA].hide(); - - HC_color_sliders[HCS_RED].disable(); - HC_color_sliders[HCS_GREEN].disable(); - HC_color_sliders[HCS_BLUE].disable(); - HC_color_sliders[HCS_ALPHA].disable(); - } else { - HC_color_sliders[HCS_RED].enable(); - HC_color_sliders[HCS_GREEN].enable(); - HC_color_sliders[HCS_BLUE].enable(); - HC_color_sliders[HCS_ALPHA].enable(); - - HC_color_sliders[HCS_RED].unhide(); - HC_color_sliders[HCS_GREEN].unhide(); - HC_color_sliders[HCS_BLUE].unhide(); - HC_color_sliders[HCS_ALPHA].unhide(); - - HC_color_sliders[HCS_RED].force_currentItem( HCS_CONV(HUD_config.clr[i].red) ); - HC_color_sliders[HCS_GREEN].force_currentItem( HCS_CONV(HUD_config.clr[i].green) ); - HC_color_sliders[HCS_BLUE].force_currentItem( HCS_CONV(HUD_config.clr[i].blue) ); - HC_color_sliders[HCS_ALPHA].force_currentItem( HCS_CONV(HUD_config.clr[i].alpha) ); - } - - // recalc alpha slider - hud_config_recalc_alpha_slider(); - } + if (mx < HC_gauge_config_coords[gr_screen.res][0]) { + return false; } + if (mx > HC_gauge_config_coords[gr_screen.res][1]) { + return false; + } + if (my < HC_gauge_config_coords[gr_screen.res][2]) { + return false; + } + if (my > HC_gauge_config_coords[gr_screen.res][3]) { + return false; + } + + return true; } /*! @@ -1147,43 +803,106 @@ void hud_config_check_regions() */ void hud_config_check_regions_by_mouse(int mx, int my) { - for (int i = 0; i < NUM_HUD_GAUGES; i++) { - HC_gauge_region *bi = &HC_gauge_regions[gr_screen.res][i]; - int iw = 0; - int ih = 0; - if (bi->bitmap > 0) { - bm_get_info(bi->bitmap, &iw, &ih, nullptr); - iw = (int)(iw * HC_gauge_scale); - ih = (int)(ih * HC_gauge_scale); - if (mx < HC_gauge_coords[i].x) - continue; - if (mx > (HC_gauge_coords[i].x + iw)) - continue; - if (my < HC_gauge_coords[i].y) - continue; - if (my > (HC_gauge_coords[i].y + ih)) - continue; - // if we've got here, must be a hit - HC_gauge_hot = i; - break; + for (const auto& coords : HC_gauge_mouse_coords) { + if (coords.second.x1 < 0) + continue; + + if (mx < coords.second.x1 || mx > coords.second.x2 || my < coords.second.y1 || my > coords.second.y2) { + continue; } + + // If we've got here, it's a hit + HC_gauge_hot = coords.first; + return; // Stop checking once we find the first match + } +} + +/*! + * @brief check mouse position against all ui buttons using the ui mask + * + */ +void hud_config_check_regions(int mx, int my) +{ + if (hud_config_check_mouse_in_hud_area(mx, my)) { + HC_gauge_hot = "-2"; + } + + if (HC_gauge_hot == "-2" && mouse_down(MOUSE_LEFT_BUTTON)) { + HC_gauge_selected.clear(); + HC_color_sliders[HCS_RED].hide(); + HC_color_sliders[HCS_GREEN].hide(); + HC_color_sliders[HCS_BLUE].hide(); + HC_color_sliders[HCS_ALPHA].hide(); + + HC_color_sliders[HCS_RED].disable(); + HC_color_sliders[HCS_GREEN].disable(); + HC_color_sliders[HCS_BLUE].disable(); + HC_color_sliders[HCS_ALPHA].disable(); + } + + if (HC_arrow_hot >= 0 && mouse_down(MOUSE_LEFT_BUTTON)) { + gamesnd_play_iface(InterfaceSounds::USER_SELECT); + if (HC_arrow_hot == 0) { + hud_config_select_hud(false); + } else { + hud_config_select_hud(true); + } + mouse_flush(); + return; + } + + hud_config_check_regions_by_mouse(mx, my); + + if (!HC_gauge_hot.empty() && mouse_down(MOUSE_LEFT_BUTTON)) { + gamesnd_play_iface(InterfaceSounds::USER_SELECT); + HC_gauge_selected = HC_gauge_hot; + + // turn off select all + hud_config_select_all_toggle(false); + + const auto gauge = hud_config_get_gauge_pointer(HC_gauge_selected); + + // maybe setup rgb sliders + if (gauge != nullptr && gauge->getConfigUseIffColor()) { + HC_color_sliders[HCS_RED].hide(); + HC_color_sliders[HCS_GREEN].hide(); + HC_color_sliders[HCS_BLUE].hide(); + HC_color_sliders[HCS_ALPHA].hide(); + + HC_color_sliders[HCS_RED].disable(); + HC_color_sliders[HCS_GREEN].disable(); + HC_color_sliders[HCS_BLUE].disable(); + HC_color_sliders[HCS_ALPHA].disable(); + } else { + HC_color_sliders[HCS_RED].enable(); + HC_color_sliders[HCS_GREEN].enable(); + HC_color_sliders[HCS_BLUE].enable(); + HC_color_sliders[HCS_ALPHA].enable(); + + HC_color_sliders[HCS_RED].unhide(); + HC_color_sliders[HCS_GREEN].unhide(); + HC_color_sliders[HCS_BLUE].unhide(); + HC_color_sliders[HCS_ALPHA].unhide(); + + color clr = HUD_config.get_gauge_color(HC_gauge_selected); + + HC_color_sliders[HCS_RED].force_currentItem(HCS_CONV(clr.red)); + HC_color_sliders[HCS_GREEN].force_currentItem(HCS_CONV(clr.green)); + HC_color_sliders[HCS_BLUE].force_currentItem(HCS_CONV(clr.blue)); + HC_color_sliders[HCS_ALPHA].force_currentItem(HCS_CONV(clr.alpha)); + } + + // recalc alpha slider + hud_config_recalc_alpha_slider(); + mouse_flush(); } } // set the display flags for a HUD gauge -void hud_config_set_gauge_flags(int gauge_index, int on_flag, int popup_flag) +void hud_config_set_gauge_flags(const SCP_string& gauge, bool on_flag, bool popup_flag) { - if ( on_flag ) { - hud_config_show_flag_set(gauge_index); - } else { - hud_config_show_flag_clear(gauge_index); - } - - if ( popup_flag ) { - hud_config_popup_flag_set(gauge_index); - } else { - hud_config_popup_flag_clear(gauge_index); - } + HUD_config.set_gauge_visibility(gauge, on_flag); + HUD_config.set_gauge_popup(gauge, popup_flag); } void hud_config_record_color(int in_color) @@ -1197,25 +916,28 @@ void hud_config_record_color(int in_color) // Set the HUD color void hud_config_set_color(int in_color) { - int idx; - hud_config_record_color(in_color); HUD_init_hud_color_array(); // apply the color to all gauges - for(idx=0; idxoff->popup void hud_cycle_gauge_status() { - if ( HC_gauge_selected < 0 ) { + if ( !HC_gauge_selected.empty() ) { return; } // gauge is off, move to popup - if ( !(hud_config_show_flag_is_set(HC_gauge_selected)) ) { - if ( HC_gauge_regions[gr_screen.res][HC_gauge_selected].can_popup ) { - hud_config_set_gauge_flags(HC_gauge_selected, 1, 1); + if ( !(HUD_config.is_gauge_visible(HC_gauge_selected)) ) { + const auto gauge = hud_config_get_gauge_pointer(HC_gauge_selected); + if (gauge != nullptr && gauge->getConfigCanPopup()) { + hud_config_set_gauge_flags(HC_gauge_selected, true, true); } else { - hud_config_set_gauge_flags(HC_gauge_selected, 1, 0); + hud_config_set_gauge_flags(HC_gauge_selected, true, false); } return; } // if gauge is popup, move to on - if ( hud_config_popup_flag_is_set(HC_gauge_selected) ) { - hud_config_set_gauge_flags(HC_gauge_selected, 1, 0); + if ( HUD_config.is_gauge_popup(HC_gauge_selected) ) { + hud_config_set_gauge_flags(HC_gauge_selected, true, false); return; } // gauge must be on, move to off - hud_config_set_gauge_flags(HC_gauge_selected, 0, 0); + hud_config_set_gauge_flags(HC_gauge_selected, false, false); } // handle keyboard input while in hud config @@ -1289,6 +1012,12 @@ void hud_config_handle_keypresses(int k) gamesnd_play_iface(InterfaceSounds::USER_SELECT); hud_cycle_gauge_status(); break; + case KEY_RIGHT: + hud_config_select_hud(true); + break; + case KEY_LEFT: + hud_config_select_hud(false); + break; } } @@ -1312,25 +1041,25 @@ void hud_config_button_do(int n) gamesnd_play_iface(InterfaceSounds::USER_SELECT); break; case HCB_ON: - if ( HC_gauge_selected < 0 ) { + if (HC_gauge_selected.empty()) { break; } gamesnd_play_iface(InterfaceSounds::USER_SELECT); - hud_config_set_gauge_flags(HC_gauge_selected,1,0); + hud_config_set_gauge_flags(HC_gauge_selected,true,false); break; case HCB_OFF: - if ( HC_gauge_selected < 0 ) { + if (HC_gauge_selected.empty()) { break; } gamesnd_play_iface(InterfaceSounds::USER_SELECT); - hud_config_set_gauge_flags(HC_gauge_selected,0,0); + hud_config_set_gauge_flags(HC_gauge_selected,false,false); break; case HCB_POPUP: - if ( HC_gauge_selected < 0 ) { + if (HC_gauge_selected.empty()) { break; } gamesnd_play_iface(InterfaceSounds::USER_SELECT); - hud_config_set_gauge_flags(HC_gauge_selected,1,1); + hud_config_set_gauge_flags(HC_gauge_selected,true,true); break; case HCB_RESET: gamesnd_play_iface(InterfaceSounds::RESET_PRESSED); @@ -1506,10 +1235,9 @@ void hud_config_button_do(int n) // Check if any buttons have been pressed void hud_config_check_buttons() { - int i; UI_BUTTON *b; - for ( i=0; ipressed() ) { hud_config_button_do(i); @@ -1540,7 +1268,7 @@ void hud_config_draw_color_status() // set the status (on/off/popup) for the selected gauge void hud_config_draw_gauge_status() { - if ( HC_gauge_selected < 0 ) { + if (HC_gauge_selected.empty()) { return; } @@ -1549,19 +1277,19 @@ void hud_config_draw_gauge_status() } // check if off - if ( !(hud_config_show_flag_is_set(HC_gauge_selected)) ) { + if (!(HUD_config.is_gauge_visible(HC_gauge_selected))) { HC_buttons[gr_screen.res][HCB_OFF].button.draw_forced(2); return; } // check if popup - if ( hud_config_popup_flag_is_set(HC_gauge_selected) ) { + if (HUD_config.is_gauge_popup(HC_gauge_selected)) { HC_buttons[gr_screen.res][HCB_POPUP].button.draw_forced(2); return; } // check if on - if ( hud_config_show_flag_is_set(HC_gauge_selected) ) { + if (HUD_config.is_gauge_visible(HC_gauge_selected)) { HC_buttons[gr_screen.res][HCB_ON].button.draw_forced(2); return; } @@ -1586,7 +1314,7 @@ void hud_config_button_enable(int index) // determine if on/off/popup buttons should be shown void hud_config_set_button_state() { - if ( HC_gauge_selected < 0 ) { + if (HC_gauge_selected.empty()) { hud_config_button_disable(HCB_ON); hud_config_button_disable(HCB_OFF); hud_config_button_disable(HCB_POPUP); @@ -1597,8 +1325,10 @@ void hud_config_set_button_state() hud_config_button_enable(HCB_ON); hud_config_button_enable(HCB_OFF); + const auto gauge = hud_config_get_gauge_pointer(HC_gauge_selected); + // popup is maybe available - if ( HC_gauge_regions[gr_screen.res][HC_gauge_selected].can_popup ) { + if (gauge != nullptr && gauge->getConfigCanPopup()) { hud_config_button_enable(HCB_POPUP); } else { hud_config_button_disable(HCB_POPUP); @@ -1609,13 +1339,17 @@ void hud_config_render_description() { int w,h,sx,sy; - if ( HC_gauge_selected >= 0 ) { - gr_set_color_fast(&Color_normal); + if (!HC_gauge_selected.empty()) { + const auto gauge = hud_config_get_gauge_pointer(HC_gauge_selected); - gr_get_string_size(&w, &h, HC_gauge_descriptions(HC_gauge_selected)); - sx = fl2i(HC_gauge_description_coords[gr_screen.res][0] + (HC_gauge_description_coords[gr_screen.res][2] - w)/2.0f); - sy = HC_gauge_description_coords[gr_screen.res][1]; - gr_string(sx, sy, HC_gauge_descriptions(HC_gauge_selected), GR_RESIZE_MENU); + if (gauge != nullptr) { + gr_set_color_fast(&Color_normal); + + gr_get_string_size(&w, &h, gauge->getConfigName().c_str()); + sx = fl2i(HC_gauge_description_coords[gr_screen.res][0] + (HC_gauge_description_coords[gr_screen.res][2] - w) / 2.0f); + sy = HC_gauge_description_coords[gr_screen.res][1]; + gr_string(sx, sy, gauge->getConfigName().c_str(), GR_RESIZE_MENU); + } } } @@ -1655,6 +1389,47 @@ void hud_config_redraw_pressed_buttons() } } +void hud_config_draw_hud_select_arrow_buttons(int mx, int my) +{ + int w1, h1; + bm_get_info(HC_arrow_bm_handles[gr_screen.res][0], &w1, &h1); + int w2, h2; + bm_get_info(HC_arrow_bm_handles[gr_screen.res][0], &w2, &h2); + + + BoundingBox l_box(HC_arrow_coords[gr_screen.res][0].first, + HC_arrow_coords[gr_screen.res][0].first + w1, + HC_arrow_coords[gr_screen.res][0].second, + HC_arrow_coords[gr_screen.res][0].second + h1); + BoundingBox r_box(HC_arrow_coords[gr_screen.res][1].first, + HC_arrow_coords[gr_screen.res][1].first + w1, + HC_arrow_coords[gr_screen.res][1].second, + HC_arrow_coords[gr_screen.res][1].second + h1); + + int hot = -1; + if (mx >= l_box.x1 && mx <= l_box.x2 && my >= l_box.y1 && my <= l_box.y2) { + hot = 0; + } + + if (mx >= r_box.x1 && mx <= r_box.x2 && my >= r_box.y1 && my <= r_box.y2) { + hot = 1; + + } + + if (hot != HC_arrow_hot) { + HC_arrow_hot = hot; + if (HC_arrow_hot >= 0) { + gamesnd_play_iface(InterfaceSounds::USER_OVER); + } + } + + for (int i = 0; i < 2; ++i) { + int on = (i == HC_arrow_hot) ? 1 : 0; + gr_set_bitmap(HC_arrow_bm_handles[i][on]); + gr_bitmap(HC_arrow_coords[gr_screen.res][i].first, HC_arrow_coords[gr_screen.res][i].second, GR_RESIZE_MENU); + } +} + void hud_config_do_frame(float /*frametime*/, bool API_Access, int mx, int my) { int k; @@ -1670,15 +1445,17 @@ void hud_config_do_frame(float /*frametime*/, bool API_Access, int mx, int my) return; } - HC_gauge_hot = -1; + HC_gauge_hot.clear(); if (!API_Access) { hud_config_set_button_state(); k = HC_ui_window.process(); + mouse_get_pos_unscaled(&mx, &my); + hud_config_handle_keypresses(k); - hud_config_check_regions(); + hud_config_check_regions(mx, my); hud_config_check_buttons(); hud_config_update_brightness(); @@ -1698,15 +1475,6 @@ void hud_config_do_frame(float /*frametime*/, bool API_Access, int mx, int my) hud_config_draw_gauge_status(); hud_config_draw_color_status(); - /* - if (HC_special_bitmaps[HC_SPECIAL_RETICLE].bitmap >= 0) { - hud_set_default_color(); - gr_set_bitmap(HC_special_bitmaps[HC_SPECIAL_RETICLE].bitmap); - gr_aabitmap(HC_special_bitmaps[HC_SPECIAL_RETICLE].x, HC_special_bitmaps[HC_SPECIAL_RETICLE].y, - GR_RESIZE_MENU); - } - */ - // maybe force draw the select all button if (HC_select_all) { HC_buttons[gr_screen.res][HCB_SELECT_ALL].button.draw_forced(2); @@ -1721,24 +1489,11 @@ void hud_config_do_frame(float /*frametime*/, bool API_Access, int mx, int my) hud_config_render_special_bitmaps(); hud_config_render_description(); - gr_flip(); - } -} - -void hud_config_unload_gauges() -{ - int i; - HC_gauge_region *hg; - - for (i=0; ibitmap >= 0 ) { - bm_release(hg->bitmap); + if (HC_available_huds.size() + (HC_show_default_hud ? 1 : 0) > 1) { + hud_config_draw_hud_select_arrow_buttons(mx, my); } - hg->bitmap=-1; - hg->nframes=0; + gr_flip(); } } @@ -1746,9 +1501,6 @@ void hud_config_unload_gauges() // void hud_config_close(bool API_Access) { -// common_free_interface_palette(); // restore game palette - hud_config_unload_gauges(); - HC_preset_filenames.clear(); if (!API_Access) { @@ -1763,6 +1515,14 @@ void hud_config_close(bool API_Access) } } + for (const auto& handle : HC_arrow_bm_handles) { + bm_unload(handle[0]); + bm_unload(handle[1]); + } + + bm_unload(HC_talking_head_frame); + HC_talking_head_frame = -1; + HUD_config_inited = 0; } @@ -1777,16 +1537,21 @@ void hud_set_default_hud_config(player * /*p*/, const char* filename) HUD_color_green = HC_colors[HUD_config.main_color].g; HUD_color_blue = HC_colors[HUD_config.main_color].b; + color clr; + gr_init_alphacolor(&clr, HUD_color_red, HUD_color_green, HUD_color_blue, (HUD_color_alpha + 1) * 16); + for(idx=0; idx= 0) { - gr_init_alphacolor(&HUD_config.clr[HC_gauge_selected], HCS_CONV(HC_color_sliders[HCS_RED].get_currentItem()), HCS_CONV(HC_color_sliders[HCS_GREEN].get_currentItem()), HCS_CONV(HC_color_sliders[HCS_BLUE].get_currentItem()), 255); + } else if (!HC_gauge_selected.empty()) { + color clr; + gr_init_alphacolor(&clr, HCS_CONV(HC_color_sliders[HCS_RED].get_currentItem()), HCS_CONV(HC_color_sliders[HCS_GREEN].get_currentItem()), HCS_CONV(HC_color_sliders[HCS_BLUE].get_currentItem()), 255); + HUD_config.set_gauge_color(HC_gauge_selected, clr); } } @@ -1946,8 +1761,10 @@ void hud_config_alpha_slider_down() // apply -- Cyborg17 -- Unless you have nothing to apply it to! if(HC_select_all){ hud_config_stuff_colors( HCS_CONV(HC_color_sliders[HCS_RED].get_currentItem()), HCS_CONV(HC_color_sliders[HCS_GREEN].get_currentItem()), HCS_CONV(HC_color_sliders[HCS_BLUE].get_currentItem()) ); - } else if (HC_gauge_selected >= 0) { - gr_init_alphacolor(&HUD_config.clr[HC_gauge_selected], HCS_CONV(HC_color_sliders[HCS_RED].get_currentItem()), HCS_CONV(HC_color_sliders[HCS_GREEN].get_currentItem()), HCS_CONV(HC_color_sliders[HCS_BLUE].get_currentItem()), 255); + } else if (!HC_gauge_selected.empty()) { + color clr; + gr_init_alphacolor(&clr, HCS_CONV(HC_color_sliders[HCS_RED].get_currentItem()), HCS_CONV(HC_color_sliders[HCS_GREEN].get_currentItem()), HCS_CONV(HC_color_sliders[HCS_BLUE].get_currentItem()), 255); + HUD_config.set_gauge_color(HC_gauge_selected, clr); } } @@ -1966,17 +1783,18 @@ void hud_config_red_slider() // select all ? if(HC_select_all){ for(idx=0; idx= static_cast(HC_available_huds.size())) { + HC_chosen_hud = HC_show_default_hud ? -1 : 0; + } + } else { + HC_chosen_hud--; + if (HC_chosen_hud < (HC_show_default_hud ? -1 : 0)) { + HC_chosen_hud = static_cast(HC_available_huds.size()) - 1; + } + } + HC_gauge_map.clear(); + HC_gauge_mouse_coords.clear(); + HC_gauge_list_clear = true; +} + +void hud_config_select_all_toggle(bool toggle, bool API_Access) { int r, g, b, a; @@ -2063,27 +1917,28 @@ void hud_config_select_all_toggle(int toggle, bool API_Access) hud_config_set_button_state(); } - HC_select_all = 0; + HC_select_all = false; } else { // synch stuff up hud_config_synch_ui(API_Access); // if we had a gauge previously selected, use its color everywhere - if(HC_gauge_selected < 0){ - r = HUD_config.clr[HUD_RADAR].red; - g = HUD_config.clr[HUD_RADAR].green; - b = HUD_config.clr[HUD_RADAR].blue; - a = HUD_config.clr[HUD_RADAR].alpha; + if(HC_gauge_selected.empty()){ + SCP_string gauge = gauge_map.get_string_id_from_numeric_id(HUD_RADAR); + r = HUD_config.gauge_colors[gauge].red; + g = HUD_config.gauge_colors[gauge].green; + b = HUD_config.gauge_colors[gauge].blue; + a = HUD_config.gauge_colors[gauge].alpha; } else { - r = HUD_config.clr[HC_gauge_selected].red; - g = HUD_config.clr[HC_gauge_selected].green; - b = HUD_config.clr[HC_gauge_selected].blue; - a = HUD_config.clr[HC_gauge_selected].alpha; + r = HUD_config.gauge_colors[HC_gauge_selected].red; + g = HUD_config.gauge_colors[HC_gauge_selected].green; + b = HUD_config.gauge_colors[HC_gauge_selected].blue; + a = HUD_config.gauge_colors[HC_gauge_selected].alpha; } hud_config_stuff_colors(r, g, b); // no gauge selected - HC_gauge_selected = -1; + HC_gauge_selected.clear(); // enable all sliders if (!API_Access) { @@ -2109,6 +1964,6 @@ void hud_config_select_all_toggle(int toggle, bool API_Access) hud_config_button_disable(HCB_POPUP); } - HC_select_all = 1; + HC_select_all = true; } } diff --git a/code/hud/hudconfig.h b/code/hud/hudconfig.h index 543910d793..02fa91cd83 100644 --- a/code/hud/hudconfig.h +++ b/code/hud/hudconfig.h @@ -34,24 +34,13 @@ struct ai_info; extern float Radar_ranges[RR_MAX_RANGES]; extern const char *Radar_range_text(int range_num); -#define RP_SHOW_DEBRIS (1<<0) -#define RP_SHOW_FRIENDLY_MISSILES (1<<1) -#define RP_SHOW_HOSTILE_MISSILES (1<<2) - -#define RP_DEFAULT ( RP_SHOW_DEBRIS | RP_SHOW_FRIENDLY_MISSILES | RP_SHOW_HOSTILE_MISSILES ) - /*! * @brief Vector for storing the filenames of hud preset files * @note main definition in hudconfig.cpp */ extern SCP_vector HC_preset_filenames; -extern int HUD_observer_default_flags; -extern int HUD_observer_default_flags2; -extern int HUD_default_popup_mask; -extern int HUD_default_popup_mask2; -extern int HUD_config_default_flags; -extern int HUD_config_default_flags2; +extern SCP_vector observer_visible_gauges; extern const int HC_gauge_config_coords[GR_NUM_RESOLUTIONS][4]; extern int HC_resize_mode; @@ -60,39 +49,75 @@ extern int HC_resize_mode; * @brief Contains core HUD configuration data * @note Is not default init'd. Assumes new player, PLR, or CSG reads will correctly set data. */ -typedef struct HUD_CONFIG_TYPE { - int show_flags; //!< bitfield, whether to show gauge (0 ~ 31) - int show_flags2; //!< bitfield, whether to show gauge (32 ~ 63) - int popup_flags; //!< bitfield, whether gauge is popup (0 ~ 31) - int popup_flags2; //!< bitfield, whether gauge is popup (32 ~ 63) - int rp_flags; //!< one of RP_ #defines in hudconfig.h; Chiefly shows/hides non-ship objects +typedef struct HUD_CONFIG_TYPE { int rp_dist; //!< one of RR_ #defines above; Is the maxium radar view distance setting int is_observer; //!< 1 or 0, observer mode or not, respectively int main_color; //!< the default HUD_COLOR selection for all gauges; each gauge may override this with a custom RGB - ubyte num_msg_window_lines; //!< Number of message lines. (Deprecated by HudGaugeMessages::Max_lines) - color clr[NUM_HUD_GAUGES]; //!< colors for all the gauges + // Maps for HUD gauge configuration + std::unordered_map gauge_colors; //!< Gauge-specific colors + std::unordered_map show_flags_map; //!< Show/hide state for gauges + std::unordered_map popup_flags_map; //!< Popup state for gauges + + static color default_white_color() + { + color white; + gr_init_alphacolor(&white, 255, 255, 255, 255); + return white; + } + + // Methods for setting and getting gauge properties where getting will return a default value + + void set_gauge_color(const std::string& gauge_id, const color& col) + { + gauge_colors[gauge_id] = col; + } + + // Get the gauge color or white if the gauge is not found + color get_gauge_color(const std::string& gauge_id) const + { + auto it = gauge_colors.find(gauge_id); + return (it != gauge_colors.end()) ? it->second : default_white_color(); + } + + void set_gauge_visibility(const std::string& gauge_id, bool visible) + { + show_flags_map[gauge_id] = visible; + } + + // Get the gauge config visibility setting or false (invisible) if not found + bool is_gauge_visible(const std::string& gauge_id) const + { + auto it = show_flags_map.find(gauge_id); + return (it != show_flags_map.end()) ? it->second : false; // Default to invisible + } + + void set_gauge_popup(const std::string& gauge_id, bool popup) + { + popup_flags_map[gauge_id] = popup; + } + + // Get the gauge config popup setting or false if not found + bool is_gauge_popup(const std::string& gauge_id) const + { + auto it = popup_flags_map.find(gauge_id); + return (it != popup_flags_map.end()) ? it->second : false; // Default to not a popup + } } HUD_CONFIG_TYPE; extern HUD_CONFIG_TYPE HUD_config; /** - * @struct HC_gauge_region + * @struct HC_gauge_setting * @brief Contains core HUD configuration data */ -struct HC_gauge_region +struct HC_gauge_setting { - const char *filename; // filename for the gauge - int x,y; // x, y coords - int hotspot; // ?? - int use_iff; // if the gauge uses target IFF color for its color - int can_popup; // if the gauge can use the popup method - int bitmap; // bitmap handle - int nframes; // ?? - int color; // If the gauge color respects target tagging? - UI_BUTTON button; // button handle for retail UI hud config + bool use_iff_color; // if the gauge uses target IFF color for its color + bool can_popup; // if the gauge can use the popup method + bool use_tag_color; // If the gauge color respects target tagging? - HC_gauge_region(const char *name, int x1, int y1, int h, int iff, int cp, int b, int nf, int cl) : filename(name), x(x1), y(y1), hotspot(h), use_iff(iff), can_popup(cp), bitmap(b), nframes(nf), color(cl){} + HC_gauge_setting(bool iff, bool cp, bool cl) : use_iff_color(iff), can_popup(cp), use_tag_color(cl){} }; class BoundingBox { @@ -105,6 +130,12 @@ class BoundingBox { // Constructor constexpr BoundingBox(int nx1, int nx2, int ny1, int ny2) : x1(nx1), x2(nx2), y1(ny1), y2(ny2) {} + // Equality operator + bool operator==(const BoundingBox& other) const + { + return x1 == other.x1 && x2 == other.x2 && y1 == other.y1 && y2 == other.y2; + } + bool isOverlapping(const BoundingBox& other) const { return (x2 >= other.x1 && // Not completely to the left @@ -120,40 +151,139 @@ class BoundingBox { } // Static function to check if any bounding box in an array overlaps with a new one - static bool isOverlappingAny(const BoundingBox mouse_coords[NUM_HUD_GAUGES], const BoundingBox& newBox, int self_index) + static bool isOverlappingAny(const SCP_vector>& mouse_coords, const BoundingBox& newBox, SCP_string self_id) { - for (int i = 0; i < NUM_HUD_GAUGES; i++) { - if (i == self_index) { - continue; + return std::any_of(mouse_coords.begin(), mouse_coords.end(), [&](const std::pair& item) { + const auto& [gauge_id, bbox] = item; + if (gauge_id == self_id) { + return false; // Skip checking against itself } - if (mouse_coords[i].isValid() && mouse_coords[i].isOverlapping(newBox)) { - return true; - } - } - return false; + return bbox.isValid() && bbox.isOverlapping(newBox); + }); } }; extern char HC_wingam_gauge_status_names[MAX_SQUADRON_WINGS][32]; -/*! - * @brief Array of hud gauges to be displayed in the hud config ui and configured by the player - * @note main definition in hudconfig.cpp - */ -extern struct HC_gauge_region HC_gauge_regions[GR_NUM_RESOLUTIONS][NUM_HUD_GAUGES]; - -extern int HC_gauge_hot; -extern int HC_gauge_selected; -extern int HC_select_all; -extern float HC_gauge_scale; +extern SCP_vector> HC_gauge_map; +extern SCP_string HC_gauge_hot; +extern SCP_string HC_gauge_selected; +extern SCP_vector> HC_available_huds; +extern int HC_chosen_hud; +extern bool HC_select_all; extern int HC_gauge_coordinates[6]; // x1, x2, y1, y2, w, h for gauge rendering -extern BoundingBox HC_gauge_mouse_coords[NUM_HUD_GAUGES]; - -const char* HC_gauge_descriptions(int n); +extern SCP_vector> HC_gauge_mouse_coords; extern int HC_talking_head_frame; extern SCP_string HC_head_anim_filename; extern SCP_string HC_shield_gauge_ship; +extern bool HC_show_default_hud; +extern std::unordered_set HC_ignored_huds; + +class HC_gauge_mappings { +public: + static HC_gauge_mappings& get_instance() { + static HC_gauge_mappings instance; + return instance; + } + + // Prevent copying + HC_gauge_mappings(const HC_gauge_mappings&) = delete; + HC_gauge_mappings& operator=(const HC_gauge_mappings&) = delete; + + // Numeric ID -> New String ID + SCP_string get_string_id_from_numeric_id(int numeric_id) const { + auto it = gauge_map.find(numeric_id); + return (it != gauge_map.end()) ? it->second.second : ""; + } + + // HCF String Name -> New String ID + SCP_string get_string_id_from_hcf_id(const SCP_string& hcf_name) const + { + for (const auto& [id, mapping] : gauge_map) { + if (XSTR(mapping.first.first.c_str(), mapping.first.second) == hcf_name) { + return mapping.second; + } + } + return ""; + } + + // New String ID -> Numeric ID (for saving to player file) + int get_numeric_id_from_string_id(const SCP_string& string_id) const { + for (const auto& [id, mapping] : gauge_map) { + if (mapping.second == string_id) { + return id; + } + } + return -1; + } + + // New String ID -> HCF String Name (for saving HCF files) + SCP_string get_hcf_name_from_string_id(const SCP_string& string_id) const + { + for (const auto& [id, mapping] : gauge_map) { + if (mapping.second == string_id) { + return XSTR(mapping.first.first.c_str(), mapping.first.second); + } + } + return ""; + } + +private: + HC_gauge_mappings() { + // Map the old gauge_config numeric IDs, the HCF file IDs (which, yes, were translated...), and the newer string IDs + // for the retail built-in gauges. Custom gauges will only have a string ID and do not need to be mapped. + gauge_map = { + {0, {{"lead indicator", 249}, "Builtin::LeadIndicator"}}, + {1, {{"target orientation", 250}, "Builtin::TargetOrientation"}}, + {2, {{"closest attacking hostile", 251}, "Builtin::ClosestAttackingHostile"}}, + {3, {{"current target direction", 252}, "Builtin::CurrentTargetDirection"}}, + {4, {{"mission time", 253}, "Builtin::MissionTime"}}, + {5, {{"reticle", 254}, "Builtin::Reticle"}}, + {6, {{"throttle", 255}, "Builtin::Throttle"}}, + {7, {{"radar", 256}, "Builtin::Radar"}}, + {8, {{"target monitor", 257}, "Builtin::TargetMonitor"}}, + {9, {{"center of reticle", 258}, "Builtin::CenterOfReticle"}}, + {10, {{"extra target info", 259}, "Builtin::ExtraTargetInfo"}}, + {11, {{"target shield", 260}, "Builtin::TargetShield"}}, + {12, {{"player shield", 261}, "Builtin::PlayerShield"}}, + {13, {{"power management", 262}, "Builtin::PowerManagement"}}, + {14, {{"auto-target icon", 263}, "Builtin::AutoTargetIcon"}}, + {15, {{"auto-speed-match icon", 264}, "Builtin::AutoSpeedMatchIcon"}}, + {16, {{"weapons display", 265}, "Builtin::WeaponsDisplay"}}, + {17, {{"monitoring view", 266}, "Builtin::MonitoringView"}}, + {18, {{"directives view", 267}, "Builtin::DirectivesView"}}, + {19, {{"threat gauge", 268}, "Builtin::ThreatGauge"}}, + {20, {{"afterburner energy", 269}, "Builtin::AfterburnerEnergy"}}, + {21, {{"weapons energy", 270}, "Builtin::WeaponsEnergy"}}, + {22, {{"weapon linking", 271}, "Builtin::WeaponLinking"}}, + {23, {{"target hull/shield icon", 272}, "Builtin::TargetHullShieldIcon"}}, + {24, {{"offscreen indicator", 273}, "Builtin::OffscreenIndicator"}}, + {25, {{"comm video", 274}, "Builtin::CommVideo"}}, + {26, {{"damage display", 275}, "Builtin::DamageDisplay"}}, + {27, {{"message output", 276}, "Builtin::MessageOutput"}}, + {28, {{"locked missile direction", 277}, "Builtin::LockedMissileDirection"}}, + {29, {{"countermeasures", 278}, "Builtin::Countermeasures"}}, + {30, {{"objective notify", 279}, "Builtin::ObjectiveNotify"}}, + {31, {{"wingmen status", 280}, "Builtin::WingmenStatus"}}, + {32, {{"offscreen range", 281}, "Builtin::OffscreenRange"}}, + {33, {{"kills gauge", 282}, "Builtin::KillsGauge"}}, + {34, {{"attacking target count", 283}, "Builtin::AttackingTargetCount"}}, + {35, {{"warning flash", 1459}, "Builtin::WarningFlash"}}, + {36, {{"comm menu", 1460}, "Builtin::CommMenu"}}, + {37, {{"support gauge", 1461}, "Builtin::SupportGauge"}}, + {38, {{"lag gauge", 1462}, "Builtin::LagGauge"}} + }; + } + + SCP_unordered_map, SCP_string>> gauge_map; +}; + + +/*! + * @brief get the gauge pointer for the given gauge index + */ +HudGauge* hud_config_get_gauge_pointer(const SCP_string& gauge_id); /*! * @brief init hud config screen, setting up the hud preview display @@ -162,8 +292,9 @@ extern SCP_string HC_shield_gauge_ship; * param[in] x the x coord to render the preview display * param[in] y the y coord to render the preview display * param[in] w the width to render the preview display + * param[in] h the height to render the preview display */ -void hud_config_init(bool API_Access = false, int x = 0, int y = 0, int w = -1); +void hud_config_init(bool API_Access = false, int x = 0, int y = 0, int w = -1, int h = -1); /*! * @brief do a hud config frame, including rendering the preview display and checking for button presses @@ -185,10 +316,20 @@ void hud_config_close(bool API_Access = false); /*! * @brief toggles selecting of all gauges for color modification * - * param[in] toggle 1 to toggle on, 0 for off + * param[bool] toggle true to toggle on, false for off * param[in] API_Access whether or not this method has been called from the lua api */ -void hud_config_select_all_toggle(int toggle, bool API_Access = false); +void hud_config_select_all_toggle(bool toggle, bool API_Access = false); + +/*! + * @brief sets no gauges as selected + */ +void hud_config_select_none(); + +/*! + * @brief sets no gauges as selected + */ +void hud_config_select_hud(bool next); /*! * @brief init the list of preset files found by cfile @@ -214,7 +355,7 @@ void hud_config_delete_preset(SCP_string filename); * param[in] on_flag if the gauge is on or off, 1 for on, 0 for off * param[in] popup_flag if the gauge is set to popup, 1 for popup, 0 otherwise */ -void hud_config_set_gauge_flags(int gauge_index, int on_flag, int popup_flag); +void hud_config_set_gauge_flags(const SCP_string& gauge, bool on_flag, bool popup_flag); void hud_config_restore(); void hud_config_backup(); @@ -232,14 +373,6 @@ void hud_config_cancel(bool change_state = true); */ void hud_config_commit(); -// flag access/manipulation routines -int hud_config_show_flag_is_set(int i); -void hud_config_show_flag_set(int i); -void hud_config_show_flag_clear(int i); -int hud_config_popup_flag_is_set(int i); -void hud_config_popup_flag_set(int i); -void hud_config_popup_flag_clear(int i); - void hud_config_record_color(int color); void hud_config_set_color(int color); @@ -251,7 +384,7 @@ void hud_config_color_load(const char *name); /*! * @brief save the current hud gauges settings to a preset file */ -void hud_config_color_save(const char* name); +void hud_config_color_save(const char* name, int version = 2); /*! * @brief same as hud_config_covert_coords but only returns the scale and doesn't convert any coords @@ -283,7 +416,7 @@ std::tuple hud_config_convert_coord_sys(float x, float y, i /*! * @brief save gauge coords during rendering time so hud config can check if the mouse is hovering over the gauge */ -void hud_config_set_mouse_coords(int gauge_config, int x1, int x2, int y1, int y2); +void hud_config_set_mouse_coords(const SCP_string& gauge_id, int x1, int x2, int y1, int y2); /*! * @brief Function to calculate screen coordinates based on angle. Used for radial positioning gauges @@ -293,13 +426,7 @@ std::pair hud_config_calc_coords_from_angle(float angle_degrees, i /*! * @brief try to find an angle with no overlapping mouse coordinates for target-related gauges */ -float hud_config_find_valid_angle(int gauge_index, float initial_angle, int centerX, int centerY, float radius); - -/*! - * @brief save gauge coords during rendering time so hud config can check if the mouse is hovering over the gauge - * @brief this one is specific to the ETS gauge's individual rendering method - */ -void hud_config_set_mouse_coords_ets(int gauge_config, int x1, int x2, int y1, int y2); +float hud_config_find_valid_angle(const SCP_string& gauge, float initial_angle, int centerX, int centerY, float radius); #endif diff --git a/code/hud/hudescort.cpp b/code/hud/hudescort.cpp index 963c28d0ff..ad6cc49f2a 100644 --- a/code/hud/hudescort.cpp +++ b/code/hud/hudescort.cpp @@ -286,7 +286,7 @@ void HudGaugeEscort::render(float /*frametime*/, bool config) if (config) { int bmw, bmh; bm_get_info(Escort_gauges[2].first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, lx + fl2i(bmw * scale), y, ly + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, lx + fl2i(bmw * scale), y, ly + fl2i(bmh * scale)); } } diff --git a/code/hud/hudets.cpp b/code/hud/hudets.cpp index 4a9a4e2539..72a57cc6fe 100644 --- a/code/hud/hudets.cpp +++ b/code/hud/hudets.cpp @@ -1100,9 +1100,9 @@ void HudGaugeEtsRetail::render(float /*frametime*/, bool config) bm_get_info(Ets_bar.first_frame, &bmw, &bmh); auto coords1 = hud_config_convert_coords(Gauge_positions[0], position[1], scale); - auto coords2 = hud_config_convert_coords(Gauge_positions[initial_position - 1] + bmw, position[1] + (bmh * 2) + 10, scale); + auto coords2 = hud_config_convert_coords(Gauge_positions[initial_position - 1] + bmw, position[1] + (bmh * 2), scale); - hud_config_set_mouse_coords(gauge_config, coords1.first, coords2.first, coords1.second, coords2.second); + hud_config_set_mouse_coords(gauge_config_id, coords1.first, coords2.first, coords1.second, coords2.second); } } @@ -1193,7 +1193,7 @@ void HudGaugeEtsWeapons::render(float /*frametime*/, bool config) int bmw, bmh; bm_get_info(Ets_bar.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords_ets(gauge_config, rx, rx + bmw, ry, ry + (bmh * 2) + 10); + hud_config_set_mouse_coords(gauge_config_id, rx, rx + bmw, ry, ry + (bmh * 2)); } } @@ -1263,7 +1263,7 @@ void HudGaugeEtsShields::render(float /*frametime*/, bool config) int bmw, bmh; bm_get_info(Ets_bar.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords_ets(gauge_config, rx, rx + bmw, ry, ry + (bmh * 2) + 10); + hud_config_set_mouse_coords(gauge_config_id, rx, rx + bmw, ry, ry + (bmh * 2)); } } @@ -1333,6 +1333,6 @@ void HudGaugeEtsEngines::render(float /*frametime*/, bool config) int bmw, bmh; bm_get_info(Ets_bar.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords_ets(gauge_config, rx, rx + bmw, ry, ry + (bmh * 2) + 10); + hud_config_set_mouse_coords(gauge_config_id, rx, rx + bmw, ry, ry + (bmh * 2)); } } diff --git a/code/hud/hudlock.cpp b/code/hud/hudlock.cpp index 073fa437f0..a1dc1407f4 100644 --- a/code/hud/hudlock.cpp +++ b/code/hud/hudlock.cpp @@ -293,7 +293,7 @@ void HudGaugeLock::render(float frametime, bool config) int w; int h; // Will need actual coords for the below if we activate this gauge in config - hud_config_set_mouse_coords(gauge_config, x, x + w, y, y + h); + hud_config_set_mouse_coords(gauge_config_id, x, x + w, y, y + h); setGaugeColor(HUD_C_NONE, config);*/ diff --git a/code/hud/hudmessage.cpp b/code/hud/hudmessage.cpp index 694cff20ac..3a9e3c774e 100644 --- a/code/hud/hudmessage.cpp +++ b/code/hud/hudmessage.cpp @@ -450,7 +450,7 @@ void HudGaugeMessages::render(float /*frametime*/, bool config) int bmw, bmh; SCP_string msg = XSTR("Terran Fighter: HUD Message Display", 1874); gr_get_string_size(&bmw, &bmh, msg.c_str(), scale); - hud_config_set_mouse_coords(gauge_config, x, x + bmw, y, y + bmh); + hud_config_set_mouse_coords(gauge_config_id, x, x + bmw, y, y + bmh); setGaugeColor(HUD_C_NONE, config); renderPrintf(x, y, scale, config, "%s", msg.c_str()); @@ -1206,7 +1206,7 @@ void HudGaugeTalkingHead::render(float frametime, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Head_frame.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); // Talking head is complex enough that we can do all the config rendering right here and exit early setGaugeColor(HUD_C_NONE, config); @@ -1398,7 +1398,7 @@ void HudGaugeFixedMessages::render(float /*frametime*/, bool config) { // That may change in the future, in which case the code below can be restored. if (config) { /*std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); - hud_config_set_mouse_coords(gauge_config, x - fl2i(w * scale), x + fl2i(w * scale), y, y + fl2i(h * scale));*/ + hud_config_set_mouse_coords(gauge_config_id, x - fl2i(w * scale), x + fl2i(w * scale), y, y + fl2i(h * scale));*/ return; } diff --git a/code/hud/hudobserver.cpp b/code/hud/hudobserver.cpp index f370152cb1..7488b72477 100644 --- a/code/hud/hudobserver.cpp +++ b/code/hud/hudobserver.cpp @@ -44,11 +44,12 @@ void hud_observer_init(ship *shipp, ai_info *aip) Hud_obs_ship.weapons = shipp->weapons; HUD_config.is_observer = 1; - HUD_config.show_flags = HUD_observer_default_flags; - HUD_config.show_flags2 = HUD_observer_default_flags2; + HUD_config.show_flags_map.clear(); + HUD_config.popup_flags_map.clear(); - HUD_config.popup_flags = 0x0; - HUD_config.popup_flags2 = 0x0; + for (const auto& gauge_id : observer_visible_gauges) { + HUD_config.show_flags_map[gauge_id] = true; + } // shutdown any playing static animations hud_init_target_static(); diff --git a/code/hud/hudparse.cpp b/code/hud/hudparse.cpp index a186c0f3e2..72153a8c7d 100644 --- a/code/hud/hudparse.cpp +++ b/code/hud/hudparse.cpp @@ -238,6 +238,9 @@ void parse_hud_gauges_tbl(const char *filename) reset_parse(); if (optional_string("#HUD Config Settings")) { + if (optional_string("$Show Default HUD:")) { + stuff_boolean(&HC_show_default_hud); + } if (optional_string("$Head Animation:")) { stuff_string(HC_head_anim_filename, F_NAME); } @@ -459,6 +462,15 @@ void parse_hud_gauges_tbl(const char *filename) case 2: stuff_string(name, F_NAME); + if (optional_string("$Show in HUD Config:")) { + bool show = true; + stuff_boolean(&show); + + if (!show) { + HC_ignored_huds.insert(name); + } + } + if (optional_string("$Load Retail Configuration:")) { stuff_boolean(&retail_config); } @@ -648,8 +660,6 @@ void hud_positions_init() // load missing retail gauges for the default and ship-specific HUDs load_missing_retail_gauges(); - - Hud_parsed_ships.clear(); } void load_missing_retail_gauges() @@ -776,38 +786,44 @@ void init_hud() { for(i = 0; i < num_gauges; i++) { config_type = Ship_info[Player_ship->ship_info_index].hud_gauges[i]->getConfigType(); + SCP_string config_id = Ship_info[Player_ship->ship_info_index].hud_gauges[i]->getConfigId(); - if ( !Ship_info[Player_ship->ship_info_index].hud_gauges[i]->isOffbyDefault() && hud_config_show_flag_is_set(config_type) ) + if ( !Ship_info[Player_ship->ship_info_index].hud_gauges[i]->isOffbyDefault() && HUD_config.is_gauge_visible(config_id) ) Ship_info[Player_ship->ship_info_index].hud_gauges[i]->updateActive(true); else Ship_info[Player_ship->ship_info_index].hud_gauges[i]->updateActive(false); - Ship_info[Player_ship->ship_info_index].hud_gauges[i]->updatePopUp(hud_config_popup_flag_is_set(config_type) ? true : false); - Ship_info[Player_ship->ship_info_index].hud_gauges[i]->updateColor( - HUD_config.clr[config_type].red, - HUD_config.clr[config_type].green, - HUD_config.clr[config_type].blue, - HUD_config.clr[config_type].alpha - ); + Ship_info[Player_ship->ship_info_index].hud_gauges[i]->updatePopUp(HUD_config.is_gauge_popup(config_id)); + color clr; + if (config_id.empty()) { + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + clr = HUD_config.gauge_colors[gauge_map.get_string_id_from_numeric_id(config_type)]; + } else { + clr = HUD_config.get_gauge_color(config_id); + } + Ship_info[Player_ship->ship_info_index].hud_gauges[i]->updateColor(clr.red, clr.green, clr.blue, clr.alpha); } } else { num_gauges = default_hud_gauges.size(); for(i = 0; i < num_gauges; i++) { config_type = default_hud_gauges[i]->getConfigType(); + SCP_string config_id = default_hud_gauges[i]->getConfigId(); - if ( !default_hud_gauges[i]->isOffbyDefault() && hud_config_show_flag_is_set(config_type) ) + if ( !default_hud_gauges[i]->isOffbyDefault() && HUD_config.is_gauge_visible(config_id) ) default_hud_gauges[i]->updateActive(true); else default_hud_gauges[i]->updateActive(false); - default_hud_gauges[i]->updatePopUp(hud_config_popup_flag_is_set(config_type) ? true : false); - default_hud_gauges[i]->updateColor( - HUD_config.clr[config_type].red, - HUD_config.clr[config_type].green, - HUD_config.clr[config_type].blue, - HUD_config.clr[config_type].alpha - ); + default_hud_gauges[i]->updatePopUp(HUD_config.is_gauge_popup(config_id)); + color clr; + if (config_id.empty()) { + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + clr = HUD_config.gauge_colors[gauge_map.get_string_id_from_numeric_id(config_type)]; + } else { + clr = HUD_config.get_gauge_color(config_id); + } + default_hud_gauges[i]->updateColor(clr.red, clr.green, clr.blue, clr.alpha); } } } @@ -829,40 +845,46 @@ void set_current_hud() for(i = 0; i < num_gauges; i++) { HudGauge* hgp = Ship_info[Player_ship->ship_info_index].hud_gauges[i].get(); config_type = hgp->getConfigType(); + SCP_string config_id = hgp->getConfigId(); - if ( ( (!hgp->isOffbyDefault() || hgp->isActive()) && hud_config_show_flag_is_set(config_type)) ) + if ( ( (!hgp->isOffbyDefault() || hgp->isActive()) && HUD_config.is_gauge_visible(config_id)) ) hgp->updateActive(true); else hgp->updateActive(false); //hgp->updateActive(hud_config_show_flag_is_set(config_type) ? true : false); - hgp->updatePopUp(hud_config_popup_flag_is_set(config_type) ? true : false); - hgp->updateColor( - HUD_config.clr[config_type].red, - HUD_config.clr[config_type].green, - HUD_config.clr[config_type].blue, - HUD_config.clr[config_type].alpha - ); + hgp->updatePopUp(HUD_config.is_gauge_popup(config_id)); + color clr; + if (config_id.empty()) { + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + clr = HUD_config.gauge_colors[gauge_map.get_string_id_from_numeric_id(config_type)]; + } else { + clr = HUD_config.get_gauge_color(config_id); + } + hgp->updateColor(clr.red, clr.green, clr.blue, clr.alpha); } } else { num_gauges = default_hud_gauges.size(); for(i = 0; i < num_gauges; i++) { config_type = default_hud_gauges[i]->getConfigType(); + SCP_string config_id = default_hud_gauges[i]->getConfigId(); - if ( ( (!default_hud_gauges[i]->isOffbyDefault() || default_hud_gauges[i]->isActive()) && hud_config_show_flag_is_set(config_type)) ) + if ( ( (!default_hud_gauges[i]->isOffbyDefault() || default_hud_gauges[i]->isActive()) &&HUD_config.is_gauge_visible(config_id)) ) default_hud_gauges[i]->updateActive(true); else default_hud_gauges[i]->updateActive(false); //default_hud_gauges[i]->updateActive(hud_config_show_flag_is_set(config_type) ? true : false); - default_hud_gauges[i]->updatePopUp(hud_config_popup_flag_is_set(config_type) ? true : false); - default_hud_gauges[i]->updateColor( - HUD_config.clr[config_type].red, - HUD_config.clr[config_type].green, - HUD_config.clr[config_type].blue, - HUD_config.clr[config_type].alpha - ); + default_hud_gauges[i]->updatePopUp(HUD_config.is_gauge_popup(config_id)); + color clr; + if (config_id.empty()) { + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + clr = HUD_config.gauge_colors[gauge_map.get_string_id_from_numeric_id(config_type)]; + } else { + clr = HUD_config.get_gauge_color(config_id); + } + default_hud_gauges[i]->updateColor(clr.red, clr.green, clr.blue, clr.alpha); } } } @@ -1304,6 +1326,7 @@ std::unique_ptr gauge_load_common(gauge_settings* settings, T* preAllocated = int display_size[2] = {0, 0}; int display_offset[2] = {0, 0}; int canvas_size[2] = {0, 0}; + bool visible_in_config = true; if(check_base_res(settings->base_res)) { if (settings->set_position) { @@ -1435,6 +1458,10 @@ std::unique_ptr gauge_load_common(gauge_settings* settings, T* preAllocated = } } + if (optional_string("Config:")) { + stuff_boolean(&visible_in_config); + } + std::unique_ptr instance(preAllocated); if (instance == NULL) @@ -1463,6 +1490,7 @@ std::unique_ptr gauge_load_common(gauge_settings* settings, T* preAllocated = //In this case, we must always slew every hud gauge, no matter what. instance->initSlew(true); } + instance->initVisible_in_config(visible_in_config); return instance; } @@ -1500,6 +1528,7 @@ void load_gauge_custom(gauge_settings* settings) int display_size[2] = {0, 0}; int display_offset[2] = {0, 0}; int canvas_size[2] = {0, 0}; + bool visible_in_config = true; if(check_base_res(settings->base_res)) { if(optional_string("Position:")) { @@ -1626,6 +1655,10 @@ void load_gauge_custom(gauge_settings* settings) stuff_boolean(&settings->slew); } + if (optional_string("Config:")) { + stuff_boolean(&visible_in_config); + } + if(optional_string("Active by default:")) { stuff_boolean(&active_by_default); } @@ -1655,6 +1688,7 @@ void load_gauge_custom(gauge_settings* settings) hud_gauge->initCockpitTarget(display_name, display_offset[0], display_offset[1], display_size[0], display_size[1], canvas_size[0], canvas_size[1]); hud_gauge->initChase_view_only(settings->chase_view_only); hud_gauge->initCockpit_view_choice(settings->cockpit_view_choice); + hud_gauge->initVisible_in_config(visible_in_config); gauge_assign_common(settings, std::move(hud_gauge)); } diff --git a/code/hud/hudreticle.cpp b/code/hud/hudreticle.cpp index 0ae67c9034..00ad4364d0 100644 --- a/code/hud/hudreticle.cpp +++ b/code/hud/hudreticle.cpp @@ -264,7 +264,7 @@ void HudGaugeReticle::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(crosshair.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } ship_info* sip = nullptr; @@ -687,7 +687,7 @@ void HudGaugeThrottle::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(throttle_frames.first_frame + 1, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } int desired_y_pos = y + fl2i(Bottom_offset_y * scale) - fl2i(std::lround(fl2i(throttle_h * scale) * desired_speed / max_speed)) - 1; @@ -999,7 +999,11 @@ void HudGaugeThreatIndicator::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(threat_arc.first_frame + 1, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + static_cast(bmw * scale), y, y + static_cast(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, + x, + x + static_cast(bmw * scale), + y, + y + static_cast(bmh * scale)); } setGaugeColor(HUD_C_NONE, config); @@ -1178,7 +1182,7 @@ void HudGaugeWeaponLinking::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(arc.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } setGaugeColor(HUD_C_NONE, config); diff --git a/code/hud/hudshield.cpp b/code/hud/hudshield.cpp index bf51f6aefd..a133d8d9a3 100644 --- a/code/hud/hudshield.cpp +++ b/code/hud/hudshield.cpp @@ -768,7 +768,7 @@ void HudGaugeShield::showShields(const object *objp, int mode, bool config) if (config) { int bmw, bmh; bm_get_info(sgp->first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } } @@ -783,7 +783,7 @@ void HudGaugeShield::showShields(const object *objp, int mode, bool config) // If this comment is here then I have not tested this if (config) { - hud_config_set_mouse_coords(gauge_config, x, x + BAR_LENGTH, y, y + BAR_HEIGHT); + hud_config_set_mouse_coords(gauge_config_id, x, x + BAR_LENGTH, y, y + BAR_HEIGHT); } switch(i) @@ -1032,7 +1032,7 @@ void HudGaugeShieldMini::showMiniShields(const object *objp, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Shield_mini_gauge.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + static_cast(bmw * scale), y, y + static_cast(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + static_cast(bmw * scale), y, y + static_cast(bmh * scale)); } setGaugeColor(HUD_C_NONE, config); diff --git a/code/hud/hudsquadmsg.cpp b/code/hud/hudsquadmsg.cpp index bb9886992d..9b8408af0a 100644 --- a/code/hud/hudsquadmsg.cpp +++ b/code/hud/hudsquadmsg.cpp @@ -2812,7 +2812,7 @@ void HudGaugeSquadMessage::render(float /*frametime*/, bool config) if (config) { int bmw, bmh; bm_get_info(Mbox_gauge[2].first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, bx + fl2i(bmw * scale), y, by + fl2i((bmh + bottom_bg_offset) * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, bx + fl2i(bmw * scale), y, by + fl2i((bmh + bottom_bg_offset) * scale)); } } diff --git a/code/hud/hudtarget.cpp b/code/hud/hudtarget.cpp index 26c6223c0a..d7e50f6a73 100644 --- a/code/hud/hudtarget.cpp +++ b/code/hud/hudtarget.cpp @@ -2776,7 +2776,7 @@ void HudGaugeOrientationTee::renderOrientation(object *from_objp, object *to_obj // Rotate the angle so that 0 is on top angle -= 180.0f; - angle = hud_config_find_valid_angle(gauge_config, angle, x + fl2i(HUD_nose_x * scale), y + fl2i(HUD_nose_y * scale), Radius * scale); + angle = hud_config_find_valid_angle(gauge_config_id, angle, x + fl2i(HUD_nose_x * scale), y + fl2i(HUD_nose_y * scale), Radius * scale); // Convert angle to radians float angle_radians = angle * static_cast(M_PI) / 180.0f; @@ -2821,7 +2821,7 @@ void HudGaugeOrientationTee::renderOrientation(object *from_objp, object *to_obj float y_min = std::min({y1, y2, y3, y4}); float y_max = std::max({y1, y2, y3, y4}); - hud_config_set_mouse_coords(gauge_config, fl2i(x_min), fl2i(x_max), fl2i(y_min), fl2i(y_max)); + hud_config_set_mouse_coords(gauge_config_id, fl2i(x_min), fl2i(x_max), fl2i(y_min), fl2i(y_max)); } // HACK! Should be antialiased! @@ -3025,7 +3025,7 @@ void HudGaugeReticleTriangle::renderTriangleMissileTail(float ang, float xpos, f float min_y = std::min({ypos, y1, y2, ytail}); float max_y = std::max({ypos, y1, y2, ytail}); - hud_config_set_mouse_coords(gauge_config, fl2i(min_x), fl2i(max_x), fl2i(min_y), fl2i(max_y)); + hud_config_set_mouse_coords(gauge_config_id, fl2i(min_x), fl2i(max_x), fl2i(min_y), fl2i(max_y)); } gr_reset_screen_scale(); } @@ -3175,7 +3175,7 @@ void HudGaugeReticleTriangle::renderTriangle(vec3d *hostile_pos, int aspect_flag float min_y = std::min({ypos, y1, y2}); float max_y = std::max({ypos, y1, y2}); - hud_config_set_mouse_coords(gauge_config, fl2i(min_x), fl2i(max_x), fl2i(min_y), fl2i(max_y)); + hud_config_set_mouse_coords(gauge_config_id, fl2i(min_x), fl2i(max_x), fl2i(min_y), fl2i(max_y)); } } } @@ -3255,7 +3255,7 @@ void HudGaugeMissileTriangles::render(float /*frametime*/, bool config) float scale; std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); - angle = hud_config_find_valid_angle(gauge_config, angle, x + fl2i(HUD_nose_x * scale), y + fl2i(HUD_nose_y * scale), Radius * scale); + angle = hud_config_find_valid_angle(gauge_config_id, angle, x + fl2i(HUD_nose_x * scale), y + fl2i(HUD_nose_y * scale), Radius * scale); auto pair = hud_config_calc_coords_from_angle(angle, x + fl2i(HUD_nose_x * scale), @@ -3797,7 +3797,7 @@ void HudGaugeHostileTriangle::render(float /*frametime*/, bool config) float scale; std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); - angle = hud_config_find_valid_angle(gauge_config, angle, x + fl2i(HUD_nose_x * scale), y + fl2i(HUD_nose_y * scale), Radius * scale); + angle = hud_config_find_valid_angle(gauge_config_id, angle, x + fl2i(HUD_nose_x * scale), y + fl2i(HUD_nose_y * scale), Radius * scale); auto pair = hud_config_calc_coords_from_angle(angle, x + fl2i(HUD_nose_x * scale), @@ -4113,7 +4113,7 @@ void HudGaugeLeadIndicator::renderIndicator(int frame_offset, object *targetp, v int max_attempts = 100; // Limit to avoid infinite loops int attempts = 0; - while (BoundingBox::isOverlappingAny(HC_gauge_mouse_coords, newBox, gauge_config)) { + while (BoundingBox::isOverlappingAny(HC_gauge_mouse_coords, newBox, gauge_config_id)) { if (++attempts > max_attempts) { break; // Safety net } @@ -4141,7 +4141,7 @@ void HudGaugeLeadIndicator::renderIndicator(int frame_offset, object *targetp, v int mx = fl2i(x - i2fl(Lead_indicator_half[0] * scale)); int my = fl2i(y - i2fl(Lead_indicator_half[1] * scale)); - hud_config_set_mouse_coords(gauge_config, mx, mx + fl2i(bmw * scale), my, my + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, mx, mx + fl2i(bmw * scale), my, my + fl2i(bmh * scale)); } else { unsize(&x, &y); } @@ -4847,7 +4847,7 @@ void HudGaugeTargetTriangle::render(float /*frametime*/, bool config) float scale; std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); - angle = hud_config_find_valid_angle(gauge_config, angle, x + fl2i(HUD_nose_x * scale), y + fl2i(HUD_nose_y * scale), Radius * scale); + angle = hud_config_find_valid_angle(gauge_config_id, angle, x + fl2i(HUD_nose_x * scale), y + fl2i(HUD_nose_y * scale), Radius * scale); auto pair = hud_config_calc_coords_from_angle(angle, x + fl2i(HUD_nose_x * scale), @@ -5104,7 +5104,7 @@ void HudGaugeAutoTarget::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Toggle_frame.first_frame + frame_offset, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } // draw the box background @@ -5202,7 +5202,7 @@ void HudGaugeAutoSpeed::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Toggle_frame.first_frame + frame_offset, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } setGaugeColor(HUD_C_NONE, config); @@ -5818,7 +5818,7 @@ void HudGaugeCmeasures::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Cmeasure_gauge.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } // hud_set_default_color(); @@ -5885,7 +5885,7 @@ void HudGaugeAfterburner::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Energy_bar.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } clip_h = fl2i(std::lround((1.0f - percent_left) * Energy_h)); @@ -6001,7 +6001,7 @@ void HudGaugeWeaponEnergy::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Energy_bar.first_frame+2, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } if(use_new_gauge) @@ -6750,7 +6750,7 @@ void HudGaugeWeapons::render(float /*frametime*/, bool config) if (config) { int bmw, bmh; bm_get_info(secondary_bottom[ballistic_hud_index].first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i((bmw + frame_offset_x[ballistic_hud_index]) * scale), y, ty + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i((bmw + frame_offset_x[ballistic_hud_index]) * scale), y, ty + fl2i(bmh * scale)); } } @@ -7200,7 +7200,7 @@ void HudGaugeOffscreen::renderOffscreenIndicator(vec2d *coords, int dir, float d } if (config) { - hud_config_set_mouse_coords(gauge_config, fl2i(xpos - w), fl2i(xpos + w), fl2i(ypos), fl2i(ypos + h * 2.0f)); + hud_config_set_mouse_coords(gauge_config_id, fl2i(xpos - w), fl2i(xpos + w), fl2i(ypos), fl2i(ypos + h * 2.0f)); } gr_reset_screen_scale(); diff --git a/code/hud/hudtargetbox.cpp b/code/hud/hudtargetbox.cpp index 753a8760d7..1bfa323ff3 100644 --- a/code/hud/hudtargetbox.cpp +++ b/code/hud/hudtargetbox.cpp @@ -402,7 +402,7 @@ void HudGaugeTargetBox::render(float frametime, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Monitor_frame.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } setGaugeColor(HUD_C_NONE, config); @@ -1569,7 +1569,7 @@ void HudGaugeExtraTargetData::render(float /*frametime*/, bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(bracket.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(order_max_w * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(order_max_w * scale), y, y + fl2i(bmh * scale)); } setGaugeColor(HUD_C_NONE, config); diff --git a/code/hud/hudwingmanstatus.cpp b/code/hud/hudwingmanstatus.cpp index 8b6730e256..78651acbe5 100644 --- a/code/hud/hudwingmanstatus.cpp +++ b/code/hud/hudwingmanstatus.cpp @@ -413,7 +413,7 @@ void HudGaugeWingmanStatus::renderBackground(int num_wings_to_draw, bool config) if (config) { int bmw, bmh; bm_get_info(Wingman_status_right.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, actual_origin[0], sx + fl2i(bmw * scale), actual_origin[1], sy + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, actual_origin[0], sx + fl2i(bmw * scale), actual_origin[1], sy + fl2i(bmh * scale)); } } diff --git a/code/localization/localize.cpp b/code/localization/localize.cpp index 5a9d7e086e..dc2806a96f 100644 --- a/code/localization/localize.cpp +++ b/code/localization/localize.cpp @@ -64,7 +64,7 @@ bool *Lcl_unexpected_tstring_check = nullptr; // NOTE: with map storage of XSTR strings, the indexes no longer need to be contiguous, // but internal strings should still increment XSTR_SIZE to avoid collisions. // retail XSTR_SIZE = 1570 -// #define XSTR_SIZE 1876 // This is the next available ID +// #define XSTR_SIZE 1877 // This is the next available ID // struct to allow for strings.tbl-determined x offset // offset is 0 for english, by default diff --git a/code/mission/missiontraining.cpp b/code/mission/missiontraining.cpp index 22f96bb17a..b4ba3a6e6f 100644 --- a/code/mission/missiontraining.cpp +++ b/code/mission/missiontraining.cpp @@ -219,7 +219,7 @@ bool HudGaugeDirectives::canRender() const } } - if (gauge_config == HUD_ETS_GAUGE) { + if (gauge_type == HUD_ETS_GAUGE) { if (Ships[Player_obj->instance].flags[Ship::Ship_Flags::No_ets]) { return false; } @@ -397,7 +397,7 @@ void HudGaugeDirectives::render(float /*frametime*/, bool config) if (config) { int bmw, bmh; bm_get_info(directives_bottom.first_frame, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, bx + fl2i(bmw * scale), y, by + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, bx + fl2i(bmw * scale), y, by + fl2i(bmh * scale)); } } diff --git a/code/parse/sexp.cpp b/code/parse/sexp.cpp index 29999cd3ed..a561e2ad4b 100644 --- a/code/parse/sexp.cpp +++ b/code/parse/sexp.cpp @@ -13561,7 +13561,8 @@ void sexp_hud_reset_color(int n) WarningEx(LOCATION, "HUD gauge %s does not have a built-in configured color!", gaugename); } else { // use the color as specified in the HUD config - auto& c = HUD_config.clr[std::distance(std::begin(Legacy_HUD_gauges), ii)]; + auto id = hg->getConfigId(); + auto& c = HUD_config.gauge_colors[id]; hg->sexpLockConfigColor(false); hg->updateColor(c.red, c.green, c.blue, (HUD_color_alpha + 1) * 16); diff --git a/code/pilotfile/csg.cpp b/code/pilotfile/csg.cpp index 3720598fb9..60010e5d07 100644 --- a/code/pilotfile/csg.cpp +++ b/code/pilotfile/csg.cpp @@ -1013,20 +1013,41 @@ void pilotfile::csg_write_redalert() void pilotfile::csg_read_hud() { - int idx; + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + int strikes = 0; // flags - HUD_config.show_flags = cfread_int(cfp); - HUD_config.show_flags2 = cfread_int(cfp); + int show_flags = cfread_int(cfp); + int show_flags2 = cfread_int(cfp); - HUD_config.popup_flags = cfread_int(cfp); - HUD_config.popup_flags2 = cfread_int(cfp); + int popup_flags = cfread_int(cfp); + int popup_flags2 = cfread_int(cfp); + + // Convert show_flags (0-31) and show_flags2 (32-63) + for (int i = 0; i < 64; i++) { + bool is_set = (i < 32) ? (show_flags & (1 << i)) : (show_flags2 & (1 << (i - 32))); + SCP_string gauge_id = gauge_map.get_string_id_from_numeric_id(i); + + if (!gauge_id.empty()) { + HUD_config.set_gauge_visibility(gauge_id, is_set); + } + } + + // Convert popup_flags (0-31) and popup_flags2 (32-63) + for (int i = 0; i < 64; i++) { + bool is_set = (i < 32) ? (popup_flags & (1 << i)) : (popup_flags2 & (1 << (i - 32))); + SCP_string gauge_id = gauge_map.get_string_id_from_numeric_id(i); + + if (!gauge_id.empty()) { + HUD_config.set_gauge_popup(gauge_id, is_set); + } + } // settings - HUD_config.num_msg_window_lines = cfread_ubyte(cfp); + SCP_UNUSED(cfread_ubyte(cfp));// Deprecated but still read for file compatibility 3/7/2025 + SCP_UNUSED(cfread_int(cfp));// Deprecated but still read for file compatibility 3/7/2025 - HUD_config.rp_flags = cfread_int(cfp); HUD_config.rp_dist = cfread_int(cfp); if (HUD_config.rp_dist < 0 || HUD_config.rp_dist >= RR_MAX_RANGES) { ReleaseWarning(LOCATION, "Campaign file has invalid radar range %d, setting to default.\n", HUD_config.rp_dist); @@ -1058,7 +1079,7 @@ void pilotfile::csg_read_hud() // gauge-specific colors int num_gauges = cfread_int(cfp); - for (idx = 0; idx < num_gauges; idx++) { + for (int idx = 0; idx < num_gauges; idx++) { ubyte red = cfread_ubyte(cfp); ubyte green = cfread_ubyte(cfp); ubyte blue = cfread_ubyte(cfp); @@ -1068,30 +1089,61 @@ void pilotfile::csg_read_hud() continue; } - HUD_config.clr[idx].red = red; - HUD_config.clr[idx].green = green; - HUD_config.clr[idx].blue = blue; - HUD_config.clr[idx].alpha = alpha; + SCP_string gauge_id = gauge_map.get_string_id_from_numeric_id(idx); + if (!gauge_id.empty()) { + color clr; + gr_init_alphacolor(&clr, red, green, blue, alpha); + HUD_config.set_gauge_color(gauge_id, clr); + } } } void pilotfile::csg_write_hud() { - int idx; - startSection(Section::HUD); - // flags - cfwrite_int(HUD_config.show_flags, cfp); - cfwrite_int(HUD_config.show_flags2, cfp); + // Get gauge mappings instance + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); - cfwrite_int(HUD_config.popup_flags, cfp); - cfwrite_int(HUD_config.popup_flags2, cfp); + // Initialize bitfields + int show_flags = 0, show_flags2 = 0; + int popup_flags = 0, popup_flags2 = 0; + + // Convert show_flags_map to bitfield + for (int i = 0; i < 64; i++) { + SCP_string gauge_id = gauge_map.get_string_id_from_numeric_id(i); + if (!gauge_id.empty() && HUD_config.is_gauge_visible(gauge_id)) { + if (i < 32) { + show_flags |= (1 << i); + } else { + show_flags2 |= (1 << (i - 32)); + } + } + } + + // Convert popup_flags_map to bitfield + for (int i = 0; i < 64; i++) { + SCP_string gauge_id = gauge_map.get_string_id_from_numeric_id(i); + if (!gauge_id.empty() && HUD_config.is_gauge_popup(gauge_id)) { + if (i < 32) { + popup_flags |= (1 << i); + } else { + popup_flags2 |= (1 << (i - 32)); + } + } + } + + // flags + cfwrite_int(show_flags, cfp); + cfwrite_int(show_flags2, cfp); + + cfwrite_int(popup_flags, cfp); + cfwrite_int(popup_flags2, cfp); // settings - cfwrite_ubyte(HUD_config.num_msg_window_lines, cfp); + cfwrite_ubyte(0, cfp);// Deprecated but still written for file compatibility 3/7/2025 + cfwrite_int(0, cfp);// Deprecated but still written for file compatibility 3/7/2025 - cfwrite_int(HUD_config.rp_flags, cfp); cfwrite_int(HUD_config.rp_dist, cfp); // basic colors @@ -1101,11 +1153,15 @@ void pilotfile::csg_write_hud() // gauge-specific colors cfwrite_int(NUM_HUD_GAUGES, cfp); - for (idx = 0; idx < NUM_HUD_GAUGES; idx++) { - cfwrite_ubyte(HUD_config.clr[idx].red, cfp); - cfwrite_ubyte(HUD_config.clr[idx].green, cfp); - cfwrite_ubyte(HUD_config.clr[idx].blue, cfp); - cfwrite_ubyte(HUD_config.clr[idx].alpha, cfp); + for (int idx = 0; idx < NUM_HUD_GAUGES; idx++) { + // Get the gauge string ID from numeric ID + SCP_string gauge_id = gauge_map.get_string_id_from_numeric_id(idx); + color clr = HUD_config.get_gauge_color(gauge_id); + + cfwrite_ubyte(clr.red, cfp); + cfwrite_ubyte(clr.green, cfp); + cfwrite_ubyte(clr.blue, cfp); + cfwrite_ubyte(clr.alpha, cfp); } endSection(); diff --git a/code/pilotfile/plr.cpp b/code/pilotfile/plr.cpp index 9d815ef6d0..b66459449e 100644 --- a/code/pilotfile/plr.cpp +++ b/code/pilotfile/plr.cpp @@ -182,18 +182,40 @@ void pilotfile::plr_write_info() void pilotfile::plr_read_hud() { + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + int strikes = 0; // flags - HUD_config.show_flags = handler->readInt("show_flags"); - HUD_config.show_flags2 = handler->readInt("show_flags2"); + int show_flags = handler->readInt("show_flags"); + int show_flags2 = handler->readInt("show_flags2"); - HUD_config.popup_flags = handler->readInt("popup_flags"); - HUD_config.popup_flags2 = handler->readInt("popup_flags2"); + int popup_flags = handler->readInt("popup_flags"); + int popup_flags2 = handler->readInt("popup_flags2"); + + // Convert show_flags (0-31) and show_flags2 (32-63) + for (int i = 0; i < 64; i++) { + bool is_set = (i < 32) ? (show_flags & (1 << i)) : (show_flags2 & (1 << (i - 32))); + SCP_string gauge_id = gauge_map.get_string_id_from_numeric_id(i); + + if (!gauge_id.empty()) { + HUD_config.set_gauge_visibility(gauge_id, is_set); + } + } + + // Convert popup_flags (0-31) and popup_flags2 (32-63) + for (int i = 0; i < 64; i++) { + bool is_set = (i < 32) ? (popup_flags & (1 << i)) : (popup_flags2 & (1 << (i - 32))); + SCP_string gauge_id = gauge_map.get_string_id_from_numeric_id(i); + + if (!gauge_id.empty()) { + HUD_config.set_gauge_popup(gauge_id, is_set); + } + } // settings - HUD_config.num_msg_window_lines = handler->readUByte("num_msg_window_lines"); + SCP_UNUSED(handler->readUByte("num_msg_window_lines"));// Deprecated but still read for file compatibility 3/7/2025 + SCP_UNUSED(handler->readInt("rp_flags"));// Deprecated but still read for file compatibility 3/7/2025 - HUD_config.rp_flags = handler->readInt("rp_flags"); HUD_config.rp_dist = handler->readInt("rp_dist"); if (HUD_config.rp_dist < 0 || HUD_config.rp_dist >= RR_MAX_RANGES) { ReleaseWarning(LOCATION, "Player file has invalid radar range %d, setting to default.\n", HUD_config.rp_dist); @@ -224,7 +246,7 @@ void pilotfile::plr_read_hud() // gauge-specific colors auto num_gauges = handler->startArrayRead("hud_gauges"); - for (size_t idx = 0; idx < num_gauges; idx++, handler->nextArraySection()) { + for (int idx = 0; idx < static_cast(num_gauges); idx++, handler->nextArraySection()) { ubyte red = handler->readUByte("red"); ubyte green = handler->readUByte("green"); ubyte blue = handler->readUByte("blue"); @@ -235,31 +257,62 @@ void pilotfile::plr_read_hud() continue; } - HUD_config.clr[idx].red = red; - HUD_config.clr[idx].green = green; - HUD_config.clr[idx].blue = blue; - HUD_config.clr[idx].alpha = alpha; + SCP_string gauge_id = gauge_map.get_string_id_from_numeric_id(idx); + if (!gauge_id.empty()) { + color clr; + gr_init_alphacolor(&clr, red, green, blue, alpha); + HUD_config.set_gauge_color(gauge_id, clr); + } } handler->endArrayRead(); } void pilotfile::plr_write_hud() { - int idx; - handler->startSectionWrite(Section::HUD); - // flags - handler->writeInt("show_flags", HUD_config.show_flags); - handler->writeInt("show_flags2", HUD_config.show_flags2); + // Get gauge mappings instance + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); - handler->writeInt("popup_flags", HUD_config.popup_flags); - handler->writeInt("popup_flags2", HUD_config.popup_flags2); + // Initialize bitfields + int show_flags = 0, show_flags2 = 0; + int popup_flags = 0, popup_flags2 = 0; + + // Convert show_flags_map to bitfield + for (int i = 0; i < 64; i++) { + SCP_string gauge_id = gauge_map.get_string_id_from_numeric_id(i); + if (!gauge_id.empty() && HUD_config.is_gauge_visible(gauge_id)) { + if (i < 32) { + show_flags |= (1 << i); + } else { + show_flags2 |= (1 << (i - 32)); + } + } + } + + // Convert popup_flags_map to bitfield + for (int i = 0; i < 64; i++) { + SCP_string gauge_id = gauge_map.get_string_id_from_numeric_id(i); + if (!gauge_id.empty() && HUD_config.is_gauge_popup(gauge_id)) { + if (i < 32) { + popup_flags |= (1 << i); + } else { + popup_flags2 |= (1 << (i - 32)); + } + } + } + + // Write converted bitfields + handler->writeInt("show_flags", show_flags); + handler->writeInt("show_flags2", show_flags2); + + handler->writeInt("popup_flags", popup_flags); + handler->writeInt("popup_flags2", popup_flags2); // settings - handler->writeUByte("num_msg_window_lines", HUD_config.num_msg_window_lines); + handler->writeUByte("num_msg_window_lines", 0);// Deprecated but still written for file compatibility 3/7/2025 + handler->writeInt("rp_flags", 0);// Deprecated but still written for file compatibility 3/7/2025 - handler->writeInt("rp_flags", HUD_config.rp_flags); handler->writeInt("rp_dist", HUD_config.rp_dist); // basic colors @@ -268,13 +321,17 @@ void pilotfile::plr_write_hud() // gauge-specific colors handler->startArrayWrite("hud_gauges", NUM_HUD_GAUGES); - for (idx = 0; idx < NUM_HUD_GAUGES; idx++) { + for (int idx = 0; idx < NUM_HUD_GAUGES; idx++) { handler->startSectionWrite(Section::Unnamed); - handler->writeUByte("red", HUD_config.clr[idx].red); - handler->writeUByte("green", HUD_config.clr[idx].green); - handler->writeUByte("blue", HUD_config.clr[idx].blue); - handler->writeUByte("alpha", HUD_config.clr[idx].alpha); + // Get the gauge string ID from numeric ID + SCP_string gauge_id = gauge_map.get_string_id_from_numeric_id(idx); + color clr = HUD_config.get_gauge_color(gauge_id); + + handler->writeUByte("red", clr.red); + handler->writeUByte("green", clr.green); + handler->writeUByte("blue", clr.blue); + handler->writeUByte("alpha", clr.alpha); handler->endSectionWrite(); } diff --git a/code/radar/radar.cpp b/code/radar/radar.cpp index ca2f541880..9bf32bf9ee 100644 --- a/code/radar/radar.cpp +++ b/code/radar/radar.cpp @@ -106,7 +106,7 @@ void HudGaugeRadarStd::blitGauge(bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Radar_gauge.first_frame + 1, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + fl2i(bmw * scale), y, y + fl2i(bmh * scale)); } if (Radar_gauge.first_frame + 1 >= 0) diff --git a/code/radar/radarorb.cpp b/code/radar/radarorb.cpp index 31b97ed3ef..72af47f99e 100644 --- a/code/radar/radarorb.cpp +++ b/code/radar/radarorb.cpp @@ -478,7 +478,7 @@ void HudGaugeRadarOrb::blitGauge(bool config) std::tie(x, y, scale) = hud_config_convert_coord_sys(position[0], position[1], base_w, base_h); int bmw, bmh; bm_get_info(Radar_gauge.first_frame + 1, &bmw, &bmh); - hud_config_set_mouse_coords(gauge_config, x, x + static_cast(bmw * scale), y, y + static_cast(bmh * scale)); + hud_config_set_mouse_coords(gauge_config_id, x, x + static_cast(bmw * scale), y, y + static_cast(bmh * scale)); } if (Radar_gauge.first_frame + 1 >= 0) diff --git a/code/scripting/api/libs/hud.cpp b/code/scripting/api/libs/hud.cpp index 0e010253d7..189a78a717 100644 --- a/code/scripting/api/libs/hud.cpp +++ b/code/scripting/api/libs/hud.cpp @@ -111,7 +111,9 @@ ADE_FUNC(getHUDConfigShowStatus, l_HUD, "number|string gaugeNameOrIndex", "Gets if ((idx < 0) || (idx >= (int)default_hud_gauges.size())) return ADE_RETURN_NIL; - if (hud_config_show_flag_is_set(idx)) + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + + if (HUD_config.is_gauge_visible(gauge_map.get_string_id_from_numeric_id(idx))) return ADE_RETURN_TRUE; else return ADE_RETURN_FALSE; @@ -149,7 +151,9 @@ ADE_FUNC(setHUDGaugeColor, l_HUD, if ((idx < 0) || (idx >= NUM_HUD_GAUGES)) return ADE_RETURN_FALSE; - gr_init_alphacolor(&HUD_config.clr[idx], r, g, b, a); + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + + gr_init_alphacolor(&HUD_config.gauge_colors[gauge_map.get_string_id_from_numeric_id(idx)], r, g, b, a); return ADE_RETURN_TRUE; } @@ -169,7 +173,9 @@ ADE_FUNC(getHUDGaugeColor, if ((idx < 0) || (idx >= NUM_HUD_GAUGES)) return ADE_RETURN_NIL; - color cur = HUD_config.clr[idx]; + const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance(); + + color cur = HUD_config.gauge_colors[gauge_map.get_string_id_from_numeric_id(idx)]; if (!rc) { return ade_set_args(L, "iiii", (int)cur.red, (int)cur.green, (int)cur.blue, (int)cur.alpha); diff --git a/code/scripting/api/libs/ui.cpp b/code/scripting/api/libs/ui.cpp index 5750a6f0e0..74345f3a9e 100644 --- a/code/scripting/api/libs/ui.cpp +++ b/code/scripting/api/libs/ui.cpp @@ -2399,19 +2399,20 @@ ADE_LIB_DERIV(l_UserInterface_HUDConfig, ADE_FUNC(initHudConfig, l_UserInterface_HUDConfig, - "[number X, number Y, number Width]", + "[number X, number Y, number Width, number height]", "Initializes the HUD Configuration data. Must be used before HUD Configuration data accessed. " "X and Y are the coordinates where the HUD preview will be drawn when drawHudConfig is used. " - "Width is the pixel width to draw the gauges preview.", + "Width is the pixel width to draw the gauges preview. Height is the pixel height to draw the gauges preview.", nullptr, nullptr) { int x = 0; int y = 0; int w = 0; - ade_get_args(L, "|iii", &x, &y, &w); + int h = 0; + ade_get_args(L, "|iiii", &x, &y, &w, &h); - hud_config_init(true, x, y, w); + hud_config_init(true, x, y, w, h); return ADE_RETURN_NIL; } @@ -2450,13 +2451,29 @@ ADE_FUNC(drawHudConfig, hud_config_do_frame(0.0f, true, mx, my); - if (HC_gauge_hot >= 0) { + if (!HC_gauge_hot.empty()) { return ade_set_args(L, "o", l_Gauge_Config.Set(gauge_config_h(HC_gauge_hot))); } else { return ade_set_error(L, "o", l_Gauge_Config.Set(gauge_config_h())); } } +ADE_FUNC(getCurrentHudName, + l_UserInterface_HUDConfig, + nullptr, + "Returns the name of the current HUD configuration.", + "string", + "The name of the current HUD configuration.") +{ + SCP_UNUSED(L); + + if (SCP_vector_inbounds(HC_available_huds, HC_chosen_hud)) { + return ade_set_args(L, "s", HC_available_huds[HC_chosen_hud].second.c_str()); + } else { + return ade_set_args(L, "s", "Default Hud"); + } +} + ADE_FUNC(selectAllGauges, l_UserInterface_HUDConfig, "boolean Toggle", @@ -2472,6 +2489,33 @@ ADE_FUNC(selectAllGauges, return ADE_RETURN_NIL; } +ADE_FUNC(selectNoGauges, l_UserInterface_HUDConfig, nullptr, "Sets no gauges as selected.", nullptr, nullptr) +{ + SCP_UNUSED(L); + + hud_config_select_none(); + + return ADE_RETURN_NIL; +} + +ADE_FUNC(selectNextHud, l_UserInterface_HUDConfig, nullptr, "Selects the next available HUD", nullptr, nullptr) +{ + SCP_UNUSED(L); + + hud_config_select_hud(true); + + return ADE_RETURN_NIL; +} + +ADE_FUNC(selectPrevHud, l_UserInterface_HUDConfig, nullptr, "Selects the previous available HUD", nullptr, nullptr) +{ + SCP_UNUSED(L); + + hud_config_select_hud(false); + + return ADE_RETURN_NIL; +} + ADE_FUNC(setToDefault, l_UserInterface_HUDConfig, "string Filename", @@ -2545,15 +2589,15 @@ ADE_INDEXER(l_HUD_Gauges, return ade_set_error(L, "o", l_Gauge_Config.Set(gauge_config_h())); idx--; // Convert from Lua's 1 based index system - if ((idx < 0) || (idx >= NUM_HUD_GAUGES)) + if ((idx < 0) || (idx >= static_cast(HC_gauge_map.size()))) return ade_set_error(L, "o", l_Gauge_Config.Set(gauge_config_h())); - return ade_set_args(L, "o", l_Gauge_Config.Set(gauge_config_h(idx))); + return ade_set_args(L, "o", l_Gauge_Config.Set(gauge_config_h(HC_gauge_map[idx].first))); } ADE_FUNC(__len, l_HUD_Gauges, nullptr, "The number of gauge configs", "number", "The number of gauge configs.") { - return ade_set_args(L, "i", NUM_HUD_GAUGES); + return ade_set_args(L, "i", static_cast(HC_gauge_map.size())); } ADE_LIB_DERIV(l_HUD_Presets, "GaugePresets", nullptr, nullptr, l_UserInterface_HUDConfig); diff --git a/code/scripting/api/objs/hudconfig.cpp b/code/scripting/api/objs/hudconfig.cpp index edb9889551..d0de0aa811 100644 --- a/code/scripting/api/objs/hudconfig.cpp +++ b/code/scripting/api/objs/hudconfig.cpp @@ -9,35 +9,25 @@ namespace scripting { namespace api { -gauge_config_h::gauge_config_h() : gauge(-1) {} -gauge_config_h::gauge_config_h(int l_gauge) : gauge(l_gauge) {} +gauge_config_h::gauge_config_h(SCP_string l_gauge) : gauge(std::move(l_gauge)) {} -HC_gauge_region* gauge_config_h::getGauge() const +HudGauge* gauge_config_h::getGauge() const { if (!isValid()) { return nullptr; } - return &HC_gauge_regions[GR_1024][gauge]; + return hud_config_get_gauge_pointer(gauge); } -int gauge_config_h::getIndex() const +SCP_string gauge_config_h::getId() const { return gauge; } -const char* gauge_config_h::getName() const -{ - if (!isValid()) { - return nullptr; - } - - return HC_gauge_descriptions(gauge); -} - bool gauge_config_h::isValid() const { - return gauge >= 0 && gauge < NUM_HUD_GAUGES; + return hud_config_get_gauge_pointer(gauge) != nullptr; } hud_preset_h::hud_preset_h() : preset(-1) {} @@ -126,7 +116,7 @@ ADE_VIRTVAR(Name, l_Gauge_Config, nullptr, "The name of this gauge", "string", " LuaError(L, "This property is read only."); } - return ade_set_args(L, "s", current.getName()); + return ade_set_args(L, "s", current.getGauge()->getConfigName().c_str()); } ADE_VIRTVAR(CurrentColor, @@ -147,24 +137,24 @@ ADE_VIRTVAR(CurrentColor, } if (ADE_SETTING_VAR) { - if (!current.getGauge()->use_iff) { - HUD_config.clr[current.getIndex()] = newColor; + if (!current.getGauge()->getConfigUseIffColor()) { + HUD_config.set_gauge_color(current.getId(), newColor); } } - const color *thisColor; + color thisColor; - if (!current.getGauge()->use_iff) { - thisColor = &HUD_config.clr[current.getIndex()]; + if (!current.getGauge()->getConfigUseIffColor()) { + thisColor = HUD_config.get_gauge_color(current.getId()); } else { - if (current.getGauge()->color == 1) { - thisColor = iff_get_color(IFF_COLOR_TAGGED, 0); + if (current.getGauge()->getConfigUseTagColor()) { + thisColor = *iff_get_color(IFF_COLOR_TAGGED, 0); } else { - thisColor = &Color_bright_red; + thisColor = Color_bright_red; } } - return ade_set_args(L, "o", l_Color.Set(*thisColor)); + return ade_set_args(L, "o", l_Color.Set(thisColor)); } ADE_VIRTVAR(ShowGaugeFlag, @@ -185,14 +175,10 @@ ADE_VIRTVAR(ShowGaugeFlag, } if (ADE_SETTING_VAR) { - if (show) { - hud_config_show_flag_set(current.getIndex()); - } else { - hud_config_show_flag_clear(current.getIndex()); - } + HUD_config.set_gauge_visibility(current.getId(), show); } - return ade_set_args(L, "b", (bool)hud_config_show_flag_is_set(current.getIndex())); + return ade_set_args(L, "b", HUD_config.is_gauge_visible(current.getId())); } ADE_VIRTVAR(PopupGaugeFlag, @@ -213,18 +199,14 @@ ADE_VIRTVAR(PopupGaugeFlag, } if (ADE_SETTING_VAR) { - if (popup) { - hud_config_popup_flag_set(current.getIndex()); - } else { - hud_config_popup_flag_clear(current.getIndex()); - } + HUD_config.set_gauge_popup(current.getId(), popup); } - if (current.getGauge()->can_popup == 0) { + if (!current.getGauge()->getConfigCanPopup()) { return ADE_RETURN_FALSE; } - return ade_set_args(L, "b", (bool)hud_config_popup_flag_is_set(current.getIndex())); + return ade_set_args(L, "b", HUD_config.is_gauge_popup(current.getId())); } ADE_VIRTVAR(CanPopup, @@ -247,7 +229,7 @@ ADE_VIRTVAR(CanPopup, LuaError(L, "This property is read only."); } - if (current.getGauge()->can_popup == 0) { + if (!current.getGauge()->getConfigCanPopup()) { return ADE_RETURN_FALSE; } @@ -274,7 +256,7 @@ ADE_VIRTVAR(UsesIffForColor, LuaError(L, "This property is read only."); } - if (current.getGauge()->use_iff == 0) { + if (!current.getGauge()->getConfigUseIffColor()) { return ADE_RETURN_FALSE; } @@ -294,7 +276,7 @@ ADE_FUNC(setSelected, l_Gauge_Config, "boolean", "Sets if the gauge is the curre } if (select) { - HC_gauge_selected = current.getIndex(); + HC_gauge_selected = current.getId(); } return ADE_RETURN_NIL; diff --git a/code/scripting/api/objs/hudconfig.h b/code/scripting/api/objs/hudconfig.h index 8cf3c432a4..25c397c7fd 100644 --- a/code/scripting/api/objs/hudconfig.h +++ b/code/scripting/api/objs/hudconfig.h @@ -7,12 +7,11 @@ namespace scripting { namespace api { struct gauge_config_h { - int gauge; - gauge_config_h(); - explicit gauge_config_h(int l_gauge); - HC_gauge_region* getGauge() const; - int getIndex() const; - const char* getName() const; + SCP_string gauge; + gauge_config_h() = default; + explicit gauge_config_h(SCP_string l_gauge); + HudGauge* getGauge() const; + SCP_string getId() const; bool isValid() const; };