Add smooth camera menu

- Added ModMenuModule menus:
    - SmoothCameraMenu
    - SmoothVehicleCameraMenu
    - SmoothFollowCameraMenu
This commit is contained in:
izawartka 2026-08-19 18:01:25 +02:00
parent d04da7f241
commit e8a9bdd552
10 changed files with 759 additions and 2 deletions

View File

@ -449,6 +449,9 @@
<ClInclude Include="src\modules\modmenu\menus\saved-vehicle-options-menu.h" />
<ClInclude Include="src\modules\modmenu\menus\select-camera-modes-menu.h" />
<ClInclude Include="src\modules\modmenu\menus\seukomod-options-menu.h" />
<ClInclude Include="src\modules\modmenu\menus\smooth-camera-menu.h" />
<ClInclude Include="src\modules\modmenu\menus\smooth-follow-camera-menu.h" />
<ClInclude Include="src\modules\modmenu\menus\smooth-vehicle-camera-menu.h" />
<ClInclude Include="src\modules\modmenu\menus\spawn-object-menu.h" />
<ClInclude Include="src\modules\modmenu\menus\spawn-ped-menu.h" />
<ClInclude Include="src\modules\modmenu\menus\spawn-vehicle-menu.h" />
@ -748,6 +751,9 @@
<ClCompile Include="src\modules\modmenu\menus\saved-vehicle-options-menu.cpp" />
<ClCompile Include="src\modules\modmenu\menus\select-camera-modes-menu.cpp" />
<ClCompile Include="src\modules\modmenu\menus\seukomod-options-menu.cpp" />
<ClCompile Include="src\modules\modmenu\menus\smooth-camera-menu.cpp" />
<ClCompile Include="src\modules\modmenu\menus\smooth-follow-camera-menu.cpp" />
<ClCompile Include="src\modules\modmenu\menus\smooth-vehicle-camera-menu.cpp" />
<ClCompile Include="src\modules\modmenu\menus\spawn-object-menu.cpp" />
<ClCompile Include="src\modules\modmenu\menus\spawn-ped-menu.cpp" />
<ClCompile Include="src\modules\modmenu\menus\spawn-vehicle-menu.cpp" />

View File

@ -230,8 +230,11 @@
<ClCompile Include="src\modules\modmenu\quick-actions\spawn-character.cpp" />
<ClCompile Include="src\events\update-car-camera.cpp" />
<ClCompile Include="src\modules\modmenu\cheats\camera\smooth-camera.cpp" />
<ClCompile Include="src\modules\modmenu\menus\smooth-camera-menu.cpp" />
<ClCompile Include="src\modules\modmenu\menus\seukomod-options-menu.cpp" />
<ClCompile Include="src\modules\modmenu\utils\scrf-lerp-utils.cpp" />
<ClCompile Include="src\modules\modmenu\menus\smooth-vehicle-camera-menu.cpp" />
<ClCompile Include="src\modules\modmenu\menus\smooth-follow-camera-menu.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\converters\ammo.h" />
@ -596,8 +599,11 @@
<ClInclude Include="src\modules\modmenu\quick-actions\spawn-character.h" />
<ClInclude Include="src\events\update-car-camera.h" />
<ClInclude Include="src\modules\modmenu\cheats\camera\smooth-camera.h" />
<ClInclude Include="src\modules\modmenu\menus\smooth-camera-menu.h" />
<ClInclude Include="src\modules\modmenu\menus\seukomod-options-menu.h" />
<ClInclude Include="src\modules\modmenu\utils\scrf-lerp-utils.h" />
<ClInclude Include="src\modules\modmenu\menus\smooth-vehicle-camera-menu.h" />
<ClInclude Include="src\modules\modmenu\menus\smooth-follow-camera-menu.h" />
</ItemGroup>
<ItemGroup>
<None Include="GTA2.props" />

View File

