yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
gui_commands.cc
Go to the documentation of this file.
2
3#include "absl/flags/declare.h"
4#include "absl/flags/flag.h"
5#include "absl/strings/numbers.h"
6#include "absl/strings/str_format.h"
7#include "absl/strings/str_join.h"
10#include "cli/util/hex_util.h"
11
12ABSL_DECLARE_FLAG(std::string, gui_server_address);
13ABSL_DECLARE_FLAG(bool, quiet);
14
15namespace yaze {
16namespace cli {
17namespace handlers {
18
20
22 Rom* rom, const resources::ArgumentParser& parser,
23 resources::OutputFormatter& formatter) {
24 auto tile_id_str = parser.GetString("tile").value();
25 auto x_str = parser.GetString("x").value();
26 auto y_str = parser.GetString("y").value();
27
28 int tile_id, x, y;
29 if (!ParseHexString(tile_id_str, &tile_id) ||
30 !absl::SimpleAtoi(x_str, &x) ||
31 !absl::SimpleAtoi(y_str, &y)) {
32 return absl::InvalidArgumentError("Invalid tile ID or coordinate format.");
33 }
34
35 CanvasAutomationClient client(absl::GetFlag(FLAGS_gui_server_address));
36 auto status = client.Connect();
37 if (!status.ok()) {
38 return absl::UnavailableError("Failed to connect to GUI server: " +
39 std::string(status.message()));
40 }
41
42 // Assume "overworld" canvas for now, or parse from args if needed
43 std::string canvas_id = "overworld";
44 status = client.SetTile(canvas_id, x, y, tile_id);
45
46 formatter.BeginObject("GUI Tile Placement");
47 formatter.AddField("tile_id", absl::StrFormat("0x%03X", tile_id));
48 formatter.AddField("x", x);
49 formatter.AddField("y", y);
50 if (status.ok()) {
51 formatter.AddField("status", "Success");
52 } else {
53 formatter.AddField("status", "Failed");
54 formatter.AddField("error", std::string(status.message()));
55 }
56 formatter.EndObject();
57
58 return status;
59}
60
62 Rom* rom, const resources::ArgumentParser& parser,
63 resources::OutputFormatter& formatter) {
64 auto target = parser.GetString("target").value();
65 auto click_type_str = parser.GetString("click-type").value_or("left");
66
67 ClickType click_type = ClickType::kLeft;
68 if (click_type_str == "right")
69 click_type = ClickType::kRight;
70 else if (click_type_str == "double")
71 click_type = ClickType::kDouble;
72
73 GuiAutomationClient client(absl::GetFlag(FLAGS_gui_server_address));
74 auto status = client.Connect();
75 if (!status.ok()) {
76 return absl::UnavailableError("Failed to connect to GUI server: " +
77 std::string(status.message()));
78 }
79
80 auto result = client.Click(target, click_type);
81
82 formatter.BeginObject("GUI Click Action");
83 formatter.AddField("target", target);
84 formatter.AddField("click_type", click_type_str);
85
86 if (result.ok()) {
87 formatter.AddField("status", result->success ? "Success" : "Failed");
88 if (!result->success) {
89 formatter.AddField("error", result->message);
90 }
91 formatter.AddField("execution_time_ms",
92 static_cast<int>(result->execution_time.count()));
93 } else {
94 formatter.AddField("status", "Error");
95 formatter.AddField("error", std::string(result.status().message()));
96 }
97 formatter.EndObject();
98
99 return result.status();
100}
101
103 Rom* rom, const resources::ArgumentParser& parser,
104 resources::OutputFormatter& formatter) {
105 auto window = parser.GetString("window").value_or("");
106 auto type_str = parser.GetString("type").value_or("all");
107
108 // Detect if we were called as 'summarize' to provide more compact output
109 bool is_summary = (GetName() == "gui-summarize-widgets");
110
111 GuiAutomationClient client(absl::GetFlag(FLAGS_gui_server_address));
112 auto status = client.Connect();
113 if (!status.ok()) {
114 return absl::UnavailableError("Failed to connect to GUI server: " +
115 std::string(status.message()));
116 }
117
119 query.window_filter = window;
121 query.include_invisible = false;
122
123 auto result = client.DiscoverWidgets(query);
124
125 formatter.BeginObject(is_summary ? "GUI Summary" : "Widget Discovery");
126 formatter.AddField("window_filter", window);
127
128 if (result.ok()) {
129 formatter.AddField("total_widgets", result->total_widgets);
130 formatter.AddField("status", "Success");
131
132 formatter.BeginArray("windows");
133 for (const auto& win : result->windows) {
134 if (!win.visible && is_summary)
135 continue;
136
137 formatter.BeginObject("window");
138 formatter.AddField("name", win.name);
139 formatter.AddField("visible", win.visible);
140
141 if (is_summary) {
142 std::vector<std::string> highlights;
143 for (const auto& w : win.widgets) {
144 if (w.type == "button" || w.type == "input" || w.type == "menu") {
145 highlights.push_back(absl::StrFormat("%s (%s)", w.label, w.type));
146 }
147 if (highlights.size() > 10)
148 break;
149 }
150 formatter.AddField("key_elements", absl::StrJoin(highlights, ", "));
151 } else {
152 formatter.BeginArray("widgets");
153 int count = 0;
154 for (const auto& widget : win.widgets) {
155 if (count++ > 50)
156 break;
157 formatter.AddArrayItem(absl::StrFormat("%s (%s) - %s", widget.label,
158 widget.type, widget.path));
159 }
160 formatter.EndArray();
161 }
162 formatter.EndObject();
163 }
164 formatter.EndArray();
165 } else {
166 formatter.AddField("status", "Error");
167 formatter.AddField("error", std::string(result.status().message()));
168 }
169 formatter.EndObject();
170
171 return result.status();
172}
173
175 Rom* rom, const resources::ArgumentParser& parser,
176 resources::OutputFormatter& formatter) {
177 auto region = parser.GetString("region").value_or("full");
178 auto image_format = parser.GetString("format").value_or("PNG");
179
180 GuiAutomationClient client(absl::GetFlag(FLAGS_gui_server_address));
181 auto status = client.Connect();
182 if (!status.ok()) {
183 return absl::UnavailableError("Failed to connect to GUI server: " +
184 std::string(status.message()));
185 }
186
187 auto result = client.Screenshot(region, image_format);
188
189 formatter.BeginObject("Screenshot Capture");
190 formatter.AddField("region", region);
191 formatter.AddField("image_format", image_format);
192
193 if (result.ok()) {
194 formatter.AddField("status", result->success ? "Success" : "Failed");
195 if (result->success) {
196 formatter.AddField("output_path", result->message);
197
198 // Also print a user-friendly message directly to stderr for visibility
199 if (!absl::GetFlag(FLAGS_quiet)) {
200 std::cerr << "\n📸 \033[1;32mScreenshot captured!\033[0m\n";
201 std::cerr << " Path: \033[1;34m" << result->message << "\033[0m\n\n";
202 }
203 } else {
204 formatter.AddField("error", result->message);
205 }
206 } else {
207 formatter.AddField("status", "Error");
208 formatter.AddField("error", std::string(result.status().message()));
209 }
210 formatter.EndObject();
211
212 return result.status();
213}
214
215} // namespace handlers
216} // namespace cli
217} // namespace yaze
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:24
absl::Status SetTile(const std::string &canvas_id, int x, int y, int tile_id)
Client for automating YAZE GUI through gRPC.
absl::StatusOr< AutomationResult > Screenshot(const std::string &region="full", const std::string &format="PNG")
Capture a screenshot.
absl::Status Connect()
Connect to the test harness server.
absl::StatusOr< DiscoverWidgetsResult > DiscoverWidgets(const DiscoverWidgetsQuery &query)
absl::StatusOr< AutomationResult > Click(const std::string &target, ClickType type=ClickType::kLeft)
Click a GUI element.
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
std::string GetName() const
Get the command name.
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
Utility for parsing common CLI argument patterns.
std::optional< std::string > GetString(const std::string &name) const
Parse a named argument (e.g., –format=json or –format json)
Utility for consistent output formatting across commands.
void BeginArray(const std::string &key)
Begin an array.
void AddArrayItem(const std::string &item)
Add an item to current array.
void BeginObject(const std::string &title="")
Start a JSON object or text section.
void EndObject()
End a JSON object or text section.
void AddField(const std::string &key, const std::string &value)
Add a key-value pair.
ABSL_DECLARE_FLAG(std::string, gui_server_address)
bool ParseHexString(absl::string_view str, int *out)
Definition hex_util.h:17
ClickType
Type of click action to perform.