yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
sheet_browser_view.cc
Go to the documentation of this file.
2#include "util/i18n/tr.h"
3
4#include <cstdlib>
5#include <cstring>
6
7#include "absl/strings/str_format.h"
11#include "app/gui/core/style.h"
14#include "imgui/imgui.h"
15
16namespace yaze {
17namespace editor {
18
20 // Initialize with sensible defaults
21 thumbnail_scale_ = 2.0f;
22 columns_ = 2;
23}
24
25void SheetBrowserView::Draw(bool* p_open) {
26 // WindowContent interface - delegate to existing Update() logic
28 ImGui::Separator();
30 ImGui::Separator();
32}
33
36 ImGui::Separator();
38 ImGui::Separator();
40 return absl::OkStatus();
41}
42
44 ImGui::Text(tr("Search:"));
45 ImGui::SameLine();
46 ImGui::SetNextItemWidth(gui::LayoutHelpers::GetHexInputWidth());
47 if (ImGui::InputText("##SheetSearch", search_buffer_, sizeof(search_buffer_),
48 ImGuiInputTextFlags_CharsHexadecimal)) {
49 // Parse hex input for sheet number
50 if (strlen(search_buffer_) > 0) {
51 int value = static_cast<int>(strtol(search_buffer_, nullptr, 16));
52 if (value >= 0 && value <= 222) {
53 state_->SelectSheet(static_cast<uint16_t>(value));
54 }
55 }
56 }
57 HOVER_HINT("Enter hex sheet number (00-DE)");
58
59 ImGui::SameLine();
60 ImGui::SetNextItemWidth(gui::LayoutHelpers::GetCompactInputWidth());
61 ImGui::DragInt("##FilterMin", &filter_min_, 1.0f, 0, 222, "%02X");
62 ImGui::SameLine();
63 ImGui::Text("-");
64 ImGui::SameLine();
65 ImGui::SetNextItemWidth(gui::LayoutHelpers::GetCompactInputWidth());
66 ImGui::DragInt("##FilterMax", &filter_max_, 1.0f, 0, 222, "%02X");
67
68 ImGui::SameLine();
69 ImGui::Checkbox(tr("Modified"), &show_only_modified_);
70 HOVER_HINT("Show only modified sheets");
71}
72
74 if (ImGui::Button(ICON_MD_SELECT_ALL " Select All")) {
75 for (int i = filter_min_; i <= filter_max_; i++) {
76 state_->selected_sheets.insert(static_cast<uint16_t>(i));
77 }
78 }
79 ImGui::SameLine();
80 if (ImGui::Button(ICON_MD_DESELECT " Clear")) {
81 state_->selected_sheets.clear();
82 }
83
84 if (!state_->selected_sheets.empty()) {
85 ImGui::SameLine();
86 ImGui::Text(tr("(%zu selected)"), state_->selected_sheets.size());
87 }
88
89 // Thumbnail size slider
90 ImGui::SameLine();
91 ImGui::SetNextItemWidth(gui::LayoutHelpers::GetSliderWidth());
92 ImGui::SliderFloat("##Scale", &thumbnail_scale_, 1.0f, 4.0f, "%.1fx");
93}
94
96 ImGui::BeginChild("##SheetGridChild", ImVec2(0, 0), true,
97 ImGuiWindowFlags_AlwaysVerticalScrollbar);
98
99 auto& sheets = gfx::Arena::Get().gfx_sheets();
100
101 // Calculate thumbnail size
102 const float thumb_width = 128 * thumbnail_scale_;
103 const float thumb_height = 32 * thumbnail_scale_;
104 const float padding = 4.0f;
105
106 // Calculate columns based on available width
107 float available_width = ImGui::GetContentRegionAvail().x;
108 columns_ = std::max(
109 1, static_cast<int>(available_width / (thumb_width + padding * 2)));
110
111 int col = 0;
112 for (int i = filter_min_; i <= filter_max_ && i < zelda3::kNumGfxSheets;
113 i++) {
114 // Filter by modification state if enabled
116 state_->modified_sheets.find(static_cast<uint16_t>(i)) ==
117 state_->modified_sheets.end()) {
118 continue;
119 }
120
121 if (col > 0) {
122 ImGui::SameLine();
123 }
124
125 ImGui::PushID(i);
126 DrawSheetThumbnail(i, sheets[i]);
127 ImGui::PopID();
128
129 col++;
130 if (col >= columns_) {
131 col = 0;
132 }
133 }
134
135 ImGui::EndChild();
136}
137
139 const float thumb_width = 128 * thumbnail_scale_;
140 const float thumb_height = 32 * thumbnail_scale_;
141
142 bool is_selected =
143 state_->current_sheet_id == static_cast<uint16_t>(sheet_id);
144 bool is_multi_selected =
145 state_->selected_sheets.count(static_cast<uint16_t>(sheet_id)) > 0;
146 bool is_modified =
147 state_->modified_sheets.count(static_cast<uint16_t>(sheet_id)) > 0;
148
149 // Selection highlight
150 std::optional<gui::StyleColorGuard> sel_bg_guard;
151 if (is_selected) {
152 ImVec4 sel_bg = gui::GetSelectedColor();
153 sel_bg.w = 0.3f;
154 sel_bg_guard.emplace(ImGuiCol_ChildBg, sel_bg);
155 } else if (is_multi_selected) {
156 ImVec4 multi_bg = gui::GetModifiedColor();
157 multi_bg.w = 0.3f;
158 sel_bg_guard.emplace(ImGuiCol_ChildBg, multi_bg);
159 }
160
161 ImGui::BeginChild(absl::StrFormat("##Sheet%02X", sheet_id).c_str(),
162 ImVec2(thumb_width + 8, thumb_height + 24), true,
163 ImGuiWindowFlags_NoScrollbar);
164
165 gui::BitmapPreviewOptions preview_opts;
166 preview_opts.canvas_size = ImVec2(thumb_width + 1, thumb_height + 1);
167 preview_opts.dest_pos = ImVec2(2, 2);
168 preview_opts.dest_size = ImVec2(thumb_width - 2, thumb_height - 2);
169 preview_opts.grid_step = 8.0f * thumbnail_scale_;
170 preview_opts.draw_context_menu = false;
171 preview_opts.ensure_texture = true;
172
173 gui::CanvasFrameOptions frame_opts;
174 frame_opts.canvas_size = preview_opts.canvas_size;
175 frame_opts.draw_context_menu = preview_opts.draw_context_menu;
176 frame_opts.draw_grid = preview_opts.draw_grid;
177 frame_opts.grid_step = preview_opts.grid_step;
178 frame_opts.draw_overlay = preview_opts.draw_overlay;
179 frame_opts.render_popups = preview_opts.render_popups;
180
181 {
183 auto rt = gui::BeginCanvas(thumbnail_canvas_, frame_opts);
184 gui::DrawBitmapPreview(rt, bitmap, preview_opts);
185
186 // Sheet label with modification indicator
187 std::string label = absl::StrFormat("%02X", sheet_id);
188 if (is_modified) {
189 label += "*";
190 }
191
192 // Draw label with background
193 ImVec2 text_pos = ImGui::GetCursorScreenPos();
194 ImVec2 text_size = ImGui::CalcTextSize(label.c_str());
196 ImVec2(2, 2), ImVec2(text_size.x + 4, text_size.y + 2),
197 is_modified ? IM_COL32(180, 100, 0, 200) : IM_COL32(0, 100, 0, 180));
198
199 thumbnail_canvas_.AddTextAt(ImVec2(4, 2), label,
200 is_modified ? IM_COL32(255, 200, 100, 255)
201 : IM_COL32(150, 255, 150, 255));
202 gui::EndCanvas(thumbnail_canvas_, rt, frame_opts);
203 }
204
205 // Click handling
206 if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
207 if (ImGui::GetIO().KeyCtrl) {
208 // Ctrl+click for multi-select
209 if (is_multi_selected) {
210 state_->selected_sheets.erase(static_cast<uint16_t>(sheet_id));
211 } else {
212 state_->selected_sheets.insert(static_cast<uint16_t>(sheet_id));
213 }
214 } else {
215 // Normal click to select
216 state_->SelectSheet(static_cast<uint16_t>(sheet_id));
217 }
218 }
219
220 // Double-click to open in new tab
221 if (ImGui::IsItemHovered() &&
222 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
223 state_->open_sheets.insert(static_cast<uint16_t>(sheet_id));
224 }
225
226 ImGui::EndChild();
227
228 sel_bg_guard.reset();
229
230 // Tooltip with sheet info
231 if (ImGui::IsItemHovered()) {
232 ImGui::BeginTooltip();
233 ImGui::Text(tr("Sheet: 0x%02X (%d)"), sheet_id, sheet_id);
234 if (bitmap.is_active()) {
235 ImGui::Text(tr("Size: %dx%d"), bitmap.width(), bitmap.height());
236 ImGui::Text(tr("Depth: %d bpp"), bitmap.depth());
237 } else {
238 ImGui::Text(tr("(Inactive)"));
239 }
240 if (is_modified) {
241 ImGui::TextColored(gui::GetModifiedColor(), tr("Modified"));
242 }
243 ImGui::EndTooltip();
244 }
245}
246
247} // namespace editor
248} // namespace yaze
void SelectSheet(uint16_t sheet_id)
Select a sheet for editing.
absl::Status Update()
Legacy Update method for backward compatibility.
void Initialize()
Initialize the view.
void Draw(bool *p_open) override
Draw the sheet browser UI.
void DrawBatchOperations()
Draw batch operation buttons.
void DrawSheetGrid()
Draw the sheet grid view.
void DrawSheetThumbnail(int sheet_id, gfx::Bitmap &bitmap)
Draw a single sheet thumbnail.
void DrawSearchBar()
Draw the search/filter bar.
std::array< gfx::Bitmap, 223 > & gfx_sheets()
Get reference to all graphics sheets.
Definition arena.h:152
static Arena & Get()
Definition arena.cc:21
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:67
bool is_active() const
Definition bitmap.h:405
int height() const
Definition bitmap.h:395
int width() const
Definition bitmap.h:394
int depth() const
Definition bitmap.h:396
void AddTextAt(ImVec2 local_pos, const std::string &text, uint32_t color)
Definition canvas.cc:1944
void AddRectFilledAt(ImVec2 local_top_left, ImVec2 size, uint32_t color)
Definition canvas.cc:1933
CanvasConfig & GetConfig()
Definition canvas.h:229
static float GetHexInputWidth()
static float GetSliderWidth()
static float GetCompactInputWidth()
#define ICON_MD_SELECT_ALL
Definition icons.h:1680
#define ICON_MD_DESELECT
Definition icons.h:540
#define HOVER_HINT(string)
Definition macro.h:24
void EndCanvas(Canvas &canvas)
void DrawBitmapPreview(const CanvasRuntime &rt, gfx::Bitmap &bitmap, const BitmapPreviewOptions &options)
void BeginCanvas(Canvas &canvas, ImVec2 child_size)
ImVec4 GetSelectedColor()
Definition ui_helpers.cc:99
ImVec4 GetModifiedColor()
constexpr uint32_t kNumGfxSheets
Definition game_data.h:26
std::optional< float > grid_step
std::optional< float > grid_step