8#include "absl/strings/str_format.h"
13#include "imgui/imgui.h"
37 return ImVec4(0.2f, 0.8f, 0.2f, 1.0f);
39 return ImVec4(0.9f, 0.7f, 0.1f, 1.0f);
40 return ImVec4(0.9f, 0.2f, 0.2f, 1.0f);
57 std::shared_ptr<emu::mesen::MesenSocketClient> client) {
70 auto status =
client_->Connect();
84 auto status =
client_->Connect(socket_path);
121 auto emu_result =
client_->GetState();
122 if (emu_result.ok()) {
127 auto game_result =
client_->GetGameState();
128 if (game_result.ok()) {
134 if (sprite_result.ok()) {
140 auto cpu_result =
client_->GetCpuState();
141 if (cpu_result.ok()) {
148 ImGui::PushID(
"MesenDebugPanel");
160 if (ImGui::BeginChild(
"MesenDebug_Panel", ImVec2(0, 0),
true)) {
161 if (ImGui::IsWindowAppearing()) {
190 ImGui::SameLine(ImGui::GetWindowWidth() - 100);
192 float pulse = 0.7f + 0.3f * std::sin(ImGui::GetTime() * 2.0f);
193 ImVec4 connected_color = ImVec4(0.1f, pulse, 0.3f, 1.0f);
196 ImGui::TextColored(theme.status_error,
"%s Disconnected",
ICON_MD_ERROR);
203 ImGui::TextDisabled(
"Socket");
204 const char* preview =
206 selected_socket_index_ < static_cast<int>(
socket_paths_.size()))
208 :
"No sockets found";
209 ImGui::SetNextItemWidth(-40);
210 if (ImGui::BeginCombo(
"##mesen_socket_combo", preview)) {
211 for (
int i = 0; i < static_cast<int>(
socket_paths_.size()); ++i) {
219 ImGui::SetItemDefaultFocus();
229 ImGui::TextDisabled(
"Path");
230 ImGui::SetNextItemWidth(-1);
231 ImGui::InputTextWithHint(
"##mesen_socket_path",
"/tmp/mesen2-12345.sock",
262 ImGui::SetNextItemWidth(60);
270 ImGui::TextColored(theme.text_secondary_color,
"%s",
278 if (ImGui::CollapsingHeader(
287 ImGui::Text(
"Position:");
289 ImGui::TextColored(theme.text_secondary_color,
"X=%d, Y=%d Layer: %d",
290 link.x, link.y, link.layer);
293 ImGui::Text(
"Direction:");
295 ImGui::TextColored(theme.text_secondary_color,
"%s (0x%02X)",
298 ImGui::Text(
" State:");
300 ImGui::TextColored(theme.text_secondary_color,
"0x%02X", link.state);
303 float health_ratio = items.max_health > 0
304 ?
static_cast<float>(items.current_health) /
305 static_cast<float>(items.max_health)
309 ImGui::Text(
"Health:");
313 int full_hearts = items.current_health / 8;
314 int max_hearts = items.max_health / 8;
316 gui::StyleColorGuard full_heart_guard(ImGuiCol_Text, health_color);
317 for (
int i = 0; i < full_hearts; ++i) {
318 ImGui::SameLine(0, 0);
323 gui::StyleColorGuard empty_heart_guard(ImGuiCol_Text,
324 ImVec4(0.3f, 0.3f, 0.3f, 1.0f));
325 for (
int i = full_hearts; i < max_hearts; ++i) {
326 ImGui::SameLine(0, 0);
332 ImGui::TextColored(theme.text_secondary_color,
" (%d/%d)",
333 items.current_health, items.max_health);
336 ImGui::Text(
"Items:");
338 ImGui::TextColored(theme.text_secondary_color,
339 "Magic: %d Rupees: %d Bombs: %d Arrows: %d",
340 items.magic, items.rupees, items.bombs, items.arrows);
349 std::string header = absl::StrFormat(
"%s Active Sprites (%zu/16)",
352 if (ImGui::CollapsingHeader(
360 ImGui::TextDisabled(
" No active sprites");
363 if (ImGui::BeginChild(
"SpriteList", ImVec2(0, 120),
true)) {
364 for (
const auto& sprite :
sprites_) {
365 ImGui::PushID(sprite.slot);
368 ImGui::TextColored(theme.text_secondary_color,
"[%d]", sprite.slot);
372 ImVec4 sprite_color = sprite.state > 0
373 ? ImVec4(0.4f, 0.8f, 0.4f, 1.0f)
374 : ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
375 ImGui::TextColored(sprite_color,
"Type: 0x%02X", sprite.type);
378 ImGui::Text(
"@ %d,%d", sprite.x, sprite.y);
381 if (sprite.health > 0) {
382 ImGui::TextColored(ImVec4(0.8f, 0.3f, 0.3f, 1.0f),
"HP:%d",
387 ImGui::TextColored(theme.text_secondary_color,
"State:%d",
404 if (ImGui::CollapsingHeader(
409 ImGui::Text(
"Mode:");
411 ImGui::TextColored(theme.text_secondary_color,
"%d (Submode: %d)",
412 game.mode, game.submode);
414 ImGui::Text(
"Location:");
417 ImGui::TextColored(ImVec4(0.6f, 0.4f, 0.2f, 1.0f),
"Dungeon Room: 0x%04X",
420 ImGui::TextColored(ImVec4(0.2f, 0.6f, 0.2f, 1.0f),
421 "Overworld Area: 0x%02X", game.overworld_area);
425 ImGui::Text(
"Frame:");
427 ImGui::TextColored(theme.text_secondary_color,
"%llu",
emu_state_.
frame);
430 ImGui::Text(
" FPS:");
432 ImGui::TextColored(theme.text_secondary_color,
"%.1f",
emu_state_.
fps);
438 ImGui::TextColored(theme.text_secondary_color,
439 "PC=$%02X:%04X A=$%04X X=$%04X Y=$%04X",
442 ImGui::TextColored(theme.text_secondary_color,
498 const char* colmaps[] = {
"A",
"B",
"C"};
499 bool overlay_changed =
false;
501 ImGui::TextDisabled(
"Collision Overlay");
503 overlay_changed =
true;
506 ImGui::SetNextItemWidth(60);
508 IM_ARRAYSIZE(colmaps))) {
509 overlay_changed =
true;
512 if (overlay_changed) {
519 ?
"Collision overlay enabled"
520 :
"Collision overlay disabled";
529 ImGui::TextDisabled(
"Save States");
530 ImGui::SetNextItemWidth(60);
539 : std::string(status.message());
546 : std::string(status.message());
551 auto screenshot =
client_->Screenshot();
552 if (!screenshot.ok()) {
556 ImGui::SetClipboardText(screenshot->c_str());
void Connect()
Attempt to connect to Mesen2.
char socket_path_buffer_[256]
int selected_socket_index_
std::string connection_error_
float time_since_refresh_
void Draw()
Draw the panel.
emu::mesen::GameState game_state_
void Disconnect()
Disconnect from Mesen2.
void SetClient(std::shared_ptr< emu::mesen::MesenSocketClient > client)
Set the socket client for Mesen2 communication.
std::vector< std::string > socket_paths_
emu::mesen::CpuState cpu_state_
void DrawControlButtons()
void DrawConnectionHeader()
bool IsConnected() const
Get connection status.
std::string status_message_
std::vector< emu::mesen::SpriteInfo > sprites_
bool collision_overlay_enabled_
void DrawOverlayControls()
emu::mesen::MesenState emu_state_
void ConnectToPath(const std::string &socket_path)
std::shared_ptr< emu::mesen::MesenSocketClient > client_
static void SetClient(std::shared_ptr< MesenSocketClient > client)
static std::shared_ptr< MesenSocketClient > GetOrCreate()
static std::vector< std::string > ListAvailableSockets()
List available Mesen2 sockets on the system.
#define ICON_MD_FAST_FORWARD
#define ICON_MD_PLAY_ARROW
#define ICON_MD_FAVORITE_BORDER
#define ICON_MD_BUG_REPORT
#define ICON_MD_AUTO_MODE
#define ICON_MD_CHECK_CIRCLE
#define ICON_MD_SKIP_NEXT
#define ICON_MD_PEST_CONTROL
#define ICON_MD_PHOTO_CAMERA
const AgentUITheme & GetTheme()
ImVec4 HealthColor(float ratio)
const char * DirectionToString(uint8_t dir)