yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
dungeon_rendering_helpers.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <array>
5#include <cmath>
6
7#include "absl/strings/str_format.h"
12#include "zelda3/dungeon/room.h"
15
16namespace yaze::editor {
17
18TrackDirectionMasks
20 switch (index) {
21 case 0:
23 case 1:
25 case 2:
27 case 3:
29 case 4:
31 case 5:
33 case 6:
36 case 7:
38 case 8:
40 case 9:
42 case 10:
44 case 11:
46 0};
47 case 12:
49 0};
50 case 13:
53 case 14:
56 default:
57 return {};
58 }
59}
60
80
82 uint8_t tile, const std::vector<uint16_t>& track_tiles,
83 const std::vector<uint16_t>& switch_tiles) {
84 auto track_it = std::find(track_tiles.begin(), track_tiles.end(), tile);
85 if (track_it != track_tiles.end()) {
87 static_cast<size_t>(track_it - track_tiles.begin()));
88 }
89
90 auto switch_it = std::find(switch_tiles.begin(), switch_tiles.end(), tile);
91 if (switch_it != switch_tiles.end()) {
93 static_cast<size_t>(switch_it - switch_tiles.begin()));
94 }
95
96 return {};
97}
98
100 const ImVec2& tip,
101 TrackDir dir, float size,
102 ImU32 color) {
103 ImVec2 a, b;
104 switch (dir) {
105 case TrackDir::North:
106 a = ImVec2(tip.x - size, tip.y + size);
107 b = ImVec2(tip.x + size, tip.y + size);
108 break;
109 case TrackDir::East:
110 a = ImVec2(tip.x - size, tip.y - size);
111 b = ImVec2(tip.x - size, tip.y + size);
112 break;
113 case TrackDir::South:
114 a = ImVec2(tip.x - size, tip.y - size);
115 b = ImVec2(tip.x + size, tip.y - size);
116 break;
117 case TrackDir::West:
118 a = ImVec2(tip.x + size, tip.y - size);
119 b = ImVec2(tip.x + size, tip.y + size);
120 break;
121 }
122 draw_list->AddTriangleFilled(tip, a, b, color);
123}
124
126 const ImVec2& min,
127 float tile_size,
128 uint8_t mask,
129 ImU32 color) {
130 if (!mask) {
131 return;
132 }
133 const ImVec2 center(min.x + tile_size * 0.5f, min.y + tile_size * 0.5f);
134 const float line_len = tile_size * 0.32f;
135 const float head_size = std::max(2.0f, tile_size * 0.18f);
136 const float thickness = std::max(1.0f, tile_size * 0.08f);
137
138 auto draw_dir = [&](TrackDir dir, float dx, float dy) {
139 ImVec2 tip(center.x + dx * line_len, center.y + dy * line_len);
140 draw_list->AddLine(center, tip, color, thickness);
141 DrawTrackArrowHead(draw_list, tip, dir, head_size, color);
142 };
143
144 if (mask & kTrackDirNorth) {
145 draw_dir(TrackDir::North, 0.0f, -1.0f);
146 }
147 if (mask & kTrackDirEast) {
148 draw_dir(TrackDir::East, 1.0f, 0.0f);
149 }
150 if (mask & kTrackDirSouth) {
151 draw_dir(TrackDir::South, 0.0f, 1.0f);
152 }
153 if (mask & kTrackDirWest) {
154 draw_dir(TrackDir::West, -1.0f, 0.0f);
155 }
156}
157
159 int room_x, int room_y) {
160 // Return unscaled relative coordinates (8 pixels per tile)
161 return {room_x * 8, room_y * 8};
162}
163
165 ImDrawList* draw_list, const std::vector<uint8_t>& preview,
166 const SDL_Rect& bounds, const ImVec2& box_min, const ImVec2& box_max,
167 const std::array<SDL_Color, 256>& color_table, uint8_t transparent_index) {
168 if (!draw_list || bounds.w <= 0 || bounds.h <= 0) {
169 return false;
170 }
171 const size_t row_stride = static_cast<size_t>(bounds.w);
172 if (static_cast<size_t>(bounds.h) > preview.size() / row_stride) {
173 return false;
174 }
175
176 const float avail_w = box_max.x - box_min.x;
177 const float avail_h = box_max.y - box_min.y;
178 if (avail_w <= 0.0f || avail_h <= 0.0f) {
179 return false;
180 }
181
182 const float scale_x = avail_w / static_cast<float>(bounds.w);
183 const float scale_y = avail_h / static_cast<float>(bounds.h);
184 const float scale = std::min(scale_x, scale_y);
185
186 const float draw_w = bounds.w * scale;
187 const float draw_h = bounds.h * scale;
188 const float origin_x = box_min.x + (avail_w - draw_w) * 0.5f;
189 const float origin_y = box_min.y + (avail_h - draw_h) * 0.5f;
190
191 for (int y = 0; y < bounds.h; ++y) {
192 int x = 0;
193 while (x < bounds.w) {
194 const uint8_t palette_index =
195 preview[static_cast<size_t>(y) * row_stride + x];
196 const SDL_Color& palette_color = color_table[palette_index];
197 if (palette_index == transparent_index || palette_color.a == 0) {
198 ++x;
199 continue;
200 }
201 const ImU32 color = IM_COL32(palette_color.r, palette_color.g,
202 palette_color.b, palette_color.a);
203
204 const int start_x = x;
205 while (x < bounds.w && preview[static_cast<size_t>(y) * row_stride + x] ==
206 palette_index) {
207 ++x;
208 }
209
210 const ImVec2 p_min(origin_x + start_x * scale, origin_y + y * scale);
211 const ImVec2 p_max(origin_x + x * scale, origin_y + (y + 1) * scale);
212 draw_list->AddRectFilled(p_min, p_max, color);
213 }
214 }
215 return true;
216}
217
219 uint8_t item_id, uint8_t* out_sprite_id) {
220 const zelda3::SpriteOamLayout* layout = nullptr;
221 uint8_t sprite_id = 0;
222 switch (item_id) {
223 case 1: // Green Rupee
225 sprite_id = 0xDA;
226 break;
227 case 4: // Heart (4)
228 case 6: // Heart
229 case 11: // Heart
230 case 19: // Heart
231 case 21: // Heart
233 sprite_id = 0xDE;
234 break;
235 case 7: // Blue Rupee
236 layout = &zelda3::kBlueRupeeLayout;
237 sprite_id = 0xDB;
238 break;
239 case 8: // Key
240 layout = &zelda3::kKeyLayout;
241 sprite_id = 0xDF;
242 break;
243 case 12: // Small Magic
245 sprite_id = 0xE1;
246 break;
247 case 13: // Large Magic
249 sprite_id = 0xE2;
250 break;
251 case 14: // Cucco
252 layout = &zelda3::kChickenLayout;
253 sprite_id = 0x0B;
254 break;
255 case 15: // Green Soldier
257 sprite_id = 0x0E;
258 break;
259 case 16: // Bush Stal
261 sprite_id = 0xA7;
262 break;
263 case 17: // Blue Soldier
265 sprite_id = 0x0F;
266 break;
267 default:
268 break;
269 }
270 if (out_sprite_id != nullptr) {
271 *out_sprite_id = sprite_id;
272 }
273 return layout;
274}
275
277 uint8_t item_id, const zelda3::Room& room, std::vector<uint8_t>& out_pixels,
278 SDL_Rect& out_bounds) {
279 uint8_t sprite_id = 0;
280 const auto* layout = GetPotItemSpriteLayout(item_id, &sprite_id);
281 if (!layout) {
282 return false;
283 }
284 zelda3::Sprite sprite;
285 sprite.set_id(sprite_id);
286 const auto& room_gfx = room.get_gfx_buffer();
287 const std::span<const uint8_t> room_gfx_span(room_gfx.data(),
288 room_gfx.size());
289 sprite.RenderPreviewGraphics(room_gfx_span, layout, {});
290 if (sprite.preview_graphics() != nullptr &&
291 !sprite.preview_graphics()->empty()) {
292 out_pixels = *sprite.preview_graphics();
293 out_bounds = sprite.preview_bounds();
294 return true;
295 }
296 return false;
297}
298
300 ImDrawList* draw_list, const ImVec2& canvas_pos, float scale,
301 const CollisionOverlayCache& cache, const TrackCollisionConfig& config,
302 bool direction_map_enabled, const std::vector<uint16_t>& track_tile_order,
303 const std::vector<uint16_t>& switch_tile_order, bool show_legend) {
304
305 const ImU32 track_color = ImGui::GetColorU32(ImVec4(0.2f, 0.8f, 0.4f, 0.35f));
306 const ImU32 stop_color = ImGui::GetColorU32(ImVec4(0.9f, 0.3f, 0.2f, 0.45f));
307 const ImU32 switch_color =
308 ImGui::GetColorU32(ImVec4(0.95f, 0.8f, 0.2f, 0.45f));
309 const ImU32 outline_color = ImGui::GetColorU32(ImVec4(0, 0, 0, 0.4f));
310 const ImU32 arrow_color =
311 ImGui::GetColorU32(ImVec4(0.05f, 0.05f, 0.05f, 0.75f));
312 const ImU32 arrow_color_dim =
313 ImGui::GetColorU32(ImVec4(0.05f, 0.05f, 0.05f, 0.4f));
314
315 for (const auto& entry : cache.entries) {
316 const float px = static_cast<float>(entry.x * 8) * scale;
317 const float py = static_cast<float>(entry.y * 8) * scale;
318 ImVec2 min(canvas_pos.x + px, canvas_pos.y + py);
319 const float tile_size = 8.0f * scale;
320 ImVec2 max(min.x + tile_size, min.y + tile_size);
321
322 ImU32 color = track_color;
323 if (config.stop_tiles[entry.tile]) {
324 color = stop_color;
325 } else if (config.switch_tiles[entry.tile]) {
326 color = switch_color;
327 }
328
329 draw_list->AddRectFilled(min, max, color);
330 draw_list->AddRect(min, max, outline_color);
331
332 if (config.stop_tiles[entry.tile]) {
333 const char* dir_label = nullptr;
334 if (entry.tile == 0xB7)
335 dir_label = "U";
336 else if (entry.tile == 0xB8)
337 dir_label = "D";
338 else if (entry.tile == 0xB9)
339 dir_label = "L";
340 else if (entry.tile == 0xBA)
341 dir_label = "R";
342
343 if (dir_label) {
344 const ImU32 label_color =
345 ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 0.9f));
346 ImVec2 text_size = ImGui::CalcTextSize(dir_label);
347 ImVec2 text_pos(min.x + (tile_size - text_size.x) * 0.5f,
348 min.y + (tile_size - text_size.y) * 0.5f);
349 draw_list->AddText(text_pos, label_color, dir_label);
350 }
351 }
352
353 if (direction_map_enabled) {
354 const auto masks = GetTrackDirectionMasksFromConfig(
355 entry.tile, track_tile_order, switch_tile_order);
356 if (masks.primary != 0) {
357 DrawTrackDirectionMask(draw_list, min, tile_size, masks.primary,
358 arrow_color);
359 if (masks.secondary != 0) {
360 DrawTrackDirectionMask(draw_list, min, tile_size, masks.secondary,
361 arrow_color_dim);
362 }
363 }
364 }
365 }
366
367 if (show_legend) {
368 ImVec2 legend_pos(canvas_pos.x + 8.0f, canvas_pos.y + 8.0f);
369 const float swatch = 10.0f;
370 const float pad = 6.0f;
371 const ImU32 text_color = ImGui::GetColorU32(ImVec4(1, 1, 1, 0.85f));
372
373 struct LegendItem {
374 const char* label;
375 ImU32 color;
376 };
377 const LegendItem items[] = {
378 {"Track", track_color},
379 {"Stop", stop_color},
380 {"Switch", switch_color},
381 };
382
383 float y = legend_pos.y;
384 for (const auto& item : items) {
385 ImVec2 swatch_min(legend_pos.x, y);
386 ImVec2 swatch_max(legend_pos.x + swatch, y + swatch);
387 draw_list->AddRectFilled(swatch_min, swatch_max, item.color);
388 draw_list->AddRect(swatch_min, swatch_max, outline_color);
389 draw_list->AddText(ImVec2(legend_pos.x + swatch + pad, y - 1.0f),
390 text_color, item.label);
391 y += swatch + 4.0f;
392 }
393 const char* arrow_label =
394 direction_map_enabled ? "Arrows: track directions" : "Arrows: disabled";
395 draw_list->AddText(ImVec2(legend_pos.x, y + 2.0f), text_color, arrow_label);
396 }
397}
398
400 ImDrawList* draw_list, const ImVec2& canvas_pos, float scale,
401 const zelda3::Room& room) {
402 const auto& theme = AgentUI::GetTheme();
403 const auto& custom = room.custom_collision();
404 if (!custom.has_data)
405 return;
406
407 const float tile_size = 8.0f * scale;
408 auto apply_alpha = [](ImVec4 c, float a) {
409 c.w = a;
410 return c;
411 };
412
413 for (int y = 0; y < 64; ++y) {
414 for (int x = 0; x < 64; ++x) {
415 uint8_t tile = custom.tiles[static_cast<size_t>(y * 64 + x)];
416 if (!custom.HasOverride(static_cast<size_t>(y * 64 + x)))
417 continue;
418
419 const float px = static_cast<float>(x * 8) * scale;
420 const float py = static_cast<float>(y * 8) * scale;
421 ImVec2 min(canvas_pos.x + px, canvas_pos.y + py);
422 ImVec2 max(min.x + tile_size, min.y + tile_size);
423
424 ImVec4 fill = apply_alpha(theme.panel_border_color, 0.25f);
425 switch (tile) {
426 case 0x00:
427 fill = apply_alpha(theme.status_success, 0.28f);
428 break;
429 case 0x08:
430 fill = apply_alpha(theme.status_active, 0.35f);
431 break;
432 case 0x09:
433 fill = apply_alpha(theme.status_active, 0.25f);
434 break;
435 case 0x1B:
436 fill = apply_alpha(theme.editor_background, 0.50f);
437 break;
438 case 0x0E:
439 case 0x3C:
440 fill = apply_alpha(theme.status_error, 0.30f);
441 break;
442 case 0x1C:
443 fill = apply_alpha(theme.status_warning, 0.30f);
444 break;
445 case 0x21:
446 case 0x22:
447 case 0x23:
448 fill = apply_alpha(theme.accent_color, 0.30f);
449 break;
450 }
451
452 draw_list->AddRectFilled(min, max, ImGui::ColorConvertFloat4ToU32(fill));
453 draw_list->AddRect(min, max,
454 ImGui::ColorConvertFloat4ToU32(
455 apply_alpha(theme.editor_grid, 0.50f)));
456
457 if (scale >= 4.0f) {
458 std::string buf = absl::StrFormat("%02X", tile);
459 ImVec2 text_size = ImGui::CalcTextSize(buf.c_str());
460 if (text_size.x < tile_size * 0.9f) {
461 ImVec2 text_pos(min.x + (tile_size - text_size.x) * 0.5f,
462 min.y + (tile_size - text_size.y) * 0.5f);
463 draw_list->AddText(text_pos,
464 ImGui::ColorConvertFloat4ToU32(
465 apply_alpha(theme.text_primary, 0.85f)),
466 buf.c_str());
467 }
468 }
469 }
470 }
471}
472
474 const ImVec2& canvas_pos,
475 float scale,
476 const zelda3::Room& room) {
477 const auto& theme = AgentUI::GetTheme();
478 const auto& zone = room.water_fill_zone();
479 if (!zone.has_data)
480 return;
481
482 const float tile_size = 8.0f * scale;
483 auto apply_alpha = [](ImVec4 c, float a) {
484 c.w = a;
485 return c;
486 };
487 const ImU32 fill_u32 =
488 ImGui::ColorConvertFloat4ToU32(apply_alpha(theme.status_active, 0.30f));
489 const ImU32 border_u32 =
490 ImGui::ColorConvertFloat4ToU32(apply_alpha(theme.editor_grid, 0.40f));
491
492 for (int y = 0; y < 64; ++y) {
493 for (int x = 0; x < 64; ++x) {
494 if (zone.tiles[static_cast<size_t>(y * 64 + x)] == 0)
495 continue;
496 const float px = static_cast<float>(x * 8) * scale;
497 const float py = static_cast<float>(y * 8) * scale;
498 ImVec2 min(canvas_pos.x + px, canvas_pos.y + py);
499 ImVec2 max(min.x + tile_size, min.y + tile_size);
500 draw_list->AddRectFilled(min, max, fill_u32);
501 draw_list->AddRect(min, max, border_u32);
502 }
503 }
504}
505
507 ImDrawList* draw_list, const ImVec2& canvas_pos, float scale,
508 const zelda3::Room& room) {
509 const auto& theme = AgentUI::GetTheme();
510 const float room_size_px = 512.0f * scale;
511 const float mid_px = 256.0f * scale;
512 const float thickness = std::max(1.0f, 1.0f * scale);
513 const ImU32 line_color = ImGui::GetColorU32(theme.editor_grid);
514
515 draw_list->AddLineV(canvas_pos.x + mid_px, canvas_pos.y,
516 canvas_pos.y + room_size_px, line_color, thickness);
517 draw_list->AddLineH(canvas_pos.x, canvas_pos.x + room_size_px,
518 canvas_pos.y + mid_px, line_color, thickness);
519
520 std::string label = absl::StrFormat("Layout %d", room.layout_id());
521 draw_list->AddText(ImVec2(canvas_pos.x + 6.0f, canvas_pos.y + 6.0f),
522 ImGui::GetColorU32(theme.text_secondary_color),
523 label.c_str());
524}
525
527 ImDrawList* draw_list, const ImVec2& canvas_pos, float scale,
528 const zelda3::Room& room, const std::bitset<256>& minecart_sprite_ids,
529 const TrackCollisionConfig& config) {
530 const auto& theme = AgentUI::GetTheme();
531 auto map_or = zelda3::LoadCustomCollisionMap(room.rom(), room.id());
532 const bool has_collision = map_or.ok() && map_or.value().has_data;
533
534 const ImU32 ok_color = ImGui::GetColorU32(theme.status_success);
535 const ImU32 warn_color = ImGui::GetColorU32(theme.status_warning);
536 const ImU32 unknown_color = ImGui::GetColorU32(theme.status_inactive);
537
538 for (const auto& sprite : room.GetSprites()) {
539 if (sprite.id() >= 256 || !minecart_sprite_ids[sprite.id()])
540 continue;
541
542 bool on_stop_tile = false;
543 bool has_tile = false;
544 if (has_collision) {
545 int tile_x = sprite.x() * 2;
546 int tile_y = sprite.y() * 2;
547 if (tile_x >= 0 && tile_x < 64 && tile_y >= 0 && tile_y < 64) {
548 uint8_t tile =
549 map_or.value().tiles[static_cast<size_t>(tile_y * 64 + tile_x)];
550 has_tile = true;
551 on_stop_tile = config.stop_tiles[tile];
552 }
553 }
554
555 ImU32 color =
556 has_tile ? (on_stop_tile ? ok_color : warn_color) : unknown_color;
557 const float px = static_cast<float>(sprite.x() * 16) * scale;
558 const float py = static_cast<float>(sprite.y() * 16) * scale;
559 ImVec2 min(canvas_pos.x + px, canvas_pos.y + py);
560 ImVec2 max(min.x + (16.0f * scale), min.y + (16.0f * scale));
561 draw_list->AddRect(min, max, color, 0.0f, 2.0f);
562 }
563}
564
566 ImDrawList* draw_list, const ImVec2& canvas_pos, float scale,
567 const zelda3::Room& room, const CollisionOverlayCache& cache) {
568
569 std::array<bool, 64 * 64> object_grid{};
570 for (const auto& obj : room.GetTileObjects()) {
571 if (obj.id_ != 0x31)
572 continue;
574 int base_x = obj.x() * 2;
575 int base_y = obj.y() * 2;
576 for (int dy = 0; dy < dim.height_tiles && (base_y + dy) < 64; ++dy) {
577 for (int dx = 0; dx < dim.width_tiles && (base_x + dx) < 64; ++dx) {
578 object_grid[static_cast<size_t>((base_y + dy) * 64 + (base_x + dx))] =
579 true;
580 }
581 }
582 }
583
584 std::array<bool, 64 * 64> collision_grid{};
585 for (const auto& entry : cache.entries) {
586 collision_grid[static_cast<size_t>(entry.y * 64 + entry.x)] = true;
587 }
588
589 const auto& theme = AgentUI::GetTheme();
590 const ImU32 gap_color = ImGui::ColorConvertFloat4ToU32(theme.status_warning);
591 const ImU32 orphan_color =
592 ImGui::ColorConvertFloat4ToU32(theme.status_inactive);
593 const float tile_size = 8.0f * scale;
594
595 for (int y = 0; y < 64; ++y) {
596 for (int x = 0; x < 64; ++x) {
597 size_t idx = static_cast<size_t>(y * 64 + x);
598 if (object_grid[idx] == collision_grid[idx])
599 continue;
600
601 const float px = static_cast<float>(x * 8) * scale;
602 const float py = static_cast<float>(y * 8) * scale;
603 ImVec2 min_pt(canvas_pos.x + px, canvas_pos.y + py);
604 ImVec2 max_pt(min_pt.x + tile_size, min_pt.y + tile_size);
605 draw_list->AddRectFilled(min_pt, max_pt,
606 object_grid[idx] ? gap_color : orphan_color);
607 }
608 }
609}
610
612 ImDrawList* draw_list, const ImVec2& canvas_pos, float scale,
613 const CollisionOverlayCache& cache) {
614 const auto& theme = AgentUI::GetTheme();
615 std::array<bool, 64 * 64> occupied{};
616 for (const auto& entry : cache.entries) {
617 occupied[static_cast<size_t>(entry.y * 64 + entry.x)] = true;
618 }
619
620 const float tile_size = 8.0f * scale;
621 const float half_tile = tile_size * 0.5f;
622 const ImU32 route_color = ImGui::ColorConvertFloat4ToU32(theme.status_active);
623 const float thickness = std::max(1.0f, 1.5f * scale);
624
625 for (const auto& entry : cache.entries) {
626 float cx =
627 canvas_pos.x + static_cast<float>(entry.x * 8) * scale + half_tile;
628 float cy =
629 canvas_pos.y + static_cast<float>(entry.y * 8) * scale + half_tile;
630
631 if (entry.x + 1 < 64 &&
632 occupied[static_cast<size_t>(entry.y * 64 + (entry.x + 1))]) {
633 draw_list->AddLineH(cx, cx + tile_size, cy, route_color, thickness);
634 }
635 if (entry.y + 1 < 64 &&
636 occupied[static_cast<size_t>((entry.y + 1) * 64 + entry.x)]) {
637 draw_list->AddLineV(cx, cy, cy + tile_size, route_color, thickness);
638 }
639 }
640}
641
642} // namespace yaze::editor
static void DrawCustomCollisionOverlay(ImDrawList *draw_list, const ImVec2 &canvas_pos, float scale, const zelda3::Room &room)
static void DrawTrackGapOverlay(ImDrawList *draw_list, const ImVec2 &canvas_pos, float scale, const zelda3::Room &room, const CollisionOverlayCache &cache)
static void DrawTrackCollisionOverlay(ImDrawList *draw_list, const ImVec2 &canvas_pos, float scale, const CollisionOverlayCache &cache, const TrackCollisionConfig &config, bool direction_map_enabled, const std::vector< uint16_t > &track_tile_order, const std::vector< uint16_t > &switch_tile_order, bool show_legend)
static void DrawCameraQuadrantOverlay(ImDrawList *draw_list, const ImVec2 &canvas_pos, float scale, const zelda3::Room &room)
static std::pair< int, int > RoomToCanvasCoordinates(int room_x, int room_y)
static void DrawTrackRouteOverlay(ImDrawList *draw_list, const ImVec2 &canvas_pos, float scale, const CollisionOverlayCache &cache)
static TrackDirectionMasks GetTrackDirectionMasksForTrackIndex(size_t index)
static void DrawMinecartSpriteOverlay(ImDrawList *draw_list, const ImVec2 &canvas_pos, float scale, const zelda3::Room &room, const std::bitset< 256 > &minecart_sprite_ids, const TrackCollisionConfig &config)
static TrackDirectionMasks GetTrackDirectionMasksForSwitchIndex(size_t index)
static void DrawWaterFillOverlay(ImDrawList *draw_list, const ImVec2 &canvas_pos, float scale, const zelda3::Room &room)
static void DrawTrackDirectionMask(ImDrawList *draw_list, const ImVec2 &min, float tile_size, uint8_t mask, ImU32 color)
static bool BuildPotItemPreview(uint8_t item_id, const zelda3::Room &room, std::vector< uint8_t > &out_pixels, SDL_Rect &out_bounds)
static void DrawTrackArrowHead(ImDrawList *draw_list, const ImVec2 &tip, TrackDir dir, float size, ImU32 color)
static TrackDirectionMasks GetTrackDirectionMasksFromConfig(uint8_t tile, const std::vector< uint16_t > &track_tiles, const std::vector< uint16_t > &track_switches)
static bool DrawSpritePreview(ImDrawList *draw_list, const std::vector< uint8_t > &preview, const SDL_Rect &bounds, const ImVec2 &box_min, const ImVec2 &box_max, const std::array< SDL_Color, 256 > &color_table, uint8_t transparent_index=kSpritePreviewTransparentIndex)
static const zelda3::SpriteOamLayout * GetPotItemSpriteLayout(uint8_t item_id, uint8_t *out_sprite_id=nullptr)
static DimensionService & Get()
DimensionResult GetDimensions(const RoomObject &obj) const
const std::array< uint8_t, 0x10000 > & get_gfx_buffer() const
Definition room.h:1120
const CustomCollisionMap & custom_collision() const
Definition room.h:559
const WaterFillZoneMap & water_fill_zone() const
Definition room.h:601
auto rom() const
Definition room.h:1082
const std::vector< zelda3::Sprite > & GetSprites() const
Definition room.h:316
const std::vector< RoomObject > & GetTileObjects() const
Definition room.h:445
uint8_t layout_id() const
Definition room.h:1026
int id() const
Definition room.h:1012
static const SpriteOamLayout * GetLayout(uint8_t sprite_id)
Get the OAM layout for a sprite ID.
A class for managing sprites in the overworld and underworld.
Definition sprite.h:39
void RenderPreviewGraphics(std::span< const uint8_t > graphics, const SpriteOamLayout *layout_override=nullptr, std::span< const uint8_t > graphics_resource={})
Definition sprite.cc:1194
auto set_id(uint8_t id)
Definition sprite.h:108
auto preview_graphics() const
Definition sprite.h:103
SDL_Rect preview_bounds() const
Definition sprite.h:106
const AgentUITheme & GetTheme()
Editors are the view controllers for the application.
constexpr uint8_t kTrackDirSouth
constexpr uint8_t kTrackDirEast
constexpr uint8_t kTrackDirNorth
constexpr uint8_t kTrackDirWest
const SpriteOamLayout kLargeMagicLayout
const SpriteOamLayout kBlueSoldierLayout
const SpriteOamLayout kBlueRupeeLayout
const SpriteOamLayout kGreenSoldierLayout
const SpriteOamLayout kSmallMagicLayout
const SpriteOamLayout kGreenRupeeLayout
absl::StatusOr< CustomCollisionMap > LoadCustomCollisionMap(Rom *rom, int room_id)
const SpriteOamLayout kChickenLayout
const SpriteOamLayout kKeyLayout
const SpriteOamLayout kSmallHeartLayout
std::array< uint8_t, 64 *64 > tiles
Complete OAM layout for a vanilla sprite.