Files
MMORPG/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/ActionMapsView.cs
cooney ce83f21c93 UI 자동화를 위해 바인딩 기능 구현
- 유니티 에셋 인증 오류로 meta 재생성
2026-01-25 01:31:34 +09:00

274 lines
11 KiB
C#

#if UNITY_EDITOR
using CmdEvents = UnityEngine.InputSystem.Editor.InputActionsEditorConstants.CommandEvents;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.UIElements;
namespace UnityEngine.InputSystem.Editor
{
/// <summary>
/// A list view to display the action maps of the currently opened input actions asset.
/// </summary>
internal class ActionMapsView : ViewBase<ActionMapsView.ViewState>
{
public ActionMapsView(VisualElement root, StateContainer stateContainer)
: base(root, stateContainer)
{
m_ListView = root.Q<ListView>("action-maps-list-view");
m_ListView.selectionType = UIElements.SelectionType.Single;
m_ListView.reorderable = true;
m_ListViewSelectionChangeFilter = new CollectionViewSelectionChangeFilter(m_ListView);
m_ListViewSelectionChangeFilter.selectedIndicesChanged += (selectedIndices) =>
{
Dispatch(Commands.SelectActionMap(((ActionMapData)m_ListView.selectedItem).mapName));
};
m_ListView.bindItem = (element, i) =>
{
var treeViewItem = (InputActionMapsTreeViewItem)element;
var mapData = (ActionMapData)m_ListView.itemsSource[i];
treeViewItem.label.text = mapData.mapName;
treeViewItem.EditTextFinishedCallback = newName => ChangeActionMapName(i, newName);
treeViewItem.EditTextFinished += treeViewItem.EditTextFinishedCallback;
treeViewItem.userData = i;
element.SetEnabled(!mapData.isDisabled);
treeViewItem.isDisabledActionMap = mapData.isDisabled;
ContextMenu.GetContextMenuForActionMapItem(this, treeViewItem, i);
};
m_ListView.makeItem = () => new InputActionMapsTreeViewItem();
m_ListView.unbindItem = (element, i) =>
{
var treeViewElement = (InputActionMapsTreeViewItem)element;
treeViewElement.Reset();
treeViewElement.EditTextFinished -= treeViewElement.EditTextFinishedCallback;
};
m_ListView.itemsChosen += objects =>
{
var item = m_ListView.GetRootElementForIndex(m_ListView.selectedIndex).Q<InputActionMapsTreeViewItem>();
item.FocusOnRenameTextField();
};
m_ListView.RegisterCallback<ExecuteCommandEvent>(OnExecuteCommand);
m_ListView.RegisterCallback<ValidateCommandEvent>(OnValidateCommand);
m_ListView.RegisterCallback<PointerDownEvent>(OnPointerDown, TrickleDown.TrickleDown);
// ISXB-748 - Scrolling the view causes a visual glitch with the rename TextField. As a work-around we
// need to cancel the rename operation in this scenario.
m_ListView.RegisterCallback<WheelEvent>(e => InputActionMapsTreeViewItem.CancelRename(), TrickleDown.TrickleDown);
var treeView = root.Q<TreeView>("actions-tree-view");
m_ListView.AddManipulator(new DropManipulator(OnDroppedHandler, treeView));
m_ListView.itemIndexChanged += OnReorder;
CreateSelector(Selectors.GetActionMapNames, Selectors.GetSelectedActionMap, (actionMapNames, actionMap, state) => new ViewState(actionMap, actionMapNames, state.GetDisabledActionMaps(actionMapNames.ToList())));
m_AddActionMapButton = root.Q<Button>("add-new-action-map-button");
m_AddActionMapButton.clicked += AddActionMap;
ContextMenu.GetContextMenuForActionMapsEmptySpace(this, root.Q<VisualElement>("rclick-area-to-add-new-action-map"));
}
void OnDroppedHandler(int mapIndex)
{
Dispatch(Commands.PasteActionIntoActionMap(mapIndex));
}
void OnReorder(int oldIndex, int newIndex)
{
Dispatch(Commands.ReorderActionMap(oldIndex, newIndex));
}
public override void RedrawUI(ViewState viewState)
{
m_ListView.itemsSource = viewState.actionMapData?.ToList() ?? new List<ActionMapData>();
if (viewState.selectedActionMap.HasValue)
{
var actionMapData = viewState.actionMapData?.Find(map => map.mapName.Equals(viewState.selectedActionMap.Value.name));
if (actionMapData.HasValue)
m_ListView.SetSelection(viewState.actionMapData.IndexOf(actionMapData.Value));
}
// UI toolkit doesn't behave the same on 6000.0 way when refreshing items
// On previous versions, we need to call Rebuild() to refresh the items since refreshItems() is less predicatable
#if UNITY_6000_0_OR_NEWER
m_ListView.RefreshItems();
#else
m_ListView.Rebuild();
#endif
RenameNewActionMaps();
}
public override void DestroyView()
{
m_AddActionMapButton.clicked -= AddActionMap;
}
private void RenameNewActionMaps()
{
if (!m_EnterRenamingMode)
return;
m_ListView.ScrollToItem(m_ListView.selectedIndex);
var element = m_ListView.GetRootElementForIndex(m_ListView.selectedIndex);
if (element == null)
return;
((InputActionMapsTreeViewItem)element).FocusOnRenameTextField();
}
internal void RenameActionMap(int index)
{
m_ListView.ScrollToItem(index);
var element = m_ListView.GetRootElementForIndex(index);
if (element == null)
return;
((InputActionMapsTreeViewItem)element).FocusOnRenameTextField();
}
internal void DeleteActionMap(int index)
{
Dispatch(Commands.DeleteActionMap(index));
}
internal void DuplicateActionMap(int index)
{
Dispatch(Commands.DuplicateActionMap(index));
}
internal void CopyItems()
{
Dispatch(Commands.CopyActionMapSelection());
}
internal void CutItems()
{
Dispatch(Commands.CutActionMapSelection());
}
internal void PasteItems(bool copiedAction)
{
Dispatch(copiedAction ? Commands.PasteActionFromActionMap(InputActionsEditorView.s_OnPasteCutElements) : Commands.PasteActionMaps(InputActionsEditorView.s_OnPasteCutElements));
}
private void ChangeActionMapName(int index, string newName)
{
m_EnterRenamingMode = false;
Dispatch(Commands.ChangeActionMapName(index, newName));
}
internal void AddActionMap()
{
Dispatch(Commands.AddActionMap());
m_EnterRenamingMode = true;
}
internal int GetMapCount()
{
return m_ListView.itemsSource.Count;
}
private void OnExecuteCommand(ExecuteCommandEvent evt)
{
var selectedItem = m_ListView.GetRootElementForIndex(m_ListView.selectedIndex);
if (selectedItem == null)
return;
if (allowUICommandExecution)
{
switch (evt.commandName)
{
case CmdEvents.Rename:
((InputActionMapsTreeViewItem)selectedItem).FocusOnRenameTextField();
break;
case CmdEvents.Delete:
case CmdEvents.SoftDelete:
DeleteActionMap(m_ListView.selectedIndex);
break;
case CmdEvents.Duplicate:
DuplicateActionMap(m_ListView.selectedIndex);
break;
case CmdEvents.Copy:
CopyItems();
break;
case CmdEvents.Cut:
CutItems();
break;
case CmdEvents.Paste:
var isActionCopied = CopyPasteHelper.GetCopiedClipboardType() == typeof(InputAction);
if (CopyPasteHelper.HasPastableClipboardData(typeof(InputActionMap)))
PasteItems(isActionCopied);
break;
default:
return; // Skip StopPropagation if we didn't execute anything
}
// Prevent any UI commands from executing until after UI has been updated
allowUICommandExecution = false;
}
evt.StopPropagation();
}
private void OnValidateCommand(ValidateCommandEvent evt)
{
// Mark commands as supported for Execute by stopping propagation of the event
switch (evt.commandName)
{
case CmdEvents.Rename:
case CmdEvents.Delete:
case CmdEvents.SoftDelete:
case CmdEvents.Duplicate:
case CmdEvents.Copy:
case CmdEvents.Cut:
case CmdEvents.Paste:
evt.StopPropagation();
break;
}
}
private void OnPointerDown(PointerDownEvent evt)
{
// Allow right clicks to select an item before we bring up the matching context menu.
if (evt.button == (int)MouseButton.RightMouse && evt.clickCount == 1)
{
var actionMap = (evt.target as VisualElement).GetFirstAncestorOfType<InputActionMapsTreeViewItem>();
if (actionMap != null)
m_ListView.SetSelection(actionMap.parent.IndexOf(actionMap));
}
}
private readonly CollectionViewSelectionChangeFilter m_ListViewSelectionChangeFilter;
private bool m_EnterRenamingMode;
private readonly ListView m_ListView;
private readonly Button m_AddActionMapButton;
internal struct ActionMapData
{
internal string mapName;
internal bool isDisabled;
public ActionMapData(string mapName, bool isDisabled)
{
this.mapName = mapName;
this.isDisabled = isDisabled;
}
}
internal class ViewState
{
public SerializedInputActionMap? selectedActionMap;
public List<ActionMapData> actionMapData;
public ViewState(SerializedInputActionMap? selectedActionMap, IEnumerable<string> actionMapNames, IEnumerable<string> disabledActionMapNames)
{
this.selectedActionMap = selectedActionMap;
actionMapData = new List<ActionMapData>();
foreach (var name in actionMapNames)
{
actionMapData.Add(new ActionMapData(name, disabledActionMapNames.Contains(name)));
}
}
}
}
}
#endif