7#include "absl/strings/str_format.h"
17 while (!s.empty() && (s.front() ==
' ' || s.front() ==
'\t' ||
18 s.front() ==
'\n' || s.front() ==
'\r')) {
21 while (!s.empty() && (s.back() ==
' ' || s.back() ==
'\t' ||
22 s.back() ==
'\n' || s.back() ==
'\r')) {
36 if (trimmed.empty()) {
40 bool decimal_mode =
false;
41 if (trimmed.size() >= 2 && (trimmed[0] ==
'd' || trimmed[0] ==
'D') &&
44 trimmed.remove_prefix(2);
45 }
else if (trimmed.size() >= 2 && trimmed[0] ==
'0' &&
46 (trimmed[1] ==
'x' || trimmed[1] ==
'X')) {
47 trimmed.remove_prefix(2);
50 if (trimmed.empty()) {
54 std::string text(trimmed);
55 unsigned int parsed = 0;
57 const char* format = decimal_mode ?
"%u%c" :
"%x%c";
58 if (std::sscanf(text.c_str(), format, &parsed, &trailing) != 1) {
62 *out_value =
static_cast<int>(parsed);
70 total_tiles_(config_.total_tiles),
71 widget_id_(std::move(widget_id)) {}
75 total_tiles_(config.total_tiles),
76 widget_id_(std::move(widget_id)) {}
115 const int tile_display_size =
123 const int tile_display_size =
127 return ImVec2(GridWidthFor(
config_),
133 constexpr float kImGuiDefaultScrollbarSize = 14.0f;
134 return ImGui::GetCurrentContext() ? ImGui::GetStyle().ScrollbarSize
135 : kImGuiDefaultScrollbarSize;
139 float scrollbar_size) {
142 return GridWidthFor(config) + scrollbar_size;
157 const int tile_display_size =
163 ImGui::SetCursorPos(ImVec2(0, 0));
164 ImGui::Dummy(content_size);
165 ImGui::SetCursorPos(ImVec2(0, 0));
173 const ImVec2 window_size = ImGui::GetWindowSize();
175 target.x - (window_size.x / 2.0f) + (tile_display_size / 2.0f);
177 target.y - (window_size.y / 2.0f) + (tile_display_size / 2.0f);
178 scroll_x = std::max(0.0f, scroll_x);
179 scroll_y = std::max(0.0f, scroll_y);
180 ImGui::SetScrollX(scroll_x);
181 ImGui::SetScrollY(scroll_y);
200 ImGui::BeginTooltip();
201 ImGui::Text(tr(
"Tile %d (0x%03X)"), hovered_tile, hovered_tile);
210 auto* texture_id = atlas.
texture();
211 if (texture_id !=
nullptr) {
212 float atlas_w =
static_cast<float>(atlas.
width());
213 float atlas_h =
static_cast<float>(atlas.
height());
214 if (atlas_w > 0 && atlas_h > 0) {
215 ImVec2 uv0(src_x / atlas_w, src_y / atlas_h);
219 ImGui::Image((ImTextureID)(intptr_t)texture_id,
220 ImVec2(preview_size, preview_size), uv0, uv1);
245 ImGui::SetClipboardText(
256 int tile_display_size) {
259 if (!ImGui::IsItemHovered()) {
263 const bool clicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
264 const bool double_clicked =
265 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left);
266 const bool right_clicked = ImGui::IsMouseClicked(ImGuiMouseButton_Right);
268 if (clicked || double_clicked || right_clicked) {
296 const ImVec2 screen_pos = ImGui::GetIO().MousePos;
305 if (local.x < 0.0f || local.y < 0.0f) {
309 const int column =
static_cast<int>(local.x / tile_display_size);
310 const int row =
static_cast<int>(local.y / tile_display_size);
327 tile_display_size, tile_display_size,
348 return ImVec2(-1, -1);
350 const int tile_display_size =
359 std::string_view input) {
361 if (!ParseTileIdText(input, &tile_id)) {
379 const bool compact = ImGui::GetContentRegionAvail().x < 115.0f;
383 if (ImGui::Button(label)) {
384 ImGui::OpenPopup(
"TileLookup");
387 "button", ImGui::GetItemID());
388 if (ImGui::IsItemHovered()) {
389 ImGui::SetTooltip(
"Jump to a tile ID or filter a range%s",
393 ImGui::SetNextWindowSizeConstraints(ImVec2(300.0f, 0.0f),
394 ImVec2(380.0f, 500.0f));
395 if (ImGui::BeginPopup(
"TileLookup")) {
398 ImGui::CloseCurrentPopup();
409 const float available_width =
410 std::max(ImGui::GetContentRegionAvail().x, 1.0f);
411 const bool compact_layout = available_width < 420.0f;
412 const float jump_input_width =
413 compact_layout ? std::clamp(available_width * 0.28f, 56.0f, 88.0f)
415 const float range_input_width =
417 ? std::clamp((available_width - 110.0f) * 0.5f, 56.0f, 88.0f)
420 constexpr ImGuiInputTextFlags kInputFlags =
421 ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll;
426 ImGui::AlignTextToFramePadding();
427 ImGui::TextUnformatted(tr(
"Go:"));
430 ImGui::SetNextItemWidth(jump_input_width);
443 "input", ImGui::GetItemID());
444 if (ImGui::IsItemHovered()) {
446 tr(
"Enter tile ID and press Enter:\n"
452 ImGui::TextDisabled(tr(
"/ 0x%03X"), max_tile_id);
455 ImGui::TextUnformatted(tr(
"Invalid tile ID (hex or d:decimal)"));
457 ImGui::Text(tr(
"Out of range (max: 0x%03X)"), max_tile_id);
461 if (!compact_layout) {
462 ImGui::SameLine(0, 12.0f);
464 ImGui::AlignTextToFramePadding();
465 ImGui::TextUnformatted(tr(
"Range:"));
468 bool range_changed =
false;
469 ImGui::SetNextItemWidth(range_input_width);
472 range_changed =
true;
475 "input", ImGui::GetItemID());
476 if (ImGui::IsItemHovered()) {
478 tr(
"Min tile ID. Press Enter to apply.\n"
483 ImGui::TextUnformatted(
"-");
485 ImGui::SetNextItemWidth(range_input_width);
488 range_changed =
true;
491 "input", ImGui::GetItemID());
492 if (ImGui::IsItemHovered()) {
494 tr(
"Max tile ID. Press Enter to apply.\n"
498 if (!compact_layout) {
500 ImGui::TextDisabled(tr(
"(hex, d:dec)"));
509 if (has_min && has_max && parsed_min <= parsed_max) {
519 }
else if (!has_min && !has_max) {
523 }
else if (has_min && has_max && parsed_min > parsed_max) {
532 if (!compact_layout) {
535 if (ImGui::SmallButton(tr(
"X##ClearRange"))) {
541 if (ImGui::IsItemHovered()) {
542 ImGui::SetTooltip(tr(
"Clear range filter"));
548 if (!compact_layout) {
549 ImGui::SameLine(0, 8.0f);
551 ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f),
552 tr(
"Min must be <= Max"));
554 if (!compact_layout) {
555 ImGui::SameLine(0, 8.0f);
557 ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f),
561 if (range_count <= 0) {
562 if (!compact_layout) {
563 ImGui::SameLine(0, 8.0f);
565 ImGui::TextDisabled(tr(
"(no tiles in range)"));
Represents a bitmap image optimized for SNES ROM hacking.
TextureHandle texture() const
Modern, robust canvas for drawing and manipulating graphics.
void DrawBitmap(Bitmap &bitmap, int border_offset, float scale)
void DrawOutlineWithColor(int x, int y, int w, int h, ImVec4 color)
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0), std::optional< ImVec2 > viewport_size=std::nullopt)
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
#define ICON_MD_CONTENT_COPY
#define ICON_MD_FILTER_ALT
Graphical User Interface (GUI) components for the application.
bool BeginTileDragSource(int tile_id, int map_id)