4#include "absl/strings/str_format.h"
11#include "imgui/imgui.h"
20 : state_(state), rom_(rom) {}
34 tr(
"Failed to load Link sheets: %s"),
35 status.message().data());
44 float panel_width = ImGui::GetContentRegionAvail().x;
45 float grid_width = std::min(300.0f, panel_width * 0.4f);
48 ImGui::BeginChild(
"##LinkSheetGrid", ImVec2(grid_width, 0),
true);
55 ImGui::BeginChild(
"##LinkPreviewArea", ImVec2(0, 0),
true);
70 tr(
"Failed to load Link sheets: %s"),
71 status.message().data());
80 float panel_width = ImGui::GetContentRegionAvail().x;
81 float grid_width = std::min(300.0f, panel_width * 0.4f);
84 ImGui::BeginChild(
"##LinkSheetGrid", ImVec2(grid_width, 0),
true);
91 ImGui::BeginChild(
"##LinkPreviewArea", ImVec2(0, 0),
true);
99 return absl::OkStatus();
106 HOVER_HINT(
"Import a .zspr Link sprite file");
112 HOVER_HINT(
"Reset Link graphics to vanilla ROM data");
130 ImGui::Text(tr(
"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,
183 ImVec2(0, 0), ImVec2(1, 1),
184 ImGui::GetColorU32(ImVec4(1, 1, 1, 1)));
189 if (ImGui::IsWindowHovered() &&
190 ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
195 if (ImGui::IsWindowHovered() &&
196 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
201 ImGui::SetCursorPosY(ImGui::GetCursorPosY() +
kThumbnailSize / 4 + 2);
202 ImGui::Text(
"%d", sheet_index);
206 sel_bg_guard.reset();
209 if (ImGui::IsItemHovered()) {
210 ImGui::BeginTooltip();
211 ImGui::Text(tr(
"Link Sheet %d"), sheet_index);
212 ImGui::Text(tr(
"Double-click to edit"));
221 float canvas_width = ImGui::GetContentRegionAvail().x - 16;
222 float canvas_height = canvas_width / 4;
225 const float grid_step = 8.0f * (canvas_width / 128.0f);
228 frame_opts.
canvas_size = ImVec2(canvas_width, canvas_height);
237 if (sheet.is_active() && sheet.texture()) {
240 draw_opts.
dest_size = ImVec2(canvas_width, canvas_height);
251 if (ImGui::Button(
ICON_MD_EDIT " Open in Pixel Editor")) {
254 HOVER_HINT(
"Open this sheet in the main pixel editor");
259 ImGui::SliderFloat(tr(
"Zoom"), &
preview_zoom_, 1.0f, 8.0f,
"%.1fx");
263 ImGui::Text(tr(
"Display Palette:"));
266 const char* palette_names[] = {
"Green Mail",
"Blue Mail",
"Red Mail",
271 if (ImGui::Combo(
"##PaletteSelect", ¤t, palette_names, 4)) {
275 HOVER_HINT(
"Change the display palette for preview");
279 ImGui::Text(tr(
"Info:"));
280 ImGui::BulletText(tr(
"896 total tiles (8x8 each)"));
281 ImGui::BulletText(tr(
"14 graphics sheets"));
282 ImGui::BulletText(tr(
"4BPP format"));
286 ImGui::Text(tr(
"Loaded ZSPR:"));
287 ImGui::BulletText(tr(
"Name: %s"),
289 ImGui::BulletText(tr(
"Author: %s"),
loaded_zspr_->metadata.author.c_str());
290 ImGui::BulletText(tr(
"Tiles: %zu"),
loaded_zspr_->tile_count());
297 if (file_path.empty()) {
301 LOG_INFO(
"LinkSpritePanel",
"Importing ZSPR: %s", file_path.c_str());
305 if (!zspr_result.ok()) {
306 LOG_ERROR(
"LinkSpritePanel",
"Failed to load ZSPR: %s",
307 zspr_result.status().message().data());
315 LOG_ERROR(
"LinkSpritePanel",
"ZSPR is not a Link sprite (type=%d)",
325 LOG_ERROR(
"LinkSpritePanel",
"Failed to apply ZSPR to ROM: %s",
326 status.message().data());
333 LOG_WARN(
"LinkSpritePanel",
"Failed to apply ZSPR palette: %s",
334 status.message().data());
341 LOG_INFO(
"LinkSpritePanel",
"ZSPR '%s' imported successfully",
350 LOG_WARN(
"LinkSpritePanel",
"Reset to vanilla not yet implemented");
360 LOG_INFO(
"LinkSpritePanel",
"Request to open Link sheet %d in pixel editor",
369 return absl::FailedPreconditionError(
"ROM not loaded");
375 return result.status();
381 LOG_INFO(
"LinkSpritePanel",
"Loaded %d Link graphics sheets",
387 return absl::OkStatus();
423 if (default_palette.
empty()) {
425 default_palette.
Resize(16);
438 palette = &default_palette;
442 if (sheet.is_active() && sheet.surface()) {
444 sheet.SetPaletteWithTransparent(*palette, 0);
452 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 (WindowContent 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)
CanvasConfig & GetConfig()
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=2, float scale=1.0f)
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