mirror of
https://github.com/wiiu-env/WiiUPluginLoaderBackend.git
synced 2026-04-17 05:55:48 -05:00
Update ConfigMenu to have a "hidden" sub menu for toggling heap tracking, preserve heap tracking option on wiiloading
This commit is contained in:
parent
f6dd18f001
commit
5cd5a7b89b
|
|
@ -43,10 +43,10 @@ PluginManagement::loadPlugins(const std::vector<PluginLoadWrapper> &pluginDataLi
|
|||
DisplayErrorNotificationMessage(errMsg, 15.0f);
|
||||
continue;
|
||||
}
|
||||
plugins.emplace_back(std::move(*metaInfo), std::move(*linkInfo), pluginDataWrapper.getPluginData());
|
||||
plugins.emplace_back(std::move(*metaInfo), std::move(*linkInfo), pluginDataWrapper.getPluginData(), pluginDataWrapper.getHeapTrackingOptions());
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_INFO("LOAD (INACTIVE) %s", metaInfo->getName().c_str());
|
||||
plugins.emplace_back(std::move(*metaInfo), PluginLinkInformation::CreateStub(), pluginDataWrapper.getPluginData());
|
||||
plugins.emplace_back(std::move(*metaInfo), PluginLinkInformation::CreateStub(), pluginDataWrapper.getPluginData(), std::nullopt);
|
||||
}
|
||||
} else {
|
||||
auto errMsg = string_format("Failed to load plugin: %s", pluginDataWrapper.getPluginData()->getSource().c_str());
|
||||
|
|
|
|||
|
|
@ -430,9 +430,6 @@ namespace ShellCommands {
|
|||
};
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<IOPShellModule::CommandGroup> sPluginGroup;
|
||||
std::optional<IOPShellModule::Command> sPluginCmdHandle;
|
||||
|
||||
std::string BytesToHumanReadable(uint32_t bytes) {
|
||||
char buffer[32];
|
||||
snprintf(buffer, sizeof(buffer), "%.2f KiB", bytes / 1024.0f);
|
||||
|
|
@ -658,14 +655,34 @@ namespace ShellCommands {
|
|||
}
|
||||
}
|
||||
|
||||
static std::unique_ptr<IOPShellModule::CommandGroup> sPluginsGroup;
|
||||
void InitPluginsCommandGroup() {
|
||||
// Must be in memory while commands are active
|
||||
sPluginsGroup = std::make_unique<IOPShellModule::CommandGroup>("plugins", "Manage aroma plugins");
|
||||
if (const auto res = sPluginsGroup->RegisterGroup(); res != IOPSHELL_MODULE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to register \"aroma plugins\" command: %s", IOPShellModule::GetErrorString(res));
|
||||
}
|
||||
|
||||
if (const auto res = sPluginsGroup->AddCommand("heap_usage", PrintHeapUsage, "Show current heap usage for tracked plugins"); res != IOPSHELL_MODULE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to create \"aroma plugins heap_usage\" command: %s", IOPShellModule::GetErrorString(res));
|
||||
}
|
||||
if (const auto res = sPluginsGroup->AddRawCommand("list", ListPlugins, "Lists active plugins", "Usage: \"list -a\" to list all plugins"); res != IOPSHELL_MODULE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to create \"aroma plugins list\" command: %s", IOPShellModule::GetErrorString(res));
|
||||
}
|
||||
if (auto res = sPluginsGroup->AddCommand("details", PluginDetails, "Shows details for plugins"); res != IOPSHELL_MODULE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to create \"aroma plugins details\" command: %s", IOPShellModule::GetErrorString(res));
|
||||
} else {
|
||||
if (res = sPluginsGroup->AddAlias("details", "show"); res != IOPSHELL_MODULE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to create \"aroma plugins details\" alias \"aroma plugins show\": %s", IOPShellModule::GetErrorString(res));
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto res = sPluginsGroup->RegisterGroup(); res != IOPSHELL_MODULE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to register \"aroma plugins\" command: %s", IOPShellModule::GetErrorString(res));
|
||||
}
|
||||
}
|
||||
|
||||
void Init() {
|
||||
sPluginGroup = std::make_unique<IOPShellModule::CommandGroup>("plugins", "Manage aroma plugins");
|
||||
|
||||
sPluginGroup->AddCommand("heap_usage", PrintHeapUsage, "Show current heap usage for tracked plugins");
|
||||
|
||||
sPluginGroup->AddRawCommand("list", ListPlugins, "Lists active plugins", "Usage: \"list -a\" to list all plugins");
|
||||
sPluginGroup->AddCommand("details", PluginDetails, "Shows details for plugins");
|
||||
|
||||
sPluginCmdHandle = sPluginGroup->Register();
|
||||
InitPluginsCommandGroup();
|
||||
}
|
||||
} // namespace ShellCommands
|
||||
|
|
@ -284,8 +284,11 @@ WUMS_APPLICATION_STARTS() {
|
|||
// Check which plugins are already loaded and which needs to be
|
||||
for (const auto &pluginLoadWrapper : filteredLoadOnNextLaunch) {
|
||||
const auto &pluginNeedsNoReloadFn = [&pluginLoadWrapper](const PluginContainer &container) {
|
||||
bool willBeLinked = pluginLoadWrapper.isLoadAndLink();
|
||||
return (container.getPluginDataCopy()->getHandle() == pluginLoadWrapper.getPluginData()->getHandle()) &&
|
||||
(container.isLinkedAndLoaded() == pluginLoadWrapper.isLoadAndLink());
|
||||
(container.isLinkedAndLoaded() == pluginLoadWrapper.isLoadAndLink()) &&
|
||||
// Only check if tracking is enabled if the plugin will actually be loaded.
|
||||
(!willBeLinked || (container.isUsingTrackingPluginHeapMemoryAllocator() == pluginLoadWrapper.isHeapTrackingEnabled()));
|
||||
};
|
||||
// Check if the plugin data is already loaded
|
||||
if (const auto it = std::ranges::find_if(gLoadedPlugins, pluginNeedsNoReloadFn);
|
||||
|
|
|
|||
|
|
@ -16,14 +16,19 @@
|
|||
|
||||
#include <optional>
|
||||
|
||||
PluginContainer::PluginContainer(PluginMetaInformation metaInformation, PluginLinkInformation pluginLinkInformation, std::shared_ptr<PluginData> pluginData)
|
||||
PluginContainer::PluginContainer(PluginMetaInformation metaInformation, PluginLinkInformation pluginLinkInformation, std::shared_ptr<PluginData> pluginData, std::optional<PluginMetaInformation::HeapTrackingOptions> heapTrackingOptions)
|
||||
: mMetaInformation(std::move(metaInformation)),
|
||||
mPluginLinkInformation(std::move(pluginLinkInformation)),
|
||||
mPluginData(std::move(pluginData)) {
|
||||
// Abuse this as a stable handle that references itself and survives std::move
|
||||
*mHandle = reinterpret_cast<uint32_t>(mHandle.get());
|
||||
|
||||
if (const bool res = useTrackingPluginHeapMemoryAllocator(mMetaInformation.getHeapTrackingOptions()); !res) {
|
||||
auto trackingOptions = mMetaInformation.getHeapTrackingOptions();
|
||||
if (heapTrackingOptions) {
|
||||
trackingOptions = *heapTrackingOptions;
|
||||
}
|
||||
|
||||
if (const bool res = useTrackingPluginHeapMemoryAllocator(trackingOptions); !res) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to set heap tracking options for \"%s\"", mMetaInformation.getName().c_str());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class PluginData;
|
|||
|
||||
class PluginContainer {
|
||||
public:
|
||||
PluginContainer(PluginMetaInformation metaInformation, PluginLinkInformation pluginLinkInformation, std::shared_ptr<PluginData> pluginData);
|
||||
PluginContainer(PluginMetaInformation metaInformation, PluginLinkInformation pluginLinkInformation, std::shared_ptr<PluginData> pluginData, std::optional<PluginMetaInformation::HeapTrackingOptions> heapTrackingOptions);
|
||||
|
||||
PluginContainer(const PluginContainer &) = delete;
|
||||
|
||||
|
|
@ -73,11 +73,6 @@ public:
|
|||
|
||||
[[nodiscard]] uint32_t getButtonComboManagerHandle() const;
|
||||
|
||||
/**
|
||||
* @return Returns true if setting the value was successful
|
||||
*/
|
||||
bool useTrackingPluginHeapMemoryAllocator(PluginMetaInformation::HeapTrackingOptions options);
|
||||
|
||||
[[nodiscard]] bool isUsingTrackingPluginHeapMemoryAllocator() const;
|
||||
|
||||
[[nodiscard]] const IPluginHeapMemoryAllocator &getMemoryAllocator() const;
|
||||
|
|
@ -87,6 +82,11 @@ public:
|
|||
[[nodiscard]] size_t getMemoryFootprint() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @return Returns true if setting the value was successful
|
||||
*/
|
||||
bool useTrackingPluginHeapMemoryAllocator(PluginMetaInformation::HeapTrackingOptions options);
|
||||
|
||||
PluginMetaInformation mMetaInformation;
|
||||
PluginLinkInformation mPluginLinkInformation;
|
||||
std::optional<TrackingPluginHeapMemoryAllocator> mTrackingHeapAllocatorOpt;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,11 @@ std::vector<PluginLoadWrapper> PluginDataFactory::loadDir(const std::string_view
|
|||
if (inactivePluginsFilenames.contains(fileName)) {
|
||||
shouldBeLoadedAndLinked = false;
|
||||
}
|
||||
result.emplace_back(std::move(pluginData), shouldBeLoadedAndLinked);
|
||||
bool enableHeapTracking = false;
|
||||
#ifdef DEBUG
|
||||
enableHeapTracking = true;
|
||||
#endif
|
||||
result.emplace_back(std::move(pluginData), shouldBeLoadedAndLinked, enableHeapTracking);
|
||||
} else {
|
||||
auto errMsg = string_format("Failed to load plugin: %s", full_file_path.c_str());
|
||||
DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str());
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "PluginMetaInformation.h"
|
||||
|
||||
|
||||
#include <memory>
|
||||
|
||||
class PluginData;
|
||||
|
||||
class PluginLoadWrapper {
|
||||
public:
|
||||
PluginLoadWrapper(std::shared_ptr<PluginData> pluginData, const bool linkAndLoad) : mPluginData(std::move(pluginData)), mIsLoadAndLink(linkAndLoad) {
|
||||
PluginLoadWrapper(std::shared_ptr<PluginData> pluginData, const bool linkAndLoad, const bool heapTrackingEnabled = false)
|
||||
: mPluginData(std::move(pluginData)), mIsLoadAndLink(linkAndLoad), mIsHeapTrackingEnabled(heapTrackingEnabled) {
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::shared_ptr<PluginData> &getPluginData() const {
|
||||
|
|
@ -17,7 +21,19 @@ public:
|
|||
return mIsLoadAndLink;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isHeapTrackingEnabled() const {
|
||||
return mIsHeapTrackingEnabled;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::optional<PluginMetaInformation::HeapTrackingOptions> getHeapTrackingOptions() const {
|
||||
if (mIsHeapTrackingEnabled) {
|
||||
return PluginMetaInformation::HeapTrackingOptions::TRACK_HEAP_OPTIONS_TRACK_SIZE_AND_COLLECT_STACK_TRACES;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<PluginData> mPluginData;
|
||||
bool mIsLoadAndLink = false;
|
||||
bool mIsLoadAndLink = false;
|
||||
bool mIsHeapTrackingEnabled = false;
|
||||
};
|
||||
|
|
@ -2,16 +2,18 @@
|
|||
|
||||
#include "config/WUPSConfig.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
ConfigDisplayItem::ConfigDisplayItem(GeneralConfigInformation &info,
|
||||
std::unique_ptr<WUPSConfigAPIBackend::WUPSConfig> config,
|
||||
const bool isActive) : mConfig(std::move(config)),
|
||||
mInfo(std::move(info)),
|
||||
mIsActivePlugin(isActive),
|
||||
mInitialIsActivePlugin(isActive) {
|
||||
const bool isActive,
|
||||
const bool isHeapTracking) : mConfig(std::move(config)),
|
||||
mInfo(std::move(info)),
|
||||
mIsActivePlugin(isActive),
|
||||
mInitialIsActivePlugin(isActive),
|
||||
mIsHeapTrackingEnabled(isHeapTracking),
|
||||
mInitialIsHeapTrackingEnabled(isHeapTracking) {
|
||||
assert(mConfig);
|
||||
}
|
||||
|
||||
|
|
@ -33,4 +35,16 @@ void ConfigDisplayItem::toggleIsActivePlugin() {
|
|||
|
||||
void ConfigDisplayItem::resetIsActivePlugin() {
|
||||
mIsActivePlugin = mInitialIsActivePlugin;
|
||||
}
|
||||
|
||||
bool ConfigDisplayItem::isHeapTrackingEnabled() const {
|
||||
return mIsHeapTrackingEnabled;
|
||||
}
|
||||
|
||||
void ConfigDisplayItem::toggleIsHeapTrackingEnabled() {
|
||||
mIsHeapTrackingEnabled = !mIsHeapTrackingEnabled;
|
||||
}
|
||||
|
||||
void ConfigDisplayItem::resetIsHeapTrackingEnabled() {
|
||||
mIsHeapTrackingEnabled = mInitialIsHeapTrackingEnabled;
|
||||
}
|
||||
|
|
@ -15,21 +15,25 @@ struct GeneralConfigInformation {
|
|||
|
||||
class ConfigDisplayItem {
|
||||
public:
|
||||
ConfigDisplayItem(GeneralConfigInformation &info, std::unique_ptr<WUPSConfigAPIBackend::WUPSConfig> config, bool isActive);
|
||||
ConfigDisplayItem(GeneralConfigInformation &info, std::unique_ptr<WUPSConfigAPIBackend::WUPSConfig> config, bool isActive, bool isHeapTracking = false);
|
||||
|
||||
[[nodiscard]] const GeneralConfigInformation &getConfigInformation() const;
|
||||
|
||||
[[nodiscard]] const WUPSConfigAPIBackend::WUPSConfig &getConfig() const;
|
||||
|
||||
[[nodiscard]] bool isActivePlugin() const;
|
||||
|
||||
void toggleIsActivePlugin();
|
||||
|
||||
void resetIsActivePlugin();
|
||||
|
||||
[[nodiscard]] bool isHeapTrackingEnabled() const;
|
||||
void toggleIsHeapTrackingEnabled();
|
||||
void resetIsHeapTrackingEnabled();
|
||||
|
||||
private:
|
||||
std::unique_ptr<WUPSConfigAPIBackend::WUPSConfig> mConfig;
|
||||
GeneralConfigInformation mInfo;
|
||||
bool mIsActivePlugin;
|
||||
bool mInitialIsActivePlugin;
|
||||
bool mIsHeapTrackingEnabled;
|
||||
bool mInitialIsHeapTrackingEnabled;
|
||||
};
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "ConfigRenderer.h"
|
||||
#include "ConfigRendererStates.h"
|
||||
|
||||
#include "CategoryRenderer.h"
|
||||
#include "ConfigDisplayItem.h"
|
||||
|
|
@ -11,15 +12,11 @@
|
|||
#include "utils/logger.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
ConfigRenderer::ConfigRenderer(std::vector<ConfigDisplayItem> &&vec) : mConfigs(std::move(vec)) {
|
||||
std::ranges::copy(mConfigs,
|
||||
std::back_inserter(mAllConfigs));
|
||||
std::ranges::copy_if(mConfigs,
|
||||
std::back_inserter(mActiveConfigs),
|
||||
[&](const auto &value) {
|
||||
return value.isActivePlugin();
|
||||
});
|
||||
SetListState(std::make_unique<DefaultListState>());
|
||||
}
|
||||
|
||||
ConfigRenderer::~ConfigRenderer() = default;
|
||||
|
|
@ -44,6 +41,10 @@ ConfigSubState ConfigRenderer::Update(Input &input, const WUPSConfigSimplePadDat
|
|||
if (complexInputData.vpad.vpadError == VPAD_READ_SUCCESS && complexInputData.vpad.data.hold != 0) {
|
||||
mLastInputWasOnWiimote = false;
|
||||
}
|
||||
|
||||
// Reset transient return state
|
||||
mNextSubState = SUB_STATE_RUNNING;
|
||||
|
||||
switch (mState) {
|
||||
case STATE_MAIN:
|
||||
return UpdateStateMain(input);
|
||||
|
|
@ -51,9 +52,9 @@ ConfigSubState ConfigRenderer::Update(Input &input, const WUPSConfigSimplePadDat
|
|||
if (mCategoryRenderer) {
|
||||
auto subResult = mCategoryRenderer->Update(input, simpleInputData, complexInputData);
|
||||
if (subResult != SUB_STATE_RUNNING) {
|
||||
mNeedRedraw = true;
|
||||
mActivePluginsDirty = false;
|
||||
mState = STATE_MAIN;
|
||||
mNeedRedraw = true;
|
||||
mPluginListDirty = false;
|
||||
mState = STATE_MAIN;
|
||||
return SUB_STATE_RUNNING;
|
||||
}
|
||||
return SUB_STATE_RUNNING;
|
||||
|
|
@ -99,90 +100,50 @@ void ConfigRenderer::ResetNeedsRedraw() {
|
|||
}
|
||||
}
|
||||
|
||||
void ConfigRenderer::RequestRedraw() {
|
||||
mNeedRedraw = true;
|
||||
}
|
||||
|
||||
ConfigSubState ConfigRenderer::UpdateStateMain(const Input &input) {
|
||||
auto &configs = GetConfigList();
|
||||
if (!mListState) return SUB_STATE_ERROR;
|
||||
|
||||
auto &configs = GetDisplayedConfigList();
|
||||
const auto prevSelectedItem = mCursorPos;
|
||||
auto totalElementSize = (int32_t) configs.size();
|
||||
|
||||
const auto &savePendingConfigFn = [&configs, this]() {
|
||||
for (const auto &element : configs) {
|
||||
CallOnCloseCallback(element.get().getConfigInformation(), element.get().getConfig());
|
||||
}
|
||||
};
|
||||
// Delegate specific inputs to the State
|
||||
bool inputHandled = mListState->HandleInput(*this, input);
|
||||
|
||||
auto totalElementSize = (int32_t) configs.size();
|
||||
if (mNextSubState != SUB_STATE_RUNNING) {
|
||||
return mNextSubState;
|
||||
}
|
||||
|
||||
if (inputHandled) {
|
||||
return SUB_STATE_RUNNING;
|
||||
}
|
||||
|
||||
// Handle Navigation (Common to all states)
|
||||
if (input.data.buttons_d & Input::eButtons::BUTTON_DOWN) {
|
||||
mCursorPos++;
|
||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_LEFT) {
|
||||
// Paging up
|
||||
mCursorPos -= MAX_BUTTONS_ON_SCREEN - 1;
|
||||
// Don't jump past the top
|
||||
if (mCursorPos < 0)
|
||||
mCursorPos = 0;
|
||||
if (mCursorPos < 0) mCursorPos = 0;
|
||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_RIGHT) {
|
||||
// Paging down
|
||||
mCursorPos += MAX_BUTTONS_ON_SCREEN - 1;
|
||||
// Don't jump past the bottom
|
||||
if (mCursorPos >= totalElementSize)
|
||||
mCursorPos = totalElementSize - 1;
|
||||
if (mCursorPos >= totalElementSize) mCursorPos = totalElementSize - 1;
|
||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_UP) {
|
||||
mCursorPos--;
|
||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_PLUS) {
|
||||
if (mSetActivePluginsMode) {
|
||||
mNeedRedraw = true;
|
||||
mCategoryRenderer.reset();
|
||||
savePendingConfigFn();
|
||||
return SUB_STATE_RETURN_WITH_PLUGIN_RELOAD;
|
||||
}
|
||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_X) {
|
||||
if (!mSetActivePluginsMode && !mAllConfigs.empty()) {
|
||||
mSetActivePluginsMode = true;
|
||||
mNeedRedraw = true;
|
||||
return SUB_STATE_RUNNING;
|
||||
}
|
||||
} else if (input.data.buttons_d & Input::eButtons::BUTTON_A) {
|
||||
if (mSetActivePluginsMode) {
|
||||
mActivePluginsDirty = true;
|
||||
mNeedRedraw = true;
|
||||
configs[mCursorPos].get().toggleIsActivePlugin();
|
||||
return SUB_STATE_RUNNING;
|
||||
} else if (!configs.empty()) {
|
||||
if (mCursorPos != mCurrentOpen) {
|
||||
mCategoryRenderer.reset();
|
||||
mCategoryRenderer = make_unique_nothrow<CategoryRenderer>(&(configs[mCursorPos].get().getConfigInformation()), &(configs[mCursorPos].get().getConfig()), true);
|
||||
}
|
||||
mNeedRedraw = true;
|
||||
mCurrentOpen = mCursorPos;
|
||||
mState = STATE_SUB;
|
||||
return SUB_STATE_RUNNING;
|
||||
}
|
||||
} else if (input.data.buttons_d & (Input::eButtons::BUTTON_B | Input::eButtons::BUTTON_HOME)) {
|
||||
if (mSetActivePluginsMode) {
|
||||
for (auto &cur : mConfigs) {
|
||||
cur.resetIsActivePlugin();
|
||||
}
|
||||
mActivePluginsDirty = false;
|
||||
mNeedRedraw = true;
|
||||
mSetActivePluginsMode = false;
|
||||
return SUB_STATE_RUNNING;
|
||||
} else {
|
||||
mNeedRedraw = true;
|
||||
mCategoryRenderer.reset();
|
||||
savePendingConfigFn();
|
||||
return SUB_STATE_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
if (mCursorPos < 0) {
|
||||
mCursorPos = totalElementSize - 1;
|
||||
} else if (mCursorPos >= totalElementSize) {
|
||||
mCursorPos = 0;
|
||||
}
|
||||
if (mCursorPos < 0) {
|
||||
if (totalElementSize > 0) {
|
||||
if (mCursorPos < 0) mCursorPos = totalElementSize - 1;
|
||||
else if (mCursorPos >= totalElementSize)
|
||||
mCursorPos = 0;
|
||||
} else {
|
||||
mCursorPos = 0;
|
||||
}
|
||||
|
||||
// Adjust the render offset when reaching the boundaries
|
||||
// Adjust render offset
|
||||
if (mCursorPos < mRenderOffset) {
|
||||
mRenderOffset = mCursorPos;
|
||||
} else if (mCursorPos >= mRenderOffset + MAX_BUTTONS_ON_SCREEN - 1) {
|
||||
|
|
@ -197,71 +158,70 @@ ConfigSubState ConfigRenderer::UpdateStateMain(const Input &input) {
|
|||
}
|
||||
|
||||
void ConfigRenderer::RenderStateMain() const {
|
||||
auto &configs = GetConfigList();
|
||||
auto &configs = GetDisplayedConfigList();
|
||||
|
||||
DrawUtils::beginDraw();
|
||||
DrawUtils::clear(COLOR_BACKGROUND);
|
||||
|
||||
auto totalElementSize = (int32_t) configs.size();
|
||||
int start = std::max(0, mRenderOffset);
|
||||
int end = std::min(start + MAX_BUTTONS_ON_SCREEN, totalElementSize);
|
||||
|
||||
// Calculate the range of items to display
|
||||
int start = std::max(0, mRenderOffset);
|
||||
int end = std::min(start + MAX_BUTTONS_ON_SCREEN, totalElementSize);
|
||||
|
||||
if (mActiveConfigs.empty() && !mSetActivePluginsMode) {
|
||||
if (configs.empty()) {
|
||||
DrawUtils::setFontSize(24);
|
||||
std::string noConfigText = "No active plugins";
|
||||
uint32_t szNoConfig = DrawUtils::getTextWidth(noConfigText.data());
|
||||
std::string noConfigText = "No plugins available";
|
||||
|
||||
if (!mAllConfigs.empty()) {
|
||||
if (!mListState->IsMainView()) {
|
||||
noConfigText = "No active plugins";
|
||||
}
|
||||
|
||||
uint32_t szNoConfig = DrawUtils::getTextWidth(noConfigText.data());
|
||||
|
||||
if (mListState->IsMainView()) {
|
||||
DrawUtils::print((SCREEN_WIDTH / 2) - (szNoConfig / 2), (SCREEN_HEIGHT / 2), noConfigText.data());
|
||||
} else {
|
||||
const auto activateHint = string_format("Press %s to activate inactive plugins", mLastInputWasOnWiimote ? "\uE048" : "\uE002");
|
||||
const auto szHint = DrawUtils::getTextWidth(activateHint.c_str());
|
||||
|
||||
DrawUtils::print((SCREEN_WIDTH / 2) - (szNoConfig / 2), (SCREEN_HEIGHT / 2) - 16, noConfigText.data());
|
||||
DrawUtils::print((SCREEN_WIDTH / 2) - (szHint / 2), (SCREEN_HEIGHT / 2) + 16, activateHint.data());
|
||||
} else {
|
||||
DrawUtils::print((SCREEN_WIDTH / 2) - (szNoConfig / 2), (SCREEN_HEIGHT / 2), noConfigText.data());
|
||||
}
|
||||
} else {
|
||||
uint32_t yOffset = 8 + 24 + 8 + 4;
|
||||
for (int32_t i = start; i < end; i++) {
|
||||
DrawConfigEntry(yOffset, configs[i].get().getConfigInformation(), i == mCursorPos, configs[i].get().isActivePlugin());
|
||||
DrawConfigEntry(yOffset, configs[i].get(), i == mCursorPos);
|
||||
yOffset += 42 + 8;
|
||||
}
|
||||
}
|
||||
|
||||
DrawUtils::setFontColor(COLOR_TEXT);
|
||||
|
||||
// draw top bar
|
||||
// Top Bar
|
||||
DrawUtils::setFontSize(24);
|
||||
if (mSetActivePluginsMode) {
|
||||
DrawUtils::print(16, 6 + 24, "Please select the plugins that should be active");
|
||||
} else {
|
||||
DrawUtils::print(16, 6 + 24, "Wii U Plugin System Config Menu");
|
||||
DrawUtils::print(16, 6 + 24, mListState->GetTitle().c_str());
|
||||
|
||||
auto countInactivePlugins = mAllConfigs.size() - mActiveConfigs.size();
|
||||
if (mListState->IsMainView()) {
|
||||
auto countInactivePlugins = mConfigs.size() - mFilteredConfigs.size();
|
||||
if (countInactivePlugins > 0) {
|
||||
DrawUtils::setFontSize(14);
|
||||
const std::string plugin_unloaded = string_format("Found %d inactive plugins", countInactivePlugins);
|
||||
DrawUtils::print(SCREEN_WIDTH - 16 - DrawUtils::getTextWidth(MODULE_VERSION_FULL) - 32, 8 + 24, plugin_unloaded.c_str(), true);
|
||||
}
|
||||
}
|
||||
|
||||
DrawUtils::setFontSize(18);
|
||||
DrawUtils::print(SCREEN_WIDTH - 16, 8 + 24, MODULE_VERSION_FULL, true);
|
||||
DrawUtils::drawRectFilled(8, 8 + 24 + 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_BLACK);
|
||||
|
||||
// draw bottom bar
|
||||
// Bottom Bar
|
||||
DrawUtils::drawRectFilled(8, SCREEN_HEIGHT - 24 - 8 - 4, SCREEN_WIDTH - 8 * 2, 3, COLOR_BLACK);
|
||||
DrawUtils::setFontSize(18);
|
||||
DrawUtils::print(16, SCREEN_HEIGHT - 10, "\uE07D/\uE07E Navigate ");
|
||||
if (mSetActivePluginsMode) {
|
||||
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 10, "\uE000 Toggle | \uE045 Apply", true);
|
||||
} else if (totalElementSize > 0) {
|
||||
const auto text = string_format("\ue000 Select | %s Manage plugins", mLastInputWasOnWiimote ? "\uE048" : "\uE002");
|
||||
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 10, text.c_str(), true);
|
||||
}
|
||||
|
||||
// draw scroll indicator
|
||||
if (totalElementSize > 0) {
|
||||
DrawUtils::print(16, SCREEN_HEIGHT - 10, "\uE07D/\uE07E Navigate ");
|
||||
}
|
||||
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 10, mListState->GetBottomBar(mLastInputWasOnWiimote).c_str(), true);
|
||||
|
||||
// Scroll Indicator
|
||||
DrawUtils::setFontSize(24);
|
||||
if (end < totalElementSize) {
|
||||
DrawUtils::print(SCREEN_WIDTH / 2 + 12, SCREEN_HEIGHT - 32, "\ufe3e", true);
|
||||
|
|
@ -270,18 +230,15 @@ void ConfigRenderer::RenderStateMain() const {
|
|||
DrawUtils::print(SCREEN_WIDTH / 2 + 12, 32 + 20, "\ufe3d", true);
|
||||
}
|
||||
|
||||
// draw home button
|
||||
// Home Button
|
||||
DrawUtils::setFontSize(18);
|
||||
const char *exitHint = "\ue044 Exit";
|
||||
if (mSetActivePluginsMode) {
|
||||
exitHint = "\ue001 Abort";
|
||||
}
|
||||
const char *exitHint = mListState->IsMainView() ? "\ue001 Abort" : "\ue044 Exit";
|
||||
DrawUtils::print(SCREEN_WIDTH / 2 + DrawUtils::getTextWidth(exitHint) / 2, SCREEN_HEIGHT - 10, exitHint, true);
|
||||
|
||||
DrawUtils::endDraw();
|
||||
}
|
||||
|
||||
void ConfigRenderer::DrawConfigEntry(uint32_t yOffset, const GeneralConfigInformation &configInformation, bool isHighlighted, bool isActive) const {
|
||||
void ConfigRenderer::DrawConfigEntry(uint32_t yOffset, const ConfigDisplayItem &item, bool isHighlighted) const {
|
||||
DrawUtils::setFontColor(COLOR_TEXT);
|
||||
|
||||
if (isHighlighted) {
|
||||
|
|
@ -291,18 +248,15 @@ void ConfigRenderer::DrawConfigEntry(uint32_t yOffset, const GeneralConfigInform
|
|||
}
|
||||
|
||||
int textXOffset = 16 * 2;
|
||||
if (mSetActivePluginsMode) {
|
||||
DrawUtils::setFontSize(24);
|
||||
if (isActive) {
|
||||
DrawUtils::print(textXOffset, yOffset + 8 + 24, "\u25C9");
|
||||
} else {
|
||||
DrawUtils::print(textXOffset, yOffset + 8 + 24, "\u25CE");
|
||||
}
|
||||
|
||||
// Delegate Icon drawing to state, returns true if icon was drawn
|
||||
if (mListState->RenderItemIcon(item, textXOffset, yOffset + 8 + 24)) {
|
||||
textXOffset += 32;
|
||||
}
|
||||
|
||||
DrawUtils::setFontSize(24);
|
||||
|
||||
const auto &configInformation = item.getConfigInformation();
|
||||
DrawUtils::print(textXOffset, yOffset + 8 + 24, configInformation.name.c_str());
|
||||
uint32_t sz = DrawUtils::getTextWidth(configInformation.name.c_str());
|
||||
DrawUtils::setFontSize(12);
|
||||
|
|
@ -310,6 +264,82 @@ void ConfigRenderer::DrawConfigEntry(uint32_t yOffset, const GeneralConfigInform
|
|||
DrawUtils::print(SCREEN_WIDTH - 16 * 2, yOffset + 8 + 24, configInformation.version.c_str(), true);
|
||||
}
|
||||
|
||||
void ConfigRenderer::SetListState(std::unique_ptr<ConfigListState> state) {
|
||||
mListState = std::move(state);
|
||||
mNeedRedraw = true;
|
||||
mCursorPos = 0;
|
||||
mRenderOffset = 0;
|
||||
// Fallback to "show all"
|
||||
std::function<bool(const ConfigDisplayItem &)> pred = [](const auto &) { return true; };
|
||||
if (mListState) {
|
||||
pred = mListState->GetConfigFilter();
|
||||
}
|
||||
// Copy references into filteredConfigView
|
||||
mFilteredConfigs.clear();
|
||||
std::ranges::copy_if(mConfigs, std::back_inserter(mFilteredConfigs),
|
||||
std::move(pred));
|
||||
}
|
||||
|
||||
const std::vector<ConfigDisplayItem> &ConfigRenderer::GetConfigItems() {
|
||||
return mConfigs;
|
||||
}
|
||||
|
||||
std::vector<std::reference_wrapper<ConfigDisplayItem>> &ConfigRenderer::GetFilteredConfigItems() {
|
||||
return mFilteredConfigs;
|
||||
}
|
||||
|
||||
int32_t ConfigRenderer::GetCursorPos() const {
|
||||
return mCursorPos;
|
||||
}
|
||||
|
||||
void ConfigRenderer::EnterSelectedCategory() {
|
||||
auto &items = GetDisplayedConfigList();
|
||||
if (mCursorPos < 0 || static_cast<size_t>(mCursorPos) >= items.size()) return;
|
||||
|
||||
if (mCursorPos != mCurrentOpen) {
|
||||
mCategoryRenderer.reset();
|
||||
mCategoryRenderer = make_unique_nothrow<CategoryRenderer>(&(items[mCursorPos].get().getConfigInformation()), &(items[mCursorPos].get().getConfig()), true);
|
||||
}
|
||||
mNeedRedraw = true;
|
||||
mCurrentOpen = mCursorPos;
|
||||
mState = STATE_SUB;
|
||||
}
|
||||
|
||||
void ConfigRenderer::SavePendingConfigs() {
|
||||
for (const auto &element : mConfigs) {
|
||||
CallOnCloseCallback(element.getConfigInformation(), element.getConfig());
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigRenderer::Exit() {
|
||||
mNeedRedraw = true;
|
||||
mCategoryRenderer.reset();
|
||||
SavePendingConfigs();
|
||||
mNextSubState = SUB_STATE_RETURN;
|
||||
}
|
||||
|
||||
void ConfigRenderer::ExitWithReload() {
|
||||
mNeedRedraw = true;
|
||||
mCategoryRenderer.reset();
|
||||
SavePendingConfigs();
|
||||
mNextSubState = SUB_STATE_RETURN_WITH_PLUGIN_RELOAD;
|
||||
}
|
||||
|
||||
void ConfigRenderer::SetPluginsListDirty(bool dirty) {
|
||||
mPluginListDirty = dirty;
|
||||
}
|
||||
|
||||
bool ConfigRenderer::GetPluginsListIfChanged(std::vector<PluginLoadWrapper> &result) {
|
||||
if (mPluginListDirty) {
|
||||
result.clear();
|
||||
for (const auto &cur : mConfigs) {
|
||||
result.emplace_back(cur.getConfigInformation().pluginData, cur.isActivePlugin(), cur.isHeapTrackingEnabled());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConfigRenderer::CallOnCloseCallback(const GeneralConfigInformation &info, const std::vector<std::unique_ptr<WUPSConfigAPIBackend::WUPSConfigCategory>> &categories) {
|
||||
for (const auto &cat : categories) {
|
||||
if (!cat->getCategories().empty()) {
|
||||
|
|
@ -321,18 +351,6 @@ void ConfigRenderer::CallOnCloseCallback(const GeneralConfigInformation &info, c
|
|||
}
|
||||
}
|
||||
|
||||
bool ConfigRenderer::GetActivePluginsIfChanged(std::vector<PluginLoadWrapper> &result) {
|
||||
if (mActivePluginsDirty) {
|
||||
std::vector<std::string> inactive_plugins;
|
||||
result.clear();
|
||||
for (const auto &cur : mConfigs) {
|
||||
result.emplace_back(cur.getConfigInformation().pluginData, cur.isActivePlugin());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConfigRenderer::CallOnCloseCallback(const GeneralConfigInformation &info, const WUPSConfigAPIBackend::WUPSConfig &config) {
|
||||
CallOnCloseCallback(info, config.getCategories());
|
||||
for (const auto &item : config.getItems()) {
|
||||
|
|
@ -340,9 +358,6 @@ void ConfigRenderer::CallOnCloseCallback(const GeneralConfigInformation &info, c
|
|||
}
|
||||
}
|
||||
|
||||
const std::vector<std::reference_wrapper<ConfigDisplayItem>> &ConfigRenderer::GetConfigList() const {
|
||||
if (mSetActivePluginsMode) {
|
||||
return mAllConfigs;
|
||||
}
|
||||
return mActiveConfigs;
|
||||
}
|
||||
const std::vector<std::reference_wrapper<ConfigDisplayItem>> &ConfigRenderer::GetDisplayedConfigList() const {
|
||||
return mFilteredConfigs;
|
||||
}
|
||||
|
|
@ -5,11 +5,11 @@
|
|||
|
||||
#include <wups/config.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace WUPSConfigAPIBackend {
|
||||
class WUPSConfig;
|
||||
class WUPSConfigCategory;
|
||||
|
|
@ -18,6 +18,8 @@ class PluginLoadWrapper;
|
|||
class Input;
|
||||
class CategoryRenderer;
|
||||
class ConfigDisplayItem;
|
||||
class ConfigListState;
|
||||
|
||||
class ConfigRenderer {
|
||||
|
||||
public:
|
||||
|
|
@ -30,22 +32,31 @@ public:
|
|||
void Render() const;
|
||||
|
||||
[[nodiscard]] bool NeedsRedraw() const;
|
||||
|
||||
void ResetNeedsRedraw();
|
||||
void RequestRedraw();
|
||||
|
||||
bool GetActivePluginsIfChanged(std::vector<PluginLoadWrapper> &result);
|
||||
bool GetPluginsListIfChanged(std::vector<PluginLoadWrapper> &result);
|
||||
|
||||
void SetListState(std::unique_ptr<ConfigListState> state);
|
||||
const std::vector<ConfigDisplayItem> &GetConfigItems();
|
||||
std::vector<std::reference_wrapper<ConfigDisplayItem>> &GetFilteredConfigItems(); // Mutable access
|
||||
int32_t GetCursorPos() const;
|
||||
void EnterSelectedCategory();
|
||||
void Exit();
|
||||
void ExitWithReload();
|
||||
void SetPluginsListDirty(bool dirty);
|
||||
|
||||
private:
|
||||
ConfigSubState UpdateStateMain(const Input &input);
|
||||
|
||||
void RenderStateMain() const;
|
||||
|
||||
void DrawConfigEntry(uint32_t yOffset, const GeneralConfigInformation &configInformation, bool isHighlighted, bool isActive) const;
|
||||
void DrawConfigEntry(uint32_t yOffset, const ConfigDisplayItem &item, bool isHighlighted) const;
|
||||
|
||||
void CallOnCloseCallback(const GeneralConfigInformation &info, const std::vector<std::unique_ptr<WUPSConfigAPIBackend::WUPSConfigCategory>> &categories);
|
||||
void CallOnCloseCallback(const GeneralConfigInformation &info, const WUPSConfigAPIBackend::WUPSConfig &config);
|
||||
void SavePendingConfigs();
|
||||
|
||||
[[nodiscard]] const std::vector<std::reference_wrapper<ConfigDisplayItem>> &GetConfigList() const;
|
||||
|
||||
[[nodiscard]] const std::vector<std::reference_wrapper<ConfigDisplayItem>> &GetDisplayedConfigList() const;
|
||||
|
||||
enum State {
|
||||
STATE_MAIN = 0,
|
||||
|
|
@ -53,18 +64,20 @@ private:
|
|||
};
|
||||
|
||||
std::vector<ConfigDisplayItem> mConfigs;
|
||||
std::vector<std::reference_wrapper<ConfigDisplayItem>> mAllConfigs;
|
||||
std::vector<std::reference_wrapper<ConfigDisplayItem>> mActiveConfigs;
|
||||
mutable std::vector<std::reference_wrapper<ConfigDisplayItem>> mFilteredConfigs;
|
||||
|
||||
std::unique_ptr<ConfigListState> mListState;
|
||||
std::unique_ptr<CategoryRenderer> mCategoryRenderer;
|
||||
|
||||
State mState = STATE_MAIN;
|
||||
// Used to signal the main loop to return a specific state
|
||||
ConfigSubState mNextSubState = SUB_STATE_RUNNING;
|
||||
|
||||
int32_t mCursorPos = 0;
|
||||
int32_t mRenderOffset = 0;
|
||||
int32_t mCurrentOpen = -1;
|
||||
|
||||
bool mNeedRedraw = true;
|
||||
bool mSetActivePluginsMode = false;
|
||||
bool mActivePluginsDirty = false;
|
||||
bool mPluginListDirty = false;
|
||||
bool mLastInputWasOnWiimote = false;
|
||||
};
|
||||
};
|
||||
177
source/utils/config/ConfigRendererStates.cpp
Normal file
177
source/utils/config/ConfigRendererStates.cpp
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
#include "ConfigRendererStates.h"
|
||||
#include "ConfigDisplayItem.h"
|
||||
#include "ConfigRenderer.h"
|
||||
#include "utils/DrawUtils.h"
|
||||
#include "utils/StringTools.h"
|
||||
#include "utils/input/Input.h"
|
||||
|
||||
std::function<bool(const ConfigDisplayItem &)> DefaultListState::GetConfigFilter() const {
|
||||
return [](const auto &item) { return item.isActivePlugin(); };
|
||||
}
|
||||
|
||||
bool DefaultListState::IsMainView() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DefaultListState::HandleInput(ConfigRenderer &renderer, const Input &input) {
|
||||
if (input.data.buttons_d & Input::eButtons::BUTTON_DOWN) {
|
||||
// Hidden Combo: L + R + Down
|
||||
constexpr auto COMBO_HOLD = Input::eButtons::BUTTON_L | Input::eButtons::BUTTON_R;
|
||||
if ((input.data.buttons_h & COMBO_HOLD) == COMBO_HOLD) {
|
||||
// Switch to Heap Tracking Mode
|
||||
if (!renderer.GetConfigItems().empty()) {
|
||||
renderer.SetListState(std::make_unique<HeapTrackingListState>());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; // Allow scrolling
|
||||
}
|
||||
|
||||
if (input.data.buttons_d & Input::eButtons::BUTTON_A) {
|
||||
if (!renderer.GetConfigItems().empty()) {
|
||||
renderer.EnterSelectedCategory();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (input.data.buttons_d & Input::eButtons::BUTTON_X) {
|
||||
if (!renderer.GetConfigItems().empty()) {
|
||||
renderer.SetListState(std::make_unique<ActivePluginsListState>());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (input.data.buttons_d & (Input::eButtons::BUTTON_B | Input::eButtons::BUTTON_HOME)) {
|
||||
renderer.Exit();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string DefaultListState::GetTitle() const {
|
||||
return "Wii U Plugin System Config Menu";
|
||||
}
|
||||
|
||||
std::string DefaultListState::GetBottomBar(bool isWiimote) const {
|
||||
return string_format("\ue000 Select | %s Manage plugins", isWiimote ? "\uE048" : "\uE002");
|
||||
}
|
||||
|
||||
bool DefaultListState::RenderItemIcon(const ConfigDisplayItem & /*item*/, int /*x*/, int /*y*/) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ActivePluginsListState::HandleInput(ConfigRenderer &renderer, const Input &input) {
|
||||
if (input.data.buttons_d & Input::eButtons::BUTTON_A) {
|
||||
auto &items = renderer.GetFilteredConfigItems();
|
||||
int pos = renderer.GetCursorPos();
|
||||
if (pos >= 0 && static_cast<size_t>(pos) < items.size()) {
|
||||
items[pos].get().toggleIsActivePlugin();
|
||||
renderer.SetPluginsListDirty(true);
|
||||
renderer.RequestRedraw();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (input.data.buttons_d & Input::eButtons::BUTTON_PLUS) {
|
||||
// Apply and Reload
|
||||
renderer.ExitWithReload();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (input.data.buttons_d & (Input::eButtons::BUTTON_B | Input::eButtons::BUTTON_HOME)) {
|
||||
// Abort / Reset
|
||||
for (auto &item : renderer.GetFilteredConfigItems()) {
|
||||
item.get().resetIsActivePlugin();
|
||||
}
|
||||
renderer.SetPluginsListDirty(false);
|
||||
renderer.SetListState(std::make_unique<DefaultListState>());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string ActivePluginsListState::GetTitle() const {
|
||||
return "Please select the plugins that should be active";
|
||||
}
|
||||
|
||||
std::string ActivePluginsListState::GetBottomBar(bool /*isWiimote*/) const {
|
||||
return "\uE000 Toggle | \uE001 Abort | \uE045 Apply";
|
||||
}
|
||||
|
||||
bool ActivePluginsListState::RenderItemIcon(const ConfigDisplayItem &item, int x, int y) const {
|
||||
DrawUtils::setFontSize(24);
|
||||
if (item.isActivePlugin()) {
|
||||
DrawUtils::print(x, y, "\u25C9");
|
||||
} else {
|
||||
DrawUtils::print(x, y, "\u25CE");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::function<bool(const ConfigDisplayItem &)> ActivePluginsListState::GetConfigFilter() const {
|
||||
return [](const auto &) { return true; };
|
||||
}
|
||||
|
||||
bool ActivePluginsListState::IsMainView() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HeapTrackingListState::HandleInput(ConfigRenderer &renderer, const Input &input) {
|
||||
if (input.data.buttons_d & Input::eButtons::BUTTON_A) {
|
||||
auto &items = renderer.GetFilteredConfigItems();
|
||||
int pos = renderer.GetCursorPos();
|
||||
if (pos >= 0 && static_cast<size_t>(pos) < items.size()) {
|
||||
items[pos].get().toggleIsHeapTrackingEnabled();
|
||||
renderer.SetPluginsListDirty(true);
|
||||
renderer.RequestRedraw();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (input.data.buttons_d & Input::eButtons::BUTTON_PLUS) {
|
||||
// Apply and Reload
|
||||
renderer.ExitWithReload();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (input.data.buttons_d & (Input::eButtons::BUTTON_B | Input::eButtons::BUTTON_HOME)) {
|
||||
// Abort
|
||||
for (auto &item : renderer.GetFilteredConfigItems()) {
|
||||
item.get().resetIsHeapTrackingEnabled();
|
||||
}
|
||||
renderer.SetPluginsListDirty(false);
|
||||
renderer.SetListState(std::make_unique<DefaultListState>());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string HeapTrackingListState::GetTitle() const {
|
||||
return "Select plugins to enable Heap Tracking";
|
||||
}
|
||||
|
||||
std::string HeapTrackingListState::GetBottomBar(bool /*isWiimote*/) const {
|
||||
return "\uE000 Toggle | \uE001 Abort | \uE045 Apply";
|
||||
}
|
||||
|
||||
bool HeapTrackingListState::RenderItemIcon(const ConfigDisplayItem &item, const int x, const int y) const {
|
||||
DrawUtils::setFontSize(24);
|
||||
if (item.isHeapTrackingEnabled()) {
|
||||
DrawUtils::print(x, y, "\u25C9");
|
||||
} else {
|
||||
DrawUtils::print(x, y, "\u25CE");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::function<bool(const ConfigDisplayItem &)> HeapTrackingListState::GetConfigFilter() const {
|
||||
return [](const auto &item) { return item.isActivePlugin(); };
|
||||
}
|
||||
|
||||
bool HeapTrackingListState::IsMainView() const {
|
||||
return false;
|
||||
}
|
||||
53
source/utils/config/ConfigRendererStates.h
Normal file
53
source/utils/config/ConfigRendererStates.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class ConfigRenderer;
|
||||
class Input;
|
||||
class ConfigDisplayItem;
|
||||
|
||||
class ConfigListState {
|
||||
public:
|
||||
virtual ~ConfigListState() = default;
|
||||
|
||||
virtual bool HandleInput(ConfigRenderer &renderer, const Input &input) = 0;
|
||||
|
||||
virtual std::string GetTitle() const = 0;
|
||||
virtual std::string GetBottomBar(bool isWiimote) const = 0;
|
||||
virtual bool RenderItemIcon(const ConfigDisplayItem &item, int x, int y) const = 0;
|
||||
|
||||
virtual std::function<bool(const ConfigDisplayItem &)> GetConfigFilter() const = 0;
|
||||
virtual bool IsMainView() const = 0;
|
||||
};
|
||||
|
||||
class DefaultListState : public ConfigListState {
|
||||
public:
|
||||
bool HandleInput(ConfigRenderer &renderer, const Input &input) override;
|
||||
std::string GetTitle() const override;
|
||||
std::string GetBottomBar(bool isWiimote) const override;
|
||||
bool RenderItemIcon(const ConfigDisplayItem &item, int x, int y) const override;
|
||||
std::function<bool(const ConfigDisplayItem &)> GetConfigFilter() const override;
|
||||
bool IsMainView() const override;
|
||||
};
|
||||
|
||||
class ActivePluginsListState : public ConfigListState {
|
||||
public:
|
||||
bool HandleInput(ConfigRenderer &renderer, const Input &input) override;
|
||||
std::string GetTitle() const override;
|
||||
std::string GetBottomBar(bool isWiimote) const override;
|
||||
bool RenderItemIcon(const ConfigDisplayItem &item, int x, int y) const override;
|
||||
std::function<bool(const ConfigDisplayItem &)> GetConfigFilter() const override;
|
||||
bool IsMainView() const override;
|
||||
};
|
||||
|
||||
class HeapTrackingListState : public ConfigListState {
|
||||
public:
|
||||
bool HandleInput(ConfigRenderer &renderer, const Input &input) override;
|
||||
std::string GetTitle() const override;
|
||||
std::string GetBottomBar(bool isWiimote) const override;
|
||||
bool RenderItemIcon(const ConfigDisplayItem &item, int x, int y) const override;
|
||||
std::function<bool(const ConfigDisplayItem &)> GetConfigFilter() const override;
|
||||
bool IsMainView() const override;
|
||||
};
|
||||
|
|
@ -133,7 +133,7 @@ void ConfigUtils::displayMenu() {
|
|||
config = make_unique_nothrow<WUPSConfigAPIBackend::WUPSConfig>(info.name);
|
||||
}
|
||||
|
||||
configs.emplace_back(info, std::move(config), plugin.isLinkedAndLoaded());
|
||||
configs.emplace_back(info, std::move(config), plugin.isLinkedAndLoaded(), plugin.isUsingTrackingPluginHeapMemoryAllocator());
|
||||
}
|
||||
|
||||
// Sort Configs by name
|
||||
|
|
@ -226,7 +226,7 @@ void ConfigUtils::displayMenu() {
|
|||
|
||||
std::vector<PluginLoadWrapper> newActivePluginsList;
|
||||
|
||||
if (subStateReturnValue == SUB_STATE_RETURN_WITH_PLUGIN_RELOAD && renderer.GetActivePluginsIfChanged(newActivePluginsList)) {
|
||||
if (subStateReturnValue == SUB_STATE_RETURN_WITH_PLUGIN_RELOAD && renderer.GetPluginsListIfChanged(newActivePluginsList)) {
|
||||
startTime = OSGetTime();
|
||||
renderBasicScreen("Applying changes, app will now restart...");
|
||||
|
||||
|
|
@ -243,6 +243,7 @@ void ConfigUtils::displayMenu() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
gLoadOnNextLaunch = newActivePluginsList;
|
||||
WUPSBackendSettings::SetInactivePluginFilenames(newInactivePluginsList);
|
||||
if (!WUPSBackendSettings::SaveSettings()) {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,17 @@ extern "C" PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(const wups_back
|
|||
|
||||
for (const auto &pluginData : gLoadedData) {
|
||||
if (pluginData->getHandle() == handle) {
|
||||
gLoadOnNextLaunch.emplace_back(pluginData, true);
|
||||
bool heapTrackingActive = false;
|
||||
#ifdef DEBUG
|
||||
heapTrackingActive = true;
|
||||
#endif
|
||||
for (const auto &plugin : gLoadedPlugins) {
|
||||
if (plugin.getPluginDataCopy()->getHandle() == handle) {
|
||||
heapTrackingActive = plugin.isUsingTrackingPluginHeapMemoryAllocator();
|
||||
break;
|
||||
}
|
||||
}
|
||||
gLoadOnNextLaunch.emplace_back(pluginData, true, heapTrackingActive);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -52,7 +62,7 @@ extern "C" PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(const wups_back
|
|||
// Keep inactive plugins loaded. Duplicates will be eliminated by comparing name/author
|
||||
for (const auto &plugin : gLoadedPlugins) {
|
||||
if (!plugin.isLinkedAndLoaded()) {
|
||||
gLoadOnNextLaunch.emplace_back(plugin.getPluginDataCopy(), false);
|
||||
gLoadOnNextLaunch.emplace_back(plugin.getPluginDataCopy(), false, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ std::string getModuleAndSymbolName(uint32_t addr) {
|
|||
}
|
||||
}
|
||||
|
||||
void PrintCapturedStackTrace(std::span<uint32_t> trace) {
|
||||
void PrintCapturedStackTrace(const std::span<const uint32_t> trace) {
|
||||
if (trace.empty()) {
|
||||
DEBUG_FUNCTION_LINE_INFO("┌────────────────────── CAPTURED TRACE ──────────────────────┐");
|
||||
DEBUG_FUNCTION_LINE_INFO("│ <Empty Trace>");
|
||||
|
|
|
|||
|
|
@ -169,6 +169,6 @@ std::vector<uint32_t> CaptureStackTrace(uint32_t maxDepth);
|
|||
|
||||
std::string getModuleAndSymbolName(uint32_t addr);
|
||||
|
||||
void PrintCapturedStackTrace(std::span<uint32_t> trace);
|
||||
void PrintCapturedStackTrace(std::span<const uint32_t> trace);
|
||||
|
||||
std::string hookNameToString(wups_loader_hook_type_t type);
|
||||
Loading…
Reference in New Issue
Block a user