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

194 lines
8.8 KiB
C#

#if UNITY_EDITOR
using System;
using System.Linq;
using UnityEditor;
using UnityEngine.UIElements;
namespace UnityEngine.InputSystem.Editor
{
internal class PropertiesView : ViewBase<PropertiesView.ViewState>
{
private ActionPropertiesView m_ActionPropertyView;
private BindingPropertiesView m_BindingPropertyView;
private NameAndParametersListView m_InteractionsListView;
private NameAndParametersListView m_ProcessorsListView;
private Foldout interactionsFoldout => rootElement.Q<Foldout>("interactions-foldout");
private Foldout processorsFoldout => rootElement.Q<Foldout>("processors-foldout");
private TextElement addInteractionButton;
private TextElement addProcessorButton;
public PropertiesView(VisualElement root, StateContainer stateContainer)
: base(root, stateContainer)
{
CreateSelector(
Selectors.GetSelectedAction,
Selectors.GetSelectedBinding,
state => state.selectionType,
(inputAction, inputBinding, selectionType, s) => new ViewState()
{
selectionType = selectionType,
serializedInputAction = inputAction,
inputBinding = inputBinding,
relatedInputAction = Selectors.GetRelatedInputAction(s)
});
var interactionsToggle = interactionsFoldout.Q<Toggle>();
interactionsToggle.AddToClassList("properties-foldout-toggle");
if (addInteractionButton == null)
{
addInteractionButton = CreateAddButton(interactionsToggle, "add-new-interaction-button");
new ContextualMenuManipulator(_ => {}){target = addInteractionButton, activators = {new ManipulatorActivationFilter(){button = MouseButton.LeftMouse}}};
}
var processorToggle = processorsFoldout.Q<Toggle>();
processorToggle.AddToClassList("properties-foldout-toggle");
if (addProcessorButton == null)
{
addProcessorButton = CreateAddButton(processorToggle, "add-new-processor-button");
new ContextualMenuManipulator(_ => {}){target = addProcessorButton, activators = {new ManipulatorActivationFilter(){button = MouseButton.LeftMouse}}};
}
}
private TextElement CreateAddButton(Toggle toggle, string name)
{
var addButton = new Button();
addButton.text = "+";
addButton.name = name;
addButton.focusable = false;
#if UNITY_EDITOR_OSX
addButton.clickable.activators.Clear();
#endif
addButton.AddToClassList("add-interaction-processor-button");
toggle.Add(addButton);
return addButton;
}
private void CreateContextMenuProcessor(string expectedControlType)
{
var processors = InputProcessor.s_Processors;
Type expectedValueType = string.IsNullOrEmpty(expectedControlType) ? null : EditorInputControlLayoutCache.GetValueType(expectedControlType);
addProcessorButton.RegisterCallback<ContextualMenuPopulateEvent>(evt =>
{
evt.menu.ClearItems();
foreach (var name in processors.internedNames.Where(x => !processors.ShouldHideInUI(x)).OrderBy(x => x.ToString()))
{
// Skip if not compatible with value type.
if (!IsValidProcessorForControl(expectedValueType, name))
continue;
var niceName = ObjectNames.NicifyVariableName(name);
evt.menu.AppendAction(niceName, _ => m_ProcessorsListView.OnAddElement(name.ToString()));
}
});
}
private bool IsValidProcessorForControl(Type expectedValueType, string name)
{
if (expectedValueType == null) return true;
var type = InputProcessor.s_Processors.LookupTypeRegistration(name);
var valueType = InputProcessor.GetValueTypeFromType(type);
if (valueType != null && !expectedValueType.IsAssignableFrom(valueType))
return false;
return true;
}
private void CreateContextMenuInteraction(string expectedControlType)
{
var interactions = InputInteraction.s_Interactions;
Type expectedValueType = string.IsNullOrEmpty(expectedControlType) ? null : EditorInputControlLayoutCache.GetValueType(expectedControlType);
addInteractionButton.RegisterCallback<ContextualMenuPopulateEvent>(evt =>
{
evt.menu.ClearItems();
foreach (var name in interactions.internedNames.Where(x => !interactions.ShouldHideInUI(x)).OrderBy(x => x.ToString()))
{
// Skip if not compatible with value type.
if (!IsValidInteractionForControl(expectedValueType, name))
continue;
var niceName = ObjectNames.NicifyVariableName(name);
evt.menu.AppendAction(niceName, _ => m_InteractionsListView.OnAddElement(name.ToString()));
}
});
}
private bool IsValidInteractionForControl(Type expectedValueType, string name)
{
if (expectedValueType == null) return true;
var type = InputInteraction.s_Interactions.LookupTypeRegistration(name);
var valueType = InputInteraction.GetValueType(type);
if (valueType != null && !expectedValueType.IsAssignableFrom(valueType))
return false;
return true;
}
public override void RedrawUI(ViewState viewState)
{
DestroyChildView(m_ActionPropertyView);
DestroyChildView(m_BindingPropertyView);
DestroyChildView(m_InteractionsListView);
DestroyChildView(m_ProcessorsListView);
var propertiesContainer = rootElement.Q<VisualElement>("properties-container");
var foldout = propertiesContainer.Q<Foldout>("properties-foldout");
foldout.Clear();
var visualElement = new VisualElement();
foldout.Add(visualElement);
foldout.Q<Toggle>().AddToClassList("properties-foldout-toggle");
var inputAction = viewState.serializedInputAction;
var inputActionOrBinding = inputAction?.wrappedProperty;
switch (viewState.selectionType)
{
case SelectionType.Action:
rootElement.Q<Label>("properties-header-label").text = "Action Properties";
m_ActionPropertyView = CreateChildView(new ActionPropertiesView(visualElement, foldout, stateContainer));
break;
case SelectionType.Binding:
rootElement.Q<Label>("properties-header-label").text = "Binding Properties";
m_BindingPropertyView = CreateChildView(new BindingPropertiesView(visualElement, foldout, stateContainer));
inputAction = viewState.relatedInputAction;
inputActionOrBinding = viewState.inputBinding?.wrappedProperty;
break;
}
CreateContextMenuProcessor(inputAction?.expectedControlType);
CreateContextMenuInteraction(inputAction?.expectedControlType);
var isPartOfComposite = viewState.selectionType == SelectionType.Binding &&
viewState.inputBinding?.isPartOfComposite == true;
//don't show for Bindings in Composites
if (!isPartOfComposite)
{
interactionsFoldout.style.display = DisplayStyle.Flex;
m_InteractionsListView = CreateChildView(new NameAndParametersListView(
interactionsFoldout,
stateContainer,
inputActionOrBinding?.FindPropertyRelative(nameof(InputAction.m_Interactions)),
state => Selectors.GetInteractionsAsParameterListViews(state, inputAction)));
}
else
interactionsFoldout.style.display = DisplayStyle.None;
m_ProcessorsListView = CreateChildView(new NameAndParametersListView(
processorsFoldout,
stateContainer,
inputActionOrBinding?.FindPropertyRelative(nameof(InputAction.m_Processors)),
state => Selectors.GetProcessorsAsParameterListViews(state, inputAction)));
}
internal class ViewState
{
public SerializedInputAction? relatedInputAction;
public SerializedInputBinding? inputBinding;
public SerializedInputAction? serializedInputAction;
public SelectionType selectionType;
}
}
}
#endif