refactor: Simplify entity dragging logic and enhance interaction handling

- Removed the `HandleEntityDragging` function to streamline entity dragging logic directly within the `OverworldEditor`.
- Implemented centralized drag-and-drop functionality for entities, improving user interaction during editing.
- Updated the `OverworldEntityRenderer` to manage hovered entities more effectively, enhancing the overall editing experience.
- Cleaned up unused code and improved readability across the entity handling components.
This commit is contained in:
scawful
2025-10-10 16:39:31 -04:00
parent 4c3cb2581d
commit 735d9243fd
7 changed files with 157 additions and 252 deletions

View File

@@ -53,54 +53,7 @@ void MoveEntityOnGrid(zelda3::GameEntity *entity, ImVec2 canvas_p0,
entity->set_y(new_y);
}
void HandleEntityDragging(zelda3::GameEntity *entity, ImVec2 canvas_p0,
ImVec2 scrolling, bool &is_dragging_entity,
zelda3::GameEntity *&dragged_entity,
zelda3::GameEntity *&current_entity,
bool free_movement) {
std::string entity_type = "Entity";
if (entity->entity_type_ == zelda3::GameEntity::EntityType::kExit) {
entity_type = "Exit";
} else if (entity->entity_type_ ==
zelda3::GameEntity::EntityType::kEntrance) {
entity_type = "Entrance";
} else if (entity->entity_type_ == zelda3::GameEntity::EntityType::kSprite) {
entity_type = "Sprite";
} else if (entity->entity_type_ == zelda3::GameEntity::EntityType::kItem) {
entity_type = "Item";
}
const auto is_hovering =
IsMouseHoveringOverEntity(*entity, canvas_p0, scrolling);
const auto drag_or_clicked = ImGui::IsMouseDragging(ImGuiMouseButton_Left) ||
ImGui::IsMouseClicked(ImGuiMouseButton_Left);
if (is_hovering && drag_or_clicked && !is_dragging_entity) {
dragged_entity = entity;
is_dragging_entity = true;
} else if (is_hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
current_entity = entity;
ImGui::OpenPopup(absl::StrFormat("%s editor", entity_type.c_str()).c_str());
} else if (is_dragging_entity && dragged_entity == entity &&
ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
MoveEntityOnGrid(dragged_entity, canvas_p0, scrolling, free_movement);
entity->UpdateMapProperties(entity->map_id_);
is_dragging_entity = false;
dragged_entity = nullptr;
} else if (is_dragging_entity && dragged_entity == entity) {
if (ImGui::BeginDragDropSource()) {
ImGui::SetDragDropPayload("ENTITY_PAYLOAD", &entity,
sizeof(zelda3::GameEntity));
Text("Moving %s ID: %s", entity_type.c_str(),
util::HexByte(entity->entity_id_).c_str());
ImGui::EndDragDropSource();
}
MoveEntityOnGrid(dragged_entity, canvas_p0, scrolling, free_movement);
entity->x_ = dragged_entity->x_;
entity->y_ = dragged_entity->y_;
entity->UpdateMapProperties(entity->map_id_);
}
}
bool DrawEntranceInserterPopup() {
bool set_done = false;

View File

@@ -17,11 +17,7 @@ bool IsMouseHoveringOverEntity(const zelda3::GameEntity &entity,
void MoveEntityOnGrid(zelda3::GameEntity *entity, ImVec2 canvas_p0,
ImVec2 scrolling, bool free_movement = false);
void HandleEntityDragging(zelda3::GameEntity *entity, ImVec2 canvas_p0,
ImVec2 scrolling, bool &is_dragging_entity,
zelda3::GameEntity *&dragged_entity,
zelda3::GameEntity *&current_entity,
bool free_movement = false);
bool DrawEntranceInserterPopup();
bool DrawOverworldEntrancePopup(zelda3::OverworldEntrance &entrance);

View File

@@ -16,6 +16,7 @@
#include "app/core/asar_wrapper.h"
#include "app/core/features.h"
#include "app/editor/overworld/map_properties.h"
#include "app/editor/overworld/entity.h"
#include "app/editor/overworld/tile16_editor.h"
#include "app/gfx/arena.h"
#include "app/gfx/bitmap.h"
@@ -342,6 +343,84 @@ absl::Status OverworldEditor::Update() {
ImGui::End();
}
// --- BEGIN CENTRALIZED INTERACTION LOGIC ---
auto* hovered_entity = entity_renderer_->hovered_entity();
// Handle all MOUSE mode interactions here
if (current_mode == EditingMode::MOUSE) {
// --- CONTEXT MENUS & POPOVERS ---
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
if (hovered_entity) {
current_entity_ = hovered_entity;
switch (hovered_entity->entity_type_) {
case zelda3::GameEntity::EntityType::kExit:
current_exit_ = *static_cast<zelda3::OverworldExit*>(hovered_entity);
ImGui::OpenPopup("Exit editor");
break;
case zelda3::GameEntity::EntityType::kEntrance:
current_entrance_ =
*static_cast<zelda3::OverworldEntrance*>(hovered_entity);
ImGui::OpenPopup("Entrance Editor");
break;
case zelda3::GameEntity::EntityType::kItem:
current_item_ = *static_cast<zelda3::OverworldItem*>(hovered_entity);
ImGui::OpenPopup("Item editor");
break;
case zelda3::GameEntity::EntityType::kSprite:
current_sprite_ = *static_cast<zelda3::Sprite*>(hovered_entity);
ImGui::OpenPopup("Sprite editor");
break;
default:
break;
}
}
}
// --- DOUBLE-CLICK ACTIONS ---
if (hovered_entity && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
if (hovered_entity->entity_type_ == zelda3::GameEntity::EntityType::kExit) {
jump_to_tab_ =
static_cast<zelda3::OverworldExit*>(hovered_entity)->room_id_;
} else if (hovered_entity->entity_type_ ==
zelda3::GameEntity::EntityType::kEntrance) {
jump_to_tab_ =
static_cast<zelda3::OverworldEntrance*>(hovered_entity)->entrance_id_;
}
}
}
// --- DRAW POPUPS ---
if (DrawExitEditorPopup(current_exit_)) {
if (current_entity_ &&
current_entity_->entity_type_ == zelda3::GameEntity::EntityType::kExit) {
*static_cast<zelda3::OverworldExit*>(current_entity_) = current_exit_;
rom_->set_dirty(true);
}
}
if (DrawOverworldEntrancePopup(current_entrance_)) {
if (current_entity_ && current_entity_->entity_type_ ==
zelda3::GameEntity::EntityType::kEntrance) {
*static_cast<zelda3::OverworldEntrance*>(current_entity_) =
current_entrance_;
rom_->set_dirty(true);
}
}
if (DrawItemEditorPopup(current_item_)) {
if (current_entity_ &&
current_entity_->entity_type_ == zelda3::GameEntity::EntityType::kItem) {
*static_cast<zelda3::OverworldItem*>(current_entity_) = current_item_;
rom_->set_dirty(true);
}
}
if (DrawSpriteEditorPopup(current_sprite_)) {
if (current_entity_ &&
current_entity_->entity_type_ == zelda3::GameEntity::EntityType::kSprite) {
*static_cast<zelda3::Sprite*>(current_entity_) = current_sprite_;
rom_->set_dirty(true);
}
}
// --- END CENTRALIZED LOGIC ---
return status_;
}
@@ -1260,23 +1339,7 @@ void OverworldEditor::HandleOverworldPan() {
middle_mouse_dragging_ = false;
}
// In MOUSE mode, left-click drag also pans
if (current_mode == EditingMode::MOUSE &&
ImGui::IsMouseDragging(ImGuiMouseButton_Left) && ImGui::IsItemHovered()) {
ImVec2 mouse_delta = ImGui::GetIO().MouseDelta;
ImVec2 current_scroll = ow_map_canvas_.scrolling();
ImVec2 new_scroll = ImVec2(
current_scroll.x + mouse_delta.x,
current_scroll.y + mouse_delta.y
);
// Clamp scroll to boundaries
ImVec2 content_size = CalculateOverworldContentSize(ow_map_canvas_.global_scale());
ImVec2 visible_size = ow_map_canvas_.canvas_size();
new_scroll = ClampScrollPosition(new_scroll, content_size, visible_size);
ow_map_canvas_.set_scrolling(new_scroll);
}
}
void OverworldEditor::HandleOverworldZoom() {
@@ -1380,7 +1443,9 @@ void OverworldEditor::DrawOverworldCanvas() {
// Context menu only in MOUSE mode
if (current_mode == EditingMode::MOUSE) {
ow_map_canvas_.DrawContextMenu();
if (entity_renderer_->hovered_entity() == nullptr) {
ow_map_canvas_.DrawContextMenu();
}
} else if (current_mode == EditingMode::DRAW_TILE) {
// Tile painting mode - handle tile edits and right-click tile picking
HandleMapInteraction();
@@ -1389,9 +1454,6 @@ void OverworldEditor::DrawOverworldCanvas() {
if (overworld_.is_loaded()) {
DrawOverworldMaps();
// Update entity renderer state
entity_renderer_->set_current_map(current_map_);
// Draw all entities using the entity renderer
// Convert entity_edit_mode_ to legacy mode int for entity renderer
int entity_mode_int = static_cast<int>(entity_edit_mode_);
@@ -1402,12 +1464,6 @@ void OverworldEditor::DrawOverworldCanvas() {
entity_renderer_->DrawItems(current_world_, entity_mode_int);
entity_renderer_->DrawSprites(current_world_, game_state_, entity_mode_int);
// Check if entity renderer wants to jump to a tab (e.g., double-clicked entrance/exit)
if (entity_renderer_->jump_to_tab() != -1) {
jump_to_tab_ = entity_renderer_->jump_to_tab();
entity_renderer_->reset_jump_to_tab();
}
// Draw overlay preview if enabled
if (show_overlay_preview_) {
map_properties_system_->DrawOverlayPreviewOnMap(
@@ -1423,6 +1479,49 @@ void OverworldEditor::DrawOverworldCanvas() {
// tracks whether mouse is over the canvas area.
if (ow_map_canvas_.IsMouseHovering())
status_ = CheckForCurrentMap();
// --- BEGIN NEW DRAG/DROP LOGIC ---
if (current_mode == EditingMode::MOUSE) {
auto hovered_entity = entity_renderer_->hovered_entity();
// 1. Initiate drag
if (!is_dragging_entity_ && hovered_entity &&
ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
dragged_entity_ = hovered_entity;
is_dragging_entity_ = true;
if (dragged_entity_->entity_type_ ==
zelda3::GameEntity::EntityType::kExit) {
dragged_entity_free_movement_ = true;
}
}
// 2. Update drag
if (is_dragging_entity_ && dragged_entity_ &&
ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
ImVec2 mouse_delta = ImGui::GetIO().MouseDelta;
float scale = ow_map_canvas_.global_scale();
if (scale > 0.0f) {
dragged_entity_->x_ += mouse_delta.x / scale;
dragged_entity_->y_ += mouse_delta.y / scale;
}
}
// 3. End drag
if (is_dragging_entity_ && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
if (dragged_entity_) {
MoveEntityOnGrid(dragged_entity_, ow_map_canvas_.zero_point(),
ow_map_canvas_.scrolling(),
dragged_entity_free_movement_);
dragged_entity_->UpdateMapProperties(dragged_entity_->map_id_);
rom_->set_dirty(true);
}
is_dragging_entity_ = false;
dragged_entity_ = nullptr;
dragged_entity_free_movement_ = false;
}
}
// --- END NEW DRAG/DROP LOGIC ---
}
ow_map_canvas_.DrawGrid();

View File

@@ -287,6 +287,7 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
bool overworld_canvas_fullscreen_ = false;
bool middle_mouse_dragging_ = false;
bool is_dragging_entity_ = false;
bool dragged_entity_free_movement_ = false;
bool current_map_lock_ = false;
bool show_custom_bg_color_editor_ = false;
bool show_overlay_editor_ = false;

View File

@@ -24,6 +24,7 @@ ImVec4 GetSpriteColor() { return ImVec4{1.0f, 0.0f, 1.0f, 1.0f}; } // So
void OverworldEntityRenderer::DrawEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
int current_world,
int current_mode) {
hovered_entity_ = nullptr;
int i = 0;
for (auto& each : overworld_->entrances()) {
if (each.map_id_ < 0x40 + (current_world * 0x40) &&
@@ -35,59 +36,21 @@ void OverworldEntityRenderer::DrawEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
entrance_color.w = 0.78f; // 200/255 alpha
}
canvas_->DrawRect(each.x_, each.y_, 16, 16, entrance_color);
if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling)) {
hovered_entity_ = &each;
}
std::string str = util::HexByte(each.entrance_id_);
if (current_mode == 1) { // EditingMode::ENTRANCES
HandleEntityDragging(&each, canvas_p0, scrolling, is_dragging_entity_,
dragged_entity_, current_entity_);
if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling) &&
ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
jump_to_tab_ = each.entrance_id_;
}
if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling) &&
ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
current_entrance_id_ = i;
current_entrance_ = each;
}
}
canvas_->DrawText(str, each.x_, each.y_);
}
i++;
}
if (DrawEntranceInserterPopup()) {
// Get the deleted entrance ID and insert it at the mouse position
auto deleted_entrance_id = overworld_->deleted_entrances().back();
overworld_->deleted_entrances().pop_back();
auto& entrance = overworld_->entrances()[deleted_entrance_id];
entrance.map_id_ = current_map_;
entrance.entrance_id_ = deleted_entrance_id;
entrance.x_ = canvas_->hover_mouse_pos().x;
entrance.y_ = canvas_->hover_mouse_pos().y;
entrance.deleted = false;
}
if (current_mode == 1) { // EditingMode::ENTRANCES
const auto is_hovering =
IsMouseHoveringOverEntity(current_entrance_, canvas_p0, scrolling);
if (!is_hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
ImGui::OpenPopup("Entrance Inserter");
} else {
if (DrawOverworldEntrancePopup(
overworld_->entrances()[current_entrance_id_])) {
overworld_->entrances()[current_entrance_id_] = current_entrance_;
}
if (overworld_->entrances()[current_entrance_id_].deleted) {
overworld_->mutable_deleted_entrances()->emplace_back(
current_entrance_id_);
}
}
}
}
void OverworldEntityRenderer::DrawExits(ImVec2 canvas_p0, ImVec2 scrolling,
@@ -98,26 +61,12 @@ void OverworldEntityRenderer::DrawExits(ImVec2 canvas_p0, ImVec2 scrolling,
if (each.map_id_ < 0x40 + (current_world * 0x40) &&
each.map_id_ >= (current_world * 0x40) && !each.deleted_) {
canvas_->DrawRect(each.x_, each.y_, 16, 16, GetExitColor());
if (current_mode == 2) { // EditingMode::EXITS
each.entity_id_ = i;
HandleEntityDragging(&each, canvas_->zero_point(),
canvas_->scrolling(), is_dragging_entity_,
dragged_entity_, current_entity_, true);
if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling) &&
ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
jump_to_tab_ = each.room_id_;
}
if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling) &&
ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
current_exit_id_ = i;
current_exit_ = each;
current_entity_ = &each;
current_entity_->entity_id_ = i;
ImGui::OpenPopup("Exit editor");
}
if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling)) {
hovered_entity_ = &each;
}
each.entity_id_ = i;
std::string str = util::HexByte(i);
canvas_->DrawText(str, each.x_, each.y_);
@@ -125,21 +74,7 @@ void OverworldEntityRenderer::DrawExits(ImVec2 canvas_p0, ImVec2 scrolling,
i++;
}
DrawExitInserterPopup();
if (current_mode == 2) { // EditingMode::EXITS
const auto hovering = IsMouseHoveringOverEntity(
overworld_->mutable_exits()->at(current_exit_id_),
canvas_->zero_point(), canvas_->scrolling());
if (!hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
ImGui::OpenPopup("Exit Inserter");
} else {
if (DrawExitEditorPopup(
overworld_->mutable_exits()->at(current_exit_id_))) {
overworld_->mutable_exits()->at(current_exit_id_) = current_exit_;
}
}
}
}
void OverworldEntityRenderer::DrawItems(int current_world, int current_mode) {
@@ -150,21 +85,13 @@ void OverworldEntityRenderer::DrawItems(int current_world, int current_mode) {
item.room_map_id_ >= (current_world * 0x40) && !item.deleted) {
canvas_->DrawRect(item.x_, item.y_, 16, 16, GetItemColor());
if (current_mode == 3) { // EditingMode::ITEMS
// Check if this item is being clicked and dragged
HandleEntityDragging(&item, canvas_->zero_point(),
canvas_->scrolling(), is_dragging_entity_,
dragged_entity_, current_entity_);
const auto hovering = IsMouseHoveringOverEntity(
item, canvas_->zero_point(), canvas_->scrolling());
if (hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
current_item_id_ = i;
current_item_ = item;
current_entity_ = &item;
}
if (IsMouseHoveringOverEntity(item, canvas_->zero_point(),
canvas_->scrolling())) {
hovered_entity_ = &item;
}
std::string item_name = "";
std::string item_name = "";
if (item.id_ < zelda3::kSecretItemNames.size()) {
item_name = zelda3::kSecretItemNames[item.id_];
} else {
@@ -175,21 +102,7 @@ void OverworldEntityRenderer::DrawItems(int current_world, int current_mode) {
i++;
}
DrawItemInsertPopup();
if (current_mode == 3) { // EditingMode::ITEMS
const auto hovering = IsMouseHoveringOverEntity(
overworld_->mutable_all_items()->at(current_item_id_),
canvas_->zero_point(), canvas_->scrolling());
if (!hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
ImGui::OpenPopup("Item Inserter");
} else {
if (DrawItemEditorPopup(
overworld_->mutable_all_items()->at(current_item_id_))) {
overworld_->mutable_all_items()->at(current_item_id_) = current_item_;
}
}
}
}
void OverworldEntityRenderer::DrawSprites(int current_world, int game_state,
@@ -209,17 +122,12 @@ void OverworldEntityRenderer::DrawSprites(int current_world, int game_state,
int original_y = sprite.y_;
canvas_->DrawRect(sprite_x, sprite_y, 16, 16, GetSpriteColor());
if (current_mode == 4) { // EditingMode::SPRITES
HandleEntityDragging(&sprite, canvas_->zero_point(),
canvas_->scrolling(), is_dragging_entity_,
dragged_entity_, current_entity_);
if (IsMouseHoveringOverEntity(sprite, canvas_->zero_point(),
canvas_->scrolling()) &&
ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
current_sprite_id_ = i;
current_sprite_ = sprite;
}
if (IsMouseHoveringOverEntity(sprite, canvas_->zero_point(),
canvas_->scrolling())) {
hovered_entity_ = &sprite;
}
if (core::FeatureFlags::get().overworld.kDrawOverworldSprites) {
if ((*sprite_previews_)[sprite.id()].is_active()) {
canvas_->DrawBitmap((*sprite_previews_)[sprite.id()], sprite_x,
@@ -237,22 +145,7 @@ void OverworldEntityRenderer::DrawSprites(int current_world, int game_state,
i++;
}
DrawSpriteInserterPopup();
if (current_mode == 4) { // EditingMode::SPRITES
const auto hovering = IsMouseHoveringOverEntity(
overworld_->mutable_sprites(game_state)->at(current_sprite_id_),
canvas_->zero_point(), canvas_->scrolling());
if (!hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
ImGui::OpenPopup("Sprite Inserter");
} else {
if (DrawSpriteEditorPopup(overworld_->mutable_sprites(game_state)
->at(current_sprite_id_))) {
overworld_->mutable_sprites(game_state)->at(current_sprite_id_) =
current_sprite_;
}
}
}
}
} // namespace editor

View File

@@ -5,11 +5,8 @@
#include "app/gfx/bitmap.h"
#include "app/gui/canvas.h"
#include "app/zelda3/common.h"
#include "app/zelda3/overworld/overworld.h"
#include "app/zelda3/overworld/overworld_entrance.h"
#include "app/zelda3/overworld/overworld_exit.h"
#include "app/zelda3/overworld/overworld_item.h"
#include "app/zelda3/sprite/sprite.h"
#include "imgui/imgui.h"
namespace yaze {
@@ -39,48 +36,13 @@ class OverworldEntityRenderer {
void DrawItems(int current_world, int current_mode);
void DrawSprites(int current_world, int game_state, int current_mode);
// State accessors
int current_entrance_id() const { return current_entrance_id_; }
int current_exit_id() const { return current_exit_id_; }
int current_item_id() const { return current_item_id_; }
int current_sprite_id() const { return current_sprite_id_; }
int jump_to_tab() const { return jump_to_tab_; }
zelda3::OverworldEntrance& current_entrance() { return current_entrance_; }
zelda3::OverworldExit& current_exit() { return current_exit_; }
zelda3::OverworldItem& current_item() { return current_item_; }
zelda3::Sprite& current_sprite() { return current_sprite_; }
void set_current_map(int map) { current_map_ = map; }
void set_is_dragging_entity(bool value) { is_dragging_entity_ = value; }
void set_dragged_entity(zelda3::GameEntity* entity) { dragged_entity_ = entity; }
void set_current_entity(zelda3::GameEntity* entity) { current_entity_ = entity; }
void reset_jump_to_tab() { jump_to_tab_ = -1; }
auto hovered_entity() const { return hovered_entity_; }
private:
zelda3::GameEntity* hovered_entity_ = nullptr;
zelda3::Overworld* overworld_;
gui::Canvas* canvas_;
std::vector<gfx::Bitmap>* sprite_previews_;
// Current entity selections
int current_entrance_id_ = 0;
int current_exit_id_ = 0;
int current_item_id_ = 0;
int current_sprite_id_ = 0;
int current_map_ = 0;
int jump_to_tab_ = -1;
// Entity interaction state
bool is_dragging_entity_ = false;
zelda3::GameEntity* dragged_entity_ = nullptr;
zelda3::GameEntity* current_entity_ = nullptr;
// Current entity instances for editing
zelda3::OverworldEntrance current_entrance_;
zelda3::OverworldExit current_exit_;
zelda3::OverworldItem current_item_;
zelda3::Sprite current_sprite_;
};
} // namespace editor

View File

@@ -1000,10 +1000,11 @@ void Canvas::DrawSelectRect(int current_map, int tile_size, float scale) {
// Calculate the rectangle's top-left and bottom-right corners
ImVec2 drag_end_pos = AlignPosToGrid(mouse_pos, scaled_size);
if (ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
auto start = ImVec2(canvas_p0_.x + drag_start_pos.x,
canvas_p0_.y + drag_start_pos.y);
auto end = ImVec2(canvas_p0_.x + drag_end_pos.x + tile_size,
canvas_p0_.y + drag_end_pos.y + tile_size);
// FIX: Origin used to be canvas_p0_, revert if there is regression.
auto start = ImVec2(origin.x + drag_start_pos.x,
origin.y + drag_start_pos.y);
auto end = ImVec2(origin.x + drag_end_pos.x + tile_size,
origin.y + drag_end_pos.y + tile_size);
draw_list_->AddRect(start, end, kWhiteColor);
dragging = true;
}