using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Tilemaps;
namespace UnityEditor.Tilemaps
{
/// This class is in charge of drag'n'drops of Tile assets on scene view
internal class TileDragAndDropManager : ScriptableSingleton
{
private bool m_RegisteredEventHandlers;
private Dictionary m_HoverData;
[SerializeField]
private string m_LastUserTileAssetPath;
[InitializeOnLoadMethod]
static void Initialize()
{
instance.RegisterEventHandlers();
}
void OnEnable()
{
RegisterEventHandlers();
}
void RegisterEventHandlers()
{
if (m_RegisteredEventHandlers)
return;
SceneView.duringSceneGui += DuringSceneGui;
m_RegisteredEventHandlers = true;
}
void OnDisable()
{
SceneView.duringSceneGui -= DuringSceneGui;
m_RegisteredEventHandlers = false;
}
private void DuringSceneGui(SceneView sceneView)
{
Event evt = Event.current;
if (evt.type != EventType.DragUpdated && evt.type != EventType.DragPerform && evt.type != EventType.DragExited && evt.type != EventType.Repaint)
return;
Grid activeGrid = GetActiveGrid();
if (activeGrid == null || DragAndDrop.objectReferences.Length == 0)
return;
Vector3 localMouse = GridEditorUtility.ScreenToLocal(activeGrid.transform, evt.mousePosition);
Vector3Int mouseGridPosition = activeGrid.LocalToCell(localMouse);
switch (evt.type)
{
//TODO: Cache this
case EventType.DragUpdated:
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
List tiles = TileDragAndDrop.GetValidTiles(DragAndDrop.objectReferences);
instance.m_HoverData = TileDragAndDrop.CreateHoverData(null, null, tiles, null, activeGrid.cellLayout);
if (instance.m_HoverData.Count > 0)
{
Event.current.Use();
GUI.changed = true;
}
break;
case EventType.DragPerform:
if (instance.m_HoverData.Count > 0)
{
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
var tileSheet = TileDragAndDrop.ConvertToTileSheet(instance.m_HoverData);
Tilemap tilemap = GetOrCreateActiveTilemap();
tilemap.ClearAllEditorPreviewTiles();
int i = 0;
foreach (KeyValuePair item in instance.m_HoverData)
{
Vector3Int position = new Vector3Int(mouseGridPosition.x + item.Key.x, mouseGridPosition.y + item.Key.y, 0);
tilemap.SetTile(position, tileSheet[i++]);
tilemap.SetTransformMatrix(position, Matrix4x4.TRS(
item.Value.hasOffset ? item.Value.positionOffset - tilemap.tileAnchor : Vector3.zero
, Quaternion.identity
, Vector3.one));
}
instance.m_HoverData = null;
GUI.changed = true;
Event.current.Use();
}
break;
case EventType.Repaint:
if (instance.m_HoverData != null)
{
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
var map = Selection.activeGameObject.GetComponentInParent();
var hasMap = map != null;
if (hasMap)
{
map.ClearAllEditorPreviewTiles();
foreach (KeyValuePair item in instance.m_HoverData)
{
var gridPos = mouseGridPosition + new Vector3Int(item.Key.x, item.Key.y, 0);
if (item.Value.hoverObject is TileBase tile)
{
map.SetEditorPreviewTile(gridPos, tile);
}
}
}
}
break;
}
if (instance.m_HoverData != null && (
Event.current.type == EventType.DragExited ||
Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape))
{
if (instance.m_HoverData.Count > 0)
{
Tilemap map = Selection.activeGameObject.GetComponentInParent();
if (map != null)
map.ClearAllEditorPreviewTiles();
Event.current.Use();
}
instance.m_HoverData = null;
}
}
internal static string GetDefaultTileAssetDirectoryPath()
{
var path = instance.m_LastUserTileAssetPath;
if (String.IsNullOrEmpty(path))
{
path = ProjectBrowser.s_LastInteractedProjectBrowser != null
? ProjectBrowser.s_LastInteractedProjectBrowser.GetActiveFolderPath()
: "Assets";
}
return path;
}
internal static void SetUserTileAssetDirectoryPath(string path)
{
var directoryPath = String.Empty;
if (!String.IsNullOrEmpty(path))
{
// UUM-29240: UnityGetDirectoryName clips off last directory if path is not a file path
if (String.IsNullOrEmpty(FileUtil.GetPathExtension(path))
&& !path.EndsWith("/") // MacOS
&& !File.Exists(path))
{
path = FileUtil.CombinePaths(path, "");
}
directoryPath = FileUtil.UnityGetDirectoryName(path);
}
instance.m_LastUserTileAssetPath = directoryPath;
}
static Tilemap GetOrCreateActiveTilemap()
{
if (Selection.activeGameObject != null)
{
Tilemap tilemap = Selection.activeGameObject.GetComponentInParent();
if (tilemap == null)
{
Grid grid = Selection.activeGameObject.GetComponentInParent();
tilemap = CreateNewTilemap(grid);
}
return tilemap;
}
return null;
}
static Tilemap CreateNewTilemap(Grid grid)
{
GameObject go = new GameObject("Tilemap");
go.transform.SetParent(grid.gameObject.transform);
Tilemap map = go.AddComponent();
go.AddComponent();
return map;
}
static Grid GetActiveGrid()
{
if (Selection.activeGameObject != null)
{
return Selection.activeGameObject.GetComponentInParent();
}
return null;
}
}
}