@ -2,6 +2,7 @@
#include "../../../converters/camera-easy-mode.h"
#include "../utils/camera-easy-mode-utils.h"
#include "camera-pos-menu.h"
#include "smooth-camera-menu.h"
#include "camera-rendering-menu.h"
#include "camera-advanced-menu.h"
#include "../cheats/camera/freecam.h"
@ -27,6 +28,7 @@ bool ModMenuModule::CameraMenu::Attach()
m_menuController->CreateItem<UiModule::Text>(vertCont, L"Go back", options.textSize);
m_menuController->CreateItem<UiModule::Text>(vertCont, L"Camera position", options.textSize);
m_menuController->CreateItem<UiModule::Text>(vertCont, L"Smooth camera", options.textSize);
m_menuController->CreateItem<UiModule::Text>(vertCont, L"Advanced rendering options", options.textSize);
m_menuController->CreateItem<UiModule::Text>(vertCont, L"Advanced camera options", options.textSize);
@ -86,10 +88,13 @@ void ModMenuModule::CameraMenu::OnMenuAction(UiModule::Selectable* item, UiModul
case 1: // Camera position
ModMenuModule::MenuManager::GetInstance()->AddMenu<CameraPosMenu>();
break;
case 2: // Advanced rendering options
case 2: // Smooth camera
ModMenuModule::MenuManager::GetInstance()->AddMenu<SmoothCameraMenu>();
break;
case 3: // Advanced rendering options
ModMenuModule::MenuManager::GetInstance()->AddMenu<CameraRenderingMenu>();
break;
case 3: // Advanced camera settings
case 4: // Advanced camera settings
ModMenuModule::MenuManager::GetInstance()->AddMenu<CameraAdvancedMenu>();
break;
default:

View File

@ -18,6 +18,9 @@
#include "get-weapon-menu.h"
#include "camera-menu.h"
#include "camera-pos-menu.h"
#include "smooth-camera-menu.h"
#include "smooth-vehicle-camera-menu.h"
#include "smooth-follow-camera-menu.h"
#include "camera-rendering-menu.h"
#include "camera-advanced-menu.h"
#include "world-menu.h"

View File

@ -0,0 +1,174 @@
#include "smooth-camera-menu.h"
#include "../root.h"
#include "../cheats/camera/smooth-camera.h"
#include "../../../converters/enabled-disabled.h"
#include "smooth-vehicle-camera-menu.h"
#include "smooth-follow-camera-menu.h"
ModMenuModule::SmoothCameraMenu::SmoothCameraMenu()
{
}
ModMenuModule::SmoothCameraMenu::~SmoothCameraMenu()
{
}
bool ModMenuModule::SmoothCameraMenu::Attach()
{
UiModule::Component* vertCont;
CreateMenu(L"#Smooth camera options#", vertCont);
UiModule::RootModule* uiRoot = UiModule::RootModule::GetInstance();
const auto& options = ModMenuModule::RootModule::GetInstance()->GetOptions();
SmoothCameraCheat* smoothCameraCheat = SmoothCameraCheat::GetInstance();
m_menuController->CreateItem<UiModule::Text>(vertCont, L"Go back", options.textSize);
// smooth camera cheat
UiModule::Text* smoothCameraCheatText = m_menuController->CreateItem<UiModule::Text>(vertCont, L"", options.textSize);
m_smoothCameraCheatController = m_menuController->CreateLatestItemController<UiModule::SelectController<bool>>(
smoothCameraCheatText,
UiModule::SelectOptionList<bool>{ false, true },
std::nullopt,
UiModule::SelectControllerOptions{ L"Smooth camera: #", L"#" }
);
m_smoothCameraCheatController->SetConverter<EnabledDisabledConverter>();
m_smoothCameraCheatController->SetSaveCallback([smoothCameraCheat](bool newValue) {
smoothCameraCheat->SetEnabled(newValue);
});
m_cheatItemsCont = uiRoot->AddComponent<UiModule::VertCont>(vertCont);
m_cheatItemsGroupId = m_menuController->RegisterGroup();
// warning
uiRoot->AddComponent<UiModule::Spacer>(
vertCont,
0,
options.menuSpacerHeight
);
auto* warnMargin = uiRoot->AddComponent<UiModule::Margin>(
vertCont,
options.menuControllerOptions.createdSelectableOptions.markerOffsetX,
0
);
auto* warnCont = uiRoot->AddComponent<UiModule::VertCont>(warnMargin);
uiRoot->AddComponent<UiModule::Text>(
warnCont,
L"Warning: This feature is experimental.",
options.textSize,
4 // orange color
);
uiRoot->AddComponent<UiModule::Text>(
warnCont,
L"Saved values may be reset in future releases.",
options.textSize,
4 // orange color
);
UpdateCheatState();
SetPreviousSelectedIndex();
return true;
}
void ModMenuModule::SmoothCameraMenu::Detach()
{
SaveCurrentSelectedIndex();
DetachCheatMenuItems();
DestroyMenu();
}
void ModMenuModule::SmoothCameraMenu::OnShow()
{
AddEventListener<ModMenuModule::CheatStateEvent>(&SmoothCameraMenu::OnCheatStateChange);
UpdateCheatState();
}
void ModMenuModule::SmoothCameraMenu::OnHide()
{
RemoveEventListener<ModMenuModule::CheatStateEvent>();
}
void ModMenuModule::SmoothCameraMenu::OnMenuAction(UiModule::Selectable* item, UiModule::MenuItemId id)
{
MenuManager* menuManager = MenuManager::GetInstance();
if (id == 0) { // Go back
menuManager->RemoveLastMenu();
return;
}
else if (id == m_carCameraMenuItemId) { // Vehicle camera
menuManager->AddMenu<SmoothVehicleCameraMenu>();
return;
}
else if (id == m_followCameraMenuItemId) { // Follow camera
menuManager->AddMenu<SmoothFollowCameraMenu>();
return;
}
}
void ModMenuModule::SmoothCameraMenu::AttachCheatMenuItems()
{
if (m_cheatItemsAttached) return;
UiModule::RootModule* uiRoot = UiModule::RootModule::GetInstance();
SmoothCameraCheat* smoothCameraCheat = SmoothCameraCheat::GetInstance();
const auto& options = ModMenuModule::RootModule::GetInstance()->GetOptions();
UiModule::VertCont* container = m_cheatItemsCont;
m_menuController->SetCurrentGroupId(m_cheatItemsGroupId);
// vehicle camera
m_menuController->CreateItem<UiModule::Text>(container, L"Vehicle camera", options.textSize);
m_carCameraMenuItemId = m_menuController->GetLatestMenuItemId();
// follow camera
m_menuController->CreateItem<UiModule::Text>(container, L"Follow camera", options.textSize);
m_followCameraMenuItemId = m_menuController->GetLatestMenuItemId();
// reset options
auto* resetOptionsText = m_menuController->CreateItem<UiModule::Text>(container, L"Reset options", options.textSize);
auto* resetOptionsBtn = m_menuController->CreateLatestItemController<UiModule::ButtonController>(resetOptionsText);
resetOptionsBtn->SetCallback([smoothCameraCheat]() {
smoothCameraCheat->SetOptions({});
});
m_cheatItemsAttached = true;
}
void ModMenuModule::SmoothCameraMenu::DetachCheatMenuItems()
{
if (!m_cheatItemsAttached) return;
m_menuController->DeleteGroupItems(m_cheatItemsGroupId);
m_cheatItemsAttached = false;
m_carCameraMenuItemId = -1;
m_followCameraMenuItemId = -1;
}
void ModMenuModule::SmoothCameraMenu::OnCheatStateChange(CheatStateEvent& event)
{
if (event.GetCheatType() == typeid(SmoothCameraCheat)) {
m_smoothCameraCheatController->SetValue(event.IsEnabled());
if (event.IsEnabled()) AttachCheatMenuItems();
else DetachCheatMenuItems();
}
}
void ModMenuModule::SmoothCameraMenu::UpdateCheatState()
{
bool smoothCameraCheatEnabled = SmoothCameraCheat::GetInstance()->IsEnabled();
m_smoothCameraCheatController->SetValue(smoothCameraCheatEnabled);
if (smoothCameraCheatEnabled) AttachCheatMenuItems();
else DetachCheatMenuItems();
}

View File

@ -0,0 +1,33 @@
#pragma once
#include "../common.h"
#include "../menu-base.h"
#include "../events/cheat-state.h"
namespace ModMenuModule {
class SmoothCameraMenu : public MenuBase, public Core::EventListenerSupport {
public:
SmoothCameraMenu();
virtual ~SmoothCameraMenu();
private:
virtual bool Attach() override;
virtual void Detach() override;
virtual void OnShow() override;
virtual void OnHide() override;
void OnMenuAction(UiModule::Selectable* item, UiModule::MenuItemId id) override;
void AttachCheatMenuItems();
void DetachCheatMenuItems();
void OnCheatStateChange(CheatStateEvent& event);
void UpdateCheatState();
UiModule::SelectController<bool>* m_smoothCameraCheatController = nullptr;
UiModule::VertCont* m_cheatItemsCont = nullptr;
UiModule::MenuItemGroupId m_cheatItemsGroupId = -1;
bool m_cheatItemsAttached = false;
UiModule::MenuItemId m_carCameraMenuItemId = -1;
UiModule::MenuItemId m_followCameraMenuItemId = -1;
};
}

View File

@ -0,0 +1,191 @@
#include "smooth-follow-camera-menu.h"
#include "../root.h"
#include "../events/cheat-options-update.h"
#include "../../../converters/enabled-disabled.h"
#include "../../../converters/float.h"
#include "../../../converters/scrf.h"
ModMenuModule::SmoothFollowCameraMenu::SmoothFollowCameraMenu()
{
}
ModMenuModule::SmoothFollowCameraMenu::~SmoothFollowCameraMenu()
{
}
bool ModMenuModule::SmoothFollowCameraMenu::Attach()
{
UiModule::Component* vertCont;
CreateMenu(L"#Smooth follow camera options#", vertCont);
UiModule::RootModule* uiRoot = UiModule::RootModule::GetInstance();
const auto& options = ModMenuModule::RootModule::GetInstance()->GetOptions();
m_menuController->CreateItem<UiModule::Text>(vertCont, L"Go back", options.textSize);
SmoothCameraCheat* smoothCameraCheat = SmoothCameraCheat::GetInstance();
if (!smoothCameraCheat->IsEnabled()) {
spdlog::debug("SmoothFollowCameraMenu: SmoothCameraCheat is not enabled, skipping Attach");
SetPreviousSelectedIndex();
return true;
}
// Smooth follow camera
UiModule::Text* smoothFollowCameraText = m_menuController->CreateItem<UiModule::Text>(vertCont, L"", options.textSize);
auto smoothFollowCameraController = m_menuController->CreateLatestItemController<UiModule::VarTextSelectController<bool, bool>>(
smoothFollowCameraText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().smoothFollowCamera;
},
UiModule::SelectOptionList<bool>{ false, true },
UiModule::VarTextSelectControllerOptions{ L"Smooth follow camera: #", L"#" }
);
smoothFollowCameraController->SetConverter<EnabledDisabledConverter>();
smoothFollowCameraController->SetCustomSaveCallback([smoothCameraCheat](bool newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.smoothFollowCamera = newValue;
smoothCameraCheat->SetOptions(options);
});
m_cheatItemsCont = uiRoot->AddComponent<UiModule::VertCont>(vertCont);
m_cheatItemsGroupId = m_menuController->RegisterGroup();
UpdateCheatState();
SetPreviousSelectedIndex();
return true;
}
void ModMenuModule::SmoothFollowCameraMenu::Detach()
{
DetachCheatMenuItems();
DestroyMenu();
}
void ModMenuModule::SmoothFollowCameraMenu::OnShow()
{
AddEventListener<ModMenuModule::CheatStateEvent>(&SmoothFollowCameraMenu::OnCheatStateChange);
AddEventListener<ModMenuModule::CheatOptionsUpdateEvent<SmoothCameraCheat>>(
&SmoothFollowCameraMenu::OnCheatOptionsUpdate
);
UpdateCheatState();
}
void ModMenuModule::SmoothFollowCameraMenu::OnHide()
{
RemoveEventListener<ModMenuModule::CheatStateEvent>();
RemoveEventListener<ModMenuModule::CheatOptionsUpdateEvent<SmoothCameraCheat>>();
}
void ModMenuModule::SmoothFollowCameraMenu::OnMenuAction(UiModule::Selectable* item, UiModule::MenuItemId id)
{
if (id == 0) { // Go back
MenuManager::GetInstance()->RemoveLastMenu();
return;
}
}
void ModMenuModule::SmoothFollowCameraMenu::AttachCheatMenuItems()
{
if (m_cheatItemsAttached) return;
UiModule::RootModule* uiRoot = UiModule::RootModule::GetInstance();
SmoothCameraCheat* smoothCameraCheat = SmoothCameraCheat::GetInstance();
const auto& options = ModMenuModule::RootModule::GetInstance()->GetOptions();
UiModule::VertCont* container = m_cheatItemsCont;
m_menuController->SetCurrentGroupId(m_cheatItemsGroupId);
// Lerp coefficient
UiModule::Text* lerpCoefText = m_menuController->CreateItem<UiModule::Text>(container, L"", options.textSize);
auto lerpCoefController = m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<float, float>>(
lerpCoefText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().followLerpCoef;
},
UiModule::VarTextEditableControllerOptions{ L"Lerp coefficient: #", L"#" }
);
lerpCoefController->SetConverter<FloatConverter<float, 3>>();
lerpCoefController->SetCustomSaveCallback([smoothCameraCheat](float newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.followLerpCoef = newValue;
smoothCameraCheat->SetOptions(options);
});
// Lerp max. delta
UiModule::Text* lerpMaxDeltaText = m_menuController->CreateItem<UiModule::Text>(container, L"", options.textSize);
auto lerpMaxDeltaController = m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<Game::SCR_f, Game::SCR_f>>(
lerpMaxDeltaText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().followMaxDelta;
},
UiModule::VarTextEditableControllerOptions{ L"Lerp max. delta: #", L"#" }
);
lerpMaxDeltaController->SetConverter<ScrfConverter>();
lerpMaxDeltaController->SetCustomSaveCallback([smoothCameraCheat](Game::SCR_f newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.followMaxDelta = newValue;
smoothCameraCheat->SetOptions(options);
});
// Lerp max. zoom delta
UiModule::Text* lerpMaxZoomDeltaText = m_menuController->CreateItem<UiModule::Text>(container, L"", options.textSize);
auto lerpMaxZoomDeltaController = m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<Game::SCR_f, Game::SCR_f>>(
lerpMaxZoomDeltaText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().followZoomMaxDelta;
},
UiModule::VarTextEditableControllerOptions{ L"Lerp max. zoom delta: #", L"#" }
);
lerpMaxZoomDeltaController->SetConverter<ScrfConverter>();
lerpMaxZoomDeltaController->SetCustomSaveCallback([smoothCameraCheat](Game::SCR_f newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.followZoomMaxDelta = newValue;
smoothCameraCheat->SetOptions(options);
});
m_cheatItemsAttached = true;
}
void ModMenuModule::SmoothFollowCameraMenu::DetachCheatMenuItems()
{
if (!m_cheatItemsAttached) return;
m_menuController->DeleteGroupItems(m_cheatItemsGroupId);
m_cheatItemsAttached = false;
}
void ModMenuModule::SmoothFollowCameraMenu::OnCheatStateChange(CheatStateEvent& event)
{
if (event.GetCheatType() != typeid(SmoothCameraCheat)) return;
if (event.IsEnabled()) return;
MenuManager::GetInstance()->RemoveLastMenu();
}
void ModMenuModule::SmoothFollowCameraMenu::OnCheatOptionsUpdate(CheatOptionsUpdateEvent<SmoothCameraCheat>& event)
{
bool isSmoothFollowCameraEnabled = event.GetNewOptions().smoothFollowCamera;
if (isSmoothFollowCameraEnabled) AttachCheatMenuItems();
else DetachCheatMenuItems();
}
void ModMenuModule::SmoothFollowCameraMenu::UpdateCheatState()
{
SmoothCameraCheat* smoothCameraCheat = SmoothCameraCheat::GetInstance();
bool smoothCameraCheatEnabled = smoothCameraCheat->IsEnabled();
if (!smoothCameraCheatEnabled) {
MenuManager::GetInstance()->RemoveLastMenu();
return;
}
bool isSmoothVehicleCameraEnabled = smoothCameraCheat->IsEnabled();
if (isSmoothVehicleCameraEnabled) AttachCheatMenuItems();
else DetachCheatMenuItems();
}

