diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 43d9ad61..411c2b61 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,7 +2,6 @@ set( YAZE_APP_CORE_SRC app/core/common.cc app/core/controller.cc - app/core/pipeline.cc ) set( @@ -49,6 +48,7 @@ set( app/gui/style.cc app/gui/widgets.cc app/gui/color.cc + app/gui/pipeline.cc ) set(SDL_TARGETS SDL2::SDL2) diff --git a/src/app/core/pipeline.h b/src/app/core/pipeline.h deleted file mode 100644 index fd6c261c..00000000 --- a/src/app/core/pipeline.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef YAZE_APP_CORE_PIPELINE_H -#define YAZE_APP_CORE_PIPELINE_H - -#include -#include -#include -#include - -#include -#include - -#include "absl/strings/string_view.h" -#include "app/core/constants.h" -#include "app/gfx/bitmap.h" -#include "app/gfx/snes_palette.h" -#include "app/gui/canvas.h" -#include "app/rom.h" - -namespace yaze { -namespace app { -namespace core { - -void SelectablePalettePipeline(uint64_t& palette_id, bool& refresh_graphics, - gfx::SNESPalette& palette); - -void GraphicsBinCanvasPipeline(int width, int height, int tile_size, - int num_sheets_to_load, int canvas_id, - bool is_loaded, gfx::BitmapTable& graphics_bin); - -void ButtonPipe(absl::string_view button_text, std::function callback); - -void BitmapCanvasPipeline(gui::Canvas& canvas, const gfx::Bitmap& bitmap, - int width, int height, int tile_size, bool is_loaded, - bool scrollbar, int canvas_id); - -void GraphicsManagerCanvasPipeline(int width, int height, int tile_size, - int num_sheets, int canvas_id, - bool is_loaded, - const gfx::BitmapManager& graphics_manager); - -void BuildAndRenderBitmapPipeline(int width, int height, int depth, Bytes data, - ROM& z3_rom, gfx::Bitmap& bitmap, - gfx::SNESPalette& palette); - -void FileDialogPipeline(absl::string_view display_key, - absl::string_view file_extensions, - std::optional button_text, - std::function callback); - -} // namespace core -} // namespace app -} // namespace yaze - -#endif \ No newline at end of file diff --git a/src/app/editor/context/gfx_context.cc b/src/app/editor/context/gfx_context.cc index fa5f5c5d..a239ba92 100644 --- a/src/app/editor/context/gfx_context.cc +++ b/src/app/editor/context/gfx_context.cc @@ -7,7 +7,7 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "app/core/editor.h" -#include "app/core/pipeline.h" +#include "app/gui/pipeline.h" #include "app/editor/modules/palette_editor.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" diff --git a/src/app/editor/context/gfx_context.h b/src/app/editor/context/gfx_context.h index a15ae07d..18cd687b 100644 --- a/src/app/editor/context/gfx_context.h +++ b/src/app/editor/context/gfx_context.h @@ -9,7 +9,7 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "app/core/editor.h" -#include "app/core/pipeline.h" +#include "app/gui/pipeline.h" #include "app/editor/modules/palette_editor.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" diff --git a/src/app/editor/dungeon_editor.cc b/src/app/editor/dungeon_editor.cc index d825d5c6..20de4319 100644 --- a/src/app/editor/dungeon_editor.cc +++ b/src/app/editor/dungeon_editor.cc @@ -3,11 +3,11 @@ #include #include "app/core/common.h" -#include "app/core/pipeline.h" #include "app/gfx/snes_palette.h" #include "app/gui/canvas.h" #include "app/gui/icons.h" #include "app/gui/input.h" +#include "app/gui/pipeline.h" #include "app/rom.h" #include "app/zelda3/dungeon/object_names.h" #include "app/zelda3/dungeon/room_names.h" @@ -55,8 +55,8 @@ absl::Status DungeonEditor::Update() { ImGui::Begin("Palette Editor", &palette_showing_, 0); current_palette_ = rom()->GetPaletteGroup("dungeon_main")[current_palette_group_id_]; - core::SelectablePalettePipeline(current_palette_id_, refresh_graphics_, - current_palette_); + gui::SelectablePalettePipeline(current_palette_id_, refresh_graphics_, + current_palette_); ImGui::End(); } diff --git a/src/app/editor/graphics_editor.cc b/src/app/editor/graphics_editor.cc index 36550ef5..2d97c7aa 100644 --- a/src/app/editor/graphics_editor.cc +++ b/src/app/editor/graphics_editor.cc @@ -7,7 +7,6 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" -#include "app/core/pipeline.h" #include "app/editor/modules/palette_editor.h" #include "app/gfx/bitmap.h" #include "app/gfx/compression.h" @@ -16,6 +15,7 @@ #include "app/gfx/snes_tile.h" #include "app/gui/canvas.h" #include "app/gui/input.h" +#include "app/gui/pipeline.h" #include "app/gui/style.h" #include "app/rom.h" @@ -52,50 +52,19 @@ absl::Status GraphicsEditor::UpdateGfxEdit() { ImGui::TableHeadersRow(); + NEXT_COLUMN(); + NEXT_COLUMN() { - graphics_bin_canvas_.DrawBackground(ImVec2(0x100 + 1, 223 * 0x40 + 1)); - graphics_bin_canvas_.DrawContextMenu(); - - for (auto& [key, value] : rom()->bitmap_manager()) { - int offset = 0x40 * (key + 1); - int top_left_y = graphics_bin_canvas_.GetZeroPoint().y + 2; - if (key >= 1) { - top_left_y = graphics_bin_canvas_.GetZeroPoint().y + 0x40 * key; - } - auto texture = value.get()->texture(); - - graphics_bin_canvas_.GetDrawList()->AddImage( - (void*)texture, - ImVec2(graphics_bin_canvas_.GetZeroPoint().x + 2, top_left_y), - ImVec2(graphics_bin_canvas_.GetZeroPoint().x + 0x100, - graphics_bin_canvas_.GetZeroPoint().y + offset)); - - // Add a slightly transparent rectangle behind the text - ImVec2 textPos(graphics_bin_canvas_.GetZeroPoint().x + 2, top_left_y); - ImVec2 textSize = - ImGui::CalcTextSize(absl::StrFormat("%02X", key).c_str()); - ImVec2 rectMin(textPos.x, textPos.y); - ImVec2 rectMax(textPos.x + textSize.x, textPos.y + textSize.y); - graphics_bin_canvas_.GetDrawList()->AddRectFilled( - rectMin, rectMax, IM_COL32(0, 125, 0, 128)); - - graphics_bin_canvas_.GetDrawList()->AddText( - textPos, IM_COL32(255, 255, 255, 255), - absl::StrFormat("%02X", key).c_str()); + if (rom()->isLoaded()) { + status_ = UpdateGfxTabView(); } - - graphics_bin_canvas_.DrawGrid(16.0f); - graphics_bin_canvas_.DrawOverlay(); } NEXT_COLUMN() { - // if (rom()->isLoaded()) { - // status_ = DrawTilesetControls(); - // status_ = DrawTilesetCanvas(); - // } + if (rom()->isLoaded()) { + status_ = UpdatePaletteColumn(); + } } - - NEXT_COLUMN() { status_ = DrawPaletteControls(); } } ImGui::EndTable(); @@ -103,6 +72,125 @@ absl::Status GraphicsEditor::UpdateGfxEdit() { return absl::OkStatus(); } +absl::Status GraphicsEditor::UpdateGfxSheetList() { + ImGui::BeginChild( + "##GfxEditChild", ImVec2(0, 0), true, + ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysVerticalScrollbar); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); + for (auto& [key, value] : rom()->bitmap_manager()) { + ImGui::BeginChild(absl::StrFormat("##GfxSheet%02X", key).c_str(), + ImVec2(0x100 + 1, 0x40 + 1), true, + ImGuiWindowFlags_NoDecoration); + ImGui::PopStyleVar(); + gui::Canvas graphics_bin_canvas_; + graphics_bin_canvas_.UpdateEvent( + [&]() { + if (value.get()->IsActive()) { + auto texture = value.get()->texture(); + graphics_bin_canvas_.GetDrawList()->AddImage( + (void*)texture, + ImVec2(graphics_bin_canvas_.GetZeroPoint().x + 2, + graphics_bin_canvas_.GetZeroPoint().y + 2), + ImVec2(graphics_bin_canvas_.GetZeroPoint().x + + value.get()->width() * sheet_scale_, + graphics_bin_canvas_.GetZeroPoint().y + + value.get()->height() * sheet_scale_)); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + current_sheet_ = key; + open_sheets_.insert(key); + } + + // Add a slightly transparent rectangle behind the text + ImVec2 textPos(graphics_bin_canvas_.GetZeroPoint().x + 2, + graphics_bin_canvas_.GetZeroPoint().y + 2); + ImVec2 textSize = + ImGui::CalcTextSize(absl::StrFormat("%02X", key).c_str()); + ImVec2 rectMin(textPos.x, textPos.y); + ImVec2 rectMax(textPos.x + textSize.x, textPos.y + textSize.y); + graphics_bin_canvas_.GetDrawList()->AddRectFilled( + rectMin, rectMax, IM_COL32(0, 125, 0, 128)); + graphics_bin_canvas_.GetDrawList()->AddText( + textPos, IM_COL32(125, 255, 125, 255), + absl::StrFormat("%02X", key).c_str()); + } + }, + ImVec2(0x100 + 1, 0x40 + 1), 0x20, 16.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); + ImGui::EndChild(); + } + ImGui::PopStyleVar(); + ImGui::EndChild(); + return absl::OkStatus(); +} + +absl::Status GraphicsEditor::UpdateGfxTabView() { + static int next_tab_id = 0; + + if (ImGui::BeginTabBar("##GfxEditTabBar", + ImGuiTabBarFlags_AutoSelectNewTabs | + ImGuiTabBarFlags_Reorderable | + ImGuiTabBarFlags_FittingPolicyResizeDown | + ImGuiTabBarFlags_TabListPopupButton)) { + // TODO: Manage the room that is being added to the tab bar. + if (ImGui::TabItemButton( + "+", ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | + ImGuiTableFlags_Hideable | ImGuiTableFlags_BordersOuter | + ImGuiTableFlags_BordersV)) { + open_sheets_.insert(next_tab_id++); // Add new tab + } + + // Submit our regular tabs + for (auto& each : open_sheets_) { + bool open = true; + + if (ImGui::BeginTabItem(absl::StrFormat("%d", each).c_str(), &open, + ImGuiTabItemFlags_None)) { + ImGui::BeginChild( + absl::StrFormat("##GfxEditPaletteChild%d", each).c_str(), + ImVec2(0, 0), true, + ImGuiWindowFlags_NoDecoration | + ImGuiWindowFlags_AlwaysVerticalScrollbar); + current_sheet_canvas_.Update(*rom()->bitmap_manager()[each], + ImVec2(0x100 + 1, 0x40 + 1), 0x20, 4.0f, + 16.0f); + ImGui::EndChild(); + + ImGui::EndTabItem(); + } + + if (!open) release_queue_.push(each); + } + + ImGui::EndTabBar(); + } + ImGui::Separator(); + while (!release_queue_.empty()) { + auto each = release_queue_.top(); + open_sheets_.erase(each); + release_queue_.pop(); + } + return absl::OkStatus(); +} + +absl::Status GraphicsEditor::UpdatePaletteColumn() { + if (rom()->isLoaded()) { + gui::TextWithSeparators("ROM Palette"); + ImGui::Combo("Palette", (int*)&edit_palette_group_, + kPaletteGroupAddressesKeys, + IM_ARRAYSIZE(kPaletteGroupAddressesKeys)); + gui::InputHex("Palette Index", &edit_palette_index_); + } + + auto palette_group = rom()->mutable_palette_group( + kPaletteGroupAddressesKeys[edit_palette_group_]) + [edit_palette_group_index_]; + auto palette = palette_group[edit_palette_index_]; + gui::SelectablePalettePipeline(edit_palette_index_, refresh_graphics_, + palette); + + return absl::OkStatus(); +} + absl::Status GraphicsEditor::UpdateLinkGfxView() { TAB_ITEM("Player Animations") @@ -153,8 +241,8 @@ absl::Status GraphicsEditor::UpdateScadView() { NEXT_COLUMN() { status_ = DrawPaletteControls(); } NEXT_COLUMN() - core::BitmapCanvasPipeline(scr_canvas_, scr_bitmap_, 0x200, 0x200, 0x20, - scr_loaded_, false, 0); + gui::BitmapCanvasPipeline(scr_canvas_, scr_bitmap_, 0x200, 0x200, 0x20, + scr_loaded_, false, 0); status_ = DrawScrImport(); NEXT_COLUMN() @@ -168,16 +256,16 @@ absl::Status GraphicsEditor::UpdateScadView() { refresh_graphics_ = false; } // Load the full graphics space from `super_donkey_1.bin` - core::GraphicsBinCanvasPipeline(0x100, 0x40, 0x20, num_sheets_to_load_, 3, - super_donkey_, graphics_bin_); + gui::GraphicsBinCanvasPipeline(0x100, 0x40, 0x20, num_sheets_to_load_, 3, + super_donkey_, graphics_bin_); } else if (cgx_loaded_ && col_file_) { // Load the CGX graphics - core::BitmapCanvasPipeline(import_canvas_, cgx_bitmap_, 0x100, 16384, 0x20, - cgx_loaded_, true, 5); + gui::BitmapCanvasPipeline(import_canvas_, cgx_bitmap_, 0x100, 16384, 0x20, + cgx_loaded_, true, 5); } else { // Load the BIN/Clipboard Graphics - core::BitmapCanvasPipeline(import_canvas_, bin_bitmap_, 0x100, 16384, 0x20, - gfx_loaded_, true, 2); + gui::BitmapCanvasPipeline(import_canvas_, bin_bitmap_, 0x100, 16384, 0x20, + gfx_loaded_, true, 2); } END_TABLE() @@ -214,7 +302,7 @@ absl::Status GraphicsEditor::DrawCgxImport() { InputText("##CGXFile", cgx_file_name_, sizeof(cgx_file_name_)); SameLine(); - core::FileDialogPipeline("ImportCgxKey", ".CGX,.cgx\0", "Open CGX", [this]() { + gui::FileDialogPipeline("ImportCgxKey", ".CGX,.cgx\0", "Open CGX", [this]() { strncpy(cgx_file_path_, ImGuiFileDialog::Instance()->GetFilePathName().c_str(), sizeof(cgx_file_path_)); @@ -224,10 +312,10 @@ absl::Status GraphicsEditor::DrawCgxImport() { is_open_ = true; cgx_loaded_ = true; }); - core::ButtonPipe("Copy CGX Path", - [this]() { ImGui::SetClipboardText(cgx_file_path_); }); + gui::ButtonPipe("Copy CGX Path", + [this]() { ImGui::SetClipboardText(cgx_file_path_); }); - core::ButtonPipe("Load CGX Data", [this]() { + gui::ButtonPipe("Load CGX Data", [this]() { status_ = gfx::LoadCgx(current_bpp_, cgx_file_path_, cgx_data_, decoded_cgx_, extra_cgx_data_); @@ -244,7 +332,7 @@ absl::Status GraphicsEditor::DrawCgxImport() { absl::Status GraphicsEditor::DrawScrImport() { InputText("##ScrFile", scr_file_name_, sizeof(scr_file_name_)); - core::FileDialogPipeline( + gui::FileDialogPipeline( "ImportScrKey", ".SCR,.scr,.BAK\0", "Open SCR", [this]() { strncpy(scr_file_path_, ImGuiFileDialog::Instance()->GetFilePathName().c_str(), @@ -258,7 +346,7 @@ absl::Status GraphicsEditor::DrawScrImport() { InputInt("SCR Mod", &scr_mod_value_); - core::ButtonPipe("Load Scr Data", [this]() { + gui::ButtonPipe("Load Scr Data", [this]() { status_ = gfx::LoadScr(scr_file_path_, scr_mod_value_, scr_data_); decoded_scr_data_.resize(0x100 * 0x100); @@ -280,7 +368,7 @@ absl::Status GraphicsEditor::DrawPaletteControls() { InputText("##ColFile", col_file_name_, sizeof(col_file_name_)); SameLine(); - core::FileDialogPipeline( + gui::FileDialogPipeline( "ImportColKey", ".COL,.col,.BAK,.bak\0", "Open COL", [this]() { strncpy(col_file_path_, ImGuiFileDialog::Instance()->GetFilePathName().c_str(), @@ -303,8 +391,8 @@ absl::Status GraphicsEditor::DrawPaletteControls() { is_open_ = true; }); - core::ButtonPipe("Copy COL Path", - [this]() { ImGui::SetClipboardText(col_file_path_); }); + gui::ButtonPipe("Copy COL Path", + [this]() { ImGui::SetClipboardText(col_file_path_); }); if (rom()->isLoaded()) { gui::TextWithSeparators("ROM Palette"); @@ -314,8 +402,8 @@ absl::Status GraphicsEditor::DrawPaletteControls() { } if (col_file_palette_.size() != 0) { - core::SelectablePalettePipeline(current_palette_index_, refresh_graphics_, - col_file_palette_); + gui::SelectablePalettePipeline(current_palette_index_, refresh_graphics_, + col_file_palette_); } return absl::OkStatus(); @@ -327,7 +415,7 @@ absl::Status GraphicsEditor::DrawObjImport() { InputText("##ObjFile", obj_file_path_, sizeof(obj_file_path_)); SameLine(); - core::FileDialogPipeline( + gui::FileDialogPipeline( "ImportObjKey", ".obj,.OBJ,.bak,.BAK\0", "Open OBJ", [this]() { strncpy(file_path_, ImGuiFileDialog::Instance()->GetFilePathName().c_str(), @@ -345,7 +433,7 @@ absl::Status GraphicsEditor::DrawTilemapImport() { InputText("##TMapFile", tilemap_file_path_, sizeof(tilemap_file_path_)); SameLine(); - core::FileDialogPipeline( + gui::FileDialogPipeline( "ImportTilemapKey", ".DAT,.dat,.BIN,.bin,.hex,.HEX\0", "Open Tilemap", [this]() { strncpy(tilemap_file_path_, @@ -369,15 +457,15 @@ absl::Status GraphicsEditor::DrawFileImport() { InputText("##ROMFile", file_path_, sizeof(file_path_)); SameLine(); - core::FileDialogPipeline("ImportDlgKey", ".bin,.hex\0", "Open BIN", [this]() { + gui::FileDialogPipeline("ImportDlgKey", ".bin,.hex\0", "Open BIN", [this]() { strncpy(file_path_, ImGuiFileDialog::Instance()->GetFilePathName().c_str(), sizeof(file_path_)); status_ = temp_rom_.LoadFromFile(file_path_); is_open_ = true; }); - core::ButtonPipe("Copy File Path", - [this]() { ImGui::SetClipboardText(file_path_); }); + gui::ButtonPipe("Copy File Path", + [this]() { ImGui::SetClipboardText(file_path_); }); gui::InputHex("BIN Offset", ¤t_offset_); gui::InputHex("BIN Size", &bin_size_); @@ -396,7 +484,7 @@ absl::Status GraphicsEditor::DrawFileImport() { absl::Status GraphicsEditor::DrawClipboardImport() { gui::TextWithSeparators("Clipboard Import"); - core::ButtonPipe("Paste from Clipboard", [this]() { + gui::ButtonPipe("Paste from Clipboard", [this]() { const char* text = ImGui::GetClipboardText(); if (text) { const auto clipboard_data = Bytes(text, text + strlen(text)); @@ -410,7 +498,7 @@ absl::Status GraphicsEditor::DrawClipboardImport() { gui::InputHex("Size", &clipboard_size_); gui::InputHex("Num Sheets", &num_sheets_to_load_); - core::ButtonPipe("Decompress Clipboard Data", [this]() { + gui::ButtonPipe("Decompress Clipboard Data", [this]() { if (temp_rom_.isLoaded()) { status_ = DecompressImportData(0x40000); } else { diff --git a/src/app/editor/graphics_editor.h b/src/app/editor/graphics_editor.h index a79e8d95..dfa5f988 100644 --- a/src/app/editor/graphics_editor.h +++ b/src/app/editor/graphics_editor.h @@ -8,12 +8,12 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" -#include "app/core/pipeline.h" #include "app/editor/modules/palette_editor.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_tile.h" #include "app/gui/canvas.h" #include "app/gui/input.h" +#include "app/gui/pipeline.h" #include "app/rom.h" #include "app/zelda3/overworld.h" @@ -51,10 +51,7 @@ constexpr const char* kPaletteGroupAddressesKeys[] = { }; static constexpr std::string_view kGfxEditColumnNames[] = { - "Tilesheets", - "Current Graphics", - "Palette Controls" -}; + "Tilesheets", "Current Graphics", "Palette Controls"}; static constexpr absl::string_view kGfxToolsetColumnNames[] = { "#memoryEditor", @@ -70,8 +67,17 @@ class GraphicsEditor : public SharedROM { absl::Status Update(); private: + + // Graphics Editor Tab absl::Status UpdateGfxEdit(); + absl::Status UpdateGfxSheetList(); + absl::Status UpdateGfxTabView(); + absl::Status UpdatePaletteColumn(); + + // Link Graphics Edit Tab absl::Status UpdateLinkGfxView(); + + // Prototype Graphics Viewer absl::Status UpdateScadView(); absl::Status DrawToolset(); @@ -91,6 +97,14 @@ class GraphicsEditor : public SharedROM { absl::Status DecompressSuperDonkey(); + uint16_t current_sheet_ = 0; + std::set open_sheets_; + std::stack release_queue_; + uint64_t edit_palette_group_ = 0; + uint64_t edit_palette_group_index_ = 0; + uint64_t edit_palette_index_ = 0; + float sheet_scale_ = 2.0f; + int current_palette_ = 0; uint64_t current_offset_ = 0; uint64_t current_size_ = 0; @@ -178,8 +192,8 @@ class GraphicsEditor : public SharedROM { gui::Canvas import_canvas_; gui::Canvas scr_canvas_; gui::Canvas super_donkey_canvas_; - - gui::Canvas graphics_bin_canvas_; + gui::Canvas current_sheet_canvas_; + // gui::Canvas graphics_bin_canvas_; absl::Status status_; }; diff --git a/src/app/editor/master_editor.cc b/src/app/editor/master_editor.cc index 9bff2a0b..c77fb3d6 100644 --- a/src/app/editor/master_editor.cc +++ b/src/app/editor/master_editor.cc @@ -9,7 +9,6 @@ #include "absl/status/status.h" #include "app/core/common.h" #include "app/core/constants.h" -#include "app/core/pipeline.h" #include "app/core/platform/file_dialog.h" #include "app/editor/dungeon_editor.h" #include "app/editor/graphics_editor.h" @@ -25,6 +24,7 @@ #include "app/gui/canvas.h" #include "app/gui/icons.h" #include "app/gui/input.h" +#include "app/gui/pipeline.h" #include "app/gui/style.h" #include "app/gui/widgets.h" #include "app/rom.h" @@ -160,22 +160,20 @@ absl::Status MasterEditor::Update() { } void MasterEditor::DrawFileDialog() { - core::FileDialogPipeline( - "ChooseFileDlgKey", ".sfc,.smc", std::nullopt, [&]() { - std::string filePathName = - ImGuiFileDialog::Instance()->GetFilePathName(); - status_ = rom()->LoadFromFile(filePathName); - static RecentFilesManager manager("recent_files.txt"); + gui::FileDialogPipeline("ChooseFileDlgKey", ".sfc,.smc", std::nullopt, [&]() { + std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName(); + status_ = rom()->LoadFromFile(filePathName); + static RecentFilesManager manager("recent_files.txt"); - // Load existing recent files - manager.Load(); + // Load existing recent files + manager.Load(); - // Add a new file - manager.AddFile(filePathName); + // Add a new file + manager.AddFile(filePathName); - // Save the updated list - manager.Save(); - }); + // Save the updated list + manager.Save(); + }); } void MasterEditor::DrawStatusPopup() { diff --git a/src/app/editor/master_editor.h b/src/app/editor/master_editor.h index 2feebf38..725b1a3a 100644 --- a/src/app/editor/master_editor.h +++ b/src/app/editor/master_editor.h @@ -10,7 +10,7 @@ #include "absl/status/status.h" #include "app/core/common.h" #include "app/core/constants.h" -#include "app/core/pipeline.h" +#include "app/gui/pipeline.h" #include "app/editor/context/gfx_context.h" #include "app/editor/dungeon_editor.h" #include "app/editor/graphics_editor.h" diff --git a/src/app/editor/modules/gfx_group_editor.cc b/src/app/editor/modules/gfx_group_editor.cc index 09a1a123..7ae53684 100644 --- a/src/app/editor/modules/gfx_group_editor.cc +++ b/src/app/editor/modules/gfx_group_editor.cc @@ -7,7 +7,6 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "app/core/editor.h" -#include "app/core/pipeline.h" #include "app/editor/modules/palette_editor.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" @@ -15,6 +14,7 @@ #include "app/gui/canvas.h" #include "app/gui/icons.h" #include "app/gui/input.h" +#include "app/gui/pipeline.h" #include "app/gui/widgets.h" #include "app/rom.h" #include "app/zelda3/overworld.h" @@ -67,8 +67,8 @@ absl::Status GfxGroupEditor::Update() { sheet.ApplyPalette(palette); rom()->UpdateBitmap(&sheet); } - core::BitmapCanvasPipeline(blockset_canvas_, sheet, 256, - 0x10 * 0x04, 0x20, true, false, 22); + gui::BitmapCanvasPipeline(blockset_canvas_, sheet, 256, 0x10 * 0x04, + 0x20, true, false, 22); } ImGui::EndGroup(); } @@ -108,8 +108,8 @@ absl::Status GfxGroupEditor::Update() { for (int i = 0; i < 4; i++) { int sheet_id = rom()->room_blockset_ids[selected_roomset_][i]; auto &sheet = *rom()->bitmap_manager()[sheet_id]; - core::BitmapCanvasPipeline(roomset_canvas_, sheet, 256, 0x10 * 0x04, - 0x20, true, false, 23); + gui::BitmapCanvasPipeline(roomset_canvas_, sheet, 256, 0x10 * 0x04, + 0x20, true, false, 23); } ImGui::EndGroup(); } @@ -149,8 +149,8 @@ absl::Status GfxGroupEditor::Update() { for (int i = 0; i < 4; i++) { int sheet_id = rom()->spriteset_ids[selected_spriteset_][i]; auto sheet = *rom()->bitmap_manager()[sheet_id]; - core::BitmapCanvasPipeline(spriteset_canvas_, sheet, 256, - 0x10 * 0x04, 0x20, true, false, 24); + gui::BitmapCanvasPipeline(spriteset_canvas_, sheet, 256, + 0x10 * 0x04, 0x20, true, false, 24); } ImGui::EndGroup(); } diff --git a/src/app/editor/modules/gfx_group_editor.h b/src/app/editor/modules/gfx_group_editor.h index 779dc91e..939ab8eb 100644 --- a/src/app/editor/modules/gfx_group_editor.h +++ b/src/app/editor/modules/gfx_group_editor.h @@ -8,7 +8,7 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "app/core/editor.h" -#include "app/core/pipeline.h" +#include "app/gui/pipeline.h" #include "app/editor/modules/palette_editor.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" diff --git a/src/app/editor/modules/tile16_editor.cc b/src/app/editor/modules/tile16_editor.cc index ec8c5946..4048433f 100644 --- a/src/app/editor/modules/tile16_editor.cc +++ b/src/app/editor/modules/tile16_editor.cc @@ -7,7 +7,6 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "app/core/editor.h" -#include "app/core/pipeline.h" #include "app/editor/modules/palette_editor.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" @@ -15,6 +14,7 @@ #include "app/gui/canvas.h" #include "app/gui/icons.h" #include "app/gui/input.h" +#include "app/gui/pipeline.h" #include "app/rom.h" #include "app/zelda3/overworld.h" @@ -100,8 +100,8 @@ absl::Status Tile16Editor::Update() { } absl::Status Tile16Editor::UpdateBlockset() { - core::BitmapCanvasPipeline(blockset_canvas_, tile16_blockset_bmp_, 0x100, - (8192 * 2), 0x20, map_blockset_loaded_, true, 55); + gui::BitmapCanvasPipeline(blockset_canvas_, tile16_blockset_bmp_, 0x100, + (8192 * 2), 0x20, map_blockset_loaded_, true, 55); if (!blockset_canvas_.Points().empty()) { uint16_t x = blockset_canvas_.Points().front().x / 32; @@ -180,7 +180,7 @@ absl::Status Tile16Editor::UpdateTransferTileCanvas() { ImGuiFileDialog::Instance()->OpenDialog( "ChooseTransferFileDlgKey", "Open Transfer ROM", ".sfc,.smc", "."); } - core::FileDialogPipeline( + gui::FileDialogPipeline( "ChooseTransferFileDlgKey", ".sfc,.smc", std::nullopt, [&]() { std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName(); @@ -198,16 +198,16 @@ absl::Status Tile16Editor::UpdateTransferTileCanvas() { palette_ = transfer_overworld_.AreaPalette(); // Create the tile16 blockset image - core::BuildAndRenderBitmapPipeline( - 0x80, 0x2000, 0x80, transfer_overworld_.Tile16Blockset(), *rom(), - transfer_blockset_bmp_, palette_); + gui::BuildAndRenderBitmapPipeline(0x80, 0x2000, 0x80, + transfer_overworld_.Tile16Blockset(), + *rom(), transfer_blockset_bmp_, palette_); transfer_blockset_loaded_ = true; } // Create a canvas for holding the tiles which will be exported - core::BitmapCanvasPipeline(transfer_canvas_, transfer_blockset_bmp_, 0x100, - (8192 * 2), 0x20, transfer_blockset_loaded_, true, - 3); + gui::BitmapCanvasPipeline(transfer_canvas_, transfer_blockset_bmp_, 0x100, + (8192 * 2), 0x20, transfer_blockset_loaded_, true, + 3); return absl::OkStatus(); } diff --git a/src/app/editor/modules/tile16_editor.h b/src/app/editor/modules/tile16_editor.h index f83e9f1a..81beb8da 100644 --- a/src/app/editor/modules/tile16_editor.h +++ b/src/app/editor/modules/tile16_editor.h @@ -8,7 +8,7 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "app/core/editor.h" -#include "app/core/pipeline.h" +#include "app/gui/pipeline.h" #include "app/editor/modules/palette_editor.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index 7aae8828..7d3c661e 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -10,7 +10,6 @@ #include "absl/status/statusor.h" #include "absl/strings/str_format.h" #include "app/core/common.h" -#include "app/core/pipeline.h" #include "app/editor/modules/palette_editor.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" @@ -18,6 +17,7 @@ #include "app/gui/canvas.h" #include "app/gui/icons.h" #include "app/gui/input.h" +#include "app/gui/pipeline.h" #include "app/gui/style.h" #include "app/gui/widgets.h" #include "app/rom.h" @@ -520,13 +520,13 @@ void OverworldEditor::DrawTileSelector() { if (ImGui::BeginTabBar(kTileSelectorTab.data(), ImGuiTabBarFlags_FittingPolicyScroll)) { if (ImGui::BeginTabItem("Tile16")) { - core::BitmapCanvasPipeline(blockset_canvas_, tile16_blockset_bmp_, 0x100, + gui::BitmapCanvasPipeline(blockset_canvas_, tile16_blockset_bmp_, 0x100, (8192 * 2), 0x20, map_blockset_loaded_, true, 1); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Tile8")) { - if (ImGui::BeginChild(core::ImGuiIdIssuer::GetNewID(), + if (ImGui::BeginChild("##tile8viewer", ImGui::GetContentRegionAvail(), true, ImGuiWindowFlags_AlwaysVerticalScrollbar)) { DrawTile8Selector(); @@ -535,7 +535,7 @@ void OverworldEditor::DrawTileSelector() { ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Area Graphics")) { - core::BitmapCanvasPipeline(current_gfx_canvas_, current_gfx_bmp_, 256, + gui::BitmapCanvasPipeline(current_gfx_canvas_, current_gfx_bmp_, 256, 0x10 * 0x40, 0x20, overworld_.isLoaded(), true, 3); ImGui::EndTabItem(); @@ -556,12 +556,12 @@ absl::Status OverworldEditor::LoadGraphics() { palette_ = overworld_.AreaPalette(); // Create the area graphics image - core::BuildAndRenderBitmapPipeline(0x80, 0x200, 0x40, + gui::BuildAndRenderBitmapPipeline(0x80, 0x200, 0x40, overworld_.AreaGraphics(), *rom(), current_gfx_bmp_, palette_); // Create the tile16 blockset image - core::BuildAndRenderBitmapPipeline(0x80, 0x2000, 0x80, + gui::BuildAndRenderBitmapPipeline(0x80, 0x2000, 0x80, overworld_.Tile16Blockset(), *rom(), tile16_blockset_bmp_, palette_); map_blockset_loaded_ = true; @@ -593,18 +593,18 @@ absl::Status OverworldEditor::LoadGraphics() { // Render the bitmaps of each tile. for (int id = 0; id < 4096; id++) { tile16_individual_.emplace_back(); - core::BuildAndRenderBitmapPipeline(0x10, 0x10, 0x80, - tile16_individual_data_[id], *rom(), - tile16_individual_[id], palette_); + gui::BuildAndRenderBitmapPipeline(0x10, 0x10, 0x80, + tile16_individual_data_[id], *rom(), + tile16_individual_[id], palette_); } // Render the overworld maps loaded from the ROM. for (int i = 0; i < zelda3::kNumOverworldMaps; ++i) { overworld_.SetCurrentMap(i); auto palette = overworld_.AreaPalette(); - core::BuildAndRenderBitmapPipeline(0x200, 0x200, 0x200, - overworld_.BitmapData(), *rom(), - maps_bmp_[i], palette); + gui::BuildAndRenderBitmapPipeline(0x200, 0x200, 0x200, + overworld_.BitmapData(), *rom(), + maps_bmp_[i], palette); } if (flags()->kDrawOverworldSprites) { @@ -644,7 +644,7 @@ absl::Status OverworldEditor::DrawExperimentalModal() { ImGui::InputText("##TilemapFile", &ow_tilemap_filename_); ImGui::SameLine(); - core::FileDialogPipeline( + gui::FileDialogPipeline( "ImportTilemapsKey", ".DAT,.dat\0", "Tilemap Hex File", [this]() { ow_tilemap_filename_ = ImGuiFileDialog::Instance()->GetFilePathName(); }); @@ -652,7 +652,7 @@ absl::Status OverworldEditor::DrawExperimentalModal() { ImGui::InputText("##Tile32ConfigurationFile", &tile32_configuration_filename_); ImGui::SameLine(); - core::FileDialogPipeline("ImportTile32Key", ".DAT,.dat\0", "Tile32 Hex File", + gui::FileDialogPipeline("ImportTile32Key", ".DAT,.dat\0", "Tile32 Hex File", [this]() { tile32_configuration_filename_ = ImGuiFileDialog::Instance()->GetFilePathName(); diff --git a/src/app/editor/overworld_editor.h b/src/app/editor/overworld_editor.h index 3362ea30..32c32c58 100644 --- a/src/app/editor/overworld_editor.h +++ b/src/app/editor/overworld_editor.h @@ -12,7 +12,7 @@ #include "absl/strings/str_format.h" #include "app/core/common.h" #include "app/core/editor.h" -#include "app/core/pipeline.h" +#include "app/gui/pipeline.h" #include "app/editor/modules/gfx_group_editor.h" #include "app/editor/modules/palette_editor.h" #include "app/editor/modules/tile16_editor.h" diff --git a/src/app/gui/canvas.cc b/src/app/gui/canvas.cc index e5cad77a..b8a3b529 100644 --- a/src/app/gui/canvas.cc +++ b/src/app/gui/canvas.cc @@ -10,7 +10,6 @@ namespace yaze { namespace app { - namespace gui { constexpr uint32_t kRectangleColor = IM_COL32(32, 32, 32, 255); @@ -18,6 +17,25 @@ constexpr uint32_t kRectangleBorder = IM_COL32(255, 255, 255, 255); constexpr ImGuiButtonFlags kMouseFlags = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight; +void Canvas::Update(const gfx::Bitmap &bitmap, ImVec2 bg_size, int tile_size, + float scale, float grid_size) { + DrawBackground(bg_size); + DrawContextMenu(); + DrawTileSelector(tile_size); + DrawBitmap(bitmap, 0, 0, scale); + DrawGrid(grid_size); + DrawOverlay(); +} + +void Canvas::UpdateEvent(const std::function &event, ImVec2 bg_size, + int tile_size, float grid_size) { + DrawBackground(bg_size); + DrawContextMenu(); + event(); + DrawGrid(grid_size); + DrawOverlay(); +} + void Canvas::DrawBackground(ImVec2 canvas_size) { canvas_p0_ = ImGui::GetCursorScreenPos(); if (!custom_canvas_size_) canvas_sz_ = ImGui::GetContentRegionAvail(); @@ -63,6 +81,7 @@ void Canvas::DrawContextMenu() { bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size, float scale) { const ImGuiIO &io = ImGui::GetIO(); const bool is_hovered = ImGui::IsItemHovered(); + is_hovered_ = is_hovered; // Lock scrolled origin const ImVec2 origin(canvas_p0_.x + scrolling_.x, canvas_p0_.y + scrolling_.y); const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y); @@ -88,10 +107,6 @@ bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size, float scale) { ImVec2(origin.x + painter_pos.x, origin.y + painter_pos.y), ImVec2(origin.x + painter_pos.x + bitmap.width() * scale, origin.y + painter_pos.y + bitmap.height() * scale)); - - // ImVec2( - // canvas_p0_.x + x_offset + scrolling_.x + (bitmap.width() * scale), - // canvas_p0_.y + y_offset + scrolling_.y + (bitmap.height() * scale))); } if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { @@ -169,9 +184,6 @@ void Canvas::RenderUpdatedBitmap(const ImVec2 &click_position, destination.WriteToPixel(pixel_index, tile_data[y * tile_size + x]); } } - - // Render the updated bitmap to the canvas - // rom()->RenderBitmap(¤t_bitmap); } void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset, bool ready) { diff --git a/src/app/gui/canvas.h b/src/app/gui/canvas.h index 48e88f2a..e263d0c4 100644 --- a/src/app/gui/canvas.h +++ b/src/app/gui/canvas.h @@ -22,6 +22,12 @@ class Canvas { explicit Canvas(ImVec2 canvas_size) : custom_canvas_size_(true), canvas_sz_(canvas_size) {} + void Update(const gfx::Bitmap& bitmap, ImVec2 bg_size, int tile_size, + float scale = 1.0f, float grid_size = 64.0f); + + void UpdateEvent(const std::function& event, ImVec2 bg_size, + int tile_size, float grid_size = 64.0f); + // Background for the Canvas represents region without any content drawn to // it, but can be controlled by the user. void DrawBackground(ImVec2 canvas_size = ImVec2(0, 0)); @@ -42,8 +48,8 @@ class Canvas { void HandleTileEdits(Canvas& blockset_canvas, std::vector& source_blockset, gfx::Bitmap& destination, int& current_tile, - float scale = 1.0f, - int tile_painter_size = 16, int tiles_per_row = 8); + float scale = 1.0f, int tile_painter_size = 16, + int tiles_per_row = 8); void RenderUpdatedBitmap(const ImVec2& click_position, const Bytes& tile_data, gfx::Bitmap& destination); @@ -70,6 +76,7 @@ class Canvas { canvas_sz_ = canvas_size; custom_canvas_size_ = true; } + auto IsMouseHovering() const { return is_hovered_; } private: bool enable_grid_ = true; @@ -85,11 +92,6 @@ class Canvas { ImVec2 canvas_p1_; ImVec2 mouse_pos_in_canvas_; ImVec2 drawn_tile_pos_; - - std::vector changed_tiles_; - app::gfx::Bitmap current_tile_; - - std::string title_; }; } // namespace gui diff --git a/src/app/core/pipeline.cc b/src/app/gui/pipeline.cc similarity index 93% rename from src/app/core/pipeline.cc rename to src/app/gui/pipeline.cc index aa4808c6..bd3a0b88 100644 --- a/src/app/core/pipeline.cc +++ b/src/app/gui/pipeline.cc @@ -19,7 +19,7 @@ namespace yaze { namespace app { -namespace core { +namespace gui { void SelectablePalettePipeline(uint64_t& palette_id, bool& refresh_graphics, gfx::SNESPalette& palette) { @@ -29,11 +29,18 @@ void SelectablePalettePipeline(uint64_t& palette_id, bool& refresh_graphics, ImGui::BeginGroup(); // Lock X position ImGui::Text("Palette"); for (int n = 0; n < palette.size(); n++) { + // static gfx::SNESColor transparent_color; + // if ((n % 8) == 0) { + // gui::SNESColorButton("##transparent", transparent_color, 0, + // ImVec2(20, 20)); + // ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); + // } + ImGui::PushID(n); - if ((n % 8) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); + if ((n % 7) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); // Check if the current row is selected - bool is_selected = (palette_id == n / 8); + bool is_selected = (palette_id == n / 7); // Add outline rectangle to the selected row if (is_selected) { @@ -46,7 +53,7 @@ void SelectablePalettePipeline(uint64_t& palette_id, bool& refresh_graphics, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20))) { - palette_id = n / 8; + palette_id = n / 7; refresh_graphics = true; } @@ -182,6 +189,6 @@ void FileDialogPipeline(absl::string_view display_key, } } -} // namespace core +} // namespace gui } // namespace app } // namespace yaze \ No newline at end of file diff --git a/src/app/rom.h b/src/app/rom.h index 7de27c41..4e1e616f 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -414,6 +414,9 @@ class ROM : public core::ExperimentFlags { gfx::PaletteGroup GetPaletteGroup(const std::string& group) { return palette_groups_[group]; } + auto mutable_palette_group(const std::string& group) { + return &palette_groups_[group]; + } Bytes graphics_buffer() const { return graphics_buffer_; } diff --git a/src/app/yaze.cc b/src/app/yaze.cc index a3b08719..c41ca6f7 100644 --- a/src/app/yaze.cc +++ b/src/app/yaze.cc @@ -17,7 +17,6 @@ int main(int argc, char** argv) { absl::InstallFailureSignalHandler(options); yaze::app::core::Controller controller; - EXIT_IF_ERROR(controller.OnEntry()) #ifdef __APPLE__ @@ -30,6 +29,5 @@ int main(int argc, char** argv) { controller.DoRender(); } controller.OnExit(); - return EXIT_SUCCESS; } \ No newline at end of file