mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Enable ImDebugger everywhere, on top of the regular UI.
This commit is contained in:
1 parent
ca3fc0fa9e
commit
db8ff4391e
7 files changed
+311
-263
No files matched your search
@@ -48,6 +48,9 @@ public:
|
||||
|
||||
virtual bool AllowKeyboardNavigation() const { return true; }
|
||||
|
||||
// Process keyboard shortcuts even outside the game.
|
||||
virtual InputMode PassInputToMapper() const { return InputMode::Keyboard; }
|
||||
|
||||
protected:
|
||||
virtual void CreateViews() = 0;
|
||||
virtual bool AllowFocusMovement() const { return true; }
|
||||
|
||||
@@ -179,8 +179,12 @@ bool PortManager::Initialize(const unsigned int timeout) {
|
||||
}
|
||||
|
||||
// Using Game ID & Player Name as default description for mapping
|
||||
std::string gameID = g_paramSFO.GetDiscID();
|
||||
m_defaultDesc = "PPSSPP:" + gameID + ":" + g_Config.sNickName; // Some routers may automatically prefixed it with "UPnP:"
|
||||
if (PSP_IsInited()) {
|
||||
std::string gameID = g_paramSFO.GetDiscID();
|
||||
m_defaultDesc = "PPSSPP:" + gameID + ":" + g_Config.sNickName; // Some routers may automatically prefixed it with "UPnP:"
|
||||
} else {
|
||||
m_defaultDesc = "PPSSPP:at_menu:" + g_Config.sNickName;
|
||||
}
|
||||
|
||||
freeUPNPDevlist(devlist);
|
||||
|
||||
|
||||
+4
-165
@@ -75,7 +75,6 @@ using namespace std::placeholders;
|
||||
#include "Core/RetroAchievements.h"
|
||||
#include "Core/SaveState.h"
|
||||
#include "Core/Screenshot.h"
|
||||
#include "UI/ImDebugger/ImDebugger.h"
|
||||
#include "Core/HLE/__sceAudio.h"
|
||||
#include "Core/HW/Display.h"
|
||||
|
||||
@@ -98,12 +97,6 @@ using namespace std::placeholders;
|
||||
#include "UI/ChatScreen.h"
|
||||
#include "UI/DebugOverlay.h"
|
||||
|
||||
#include "ext/imgui/imgui.h"
|
||||
#include "ext/imgui/imgui_internal.h"
|
||||
#include "ext/imgui/imgui_impl_thin3d.h"
|
||||
#include "ext/imgui/imgui_impl_platform.h"
|
||||
|
||||
|
||||
#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
|
||||
#include "Windows/MainWindow.h"
|
||||
#endif
|
||||
@@ -114,15 +107,6 @@ static AVIDump avi;
|
||||
|
||||
extern bool g_TakeScreenshot;
|
||||
|
||||
static void AssertCancelCallback(const char *message, void *userdata) {
|
||||
NOTICE_LOG(Log::CPU, "Broke after assert: %s", message);
|
||||
Core_Break(BreakReason::AssertChoice);
|
||||
g_Config.bShowImDebugger = true;
|
||||
|
||||
EmuScreen *emuScreen = (EmuScreen *)userdata;
|
||||
emuScreen->SendImDebuggerCommand(ImCommand{ ImCmd::SHOW_IN_CPU_DISASM, currentMIPS->pc });
|
||||
}
|
||||
|
||||
// Handles control rotation due to internal screen rotation.
|
||||
void EmuScreen::UpdatePSPButtons(uint32_t bitsToSet, uint32_t bitsToClear) {
|
||||
if (!IsOnTop()) {
|
||||
@@ -283,8 +267,6 @@ void EmuScreen::ProcessGameBoot(const Path &filename) {
|
||||
break;
|
||||
}
|
||||
|
||||
SetAssertCancelCallback(&AssertCancelCallback, this);
|
||||
|
||||
if (!g_Config.bShaderCache) {
|
||||
// Only developers should ever see this.
|
||||
g_OSD.Show(OSDType::MESSAGE_WARNING, "Shader cache is disabled (developer)");
|
||||
@@ -454,11 +436,6 @@ void EmuScreen::bootComplete() {
|
||||
EmuScreen::~EmuScreen() {
|
||||
g_controlMapper.RemoveListener(this);
|
||||
|
||||
if (imguiInited_) {
|
||||
ImGui_ImplThin3d_Shutdown();
|
||||
ImGui::DestroyContext(ctx_);
|
||||
}
|
||||
|
||||
std::string gameID = g_paramSFO.GetValueString("DISC_ID");
|
||||
g_Config.TimeTracker().Stop(gameID);
|
||||
|
||||
@@ -533,9 +510,6 @@ void EmuScreen::dialogFinished(const Screen *dialog, DialogResult result) {
|
||||
}
|
||||
|
||||
SetExtraAssertInfo(extraAssertInfoStr_.c_str());
|
||||
|
||||
// Make sure we re-enable keyboard mode if it was disabled by the dialog, and if needed.
|
||||
lastImguiEnabled_ = false;
|
||||
}
|
||||
|
||||
void EmuScreen::focusChanged(ScreenFocusChange focusChange) {
|
||||
@@ -771,11 +745,6 @@ void EmuScreen::ProcessVKey(VirtKey virtKey, bool down) {
|
||||
}
|
||||
break;
|
||||
|
||||
case VIRTKEY_TOGGLE_DEBUGGER:
|
||||
if (down) {
|
||||
g_Config.bShowImDebugger = !g_Config.bShowImDebugger;
|
||||
}
|
||||
break;
|
||||
case VIRTKEY_TOGGLE_TILT:
|
||||
if (down) {
|
||||
g_Config.bTiltInputEnabled = !g_Config.bTiltInputEnabled;
|
||||
@@ -1160,27 +1129,12 @@ InputMode EmuScreen::PassInputToMapper() const {
|
||||
return InputMode::None;
|
||||
}
|
||||
|
||||
InputMode modes = InputMode::Keyboard | InputMode::Mouse | InputMode::Other | InputMode::ImDebuggerToggle;
|
||||
if (g_Config.bShowImDebugger && imguiInited_) {
|
||||
if (ImGui::GetIO().WantCaptureKeyboard) {
|
||||
modes &= ~InputMode::Keyboard;
|
||||
}
|
||||
if (ImGui::GetIO().WantCaptureMouse) {
|
||||
modes &= ~InputMode::Mouse;
|
||||
}
|
||||
return modes;
|
||||
}
|
||||
|
||||
return modes;
|
||||
return InputMode::Keyboard | InputMode::Mouse | InputMode::Other | InputMode::ImDebuggerToggle;
|
||||
}
|
||||
|
||||
bool EmuScreen::key(const KeyInput &key) {
|
||||
bool retval = UIScreen::key(key);
|
||||
|
||||
if (!retval && g_Config.bShowImDebugger && imguiInited_) {
|
||||
ImGui_ImplPlatform_KeyEvent(key);
|
||||
}
|
||||
|
||||
if (!retval && (key.flags & KeyInputFlags::DOWN) != 0 && UI::IsEscapeKey(key)) {
|
||||
if (chatMenu_)
|
||||
chatMenu_->Close();
|
||||
@@ -1206,18 +1160,13 @@ bool EmuScreen::touch(const TouchInput &touch) {
|
||||
}
|
||||
|
||||
if (touch.flags & TouchInputFlags::DOWN) {
|
||||
if (!(g_Config.bShowImDebugger && imguiInited_) && !ignoreGamepad) {
|
||||
if (!g_Config.bShowImDebugger && !ignoreGamepad) {
|
||||
// This just prevents the gamepad from timing out.
|
||||
GamepadTouch();
|
||||
}
|
||||
}
|
||||
|
||||
if (g_Config.bShowImDebugger && imguiInited_) {
|
||||
ImGui_ImplPlatform_TouchEvent(touch);
|
||||
if (!ImGui::GetIO().WantCaptureMouse) {
|
||||
return UIScreen::touch(touch);
|
||||
}
|
||||
} else if (g_Config.bMouseControl && !(touch.flags & TouchInputFlags::UP) && (touch.flags & TouchInputFlags::MOUSE)) {
|
||||
if (g_Config.bMouseControl && !(touch.flags & TouchInputFlags::UP) && (touch.flags & TouchInputFlags::MOUSE)) {
|
||||
// don't do anything as the mouse pointer is hidden in this case.
|
||||
// But we let touch-up events through to avoid getting stuck if the user toggles mouse control.
|
||||
} else {
|
||||
@@ -1385,20 +1334,10 @@ void EmuScreen::deviceLost() {
|
||||
}
|
||||
|
||||
UIScreen::deviceLost();
|
||||
|
||||
if (imguiInited_) {
|
||||
if (imDebugger_) {
|
||||
imDebugger_->DeviceLost();
|
||||
}
|
||||
ImGui_ImplThin3d_DestroyDeviceObjects();
|
||||
}
|
||||
}
|
||||
|
||||
void EmuScreen::deviceRestored(Draw::DrawContext *draw) {
|
||||
UIScreen::deviceRestored(draw);
|
||||
if (imguiInited_) {
|
||||
ImGui_ImplThin3d_CreateDeviceObjects(draw);
|
||||
}
|
||||
}
|
||||
|
||||
void EmuScreen::OnDevTools(UI::EventParams ¶ms) {
|
||||
@@ -1707,7 +1646,6 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
|
||||
Draw::BackendState state = draw->GetCurrentBackendState();
|
||||
|
||||
if (!(mode & ScreenRenderMode::TOP)) {
|
||||
renderImDebugger();
|
||||
// We're in run-behind mode, but we don't want to draw chat, debug UI and stuff. We do draw the imdebugger though.
|
||||
// So, darken and bail here.
|
||||
// Reset viewport/scissor to be sure.
|
||||
@@ -1735,7 +1673,7 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
|
||||
SetVRAppMode(screenManager()->topScreen() == this ? VRAppMode::VR_GAME_MODE : VRAppMode::VR_DIALOG_MODE);
|
||||
}
|
||||
|
||||
renderImDebugger();
|
||||
// renderImDebugger();
|
||||
return screenRenderFlags;
|
||||
}
|
||||
|
||||
@@ -1859,108 +1797,9 @@ ScreenRenderFlags EmuScreen::RunEmulation(bool skipBufferEffects) {
|
||||
}
|
||||
}
|
||||
|
||||
runImDebugger();
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void EmuScreen::runImDebugger() {
|
||||
if (!lastImguiEnabled_ && g_Config.bShowImDebugger) {
|
||||
#if !defined(MOBILE_DEVICE)
|
||||
// On mobile devices (specifically iOS) we don't want to pop the keyboard
|
||||
// on activating imgui. Instead, we should do it when a text edit field in imgui gets focus,
|
||||
// although we'll still have ugly overlap problems.
|
||||
System_NotifyUIEvent(UIEventNotification::TEXT_GOTFOCUS);
|
||||
#endif
|
||||
VERBOSE_LOG(Log::System, "activating keyboard");
|
||||
} else if (lastImguiEnabled_ && !g_Config.bShowImDebugger) {
|
||||
System_NotifyUIEvent(UIEventNotification::TEXT_LOSTFOCUS);
|
||||
VERBOSE_LOG(Log::System, "deactivating keyboard");
|
||||
}
|
||||
lastImguiEnabled_ = g_Config.bShowImDebugger;
|
||||
if (g_Config.bShowImDebugger) {
|
||||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||
if (!imguiInited_) {
|
||||
// TODO: Do this only on demand.
|
||||
IMGUI_CHECKVERSION();
|
||||
ctx_ = ImGui::CreateContext();
|
||||
|
||||
ImGui_ImplPlatform_Init(GetSysDirectory(DIRECTORY_SYSTEM) / "imgui.ini");
|
||||
imDebugger_ = std::make_unique<ImDebugger>();
|
||||
|
||||
// Read the TTF font
|
||||
size_t propSize = 0;
|
||||
const uint8_t *propFontData = g_VFS.ReadFile("Roboto_Condensed-Regular.ttf", &propSize);
|
||||
size_t fixedSize = 0;
|
||||
const uint8_t *fixedFontData = g_VFS.ReadFile("Inconsolata-Regular.ttf", &fixedSize);
|
||||
// This call works even if fontData is nullptr, in which case the font just won't get loaded.
|
||||
// This takes ownership of the font array.
|
||||
ImGui_ImplThin3d_Init(draw, propFontData, propSize, fixedFontData, fixedSize);
|
||||
imguiInited_ = true;
|
||||
}
|
||||
|
||||
if (PSP_IsInited()) {
|
||||
_dbg_assert_(imDebugger_);
|
||||
|
||||
ImGui_ImplPlatform_NewFrame();
|
||||
ImGui_ImplThin3d_NewFrame(draw, ui_draw2d.GetDrawMatrix());
|
||||
|
||||
ImGui::NewFrame();
|
||||
|
||||
if (imCmd_.cmd != ImCmd::NONE) {
|
||||
imDebugger_->PostCmd(imCmd_);
|
||||
imCmd_.cmd = ImCmd::NONE;
|
||||
}
|
||||
|
||||
// Update keyboard modifiers.
|
||||
auto &io = ImGui::GetIO();
|
||||
|
||||
KeyModifier modifiers = NativeGetKeyModifiers();
|
||||
|
||||
const bool keyCtrl = (modifiers & KeyModifier::LCTRL) || (modifiers & KeyModifier::RCTRL);
|
||||
const bool keyShift = (modifiers & KeyModifier::LSHIFT) || (modifiers & KeyModifier::RSHIFT);
|
||||
const bool keyAlt = (modifiers & KeyModifier::LALT) || (modifiers & KeyModifier::RALT);
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, keyCtrl);
|
||||
io.AddKeyEvent(ImGuiMod_Shift, keyShift);
|
||||
io.AddKeyEvent(ImGuiMod_Alt, keyAlt);
|
||||
// io.AddKeyEvent(ImGuiMod_Super, e.key.super);
|
||||
|
||||
ImGuiID dockID = ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_NoDockingOverCentralNode);
|
||||
ImGuiDockNode* node = ImGui::DockBuilderGetCentralNode(dockID);
|
||||
|
||||
// Not elegant! But don't know how else to pass through the bounds, without making a mess.
|
||||
Bounds centralNode(node->Pos.x, node->Pos.y, node->Size.x, node->Size.y);
|
||||
SetOverrideScreenFrame(¢ralNode);
|
||||
|
||||
if (!io.WantCaptureKeyboard) {
|
||||
// Draw a focus rectangle to indicate inputs will be passed through.
|
||||
ImGui::GetBackgroundDrawList()->AddRect
|
||||
(
|
||||
node->Pos,
|
||||
{ node->Pos.x + node->Size.x, node->Pos.y + node->Size.y },
|
||||
IM_COL32(255, 255, 255, 90),
|
||||
0.f,
|
||||
ImDrawFlags_None,
|
||||
1.f
|
||||
);
|
||||
}
|
||||
imDebugger_->Frame(currentDebugMIPS, gpu, draw);
|
||||
|
||||
// Convert to drawlists.
|
||||
ImGui::Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EmuScreen::renderImDebugger() {
|
||||
if (g_Config.bShowImDebugger) {
|
||||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||
if (PSP_IsInited() && imDebugger_) {
|
||||
ImGui_ImplThin3d_RenderDrawData(ImGui::GetDrawData(), draw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool EmuScreen::hasVisibleUI() {
|
||||
// Regular but uncommon UI.
|
||||
if (saveStatePreview_->GetVisibility() != UI::V_GONE || loadingSpinner_->GetVisibility() == UI::V_VISIBLE)
|
||||
|
||||
@@ -61,10 +61,6 @@ public:
|
||||
void deviceLost() override;
|
||||
void deviceRestored(Draw::DrawContext *draw) override;
|
||||
|
||||
void SendImDebuggerCommand(const ImCommand &command) {
|
||||
imCmd_ = command;
|
||||
}
|
||||
|
||||
protected:
|
||||
void darken();
|
||||
void focusChanged(ScreenFocusChange focusChange) override;
|
||||
@@ -91,9 +87,6 @@ private:
|
||||
void bootComplete();
|
||||
bool hasVisibleUI();
|
||||
void renderUI();
|
||||
void runImDebugger();
|
||||
void renderImDebugger();
|
||||
|
||||
|
||||
void AutoLoadSaveState();
|
||||
bool checkPowerDown();
|
||||
@@ -141,18 +134,9 @@ private:
|
||||
|
||||
std::string extraAssertInfoStr_;
|
||||
|
||||
std::unique_ptr<ImDebugger> imDebugger_;
|
||||
ImCommand imCmd_{}; // needed to buffer commands in case imgui wasn't created yet.
|
||||
|
||||
bool imguiInited_ = false;
|
||||
|
||||
bool lastImguiEnabled_ = false;
|
||||
|
||||
std::mutex queuedVirtKeysLock_;
|
||||
std::vector<std::pair<VirtKey, bool>> queuedVirtKeys_;
|
||||
|
||||
ImGuiContext *ctx_ = nullptr;
|
||||
|
||||
bool frameStep_ = false;
|
||||
#ifndef MOBILE_DEVICE
|
||||
bool startDumping_ = false;
|
||||
|
||||
@@ -2363,19 +2363,21 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUCommon *gpuDebug, Draw:
|
||||
|
||||
// Watch the step counters to figure out when to update things.
|
||||
|
||||
if (lastCpuStepCount_ != Core_GetSteppingCounter()) {
|
||||
lastCpuStepCount_ = Core_GetSteppingCounter();
|
||||
snapshot_ = newSnapshot_; // Compare against the previous snapshot.
|
||||
Snapshot(currentMIPS);
|
||||
disasm_.NotifyStep();
|
||||
}
|
||||
if (PSP_IsInited()) {
|
||||
if (lastCpuStepCount_ != Core_GetSteppingCounter()) {
|
||||
lastCpuStepCount_ = Core_GetSteppingCounter();
|
||||
snapshot_ = newSnapshot_; // Compare against the previous snapshot.
|
||||
Snapshot(currentMIPS);
|
||||
disasm_.NotifyStep();
|
||||
}
|
||||
|
||||
if (lastGpuStepCount_ != GPUStepping::GetSteppingCounter()) {
|
||||
// A GPU step has happened since last time. This means that we should re-center the cursor.
|
||||
// Snapshot();
|
||||
lastGpuStepCount_ = GPUStepping::GetSteppingCounter();
|
||||
SnapshotGPU(gpuDebug);
|
||||
geDebugger_.NotifyStep();
|
||||
if (gpuDebug && lastGpuStepCount_ != GPUStepping::GetSteppingCounter()) {
|
||||
// A GPU step has happened since last time. This means that we should re-center the cursor.
|
||||
// Snapshot();
|
||||
lastGpuStepCount_ = GPUStepping::GetSteppingCounter();
|
||||
SnapshotGPU(gpuDebug);
|
||||
geDebugger_.NotifyStep();
|
||||
}
|
||||
}
|
||||
|
||||
ImControl control{};
|
||||
@@ -2645,12 +2647,14 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUCommon *gpuDebug, Draw:
|
||||
atracToolWindow_.Draw(cfg_);
|
||||
}
|
||||
|
||||
if (cfg_.framebuffersOpen) {
|
||||
DrawFramebuffersWindow(cfg_, gpuDebug->GetFramebufferManagerCommon());
|
||||
}
|
||||
if (gpuDebug) {
|
||||
if (cfg_.framebuffersOpen) {
|
||||
DrawFramebuffersWindow(cfg_, gpuDebug->GetFramebufferManagerCommon());
|
||||
}
|
||||
|
||||
if (cfg_.texturesOpen) {
|
||||
DrawTexturesWindow(cfg_, gpuDebug->GetTextureCacheCommon());
|
||||
if (cfg_.texturesOpen) {
|
||||
DrawTexturesWindow(cfg_, gpuDebug->GetTextureCacheCommon());
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg_.logConfigOpen) {
|
||||
@@ -2661,78 +2665,82 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUCommon *gpuDebug, Draw:
|
||||
logWindow_.Draw(cfg_);
|
||||
}
|
||||
|
||||
if (cfg_.jitViewerOpen) {
|
||||
jitViewer_.Draw(cfg_, control);
|
||||
}
|
||||
if (PSP_IsInited()) {
|
||||
if (cfg_.jitViewerOpen) {
|
||||
jitViewer_.Draw(cfg_, control);
|
||||
}
|
||||
|
||||
if (cfg_.displayOpen) {
|
||||
DrawDisplayWindow(cfg_, gpuDebug->GetFramebufferManagerCommon());
|
||||
}
|
||||
if (cfg_.displayOpen) {
|
||||
DrawDisplayWindow(cfg_, gpuDebug->GetFramebufferManagerCommon());
|
||||
}
|
||||
|
||||
if (cfg_.debugStatsOpen) {
|
||||
DrawDebugStatsWindow(cfg_);
|
||||
if (cfg_.debugStatsOpen) {
|
||||
DrawDebugStatsWindow(cfg_);
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg_.structViewerOpen) {
|
||||
structViewer_.Draw(cfg_, control, mipsDebug);
|
||||
}
|
||||
|
||||
if (cfg_.paramSFOOpen) {
|
||||
DrawParamSFO(cfg_, control);
|
||||
}
|
||||
|
||||
if (cfg_.geDebuggerOpen) {
|
||||
geDebugger_.Draw(cfg_, control, gpuDebug, draw);
|
||||
}
|
||||
|
||||
if (cfg_.geStateOpen) {
|
||||
geStateWindow_.Draw(cfg_, control, gpuDebug);
|
||||
}
|
||||
|
||||
if (cfg_.geVertsOpen) {
|
||||
DrawImGeVertsWindow(cfg_, control, gpuDebug);
|
||||
}
|
||||
|
||||
if (cfg_.schedulerOpen) {
|
||||
DrawSchedulerView(cfg_);
|
||||
}
|
||||
|
||||
if (cfg_.timeOpen) {
|
||||
DrawTimeView(cfg_);
|
||||
}
|
||||
|
||||
if (cfg_.pixelViewerOpen) {
|
||||
pixelViewer_.Draw(cfg_, control, gpuDebug, draw);
|
||||
}
|
||||
|
||||
if (cfg_.memDumpOpen) {
|
||||
memDumpWindow_.Draw(cfg_, mipsDebug);
|
||||
}
|
||||
|
||||
if (cfg_.watchOpen) {
|
||||
watchWindow_.Draw(cfg_, control, mipsDebug);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (cfg_.memViewOpen[i]) {
|
||||
mem_[i].Draw(mipsDebug, cfg_, control, i);
|
||||
if (PSP_IsInited()) {
|
||||
if (cfg_.paramSFOOpen) {
|
||||
DrawParamSFO(cfg_, control);
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg_.socketsOpen) {
|
||||
DrawSockets(cfg_);
|
||||
}
|
||||
if (cfg_.geDebuggerOpen) {
|
||||
geDebugger_.Draw(cfg_, control, gpuDebug, draw);
|
||||
}
|
||||
|
||||
if (cfg_.npOpen) {
|
||||
DrawNp(cfg_);
|
||||
}
|
||||
if (cfg_.geStateOpen) {
|
||||
geStateWindow_.Draw(cfg_, control, gpuDebug);
|
||||
}
|
||||
|
||||
if (cfg_.adhocOpen) {
|
||||
DrawAdhoc(cfg_);
|
||||
}
|
||||
if (cfg_.geVertsOpen) {
|
||||
DrawImGeVertsWindow(cfg_, control, gpuDebug);
|
||||
}
|
||||
|
||||
if (cfg_.apctlOpen) {
|
||||
DrawApctl(cfg_);
|
||||
if (cfg_.schedulerOpen) {
|
||||
DrawSchedulerView(cfg_);
|
||||
}
|
||||
|
||||
if (cfg_.timeOpen) {
|
||||
DrawTimeView(cfg_);
|
||||
}
|
||||
|
||||
if (cfg_.pixelViewerOpen) {
|
||||
pixelViewer_.Draw(cfg_, control, gpuDebug, draw);
|
||||
}
|
||||
|
||||
if (cfg_.memDumpOpen) {
|
||||
memDumpWindow_.Draw(cfg_, mipsDebug);
|
||||
}
|
||||
|
||||
if (cfg_.watchOpen) {
|
||||
watchWindow_.Draw(cfg_, control, mipsDebug);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (cfg_.memViewOpen[i]) {
|
||||
mem_[i].Draw(mipsDebug, cfg_, control, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg_.socketsOpen) {
|
||||
DrawSockets(cfg_);
|
||||
}
|
||||
|
||||
if (cfg_.npOpen) {
|
||||
DrawNp(cfg_);
|
||||
}
|
||||
|
||||
if (cfg_.adhocOpen) {
|
||||
DrawAdhoc(cfg_);
|
||||
}
|
||||
|
||||
if (cfg_.apctlOpen) {
|
||||
DrawApctl(cfg_);
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg_.internalsOpen) {
|
||||
|
||||
+12
-2
@@ -436,14 +436,24 @@ void ViewSearch::ApplySearchFilter(UI::ViewGroup *viewGroup, bool setKeyboardFoc
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsSearchableChar(int unichar) {
|
||||
// 127 gets produced from Ctrl+Backspace on Windows for some reason.
|
||||
return unichar >= 0x20 && unichar != 127;
|
||||
}
|
||||
|
||||
static bool IsFirstSearchableChar(int unichar) {
|
||||
// Don't allow spaces as the first character, it looks confusing (empty search field)
|
||||
return IsSearchableChar(unichar) && unichar != ' ' && unichar != '`' && unichar != '.' && unichar != ',';
|
||||
}
|
||||
|
||||
bool ViewSearch::Key(UI::ViewGroup *viewGroup, const KeyInput &input) {
|
||||
bool retval = false;
|
||||
// Only one is visible at a time, so we can just grab all Char input.
|
||||
if (input.flags & KeyInputFlags::CHAR) {
|
||||
const int unichar = input.keyCode;
|
||||
if (unichar >= 0x20 && unichar != 127) { // 127 gets produced from Ctrl+Backspace on Windows for some reason.
|
||||
if (IsSearchableChar(unichar)) {
|
||||
// Don't allow spaces as the first character, it looks confusing (empty search field)
|
||||
if (searchFilter.empty() && unichar == ' ') {
|
||||
if (searchFilter.empty() && !IsFirstSearchableChar(unichar)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+202
-2
@@ -38,6 +38,13 @@
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
|
||||
#include "ext/imgui/imgui.h"
|
||||
#include "ext/imgui/imgui_internal.h"
|
||||
#include "ext/imgui/imgui_impl_thin3d.h"
|
||||
#include "ext/imgui/imgui_impl_platform.h"
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "Windows/WindowsAudio.h"
|
||||
#include "Windows/MainWindow.h"
|
||||
@@ -121,6 +128,7 @@
|
||||
|
||||
#include "GPU/GPUCommon.h"
|
||||
#include "GPU/Common/PresentationCommon.h"
|
||||
#include "UI/ImDebugger/ImDebugger.h"
|
||||
#include "UI/AudioCommon.h"
|
||||
#include "UI/Background.h"
|
||||
#include "UI/BackgroundAudio.h"
|
||||
@@ -139,7 +147,6 @@
|
||||
#include "UI/Theme.h"
|
||||
#include "UI/PauseScreen.h"
|
||||
#include "UI/UIAtlas.h"
|
||||
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
#include <dwrite_3.h>
|
||||
#include "UWP/UWPHelpers/InputHelpers.h"
|
||||
@@ -202,6 +209,32 @@ static bool g_nativeMainThreadReady = false;
|
||||
static std::mutex g_inputEventQueueLock;
|
||||
static std::vector<QueuedEvent> g_inputEventQueue;
|
||||
|
||||
static std::unique_ptr<ImDebugger> imDebugger_;
|
||||
static ImCommand imCmd_{}; // needed to buffer commands in case imgui wasn't created yet.
|
||||
static bool imguiInited_ = false;
|
||||
static bool lastImguiEnabled_ = false;
|
||||
static ImGuiContext *ctx_ = nullptr;
|
||||
|
||||
class GlobalListener : public ControlListener {
|
||||
virtual void OnVKey(VirtKey vkey, bool down) {
|
||||
switch (vkey) {
|
||||
case VIRTKEY_TOGGLE_DEBUGGER:
|
||||
if (down) {
|
||||
g_Config.bShowImDebugger = !g_Config.bShowImDebugger;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
GlobalListener g_globalListener;
|
||||
|
||||
static void AssertCancelCallback(const char *message, void *userdata) {
|
||||
NOTICE_LOG(Log::CPU, "Broke after assert: %s", message);
|
||||
Core_Break(BreakReason::AssertChoice);
|
||||
g_Config.bShowImDebugger = true;
|
||||
imCmd_ = ImCommand{ImCmd::SHOW_IN_CPU_DISASM, currentMIPS->pc};
|
||||
}
|
||||
|
||||
static void ApplyAchievementsRuntimeSettings() {
|
||||
auto *client = Achievements::GetClient();
|
||||
if (!client) {
|
||||
@@ -261,6 +294,101 @@ static void RunAchievementsOverrideUpdate(std::function<void()> func) {
|
||||
}
|
||||
}
|
||||
|
||||
void runImDebugger(Draw::DrawContext *draw) {
|
||||
bool lastImguiEnabled_ = false; // temp
|
||||
if (lastImguiEnabled_ && g_Config.bShowImDebugger) {
|
||||
#if !defined(MOBILE_DEVICE)
|
||||
// On mobile devices (specifically iOS) we don't want to pop the keyboard
|
||||
// on activating imgui. Instead, we should do it when a text edit field in imgui gets focus,
|
||||
// although we'll still have ugly overlap problems.
|
||||
System_NotifyUIEvent(UIEventNotification::TEXT_GOTFOCUS);
|
||||
#endif
|
||||
VERBOSE_LOG(Log::System, "activating keyboard");
|
||||
} else if (lastImguiEnabled_ && !g_Config.bShowImDebugger) {
|
||||
System_NotifyUIEvent(UIEventNotification::TEXT_LOSTFOCUS);
|
||||
VERBOSE_LOG(Log::System, "deactivating keyboard");
|
||||
}
|
||||
lastImguiEnabled_ = g_Config.bShowImDebugger;
|
||||
if (g_Config.bShowImDebugger) {
|
||||
if (!imguiInited_) {
|
||||
// TODO: Do this only on demand.
|
||||
IMGUI_CHECKVERSION();
|
||||
ctx_ = ImGui::CreateContext();
|
||||
|
||||
ImGui_ImplPlatform_Init(GetSysDirectory(DIRECTORY_SYSTEM) / "imgui.ini");
|
||||
imDebugger_ = std::make_unique<ImDebugger>();
|
||||
|
||||
// Read the TTF font
|
||||
size_t propSize = 0;
|
||||
const uint8_t *propFontData = g_VFS.ReadFile("Roboto_Condensed-Regular.ttf", &propSize);
|
||||
size_t fixedSize = 0;
|
||||
const uint8_t *fixedFontData = g_VFS.ReadFile("Inconsolata-Regular.ttf", &fixedSize);
|
||||
// This call works even if fontData is nullptr, in which case the font just won't get loaded.
|
||||
// This takes ownership of the font array.
|
||||
ImGui_ImplThin3d_Init(draw, propFontData, propSize, fixedFontData, fixedSize);
|
||||
imguiInited_ = true;
|
||||
}
|
||||
|
||||
_dbg_assert_(imDebugger_);
|
||||
|
||||
ImGui_ImplPlatform_NewFrame();
|
||||
ImGui_ImplThin3d_NewFrame(draw, ui_draw2d.GetDrawMatrix());
|
||||
|
||||
ImGui::NewFrame();
|
||||
|
||||
if (imCmd_.cmd != ImCmd::NONE) {
|
||||
imDebugger_->PostCmd(imCmd_);
|
||||
imCmd_.cmd = ImCmd::NONE;
|
||||
}
|
||||
|
||||
// Update keyboard modifiers.
|
||||
auto &io = ImGui::GetIO();
|
||||
|
||||
KeyModifier modifiers = NativeGetKeyModifiers();
|
||||
|
||||
const bool keyCtrl = (modifiers & KeyModifier::LCTRL) || (modifiers & KeyModifier::RCTRL);
|
||||
const bool keyShift = (modifiers & KeyModifier::LSHIFT) || (modifiers & KeyModifier::RSHIFT);
|
||||
const bool keyAlt = (modifiers & KeyModifier::LALT) || (modifiers & KeyModifier::RALT);
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, keyCtrl);
|
||||
io.AddKeyEvent(ImGuiMod_Shift, keyShift);
|
||||
io.AddKeyEvent(ImGuiMod_Alt, keyAlt);
|
||||
// io.AddKeyEvent(ImGuiMod_Super, e.key.super);
|
||||
|
||||
ImGuiID dockID = ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_NoDockingOverCentralNode);
|
||||
ImGuiDockNode* node = ImGui::DockBuilderGetCentralNode(dockID);
|
||||
|
||||
// Not elegant! But don't know how else to pass through the bounds, without making a mess.
|
||||
Bounds centralNode(node->Pos.x, node->Pos.y, node->Size.x, node->Size.y);
|
||||
SetOverrideScreenFrame(¢ralNode);
|
||||
|
||||
if (!io.WantCaptureKeyboard) {
|
||||
// Draw a focus rectangle to indicate inputs will be passed through.
|
||||
ImGui::GetBackgroundDrawList()->AddRect
|
||||
(
|
||||
node->Pos,
|
||||
{node->Pos.x + node->Size.x, node->Pos.y + node->Size.y},
|
||||
IM_COL32(255, 255, 255, 90),
|
||||
0.f,
|
||||
ImDrawFlags_None,
|
||||
1.f
|
||||
);
|
||||
}
|
||||
imDebugger_->Frame(currentDebugMIPS, gpu, draw);
|
||||
|
||||
// Convert to drawlists.
|
||||
ImGui::Render();
|
||||
}
|
||||
}
|
||||
|
||||
void renderImDebugger(Draw::DrawContext *draw) {
|
||||
if (g_Config.bShowImDebugger) {
|
||||
if (imDebugger_) {
|
||||
ImGui_ImplThin3d_RenderDrawData(ImGui::GetDrawData(), draw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::function<void()>> g_pendingClosures;
|
||||
|
||||
AudioBackend *g_audioBackend = nullptr;
|
||||
@@ -395,6 +523,10 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO
|
||||
|
||||
g_Config.Init();
|
||||
|
||||
g_controlMapper.AddListener(&g_globalListener);
|
||||
|
||||
SetAssertCancelCallback(&AssertCancelCallback, nullptr);
|
||||
|
||||
IncrementDebugCounter(DebugCounter::APP_BOOT);
|
||||
|
||||
// Probably an excessive timeout. it only causes delays on shutdown, though.
|
||||
@@ -851,6 +983,11 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) {
|
||||
gpu->DeviceRestore(g_draw);
|
||||
}
|
||||
|
||||
if (imguiInited_) {
|
||||
ImGui_ImplThin3d_CreateDeviceObjects(g_draw);
|
||||
}
|
||||
|
||||
|
||||
INFO_LOG(Log::System, "NativeInitGraphics completed");
|
||||
|
||||
return true;
|
||||
@@ -922,6 +1059,15 @@ void NativeShutdownGraphics(GraphicsContext *graphicsContext) {
|
||||
gpu->DeviceLost();
|
||||
}
|
||||
|
||||
if (imguiInited_) {
|
||||
if (imDebugger_) {
|
||||
imDebugger_->DeviceLost();
|
||||
}
|
||||
ImGui_ImplThin3d_DestroyDeviceObjects();
|
||||
ImGui_ImplThin3d_Shutdown();
|
||||
ImGui::DestroyContext(ctx_);
|
||||
}
|
||||
|
||||
#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
|
||||
if (winCamera) {
|
||||
winCamera->waitShutDown();
|
||||
@@ -1038,8 +1184,47 @@ void NativeFrame(GraphicsContext *graphicsContext) {
|
||||
}
|
||||
|
||||
for (auto &event : inputEvents) {
|
||||
g_screenManager->ProcessInputEvent(event);
|
||||
bool filterTouch = false;
|
||||
bool filterKey = false;
|
||||
if (g_Config.bShowImDebugger && imguiInited_) {
|
||||
// Let ImGui handle input if it's active.
|
||||
if (ImGui::GetIO().WantCaptureMouse) {
|
||||
filterTouch = true;
|
||||
}
|
||||
if (ImGui::GetIO().WantCaptureKeyboard) {
|
||||
filterKey = true;
|
||||
}
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case QueuedEventType::KEY:
|
||||
// Let through up events to avoid stuck keys.
|
||||
if (!filterKey || (event.key.flags & KeyInputFlags::UP)) {
|
||||
g_screenManager->ProcessInputEvent(event);
|
||||
}
|
||||
break;
|
||||
case QueuedEventType::TOUCH:
|
||||
if (!filterTouch) {
|
||||
g_screenManager->ProcessInputEvent(event);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_screenManager->ProcessInputEvent(event);
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_Config.bShowImDebugger && imguiInited_) {
|
||||
switch (event.type) {
|
||||
case QueuedEventType::KEY:
|
||||
ImGui_ImplPlatform_KeyEvent(event.key);
|
||||
break;
|
||||
case QueuedEventType::TOUCH:
|
||||
ImGui_ImplPlatform_TouchEvent(event.touch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_screenManager->Update(); // This must happen *after* input event processing!
|
||||
|
||||
// Do this after g_screenManager.update() so we can receive setting changes before rendering.
|
||||
@@ -1111,6 +1296,8 @@ void NativeFrame(GraphicsContext *graphicsContext) {
|
||||
|
||||
ui_draw2d.PopDrawMatrix();
|
||||
|
||||
runImDebugger(g_draw);
|
||||
renderImDebugger(g_draw);
|
||||
g_draw->EndFrame();
|
||||
|
||||
// This, between EndFrame and Present, is where we should actually wait to do present time management.
|
||||
@@ -1379,6 +1566,16 @@ bool NativeKey(const KeyInput &key) {
|
||||
|
||||
// Filtering, detailed rules needed for good imgui behavior without having to ask the screen about what to do.
|
||||
InputMode inputMode = g_screenManager->PassInputToMapper();
|
||||
|
||||
if (g_Config.bShowImDebugger && imguiInited_) {
|
||||
if (ImGui::GetIO().WantCaptureKeyboard) {
|
||||
inputMode &= ~InputMode::Keyboard;
|
||||
}
|
||||
if (ImGui::GetIO().WantCaptureMouse) {
|
||||
inputMode &= ~InputMode::Mouse;
|
||||
}
|
||||
}
|
||||
|
||||
bool passKeyThrough = false;
|
||||
if (inputMode != InputMode::None) {
|
||||
if ((inputMode & InputMode::ImDebuggerToggle) && (key.flags & (KeyInputFlags::UP | KeyInputFlags::DOWN))) {
|
||||
@@ -1394,6 +1591,7 @@ bool NativeKey(const KeyInput &key) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (key.deviceId == DEVICE_ID_MOUSE) {
|
||||
if (inputMode & InputMode::Mouse) {
|
||||
passKeyThrough = true;
|
||||
@@ -1637,6 +1835,8 @@ void NativeShutdown() {
|
||||
ClearAchievementsHostOverride();
|
||||
g_nativeMainThreadReady = false;
|
||||
|
||||
g_controlMapper.RemoveListener(&g_globalListener);
|
||||
|
||||
Achievements::Shutdown();
|
||||
|
||||
if (g_Config.bAchievementsEnable) {
|
||||
|
||||
Reference in new issue
Block a user