initial commit; cv 0.0.3

This commit is contained in:
2026-09-07 19:33:58 -04:00
commit abf065ddde
63 changed files with 8816 additions and 0 deletions

194
Features/IUIFeature.hpp Normal file
View File

@@ -0,0 +1,194 @@
#pragma once
#include <chrono>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <exception>
#include <DynamicOutput/DynamicOutput.hpp>
#include <Unreal/UObject.hpp>
#include <Static/LogGate.hpp>
namespace PalUIExtension::Features
{
using namespace RC;
using namespace RC::Unreal;
class IUIFeature
{
public:
using StringType = std::basic_string<TCHAR>;
virtual ~IUIFeature() = default;
virtual auto Name() const -> const TCHAR* = 0;
virtual auto InstallHooks() -> void = 0;
virtual auto OnWorldTeardown() -> void {}
virtual auto SetEnabled(bool enabled) -> void {}
virtual auto GetEnabled() -> bool { return false; }
// ---- logging ---------------------------------------------------
template <typename... Args>
auto SendLog(LogLevel::LogLevel Level, const TCHAR* Fmt, Args&&... Fargs) const -> void
{
Emit(Level, Fmt, std::forward<Args>(Fargs)...);
}
template <typename... Args>
auto SendLogOnce(const TCHAR* Key, LogLevel::LogLevel Level, const TCHAR* Fmt, Args&&... Fargs) const -> void
{
if (!Key) return;
if (!m_log_once_keys.insert(StringType{ Key }).second) return;
Emit(Level, Fmt, std::forward<Args>(Fargs)...);
}
template <typename... Args>
auto SendLogThrottled(const TCHAR* Key, int64_t IntervalMs, LogLevel::LogLevel Level, const TCHAR* Fmt, Args&&... Fargs) const -> void
{
if (!Key) return;
using Clock = std::chrono::steady_clock;
const auto Now = Clock::now();
auto& Last = m_log_throttle[StringType{ Key }];
if (Last.time_since_epoch().count() != 0 && std::chrono::duration_cast<std::chrono::milliseconds>(Now - Last).count() < IntervalMs)
{
return;
}
Last = Now;
Emit(Level, Fmt, std::forward<Args>(Fargs)...);
}
template <typename... Args>
auto SendVerbose(const TCHAR* Fmt, Args&&... Fargs) const -> void
{
if constexpr (Static::kVerboseLogging)
{
Emit(LogLevel::Verbose, Fmt, std::forward<Args>(Fargs)...);
}
}
auto ResetLogOnce() const -> void
{
m_log_once_keys.clear();
m_log_throttle.clear();
}
// ---- argument helpers -------------------------------------------
static auto NameOf(UObject* Obj) -> StringType { return Obj ? Obj->GetName() : StringType{ STR("<null>") }; }
static auto FullNameOf(UObject* Obj) -> StringType { return Obj ? Obj->GetFullName() : StringType{ STR("<null>") }; }
static auto ClassNameOf(UObject* Obj) -> StringType
{
if (!Obj) return StringType{ STR("<null>") };
UClass* Cls = Obj->GetClassPrivate();
return Cls ? Cls->GetName() : StringType{ STR("<no class>") };
}
static auto AddressOf(const void* P) -> uint64_t
{
return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(P));
}
private:
template <typename... Args>
auto Emit(LogLevel::LogLevel Level, const TCHAR* Fmt, Args&&... Fargs) const -> void
{
if (!Fmt) return;
try
{
switch (Level)
{
case LogLevel::Error:
Output::send<LogLevel::Error>(STR("PalUIExt [{}] "), Name());
Output::send<LogLevel::Error>(Fmt, std::forward<Args>(Fargs)...);
Output::send<LogLevel::Error>(STR("\n"));
break;
case LogLevel::Warning:
Output::send<LogLevel::Warning>(STR("PalUIExt [{}] "), Name());
Output::send<LogLevel::Warning>(Fmt, std::forward<Args>(Fargs)...);
Output::send<LogLevel::Warning>(STR("\n"));
break;
case LogLevel::Verbose:
Output::send<LogLevel::Verbose>(STR("PalUIExt [{}] "), Name());
Output::send<LogLevel::Verbose>(Fmt, std::forward<Args>(Fargs)...);
Output::send<LogLevel::Verbose>(STR("\n"));
break;
default:
Output::send<LogLevel::Normal>(STR("PalUIExt [{}] "), Name());
Output::send<LogLevel::Normal>(Fmt, std::forward<Args>(Fargs)...);
Output::send<LogLevel::Normal>(STR("\n"));
break;
}
}
catch (const std::exception&)
{
try { Output::send<LogLevel::Error>(STR("PalUIExt: malformed log format string\n")); }
catch (...) {}
}
catch (...)
{
}
}
mutable std::unordered_set<StringType> m_log_once_keys;
mutable std::unordered_map<StringType, std::chrono::steady_clock::time_point> m_log_throttle;
};
class ScopedHotPathTimer
{
public:
ScopedHotPathTimer(const IUIFeature& Feature, const TCHAR* Label,
int64_t ReportAboveMicros = 250)
: m_feature(Feature), m_label(Label), m_threshold(ReportAboveMicros)
{
if constexpr (Static::kProfileHotPath)
{
m_start = std::chrono::steady_clock::now();
}
}
~ScopedHotPathTimer()
{
if constexpr (Static::kProfileHotPath)
{
const auto Micros = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - m_start).count();
if (Micros >= m_threshold)
{
m_feature.SendLogThrottled(m_label, 1000, LogLevel::Warning,
STR("slow path: {} took {}us"), m_label, Micros);
}
}
}
ScopedHotPathTimer(const ScopedHotPathTimer&) = delete;
ScopedHotPathTimer& operator=(const ScopedHotPathTimer&) = delete;
private:
const IUIFeature& m_feature;
const TCHAR* m_label;
int64_t m_threshold;
std::chrono::steady_clock::time_point m_start{};
};
}