mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 08:15:59 -10:00
Support Custom Gauges in HUD Config UI (#6670)
* Support coloring custom gauges * remove NULL
This commit is contained in:
1 parent
42dd1eb3c2
commit
f1f95717d1
10 files changed
+450
-173
No files matched your search
+13
-17
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
@@ -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"));
|
||||
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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(¤t))) {
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user