3#include "absl/strings/str_format.h"
10#include "imgui/imgui.h"
19 : state_(state), rom_(rom) {}
33 "Failed to load Link sheets: %s",
34 status.message().data());
43 float panel_width = ImGui::GetContentRegionAvail().x;
44 float grid_width = std::min(300.0f, panel_width * 0.4f);
47 ImGui::BeginChild(
"##LinkSheetGrid", ImVec2(grid_width, 0),
true);
54 ImGui::BeginChild(
"##LinkPreviewArea", ImVec2(0, 0),
true);
69 "Failed to load Link sheets: %s",
70 status.message().data());
79 float panel_width = ImGui::GetContentRegionAvail().x;
80 float grid_width = std::min(300.0f, panel_width * 0.4f);
83 ImGui::BeginChild(
"##LinkSheetGrid", ImVec2(grid_width, 0),
true);
90 ImGui::BeginChild(
"##LinkPreviewArea", ImVec2(0, 0),
true);
98 return absl::OkStatus();
105 HOVER_HINT(
"Import a .zspr Link sprite file");
111 HOVER_HINT(
"Reset Link graphics to vanilla ROM data");
130 ImGui::Text(
"Link Sheets (14)");
157 std::optional<gui::StyleColorGuard> sel_bg_guard;
159 sel_bg_guard.emplace(ImGuiCol_ChildBg, ImVec4(0.3f, 0.5f, 0.8f, 0.4f));
162 ImGui::BeginChild(absl::StrFormat(
"##LinkSheet%d", sheet_index).c_str(),
165 true, ImGuiWindowFlags_NoScrollbar);
169 if (sheet.is_active()) {
171 if (!sheet.texture() && sheet.surface()) {
177 if (sheet.texture()) {
178 ImVec2 cursor_pos = ImGui::GetCursorScreenPos();
179 ImGui::GetWindowDrawList()->AddImage(
180 (ImTextureID)(intptr_t)sheet.texture(), cursor_pos,
187 if (ImGui::IsWindowHovered() &&
188 ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
193 if (ImGui::IsWindowHovered() &&
194 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
199 ImGui::SetCursorPosY(ImGui::GetCursorPosY() +
kThumbnailSize / 4 + 2);
200 ImGui::Text(
"%d", sheet_index);
204 sel_bg_guard.reset();
207 if (ImGui::IsItemHovered()) {
208 ImGui::BeginTooltip();
209 ImGui::Text(
"Link Sheet %d", sheet_index);
210 ImGui::Text(
"Double-click to edit");
219 float canvas_width = ImGui::GetContentRegionAvail().x - 16;
220 float canvas_height = canvas_width / 4;
223 const float grid_step = 8.0f * (canvas_width / 128.0f);
226 frame_opts.
canvas_size = ImVec2(canvas_width, canvas_height);
234 if (sheet.is_active() && sheet.texture()) {
237 draw_opts.
dest_size = ImVec2(canvas_width, canvas_height);
248 if (ImGui::Button(
ICON_MD_EDIT " Open in Pixel Editor")) {
251 HOVER_HINT(
"Open this sheet in the main pixel editor");
256 ImGui::SliderFloat(
"Zoom", &
preview_zoom_, 1.0f, 8.0f,
"%.1fx");
260 ImGui::Text(
"Display Palette:");
263 const char* palette_names[] = {
"Green Mail",
"Blue Mail",
"Red Mail",
268 if (ImGui::Combo(
"##PaletteSelect", ¤t, palette_names, 4)) {
272 HOVER_HINT(
"Change the display palette for preview");
276 ImGui::Text(
"Info:");
277 ImGui::BulletText(
"896 total tiles (8x8 each)");
278 ImGui::BulletText(
"14 graphics sheets");
279 ImGui::BulletText(
"4BPP format");
283 ImGui::Text(
"Loaded ZSPR:");
284 ImGui::BulletText(
"Name: %s",
loaded_zspr_->metadata.display_name.c_str());
285 ImGui::BulletText(
"Author: %s",
loaded_zspr_->metadata.author.c_str());
286 ImGui::BulletText(
"Tiles: %zu",
loaded_zspr_->tile_count());
293 if (file_path.empty()) {
297 LOG_INFO(
"LinkSpritePanel",
"Importing ZSPR: %s", file_path.c_str());
301 if (!zspr_result.ok()) {
302 LOG_ERROR(
"LinkSpritePanel",
"Failed to load ZSPR: %s",
303 zspr_result.status().message().data());
311 LOG_ERROR(
"LinkSpritePanel",
"ZSPR is not a Link sprite (type=%d)",
321 LOG_ERROR(
"LinkSpritePanel",
"Failed to apply ZSPR to ROM: %s",
322 status.message().data());
329 LOG_WARN(
"LinkSpritePanel",
"Failed to apply ZSPR palette: %s",
330 status.message().data());
337 LOG_INFO(
"LinkSpritePanel",
"ZSPR '%s' imported successfully",
346 LOG_WARN(
"LinkSpritePanel",
"Reset to vanilla not yet implemented");
356 LOG_INFO(
"LinkSpritePanel",
"Request to open Link sheet %d in pixel editor",
365 return absl::FailedPreconditionError(
"ROM not loaded");
371 return result.status();
377 LOG_INFO(
"LinkSpritePanel",
"Loaded %d Link graphics sheets",
383 return absl::OkStatus();
419 if (default_palette.
empty()) {
421 default_palette.
Resize(16);
434 palette = &default_palette;
438 if (sheet.is_active() && sheet.surface()) {
440 sheet.SetPaletteWithTransparent(*palette, 0);
448 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 float GetSliderWidth()
static float GetComboWidth()
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 ICON_MD_CHECK_CIRCLE
#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