yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
canvas_automation_service.cc
Go to the documentation of this file.
2
3#ifdef YAZE_WITH_GRPC
4
5#include <grpcpp/grpcpp.h>
6#include "protos/canvas_automation.pb.h"
7#include "protos/canvas_automation.grpc.pb.h"
10
11namespace yaze {
12
13namespace {
14
15// Helper to convert absl::Status to grpc::Status
16grpc::Status ConvertStatus(const absl::Status& status) {
17 if (status.ok()) {
18 return grpc::Status::OK;
19 }
20
21 grpc::StatusCode code;
22 switch (status.code()) {
23 case absl::StatusCode::kNotFound:
24 code = grpc::StatusCode::NOT_FOUND;
25 break;
26 case absl::StatusCode::kInvalidArgument:
27 code = grpc::StatusCode::INVALID_ARGUMENT;
28 break;
29 case absl::StatusCode::kFailedPrecondition:
30 code = grpc::StatusCode::FAILED_PRECONDITION;
31 break;
32 case absl::StatusCode::kOutOfRange:
33 code = grpc::StatusCode::OUT_OF_RANGE;
34 break;
35 case absl::StatusCode::kUnimplemented:
36 code = grpc::StatusCode::UNIMPLEMENTED;
37 break;
38 case absl::StatusCode::kInternal:
39 code = grpc::StatusCode::INTERNAL;
40 break;
41 case absl::StatusCode::kUnavailable:
42 code = grpc::StatusCode::UNAVAILABLE;
43 break;
44 default:
45 code = grpc::StatusCode::UNKNOWN;
46 break;
47 }
48
49 return grpc::Status(code, std::string(status.message()));
50}
51
52} // namespace
53
54void CanvasAutomationServiceImpl::RegisterCanvas(const std::string& canvas_id,
55 gui::Canvas* canvas) {
56 canvases_[canvas_id] = canvas;
57}
58
59void CanvasAutomationServiceImpl::RegisterOverworldEditor(
60 const std::string& canvas_id, editor::OverworldEditor* editor) {
61 overworld_editors_[canvas_id] = editor;
62}
63
64gui::Canvas* CanvasAutomationServiceImpl::GetCanvas(const std::string& canvas_id) {
65 auto it = canvases_.find(canvas_id);
66 if (it != canvases_.end()) {
67 return it->second;
68 }
69 return nullptr;
70}
71
72editor::OverworldEditor* CanvasAutomationServiceImpl::GetOverworldEditor(
73 const std::string& canvas_id) {
74 auto it = overworld_editors_.find(canvas_id);
75 if (it != overworld_editors_.end()) {
76 return it->second;
77 }
78 return nullptr;
79}
80
81// ============================================================================
82// Tile Operations
83// ============================================================================
84
85absl::Status CanvasAutomationServiceImpl::SetTile(
86 const proto::SetTileRequest* request, proto::SetTileResponse* response) {
87
88 auto* canvas = GetCanvas(request->canvas_id());
89 if (!canvas) {
90 response->set_success(false);
91 response->set_error("Canvas not found: " + request->canvas_id());
92 return absl::NotFoundError(response->error());
93 }
94
95 auto* api = canvas->GetAutomationAPI();
96 bool success = api->SetTileAt(request->x(), request->y(), request->tile_id());
97
98 response->set_success(success);
99 if (!success) {
100 response->set_error("Failed to set tile - out of bounds or callback failed");
101 }
102
103 return absl::OkStatus();
104}
105
106absl::Status CanvasAutomationServiceImpl::GetTile(
107 const proto::GetTileRequest* request, proto::GetTileResponse* response) {
108
109 auto* canvas = GetCanvas(request->canvas_id());
110 if (!canvas) {
111 response->set_success(false);
112 response->set_error("Canvas not found: " + request->canvas_id());
113 return absl::NotFoundError(response->error());
114 }
115
116 auto* api = canvas->GetAutomationAPI();
117 int tile_id = api->GetTileAt(request->x(), request->y());
118
119 if (tile_id >= 0) {
120 response->set_tile_id(tile_id);
121 response->set_success(true);
122 } else {
123 response->set_success(false);
124 response->set_error("Tile not found - out of bounds or no callback set");
125 }
126
127 return absl::OkStatus();
128}
129
130absl::Status CanvasAutomationServiceImpl::SetTiles(
131 const proto::SetTilesRequest* request, proto::SetTilesResponse* response) {
132
133 auto* canvas = GetCanvas(request->canvas_id());
134 if (!canvas) {
135 response->set_success(false);
136 response->set_error("Canvas not found: " + request->canvas_id());
137 return absl::NotFoundError(response->error());
138 }
139
140 auto* api = canvas->GetAutomationAPI();
141
142 std::vector<std::tuple<int, int, int>> tiles;
143 for (const auto& tile : request->tiles()) {
144 tiles.push_back({tile.x(), tile.y(), tile.tile_id()});
145 }
146
147 bool success = api->SetTiles(tiles);
148 response->set_success(success);
149 response->set_tiles_painted(tiles.size());
150
151 return absl::OkStatus();
152}
153
154// ============================================================================
155// Selection Operations
156// ============================================================================
157
158absl::Status CanvasAutomationServiceImpl::SelectTile(
159 const proto::SelectTileRequest* request, proto::SelectTileResponse* response) {
160
161 auto* canvas = GetCanvas(request->canvas_id());
162 if (!canvas) {
163 response->set_success(false);
164 response->set_error("Canvas not found: " + request->canvas_id());
165 return absl::NotFoundError(response->error());
166 }
167
168 auto* api = canvas->GetAutomationAPI();
169 api->SelectTile(request->x(), request->y());
170 response->set_success(true);
171
172 return absl::OkStatus();
173}
174
175absl::Status CanvasAutomationServiceImpl::SelectTileRect(
176 const proto::SelectTileRectRequest* request,
177 proto::SelectTileRectResponse* response) {
178
179 auto* canvas = GetCanvas(request->canvas_id());
180 if (!canvas) {
181 response->set_success(false);
182 response->set_error("Canvas not found: " + request->canvas_id());
183 return absl::NotFoundError(response->error());
184 }
185
186 auto* api = canvas->GetAutomationAPI();
187 const auto& rect = request->rect();
188 api->SelectTileRect(rect.x1(), rect.y1(), rect.x2(), rect.y2());
189
190 auto selection = api->GetSelection();
191 response->set_success(true);
192 response->set_tiles_selected(selection.selected_tiles.size());
193
194 return absl::OkStatus();
195}
196
197absl::Status CanvasAutomationServiceImpl::GetSelection(
198 const proto::GetSelectionRequest* request,
199 proto::GetSelectionResponse* response) {
200
201 auto* canvas = GetCanvas(request->canvas_id());
202 if (!canvas) {
203 return absl::NotFoundError("Canvas not found: " + request->canvas_id());
204 }
205
206 auto* api = canvas->GetAutomationAPI();
207 auto selection = api->GetSelection();
208
209 response->set_has_selection(selection.has_selection);
210
211 for (const auto& tile : selection.selected_tiles) {
212 auto* coord = response->add_selected_tiles();
213 coord->set_x(static_cast<int>(tile.x));
214 coord->set_y(static_cast<int>(tile.y));
215 }
216
217 auto* start = response->mutable_selection_start();
218 start->set_x(static_cast<int>(selection.selection_start.x));
219 start->set_y(static_cast<int>(selection.selection_start.y));
220
221 auto* end = response->mutable_selection_end();
222 end->set_x(static_cast<int>(selection.selection_end.x));
223 end->set_y(static_cast<int>(selection.selection_end.y));
224
225 return absl::OkStatus();
226}
227
228absl::Status CanvasAutomationServiceImpl::ClearSelection(
229 const proto::ClearSelectionRequest* request,
230 proto::ClearSelectionResponse* response) {
231
232 auto* canvas = GetCanvas(request->canvas_id());
233 if (!canvas) {
234 response->set_success(false);
235 return absl::NotFoundError("Canvas not found: " + request->canvas_id());
236 }
237
238 auto* api = canvas->GetAutomationAPI();
239 api->ClearSelection();
240 response->set_success(true);
241
242 return absl::OkStatus();
243}
244
245// ============================================================================
246// View Operations
247// ============================================================================
248
249absl::Status CanvasAutomationServiceImpl::ScrollToTile(
250 const proto::ScrollToTileRequest* request,
251 proto::ScrollToTileResponse* response) {
252
253 auto* canvas = GetCanvas(request->canvas_id());
254 if (!canvas) {
255 response->set_success(false);
256 response->set_error("Canvas not found: " + request->canvas_id());
257 return absl::NotFoundError(response->error());
258 }
259
260 auto* api = canvas->GetAutomationAPI();
261 api->ScrollToTile(request->x(), request->y(), request->center());
262 response->set_success(true);
263
264 return absl::OkStatus();
265}
266
267absl::Status CanvasAutomationServiceImpl::CenterOn(
268 const proto::CenterOnRequest* request, proto::CenterOnResponse* response) {
269
270 auto* canvas = GetCanvas(request->canvas_id());
271 if (!canvas) {
272 response->set_success(false);
273 response->set_error("Canvas not found: " + request->canvas_id());
274 return absl::NotFoundError(response->error());
275 }
276
277 auto* api = canvas->GetAutomationAPI();
278 api->CenterOn(request->x(), request->y());
279 response->set_success(true);
280
281 return absl::OkStatus();
282}
283
284absl::Status CanvasAutomationServiceImpl::SetZoom(
285 const proto::SetZoomRequest* request, proto::SetZoomResponse* response) {
286
287 auto* canvas = GetCanvas(request->canvas_id());
288 if (!canvas) {
289 response->set_success(false);
290 response->set_error("Canvas not found: " + request->canvas_id());
291 return absl::NotFoundError(response->error());
292 }
293
294 auto* api = canvas->GetAutomationAPI();
295 api->SetZoom(request->zoom());
296
297 float actual_zoom = api->GetZoom();
298 response->set_success(true);
299 response->set_actual_zoom(actual_zoom);
300
301 return absl::OkStatus();
302}
303
304absl::Status CanvasAutomationServiceImpl::GetZoom(
305 const proto::GetZoomRequest* request, proto::GetZoomResponse* response) {
306
307 auto* canvas = GetCanvas(request->canvas_id());
308 if (!canvas) {
309 return absl::NotFoundError("Canvas not found: " + request->canvas_id());
310 }
311
312 auto* api = canvas->GetAutomationAPI();
313 response->set_zoom(api->GetZoom());
314
315 return absl::OkStatus();
316}
317
318// ============================================================================
319// Query Operations
320// ============================================================================
321
322absl::Status CanvasAutomationServiceImpl::GetDimensions(
323 const proto::GetDimensionsRequest* request,
324 proto::GetDimensionsResponse* response) {
325
326 auto* canvas = GetCanvas(request->canvas_id());
327 if (!canvas) {
328 return absl::NotFoundError("Canvas not found: " + request->canvas_id());
329 }
330
331 auto* api = canvas->GetAutomationAPI();
332 auto dims = api->GetDimensions();
333
334 auto* proto_dims = response->mutable_dimensions();
335 proto_dims->set_width_tiles(dims.width_tiles);
336 proto_dims->set_height_tiles(dims.height_tiles);
337 proto_dims->set_tile_size(dims.tile_size);
338
339 return absl::OkStatus();
340}
341
342absl::Status CanvasAutomationServiceImpl::GetVisibleRegion(
343 const proto::GetVisibleRegionRequest* request,
344 proto::GetVisibleRegionResponse* response) {
345
346 auto* canvas = GetCanvas(request->canvas_id());
347 if (!canvas) {
348 return absl::NotFoundError("Canvas not found: " + request->canvas_id());
349 }
350
351 auto* api = canvas->GetAutomationAPI();
352 auto region = api->GetVisibleRegion();
353
354 auto* proto_region = response->mutable_region();
355 proto_region->set_min_x(region.min_x);
356 proto_region->set_min_y(region.min_y);
357 proto_region->set_max_x(region.max_x);
358 proto_region->set_max_y(region.max_y);
359
360 return absl::OkStatus();
361}
362
363absl::Status CanvasAutomationServiceImpl::IsTileVisible(
364 const proto::IsTileVisibleRequest* request,
365 proto::IsTileVisibleResponse* response) {
366
367 auto* canvas = GetCanvas(request->canvas_id());
368 if (!canvas) {
369 return absl::NotFoundError("Canvas not found: " + request->canvas_id());
370 }
371
372 auto* api = canvas->GetAutomationAPI();
373 response->set_is_visible(api->IsTileVisible(request->x(), request->y()));
374
375 return absl::OkStatus();
376}
377
378// ============================================================================
379// gRPC Service Wrapper
380// ============================================================================
381
389class CanvasAutomationServiceGrpc final : public proto::CanvasAutomation::Service {
390 public:
391 explicit CanvasAutomationServiceGrpc(CanvasAutomationServiceImpl* impl)
392 : impl_(impl) {}
393
394 // Tile Operations
395 grpc::Status SetTile(grpc::ServerContext* context,
396 const proto::SetTileRequest* request,
397 proto::SetTileResponse* response) override {
398 return ConvertStatus(impl_->SetTile(request, response));
399 }
400
401 grpc::Status GetTile(grpc::ServerContext* context,
402 const proto::GetTileRequest* request,
403 proto::GetTileResponse* response) override {
404 return ConvertStatus(impl_->GetTile(request, response));
405 }
406
407 grpc::Status SetTiles(grpc::ServerContext* context,
408 const proto::SetTilesRequest* request,
409 proto::SetTilesResponse* response) override {
410 return ConvertStatus(impl_->SetTiles(request, response));
411 }
412
413 // Selection Operations
414 grpc::Status SelectTile(grpc::ServerContext* context,
415 const proto::SelectTileRequest* request,
416 proto::SelectTileResponse* response) override {
417 return ConvertStatus(impl_->SelectTile(request, response));
418 }
419
420 grpc::Status SelectTileRect(grpc::ServerContext* context,
421 const proto::SelectTileRectRequest* request,
422 proto::SelectTileRectResponse* response) override {
423 return ConvertStatus(impl_->SelectTileRect(request, response));
424 }
425
426 grpc::Status GetSelection(grpc::ServerContext* context,
427 const proto::GetSelectionRequest* request,
428 proto::GetSelectionResponse* response) override {
429 return ConvertStatus(impl_->GetSelection(request, response));
430 }
431
432 grpc::Status ClearSelection(grpc::ServerContext* context,
433 const proto::ClearSelectionRequest* request,
434 proto::ClearSelectionResponse* response) override {
435 return ConvertStatus(impl_->ClearSelection(request, response));
436 }
437
438 // View Operations
439 grpc::Status ScrollToTile(grpc::ServerContext* context,
440 const proto::ScrollToTileRequest* request,
441 proto::ScrollToTileResponse* response) override {
442 return ConvertStatus(impl_->ScrollToTile(request, response));
443 }
444
445 grpc::Status CenterOn(grpc::ServerContext* context,
446 const proto::CenterOnRequest* request,
447 proto::CenterOnResponse* response) override {
448 return ConvertStatus(impl_->CenterOn(request, response));
449 }
450
451 grpc::Status SetZoom(grpc::ServerContext* context,
452 const proto::SetZoomRequest* request,
453 proto::SetZoomResponse* response) override {
454 return ConvertStatus(impl_->SetZoom(request, response));
455 }
456
457 grpc::Status GetZoom(grpc::ServerContext* context,
458 const proto::GetZoomRequest* request,
459 proto::GetZoomResponse* response) override {
460 return ConvertStatus(impl_->GetZoom(request, response));
461 }
462
463 // Query Operations
464 grpc::Status GetDimensions(grpc::ServerContext* context,
465 const proto::GetDimensionsRequest* request,
466 proto::GetDimensionsResponse* response) override {
467 return ConvertStatus(impl_->GetDimensions(request, response));
468 }
469
470 grpc::Status GetVisibleRegion(grpc::ServerContext* context,
471 const proto::GetVisibleRegionRequest* request,
472 proto::GetVisibleRegionResponse* response) override {
473 return ConvertStatus(impl_->GetVisibleRegion(request, response));
474 }
475
476 grpc::Status IsTileVisible(grpc::ServerContext* context,
477 const proto::IsTileVisibleRequest* request,
478 proto::IsTileVisibleResponse* response) override {
479 return ConvertStatus(impl_->IsTileVisible(request, response));
480 }
481
482 private:
483 CanvasAutomationServiceImpl* impl_;
484};
485
486// Factory function to create the gRPC wrapper
487// Returns as base grpc::Service* to avoid incomplete type issues in headers
488std::unique_ptr<grpc::Service> CreateCanvasAutomationServiceGrpc(
489 CanvasAutomationServiceImpl* impl) {
490 return std::make_unique<CanvasAutomationServiceGrpc>(impl);
491}
492
493} // namespace yaze
494
495#endif // YAZE_WITH_GRPC
496
Main namespace for the application.
Definition controller.cc:20