2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-05-13 15:51:22 +00:00
metaforce/Runtime/GuiSys/CHudVisorBeamMenu.cpp
Lioncash 5d209c8dc8 General: Mark a handful of deduced const variables as const explicitly
Same behavior, but makes it explicit to the reader that these are const.

Prevents cases where the reader might assume that just because the
variable isn't const qualified that it must be mutable, when it actually
isn't.
2020-05-08 18:41:29 -04:00

321 lines
12 KiB
C++

#include "Runtime/GuiSys/CHudVisorBeamMenu.hpp"
#include <array>
#include "Runtime/CGameState.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Audio/CSfxManager.hpp"
#include "Runtime/GuiSys/CGuiFrame.hpp"
#include "Runtime/GuiSys/CGuiModel.hpp"
#include "Runtime/GuiSys/CGuiTextPane.hpp"
#include "Runtime/GuiSys/CStringTable.hpp"
namespace urde {
constexpr std::array BaseMenuNames{
"BaseWidget_VisorMenu"sv,
"BaseWidget_BeamMenu"sv,
};
constexpr std::array TextNames{
"TextPane_VisorMenu"sv,
"TextPane_BeamMenu"sv,
};
constexpr std::array BaseTitleNames{
"basewidget_visormenutitle"sv,
"basewidget_beammenutitle"sv,
};
constexpr std::array ModelNames{
"model_visor"sv,
"model_beam"sv,
};
constexpr std::array<std::array<char, 4>, 2> MenuItemOrders{{
{'1', '0', '3', '2'},
{'3', '2', '1', '0'},
}};
constexpr std::array<std::array<int, 4>, 2> MenuStringIdx{{
{0, 2, 1, 3}, // Combat, XRay, Scan, Thermal
{4, 5, 6, 7}, // Power, Ice, Wave, Plasma
}};
constexpr std::array<u16, 2> SelectionSfxs{
SFXui_select_visor,
SFXui_select_beam,
};
CHudVisorBeamMenu::CHudVisorBeamMenu(CGuiFrame& baseHud, EHudVisorBeamMenu type,
const rstl::reserved_vector<bool, 4>& enables)
: x0_baseHud(baseHud), x4_type(type) {
x7c_animDur = g_tweakGui->GetBeamVisorMenuAnimTime();
x80_24_swapBeamControls = g_GameState->GameOptions().GetSwapBeamControls();
EHudVisorBeamMenu swappedType;
if (x80_24_swapBeamControls)
swappedType = EHudVisorBeamMenu(1 - int(x4_type));
else
swappedType = x4_type;
x20_textpane_menu = static_cast<CGuiTextPane*>(x0_baseHud.FindWidget(TextNames[size_t(swappedType)]));
x1c_basewidget_menutitle = x0_baseHud.FindWidget(BaseTitleNames[size_t(swappedType)]);
x18_basewidget_menu = x0_baseHud.FindWidget(BaseMenuNames[size_t(swappedType)]);
x24_model_ghost =
static_cast<CGuiModel*>(x0_baseHud.FindWidget(fmt::format(FMT_STRING("{}ghost"), ModelNames[size_t(x4_type)])));
x28_menuItems.resize(4);
for (size_t i = 0; i < x28_menuItems.size(); i++) {
const auto modelName = ModelNames[size_t(x4_type)];
const auto menuItemOrder = MenuItemOrders[size_t(x4_type)][i];
SMenuItem& item = x28_menuItems[i];
item.x0_model_loz =
static_cast<CGuiModel*>(x0_baseHud.FindWidget(fmt::format(FMT_STRING("{}loz{}"), modelName, menuItemOrder)));
item.x4_model_icon =
static_cast<CGuiModel*>(x0_baseHud.FindWidget(fmt::format(FMT_STRING("{}icon{}"), modelName, menuItemOrder)));
item.xc_opacity = enables[i] ? 1.f : 0.f;
}
if (x4_type == EHudVisorBeamMenu::Visor) {
x20_textpane_menu->TextSupport().SetFontColor(g_tweakGuiColors->GetVisorMenuTextFont());
x20_textpane_menu->TextSupport().SetOutlineColor(g_tweakGuiColors->GetVisorMenuTextOutline());
} else {
x20_textpane_menu->TextSupport().SetFontColor(g_tweakGuiColors->GetBeamMenuTextFont());
x20_textpane_menu->TextSupport().SetOutlineColor(g_tweakGuiColors->GetBeamMenuTextOutline());
}
zeus::CColor titleColor = zeus::skWhite;
titleColor.a() = 0.f;
x1c_basewidget_menutitle->SetColor(titleColor);
x20_textpane_menu->TextSupport().SetText(
g_MainStringTable->GetString(MenuStringIdx[size_t(x4_type)][x8_selectedItem]));
for (size_t i = 0; i < x28_menuItems.size(); ++i) {
SMenuItem& item = x28_menuItems[i];
item.x0_model_loz->SetColor(g_tweakGuiColors->GetVisorBeamMenuLozColor());
UpdateMenuWidgetTransform(i, *item.x0_model_loz, 1.f);
}
Update(0.f, true);
}
void CHudVisorBeamMenu::UpdateMenuWidgetTransform(size_t idx, CGuiWidget& w, float t) {
const float translate = t * g_tweakGui->GetVisorBeamMenuItemTranslate();
const float scale =
t * g_tweakGui->GetVisorBeamMenuItemInactiveScale() + (1.f - t) * g_tweakGui->GetVisorBeamMenuItemActiveScale();
if (x4_type == EHudVisorBeamMenu::Visor) {
if (idx == 2) {
idx = 3;
} else if (idx == 3) {
idx = 2;
}
} else {
if (idx == 1) {
idx = 2;
} else if (idx == 2) {
idx = 1;
}
}
switch (idx) {
case 0:
w.SetO2WTransform(x18_basewidget_menu->GetWorldTransform() * zeus::CTransform::Translate(0.f, 0.f, translate) *
zeus::CTransform::Scale(scale));
break;
case 1:
w.SetO2WTransform(x18_basewidget_menu->GetWorldTransform() * zeus::CTransform::Translate(translate, 0.f, 0.f) *
zeus::CTransform::Scale(scale));
break;
case 2:
w.SetO2WTransform(x18_basewidget_menu->GetWorldTransform() * zeus::CTransform::Translate(0.f, 0.f, -translate) *
zeus::CTransform::Scale(scale));
break;
case 3:
w.SetO2WTransform(x18_basewidget_menu->GetWorldTransform() * zeus::CTransform::Translate(-translate, 0.f, 0.f) *
zeus::CTransform::Scale(scale));
break;
default:
break;
}
}
void CHudVisorBeamMenu::Update(float dt, bool init) {
bool curSwapBeamControls = g_GameState->GameOptions().GetSwapBeamControls();
if (x80_24_swapBeamControls != curSwapBeamControls) {
x80_24_swapBeamControls = curSwapBeamControls;
EHudVisorBeamMenu swappedType;
if (x80_24_swapBeamControls)
swappedType = EHudVisorBeamMenu(1 - int(x4_type));
else
swappedType = x4_type;
x18_basewidget_menu = x0_baseHud.FindWidget(BaseMenuNames[size_t(swappedType)]);
x20_textpane_menu = static_cast<CGuiTextPane*>(x0_baseHud.FindWidget(TextNames[size_t(swappedType)]));
x1c_basewidget_menutitle = x0_baseHud.FindWidget(BaseTitleNames[size_t(swappedType)]);
for (size_t i = 0; i < x28_menuItems.size(); ++i) {
SMenuItem& item = x28_menuItems[i];
UpdateMenuWidgetTransform(i, *item.x4_model_icon, item.x8_positioner);
UpdateMenuWidgetTransform(i, *item.x0_model_loz, 1.f);
}
UpdateMenuWidgetTransform(size_t(x8_selectedItem), *x24_model_ghost, x28_menuItems[x8_selectedItem].x8_positioner);
}
zeus::CColor activeColor = g_tweakGuiColors->GetVisorBeamMenuItemActive();
zeus::CColor inactiveColor = g_tweakGuiColors->GetVisorBeamMenuItemInactive();
zeus::CColor lozColor = g_tweakGuiColors->GetVisorBeamMenuLozColor();
std::array<zeus::CColor, 4> tmpColors;
for (size_t i = 0; i < x28_menuItems.size(); ++i) {
SMenuItem& item = x28_menuItems[i];
if (item.xc_opacity > 0.f) {
item.xc_opacity = std::min(item.xc_opacity + dt, 1.f);
}
tmpColors[i] = zeus::CColor::lerp(activeColor, zeus::skClear, item.xc_opacity);
}
switch (x6c_animPhase) {
case EAnimPhase::Steady:
for (size_t i = 0; i < x28_menuItems.size(); ++i) {
SMenuItem& item = x28_menuItems[i];
const bool isSelectedItem = x8_selectedItem == int(i);
const bool isClear = item.xc_opacity == 0.0f;
const zeus::CColor& color0 = isSelectedItem ? activeColor : inactiveColor;
const zeus::CColor& color1 = isSelectedItem ? lozColor : inactiveColor;
const zeus::CColor iconColor = isClear ? zeus::skClear : color0 + tmpColors[i];
const zeus::CColor lColor = isClear ? lozColor : color1 + tmpColors[i];
item.x4_model_icon->SetColor(iconColor);
item.x0_model_loz->SetColor(lColor);
item.x8_positioner = isSelectedItem ? 0.f : 1.f;
}
x24_model_ghost->SetColor(activeColor);
break;
case EAnimPhase::SelectFlash: {
zeus::CColor color = zeus::skWhite;
color.a() = 0.f;
x1c_basewidget_menutitle->SetColor(color);
zeus::CColor& color0 = std::fmod(x10_interp, 0.1f) > 0.05f ? activeColor : inactiveColor;
SMenuItem& item0 = x28_menuItems[xc_pendingSelection];
color = color0 + tmpColors[xc_pendingSelection];
item0.x4_model_icon->SetColor(color);
item0.x0_model_loz->SetColor(color);
SMenuItem& item1 = x28_menuItems[x8_selectedItem];
color = zeus::CColor::lerp(inactiveColor, activeColor, x10_interp) + tmpColors[x8_selectedItem];
item1.x4_model_icon->SetColor(color);
item1.x0_model_loz->SetColor(lozColor);
for (size_t i = 0; i < x28_menuItems.size(); ++i) {
const bool isSelectedItem = x8_selectedItem == int(i);
x28_menuItems[i].x8_positioner = isSelectedItem ? 1.f - x10_interp : 1.f;
}
x24_model_ghost->SetColor(zeus::CColor::lerp(activeColor, inactiveColor, item1.x8_positioner));
break;
}
case EAnimPhase::Animate:
for (size_t i = 0; i < x28_menuItems.size(); ++i) {
SMenuItem& item = x28_menuItems[i];
const bool isSelectedItem = x8_selectedItem == int(i);
const bool isClear = item.xc_opacity == 0.f;
const zeus::CColor& color0 = isSelectedItem ? activeColor : inactiveColor;
const zeus::CColor iconColor = isClear ? zeus::skClear : color0 + tmpColors[i];
item.x4_model_icon->SetColor(iconColor);
item.x0_model_loz->SetColor((isClear || isSelectedItem) ? lozColor : inactiveColor);
item.x8_positioner = isSelectedItem ? 1.f - x10_interp : 1.f;
}
x24_model_ghost->SetColor(
zeus::CColor::lerp(activeColor, inactiveColor, x28_menuItems[x8_selectedItem].x8_positioner));
break;
default:
break;
}
if (x78_textFader > 0.f) {
x78_textFader = std::max(0.f, x78_textFader - dt);
zeus::CColor color = zeus::skWhite;
color.a() = x78_textFader / x7c_animDur;
x1c_basewidget_menutitle->SetColor(color);
}
if (x14_26_dirty || init) {
x14_26_dirty = false;
for (size_t i = 0; i < x28_menuItems.size(); ++i) {
SMenuItem& item = x28_menuItems[i];
UpdateMenuWidgetTransform(i, *item.x4_model_icon, item.x8_positioner);
}
UpdateMenuWidgetTransform(size_t(x8_selectedItem), *x24_model_ghost, x28_menuItems[x8_selectedItem].x8_positioner);
}
if (!x14_24_visibleDebug || !x14_25_visibleGame)
return;
x1c_basewidget_menutitle->SetVisibility(x1c_basewidget_menutitle->GetGeometryColor().a() != 0.f,
ETraversalMode::Children);
for (SMenuItem& item : x28_menuItems) {
item.x4_model_icon->SetIsVisible(item.x4_model_icon->GetGeometryColor().a() != 0.f);
}
}
void CHudVisorBeamMenu::UpdateHudAlpha(float alpha) {
zeus::CColor color = zeus::skWhite;
color.a() = g_GameState->GameOptions().GetHUDAlpha() / 255.f * alpha;
x18_basewidget_menu->SetColor(color);
}
void CHudVisorBeamMenu::SetIsVisibleGame(bool v) {
x14_25_visibleGame = v;
bool vis = x14_24_visibleDebug && x14_25_visibleGame;
x18_basewidget_menu->SetVisibility(vis, ETraversalMode::Children);
if (vis)
Update(0.f, true);
}
void CHudVisorBeamMenu::SetPlayerHas(const rstl::reserved_vector<bool, 4>& enables) {
for (size_t i = 0; i < x28_menuItems.size(); ++i) {
SMenuItem& item = x28_menuItems[i];
if (item.xc_opacity == 0.f && enables[i]) {
item.xc_opacity = FLT_EPSILON;
}
}
}
void CHudVisorBeamMenu::SetSelection(int selection, int pending, float interp) {
if (x8_selectedItem == selection && xc_pendingSelection == pending && x10_interp == interp)
return;
if (pending != selection) {
if (x6c_animPhase != EAnimPhase::SelectFlash) {
CSfxManager::SfxStart(SelectionSfxs[size_t(x4_type)], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
}
x6c_animPhase = EAnimPhase::SelectFlash;
} else if (interp < 1.f) {
x6c_animPhase = EAnimPhase::Animate;
x20_textpane_menu->TextSupport().SetText(
g_MainStringTable->GetString(MenuStringIdx[size_t(x4_type)][x8_selectedItem]));
x20_textpane_menu->TextSupport().SetTypeWriteEffectOptions(true, 0.1f, 16.f);
} else {
if (x6c_animPhase != EAnimPhase::Steady)
x78_textFader = x7c_animDur;
x6c_animPhase = EAnimPhase::Steady;
}
x14_26_dirty = true;
x8_selectedItem = selection;
xc_pendingSelection = pending;
x10_interp = interp;
}
} // namespace urde