8#include <unordered_map>
11#include "absl/status/status.h"
12#include "absl/strings/str_format.h"
33#include "imgui/imgui.h"
34#include "imgui_memory_editor.h"
46 Text(
"Scratch Space Slot:");
47 for (
int i = 0; i < 4; i++) {
52 PushStyleColor(ImGuiCol_Button, ImVec4(0.4f, 0.7f, 0.4f, 1.0f));
53 if (Button(std::to_string(i + 1).c_str(), ImVec2(25, 25))) {
61 if (Button(
"Save Selection")) {
69 if (Button(
"Clear")) {
75 Text(
"Selection Transfer:");
83 HOVER_HINT(
"Copy current overworld selection to this scratch slot");
91 std::vector<int> scratch_tile_ids;
93 int tile_x =
static_cast<int>(tile_pos.x) / 32;
94 int tile_y =
static_cast<int>(tile_pos.y) / 32;
95 if (tile_x >= 0 && tile_x < 32 && tile_y >= 0 && tile_y < 32) {
96 scratch_tile_ids.push_back(
100 if (!scratch_tile_ids.empty() &&
context_) {
103 std::abs(
static_cast<int>((points[1].x - points[0].x) / 32)) + 1;
105 std::abs(
static_cast<int>((points[1].y - points[0].y) / 32)) + 1;
107 std::move(scratch_tile_ids);
114 HOVER_HINT(
"Copy scratch selection to clipboard for pasting in overworld");
118 " Pattern ready! Use Shift+Click to stamp, or paste in overworld");
126 "Select tiles from Tile16 tab or make selections in overworld, then draw "
131 if (!current_slot.scratch_bitmap.is_active()) {
133 int bitmap_width = current_slot.width * 16;
134 int bitmap_height = current_slot.height * 16;
135 std::vector<uint8_t> empty_data(bitmap_width * bitmap_height, 0);
136 current_slot.scratch_bitmap.Create(bitmap_width, bitmap_height, 8,
140 current_slot.scratch_bitmap.SetPalette(
palette_);
152 ImVec2 scratch_content_size(current_slot.width * 16 + 4,
153 current_slot.height * 16 + 4);
155 scratch_content_size);
163 if (current_slot.scratch_bitmap.is_active()) {
178 return absl::OkStatus();
191 int tile_x =
static_cast<int>(mouse_position.x) / grid_size;
192 int tile_y =
static_cast<int>(mouse_position.y) / grid_size;
196 int max_width = current_slot.width > 0 ? current_slot.width : 20;
197 int max_height = current_slot.height > 0 ? current_slot.height : 30;
200 if (tile_x >= 0 && tile_x < max_width && tile_y >= 0 && tile_y < max_height) {
202 if (tile_x < 32 && tile_y < 32) {
210 if (!current_slot.in_use) {
211 current_slot.in_use =
true;
223 int start_tile_x =
static_cast<int>(mouse_position.x) / 32;
224 int start_tile_y =
static_cast<int>(mouse_position.y) / 32;
235 if (tile_ids.empty())
239 int max_width = current_slot.width > 0 ? current_slot.width : 20;
240 int max_height = current_slot.height > 0 ? current_slot.height : 30;
244 for (
int py = 0; py < pattern_height && (start_tile_y + py) < max_height;
246 for (
int px = 0; px < pattern_width && (start_tile_x + px) < max_width;
248 if (idx <
static_cast<int>(tile_ids.size())) {
249 int tile_id = tile_ids[idx];
250 int scratch_x = start_tile_x + px;
251 int scratch_y = start_tile_y + py;
254 if (scratch_x >= 0 && scratch_x < 32 && scratch_y >= 0 &&
256 current_slot.tile_data[scratch_x][scratch_y] = tile_id;
265 current_slot.in_use =
true;
266 if (current_slot.name ==
"Empty") {
268 absl::StrFormat(
"Pattern %dx%d", pattern_width, pattern_height);
273 int tile_id,
int slot) {
282 if (tile_data.empty())
288 const int grid_size = 32;
289 int scratch_bitmap_width = scratch_slot.scratch_bitmap.width();
290 int scratch_bitmap_height = scratch_slot.scratch_bitmap.height();
293 for (
int y = 0; y < 16; ++y) {
294 for (
int x = 0; x < 16; ++x) {
295 int src_index = y * 16 + x;
298 int dst_x = tile_x * grid_size + x + x;
299 int dst_y = tile_y * grid_size + y + y;
302 if (dst_x >= 0 && dst_x < scratch_bitmap_width && dst_y >= 0 &&
303 dst_y < scratch_bitmap_height &&
304 src_index <
static_cast<int>(tile_data.size())) {
307 for (
int py = 0; py < 2 && (dst_y + py) < scratch_bitmap_height; ++py) {
308 for (
int px = 0; px < 2 && (dst_x + px) < scratch_bitmap_width;
310 int dst_index = (dst_y + py) * scratch_bitmap_width + (dst_x + px);
311 scratch_slot.scratch_bitmap.WriteToPixel(dst_index,
312 tile_data[src_index]);
319 scratch_slot.scratch_bitmap.set_modified(
true);
323 scratch_slot.in_use =
true;
329 if (slot < 0 || slot >= 4) {
330 return absl::InvalidArgumentError(
"Invalid scratch slot");
337 if (selected_points.size() >= 2) {
338 const auto start = selected_points[0];
339 const auto end = selected_points[1];
342 int selection_width =
343 std::abs(
static_cast<int>((end.x - start.x) / 16)) + 1;
344 int selection_height =
345 std::abs(
static_cast<int>((end.y - start.y) / 16)) + 1;
348 scratch_spaces_[slot].width = std::max(1, std::min(selection_width, 32));
350 std::max(1, std::min(selection_height, 32));
359 std::vector<uint8_t> empty_data(bitmap_width * bitmap_height, 0);
360 scratch_spaces_[slot].scratch_bitmap.Create(bitmap_width, bitmap_height,
387 if (x < 32 && y < 32) {
406 return absl::OkStatus();
410 if (slot < 0 || slot >= 4) {
411 return absl::InvalidArgumentError(
"Invalid scratch slot");
415 return absl::FailedPreconditionError(
"Scratch slot is empty");
419 util::logf(
"Loading scratch slot %d: %s", slot,
422 return absl::OkStatus();
426 if (slot < 0 || slot >= 4) {
427 return absl::InvalidArgumentError(
"Invalid scratch slot");
436 std::fill(data.begin(), data.end(), 0);
443 return absl::OkStatus();
bool map_blockset_loaded_
absl::Status DrawScratchSpace()
std::array< ScratchSpaceSlot, 4 > scratch_spaces_
absl::Status ClearScratchSpace(int slot)
gfx::Tilemap tile16_blockset_
gui::Canvas ow_map_canvas_
void DrawScratchSpacePattern()
gui::Canvas scratch_canvas_
absl::Status SaveCurrentSelectionToScratch(int slot)
void DrawScratchSpaceEdits()
absl::Status LoadScratchToSelection(int slot)
zelda3::Overworld overworld_
void UpdateScratchBitmapTile(int tile_x, int tile_y, int tile_id, int slot=-1)
int current_scratch_slot_
gfx::SnesPalette palette_
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
RAII timer for automatic timing management.
void DrawBitmap(Bitmap &bitmap, int border_offset, float scale)
auto global_scale() const
auto select_rect_active() const
auto selected_tiles() const
auto drawn_tile_position() const
bool DrawTileSelector(int size, int size_y=0)
void SetContextMenuEnabled(bool enabled)
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0))
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
auto selected_points() const
auto current_area_palette() const
void set_current_world(int world)
int GetTileFromPosition(ImVec2 position) const
void set_current_map(int i)
#define ICON_MD_CONTENT_PASTE
#define RETURN_IF_ERROR(expression)
#define HOVER_HINT(string)
Editors are the view controllers for the application.
std::vector< uint8_t > GetTilemapData(Tilemap &tilemap, int tile_id)
void BeginChildWithScrollbar(const char *str_id)
void logf(const absl::FormatSpec< Args... > &format, Args &&... args)
bool has_overworld_tile16
std::vector< int > overworld_tile16_ids
struct yaze::editor::EditorContext::SharedClipboard shared_clipboard