using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.UIElements.Experimental;
namespace UnityEditor.Tilemaps
{
///
/// Popup Field for selecting the Active Target for Grid Painting.
///
[UxmlElement]
public sealed partial class TilePaletteActiveTargetsPopup : PopupField
{
private static string k_NullGameObjectName = GridPaintTargetsDropdown.k_CreateNewPaintTargetName;
private static string k_LabelTooltip =
L10n.Tr("Specifies the currently active Tilemap used for painting in the Scene View.");
private static string k_WarningTooltip =
L10n.Tr("Editing Tilemaps in Prefabs will have better performance if edited in Prefab Mode.");
///
/// Factory for TilePaletteActiveTargetsPopup.
///
[Obsolete("TilePaletteActiveTargetsPopupFactory is deprecated and will be removed. Use UxmlElementAttribute instead.", false)]
public class TilePaletteActiveTargetsPopupFactory : UxmlFactory {}
///
/// UxmlTraits for TilePaletteActiveTargetsPopup.
///
[Obsolete("TilePaletteActiveTargetsPopupUxmlTraits is deprecated and will be removed. Use UxmlElementAttribute instead.", false)]
public class TilePaletteActiveTargetsPopupUxmlTraits : UxmlTraits {}
///
/// USS class name of elements of this type.
///
private new static readonly string ussClassName = "unity-tilepalette-activetargets-field";
///
/// USS class name of labels in elements of this type.
///
private new static readonly string labelUssClassName = ussClassName + "__label";
///
/// USS class name of input elements in elements of this type.
///
private new static readonly string inputUssClassName = ussClassName + "__input";
///
/// USS class name of warning elements in elements of this type.
///
private static readonly string warningUssClassName = ussClassName + "__warning";
///
/// USS class name of input elements in elements of this type when create target hint is shown.
///
private static readonly string createHintUssClassName = ussClassName + "__create";
private readonly VisualElement m_WarningIconElement;
private static List s_InvalidTargetsList = new List();
private bool needCreate
{
get => GridPaintingState.scenePaintTarget == null
&& (GridPaintingState.validTargets == null
|| GridPaintingState.validTargets.Length == 0);
}
private ValueAnimation currentAnim;
///
/// Initializes and returns an instance of TilePaletteActiveTargetsPopup.
///
public TilePaletteActiveTargetsPopup() : this(null) {}
///
/// Initializes and returns an instance of TilePaletteActiveTargetsPopup.
///
/// Label name for the Popup
public TilePaletteActiveTargetsPopup(string label)
: base(label
, GridPaintingState.validTargets != null ? GridPaintingState.validTargets.ToList() : s_InvalidTargetsList
, GetActiveTargetIndex())
{
AddToClassList(ussClassName);
labelElement.AddToClassList(labelUssClassName);
visualInput.AddToClassList(inputUssClassName);
TilePaletteOverlayUtility.SetStyleSheet(this);
labelElement.tooltip = k_LabelTooltip;
m_WarningIconElement = new VisualElement();
m_WarningIconElement.name = "Warning Icon";
m_WarningIconElement.AddToClassList(warningUssClassName);
m_WarningIconElement.tooltip = k_WarningTooltip;
contentContainer.Add(m_WarningIconElement);
RegisterCallback(OnAttachedToPanel);
RegisterCallback(OnDetachFromPanel);
m_FormatSelectedValueCallback += FormatSelectedValueCallback;
createMenuCallback += CreateMenuCallback;
UpdateTargets();
SetValueWithoutNotify(GridPaintingState.scenePaintTarget);
}
private void OnAttachedToPanel(AttachToPanelEvent evt)
{
GridPaintingState.scenePaintTargetChanged += OnScenePaintTargetChanged;
GridPaintingState.validTargetsChanged += UpdateTargets;
GridPaintingState.scenePaintTargetEdited += OnScenePaintTargetEdited;
}
private void OnDetachFromPanel(DetachFromPanelEvent evt)
{
GridPaintingState.scenePaintTargetChanged -= OnScenePaintTargetChanged;
GridPaintingState.validTargetsChanged -= UpdateTargets;
GridPaintingState.scenePaintTargetEdited -= OnScenePaintTargetEdited;
}
private string FormatSelectedValueCallback(GameObject go)
{
if (go != null)
return go.name;
if (GridPaintingState.scenePaintTarget != null)
return GridPaintingState.scenePaintTarget.name;
return k_NullGameObjectName;
}
private IGenericMenu CreateMenuCallback()
{
return new TilePaletteActiveTargetsDropdownMenu();
}
private static int GetActiveTargetIndex()
{
if (GridPaintingState.validTargets == null)
return -1;
return Array.IndexOf(GridPaintingState.validTargets, GridPaintingState.scenePaintTarget);
}
private void OnScenePaintTargetChanged(GameObject _)
{
UpdateActiveTarget();
}
private void UpdateChoices()
{
choices.Clear();
if (GridPaintingState.validTargets == null)
return;
foreach (var target in GridPaintingState.validTargets)
{
choices.Add(target);
}
SetValueWithoutNotify(GridPaintingState.scenePaintTarget);
}
private void UpdateActiveTarget()
{
var newIndex = GetActiveTargetIndex();
if (newIndex != -1 && choices.Count < newIndex)
{
UpdateChoices();
newIndex = GetActiveTargetIndex();
}
index = newIndex;
var needWarning = TilePalettePrefabUtility.IsObjectPrefabInstance(GridPaintingState.scenePaintTarget);
m_WarningIconElement.visible = needWarning;
m_WarningIconElement.style.position = needWarning ? Position.Relative : Position.Absolute;
}
private void OnScenePaintTargetEdited(GameObject obj)
{
if (!needCreate
|| obj != null)
return;
if (currentAnim?.durationMs > 4000)
{
currentAnim.KeepAlive();
ClearAnim(currentAnim);
}
var target = parent ?? this;
var anim = target.experimental.animation.Start(
new StyleValues()
{
borderColor = Color.yellow,
},
new StyleValues()
{
borderColor = Color.clear,
}, 8000).Ease(Easing.OutQuad);
anim.OnCompleted(() => ClearAnim(anim));
currentAnim = anim;
}
void ClearAnim(IValueAnimation anim)
{
if (currentAnim != null && currentAnim == anim)
{
currentAnim = null;
anim.Stop();
anim.Recycle();
}
}
private void UpdateTargets()
{
UpdateChoices();
UpdateActiveTarget();
}
}
///
/// Visual Element displaying the Icon for Active Target for Grid Painting.
///
internal class TilePaletteActiveTargetsPopupIcon : VisualElement
{
///
/// USS class name of elements of this type.
///
private static readonly string ussClassName = "unity-tilepalette-activetargets-icon";
private readonly string kTooltip = L10n.Tr("Active Target");
private readonly string kIconPath = "Packages/com.unity.2d.tilemap/Editor/Icons/Tilemap.ActiveTargetLayers.png";
///
/// Constructor for TilePaletteActiveTargetsPopupIcon
///
public TilePaletteActiveTargetsPopupIcon()
{
AddToClassList(ussClassName);
TilePaletteOverlayUtility.SetStyleSheet(this);
tooltip = kTooltip;
style.backgroundImage = EditorGUIUtility.LoadIcon(kIconPath);
}
}
}