10#include "absl/strings/str_format.h"
11#include "absl/strings/str_join.h"
23#include "imgui/imgui.h"
24#include "imgui/misc/cpp/imgui_stdlib.h"
52 if (ImGui::BeginTabBar(
"##SheetBrowserTabs")) {
53 const bool show_sheets = ImGui::BeginTabItem(tr(
"Sheets"));
60 const bool show_details = ImGui::BeginTabItem(tr(
"Details"));
63 ImGui::BeginChild(
"##SheetDetails", ImVec2(0, 0));
68 const bool show_png = ImGui::BeginTabItem(tr(
"PNG"));
71 ImGui::BeginChild(
"##SheetTransfer", ImVec2(0, 0));
76 const bool show_catalog = ImGui::BeginTabItem(tr(
"Catalog"));
79 ImGui::BeginChild(
"##CatalogTileTransfer", ImVec2(0, 0));
87 return absl::OkStatus();
124std::string
HexList(
const std::vector<int>& values) {
125 if (values.empty()) {
128 return absl::StrJoin(values,
" ", [](std::string* out,
int value) {
129 out->append(absl::StrFormat(
"%02X", value));
134 ImGui::TableNextRow();
135 ImGui::TableSetColumnIndex(0);
136 ImGui::TextUnformatted(label);
137 ImGui::TableSetColumnIndex(1);
138 ImGui::Text(
"%zu", values.size());
139 ImGui::TableSetColumnIndex(2);
140 ImGui::TextWrapped(
"%s",
HexList(values).c_str());
158 ImGui::BeginDisabled(!can_edit);
159 ImGui::SetNextItemWidth(-1);
160 const bool submitted = ImGui::InputTextWithHint(
161 "##SheetLabel", tr(
"Sheet label (stored in the project)"), &
label_buffer_,
162 ImGuiInputTextFlags_EnterReturnsTrue);
163 if ((submitted || ImGui::IsItemDeactivatedAfterEdit()) && can_edit) {
165 label_status_ = status.ok() ?
"Label set; save the project to keep it"
166 : std::string(status.message());
172 std::ifstream file(path);
173 std::stringstream text;
174 text << file.rdbuf();
178 "Imported %d sheet label(s); existing labels "
181 : std::string(imported.status().message());
186 "Label sprite sheets from Oracle's \"Spritesets\" CSV: a cell like "
187 "\"0x46 Cannon Soldiers\" names sheet 0x46 + 0x73.");
188 ImGui::EndDisabled();
191 tr(
"Open the project that owns this ROM to edit "
201 if (!ImGui::CollapsingHeader(
202 absl::StrFormat(
"Sheet 0x%02X usage and free space###SheetUsage",
205 ImGuiTreeNodeFlags_DefaultOpen)) {
212 "Re-read the ROM buffer (saved sheets, group tables, areas, "
213 "rooms). Unsaved pixel edits are not included.");
216 HOVER_HINT(
"Outline empty, unreserved 16x16 blocks on the thumbnails");
227 const auto& entry =
inventory_->sheets[sheet_id];
232 if (entry.stored_bytes.has_value()) {
234 ImGui::Text(tr(
"stored %zu bytes"), *entry.stored_bytes);
236 if (entry.sprite_value.has_value()) {
238 ImGui::Text(tr(
"sprite value 0x%02X"), *entry.sprite_value);
240 if (!entry.error.empty()) {
243 if (entry.reserved) {
251 if (entry.engine_loaded) {
255 if (!entry.labels.empty()) {
256 ImGui::TextWrapped(
"%s", absl::StrJoin(entry.labels,
"; ").c_str());
259 const auto free_blocks = entry.FreeBlocks();
260 if (entry.has_block_stats) {
261 ImGui::Text(tr(
"Free 16x16 blocks: %zu of 16 (empty 8x8 tiles: %d)"),
262 free_blocks.size(), entry.empty_8x8);
263 if (!free_blocks.empty()) {
265 ImGui::TextDisabled(
"[%s]", HexList(free_blocks).c_str());
267 if (!entry.reserved_blocks.empty()) {
268 ImGui::Text(tr(
"Reserved blocks: %s"),
269 absl::StrJoin(entry.reserved_blocks,
" ").c_str());
273 if (ImGui::BeginTable(
"##SheetUsedBy", 3,
274 ImGuiTableFlags_SizingStretchProp |
275 ImGuiTableFlags_RowBg |
276 ImGuiTableFlags_BordersInnerH)) {
278 ImGuiTableColumnFlags_WidthFixed);
279 ImGui::TableSetupColumn(
"#", ImGuiTableColumnFlags_WidthFixed);
281 ImGui::TableHeadersRow();
282 const auto& use = entry.usage;
283 if (entry.sprite_value.has_value()) {
284 DrawUsageRow(tr(
"Spritesets"), use.spritesets);
285 DrawUsageRow(tr(
"OW areas (sprites)"), use.ow_areas_sprite);
286 DrawUsageRow(tr(
"Rooms (sprites)"), use.rooms_sprite);
288 DrawUsageRow(tr(
"Main blocksets"), use.main_blocksets);
289 DrawUsageRow(tr(
"Room blocksets"), use.room_blocksets);
290 DrawUsageRow(tr(
"OW areas (static)"), use.ow_areas_static);
293 if (entry.unreferenced) {
294 ImGui::TextDisabled(tr(
"No table references this sheet."));
303 const auto& use =
inventory_->sheets[sheet_id].usage;
304 std::vector<std::string> parts;
305 auto add = [&parts](
size_t count,
const char* what) {
307 parts.push_back(absl::StrFormat(
"%zu %s", count, what));
310 add(use.main_blocksets.size(),
"main blocksets");
311 add(use.room_blocksets.size(),
"room blocksets");
312 add(use.spritesets.size(),
"spritesets");
313 add(use.ow_areas_static.size() + use.ow_areas_sprite.size(),
"OW areas");
314 add(use.rooms_sprite.size(),
"rooms");
315 return parts.empty() ? std::string(
"no table uses it")
316 :
"used by " + absl::StrJoin(parts,
", ");
323 if (!ImGui::CollapsingHeader(
324 absl::StrFormat(
"Pending graphics save (%zu)###PendingSave",
327 ImGuiTreeNodeFlags_DefaultOpen)) {
342 "Writes every dirty sheet to a scratch copy of the ROM and decodes it "
343 "back. Saving the ROM does the same for real, and writes nothing if any "
350 ImGui::TextDisabled(
"%s", tr(
"Check the plan before saving the ROM."));
355 tr(
"Edits changed since the check; check again."));
363 ImGui::TextColored(color,
"%s",
366 if (!usage.empty()) {
368 ImGui::TextDisabled(
"%s", usage.c_str());
384 return absl::FailedPreconditionError(
"Open a ROM to use room palettes");
389 target->sheet_id != sheet_id || target->palette.size() != 8) {
390 return absl::FailedPreconditionError(
391 "Use Edit Graphics from a source tile to supply its palette");
394 for (
int i = 0; i < 8; ++i) {
395 const auto rgb = target->palette[i].rgb();
396 palette[i] = {
static_cast<uint8_t
>(rgb.x),
static_cast<uint8_t
>(rgb.y),
397 static_cast<uint8_t
>(rgb.z)};
405 return context.status();
407 return absl::FailedPreconditionError(
408 "Choose a room slot that loads the selected sheet");
410 return context->colors;
421 if (!ImGui::CollapsingHeader(tr(
"PNG export and import###SheetPng"))) {
425 const bool arena_is_ours =
game_data_ !=
nullptr &&
427 if (!arena_is_ours) {
429 tr(
"The sheets in memory belong to another open ROM."));
433 const char* modes[] = {tr(
"Grayscale"), tr(
"Background row (left half)"),
434 tr(
"Room sprite row"), tr(
"Room background slot"),
435 tr(
"Selected source tile")};
436 ImGui::SetNextItemWidth(180.0f);
438 IM_ARRAYSIZE(modes));
440 ImGui::SetNextItemWidth(90.0f);
441 ImGui::InputInt(tr(
"Room##png"), &
png_room_, 1, 16,
442 ImGuiInputTextFlags_CharsHexadecimal);
446 ImGui::SetNextItemWidth(90.0f);
450 "The room picks the palette rows and, for room PNGs, the room's 8 "
451 "background sheets.");
452 ImGui::EndDisabled();
456 "%s", target !=
nullptr
457 ? target->label.c_str()
458 :
"Use Edit Graphics from the tile you want to work on.");
464 std::vector<int> matches;
465 for (
int slot = 0; slot < 8; ++slot) {
466 if (set.sheets[slot] == sheet_id)
467 matches.push_back(slot);
473 auto slot_label = [&](
int slot) {
474 return absl::StrFormat(
475 "Slot %d / %s half", slot,
480 const std::string selected =
481 png_room_slot_ < 0 ? (matches.empty() ?
"Sheet not loaded by this room"
482 :
"Choose a loaded slot")
484 if (ImGui::BeginCombo(tr(
"Loaded slot##png"), selected.c_str())) {
485 for (
int slot : matches) {
486 if (ImGui::Selectable(slot_label(slot).c_str(),
494 "Uses the saved room header and its default entrance graphics. "
495 "Inherited entrance "
496 "choices may differ from a particular gameplay route. PNG "
497 "indices stay 0-7; slot 7's animation overlay is not included.");
499 ImGui::SetNextItemWidth(320.0f);
500 ImGui::InputTextWithHint(
"File##PngPath", tr(
"empty: choose in a dialog"),
503 "PNG path for the export and import buttons. Leave it empty to choose "
504 "the file in a dialog.");
505 ImGui::SetNextItemWidth(90.0f);
509 "The 16x16 block (0-15, 8 per row) where an imported sheet PNG starts; "
510 "pick a free block from the usage list above.");
513 const std::vector<uint8_t> pixels = sheet_id < sheets.size()
514 ? sheets[sheet_id].vector()
515 : std::vector<uint8_t>{};
517 png_filter.
filters.push_back({
"PNG image",
"png"});
519 auto save_path = [
this](
const std::string& default_name) {
524 auto open_path = [
this, &png_filter]() {
532 auto png = palette.ok()
534 : absl::StatusOr<std::vector<uint8_t>>(palette.status());
536 SetPngStatus(std::string(png.status().message()),
true);
538 const std::string path =
539 save_path(absl::StrFormat(
"sheet_%02X", sheet_id));
543 status.ok() ?
"Exported " + path : std::string(status.message()),
551 const std::string path = palette.ok() ? open_path() : std::string();
553 SetPngStatus(std::string(palette.status().message()),
true);
554 }
else if (!path.empty()) {
559 : absl::StatusOr<SheetPngImportPreview>(bytes.status());
562 SetPngStatus(std::string(preview.status().message()),
true);
574 SetPngStatus(std::string(palette.status().message()),
true);
581 SetPngStatus(std::string(png.status().message()),
true);
583 const std::string path =
584 save_path(absl::StrFormat(
"room_%03X_background",
png_room_));
588 status.ok() ?
"Exported " + path +
" (sheets as saved in the ROM)"
589 : std::string(status.message()),
596 "128x256: the room's 8 background sheets in slot order, read from the "
597 "ROM (save pixel edits first to include them). This legacy layout uses "
598 "one uniform palette for all slots.");
602 const std::string path = palette.ok() ? open_path() : std::string();
604 SetPngStatus(std::string(palette.status().message()),
true);
605 }
else if (!path.empty() &&
rom_ !=
nullptr &&
game_data_ !=
nullptr) {
612 : absl::StatusOr<std::vector<SheetPngImportPreview>>(
615 if (!previews.ok()) {
616 SetPngStatus(std::string(previews.status().message()),
true);
620 std::vector<std::string> unsaved;
621 for (
const auto& preview : *previews) {
623 unsaved.push_back(absl::StrFormat(
"0x%02X", preview.sheet_id));
626 if (!unsaved.empty()) {
627 SetPngStatus(absl::StrFormat(
"Save or discard the pixel edits to "
628 "sheet(s) %s before a room import",
629 absl::StrJoin(unsaved,
", ")),
639 ImGui::EndDisabled();
642 "Room slot colors apply to one sheet. Use Export sheet "
643 "PNG for the selected slot.");
653 bool any_change =
false;
656 any_change = any_change || !preview.changed_tiles.empty();
658 ImGui::BeginDisabled(!any_change);
660 std::vector<std::string> errors;
662 const absl::Status status =
665 errors.push_back(std::string(status.message()));
668 SetPngStatus(errors.empty() ? std::string(
"Imported; save the ROM to write "
670 : absl::StrJoin(errors,
"; "),
674 ImGui::EndDisabled();
683 ImGui::Text(tr(
"Search:"));
687 ImGuiInputTextFlags_CharsHexadecimal)) {
690 int value =
static_cast<int>(strtol(
search_buffer_,
nullptr, 16));
691 if (value >= 0 && value <= 222) {
700 ImGui::OpenPopup(
"Sheet filters");
703 HOVER_HINT(
"Filter range, modified sheets, and thumbnail size");
704 if (ImGui::BeginPopup(
"Sheet filters")) {
705 ImGui::SetNextItemWidth(70);
706 ImGui::DragInt(
"First", &
filter_min_, 1.0f, 0, 222,
"%02X");
707 ImGui::SetNextItemWidth(70);
708 ImGui::DragInt(
"Last", &
filter_max_, 1.0f, 0, 222,
"%02X");
718 ImGui::AlignTextToFramePadding();
719 ImGui::TextUnformatted(tr(
"Palette:"));
720 HOVER_HINT(
"Show every sheet in this palette; display only");
722 ImGui::PushID(
"BrowserPalette");
752 ImGui::BeginChild(
"##SheetGridChild", ImVec2(0, 0),
true,
753 ImGuiWindowFlags_AlwaysVerticalScrollbar);
758 const float fit_scale =
760 std::max(0.25f, (ImGui::GetContentRegionAvail().x - 12) / 128));
761 const float thumb_width = 128 * fit_scale;
762 const float thumb_height = 32 * fit_scale;
763 const float padding = 4.0f;
766 float available_width = ImGui::GetContentRegionAvail().x;
768 1,
static_cast<int>(available_width / (thumb_width + padding * 2)));
798 const float fit_scale =
800 std::max(0.25f, (ImGui::GetContentRegionAvail().x - 12) / 128));
801 const float thumb_width = 128 * fit_scale;
802 const float thumb_height = 32 * fit_scale;
806 bool is_multi_selected =
812 std::optional<gui::StyleColorGuard> sel_bg_guard;
816 sel_bg_guard.emplace(ImGuiCol_ChildBg, sel_bg);
817 }
else if (is_multi_selected) {
820 sel_bg_guard.emplace(ImGuiCol_ChildBg, multi_bg);
823 ImGui::BeginChild(absl::StrFormat(
"##Sheet%02X", sheet_id).c_str(),
824 ImVec2(thumb_width + 8, thumb_height + 24),
true,
825 ImGuiWindowFlags_NoScrollbar);
828 preview_opts.
canvas_size = ImVec2(thumb_width + 1, thumb_height + 1);
829 preview_opts.
dest_pos = ImVec2(2, 2);
830 preview_opts.
dest_size = ImVec2(thumb_width - 2, thumb_height - 2);
831 preview_opts.
grid_step = 8.0f * fit_scale;
849 std::string label = absl::StrFormat(
"%02X", sheet_id);
855 ImVec2 text_pos = ImGui::GetCursorScreenPos();
856 ImVec2 text_size = ImGui::CalcTextSize(label.c_str());
858 ImVec2(2, 2), ImVec2(text_size.x + 4, text_size.y + 2),
859 is_modified ? ImGui::GetColorU32(IM_COL32(180, 100, 0, 200))
860 : ImGui::GetColorU32(IM_COL32(0, 100, 0, 180)));
864 is_modified ? ImGui::GetColorU32(IM_COL32(255, 200, 100, 255))
865 : ImGui::GetColorU32(IM_COL32(150, 255, 150, 255)));
871 ImGui::GetWindowDrawList()->AddCircleFilled(
876 sheet_id <
static_cast<int>(
inventory_->sheets.size())) {
877 const auto& entry =
inventory_->sheets[sheet_id];
878 const float block_w = preview_opts.
dest_size.x / 8.0f;
879 const float block_h = preview_opts.
dest_size.y / 2.0f;
881 for (
int block : entry.FreeBlocks()) {
883 ImVec2(preview_opts.
dest_pos.x + (block % 8) * block_w,
884 preview_opts.
dest_pos.y + (block / 8) * block_h),
885 ImVec2(block_w, block_h),
886 entry.flagged ? ImGui::GetColorU32(IM_COL32(230, 180, 40, 70))
887 : ImGui::GetColorU32(IM_COL32(60, 200, 90, 70)));
891 entry.reserved ?
"RES" : (entry.flagged ?
"ASK" :
nullptr);
892 if (badge !=
nullptr) {
893 const ImVec2 badge_size = ImGui::CalcTextSize(badge);
894 const ImVec2 badge_pos(thumb_width - badge_size.x - 4, 2);
896 badge_pos, ImVec2(badge_size.x + 4, badge_size.y + 2),
897 entry.reserved ? ImGui::GetColorU32(IM_COL32(170, 30, 30, 220))
898 : ImGui::GetColorU32(IM_COL32(170, 120, 20, 220)));
900 ImVec2(badge_pos.x + 2, badge_pos.y), badge,
901 ImGui::GetColorU32(IM_COL32(255, 255, 255, 255)));
908 if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
909 if (ImGui::GetIO().KeyCtrl) {
911 if (is_multi_selected) {
923 if (ImGui::IsItemHovered() &&
924 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
930 sel_bg_guard.reset();
933 if (ImGui::IsItemHovered()) {
934 ImGui::BeginTooltip();
935 ImGui::Text(tr(
"Sheet: 0x%02X (%d)"), sheet_id, sheet_id);
936 if (
const std::string label =
SheetLabel(
static_cast<uint16_t
>(sheet_id));
938 ImGui::TextUnformatted(label.c_str());
941 ImGui::Text(tr(
"Size: %dx%d"), bitmap.
width(), bitmap.
height());
942 ImGui::Text(tr(
"Depth: %d bpp"), bitmap.
depth());
944 ImGui::Text(tr(
"(Inactive)"));
950 sheet_id <
static_cast<int>(
inventory_->sheets.size())) {
951 const auto& entry =
inventory_->sheets[sheet_id];
952 if (entry.reserved) {
954 }
else if (entry.flagged) {
957 if (entry.has_block_stats) {
958 ImGui::Text(tr(
"Free 16x16 blocks: %zu"), entry.FreeBlocks().size());
960 if (!entry.labels.empty()) {
961 ImGui::TextUnformatted(absl::StrJoin(entry.labels,
"; ").c_str());
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
std::set< uint16_t > selected_sheets
std::set< uint16_t > modified_sheets
uint16_t current_sheet_id
std::set< uint16_t > open_sheets
zelda3::GameData * game_data
void SelectSheet(uint16_t sheet_id)
Select a sheet for editing.
const GraphicsEditTarget * SourceTarget() const
void DrawBatchOperations()
Draw batch operation buttons.
absl::StatusOr< zelda3::SheetPalette > PngPalette(int sheet_id=-1)
std::function< const project::YazeProject *()> project_getter_
UndoManager * undo_manager_
bool png_status_is_error_
const Rom * inventory_rom_
std::string label_buffer_
void Draw(bool *p_open) override
Draw the sheet browser UI.
const std::optional< zelda3::GfxSheetInventory > & inventory() const
void DrawPngTransfer(uint16_t sheet_id)
std::string inventory_error_
std::string save_plan_error_
std::optional< zelda3::GfxSheetInventory > inventory_
std::string label_status_
LabelImporter label_importer_
std::string SheetUsageSummary(uint16_t sheet_id) const
SavePlanner save_planner_
void SetDataSources(Rom *rom, zelda3::GameData *game_data, std::function< const project::YazeProject *()> project_getter)
Where free-block and "used by" data come from. The project getter may return null (no project open).
GraphicsEditorState * state_
void RefreshInventory()
Rebuild the sheet inventory from the ROM buffer. Runs lazily on the first draw and when the ROM chang...
CatalogTileBrowserState catalog_browser_
void DrawSheetLabelEditor(uint16_t sheet_id)
zelda3::GameData * game_data_
void DrawSelectedSheetInfo()
Storage, reserved state, free 16x16 blocks and "used by" for the current sheet.
void SetPngStatus(std::string message, bool is_error)
void DrawSearchBar()
Draw the search/filter bar.
void Initialize()
Initialize the panel.
LabelSetter label_setter_
void DrawSheetThumbnail(int sheet_id, gfx::Bitmap &bitmap)
Draw a single sheet thumbnail.
gui::Canvas thumbnail_canvas_
std::vector< GraphicsSavePlanEntry > save_plan_
std::vector< SheetPngImportPreview > png_pending_
std::set< uint16_t > save_plan_sheets_
std::string SheetLabel(uint16_t sheet) const
void DrawSheetGrid()
Draw the sheet grid view.
absl::Status Update()
Legacy Update method for backward compatibility.
const void * gfx_sheets_owner() const
GraphicsSheets & gfx_sheets()
Represents a bitmap image optimized for SNES ROM hacking.
void AddTextAt(ImVec2 local_pos, const std::string &text, uint32_t color)
void AddRectFilledAt(ImVec2 local_top_left, ImVec2 size, uint32_t color)
CanvasConfig & GetConfig()
static float GetHexInputWidth()
static float GetSliderWidth()
static std::string ShowSaveFileDialog(const std::string &default_name="", const std::string &default_extension="")
ShowSaveFileDialog opens a save file dialog and returns the selected filepath. Uses global feature fl...
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath. Uses global feature flag to...
3bpp graphics sheets to and from indexed PNGs.
#define ICON_MD_FILE_DOWNLOAD
#define ICON_MD_FILE_UPLOAD
#define ICON_MD_FACT_CHECK
#define ICON_MD_UPLOAD_FILE
#define ICON_MD_SELECT_ALL
#define HOVER_HINT(string)
zelda3::GfxSheetInventoryOptions BuildGfxSheetInventoryOptions(const project::YazeProject *project)
std::string GetGraphicsSheetLabel(const project::YazeProject &project, uint16_t sheet)
void DrawUsageRow(const char *label, const std::vector< int > &values)
std::string HexList(const std::vector< int > &values)
absl::StatusOr< std::vector< uint8_t > > ExportSheetPixelsPng(uint16_t sheet_id, const std::vector< uint8_t > &indexed_pixels, const zelda3::SheetPalette &palette)
void DrawCatalogTileBrowser(CatalogTileBrowserState &browser, GraphicsEditorState &destination, UndoManager *undo_manager, const std::string &destination_usage)
std::string DescribeSheetPngImport(const SheetPngImportPreview &preview)
"Sheet 0x20: blocks 0, 3 (5 tiles)" for the preview list.
void DrawGraphicsPreviewPaletteSelector(GraphicsEditorState &state, GraphicsPaletteSelectorLayout layout, GraphicsPaletteSelectorScope scope)
std::string DescribeGraphicsSavePlanEntry(const GraphicsSavePlanEntry &entry)
"Sheet 0x92: in place at 0x0AED16, 1476 -> 1473 bytes".
absl::StatusOr< std::vector< SheetPngImportPreview > > PreviewRoomPngImport(const Rom &rom, const zelda3::RoomBackgroundSet &set, const std::vector< uint8_t > &png_bytes, const zelda3::SheetPalette &palette)
absl::StatusOr< SheetPngImportPreview > PreviewSheetPngImport(uint16_t sheet_id, const std::vector< uint8_t > &indexed_pixels, const std::vector< uint8_t > &png_bytes, const zelda3::SheetPalette &palette, int first_block)
absl::Status ApplySheetPngImport(const SheetPngImportPreview &preview, GraphicsEditorState &state, UndoManager *undo_manager)
void EndCanvas(Canvas &canvas)
std::string ColumnLabel(absl::string_view text, absl::string_view stable_id)
void DrawBitmapPreview(const CanvasRuntime &rt, gfx::Bitmap &bitmap, const BitmapPreviewOptions &options)
void AutoRegisterLastItem(const std::string &widget_type, const std::string &explicit_label, const std::string &description)
Automatically register the last ImGui item.
void BeginCanvas(Canvas &canvas, ImVec2 child_size)
ImVec4 GetSelectedColor()
ImVec4 GetModifiedColor()
absl::Status WriteBinaryFile(const std::string &path, const std::vector< uint8_t > &bytes)
absl::StatusOr< std::vector< uint8_t > > ReadBinaryFile(const std::string &path)
std::vector< RoomBackgroundSet > ResolveAllRoomBackgroundSets(const Rom &rom, const GameData &data)
All 296 rooms' background sets (header bytes read from the ROM).
absl::StatusOr< SheetPalette > RoomSpriteSheetPalette(Rom &rom, GameData &data, int room, int row, bool high_half)
absl::StatusOr< RoomSheetPaletteContext > ResolveRoomSheetPalette(Rom &rom, GameData &data, int room, int slot, int row)
absl::StatusOr< std::vector< uint8_t > > ExportRoomBackgroundPng(const Rom &rom, const RoomBackgroundSet &set, const SheetPalette &palette)
Room LoadRoomHeaderFromRom(Rom *rom, int room_id)
std::map< int, OverworldAreaGfxInfo > CollectOverworldAreaGfx(Rom &rom, GameData *game_data)
const char * GfxSheetInventoryKindName(GfxSheetStorageKind kind)
RoomBackgroundSet ResolveRoomBackgroundSet(const GameData &data, int room, uint8_t header_blockset)
absl::StatusOr< GfxSheetInventory > BuildGfxSheetInventory(const Rom &rom, const std::map< int, OverworldAreaGfxInfo > &areas, const std::map< int, RoomGfxInfo > &rooms, const GfxSheetInventoryOptions &options)
bool IsHighHalfSpriteSheet(int sheet)
std::map< int, RoomGfxInfo > CollectRoomGfx(const Rom &rom)
constexpr uint32_t kNumGfxSheets
int DungeonBackgroundPaletteOffset(uint8_t main_blockset, int destination_slot)
std::array< SheetColor, 8 > SheetPalette
Colors for 3bpp indices 0-7. Index 0 is exported as transparent.
SheetPalette GrayscaleSheetPalette()
absl::StatusOr< SheetPalette > RoomBackgroundSheetPalette(Rom &rom, GameData &data, int room, int row)
std::optional< CatalogTileTransferPlan > pending
std::optional< float > grid_step
std::optional< float > grid_step
Modern project structure with comprehensive settings consolidation.
std::vector< FileDialogFilter > filters