mirror of https://github.com/AxioDL/metaforce.git
Various updates:
- Simplify Layers logic with hecl bugfix - Show About window with error message on launch with no game - Use high_resolution_clock for FPS & load logic (increased resolution on Windows)
This commit is contained in:
parent
052c1888cb
commit
78bcba85e2
|
@ -26,46 +26,47 @@ static void AthenaExc(athena::error::Level level, const char* file, const char*,
|
||||||
}
|
}
|
||||||
|
|
||||||
class Limiter {
|
class Limiter {
|
||||||
using delta_clock = std::chrono::steady_clock;
|
using delta_clock = std::chrono::high_resolution_clock;
|
||||||
using nanotime_t = std::chrono::nanoseconds::rep;
|
using duration_t = std::chrono::nanoseconds;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Sleep(nanotime_t targetFrameTime) {
|
void Reset() { m_oldTime = delta_clock::now(); }
|
||||||
if (targetFrameTime == 0) {
|
|
||||||
|
void Sleep(duration_t targetFrameTime) {
|
||||||
|
if (targetFrameTime.count() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto start = delta_clock::now();
|
auto start = delta_clock::now();
|
||||||
nanotime_t adjustedSleepTime = ShouldSleep(targetFrameTime);
|
duration_t adjustedSleepTime = SleepTime(targetFrameTime);
|
||||||
if (adjustedSleepTime > 0) {
|
if (adjustedSleepTime.count() > 0) {
|
||||||
std::this_thread::sleep_for(std::chrono::nanoseconds(adjustedSleepTime));
|
std::this_thread::sleep_for(adjustedSleepTime);
|
||||||
nanotime_t overslept = TimeSince(start) - adjustedSleepTime;
|
duration_t overslept = TimeSince(start) - adjustedSleepTime;
|
||||||
if (overslept < targetFrameTime) {
|
if (overslept < duration_t{targetFrameTime}) {
|
||||||
m_overheadTimes[m_overheadTimeIdx] = overslept;
|
m_overheadTimes[m_overheadTimeIdx] = overslept;
|
||||||
m_overheadTimeIdx = (m_overheadTimeIdx + 1) % m_overheadTimes.size();
|
m_overheadTimeIdx = (m_overheadTimeIdx + 1) % m_overheadTimes.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_oldTime = delta_clock::now();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
nanotime_t ShouldSleep(nanotime_t targetFrameTime) {
|
duration_t SleepTime(duration_t targetFrameTime) {
|
||||||
nanotime_t sleepTime = targetFrameTime - TimeSince(m_oldTime);
|
const auto sleepTime = duration_t{targetFrameTime} - TimeSince(m_oldTime);
|
||||||
m_overhead = std::accumulate(m_overheadTimes.begin(), m_overheadTimes.end(), nanotime_t{}) /
|
m_overhead = std::accumulate(m_overheadTimes.begin(), m_overheadTimes.end(), duration_t{}) / m_overheadTimes.size();
|
||||||
static_cast<nanotime_t>(m_overheadTimes.size());
|
|
||||||
if (sleepTime > m_overhead) {
|
if (sleepTime > m_overhead) {
|
||||||
return sleepTime - m_overhead;
|
return sleepTime - m_overhead;
|
||||||
}
|
}
|
||||||
return 0;
|
return duration_t{0};
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
delta_clock::time_point m_oldTime;
|
delta_clock::time_point m_oldTime;
|
||||||
std::array<nanotime_t, 4> m_overheadTimes{};
|
std::array<duration_t, 4> m_overheadTimes{};
|
||||||
size_t m_overheadTimeIdx = 0;
|
size_t m_overheadTimeIdx = 0;
|
||||||
nanotime_t m_overhead = 0;
|
duration_t m_overhead = duration_t{0};
|
||||||
|
|
||||||
nanotime_t TimeSince(delta_clock::time_point start) {
|
duration_t TimeSince(delta_clock::time_point start) {
|
||||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(delta_clock::now() - start).count();
|
return std::chrono::duration_cast<duration_t>(delta_clock::now() - start);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -217,6 +218,8 @@ private:
|
||||||
hecl::Runtime::FileStoreManager& m_fileMgr;
|
hecl::Runtime::FileStoreManager& m_fileMgr;
|
||||||
hecl::CVarManager& m_cvarManager;
|
hecl::CVarManager& m_cvarManager;
|
||||||
hecl::CVarCommons& m_cvarCommons;
|
hecl::CVarCommons& m_cvarCommons;
|
||||||
|
ImGuiConsole m_imGuiConsole;
|
||||||
|
std::string m_errorString;
|
||||||
|
|
||||||
boo::ObjToken<boo::ITextureR> m_renderTex;
|
boo::ObjToken<boo::ITextureR> m_renderTex;
|
||||||
hecl::SystemString m_deferredProject;
|
hecl::SystemString m_deferredProject;
|
||||||
|
@ -236,7 +239,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Application(hecl::Runtime::FileStoreManager& fileMgr, hecl::CVarManager& cvarMgr, hecl::CVarCommons& cvarCmns)
|
Application(hecl::Runtime::FileStoreManager& fileMgr, hecl::CVarManager& cvarMgr, hecl::CVarCommons& cvarCmns)
|
||||||
: m_fileMgr(fileMgr), m_cvarManager(cvarMgr), m_cvarCommons(cvarCmns) {}
|
: m_fileMgr(fileMgr), m_cvarManager(cvarMgr), m_cvarCommons(cvarCmns), m_imGuiConsole(cvarMgr, cvarCmns) {}
|
||||||
|
|
||||||
int appMain(boo::IApplication* app) override {
|
int appMain(boo::IApplication* app) override {
|
||||||
initialize(app);
|
initialize(app);
|
||||||
|
@ -297,6 +300,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_imGuiInitialized) {
|
if (m_imGuiInitialized) {
|
||||||
|
m_imGuiConsole.Shutdown();
|
||||||
ImGuiEngine::Shutdown();
|
ImGuiEngine::Shutdown();
|
||||||
}
|
}
|
||||||
if (g_mainMP1) {
|
if (g_mainMP1) {
|
||||||
|
@ -334,20 +338,20 @@ public:
|
||||||
if (!m_deferredProject.empty()) {
|
if (!m_deferredProject.empty()) {
|
||||||
hecl::SystemString subPath;
|
hecl::SystemString subPath;
|
||||||
hecl::ProjectRootPath projPath = hecl::SearchForProject(m_deferredProject, subPath);
|
hecl::ProjectRootPath projPath = hecl::SearchForProject(m_deferredProject, subPath);
|
||||||
if (!projPath) {
|
if (projPath) {
|
||||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("project doesn't exist at '{}'")), m_deferredProject);
|
|
||||||
m_running.store(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_proj = std::make_unique<hecl::Database::Project>(projPath);
|
m_proj = std::make_unique<hecl::Database::Project>(projPath);
|
||||||
m_deferredProject.clear();
|
m_deferredProject.clear();
|
||||||
hecl::ProjectPath projectPath{m_proj->getProjectWorkingPath(), _SYS_STR("out/files/MP1")};
|
hecl::ProjectPath projectPath{m_proj->getProjectWorkingPath(), _SYS_STR("out/files/MP1")};
|
||||||
CDvdFile::Initialize(projectPath);
|
CDvdFile::Initialize(projectPath);
|
||||||
|
} else {
|
||||||
|
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Project doesn't exist at '{}'")), m_deferredProject);
|
||||||
|
hecl::SystemUTF8Conv conv{m_deferredProject};
|
||||||
|
m_errorString = fmt::format(FMT_STRING("Project not found at '{}'"), conv.str());
|
||||||
|
m_deferredProject.clear();
|
||||||
}
|
}
|
||||||
if (!m_proj) {
|
}
|
||||||
Log.report(logvisor::Error, FMT_STRING(_SYS_STR("Project directory not specified")));
|
if (!m_proj && m_errorString.empty()) {
|
||||||
m_running.store(false);
|
m_errorString = "Project directory not specified"s;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cvarManager.proc();
|
m_cvarManager.proc();
|
||||||
|
@ -377,12 +381,14 @@ public:
|
||||||
|
|
||||||
boo::IGraphicsDataFactory* gfxF = m_window->getMainContextDataFactory();
|
boo::IGraphicsDataFactory* gfxF = m_window->getMainContextDataFactory();
|
||||||
float scale = std::floor(m_window->getVirtualPixelFactor() * 4.f) / 4.f;
|
float scale = std::floor(m_window->getVirtualPixelFactor() * 4.f) / 4.f;
|
||||||
if (!g_mainMP1) {
|
if (!g_mainMP1 && m_proj) {
|
||||||
g_mainMP1.emplace(nullptr, nullptr, gfxF, gfxQ, m_renderTex.get());
|
g_mainMP1.emplace(nullptr, nullptr, gfxF, gfxQ, m_renderTex.get());
|
||||||
g_mainMP1->Init(m_fileMgr, &m_cvarManager, m_window.get(), m_voiceEngine.get(), *m_amuseAllocWrapper);
|
g_mainMP1->Init(m_fileMgr, &m_cvarManager, m_window.get(), m_voiceEngine.get(), *m_amuseAllocWrapper);
|
||||||
if (!m_noShaderWarmup) {
|
if (!m_noShaderWarmup) {
|
||||||
g_mainMP1->WarmupShaders();
|
g_mainMP1->WarmupShaders();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (!m_imGuiInitialized) {
|
||||||
ImGuiEngine::Initialize(gfxF, m_window.get(), scale);
|
ImGuiEngine::Initialize(gfxF, m_window.get(), scale);
|
||||||
m_imGuiInitialized = true;
|
m_imGuiInitialized = true;
|
||||||
}
|
}
|
||||||
|
@ -403,20 +409,29 @@ public:
|
||||||
|
|
||||||
ImGuiEngine::Begin(realDt, scale);
|
ImGuiEngine::Begin(realDt, scale);
|
||||||
|
|
||||||
|
if (g_mainMP1) {
|
||||||
|
m_imGuiConsole.PreUpdate();
|
||||||
if (g_mainMP1->Proc(dt)) {
|
if (g_mainMP1->Proc(dt)) {
|
||||||
m_running.store(false);
|
m_running.store(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
m_imGuiConsole.PostUpdate();
|
||||||
|
} else {
|
||||||
|
m_imGuiConsole.ShowAboutWindow(false, m_errorString);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
OPTICK_EVENT("Draw");
|
OPTICK_EVENT("Draw");
|
||||||
gfxQ->setRenderTarget(m_renderTex);
|
gfxQ->setRenderTarget(m_renderTex);
|
||||||
|
gfxQ->clearTarget();
|
||||||
gfxQ->setViewport(rect);
|
gfxQ->setViewport(rect);
|
||||||
gfxQ->setScissor(rect);
|
gfxQ->setScissor(rect);
|
||||||
if (g_Renderer != nullptr) {
|
if (g_Renderer != nullptr) {
|
||||||
g_Renderer->BeginScene();
|
g_Renderer->BeginScene();
|
||||||
}
|
}
|
||||||
|
if (g_mainMP1) {
|
||||||
g_mainMP1->Draw();
|
g_mainMP1->Draw();
|
||||||
|
}
|
||||||
if (g_Renderer != nullptr) {
|
if (g_Renderer != nullptr) {
|
||||||
g_Renderer->EndScene();
|
g_Renderer->EndScene();
|
||||||
}
|
}
|
||||||
|
@ -436,12 +451,15 @@ public:
|
||||||
gfxQ->resolveDisplay(m_renderTex);
|
gfxQ->resolveDisplay(m_renderTex);
|
||||||
|
|
||||||
if (g_ResFactory != nullptr) {
|
if (g_ResFactory != nullptr) {
|
||||||
int64_t targetFrameTime = getTargetFrameTime();
|
const auto targetFrameTime = getTargetFrameTime();
|
||||||
do {
|
const auto idleTime = m_limiter.SleepTime(targetFrameTime);
|
||||||
g_ResFactory->AsyncIdle();
|
if (g_ResFactory->AsyncIdle(idleTime)) {
|
||||||
} while (m_limiter.ShouldSleep(targetFrameTime) != 0);
|
m_limiter.Reset();
|
||||||
|
} else {
|
||||||
|
// No more to load; sleep
|
||||||
m_limiter.Sleep(targetFrameTime);
|
m_limiter.Sleep(targetFrameTime);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_voiceEngine) {
|
if (m_voiceEngine) {
|
||||||
m_voiceEngine->pumpAndMixVoices();
|
m_voiceEngine->pumpAndMixVoices();
|
||||||
|
@ -461,8 +479,11 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] bool getDeepColor() const { return m_cvarCommons.getDeepColor(); }
|
[[nodiscard]] bool getDeepColor() const { return m_cvarCommons.getDeepColor(); }
|
||||||
|
|
||||||
[[nodiscard]] int64_t getTargetFrameTime() const {
|
[[nodiscard]] std::chrono::nanoseconds getTargetFrameTime() const {
|
||||||
return m_cvarCommons.getVariableFrameTime() ? 0 : 1000000000L / 60;
|
if (m_cvarCommons.getVariableFrameTime()) {
|
||||||
|
return std::chrono::nanoseconds{0};
|
||||||
|
}
|
||||||
|
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds{1}) / 60;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -75,21 +75,24 @@ void CResFactory::BuildAsync(const SObjectTag& tag, const CVParamTransfer& xfer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResFactory::AsyncIdle() {
|
bool CResFactory::AsyncIdle(std::chrono::nanoseconds target) {
|
||||||
OPTICK_EVENT();
|
OPTICK_EVENT();
|
||||||
if (m_loadList.empty())
|
if (m_loadList.empty()) {
|
||||||
return;
|
return false;
|
||||||
auto startTime = std::chrono::steady_clock::now();
|
}
|
||||||
while (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - startTime).count() <
|
auto startTime = std::chrono::high_resolution_clock::now();
|
||||||
5) {
|
do {
|
||||||
auto& task = m_loadList.front();
|
auto& task = m_loadList.front();
|
||||||
if (PumpResource(task)) {
|
if (PumpResource(task)) {
|
||||||
m_loadMap.erase(task.x0_tag);
|
m_loadMap.erase(task.x0_tag);
|
||||||
m_loadList.pop_front();
|
m_loadList.pop_front();
|
||||||
if (m_loadList.empty())
|
if (m_loadList.empty()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} while (std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - startTime) <
|
||||||
|
target);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResFactory::CancelBuild(const SObjectTag& tag) {
|
void CResFactory::CancelBuild(const SObjectTag& tag) {
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
std::unique_ptr<IObj> Build(const SObjectTag&, const CVParamTransfer&, CObjectReference* selfRef) override;
|
std::unique_ptr<IObj> Build(const SObjectTag&, const CVParamTransfer&, CObjectReference* selfRef) override;
|
||||||
void BuildAsync(const SObjectTag&, const CVParamTransfer&, std::unique_ptr<IObj>*,
|
void BuildAsync(const SObjectTag&, const CVParamTransfer&, std::unique_ptr<IObj>*,
|
||||||
CObjectReference* selfRef) override;
|
CObjectReference* selfRef) override;
|
||||||
void AsyncIdle() override;
|
bool AsyncIdle(std::chrono::nanoseconds target) override;
|
||||||
void CancelBuild(const SObjectTag&) override;
|
void CancelBuild(const SObjectTag&) override;
|
||||||
|
|
||||||
bool CanBuild(const SObjectTag& tag) override { return x4_loader.ResourceExists(tag); }
|
bool CanBuild(const SObjectTag& tag) override { return x4_loader.ResourceExists(tag); }
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
EnumerateNamedResources(const std::function<bool(std::string_view, const SObjectTag&)>& lambda) const = 0;
|
EnumerateNamedResources(const std::function<bool(std::string_view, const SObjectTag&)>& lambda) const = 0;
|
||||||
virtual CResLoader* GetResLoader() { return nullptr; }
|
virtual CResLoader* GetResLoader() { return nullptr; }
|
||||||
virtual CFactoryMgr* GetFactoryMgr() { return nullptr; }
|
virtual CFactoryMgr* GetFactoryMgr() { return nullptr; }
|
||||||
virtual void AsyncIdle() {}
|
virtual bool AsyncIdle(std::chrono::nanoseconds target) { return false; }
|
||||||
|
|
||||||
/* Non-factory versions, replaces CResLoader */
|
/* Non-factory versions, replaces CResLoader */
|
||||||
virtual u32 ResourceSize(const metaforce::SObjectTag& tag) = 0;
|
virtual u32 ResourceSize(const metaforce::SObjectTag& tag) = 0;
|
||||||
|
|
|
@ -350,7 +350,7 @@ bool ImGuiConsole::ShowEntityInfoWindow(TUniqueId uid) {
|
||||||
return open;
|
return open;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiConsole::ShowAboutWindow() {
|
void ImGuiConsole::ShowAboutWindow(bool canClose, std::string_view errorString) {
|
||||||
// Center window
|
// Center window
|
||||||
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
|
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
|
||||||
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
||||||
|
@ -359,9 +359,15 @@ void ImGuiConsole::ShowAboutWindow() {
|
||||||
ImGui::PushStyleColor(ImGuiCol_TitleBg, windowBg);
|
ImGui::PushStyleColor(ImGuiCol_TitleBg, windowBg);
|
||||||
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, windowBg);
|
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, windowBg);
|
||||||
|
|
||||||
if (ImGui::Begin("About", &m_showAboutWindow,
|
bool* open = nullptr;
|
||||||
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoNav |
|
ImGuiWindowFlags flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoNav |
|
||||||
ImGuiWindowFlags_NoSavedSettings)) {
|
ImGuiWindowFlags_NoSavedSettings;
|
||||||
|
if (canClose) {
|
||||||
|
open = &m_showAboutWindow;
|
||||||
|
} else {
|
||||||
|
flags |= ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove;
|
||||||
|
}
|
||||||
|
if (ImGui::Begin("About", open, flags)) {
|
||||||
float iconSize = 128.f * ImGui::GetIO().DisplayFramebufferScale.x;
|
float iconSize = 128.f * ImGui::GetIO().DisplayFramebufferScale.x;
|
||||||
ImGui::SameLine(ImGui::GetWindowSize().x / 2 - iconSize + (iconSize / 2));
|
ImGui::SameLine(ImGui::GetWindowSize().x / 2 - iconSize + (iconSize / 2));
|
||||||
ImGui::Image(ImGuiUserTextureID_MetaforceIcon, ImVec2{iconSize, iconSize});
|
ImGui::Image(ImGuiUserTextureID_MetaforceIcon, ImVec2{iconSize, iconSize});
|
||||||
|
@ -371,6 +377,12 @@ void ImGuiConsole::ShowAboutWindow() {
|
||||||
ImGuiTextCenter(METAFORCE_WC_DESCRIBE);
|
ImGuiTextCenter(METAFORCE_WC_DESCRIBE);
|
||||||
const ImVec2& padding = ImGui::GetStyle().WindowPadding;
|
const ImVec2& padding = ImGui::GetStyle().WindowPadding;
|
||||||
ImGui::Dummy(padding);
|
ImGui::Dummy(padding);
|
||||||
|
if (!errorString.empty()) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4{0.77f, 0.12f, 0.23f, 1.f});
|
||||||
|
ImGuiTextCenter(errorString);
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::Dummy(padding);
|
||||||
|
}
|
||||||
ImGuiTextCenter("2015-2021");
|
ImGuiTextCenter("2015-2021");
|
||||||
ImGuiTextCenter("Phillip Stephens (Antidote)");
|
ImGuiTextCenter("Phillip Stephens (Antidote)");
|
||||||
ImGuiTextCenter("Jack Andersen (jackoalan)");
|
ImGuiTextCenter("Jack Andersen (jackoalan)");
|
||||||
|
@ -414,6 +426,7 @@ void ImGuiConsole::ShowAboutWindow() {
|
||||||
if (ImGui::TableNextColumn()) {
|
if (ImGui::TableNextColumn()) {
|
||||||
ImGuiStringViewText(METAFORCE_BUILD_TYPE);
|
ImGuiStringViewText(METAFORCE_BUILD_TYPE);
|
||||||
}
|
}
|
||||||
|
if (g_Main != nullptr) {
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
if (ImGui::TableNextColumn()) {
|
if (ImGui::TableNextColumn()) {
|
||||||
ImGuiStringViewText("Game");
|
ImGuiStringViewText("Game");
|
||||||
|
@ -421,6 +434,7 @@ void ImGuiConsole::ShowAboutWindow() {
|
||||||
if (ImGui::TableNextColumn()) {
|
if (ImGui::TableNextColumn()) {
|
||||||
ImGuiStringViewText(g_Main->GetVersionString());
|
ImGuiStringViewText(g_Main->GetVersionString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -573,8 +587,6 @@ void ImGuiConsole::ShowDebugOverlay() {
|
||||||
if (hasPrevious) {
|
if (hasPrevious) {
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
}
|
}
|
||||||
// ImGui::NewLine();
|
|
||||||
|
|
||||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||||
zeus::CVector2f p = ImGui::GetCursorScreenPos();
|
zeus::CVector2f p = ImGui::GetCursorScreenPos();
|
||||||
|
|
||||||
|
@ -633,11 +645,11 @@ void ImGuiConsole::ShowDebugOverlay() {
|
||||||
// dpad
|
// dpad
|
||||||
{
|
{
|
||||||
float halfWidth = dpadWidth / 2;
|
float halfWidth = dpadWidth / 2;
|
||||||
dl->AddRectFilled(dpadCenter + zeus::CVector2f(-halfWidth, -dpadRadius), dpadCenter + zeus::CVector2f(halfWidth, dpadRadius),
|
dl->AddRectFilled(dpadCenter + zeus::CVector2f(-halfWidth, -dpadRadius),
|
||||||
stickGray);
|
dpadCenter + zeus::CVector2f(halfWidth, dpadRadius), stickGray);
|
||||||
|
|
||||||
dl->AddRectFilled(dpadCenter + zeus::CVector2f(-dpadRadius, -halfWidth), dpadCenter + zeus::CVector2f(dpadRadius, halfWidth),
|
dl->AddRectFilled(dpadCenter + zeus::CVector2f(-dpadRadius, -halfWidth),
|
||||||
stickGray);
|
dpadCenter + zeus::CVector2f(dpadRadius, halfWidth), stickGray);
|
||||||
|
|
||||||
if (input.DDPUp()) {
|
if (input.DDPUp()) {
|
||||||
dl->AddRectFilled(dpadCenter + zeus::CVector2f(-halfWidth, -dpadRadius),
|
dl->AddRectFilled(dpadCenter + zeus::CVector2f(-halfWidth, -dpadRadius),
|
||||||
|
@ -822,7 +834,7 @@ void ImGuiConsole::PreUpdate() {
|
||||||
ShowLayersWindow();
|
ShowLayersWindow();
|
||||||
}
|
}
|
||||||
if (m_showAboutWindow) {
|
if (m_showAboutWindow) {
|
||||||
ShowAboutWindow();
|
ShowAboutWindow(true);
|
||||||
}
|
}
|
||||||
if (m_showDemoWindow) {
|
if (m_showDemoWindow) {
|
||||||
ImGui::ShowDemoWindow(&m_showDemoWindow);
|
ImGui::ShowDemoWindow(&m_showDemoWindow);
|
||||||
|
@ -853,7 +865,7 @@ void ImGuiConsole::PostUpdate() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiConsole::~ImGuiConsole() {
|
void ImGuiConsole::Shutdown() {
|
||||||
dummyWorlds.clear();
|
dummyWorlds.clear();
|
||||||
stringTables.clear();
|
stringTables.clear();
|
||||||
}
|
}
|
||||||
|
@ -1029,33 +1041,19 @@ void ImGuiConsole::ShowLayersWindow() {
|
||||||
|
|
||||||
auto worldLayerState = g_GameState->StateForWorld(world.second).GetLayerState();
|
auto worldLayerState = g_GameState->StateForWorld(world.second).GetLayerState();
|
||||||
auto areas = ListAreas(world.second);
|
auto areas = ListAreas(world.second);
|
||||||
// TODO: m_startNameIdx have incorrect values in the data due to a Metaforce bug
|
|
||||||
// so when filtering we need to keep track of these here, this can be simplified when fixed
|
|
||||||
std::vector<u32> layerStartIdx;
|
|
||||||
layerStartIdx.reserve(areas.size());
|
|
||||||
u32 startNameIdx = 0;
|
|
||||||
auto iter = areas.begin();
|
auto iter = areas.begin();
|
||||||
while (iter != areas.end()) {
|
while (iter != areas.end()) {
|
||||||
u32 layerCount = worldLayerState->GetAreaLayerCount(iter->second);
|
|
||||||
if (layerCount == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!search.empty() && !ContainsCaseInsensitive(iter->first, search)) {
|
if (!search.empty() && !ContainsCaseInsensitive(iter->first, search)) {
|
||||||
iter = areas.erase(iter);
|
iter = areas.erase(iter);
|
||||||
} else {
|
} else {
|
||||||
layerStartIdx.push_back(startNameIdx);
|
|
||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
if (iter != areas.end()) {
|
|
||||||
startNameIdx += layerCount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (areas.empty()) {
|
if (areas.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::TreeNodeEx(world.first.c_str(), search.empty() ? 0 : ImGuiTreeNodeFlags_DefaultOpen)) {
|
if (ImGui::TreeNodeEx(world.first.c_str(), search.empty() ? 0 : ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
auto startNameIdxIter = layerStartIdx.begin();
|
|
||||||
for (const auto& area : areas) {
|
for (const auto& area : areas) {
|
||||||
u32 layerCount = worldLayerState->GetAreaLayerCount(area.second);
|
u32 layerCount = worldLayerState->GetAreaLayerCount(area.second);
|
||||||
if (layerCount == 0) {
|
if (layerCount == 0) {
|
||||||
|
@ -1065,18 +1063,19 @@ void ImGuiConsole::ShowLayersWindow() {
|
||||||
if (ImGui::Button("Warp here")) {
|
if (ImGui::Button("Warp here")) {
|
||||||
Warp(world.second, area.second);
|
Warp(world.second, area.second);
|
||||||
}
|
}
|
||||||
// TODO see above comment
|
u32 startNameIdx = layers->m_areas[area.second].m_startNameIdx;
|
||||||
// u32 startNameIdx = layers->m_areas[area.second].m_startNameIdx;
|
if (startNameIdx + layerCount > layers->m_names.size()) {
|
||||||
|
ImGui::Text("Broken layer data, please re-package");
|
||||||
|
} else {
|
||||||
for (u32 layer = 0; layer < layerCount; ++layer) {
|
for (u32 layer = 0; layer < layerCount; ++layer) {
|
||||||
bool active = worldLayerState->IsLayerActive(area.second, layer);
|
bool active = worldLayerState->IsLayerActive(area.second, layer);
|
||||||
if (ImGui::Checkbox(layers->m_names[*startNameIdxIter + layer].c_str(), &active)) {
|
if (ImGui::Checkbox(layers->m_names[startNameIdx + layer].c_str(), &active)) {
|
||||||
worldLayerState->SetLayerActive(area.second, layer, active);
|
worldLayerState->SetLayerActive(area.second, layer, active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
startNameIdxIter++;
|
|
||||||
}
|
}
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,9 +36,10 @@ public:
|
||||||
|
|
||||||
ImGuiConsole(hecl::CVarManager& cvarMgr, hecl::CVarCommons& cvarCommons)
|
ImGuiConsole(hecl::CVarManager& cvarMgr, hecl::CVarCommons& cvarCommons)
|
||||||
: m_cvarMgr(cvarMgr), m_cvarCommons(cvarCommons) {}
|
: m_cvarMgr(cvarMgr), m_cvarCommons(cvarCommons) {}
|
||||||
~ImGuiConsole();
|
|
||||||
void PreUpdate();
|
void PreUpdate();
|
||||||
void PostUpdate();
|
void PostUpdate();
|
||||||
|
void Shutdown();
|
||||||
|
void ShowAboutWindow(bool canClose, std::string_view errorString = ""sv);
|
||||||
|
|
||||||
static void BeginEntityRow(const ImGuiEntityEntry& entry);
|
static void BeginEntityRow(const ImGuiEntityEntry& entry);
|
||||||
static void EndEntityRow(const ImGuiEntityEntry& entry);
|
static void EndEntityRow(const ImGuiEntityEntry& entry);
|
||||||
|
@ -84,7 +85,6 @@ private:
|
||||||
void ShowInspectWindow(bool* isOpen);
|
void ShowInspectWindow(bool* isOpen);
|
||||||
void LerpDebugColor(CActor* act);
|
void LerpDebugColor(CActor* act);
|
||||||
void UpdateEntityEntries();
|
void UpdateEntityEntries();
|
||||||
void ShowAboutWindow();
|
|
||||||
void ShowDebugOverlay();
|
void ShowDebugOverlay();
|
||||||
void ShowItemsWindow();
|
void ShowItemsWindow();
|
||||||
void ShowLayersWindow();
|
void ShowLayersWindow();
|
||||||
|
|
|
@ -238,8 +238,8 @@ void CGameArchitectureSupport::specialKeyUp(boo::ESpecialKey key, boo::EModifier
|
||||||
CMain::CMain(IFactory* resFactory, CSimplePool* resStore, boo::IGraphicsDataFactory* gfxFactory,
|
CMain::CMain(IFactory* resFactory, CSimplePool* resStore, boo::IGraphicsDataFactory* gfxFactory,
|
||||||
boo::IGraphicsCommandQueue* cmdQ, const boo::ObjToken<boo::ITextureR>& spareTex)
|
boo::IGraphicsCommandQueue* cmdQ, const boo::ObjToken<boo::ITextureR>& spareTex)
|
||||||
: m_booSetter(gfxFactory, cmdQ, spareTex)
|
: m_booSetter(gfxFactory, cmdQ, spareTex)
|
||||||
|
, xe4_gameplayResult(EGameplayResult::Playing)
|
||||||
, x128_globalObjects(std::make_unique<CGameGlobalObjects>(resFactory, resStore)) {
|
, x128_globalObjects(std::make_unique<CGameGlobalObjects>(resFactory, resStore)) {
|
||||||
xe4_gameplayResult = EGameplayResult::Playing;
|
|
||||||
g_Main = this;
|
g_Main = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,7 +769,6 @@ void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarMana
|
||||||
"Warp"sv, "Warps to a given area and world"sv, "[worldname] areaId"sv,
|
"Warp"sv, "Warps to a given area and world"sv, "[worldname] areaId"sv,
|
||||||
[this](hecl::Console* console, const std::vector<std::string>& args) { Warp(console, args); },
|
[this](hecl::Console* console, const std::vector<std::string>& args) { Warp(console, args); },
|
||||||
hecl::SConsoleCommand::ECommandFlags::Normal);
|
hecl::SConsoleCommand::ECommandFlags::Normal);
|
||||||
m_imGuiConsole = std::make_unique<ImGuiConsole>(*m_cvarMgr, *m_cvarCommons);
|
|
||||||
|
|
||||||
bool loadedVersion = false;
|
bool loadedVersion = false;
|
||||||
if (CDvdFile::FileExists("version.yaml")) {
|
if (CDvdFile::FileExists("version.yaml")) {
|
||||||
|
@ -908,8 +907,6 @@ bool CMain::Proc(float dt) {
|
||||||
m_loadedPersistentResources = true;
|
m_loadedPersistentResources = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_imGuiConsole->PreUpdate();
|
|
||||||
|
|
||||||
if (!m_paused) {
|
if (!m_paused) {
|
||||||
CGBASupport::GlobalPoll();
|
CGBASupport::GlobalPoll();
|
||||||
x164_archSupport->UpdateTicks(dt);
|
x164_archSupport->UpdateTicks(dt);
|
||||||
|
@ -918,8 +915,6 @@ bool CMain::Proc(float dt) {
|
||||||
CStreamAudioManager::Update(dt);
|
CStreamAudioManager::Update(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_imGuiConsole->PostUpdate();
|
|
||||||
|
|
||||||
if (x164_archSupport->GetIOWinManager().IsEmpty() || CheckReset()) {
|
if (x164_archSupport->GetIOWinManager().IsEmpty() || CheckReset()) {
|
||||||
CStreamAudioManager::StopAll();
|
CStreamAudioManager::StopAll();
|
||||||
/*
|
/*
|
||||||
|
@ -965,7 +960,6 @@ void CMain::Draw() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGraphics::g_BooMainCommandQueue->clearTarget(true, true);
|
|
||||||
x164_archSupport->Draw();
|
x164_archSupport->Draw();
|
||||||
m_console->draw(CGraphics::g_BooMainCommandQueue);
|
m_console->draw(CGraphics::g_BooMainCommandQueue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,7 +248,6 @@ private:
|
||||||
hecl::CVarManager* m_cvarMgr = nullptr;
|
hecl::CVarManager* m_cvarMgr = nullptr;
|
||||||
std::unique_ptr<hecl::CVarCommons> m_cvarCommons;
|
std::unique_ptr<hecl::CVarCommons> m_cvarCommons;
|
||||||
std::unique_ptr<hecl::Console> m_console;
|
std::unique_ptr<hecl::Console> m_console;
|
||||||
std::unique_ptr<ImGuiConsole> m_imGuiConsole;
|
|
||||||
// Warmup state
|
// Warmup state
|
||||||
std::vector<SObjectTag> m_warmupTags;
|
std::vector<SObjectTag> m_warmupTags;
|
||||||
std::vector<SObjectTag>::iterator m_warmupIt;
|
std::vector<SObjectTag>::iterator m_warmupIt;
|
||||||
|
|
Loading…
Reference in New Issue