using System;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor.EditorTools;
namespace UnityEditor.Tilemaps
{
///
/// A Visual Element which handles and displays a Tile Palette Clipboard.
/// A Tile Palette Clipboard shows the Active Palette for Grid Painting and allows
/// users to use the Active Brush to assign and pick items for painting.
///
[UxmlElement]
public partial class TilePaletteClipboardElement : VisualElement
{
///
/// Factory for TilePaletteClipboardElement.
///
[Obsolete("TilePaletteClipboardElementFactory is deprecated and will be removed. Use UxmlElementAttribute instead.", false)]
public class TilePaletteClipboardElementFactory : UxmlFactory {}
///
/// UxmlTraits for TilePaletteClipboardElement.
///
[Obsolete("TilePaletteClipboardElementUxmlTraits is deprecated and will be removed. Use UxmlElementAttribute instead.", false)]
public class TilePaletteClipboardElementUxmlTraits : UxmlTraits {}
internal static readonly string overlayClassName = "unity-tilepalette-clipboard-element-overlay";
private static readonly string ussClassName = "unity-tilepalette-clipboard-element";
private static readonly string k_Name = L10n.Tr("Tile Palette Clipboard Element");
private GridPaintPaletteClipboard m_TilePaletteClipboard;
private EditorWindow m_Window;
///
/// Callback when the active Brush does a Pick on the Clipboard.
///
public event Action onBrushPicked;
///
/// Whether the clipboard is unlocked for editing.
///
public bool clipboardUnlocked
{
get => m_TilePaletteClipboard.unlocked;
set => m_TilePaletteClipboard.unlocked = value;
}
///
/// The last active grid position on the clipboard.
///
public Vector3Int clipboardMouseGridPosition => new Vector3Int(m_TilePaletteClipboard.mouseGridPosition.x, m_TilePaletteClipboard.mouseGridPosition.y, m_TilePaletteClipboard.zPosition);
///
/// Callback when the clipboard unlock status has changed
///
public event Action clipboardUnlockedChanged;
private bool clipboardIsNotActive => m_TilePaletteClipboard == null || !m_ClipboardImageElement.visible;
internal GridPaintPaletteClipboard clipboardView => m_TilePaletteClipboard;
private TilePaletteClipboardFirstUserElement m_FirstUserElement;
private TilePaletteClipboardErrorElement m_ErrorElement;
private IMGUIContainer m_GizmoHandlerElement;
private Image m_ClipboardImageElement;
///
/// Initializes and returns an instance of TilePaletteClipboardElement.
///
public TilePaletteClipboardElement()
{
AddToClassList(ussClassName);
name = k_Name;
TilePaletteOverlayUtility.SetStyleSheet(this);
RegisterCallback(OnAttachedToPanel);
RegisterCallback(OnDetachFromPanel);
m_GizmoHandlerElement = new IMGUIContainer(HandleIMGUI);
m_GizmoHandlerElement.style.flexGrow = 1.0f;
m_ClipboardImageElement = new Image();
m_ClipboardImageElement.style.backgroundColor = GridPaintPaletteClipboard.tilePaletteBackgroundColor.Color;
m_ClipboardImageElement.style.flexGrow = 1.0f;
m_ClipboardImageElement.focusable = true;
m_ClipboardImageElement.Add(m_GizmoHandlerElement);
Add(m_ClipboardImageElement);
m_ErrorElement = new TilePaletteClipboardErrorElement();
m_ErrorElement.style.display = DisplayStyle.None;
m_ErrorElement.style.visibility = Visibility.Hidden;
m_ErrorElement.SetEmptyPaletteText();
Add(m_ErrorElement);
m_FirstUserElement = new TilePaletteClipboardFirstUserElement();
m_FirstUserElement.style.display = DisplayStyle.None;
m_FirstUserElement.style.visibility = Visibility.Hidden;
Add(m_FirstUserElement);
}
private void UnlockChanged(bool unlocked)
{
clipboardUnlockedChanged?.Invoke(unlocked);
CheckPaletteState();
}
private void OnAttachedToPanel(AttachToPanelEvent evt)
{
if (EditorApplication.isPlayingOrWillChangePlaymode && !EditorApplication.isPlaying)
{
// Delay AttachToPanel if Editor is entering playmode
EditorApplication.delayCall += AttachToPanel;
}
else
{
AttachToPanel();
}
}
private void AttachToPanel()
{
if (m_TilePaletteClipboard == null)
{
m_TilePaletteClipboard = ScriptableObject.CreateInstance();
m_TilePaletteClipboard.hideFlags = HideFlags.HideAndDontSave;
m_TilePaletteClipboard.unlockedChanged += UnlockChanged;
m_TilePaletteClipboard.unlocked = false;
m_TilePaletteClipboard.attachedVisualElement = this;
var guiRect = new Rect(0, 0, layout.width, layout.height);
m_TilePaletteClipboard.guiRect = guiRect;
CheckPaletteState(m_TilePaletteClipboard.paletteInstance);
}
RegisterCallback(OnGeometryChangedEvent);
RegisterCallback(OnValidateCommandEvent);
RegisterCallback(OnExecuteCommandEvent);
RegisterCallback(OnGeometryChangedEvent);
RegisterCallback(OnWheelEvent);
RegisterCallback(OnPointerDownEvent);
RegisterCallback(OnPointerMoveEvent);
RegisterCallback(OnPointerUpEvent);
RegisterCallback(OnPointerEnterEvent);
RegisterCallback(OnPointerLeaveEvent);
RegisterCallback(OnKeyDownEvent);
RegisterCallback(OnKeyUpEvent);
RegisterCallback(OnDragEnterEvent);
RegisterCallback(OnDragUpdatedEvent);
RegisterCallback(OnDragPerformEvent);
RegisterCallback(OnDragLeaveEvent);
RegisterCallback(OnDragExitedEvent);
generateVisualContent += GenerateVisualContent;
m_FirstUserElement.firstUserPaletteType = m_TilePaletteClipboard.firstUserPaletteType;
m_FirstUserElement.onFirstUserPaletteTypeChanged += OnFirstUserPaletteTypeChanged;
ToolManager.activeToolChanged += ActiveToolChanged;
GridPaintingState.beforePaletteChanged += BeforePaletteChanged;
GridPaintingState.paletteChanged += PaletteChanged;
GridPaintingState.palettesChanged += CheckPaletteState;
}
private void GenerateVisualContent(MeshGenerationContext obj)
{
if (m_ClipboardImageElement.visible)
{
var texture = m_TilePaletteClipboard.RenderTexture();
EditorApplication.delayCall += () =>
{
if (m_TilePaletteClipboard == null)
return;
m_ClipboardImageElement.style.backgroundColor = m_TilePaletteClipboard.backgroundColor;
m_ClipboardImageElement.image = texture;
};
}
}
private void OnDetachFromPanel(DetachFromPanelEvent evt)
{
UnregisterCallback(OnGeometryChangedEvent);
UnregisterCallback(OnValidateCommandEvent);
UnregisterCallback(OnExecuteCommandEvent);
UnregisterCallback(OnGeometryChangedEvent);
UnregisterCallback(OnWheelEvent);
UnregisterCallback(OnPointerDownEvent);
UnregisterCallback(OnPointerMoveEvent);
UnregisterCallback(OnPointerUpEvent);
UnregisterCallback(OnPointerEnterEvent);
UnregisterCallback(OnPointerLeaveEvent);
UnregisterCallback(OnKeyDownEvent);
UnregisterCallback(OnKeyUpEvent);
UnregisterCallback(OnDragEnterEvent);
UnregisterCallback(OnDragUpdatedEvent);
UnregisterCallback(OnDragPerformEvent);
UnregisterCallback(OnDragExitedEvent);
UnregisterCallback(OnDragLeaveEvent);
generateVisualContent -= GenerateVisualContent;
m_FirstUserElement.onFirstUserPaletteTypeChanged -= OnFirstUserPaletteTypeChanged;
if (m_TilePaletteClipboard != null)
m_TilePaletteClipboard.unlockedChanged -= UnlockChanged;
ToolManager.activeToolChanged -= ActiveToolChanged;
GridPaintingState.beforePaletteChanged -= BeforePaletteChanged;
GridPaintingState.paletteChanged -= PaletteChanged;
GridPaintingState.palettesChanged -= CheckPaletteState;
Cleanup();
}
private void OnFirstUserPaletteTypeChanged(GridPaletteUtility.GridPaletteType paletteType)
{
if (m_TilePaletteClipboard != null)
m_TilePaletteClipboard.firstUserPaletteType = paletteType;
}
private void OnGeometryChangedEvent(GeometryChangedEvent evt)
{
if (m_TilePaletteClipboard == null)
return;
var guiRect = new Rect(0, 0, layout.width, layout.height);
m_TilePaletteClipboard.guiRect = guiRect;
}
private void ActiveToolChanged()
{
CheckPaletteState();
}
private void HandleIMGUI()
{
if (clipboardIsNotActive)
return;
var texture = m_TilePaletteClipboard.HandleIMGUI();
if (texture != null)
{
m_ClipboardImageElement.style.backgroundColor = m_TilePaletteClipboard.backgroundColor;
m_ClipboardImageElement.image = texture;
}
}
private void HandleRepaint()
{
MarkDirtyRepaint();
m_ClipboardImageElement.MarkDirtyRepaint();
}
private void OnExecuteCommandEvent(ExecuteCommandEvent evt)
{
if (clipboardIsNotActive)
return;
m_TilePaletteClipboard.HandleExecuteCommandEvent(evt);
}
private void OnValidateCommandEvent(ValidateCommandEvent evt)
{
if (clipboardIsNotActive)
return;
m_TilePaletteClipboard.HandleValidateCommandEvent(evt);
}
private void OnWheelEvent(WheelEvent evt)
{
if (clipboardIsNotActive)
return;
m_TilePaletteClipboard.HandleWheelEvent(evt.delta, evt.mousePosition, evt.shiftKey);
evt.StopPropagation();
HandleRepaint();
}
private void OnPointerDownEvent(PointerDownEvent evt)
{
if (clipboardIsNotActive)
return;
m_TilePaletteClipboard.HandlePointerDownEvent(evt
, evt.button
, evt.altKey
, evt.ctrlKey
, evt.localPosition);
HandleRepaint();
}
private void OnPointerMoveEvent(PointerMoveEvent evt)
{
if (clipboardIsNotActive)
return;
m_TilePaletteClipboard.HandlePointerMoveEvent(evt
, evt.button
, evt.altKey
, evt.localPosition
, evt.deltaPosition);
HandleRepaint();
}
private void OnPointerUpEvent(PointerUpEvent evt)
{
if (clipboardIsNotActive)
return;
if (onBrushPicked != null && m_TilePaletteClipboard != null)
m_TilePaletteClipboard.onBrushPicked += onBrushPicked;
m_TilePaletteClipboard.HandlePointerUpEvent(evt);
if (onBrushPicked != null && m_TilePaletteClipboard != null)
m_TilePaletteClipboard.onBrushPicked -= onBrushPicked;
HandleRepaint();
}
private void OnPointerEnterEvent(PointerEnterEvent evt)
{
if (m_TilePaletteClipboard == null)
return;
if (ClassListContains(overlayClassName))
{
m_ClipboardImageElement.Focus();
}
m_TilePaletteClipboard.HandlePointerEnterEvent(evt);
HandleRepaint();
}
private void OnPointerLeaveEvent(PointerLeaveEvent evt)
{
if (m_TilePaletteClipboard == null)
return;
m_TilePaletteClipboard.HandlePointerLeaveEvent(evt);
HandleRepaint();
}
private void OnKeyDownEvent(KeyDownEvent evt)
{
if (clipboardIsNotActive)
return;
m_TilePaletteClipboard.HandleKeyDownEvent(evt);
HandleRepaint();
}
private void OnKeyUpEvent(KeyUpEvent evt)
{
if (clipboardIsNotActive)
return;
m_TilePaletteClipboard.HandleKeyUpEvent();
HandleRepaint();
}
private void OnDragEnterEvent(DragEnterEvent evt)
{
if (m_TilePaletteClipboard == null)
return;
m_TilePaletteClipboard.HandleDragEnterEvent(evt);
var texture = m_TilePaletteClipboard.RenderTexture();
m_ClipboardImageElement.image = texture;
CheckPaletteState(m_TilePaletteClipboard.paletteInstance);
HandleRepaint();
}
private void OnDragUpdatedEvent(DragUpdatedEvent evt)
{
if (clipboardIsNotActive)
return;
m_TilePaletteClipboard.HandleDragUpdatedEvent(evt);
HandleRepaint();
}
private void OnDragPerformEvent(DragPerformEvent evt)
{
if (clipboardIsNotActive)
return;
m_TilePaletteClipboard.HandleDragPerformEvent(evt);
CheckPaletteState(m_TilePaletteClipboard.paletteInstance);
HandleRepaint();
}
private void OnDragLeaveEvent(DragLeaveEvent evt)
{
if (clipboardIsNotActive)
return;
m_TilePaletteClipboard.HandleDragLeaveEvent(evt);
CheckPaletteState(m_TilePaletteClipboard.paletteInstance);
HandleRepaint();
}
private void OnDragExitedEvent(DragExitedEvent evt)
{
if (clipboardIsNotActive)
return;
m_TilePaletteClipboard.HandleDragExitedEvent(evt);
HandleRepaint();
}
///
/// Handles cleanup for the Tile Palette Clipboard.
///
private void Cleanup()
{
UnityEngine.Object.DestroyImmediate(m_TilePaletteClipboard);
m_TilePaletteClipboard = null;
}
private void BeforePaletteChanged()
{
if (m_TilePaletteClipboard == null)
return;
m_TilePaletteClipboard.OnBeforePaletteSelectionChanged();
}
private void PaletteChanged(GameObject palette)
{
if (m_TilePaletteClipboard == null)
return;
m_TilePaletteClipboard.OnAfterPaletteSelectionChanged();
CheckPaletteState(palette);
}
internal void CheckPaletteState()
{
CheckPaletteState(GridPaintingState.palette);
}
private void CheckPaletteState(GameObject palette)
{
if (palette == null && GridPaintingState.palettes.Count == 0)
{
m_ClipboardImageElement.style.display = DisplayStyle.None;
m_ClipboardImageElement.style.visibility = Visibility.Hidden;
m_ErrorElement.style.display = DisplayStyle.None;
m_ErrorElement.style.visibility = Visibility.Hidden;
m_ErrorElement.ClearText();
m_FirstUserElement.style.display = DisplayStyle.Flex;
m_FirstUserElement.style.visibility = Visibility.Visible;
}
else if (palette == null && GridPaintingState.palettes.Count > 0)
{
m_ClipboardImageElement.style.display = DisplayStyle.None;
m_ClipboardImageElement.style.visibility = Visibility.Hidden;
m_FirstUserElement.style.display = DisplayStyle.None;
m_FirstUserElement.style.visibility = Visibility.Hidden;
m_ErrorElement.style.display = DisplayStyle.Flex;
m_ErrorElement.style.visibility = Visibility.Visible;
m_ErrorElement.SetInvalidPaletteText();
}
else if (m_TilePaletteClipboard.activeDragAndDrop && m_TilePaletteClipboard.invalidDragAndDrop)
{
m_ClipboardImageElement.style.display = DisplayStyle.None;
m_ClipboardImageElement.style.visibility = Visibility.Hidden;
m_FirstUserElement.style.display = DisplayStyle.None;
m_FirstUserElement.style.visibility = Visibility.Hidden;
m_ErrorElement.style.display = DisplayStyle.Flex;
m_ErrorElement.style.visibility = Visibility.Visible;
m_ErrorElement.SetInvalidDragAndDropText();
}
else if (palette.GetComponent() == null)
{
m_ClipboardImageElement.style.display = DisplayStyle.None;
m_ClipboardImageElement.style.visibility = Visibility.Hidden;
m_FirstUserElement.style.display = DisplayStyle.None;
m_FirstUserElement.style.visibility = Visibility.Hidden;
m_ErrorElement.style.display = DisplayStyle.Flex;
m_ErrorElement.style.visibility = Visibility.Visible;
m_ErrorElement.SetInvalidGridText();
}
else if (m_TilePaletteClipboard.showNewEmptyClipboardInfo)
{
m_ClipboardImageElement.style.display = DisplayStyle.None;
m_ClipboardImageElement.style.visibility = Visibility.Hidden;
m_FirstUserElement.style.display = DisplayStyle.None;
m_FirstUserElement.style.visibility = Visibility.Hidden;
m_ErrorElement.style.display = DisplayStyle.Flex;
m_ErrorElement.style.visibility = Visibility.Visible;
m_ErrorElement.SetEmptyPaletteText();
}
else
{
m_ErrorElement.style.display = DisplayStyle.None;
m_ErrorElement.style.visibility = Visibility.Hidden;
m_ErrorElement.ClearText();
m_FirstUserElement.style.display = DisplayStyle.None;
m_FirstUserElement.style.visibility = Visibility.Hidden;
m_ClipboardImageElement.style.display = DisplayStyle.Flex;
m_ClipboardImageElement.style.visibility = Visibility.Visible;
}
HandleRepaint();
}
}
}