5#include "absl/status/status.h"
6#include "absl/status/statusor.h"
7#include "absl/strings/str_cat.h"
24#include "imgui/imgui.h"
25#include "imgui/misc/cpp/imgui_stdlib.h"
26#include "imgui_memory_editor.h"
36using ImGui::InputText;
38using ImGui::TableNextColumn;
41 ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable |
42 ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable |
43 ImGuiTableFlags_SizingFixedFit;
50 if (ImGui::BeginTabBar(
"##TabBar")) {
52 if (ImGui::BeginTabItem(
"Sheet Browser")) {
64 return absl::OkStatus();
68 if (ImGui::BeginTabItem(
"Sheet Editor")) {
71 for (
const auto& name :
72 {
"Tilesheets",
"Current Graphics",
"Palette Controls"})
73 ImGui::TableSetupColumn(name);
75 ImGui::TableHeadersRow();
76 ImGui::TableNextColumn();
79 ImGui::TableNextColumn();
80 if (
rom()->is_loaded()) {
85 ImGui::TableNextColumn();
86 if (
rom()->is_loaded()) {
94 return absl::OkStatus();
98 if (ImGui::BeginTable(
"##GfxEditToolset", 9, ImGuiTableFlags_SizingFixedFit,
100 for (
const auto& name :
101 {
"Select",
"Pencil",
"Fill",
"Copy Sheet",
"Paste Sheet",
"Zoom Out",
102 "Zoom In",
"Current Color",
"Tile Size"})
103 ImGui::TableSetupColumn(name);
124 std::vector<uint8_t> png_data =
132 std::vector<uint8_t> png_data;
135 if (png_data.size() > 0) {
139 .Create(width, height, 8, png_data);
162 auto palette = bitmap.palette();
163 for (
int i = 0; i < palette.size(); i++) {
166 ImVec4(palette[i].rgb().x / 255.0f, palette[i].rgb().y / 255.0f,
167 palette[i].rgb().z / 255.0f, 255.0f);
168 if (ImGui::ColorButton(absl::StrFormat(
"Palette Color %d", i).c_str(),
183 "##GfxEditChild", ImVec2(0, 0),
true,
184 ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysVerticalScrollbar);
185 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
187 static ImGuiSelectionBasicStorage selection;
188 ImGuiMultiSelectFlags flags =
189 ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
190 ImGuiMultiSelectIO* ms_io =
191 ImGui::BeginMultiSelect(flags, selection.Size,
kNumGfxSheets);
192 selection.ApplyRequests(ms_io);
193 ImGuiListClipper clipper;
195 if (ms_io->RangeSrcItem != -1)
196 clipper.IncludeItemByIndex(
197 (
int)ms_io->RangeSrcItem);
201 ImGui::BeginChild(absl::StrFormat(
"##GfxSheet%02X", key).c_str(),
202 ImVec2(0x100 + 1, 0x40 + 1),
true,
203 ImGuiWindowFlags_NoDecoration);
204 ImGui::PopStyleVar();
208 if (value.is_active()) {
209 auto texture = value.texture();
211 (ImTextureID)(intptr_t)texture,
219 if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
228 ImGui::CalcTextSize(absl::StrFormat(
"%02X", key).c_str());
229 ImVec2 rent_min(text_pos.x, text_pos.y);
230 ImVec2 rent_max(text_pos.x + text_size.x, text_pos.y + text_size.y);
233 IM_COL32(0, 125, 0, 128));
236 text_pos, IM_COL32(125, 255, 125, 255),
237 absl::StrFormat(
"%02X", key).c_str());
244 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
247 ImGui::PopStyleVar();
248 ms_io = ImGui::EndMultiSelect();
249 selection.ApplyRequests(ms_io);
251 return absl::OkStatus();
255 static int next_tab_id = 0;
256 constexpr ImGuiTabBarFlags kGfxEditTabBarFlags =
257 ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable |
258 ImGuiTabBarFlags_FittingPolicyResizeDown |
259 ImGuiTabBarFlags_TabListPopupButton;
261 if (ImGui::BeginTabBar(
"##GfxEditTabBar", kGfxEditTabBarFlags)) {
262 if (ImGui::TabItemButton(
ICON_MD_ADD, ImGuiTabItemFlags_Trailing |
263 ImGuiTabItemFlags_NoTooltip)) {
269 if (ImGui::BeginTabItem(absl::StrFormat(
"%d", sheet_id).c_str(), &open,
270 ImGuiTabItemFlags_None)) {
272 if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
275 if (ImGui::IsItemHovered()) {
276 if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
282 const auto child_id =
283 absl::StrFormat(
"##GfxEditPaletteChildWindow%d", sheet_id);
284 ImGui::BeginChild(child_id.c_str(), ImVec2(0, 0),
true,
285 ImGuiWindowFlags_NoDecoration |
286 ImGuiWindowFlags_AlwaysVerticalScrollbar |
287 ImGuiWindowFlags_AlwaysHorizontalScrollbar);
292 auto draw_tile_event = [&]() {
321 int id_to_release = -1;
324 ImGui::SetNextWindowPos(ImGui::GetIO().MousePos, ImGuiCond_Once);
325 ImGui::SetNextWindowSize(ImVec2(0x100 + 1 * 16, 0x40 + 1 * 16),
327 ImGui::Begin(absl::StrFormat(
"##GfxEditPaletteChildWindow%d",
id).c_str(),
328 &
active, ImGuiWindowFlags_AlwaysUseWindowPadding);
343 if (id_to_release != -1) {
348 return absl::OkStatus();
352 if (
rom()->is_loaded()) {
357 ImGui::SetNextItemWidth(100.f);
361 ImGui::SetNextItemWidth(100.f);
377 return absl::OkStatus();
385 for (
const auto& name : {
"Canvas",
"Animation Steps",
"Properties"})
386 ImGui::TableSetupColumn(name);
388 ImGui::TableHeadersRow();
390 ImGui::TableNextColumn();
399 link_canvas_.DrawBitmap(link_sheet, x_offset, y_offset, 4);
405 ImGui::TableNextColumn();
406 ImGui::Text(
"Placeholder");
408 ImGui::TableNextColumn();
409 if (ImGui::Button(
"Load Link Graphics (Experimental)")) {
410 if (
rom()->is_loaded()) {
425 return absl::OkStatus();
439 constexpr ImGuiTableFlags kGfxEditFlags = ImGuiTableFlags_Reorderable |
440 ImGuiTableFlags_Resizable |
441 ImGuiTableFlags_SizingStretchSame;
446 ImGui::TableSetupColumn(
"Tilemaps and Objects (SCR, PNL, OBJ)",
447 ImGuiTableColumnFlags_WidthFixed);
490 return absl::OkStatus();
494 static constexpr absl::string_view kGfxToolsetColumnNames[] = {
498 if (ImGui::BeginTable(
"GraphicsToolset", 1, ImGuiTableFlags_SizingFixedFit,
500 for (
const auto& name : kGfxToolsetColumnNames)
501 ImGui::TableSetupColumn(name.data());
504 if (Button(absl::StrCat(
ICON_MD_MEMORY,
"Open Memory Editor").c_str())) {
514 return absl::OkStatus();
524 if (ImGui::Button(
"Open CGX")) {
532 if (ImGui::Button(
"Copy CGX Path")) {
536 if (ImGui::Button(
"Load CGX Data")) {
547 return absl::OkStatus();
553 if (ImGui::Button(
"Open SCR")) {
563 if (ImGui::Button(
"Load Scr Data")) {
577 return absl::OkStatus();
585 if (ImGui::Button(
"Open COL")) {
595 auto col_file_palette_group_status =
597 if (col_file_palette_group_status.ok()) {
609 if (ImGui::Button(
"Copy Col Path")) {
613 if (
rom()->is_loaded()) {
625 return absl::OkStatus();
634 if (ImGui::Button(
"Open OBJ")) {
643 return absl::OkStatus();
652 if (ImGui::Button(
"Open Tilemap")) {
666 return absl::OkStatus();
675 if (ImGui::Button(
"Open BIN")) {
683 if (Button(
"Copy File Path")) {
690 if (Button(
"Decompress BIN")) {
692 return absl::InvalidArgumentError(
693 "Please select a file before decompressing.");
698 return absl::OkStatus();
703 if (Button(
"Paste From Clipboard")) {
704 const char* text = ImGui::GetClipboardText();
706 const auto clipboard_data =
707 std::vector<uint8_t>(text, text + strlen(text));
708 ImGui::MemFree((
void*)text);
718 if (Button(
"Decompress Clipboard Data")) {
722 status_ = absl::InvalidArgumentError(
723 "Please paste data into the clipboard before "
728 return absl::OkStatus();
733 if (Button(
"Decompress Super Donkey Full")) {
735 return absl::InvalidArgumentError(
736 "Please select `super_donkey_1.bin` before "
741 ImGui::SetItemTooltip(
742 "Requires `super_donkey_1.bin` to be imported under the "
743 "BIN import section.");
744 return absl::OkStatus();
748 std::string title =
"Memory Editor";
750 static MemoryEditor mem_edit;
751 mem_edit.DrawWindow(title.c_str(),
temp_rom_.mutable_data(),
754 return absl::OkStatus();
765 if (
rom()->is_loaded()) {
778 return absl::OkStatus();
785 std::stoi(offset,
nullptr, 16);
787 auto decompressed_data,
810 std::stoi(offset,
nullptr, 16);
812 auto decompressed_data,
834 return absl::OkStatus();
auto palette_group() const
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath.
void UpdateBitmap(gfx::Bitmap *bitmap)
void RenderBitmap(gfx::Bitmap *bitmap)
absl::Status UpdateGfxEdit()
std::vector< uint8_t > scr_data_
uint64_t edit_palette_group_name_index_
std::array< gfx::Bitmap, kNumLinkSheets > link_sheets_
uint64_t clipboard_offset_
absl::Status UpdatePaletteColumn()
gfx::PaletteGroup col_file_palette_group_
std::string col_file_path_
absl::Status UpdateLinkGfxView()
std::string cgx_file_path_
absl::Status DrawMemoryEditor()
absl::Status Load() override
void Initialize() override
absl::Status UpdateGfxSheetList()
std::vector< uint8_t > decoded_cgx_
std::string scr_file_path_
GfxEditMode gfx_edit_mode_
std::set< uint16_t > child_window_sheets_
absl::Status DecompressSuperDonkey()
std::array< gfx::Bitmap, kNumGfxSheets > gfx_sheets_
gfx::SnesPalette col_file_palette_
std::string col_file_name_
absl::Status DrawToolset()
absl::Status DrawCgxImport()
std::vector< uint8_t > cgx_data_
void DrawGfxEditToolset()
std::string obj_file_path_
uint64_t edit_palette_index_
absl::Status DrawFileImport()
std::vector< uint8_t > import_data_
uint64_t current_palette_index_
std::vector< SDL_Color > decoded_col_
absl::Status DrawTilemapImport()
gfx::SnesPalette z3_rom_palette_
std::set< uint16_t > open_sheets_
absl::Status Update() override
absl::Status DrawScrImport()
uint64_t edit_palette_sub_index_
std::string tilemap_file_path_
gui::Canvas current_sheet_canvas_
absl::Status UpdateScadView()
std::vector< uint8_t > extra_cgx_data_
gui::Canvas import_canvas_
std::vector< uint8_t > decoded_scr_data_
std::stack< uint16_t > release_queue_
std::string cgx_file_name_
absl::Status DrawObjImport()
absl::Status DrawClipboardImport()
gui::GfxSheetAssetBrowser asset_browser_
absl::Status UpdateGfxTabView()
uint64_t num_sheets_to_load_
absl::Status DecompressImportData(int size)
absl::Status DrawExperimentalFeatures()
gui::Canvas graphics_bin_canvas_
absl::Status DrawPaletteControls()
std::string scr_file_name_
auto mutable_gfx_sheets()
std::array< gfx::Bitmap, 223 > & gfx_sheets()
Represents a bitmap image.
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
#define ICON_MD_FORMAT_COLOR_FILL
#define ICON_MD_CONTENT_PASTE
#define ICON_MD_SELECT_ALL
#define ICON_MD_CONTENT_COPY
#define BEGIN_TABLE(l, n, f)
#define RETURN_IF_ERROR(expression)
#define ASSIGN_OR_RETURN(type_variable_name, expression)
#define CLEAR_AND_RETURN_STATUS(status)
#define HOVER_HINT(string)
void GetImageFromClipboard(std::vector< uint8_t > &data, int &width, int &height)
void CopyImageToClipboard(const std::vector< uint8_t > &data)
Editors are the view controllers for the application.
const std::string kSuperDonkeySprites[]
constexpr ImGuiTableFlags kGfxEditTableFlags
const std::string kSuperDonkeyTiles[]
constexpr int kNintendoMode1
absl::StatusOr< std::vector< uint8_t > > DecompressV2(const uint8_t *data, int offset, int size, int mode)
Decompresses a buffer of data using the LC_LZ2 algorithm.
absl::Status LoadScr(std::string_view filename, uint8_t input_value, std::vector< uint8_t > &map_data)
Load Scr file (screen data)
std::vector< SDL_Color > DecodeColFile(const std::string_view filename)
Decode color file.
constexpr int kTilesheetHeight
constexpr int kTilesheetWidth
absl::Status LoadCgx(uint8_t bpp, std::string_view filename, std::vector< uint8_t > &cgx_data, std::vector< uint8_t > &cgx_loaded, std::vector< uint8_t > &cgx_header)
Load Cgx file (graphical content)
constexpr const char * kPaletteGroupAddressesKeys[]
absl::Status DrawScrWithCgx(uint8_t bpp, std::vector< uint8_t > &map_data, std::vector< uint8_t > &map_bitmap_data, std::vector< uint8_t > &cgx_loaded)
Draw screen tilemap with graphical data.
constexpr int kTilesheetDepth
std::vector< uint8_t > SnesTo8bppSheet(std::span< uint8_t > sheet, int bpp, int num_sheets)
absl::StatusOr< PaletteGroup > CreatePaletteGroupFromColFile(std::vector< SnesColor > &palette_rows)
std::vector< SnesColor > GetColFileData(uint8_t *data)
void BitmapCanvasPipeline(gui::Canvas &canvas, gfx::Bitmap &bitmap, int width, int height, int tile_size, bool is_loaded, bool scrollbar, int canvas_id)
bool InputHex(const char *label, uint64_t *data)
void SelectablePalettePipeline(uint64_t &palette_id, bool &refresh_graphics, gfx::SnesPalette &palette)
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
void TextWithSeparators(const absl::string_view &text)
Main namespace for the application.
absl::StatusOr< std::array< gfx::Bitmap, kNumLinkSheets > > LoadLinkGraphics(const Rom &rom)
Loads the players 4bpp graphics sheet from Rom data.
constexpr uint32_t kNumGfxSheets