5#include "absl/status/status.h"
6#include "absl/status/statusor.h"
7#include "absl/strings/str_cat.h"
23#include "imgui/imgui.h"
24#include "imgui/misc/cpp/imgui_stdlib.h"
25#include "imgui_memory_editor.h"
35using ImGui::InputText;
37using ImGui::TableNextColumn;
40 ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable |
41 ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable |
42 ImGuiTableFlags_SizingFixedFit;
49 if (ImGui::BeginTabBar(
"##TabBar")) {
63 return absl::OkStatus();
67 if (ImGui::BeginTabItem(
"Sheet Editor")) {
70 for (
const auto& name :
71 {
"Tilesheets",
"Current Graphics",
"Palette Controls"})
72 ImGui::TableSetupColumn(name);
74 ImGui::TableHeadersRow();
80 if (
rom()->is_loaded()) {
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);
134 std::vector<uint8_t> png_data;
137 if (png_data.size() > 0) {
141 .Create(width, height, 8, png_data);
166 auto palette = bitmap.palette();
167 for (
int i = 0; i < palette.size(); i++) {
170 ImVec4(palette[i].rgb().x / 255.0f, palette[i].rgb().y / 255.0f,
171 palette[i].rgb().z / 255.0f, 255.0f);
172 if (ImGui::ColorButton(absl::StrFormat(
"Palette Color %d", i).c_str(),
187 "##GfxEditChild", ImVec2(0, 0),
true,
188 ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysVerticalScrollbar);
189 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
191 static ImGuiSelectionBasicStorage selection;
192 ImGuiMultiSelectFlags flags =
193 ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
194 ImGuiMultiSelectIO* ms_io =
195 ImGui::BeginMultiSelect(flags, selection.Size,
kNumGfxSheets);
196 selection.ApplyRequests(ms_io);
197 ImGuiListClipper clipper;
199 if (ms_io->RangeSrcItem != -1)
200 clipper.IncludeItemByIndex(
201 (
int)ms_io->RangeSrcItem);
205 ImGui::BeginChild(absl::StrFormat(
"##GfxSheet%02X", key).c_str(),
206 ImVec2(0x100 + 1, 0x40 + 1),
true,
207 ImGuiWindowFlags_NoDecoration);
208 ImGui::PopStyleVar();
212 if (value.is_active()) {
213 auto texture = value.texture();
215 (ImTextureID)(intptr_t)texture,
223 if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
232 ImGui::CalcTextSize(absl::StrFormat(
"%02X", key).c_str());
233 ImVec2 rent_min(text_pos.x, text_pos.y);
234 ImVec2 rent_max(text_pos.x + text_size.x, text_pos.y + text_size.y);
237 IM_COL32(0, 125, 0, 128));
240 text_pos, IM_COL32(125, 255, 125, 255),
241 absl::StrFormat(
"%02X", key).c_str());
248 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
251 ImGui::PopStyleVar();
252 ms_io = ImGui::EndMultiSelect();
253 selection.ApplyRequests(ms_io);
255 return absl::OkStatus();
259 static int next_tab_id = 0;
260 constexpr ImGuiTabBarFlags kGfxEditTabBarFlags =
261 ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable |
262 ImGuiTabBarFlags_FittingPolicyResizeDown |
263 ImGuiTabBarFlags_TabListPopupButton;
265 if (ImGui::BeginTabBar(
"##GfxEditTabBar", kGfxEditTabBarFlags)) {
266 if (ImGui::TabItemButton(
ICON_MD_ADD, ImGuiTabItemFlags_Trailing |
267 ImGuiTabItemFlags_NoTooltip)) {
273 if (ImGui::BeginTabItem(absl::StrFormat(
"%d", sheet_id).c_str(), &open,
274 ImGuiTabItemFlags_None)) {
276 if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
279 if (ImGui::IsItemHovered()) {
280 if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
286 const auto child_id =
287 absl::StrFormat(
"##GfxEditPaletteChildWindow%d", sheet_id);
288 ImGui::BeginChild(child_id.c_str(), ImVec2(0, 0),
true,
289 ImGuiWindowFlags_NoDecoration |
290 ImGuiWindowFlags_AlwaysVerticalScrollbar |
291 ImGuiWindowFlags_AlwaysHorizontalScrollbar);
297 auto draw_tile_event = [&]() {
327 int id_to_release = -1;
330 ImGui::SetNextWindowPos(ImGui::GetIO().MousePos, ImGuiCond_Once);
331 ImGui::SetNextWindowSize(ImVec2(0x100 + 1 * 16, 0x40 + 1 * 16),
333 ImGui::Begin(absl::StrFormat(
"##GfxEditPaletteChildWindow%d",
id).c_str(),
334 &
active, ImGuiWindowFlags_AlwaysUseWindowPadding);
350 if (id_to_release != -1) {
355 return absl::OkStatus();
359 if (
rom()->is_loaded()) {
364 ImGui::SetNextItemWidth(100.f);
368 ImGui::SetNextItemWidth(100.f);
380 .mutable_gfx_sheets()
385 return absl::OkStatus();
393 for (
const auto& name : {
"Canvas",
"Animation Steps",
"Properties"})
394 ImGui::TableSetupColumn(name);
396 ImGui::TableHeadersRow();
407 link_canvas_.DrawBitmap(link_sheet, x_offset, y_offset, 4);
414 ImGui::Text(
"Placeholder");
417 if (ImGui::Button(
"Load Link Graphics (Experimental)")) {
418 if (
rom()->is_loaded()) {
433 return absl::OkStatus();
447 constexpr ImGuiTableFlags kGfxEditFlags = ImGuiTableFlags_Reorderable |
448 ImGuiTableFlags_Resizable |
449 ImGuiTableFlags_SizingStretchSame;
454 ImGui::TableSetupColumn(
"Tilemaps and Objects (SCR, PNL, OBJ)",
455 ImGuiTableColumnFlags_WidthFixed);
498 return absl::OkStatus();
502 static constexpr absl::string_view kGfxToolsetColumnNames[] = {
506 if (ImGui::BeginTable(
"GraphicsToolset", 1, ImGuiTableFlags_SizingFixedFit,
508 for (
const auto& name : kGfxToolsetColumnNames)
509 ImGui::TableSetupColumn(name.data());
512 if (Button(absl::StrCat(
ICON_MD_MEMORY,
"Open Memory Editor").c_str())) {
522 return absl::OkStatus();
532 if (ImGui::Button(
"Open CGX")) {
540 if (ImGui::Button(
"Copy CGX Path")) {
544 if (ImGui::Button(
"Load CGX Data")) {
555 return absl::OkStatus();
561 if (ImGui::Button(
"Open SCR")) {
571 if (ImGui::Button(
"Load Scr Data")) {
585 return absl::OkStatus();
593 if (ImGui::Button(
"Open COL")) {
603 auto col_file_palette_group_status =
605 if (col_file_palette_group_status.ok()) {
617 if (ImGui::Button(
"Copy Col Path")) {
621 if (
rom()->is_loaded()) {
633 return absl::OkStatus();
642 if (ImGui::Button(
"Open OBJ")) {
651 return absl::OkStatus();
660 if (ImGui::Button(
"Open Tilemap")) {
674 return absl::OkStatus();
683 if (ImGui::Button(
"Open BIN")) {
691 if (Button(
"Copy File Path")) {
698 if (Button(
"Decompress BIN")) {
700 return absl::InvalidArgumentError(
701 "Please select a file before decompressing.");
706 return absl::OkStatus();
711 if (Button(
"Paste From Clipboard")) {
712 const char* text = ImGui::GetClipboardText();
714 const auto clipboard_data =
715 std::vector<uint8_t>(text, text + strlen(text));
716 ImGui::MemFree((
void*)text);
726 if (Button(
"Decompress Clipboard Data")) {
730 status_ = absl::InvalidArgumentError(
731 "Please paste data into the clipboard before "
736 return absl::OkStatus();
741 if (Button(
"Decompress Super Donkey Full")) {
743 return absl::InvalidArgumentError(
744 "Please select `super_donkey_1.bin` before "
749 ImGui::SetItemTooltip(
750 "Requires `super_donkey_1.bin` to be imported under the "
751 "BIN import section.");
752 return absl::OkStatus();
756 std::string title =
"Memory Editor";
758 static MemoryEditor mem_edit;
759 mem_edit.DrawWindow(title.c_str(),
temp_rom_.mutable_data(),
762 return absl::OkStatus();
773 if (
rom()->is_loaded()) {
786 return absl::OkStatus();
793 std::stoi(offset,
nullptr, 16);
795 auto decompressed_data,
818 std::stoi(offset,
nullptr, 16);
820 auto decompressed_data,
842 return absl::OkStatus();
auto mutable_gfx_sheets()
static GraphicsSheetManager & GetInstance()
std::array< gfx::Bitmap, kNumGfxSheets > & gfx_sheets()
auto palette_group() const
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath.
void UpdateBitmap(gfx::Bitmap *bitmap)
Used to update a bitmap on the screen.
void RenderBitmap(gfx::Bitmap *bitmap)
Used to render a bitmap to the screen.
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_
static Renderer & GetInstance()
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
absl::StatusOr< PaletteGroup > CreatePaletteGroupFromColFile(std::vector< SnesColor > &palette_rows)
std::vector< SnesColor > GetColFileData(uint8_t *data)
std::vector< uint8_t > SnesTo8bppSheet(const std::vector< uint8_t > &sheet, int bpp, int num_sheets)
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