Support Custom Gauges in HUD Config UI (#6670)

* Support coloring custom gauges

* remove NULL
This commit is contained in:
Mike Nelson authored and GitHub committed 2025-05-14 13:18:03 -04:00
1 parent 42dd1eb3c2
commit f1f95717d1
10 files changed
+450 -173

No files matched your search

+13 -17
View File
@@ -385,11 +385,18 @@ render_for_cockpit_toggle(0), custom_gauge(true), textoffset_x(txtoffset_x), tex
const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance();
gauge_config_id = ""; // gauge_map.get_string_id_from_numeric_id(_gauge_config);
gauge_config_id = create_custom_gauge_id(_custom_name);
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));
//Set the gauge type for color backup lookup
HUD_config.set_gauge_type(gauge_config_id, gauge_type);
// Custom gauges are always default visible and popup false for now
HUD_config.set_gauge_visibility(gauge_config_id, true);
HUD_config.set_gauge_popup(gauge_config_id, false);
popup_timer = timestamp(1);
texture_target_fname[0] = '\0';
@@ -583,15 +590,9 @@ void HudGauge::setGaugeColor(int bright_index, bool config)
if (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);
}
use_color = HUD_config.get_gauge_color(gauge_config_id);
if (!custom_gauge && HUD_config.is_gauge_visible(gauge_config_id)) {
if (HUD_config.is_gauge_visible(gauge_config_id)) {
if (use_iff_color) {
// Ditto for target tagging color
if (use_tag_color) {
@@ -610,11 +611,6 @@ void HudGauge::setGaugeColor(int bright_index, bool config)
}
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);
@@ -881,10 +877,10 @@ void HudGauge::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);
// The following code will be used to allow custom coloring of custom HUD gauges. This will be implemented in the future.
/*int bmw, bmh;
// Commenting out this code below will disable custom gauges from being selectable and individually colorable
int bmw, bmh;
bm_get_info(custom_frame.first_frame, &bmw, &bmh);
hud_config_set_mouse_coords(gauge_config_id, x, x + static_cast<int>(bmw * scale), y, y + static_cast<int>(bmh * scale));*/
hud_config_set_mouse_coords(gauge_config_id, x, x + static_cast<int>(bmw * scale), y, y + static_cast<int>(bmh * scale));
}
setGaugeColor(HUD_C_NONE, config);
+78 -41
View File
@@ -937,31 +937,37 @@ void hud_config_record_color(int in_color)
HUD_color_blue = HC_colors[in_color].b;
}
// Set the HUD color
// Set the HUD color to one of the color presets
void hud_config_set_color(int in_color)
{
hud_config_record_color(in_color);
HUD_init_hud_color_array();
// apply the color to all gauges
for(int idx=0; idx<NUM_HUD_GAUGES; idx++){
color clr;
gr_init_alphacolor(&clr, HC_colors[in_color].r, HC_colors[in_color].g, HC_colors[in_color].b, (HUD_color_alpha+1)*16);
SCP_string gauge = gauge_map.get_string_id_from_numeric_id(idx);
HUD_config.set_gauge_color(gauge, clr);
}
color clr;
gr_init_alphacolor(&clr, HC_colors[in_color].r, HC_colors[in_color].g, HC_colors[in_color].b, (HUD_color_alpha+1)*16);
// apply the color to all built-in gauges gauges
for(const auto& gauge_pair : HC_gauge_map){
const SCP_string& gauge_id = gauge_pair.first;
if (!gauge_id.empty()) {
HUD_config.set_gauge_color(gauge_id, clr);
}
}
}
// Set the HUD color when ALL GAUGES is selected in the HUD Config UI
void hud_config_stuff_colors(int r, int g, int b)
{
color clr;
gr_init_alphacolor(&clr, r, g, b, 255);
// apply the color to all gauges
for(int idx=0; idx<NUM_HUD_GAUGES; idx++){
SCP_string gauge = gauge_map.get_string_id_from_numeric_id(idx);
HUD_config.set_gauge_color(gauge, clr);
for (const auto& gauge_pair : HC_gauge_map) {
const SCP_string& gauge_id = gauge_pair.first;
if (!gauge_id.empty()) {
HUD_config.set_gauge_color(gauge_id, clr);
}
}
}
@@ -1338,7 +1344,10 @@ 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.empty()) {
const auto gauge = hud_config_get_gauge_pointer(HC_gauge_selected);
// Custom gauges cannot currently be set to popup or toggle visibility
if (HC_gauge_selected.empty() || gauge->isCustom()) {
hud_config_button_disable(HCB_ON);
hud_config_button_disable(HCB_OFF);
hud_config_button_disable(HCB_POPUP);
@@ -1349,8 +1358,6 @@ 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 (gauge != nullptr && gauge->getConfigCanPopup()) {
hud_config_button_enable(HCB_POPUP);
@@ -1553,8 +1560,6 @@ void hud_config_close(bool API_Access)
// hud_set_default_hud_config() will set the hud configuration to default values
void hud_set_default_hud_config(player * /*p*/, const SCP_string& filename)
{
int idx;
HUD_color_alpha = HUD_COLOR_ALPHA_DEFAULT;
HUD_config.main_color = HC_default_color;
HUD_color_red = HC_colors[HUD_config.main_color].r;
@@ -1564,20 +1569,31 @@ void hud_set_default_hud_config(player * /*p*/, const SCP_string& filename)
color clr;
gr_init_alphacolor(&clr, HUD_color_red, HUD_color_green, HUD_color_blue, (HUD_color_alpha + 1) * 16);
for(idx=0; idx<NUM_HUD_GAUGES; idx++){
SCP_string gauge = gauge_map.get_string_id_from_numeric_id(idx);
HUD_config.set_gauge_color(gauge, clr);
for (const auto& gauge_pair : HC_gauge_map) {
const SCP_string& gauge_id = gauge_pair.first;
if (!gauge_id.empty()) {
HUD_config.set_gauge_color(gauge_id, clr);
}
}
HUD_config.show_flags_map.clear();
HUD_config.popup_flags_map.clear();
// Built-in have specific settings
for (const auto& gauge_id : default_visible_gauges) {
HUD_config.show_flags_map[gauge_id] = true;
}
// Custom gauges are always visible by default
for (const auto& gauge_pair : HC_gauge_map) {
if (gauge_pair.second->isCustom()) {
const SCP_string& gauge_id = gauge_pair.first;
HUD_config.show_flags_map[gauge_id] = true;
}
}
HUD_config.rp_dist = RR_INFINITY;
HUD_config.is_observer = 0;
HUD_config.is_observer = false;
// load up the default colors
hud_config_color_load(filename.c_str());
@@ -1801,15 +1817,15 @@ void hud_config_recalc_alpha_slider()
void hud_config_red_slider()
{
int idx;
int pos = HCS_CONV(HC_color_sliders[HCS_RED].get_currentItem()) ;
// select all ?
if(HC_select_all){
for(idx=0; idx<NUM_HUD_GAUGES; idx++){
SCP_string gauge = gauge_map.get_string_id_from_numeric_id(idx);
gr_init_alphacolor(&HUD_config.gauge_colors[gauge], pos, HUD_config.gauge_colors[gauge].green, HUD_config.gauge_colors[gauge].blue, HUD_config.gauge_colors[gauge].alpha);
}
for(const auto& gauge_pair : HC_gauge_map){
const SCP_string& gauge_id = gauge_pair.first;
if (!gauge_id.empty()) {
gr_init_alphacolor(&HUD_config.gauge_colors[gauge_id], pos, HUD_config.gauge_colors[gauge_id].green, HUD_config.gauge_colors[gauge_id].blue, HUD_config.gauge_colors[gauge_id].alpha);
}
}
}
// individual gauge
else {
@@ -1817,7 +1833,6 @@ void hud_config_red_slider()
return;
}
// get slider position
gr_init_alphacolor(&HUD_config.gauge_colors[HC_gauge_selected], pos, HUD_config.gauge_colors[HC_gauge_selected].green, HUD_config.gauge_colors[HC_gauge_selected].blue, HUD_config.gauge_colors[HC_gauge_selected].alpha);
}
@@ -1826,15 +1841,15 @@ void hud_config_red_slider()
void hud_config_green_slider()
{
int idx;
int pos = HCS_CONV(HC_color_sliders[HCS_GREEN].get_currentItem()) ;
// select all ?
if(HC_select_all){
for(idx=0; idx<NUM_HUD_GAUGES; idx++){
SCP_string gauge = gauge_map.get_string_id_from_numeric_id(idx);
gr_init_alphacolor(&HUD_config.gauge_colors[gauge], HUD_config.gauge_colors[gauge].red, pos, HUD_config.gauge_colors[gauge].blue, HUD_config.gauge_colors[gauge].alpha);
}
for(const auto& gauge_pair : HC_gauge_map){
const SCP_string& gauge_id = gauge_pair.first;
if (!gauge_id.empty()) {
gr_init_alphacolor(&HUD_config.gauge_colors[gauge_id], pos, HUD_config.gauge_colors[gauge_id].green, HUD_config.gauge_colors[gauge_id].blue, HUD_config.gauge_colors[gauge_id].alpha);
}
}
}
// individual gauge
else {
@@ -1842,7 +1857,6 @@ void hud_config_green_slider()
return;
}
// get slider position
gr_init_alphacolor(&HUD_config.gauge_colors[HC_gauge_selected], HUD_config.gauge_colors[HC_gauge_selected].red, pos, HUD_config.gauge_colors[HC_gauge_selected].blue, HUD_config.gauge_colors[HC_gauge_selected].alpha);
}
@@ -1851,15 +1865,15 @@ void hud_config_green_slider()
void hud_config_blue_slider()
{
int idx;
int pos = HCS_CONV(HC_color_sliders[HCS_BLUE].get_currentItem());
// select all ?
if(HC_select_all){
for(idx=0; idx<NUM_HUD_GAUGES; idx++){
SCP_string gauge = gauge_map.get_string_id_from_numeric_id(idx);
gr_init_alphacolor(&HUD_config.gauge_colors[gauge], HUD_config.gauge_colors[gauge].red, HUD_config.gauge_colors[gauge].green, pos, HUD_config.gauge_colors[gauge].alpha);
}
for(const auto& gauge_pair : HC_gauge_map){
const SCP_string& gauge_id = gauge_pair.first;
if (!gauge_id.empty()) {
gr_init_alphacolor(&HUD_config.gauge_colors[gauge_id], pos, HUD_config.gauge_colors[gauge_id].green, HUD_config.gauge_colors[gauge_id].blue, HUD_config.gauge_colors[gauge_id].alpha);
}
}
}
// individual gauge
else {
@@ -1867,7 +1881,6 @@ void hud_config_blue_slider()
return;
}
// get slider position
gr_init_alphacolor(&HUD_config.gauge_colors[HC_gauge_selected], HUD_config.gauge_colors[HC_gauge_selected].red, HUD_config.gauge_colors[HC_gauge_selected].green, pos, HUD_config.gauge_colors[HC_gauge_selected].alpha);
}
@@ -1991,3 +2004,27 @@ void hud_config_select_all_toggle(bool toggle, bool API_Access)
HC_select_all = true;
}
}
SCP_string create_custom_gauge_id(const SCP_string& gauge_name) {
Assertion(!gauge_name.empty(), "Custom gauge has no name!");
SCP_string id;
if (Mod_title.empty()) {
id = Cmdline_mod;
// Basic cleanup attempt
id = id.substr(0, id.find_first_of(DIR_SEPARATOR_CHAR));
} else {
id = Mod_title;
}
if (!id.empty()) {
std::replace(id.begin(), id.end(), ' ', '_');
} else {
id = "Custom";
}
id += "::" + gauge_name;
return id;
}
+142 -113
View File
@@ -35,6 +35,107 @@ struct ai_info;
extern float Radar_ranges[RR_MAX_RANGES];
extern const char *Radar_range_text(int range_num);
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<int, std::pair<std::pair<SCP_string, int>, SCP_string>> gauge_map;
};
/*!
* @brief Vector for storing the filenames of hud preset files
* @note main definition in hudconfig.cpp
@@ -51,14 +152,15 @@ extern int HC_resize_mode;
* @note Is not default init'd. Assumes new player, PLR, or CSG reads will correctly set data.
*/
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
int rp_dist; // one of RR_ #defines above; Is the maxium radar view distance setting
bool 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
// Maps for HUD gauge configuration
std::unordered_map<std::string, color> gauge_colors; //!< Gauge-specific colors
std::unordered_map<std::string, bool> show_flags_map; //!< Show/hide state for gauges
std::unordered_map<std::string, bool> popup_flags_map; //!< Popup state for gauges
SCP_unordered_map<SCP_string, color> gauge_colors; // Gauge-specific colors
SCP_unordered_map<SCP_string, bool> show_flags_map; // Show/hide state for gauges
SCP_unordered_map<SCP_string, bool> popup_flags_map; // Popup state for gauges
SCP_unordered_map<SCP_string, int> gauge_types; // Gauge types used for backup colors for custom gauges to preseve old behavior
static color default_white_color()
{
@@ -69,37 +171,58 @@ typedef struct HUD_CONFIG_TYPE {
// 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)
void set_gauge_color(const SCP_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
// Get the gauge color, the color based on it's type, or white if the gauge is not found
color get_gauge_color(const SCP_string& gauge_id) const
{
auto it = gauge_colors.find(gauge_id);
return (it != gauge_colors.end()) ? it->second : default_white_color();
// Got a match? Return it
if (it != gauge_colors.end()) {
return it->second;
}
// No match.. try using the gauge type
auto type_it = gauge_types.find(gauge_id);
if (type_it != gauge_types.end()) {
const HC_gauge_mappings& gauge_map = HC_gauge_mappings::get_instance();
it = gauge_colors.find(gauge_map.get_string_id_from_numeric_id(type_it->second));
return it->second;
}
// Still nothing.. return white
return default_white_color();
}
void set_gauge_visibility(const std::string& gauge_id, bool visible)
void set_gauge_type(const SCP_string& gauge_id, int type) {
gauge_types[gauge_id] = type;
}
void set_gauge_visibility(const SCP_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
bool is_gauge_visible(const SCP_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)
void set_gauge_popup(const SCP_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
bool is_gauge_popup(const SCP_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
@@ -196,105 +319,6 @@ extern SCP_map<SCP_string, std::array<SCP_string, num_shield_gauge_types>> HC_hu
extern SCP_map<SCP_string, SCP_vector<SCP_string>> HC_hud_primary_weapons;
extern SCP_map<SCP_string, SCP_vector<SCP_string>> HC_hud_secondary_weapons;
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<int, std::pair<std::pair<SCP_string, int>, SCP_string>> gauge_map;
};
/*!
* @brief get the gauge pointer for the given gauge index
@@ -444,5 +468,10 @@ std::pair<float, float> hud_config_calc_coords_from_angle(float angle_degrees, i
*/
float hud_config_find_valid_angle(const SCP_string& gauge, float initial_angle, int centerX, int centerY, float radius);
/*!
* @brief generage a custom gauge id
*/
SCP_string create_custom_gauge_id(const SCP_string& gauge_name);
#endif
+1 -1
View File
@@ -43,7 +43,7 @@ void hud_observer_init(ship *shipp, ai_info *aip)
Hud_obs_ship.ship_max_shield_strength = shipp->ship_max_shield_strength;
Hud_obs_ship.weapons = shipp->weapons;
HUD_config.is_observer = 1;
HUD_config.is_observer = true;
HUD_config.show_flags_map.clear();
HUD_config.popup_flags_map.clear();
+7
View File
@@ -15,6 +15,7 @@
#include "options/OptionsManager.h"
#include "parse/sexp_container.h"
#include "pilotfile/pilotfile.h"
#include "pilotfile/plr_hudprefs.h"
#include "playerman/player.h"
#include "ship/ship.h"
#include "sound/audiostr.h"
@@ -1824,6 +1825,9 @@ bool pilotfile::load_savefile(player *_p, const char *campaign)
}
}
mprintf(("HUDPREFS => Loading extended player HUD preferences...\n"));
hud_config_load_player_prefs(p->callsign);
// Probably don't need to persist these to disk but it'll make sure on next boot we start with these campaign options set
// The github tests don't know what to do with the ini file so I guess we'll skip this for now
//options::OptionsManager::instance()->persistChanges();
@@ -1923,6 +1927,9 @@ bool pilotfile::save_savefile()
mprintf(("CSG => Saving: Containers...\n"));
csg_write_containers();
mprintf(("HUDPREFS => Saving player HUD preferences (testing)...\n"));
hud_config_save_player_prefs(p->callsign);
// Done!
mprintf(("CSG => Saving complete!\n"));
+12 -1
View File
@@ -16,6 +16,7 @@
#include "pilotfile/pilotfile.h"
#include "pilotfile/BinaryFileHandler.h"
#include "pilotfile/JSONFileHandler.h"
#include "pilotfile/plr_hudprefs.h"
#include "playerman/managepilot.h"
#include "playerman/player.h"
#include "scripting/hook_api.h"
@@ -242,7 +243,11 @@ void pilotfile::plr_read_hud()
ReleaseWarning(LOCATION, "Player file has too many hud config errors, and is likely corrupted. Please verify and save your settings in the hud config menu.");
}
hud_config_set_color(HUD_config.main_color);
// This seemed to be previously used to ensure a valid color was set
// but under the new method we can rely on the getter to return a valid color
// in all cases. So comment this out to prevent forcing a default color on
// custom gauges that rely on color by their gauge type
//hud_config_set_color(HUD_config.main_color);
// gauge-specific colors
auto num_gauges = handler->startArrayRead("hud_gauges");
@@ -1215,6 +1220,9 @@ bool pilotfile::load_player(const char* callsign, player* _p, bool force_binary)
}
handler->endSectionRead();
mprintf(("HUDPREFS => Loading extended player HUD preferences...\n"));
hud_config_load_player_prefs(callsign);
// Probably don't need to persist these to disk but it'll make sure on next boot we start with these player options set
// The github tests don't know what to do with the ini file so I guess we'll skip this for now
//options::OptionsManager::instance()->persistChanges();
@@ -1331,6 +1339,9 @@ bool pilotfile::save_player(player *_p)
handler->flush();
mprintf(("HUDPREFS => Saving player HUD preferences (testing)...\n"));
hud_config_save_player_prefs(p->callsign);
// Done!
mprintf(("PLR => Saving complete!\n"));
+156
View File
@@ -0,0 +1,156 @@
#include "plr_hudprefs.h"
#include "globalincs/pstypes.h"
#include "cfile/cfile.h"
#include "hud/hudconfig.h"
#include <parse/parselo.h>
// Saves the player's current HUD preferences (visibility, popup, color for all gauges)
// to a specific file (<callsign>.hdp) in the player directory.
void hud_config_save_player_prefs(const char* callsign)
{
if (callsign == nullptr || *callsign == '\0') {
mprintf(("HUDPREFS: Cannot save preferences - invalid callsign provided.\n"));
return;
}
SCP_string filename = callsign;
filename += ".hdp";
CFILE* file = cfopen(filename.c_str(), "wt", CFILE_NORMAL, CF_TYPE_DATA);
if (file == nullptr) {
mprintf(("HUDPREFS: Unable to open file '%s' for writing player HUD preferences.\n", filename.c_str()));
return;
}
mprintf(("HUDPREFS: Saving player HUD preferences to '%s'...\n", filename.c_str()));
char format_buffer[256];
cfputs("+Version: 1\n\n", file);
// Iterate ALL gauges
for (const auto& pair : HUD_config.gauge_colors) {
const SCP_string& gauge_id = pair.first;
if (gauge_id.empty()) {
continue;
}
// Get current state
bool is_visible = HUD_config.is_gauge_visible(gauge_id);
bool is_popup = HUD_config.is_gauge_popup(gauge_id);
color clr = pair.second;
// +Gauge: <id>
sprintf(format_buffer, "+Gauge: %s\n", gauge_id.c_str());
cfputs(format_buffer, file);
// +Visible: <0_or_1>
sprintf(format_buffer, "+Visible: %d\n", is_visible ? 1 : 0);
cfputs(format_buffer, file);
// +Popup: <0_or_1>
sprintf(format_buffer, "+Popup: %d\n", is_popup ? 1 : 0);
cfputs(format_buffer, file);
// +Color: <r> <g> <b> <a>
sprintf(format_buffer, "+Color: %d %d %d %d\n\n", clr.red, clr.green, clr.blue, clr.alpha);
cfputs(format_buffer, file);
}
cfclose(file);
mprintf(("HUDPREFS: Finished saving player HUD preferences.\n"));
}
// Loads the player's HUD preferences (visibility, popup, color for all gauges)
// from the specific file (<callsign>.hdp) in the player directory, if it exists.
void hud_config_load_player_prefs(const char* callsign)
{
if (callsign == nullptr || *callsign == '\0') {
mprintf(("HUDPREFS: Cannot load preferences - invalid callsign provided.\n"));
return;
}
// Construct the filename: <callsign>.hdp
SCP_string filename = callsign;
filename += ".hdp";
// Check if the file exists in the player directories
int file_location = cf_exists(filename.c_str(), CF_TYPE_DATA);
if (file_location == -1) {
// File doesn't exist, which is fine - means no custom prefs saved yet.
mprintf(("HUDPREFS: No player HUD preferences file found ('%s'). Using defaults/player file settings.\n", filename.c_str()));
return;
}
mprintf(("HUDPREFS: Loading player HUD preferences from '%s'...\n", filename.c_str()));
try {
read_file_text(filename.c_str());
reset_parse();
if (optional_string("+Version:")) {
int version = 1;
stuff_int(&version);
// Can add version checks here later if format changes
if (version != 1) {
mprintf(("HUDPREFS: Warning - Unknown version %d in '%s'. Trying to parse anyway.\n",
version,
filename.c_str()));
}
}
// Loop through all gauge blocks in the file
while (optional_string("+Gauge:")) {
SCP_string gauge_id;
int visible_int = 0;
int popup_int = 0;
ubyte r = 0, g = 0, b = 0, a = 255; // Default alpha to opaque
// Parse gauge ID
stuff_string(gauge_id, F_NAME);
// Parse visibility
required_string("+Visible:");
stuff_int(&visible_int);
bool is_visible = (visible_int != 0);
// Parse popup
required_string("+Popup:");
stuff_int(&popup_int);
bool is_popup = (popup_int != 0);
// Parse color
required_string("+Color:");
stuff_ubyte(&r);
stuff_ubyte(&g);
stuff_ubyte(&b);
stuff_ubyte(&a);
// Validate gauge ID before applying settings
if (!gauge_id.empty()) {
color clr;
gr_init_alphacolor(&clr, r, g, b, a);
HUD_config.set_gauge_visibility(gauge_id, is_visible);
HUD_config.set_gauge_popup(gauge_id, is_popup);
HUD_config.set_gauge_color(gauge_id, clr);
} else {
mprintf(("HUDPREFS: Warning - Encountered empty gauge ID while parsing '%s'. Skipping entry.\n",filename.c_str()));
}
}
mprintf(("HUDPREFS: Finished loading player HUD preferences.\n"));
} catch (const parse::ParseException& e) {
mprintf(("HUDPREFS: Error parsing player HUD preferences file '%s'! Error: %s\n", filename.c_str(), e.what()));
} catch (...) {
mprintf(("HUDPREFS: Unknown error parsing player HUD preferences file '%s'!\n", filename.c_str()));
}
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef _PLAYER_HUDPREFS_H
#define _PLAYER_HUDPREFS_H
// Saves the player's current HUD preferences (vis/popup/color for all gauges)
// to <callsign>.hdp
void hud_config_save_player_prefs(const char* callsign);
// Loads the player's current HUD preferences (vis/popup/color for all gauges)
// from <callsign>.hdp
void hud_config_load_player_prefs(const char* callsign);
#endif // _PLAYER_HUDPREFS_H
+27
View File
@@ -361,6 +361,33 @@ ADE_VIRTVAR(UsesIffForColor,
return ADE_RETURN_TRUE;
}
ADE_VIRTVAR(isCustomGauge,
l_Gauge_Config,
nullptr,
"Gets whether or not the gauge is a custom gauge.",
"boolean",
"True if custom, false otherwise")
{
gauge_config_h current;
if (!ade_get_args(L, "o", l_Gauge_Config.Get(&current))) {
return ADE_RETURN_NIL;
}
if (!current.isValid()) {
return ade_set_error(L, "b", false);
}
if (ADE_SETTING_VAR) {
LuaError(L, "This property is read only.");
}
if (!current.getGauge()->isCustom()) {
return ADE_RETURN_FALSE;
}
return ADE_RETURN_TRUE;
}
ADE_FUNC(setSelected, l_Gauge_Config, "boolean", "Sets if the gauge is the currently selected gauge for drawing as selected.", nullptr, nullptr)
{
gauge_config_h current;
+2
View File
@@ -1173,6 +1173,8 @@ add_file_folder("PilotFile"
pilotfile/pilotfile_convert.h
pilotfile/plr.cpp
pilotfile/plr_convert.cpp
pilotfile/plr_hudprefs.cpp
pilotfile/plr_hudprefs.h
)
# Playerman files