3#include "absl/strings/str_format.h"
7#include "imgui/imgui.h"
16 : state_(state), rom_(rom) {}
29 ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f),
30 "Failed to load Link sheets: %s",
31 status.message().data());
40 float panel_width = ImGui::GetContentRegionAvail().x;
41 float grid_width = std::min(300.0f, panel_width * 0.4f);
44 ImGui::BeginChild(
"##LinkSheetGrid", ImVec2(grid_width, 0),
true);
51 ImGui::BeginChild(
"##LinkPreviewArea", ImVec2(0, 0),
true);
65 ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f),
66 "Failed to load Link sheets: %s",
67 status.message().data());
76 float panel_width = ImGui::GetContentRegionAvail().x;
77 float grid_width = std::min(300.0f, panel_width * 0.4f);
80 ImGui::BeginChild(
"##LinkSheetGrid", ImVec2(grid_width, 0),
true);
87 ImGui::BeginChild(
"##LinkPreviewArea", ImVec2(0, 0),
true);
95 return absl::OkStatus();
102 HOVER_HINT(
"Import a .zspr Link sprite file");
108 HOVER_HINT(
"Reset Link graphics to vanilla ROM data");
113 ImGui::TextColored(ImVec4(0.5f, 1.0f, 0.5f, 1.0f),
"Loaded: %s",
120 ImGui::TextColored(ImVec4(1.0f, 0.6f, 0.2f, 1.0f),
"[Unsaved]");
125 ImGui::Text(
"Link Sheets (14)");
153 ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.3f, 0.5f, 0.8f, 0.4f));
156 ImGui::BeginChild(absl::StrFormat(
"##LinkSheet%d", sheet_index).c_str(),
159 true, ImGuiWindowFlags_NoScrollbar);
163 if (sheet.is_active()) {
165 if (!sheet.texture() && sheet.surface()) {
171 if (sheet.texture()) {
172 ImVec2 cursor_pos = ImGui::GetCursorScreenPos();
173 ImGui::GetWindowDrawList()->AddImage(
174 (ImTextureID)(intptr_t)sheet.texture(), cursor_pos,
181 if (ImGui::IsWindowHovered() &&
182 ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
187 if (ImGui::IsWindowHovered() &&
188 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
193 ImGui::SetCursorPosY(ImGui::GetCursorPosY() +
kThumbnailSize / 4 + 2);
194 ImGui::Text(
"%d", sheet_index);
199 ImGui::PopStyleColor();
203 if (ImGui::IsItemHovered()) {
204 ImGui::BeginTooltip();
205 ImGui::Text(
"Link Sheet %d", sheet_index);
206 ImGui::Text(
"Double-click to edit");
215 float canvas_width = ImGui::GetContentRegionAvail().x - 16;
216 float canvas_height = canvas_width / 4;
219 const float grid_step = 8.0f * (canvas_width / 128.0f);
222 frame_opts.
canvas_size = ImVec2(canvas_width, canvas_height);
230 if (sheet.is_active() && sheet.texture()) {
233 draw_opts.
dest_size = ImVec2(canvas_width, canvas_height);
244 if (ImGui::Button(
ICON_MD_EDIT " Open in Pixel Editor")) {
247 HOVER_HINT(
"Open this sheet in the main pixel editor");
251 ImGui::SetNextItemWidth(100);
252 ImGui::SliderFloat(
"Zoom", &
preview_zoom_, 1.0f, 8.0f,
"%.1fx");
256 ImGui::Text(
"Display Palette:");
259 const char* palette_names[] = {
"Green Mail",
"Blue Mail",
"Red Mail",
263 ImGui::SetNextItemWidth(120);
264 if (ImGui::Combo(
"##PaletteSelect", ¤t, palette_names, 4)) {
268 HOVER_HINT(
"Change the display palette for preview");
272 ImGui::Text(
"Info:");
273 ImGui::BulletText(
"896 total tiles (8x8 each)");
274 ImGui::BulletText(
"14 graphics sheets");
275 ImGui::BulletText(
"4BPP format");
279 ImGui::Text(
"Loaded ZSPR:");
280 ImGui::BulletText(
"Name: %s",
loaded_zspr_->metadata.display_name.c_str());
281 ImGui::BulletText(
"Author: %s",
loaded_zspr_->metadata.author.c_str());
282 ImGui::BulletText(
"Tiles: %zu",
loaded_zspr_->tile_count());
289 if (file_path.empty()) {
293 LOG_INFO(
"LinkSpritePanel",
"Importing ZSPR: %s", file_path.c_str());
297 if (!zspr_result.ok()) {
298 LOG_ERROR(
"LinkSpritePanel",
"Failed to load ZSPR: %s",
299 zspr_result.status().message().data());
307 LOG_ERROR(
"LinkSpritePanel",
"ZSPR is not a Link sprite (type=%d)",
317 LOG_ERROR(
"LinkSpritePanel",
"Failed to apply ZSPR to ROM: %s",
318 status.message().data());
325 LOG_WARN(
"LinkSpritePanel",
"Failed to apply ZSPR palette: %s",
326 status.message().data());
333 LOG_INFO(
"LinkSpritePanel",
"ZSPR '%s' imported successfully",
342 LOG_WARN(
"LinkSpritePanel",
"Reset to vanilla not yet implemented");
352 LOG_INFO(
"LinkSpritePanel",
"Request to open Link sheet %d in pixel editor",
361 return absl::FailedPreconditionError(
"ROM not loaded");
367 return result.status();
373 LOG_INFO(
"LinkSpritePanel",
"Loaded %d Link graphics sheets",
379 return absl::OkStatus();
415 if (default_palette.
empty()) {
417 default_palette.
Resize(16);
430 palette = &default_palette;
434 if (sheet.is_active() && sheet.surface()) {
436 sheet.SetPaletteWithTransparent(*palette, 0);
444 LOG_INFO(
"LinkSpritePanel",
"Applied palette %s to %zu sheets",
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Shared state between GraphicsEditor panel components.
static constexpr float kThumbnailPadding
PaletteType
Link sprite palette types.
bool has_unsaved_changes_
absl::Status LoadLinkSheets()
Load Link graphics sheets from ROM.
void Draw(bool *p_open) override
Draw the panel UI (EditorPanel interface)
void Initialize()
Initialize the panel and load Link sheets.
PaletteType selected_palette_
void OpenSheetInPixelEditor()
Open selected sheet in the main pixel editor.
absl::Status Update()
Legacy Update method for backward compatibility.
std::optional< gfx::ZsprData > loaded_zspr_
void ApplySelectedPalette()
Apply the selected palette to Link sheets for display.
void ImportZspr()
Handle ZSPR file import.
void DrawSheetGrid()
Draw the 4x4 sheet selection grid.
static constexpr int kNumLinkSheets
void DrawPreviewCanvas()
Draw the preview canvas for selected sheet.
void DrawInfoPanel()
Draw info panel with stats.
gui::Canvas preview_canvas_
static const char * GetPaletteName(PaletteType type)
Get the name of a palette type.
void DrawPaletteSelector()
Draw the palette selector dropdown.
std::array< gfx::Bitmap, kNumLinkSheets > link_sheets_
LinkSpritePanel(GraphicsEditorState *state, Rom *rom)
void DrawToolbar()
Draw the toolbar with Import/Reset buttons.
void ResetToVanilla()
Reset Link sheets to vanilla ROM data.
void DrawSheetThumbnail(int sheet_index)
Draw a single Link sheet thumbnail.
static constexpr float kThumbnailSize
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
Represents a bitmap image optimized for SNES ROM hacking.
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
static absl::Status ApplyToRom(Rom &rom, const ZsprData &zspr)
Apply loaded ZSPR sprite data to ROM's Link graphics.
static absl::Status ApplyPaletteToRom(Rom &rom, const ZsprData &zspr)
Apply ZSPR palette data to ROM.
static absl::StatusOr< ZsprData > LoadFromFile(const std::string &path)
Load ZSPR data from a file path.
void SetCanvasSize(ImVec2 canvas_size)
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath. Uses global feature flag to...
#define ICON_MD_FILE_UPLOAD
#define LOG_ERROR(category, format,...)
#define LOG_WARN(category, format,...)
#define LOG_INFO(category, format,...)
#define HOVER_HINT(string)
void EndCanvas(Canvas &canvas)
void BeginCanvas(Canvas &canvas, ImVec2 child_size)
void DrawBitmap(const CanvasRuntime &rt, gfx::Bitmap &bitmap, int border_offset, float scale)
absl::StatusOr< std::array< gfx::Bitmap, kNumLinkSheets > > LoadLinkGraphics(const Rom &rom)
Loads Link's graphics sheets from ROM.
constexpr uint32_t kNumLinkSheets
std::optional< float > grid_step