public NodePortInfo CreateLooseDynamicPortInfo(NodePort port, out InspectorPropertyInfo info, out InspectorPropertyInfo portInfo, params Attribute[] attributes) { info = InspectorPropertyInfo.CreateValue( port.fieldName, 1, Property.ValueEntry.SerializationBackend, new GetterSetter <TValue, int>( ( ref TValue owner ) => 0, (ref TValue owner, int value) => { } ), attributes ); portInfo = InspectorPropertyInfo.CreateValue( $"{info.PropertyName}:port", 0, Property.ValueEntry.SerializationBackend, new GetterSetter <TValue, NodePort>( ( ref TValue owner ) => port, (ref TValue owner, NodePort value) => { } ) , new HideInInspector() ); // Create a fake property and a fake node NodePortInfo nodePortInfo = new NodePortInfo( portInfo, info, port.fieldName, port.ValueType, Property.Tree.WeakTargets.FirstOrDefault() as Node, // Needed? ShowBackingValue.Never, port.connectionType, port.typeConstraint, false, true, port.IsInput, false ); return(nodePortInfo); }
protected InspectorPropertyInfo[] GetPropertyInfos() { if (this.processors == null) { this.processors = OdinPropertyProcessorLocator.GetMemberProcessors(this.Property); } var includeSpeciallySerializedMembers = this.Property.ValueEntry.SerializationBackend != SerializationBackend.Unity; var infos = InspectorPropertyInfoUtility.CreateMemberProperties(this.Property, typeof(TValue), includeSpeciallySerializedMembers); // If we resolve the ports from the port dictionary i might be able to communicate between properties // in order to make dynamic port adding cleaner // Resolve my own members so I can see them #if DEBUG_RESOLVER infos.AddValue( $"resolver:{nameof(infos)}", () => this.infos, value => { } ); infos.AddValue( $"resolver:{nameof( namesToIndex )}", () => this.namesToIndex, value => { } ); infos.AddValue( $"resolver:{nameof( nameToNodePropertyInfo )}", () => this.nameToNodePropertyInfo, value => { } ); infos.AddValue( $"resolver:{nameof( propertyToNodeProperty )}", () => this.propertyToNodeProperty, value => { } ); #endif LabelWidthAttribute labelWidthAttribute = Property.GetAttribute <LabelWidthAttribute>(); displayDynamicPortsAttribute = Property.GetAttribute <DisplayDynamicPortsAttribute>(); // Port makers { for (int i = 0; i < infos.Count; ++i) { var info = infos[i]; if (labelWidthAttribute != null) { if (info.GetAttribute <LabelWidthAttribute>() == null) { info.GetEditableAttributesList().Add(labelWidthAttribute); } } var inputAttribute = info.GetMemberInfo().GetAttribute <InputAttribute>(); var outputAttribute = info.GetMemberInfo().GetAttribute <OutputAttribute>(); if (inputAttribute != null || outputAttribute != null) // Make a port.... we'll deal with dynamic later { string baseFieldName = info.PropertyName; NodePort port = Node.GetPort(info.PropertyName); ShowBackingValue showBackingValue = ShowBackingValue.Always; ConnectionType connectionType = ConnectionType.Multiple; TypeConstraint typeConstraint = TypeConstraint.None; bool isDynamicPortList = false; bool isInput = false; if (inputAttribute != null) { showBackingValue = inputAttribute.backingValue; connectionType = inputAttribute.connectionType; typeConstraint = inputAttribute.typeConstraint; isDynamicPortList = inputAttribute.dynamicPortList; isInput = true; } else if (outputAttribute != null) { showBackingValue = outputAttribute.backingValue; connectionType = outputAttribute.connectionType; typeConstraint = outputAttribute.typeConstraint; isDynamicPortList = outputAttribute.dynamicPortList; isInput = false; } // The port didn't exist... let's just make it exist again? if (port == null) { Node.UpdatePorts(); port = Node.GetPort(info.PropertyName); } var portInfo = InspectorPropertyInfo.CreateValue( $"{info.PropertyName}:port", 0, Property.ValueEntry.SerializationBackend, new GetterSetter <TValue, NodePort>( ( ref TValue owner ) => port, (ref TValue owner, NodePort value) => { } ) , new HideInInspector() ); var nodePortInfo = new NodePortInfo( portInfo, info, baseFieldName, info.TypeOfValue, Property.Tree.WeakTargets.FirstOrDefault() as Node, // Needed? showBackingValue, connectionType, typeConstraint, isDynamicPortList, false, isInput, true ); propertyToNodeProperty[info.PropertyName] = portInfo.PropertyName; nameToNodePropertyInfo[portInfo.PropertyName] = nodePortInfo; if (isDynamicPortList) { var listDrawerAttributes = info.GetAttribute <ListDrawerSettingsAttribute>(); if (listDrawerAttributes == null) { listDrawerAttributes = new ListDrawerSettingsAttribute(); info.GetEditableAttributesList().Add(listDrawerAttributes); } listDrawerAttributes.Expanded = true; listDrawerAttributes.ShowPaging = false; } infos.Insert(i, portInfo); ++i; // Skip the next entry } } if (displayDynamicPortsAttribute != null) { // If I find any dynamic ports that were not covered here then add them as well // This should include anything that wouldn't be directly related to the ports I *did* find foreach (var port in Node.Ports) { if (port.IsDynamic) { // If is likely to be an automatically added port? if (IsManagedPort(port.fieldName)) { continue; } // No one claimed it? var nodePortInfo = CreateLooseDynamicPortInfo(port, out var info, out var portInfo, displayDynamicPortsAttribute); propertyToNodeProperty[info.PropertyName] = portInfo.PropertyName; nameToNodePropertyInfo[portInfo.PropertyName] = nodePortInfo; infos.Add(info); infos.Add(portInfo); } } } } for (int i = 0; i < this.processors.Count; i++) { ProcessedMemberPropertyResolverExtensions.ProcessingOwnerType = typeof(TValue); this.processors[i].ProcessMemberProperties(infos); } EditorApplication.update -= Update; if (displayDynamicPortsAttribute != null) { EditorApplication.update += Update; } knownPortKeys.Clear(); knownPortKeys.AddRange(Node.Ports.Select(x => x.fieldName)); return(InspectorPropertyInfoUtility.BuildPropertyGroupsAndFinalize(this.Property, typeof(TValue), infos, includeSpeciallySerializedMembers)); }