View File

@ -0,0 +1,34 @@
#pragma once
#include "../common.h"
#include "../menu-base.h"
#include "../events/cheat-state.h"
#include "../events/cheat-options-update.h"
#include "../cheats/camera/smooth-camera.h"
namespace ModMenuModule {
class SmoothFollowCameraMenu : public MenuBase, public Core::EventListenerSupport {
public:
SmoothFollowCameraMenu();
virtual ~SmoothFollowCameraMenu();
private:
virtual bool Attach() override;
virtual void Detach() override;
virtual void OnShow() override;
virtual void OnHide() override;
void OnMenuAction(UiModule::Selectable* item, UiModule::MenuItemId id) override;
void AttachCheatMenuItems();
void DetachCheatMenuItems();
void OnCheatStateChange(CheatStateEvent& event);
void OnCheatOptionsUpdate(CheatOptionsUpdateEvent<SmoothCameraCheat>& event);
void UpdateCheatState();
UiModule::SelectController<bool>* m_smoothCameraCheatController = nullptr;
UiModule::VertCont* m_cheatItemsCont = nullptr;
UiModule::MenuItemGroupId m_cheatItemsGroupId = -1;
bool m_cheatItemsAttached = false;
};
}

View File

@ -0,0 +1,271 @@
#include "smooth-vehicle-camera-menu.h"
#include "../root.h"
#include "../events/cheat-options-update.h"
#include "../../../converters/enabled-disabled.h"
#include "../../../converters/float.h"
#include "../../../converters/scrf.h"
#include "../../../converters/radians.h"
ModMenuModule::SmoothVehicleCameraMenu::SmoothVehicleCameraMenu()
{
}
ModMenuModule::SmoothVehicleCameraMenu::~SmoothVehicleCameraMenu()
{
}
bool ModMenuModule::SmoothVehicleCameraMenu::Attach()
{
UiModule::Component* vertCont;
CreateMenu(L"#Smooth vehicle camera options#", vertCont);
UiModule::RootModule* uiRoot = UiModule::RootModule::GetInstance();
const auto& options = ModMenuModule::RootModule::GetInstance()->GetOptions();
m_menuController->CreateItem<UiModule::Text>(vertCont, L"Go back", options.textSize);
SmoothCameraCheat* smoothCameraCheat = SmoothCameraCheat::GetInstance();
if (!smoothCameraCheat->IsEnabled()) {
spdlog::debug("SmoothVehicleCameraMenu: SmoothCameraCheat is not enabled, skipping Attach");
SetPreviousSelectedIndex();
return true;
}
// Smooth car camera
UiModule::Text* smoothVehicleCameraText = m_menuController->CreateItem<UiModule::Text>(vertCont, L"", options.textSize);
auto smoothVehicleCameraController = m_menuController->CreateLatestItemController<UiModule::VarTextSelectController<bool, bool>>(
smoothVehicleCameraText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().smoothCarCamera;
},
UiModule::SelectOptionList<bool>{ false, true },
UiModule::VarTextSelectControllerOptions{ L"Smooth vehicle camera: #", L"#" }
);
smoothVehicleCameraController->SetConverter<EnabledDisabledConverter>();
smoothVehicleCameraController->SetCustomSaveCallback([smoothCameraCheat](bool newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.smoothCarCamera = newValue;
smoothCameraCheat->SetOptions(options);
});
m_cheatItemsCont = uiRoot->AddComponent<UiModule::VertCont>(vertCont);
m_cheatItemsGroupId = m_menuController->RegisterGroup();
UpdateCheatState();
SetPreviousSelectedIndex();
return true;
}
void ModMenuModule::SmoothVehicleCameraMenu::Detach()
{
DetachCheatMenuItems();
DestroyMenu();
}
void ModMenuModule::SmoothVehicleCameraMenu::OnShow()
{
AddEventListener<ModMenuModule::CheatStateEvent>(&SmoothVehicleCameraMenu::OnCheatStateChange);
AddEventListener<ModMenuModule::CheatOptionsUpdateEvent<SmoothCameraCheat>>(
&SmoothVehicleCameraMenu::OnCheatOptionsUpdate
);
UpdateCheatState();
}
void ModMenuModule::SmoothVehicleCameraMenu::OnHide()
{
RemoveEventListener<ModMenuModule::CheatStateEvent>();
RemoveEventListener<ModMenuModule::CheatOptionsUpdateEvent<SmoothCameraCheat>>();
}
void ModMenuModule::SmoothVehicleCameraMenu::OnMenuAction(UiModule::Selectable* item, UiModule::MenuItemId id)
{
if (id == 0) { // Go back
MenuManager::GetInstance()->RemoveLastMenu();
return;
}
}
void ModMenuModule::SmoothVehicleCameraMenu::AttachCheatMenuItems()
{
if (m_cheatItemsAttached) return;
UiModule::RootModule* uiRoot = UiModule::RootModule::GetInstance();
SmoothCameraCheat* smoothCameraCheat = SmoothCameraCheat::GetInstance();
const auto& options = ModMenuModule::RootModule::GetInstance()->GetOptions();
UiModule::VertCont* container = m_cheatItemsCont;
m_menuController->SetCurrentGroupId(m_cheatItemsGroupId);
// Horizontal move scale
UiModule::Text* horMoveScaleText = m_menuController->CreateItem<UiModule::Text>(container, L"", options.textSize);
auto horMoveScaleController = m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<float, float>>(
horMoveScaleText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().carCameraHorMoveScale;
},
UiModule::VarTextEditableControllerOptions{ L"Horizontal move scale: #", L"#" }
);
horMoveScaleController->SetConverter<FloatConverter<float, 3>>();
horMoveScaleController->SetCustomSaveCallback([smoothCameraCheat](float newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.carCameraHorMoveScale = newValue;
smoothCameraCheat->SetOptions(options);
});
// Vertical move scale
UiModule::Text* vertMoveScaleText = m_menuController->CreateItem<UiModule::Text>(container, L"", options.textSize);
auto vertMoveScaleController = m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<float, float>>(
vertMoveScaleText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().carCameraVertMoveScale;
},
UiModule::VarTextEditableControllerOptions{ L"Vertical move scale: #", L"#" }
);
vertMoveScaleController->SetConverter<FloatConverter<float, 3>>();
vertMoveScaleController->SetCustomSaveCallback([smoothCameraCheat](float newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.carCameraVertMoveScale = newValue;
smoothCameraCheat->SetOptions(options);
});
// Magnitude lerp coefficient
UiModule::Text* magLerpCoefText = m_menuController->CreateItem<UiModule::Text>(container, L"", options.textSize);
auto magLerpCoefController = m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<float, float>>(
magLerpCoefText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().carCameraMagLerpCoef;
},
UiModule::VarTextEditableControllerOptions{ L"Magnitude lerp coefficient: #", L"#" }
);
magLerpCoefController->SetConverter<FloatConverter<float, 3>>();
magLerpCoefController->SetCustomSaveCallback([smoothCameraCheat](float newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.carCameraMagLerpCoef = newValue;
smoothCameraCheat->SetOptions(options);
});
// Magnitude lerp max. delta
UiModule::Text* magLerpMaxDeltaText = m_menuController->CreateItem<UiModule::Text>(container, L"", options.textSize);
auto magLerpMaxDeltaController = m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<Game::SCR_f, Game::SCR_f>>(
magLerpMaxDeltaText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().carCameraMagMaxDelta;
},
UiModule::VarTextEditableControllerOptions{ L"Magnitude lerp max. delta: #", L"#" }
);
magLerpMaxDeltaController->SetConverter<ScrfConverter>();
magLerpMaxDeltaController->SetCustomSaveCallback([smoothCameraCheat](Game::SCR_f newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.carCameraMagMaxDelta = newValue;
smoothCameraCheat->SetOptions(options);
});
// Hor. rot. lerp coefficient
UiModule::Text* horLerpCoefText = m_menuController->CreateItem<UiModule::Text>(container, L"", options.textSize);
auto horLerpCoefController = m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<float, float>>(
horLerpCoefText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().carCameraHorLerpCoef;
},
UiModule::VarTextEditableControllerOptions{ L"Hor. rot. lerp coefficient: #", L"#" }
);
horLerpCoefController->SetConverter<FloatConverter<float, 3>>();
horLerpCoefController->SetCustomSaveCallback([smoothCameraCheat](float newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.carCameraHorLerpCoef = newValue;
smoothCameraCheat->SetOptions(options);
});
// Hor. rot. lerp max. delta
UiModule::Text* horLerpMaxDeltaText = m_menuController->CreateItem<UiModule::Text>(container, L"", options.textSize);
auto horLerpMaxDeltaController = m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<float, float>>(
horLerpMaxDeltaText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().carCameraHorMaxDelta;
},
UiModule::VarTextEditableControllerOptions{ L"Hor. rot. lerp max. delta: #", L" deg#" }
);
horLerpMaxDeltaController->SetConverter<RadiansConverter<>>();
horLerpMaxDeltaController->SetCustomSaveCallback([smoothCameraCheat](float newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.carCameraHorMaxDelta = newValue;
smoothCameraCheat->SetOptions(options);
});
// Vert. rot. lerp coefficient
UiModule::Text* vertLerpCoefText = m_menuController->CreateItem<UiModule::Text>(container, L"", options.textSize);
auto vertLerpCoefController = m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<float, float>>(
vertLerpCoefText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().carCameraVertLerpCoef;
},
UiModule::VarTextEditableControllerOptions{ L"Vert. rot. lerp coefficient: #", L"#" }
);
vertLerpCoefController->SetConverter<FloatConverter<float, 3>>();
vertLerpCoefController->SetCustomSaveCallback([smoothCameraCheat](float newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.carCameraVertLerpCoef = newValue;
smoothCameraCheat->SetOptions(options);
});
// Vert. rot. lerp max. delta
UiModule::Text* vertLerpMaxDeltaText = m_menuController->CreateItem<UiModule::Text>(container, L"", options.textSize);
auto vertLerpMaxDeltaController = m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<float, float>>(
vertLerpMaxDeltaText,
[smoothCameraCheat]() {
return smoothCameraCheat->GetOptions().carCameraVertMaxDelta;
},
UiModule::VarTextEditableControllerOptions{ L"Vert. rot. lerp max. delta: #", L" deg#" }
);
vertLerpMaxDeltaController->SetConverter<RadiansConverter<>>();
vertLerpMaxDeltaController->SetCustomSaveCallback([smoothCameraCheat](float newValue) {
SmoothCameraCheatOptions options = smoothCameraCheat->GetOptions();
options.carCameraVertMaxDelta = newValue;
smoothCameraCheat->SetOptions(options);
});
m_cheatItemsAttached = true;
}
void ModMenuModule::SmoothVehicleCameraMenu::DetachCheatMenuItems()
{
if (!m_cheatItemsAttached) return;
m_menuController->DeleteGroupItems(m_cheatItemsGroupId);
m_cheatItemsAttached = false;
}
void ModMenuModule::SmoothVehicleCameraMenu::OnCheatStateChange(CheatStateEvent& event)
{
if (event.GetCheatType() != typeid(SmoothCameraCheat)) return;
if (event.IsEnabled()) return;
MenuManager::GetInstance()->RemoveLastMenu();
}
void ModMenuModule::SmoothVehicleCameraMenu::OnCheatOptionsUpdate(CheatOptionsUpdateEvent<SmoothCameraCheat>& event)
{
bool isSmoothVehicleCameraEnabled = event.GetNewOptions().smoothCarCamera;
if (isSmoothVehicleCameraEnabled) AttachCheatMenuItems();
else DetachCheatMenuItems();
}
void ModMenuModule::SmoothVehicleCameraMenu::UpdateCheatState()
{
SmoothCameraCheat* smoothCameraCheat = SmoothCameraCheat::GetInstance();
bool smoothCameraCheatEnabled = smoothCameraCheat->IsEnabled();
if (!smoothCameraCheatEnabled) {
MenuManager::GetInstance()->RemoveLastMenu();
return;
}
bool isSmoothVehicleCameraEnabled = smoothCameraCheat->IsEnabled();
if (isSmoothVehicleCameraEnabled) AttachCheatMenuItems();
else DetachCheatMenuItems();
}

View File

@ -0,0 +1,34 @@
#pragma once
#include "../common.h"
#include "../menu-base.h"
#include "../events/cheat-state.h"
#include "../events/cheat-options-update.h"
#include "../cheats/camera/smooth-camera.h"
namespace ModMenuModule {
class SmoothVehicleCameraMenu : public MenuBase, public Core::EventListenerSupport {
public:
SmoothVehicleCameraMenu();
virtual ~SmoothVehicleCameraMenu();
private:
virtual bool Attach() override;
virtual void Detach() override;
virtual void OnShow() override;
virtual void OnHide() override;
void OnMenuAction(UiModule::Selectable* item, UiModule::MenuItemId id) override;
void AttachCheatMenuItems();
void DetachCheatMenuItems();
void OnCheatStateChange(CheatStateEvent& event);
void OnCheatOptionsUpdate(CheatOptionsUpdateEvent<SmoothCameraCheat>& event);
void UpdateCheatState();
UiModule::SelectController<bool>* m_smoothCameraCheatController = nullptr;
UiModule::VertCont* m_cheatItemsCont = nullptr;
UiModule::MenuItemGroupId m_cheatItemsGroupId = -1;
bool m_cheatItemsAttached = false;
};
}