private void OnCompositeTypeChanged() { var nameAndParameters = new InputControlLayout.NameAndParameters { name = m_CompositeTypes[m_SelectedCompositeType], parameters = m_CompositeParameters.GetParameters() }; m_PathProperty.stringValue = nameAndParameters.ToString(); onChange(k_CompositeTypeChanged); }
public static SerializedProperty ChangeCompositeBindingType(SerializedProperty bindingProperty, InputControlLayout.NameAndParameters nameAndParameters) { var bindingsArrayProperty = bindingProperty.GetArrayPropertyFromElement(); Debug.Assert(bindingsArrayProperty != null, "SerializedProperty is not an array of bindings"); var bindingIndex = bindingProperty.GetIndexOfArrayElement(); Debug.Assert(IsCompositeBinding(bindingProperty), $"Binding {bindingProperty.propertyPath} is not a composite"); // If the composite still has the default name, change it to the default // one for the new composite type. var pathProperty = bindingProperty.FindPropertyRelative("m_Path"); var nameProperty = bindingProperty.FindPropertyRelative("m_Name"); if (nameProperty.stringValue == ObjectNames.NicifyVariableName(InputControlLayout.ParseNameAndParameters(pathProperty.stringValue).name)) { nameProperty.stringValue = ObjectNames.NicifyVariableName(nameAndParameters.name); } pathProperty.stringValue = nameAndParameters.ToString(); // Adjust part bindings if we have information on the registered composite. If we don't have // a type, we don't know about the parts. In that case, leave part bindings untouched. var compositeType = InputBindingComposite.s_Composites.LookupTypeRegistration(nameAndParameters.name); if (compositeType != null) { var actionName = bindingProperty.FindPropertyRelative("m_Action").stringValue; // Repurpose existing part bindings for the new composite or add any part bindings that // we're missing. var fields = compositeType.GetFields(BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance); var partIndex = 0; var partBindingsStartIndex = bindingIndex + 1; foreach (var field in fields) { // Skip fields that aren't marked with [InputControl] attribute. if (field.GetCustomAttribute <InputControlAttribute>(false) == null) { continue; } // See if we can reuse an existing part binding. SerializedProperty partProperty = null; if (partBindingsStartIndex + partIndex < bindingsArrayProperty.arraySize) { ////REVIEW: this should probably look up part bindings by name rather than going sequentially var element = bindingsArrayProperty.GetArrayElementAtIndex(partBindingsStartIndex + partIndex); if (((InputBinding.Flags)element.FindPropertyRelative("m_Flags").intValue & InputBinding.Flags.PartOfComposite) != 0) { partProperty = element; } } // If not, insert a new binding. if (partProperty == null) { partProperty = AddBindingToBindingArray(bindingsArrayProperty, partBindingsStartIndex + partIndex, flags: InputBinding.Flags.PartOfComposite); } // Initialize. partProperty.FindPropertyRelative("m_Name").stringValue = ObjectNames.NicifyVariableName(field.Name); partProperty.FindPropertyRelative("m_Action").stringValue = actionName; ++partIndex; } ////REVIEW: when we allow adding the same part multiple times, we may want to do something smarter here // Delete extraneous part bindings. while (partBindingsStartIndex + partIndex < bindingsArrayProperty.arraySize) { var element = bindingsArrayProperty.GetArrayElementAtIndex(partBindingsStartIndex + partIndex); if (((InputBinding.Flags)element.FindPropertyRelative("m_Flags").intValue & InputBinding.Flags.PartOfComposite) == 0) { break; } bindingsArrayProperty.DeleteArrayElementAtIndex(partBindingsStartIndex + partIndex); // No incrementing of partIndex. } } return(bindingProperty); }