Rando: Keyring tristate (#3960)

* Initial implementation

* Fix build

* Update UIWidgets.cpp

* Update option.cpp

* Update settings.cpp

* Update settings.cpp

* Apply Pepper0ni's patch

Co-Authored-By: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com>

* Update option_descriptions.cpp

---------

Co-authored-by: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com>
This commit is contained in:
Pepe20129 2024-07-17 05:25:06 +02:00 committed by GitHub
parent 2ff795e227
commit 8eb6304999
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 141 additions and 45 deletions

View File

@ -140,6 +140,9 @@ bool Option::RenderImGui() const {
case WidgetType::Checkbox:
changed = RenderCheckbox();
break;
case WidgetType::TristateCheckbox:
changed = RenderTristateCheckbox();
break;
case WidgetType::Combobox:
changed = RenderCombobox();
break;
@ -209,6 +212,26 @@ bool Option::RenderCheckbox() const {
return changed;
}
bool Option::RenderTristateCheckbox() const {
bool changed = false;
if (disabled) {
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
int val = CVarGetInteger(cvarName.c_str(), defaultOption);
if (CustomCheckboxTristate(name.c_str(), &val, disabled, disabledGraphic)) {
CVarSetInteger(cvarName.c_str(), val);
changed = true;
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
if (!description.empty()) {
UIWidgets::InsertHelpHoverText(description.c_str());
}
if (disabled) {
UIWidgets::ReEnableComponent(disabledText.c_str());
}
return changed;
}
bool Option::RenderCombobox() const {
bool changed = false;
if (disabled) {

View File

@ -34,6 +34,7 @@ enum class OptionCategory {
*/
enum class WidgetType {
Checkbox, /** Default for Bools, not compatible if options.size() > 2. */
TristateCheckbox, /** Compatible with U8s, not compatible if options.size() != 3. */
Combobox, /** Default for U8s, works with U8s and Bools. */
Slider, /** Compatible with U8s. If constructed with NumOpts, consider using this. Technically can be used for Bool or non-NumOpts options but it would be a bit weird semantically. */
};
@ -317,6 +318,7 @@ protected:
private:
bool RenderCheckbox() const;
bool RenderTristateCheckbox() const;
bool RenderCombobox() const;
bool RenderSlider() const;
std::variant<bool, uint8_t> var;

View File

@ -370,7 +370,8 @@ void Settings::CreateOptionDescriptions() {
"\n"
"Count - A specified amount of randomly selected dungeons will have their keys replaced with keyrings.\n"
"\n"
"Selection - Hand select which dungeons will have their keys replaced with keyrings.\n"
"Selection - Hand select which dungeons will have their keys replaced with keyrings\n"
"(can also be left as random, in which case each one will have a 50% chance of being a keyring).\n"
"\n"
"Selecting key ring for dungeons will have no effect if Small Keys are set to Start With or Vanilla.\n"
"\n"

View File

@ -3876,6 +3876,12 @@ typedef enum {
RO_KEYRINGS_SELECTION,
} RandoOptionKeyrings;
typedef enum {
RO_KEYRING_FOR_DUNGEON_OFF,
RO_KEYRING_FOR_DUNGEON_RANDOM,
RO_KEYRING_FOR_DUNGEON_ON,
} RandoOptionKeyringForDungeon;
//Ganon's Boss Key Settings (vanilla, own dungeon, start with,
//overworld, anywhere, 100 GS reward)
typedef enum {

View File

@ -136,15 +136,15 @@ void Settings::CreateOptions() {
mOptions[RSK_LACS_OPTIONS] = Option::U8("LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), "", WidgetType::Combobox, RO_LACS_STANDARD_REWARD);
mOptions[RSK_KEYRINGS] = Option::U8("Key Rings", {"Off", "Random", "Count", "Selection"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), mOptionDescriptions[RSK_KEYRINGS], WidgetType::Combobox, RO_KEYRINGS_OFF);
mOptions[RSK_KEYRINGS_RANDOM_COUNT] = Option::U8("Keyring Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), "", WidgetType::Slider, 8);
mOptions[RSK_KEYRINGS_GERUDO_FORTRESS] = Option::Bool("Gerudo Fortress", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", IMFLAG_NONE);
mOptions[RSK_KEYRINGS_FOREST_TEMPLE] = Option::Bool("Forest Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple"), "", IMFLAG_NONE);
mOptions[RSK_KEYRINGS_FIRE_TEMPLE] = Option::Bool("Fire Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple"), "", IMFLAG_NONE);
mOptions[RSK_KEYRINGS_WATER_TEMPLE] = Option::Bool("Water Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple"), "", IMFLAG_NONE);
mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE] = Option::Bool("Spirit Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple"), "", IMFLAG_NONE);
mOptions[RSK_KEYRINGS_SHADOW_TEMPLE] = Option::Bool("Shadow Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple"), "", IMFLAG_NONE);
mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL] = Option::Bool("Bottom of the Well", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), "", IMFLAG_NONE);
mOptions[RSK_KEYRINGS_GTG] = Option::Bool("Gerudo Training Grounds", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), "", IMFLAG_NONE);
mOptions[RSK_KEYRINGS_GANONS_CASTLE] = Option::Bool("Ganon's Castle", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle"));
mOptions[RSK_KEYRINGS_GERUDO_FORTRESS] = Option::U8("Gerudo Fortress Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", WidgetType::TristateCheckbox, 0);
mOptions[RSK_KEYRINGS_FOREST_TEMPLE] = Option::U8("Forest Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple"), "", WidgetType::TristateCheckbox, 0);
mOptions[RSK_KEYRINGS_FIRE_TEMPLE] = Option::U8("Fire Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple"), "", WidgetType::TristateCheckbox, 0);
mOptions[RSK_KEYRINGS_WATER_TEMPLE] = Option::U8("Water Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple"), "", WidgetType::TristateCheckbox, 0);
mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE] = Option::U8("Spirit Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple"), "", WidgetType::TristateCheckbox, 0);
mOptions[RSK_KEYRINGS_SHADOW_TEMPLE] = Option::U8("Shadow Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple"), "", WidgetType::TristateCheckbox, 0);
mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL] = Option::U8("Bottom of the Well Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), "", WidgetType::TristateCheckbox, 0);
mOptions[RSK_KEYRINGS_GTG] = Option::U8("Gerudo Training Grounds Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), "", WidgetType::TristateCheckbox, 0);
mOptions[RSK_KEYRINGS_GANONS_CASTLE] = Option::U8("Ganon's Castle Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle"), "", WidgetType::TristateCheckbox, 0);
mOptions[RSK_SKIP_CHILD_STEALTH] = Option::Bool("Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildStealth"), mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
mOptions[RSK_SKIP_CHILD_ZELDA] = Option::Bool("Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildZelda"), mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
mOptions[RSK_SKIP_EPONA_RACE] = Option::Bool("Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipEponaRace"), mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
@ -1145,15 +1145,15 @@ void Settings::CreateOptions() {
{ "Shuffle Dungeon Items:LACS Reward Options", RSK_LACS_OPTIONS },
{ "Shuffle Dungeon Items:Key Rings", RSK_KEYRINGS },
{ "Shuffle Dungeon Items:Keyring Dungeon Count", RSK_KEYRINGS_RANDOM_COUNT },
{ "Shuffle Dungeon Items:Gerudo Fortress", RSK_KEYRINGS_GERUDO_FORTRESS },
{ "Shuffle Dungeon Items:Forest Temple", RSK_KEYRINGS_FOREST_TEMPLE },
{ "Shuffle Dungeon Items:Fire Temple", RSK_KEYRINGS_FIRE_TEMPLE },
{ "Shuffle Dungeon Items:Water Temple", RSK_KEYRINGS_WATER_TEMPLE },
{ "Shuffle Dungeon Items:Spirit Temple", RSK_KEYRINGS_SPIRIT_TEMPLE },
{ "Shuffle Dungeon Items:Shadow Temple", RSK_KEYRINGS_SHADOW_TEMPLE },
{ "Shuffle Dungeon Items:Bottom of the Well", RSK_KEYRINGS_BOTTOM_OF_THE_WELL },
{ "Shuffle Dungeon Items:GTG", RSK_KEYRINGS_GTG },
{ "Shuffle Dungeon Items:Ganon's Castle", RSK_KEYRINGS_GANONS_CASTLE },
{ "Shuffle Dungeon Items:Gerudo Fortress Keyring", RSK_KEYRINGS_GERUDO_FORTRESS },
{ "Shuffle Dungeon Items:Forest Temple Keyring", RSK_KEYRINGS_FOREST_TEMPLE },
{ "Shuffle Dungeon Items:Fire Temple Keyring", RSK_KEYRINGS_FIRE_TEMPLE },
{ "Shuffle Dungeon Items:Water Temple Keyring", RSK_KEYRINGS_WATER_TEMPLE },
{ "Shuffle Dungeon Items:Spirit Temple Keyring", RSK_KEYRINGS_SPIRIT_TEMPLE },
{ "Shuffle Dungeon Items:Shadow Temple Keyring", RSK_KEYRINGS_SHADOW_TEMPLE },
{ "Shuffle Dungeon Items:Bottom of the Well Keyring", RSK_KEYRINGS_BOTTOM_OF_THE_WELL },
{ "Shuffle Dungeon Items:GTG Keyring", RSK_KEYRINGS_GTG },
{ "Shuffle Dungeon Items:Ganon's Castle Keyring", RSK_KEYRINGS_GANONS_CASTLE },
{ "World Settings:Starting Age", RSK_STARTING_AGE },
// TODO: Ammo Drop settings
{ "World Settings:Bombchu Drops", RSK_ENABLE_BOMBCHU_DROPS },
@ -1952,39 +1952,44 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio
if (mOptions[RSK_KEYRINGS]) {
// Random Key Rings
auto keyrings = keyRingOptions;
if (mOptions[RSK_GERUDO_FORTRESS].Is(RO_GF_NORMAL) && mOptions[RSK_GERUDO_KEYS].IsNot(RO_GERUDO_KEYS_VANILLA)) {
keyrings.push_back(&mOptions[RSK_KEYRINGS_GERUDO_FORTRESS]);
} else {
mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_OFF);
}
if (mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_RANDOM) || mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_COUNT)) {
auto keyrings = keyRingOptions;
if (mOptions[RSK_GERUDO_FORTRESS].Is(RO_GF_NORMAL) && mOptions[RSK_GERUDO_KEYS].IsNot(RO_GERUDO_KEYS_VANILLA)) {
keyrings.push_back(&mOptions[RSK_KEYRINGS_GERUDO_FORTRESS]);
}
const uint32_t keyRingCount = mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_COUNT) ? mOptions[RSK_KEYRINGS_RANDOM_COUNT].Value<uint8_t>() : Random(0, static_cast<int>(keyrings.size()));
Shuffle(keyrings);
for (size_t i = 0; i < keyRingCount; i++) {
keyrings[i]->SetSelectedIndex(RO_GENERIC_ON);
keyrings[i]->SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_ON);
}
for (size_t i = keyRingCount; i < keyrings.size(); i++) {
keyrings[i]->SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_OFF);
}
}
if (mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL]) {
if (mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
ctx->GetDungeon(BOTTOM_OF_THE_WELL)->SetKeyRing();
}
if (mOptions[RSK_KEYRINGS_FOREST_TEMPLE]) {
if (mOptions[RSK_KEYRINGS_FOREST_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_FOREST_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
ctx->GetDungeon(FOREST_TEMPLE)->SetKeyRing();
}
if (mOptions[RSK_KEYRINGS_FIRE_TEMPLE]) {
if (mOptions[RSK_KEYRINGS_FIRE_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_FIRE_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
ctx->GetDungeon(FIRE_TEMPLE)->SetKeyRing();
}
if (mOptions[RSK_KEYRINGS_WATER_TEMPLE]) {
if (mOptions[RSK_KEYRINGS_WATER_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_WATER_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
ctx->GetDungeon(WATER_TEMPLE)->SetKeyRing();
}
if (mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE]) {
if (mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
ctx->GetDungeon(SPIRIT_TEMPLE)->SetKeyRing();
}
if (mOptions[RSK_KEYRINGS_SHADOW_TEMPLE]) {
if (mOptions[RSK_KEYRINGS_SHADOW_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_SHADOW_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
ctx->GetDungeon(SHADOW_TEMPLE)->SetKeyRing();
}
if (mOptions[RSK_KEYRINGS_GTG]) {
if (mOptions[RSK_KEYRINGS_GTG].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_GTG].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
ctx->GetDungeon(GERUDO_TRAINING_GROUNDS)->SetKeyRing();
}
if (mOptions[RSK_KEYRINGS_GANONS_CASTLE]) {
if (mOptions[RSK_KEYRINGS_GANONS_CASTLE].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_GANONS_CASTLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
ctx->GetDungeon(GANONS_CASTLE)->SetKeyRing();
}
}
@ -2322,15 +2327,6 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) {
case RSK_HBA_HINT:
case RSK_WARP_SONG_HINTS:
case RSK_SCRUB_TEXT_HINT:
case RSK_KEYRINGS_GERUDO_FORTRESS:
case RSK_KEYRINGS_FOREST_TEMPLE:
case RSK_KEYRINGS_FIRE_TEMPLE:
case RSK_KEYRINGS_WATER_TEMPLE:
case RSK_KEYRINGS_SHADOW_TEMPLE:
case RSK_KEYRINGS_SPIRIT_TEMPLE:
case RSK_KEYRINGS_BOTTOM_OF_THE_WELL:
case RSK_KEYRINGS_GTG:
case RSK_KEYRINGS_GANONS_CASTLE:
case RSK_SHUFFLE_ENTRANCES:
case RSK_SHUFFLE_OVERWORLD_ENTRANCES:
case RSK_SHUFFLE_GROTTO_ENTRANCES:
@ -2365,6 +2361,23 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) {
mOptions[index].SetSelectedIndex(RO_KEYRINGS_SELECTION);
}
break;
case RSK_KEYRINGS_GERUDO_FORTRESS:
case RSK_KEYRINGS_FOREST_TEMPLE:
case RSK_KEYRINGS_FIRE_TEMPLE:
case RSK_KEYRINGS_WATER_TEMPLE:
case RSK_KEYRINGS_SHADOW_TEMPLE:
case RSK_KEYRINGS_SPIRIT_TEMPLE:
case RSK_KEYRINGS_BOTTOM_OF_THE_WELL:
case RSK_KEYRINGS_GTG:
case RSK_KEYRINGS_GANONS_CASTLE:
if (it.value() == "No") {
mOptions[index].SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_OFF);
} else if (it.value() == "Random") {
mOptions[index].SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_RANDOM);
} else if (it.value() == "Yes") {
mOptions[index].SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_ON);
}
break;
case RSK_SHUFFLE_MERCHANTS:
if (it.value() == "Off") {
mOptions[index].SetSelectedIndex(RO_SHUFFLE_MERCHANTS_OFF);

View File

@ -127,7 +127,7 @@ namespace UIWidgets {
draw_list->PathStroke(col, 0, thickness);
}
bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic) {
bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic, bool renderCrossWhenOff) {
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems) {
return false;
@ -168,9 +168,9 @@ namespace UIWidgets {
} else if ((!disabled && *v) || (disabled && disabledGraphic == CheckboxGraphics::Checkmark)) {
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
ImGui::RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f);
} else if (disabled && disabledGraphic == CheckboxGraphics::Cross) {
} else if ((!disabled && !*v && renderCrossWhenOff) || (disabled && disabledGraphic == CheckboxGraphics::Cross)) {
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
RenderCross(window->DrawList, check_bb.Min + ImVec2(pad, pad), cross_col, square_sz - pad * 2.0f);
RenderCross(window->DrawList, check_bb.Min + ImVec2(pad, pad), disabled ? cross_col : check_col, square_sz - pad * 2.0f);
}
ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
@ -185,6 +185,36 @@ namespace UIWidgets {
return pressed;
}
bool CustomCheckboxTristate(const char* label, int* v, bool disabled, CheckboxGraphics disabledGraphic) {
bool ret;
if (*v == 0) {
bool b = false;
ret = CustomCheckbox(label, &b, disabled, disabledGraphic, true);
if (ret) {
*v = 1;
}
} else if (*v == 1) {
ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, true);
bool b = true;
ret = CustomCheckbox(label, &b, disabled, disabledGraphic, true);
if (ret) {
*v = 2;
}
ImGui::PopItemFlag();
} else if (*v == 2) {
bool b = true;
ret = CustomCheckbox(label, &b, disabled, disabledGraphic, true);
if (ret) {
*v = 0;
}
} else {
SPDLOG_INFO("Invalid CheckBoxTristate value: {}", *v);
*v = 0;
return false;
}
return ret;
}
void ReEnableComponent(const char* disabledTooltipText) {
// End of disable region of previous component
ImGui::PopStyleVar(1);
@ -218,6 +248,25 @@ namespace UIWidgets {
return changed;
}
bool EnhancementCheckboxTristate(const char* text, const char* cvarName, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic, bool defaultValue) {
bool changed = false;
if (disabled) {
DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
}
int val = CVarGetInteger(cvarName, defaultValue);
if (CustomCheckboxTristate(text, &val, disabled, disabledGraphic)) {
CVarSetInteger(cvarName, val);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
changed = true;
}
if (disabled) {
ReEnableComponent(disabledTooltipText);
}
return changed;
}
bool PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic, bool defaultValue) {
ImGui::BeginGroup();
if (padTop) Spacer(0);

View File

@ -68,12 +68,14 @@ namespace UIWidgets {
void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalTopPadding = 0.0f, float extraVerticalBottomPadding = 0.0f);
void RenderCross(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz);
bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic);
bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic, bool renderCrossWhenOff = false);
bool CustomCheckboxTristate(const char* label, int* v, bool disabled, CheckboxGraphics disabledGraphic);
void ReEnableComponent(const char* disabledTooltipText);
void DisableComponent(const float alpha);
bool EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross, bool defaultValue = false);
bool EnhancementCheckboxTristate(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross, bool defaultValue = false);
bool PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross, bool defaultValue = false);
bool EnhancementCombobox(const char* cvarName, std::span<const char*, std::dynamic_extent> comboArray, uint8_t defaultIndex, bool disabled = false, const char* disabledTooltipText = "", uint8_t disabledValue = -1);