public SerializableAction_Single(Object targetObject, SerializableMethod target, params object[] parameters)
        {
            Assert.AreEqual(target.ParameterTypes.Length, parameters.Length);
            for (var i = 0; i < target.ParameterTypes.Length; i++)
            {
                var parameterType = target.ParameterTypes[i];
                Assert.IsTrue((parameters[i] == null && !parameterType.SystemType.IsValueType) || parameterType.SystemType.IsInstanceOfType(parameters[i]));
            }

            this.targetObject = targetObject;
            this.target       = new SerializableActionTarget(target);
            arguments         = new SerializableArgument[parameters.Length];
            for (int i = 0; i < arguments.Length; i++)
            {
                arguments[i] = new SerializableArgument(parameters[i], parameters[i].GetType(), target.ParameterNames[i]);
            }
        }
Ejemplo n.º 2
0
        /*
         * This OnGUI mostly uses the raw object instead of fiddling with the SerializedProperty.
         * This is because we need to handle things like raw System.Objects and arrays,
         * both of which SerializedProperties can't deal with.
         *
         * static so the list drawer can use it
         */
        public static void DrawSerializableAction(Rect position, SerializedProperty property)
        {
            EditorGUI.BeginChangeCheck();
            position.height = EditorGUIUtility.singleLineHeight;
            var action = (SerializableAction_Single)SerializedPropertyHelper.GetTargetObjectOfProperty(property);

            Object containingObject = action.TargetObject;

            if (action.TargetObject != null && action.TargetObject is Component)
            {
                containingObject = (action.TargetObject as Component).gameObject;
            }

            var callStateRect = position;

            callStateRect.width *= .3f;
            action.callState     = (UnityEventCallState)EditorGUI.EnumPopup(callStateRect, action.callState);

            var objectRect          = EditorUtil.NextPosition(callStateRect, EditorGUIUtility.singleLineHeight);
            var newContainingObject = EditorGUI.ObjectField(objectRect, containingObject, typeof(Object), true);

            if (newContainingObject != containingObject)
            {
                action.TargetObject = newContainingObject;
            }
            containingObject = newContainingObject;

            if (action.TargetObject == null)
            {
                if (EditorGUI.EndChangeCheck())
                {
                    property.SetDirty();
                }
                return;
            }

            int objectIdx;

            Object[] objectsOnContainer;
            string[] objectNames;
            ReadyObjectSelectDropdown(containingObject, action.TargetObject, out objectsOnContainer, out objectNames, out objectIdx);

            var objectSelectRect = position;

            objectSelectRect.xMin = callStateRect.xMax + 5f;

            var objectSelectRect_label = objectSelectRect;
            var objectSelectRect_popup = objectSelectRect;

            objectSelectRect_label.width = 90f;
            objectSelectRect_popup.xMin  = objectSelectRect_label.xMax + 5f;

            EditorGUI.LabelField(objectSelectRect_label, "Target Script:");
            var newIdx = EditorGUI.Popup(objectSelectRect_popup, objectIdx, objectNames);

            if (newIdx != objectIdx)
            {
                objectIdx           = newIdx;
                action.TargetObject = objectsOnContainer[objectIdx];
                action.Target       = null;
                action.Arguments    = null;
            }

            var type = action.TargetObject.GetType();

            EnsureDataCached(type);

            var methods             = typeToMethods[type];
            var fields              = typeToFields[type];
            var methodAndFieldNames = typeToNames[type];

            int  methodIdx = 0, fieldIdx = 0, nameIdx = 0;
            bool isDeleted = false;

            var target = action.Target;

            //@TODO: This might never be null due to Unity's inspector always initializing fields.
            if (target != null)
            {
                if (target.IsMethod)
                {
                    fieldIdx  = -1;
                    methodIdx = target.HasTarget ? methods.IndexOf(target.TargetMethod) : -1;
                    nameIdx   = methodIdx + 1;

                    isDeleted = methodIdx == -1 && !string.IsNullOrEmpty(target.TargetMethod.MethodName);
                }
                else
                {
                    methodIdx = -1;
                    fieldIdx  = target.HasTarget ? fields.IndexOf(target.TargetFieldSetter) : -1;
                    nameIdx   = fieldIdx == -1 ? 0 : fieldIdx + 1 + methods.Count;

                    isDeleted = fieldIdx == -1 && !string.IsNullOrEmpty(target.TargetFieldSetter.FieldName);
                }
            }

            //Detect deleted method
            if (isDeleted)
            {
                methodAndFieldNames[0] = string.Format("Deleted {0}! Old name: {1}", target.IsMethod ? "Method" : "Field", target.Name);
            }
            else
            {
                methodAndFieldNames[0] = NoMethodSelected;
            }

            var actionSelectRect       = EditorUtil.NextPosition(objectSelectRect, EditorGUIUtility.singleLineHeight);
            var actionSelectRect_label = actionSelectRect;
            var actionSelectRect_popup = actionSelectRect;

            actionSelectRect_label.width = 90f;
            actionSelectRect_popup.xMin  = actionSelectRect_label.xMax + 5f;

            EditorGUI.LabelField(actionSelectRect_label, "Target action:");
            var newNameIdx = EditorGUI.Popup(actionSelectRect_popup, nameIdx, methodAndFieldNames);

            if (newNameIdx != nameIdx)
            {
                //Selected "None", clear target method
                if (newNameIdx == 0)
                {
                    action.Target    = null;
                    action.Arguments = new SerializableArgument[0];
                }
                //Selected a method or a setter
                else if (newNameIdx < methods.Count + 1)
                {
                    var oldMethod    = action.Target.IsMethod ? action.Target.TargetMethod : null;
                    var targetMethod = methods[newNameIdx - 1];
                    action.Target.TargetMethod = targetMethod;

                    var oldParameters = action.Arguments;
                    action.Arguments = new SerializableArgument[targetMethod.ParameterTypes.Length];
                    for (int i = 0; i < action.Arguments.Length; i++)
                    {
                        object value;
                        if (oldMethod != null && oldParameters != null && i < oldParameters.Length &&
                            oldMethod.ParameterTypes[i].Equals(targetMethod.ParameterTypes[i]))
                        {
                            value = oldParameters[i].UnpackParameter();
                        }
                        else
                        {
                            value = DefaultValueFinder.CreateDefaultFor(targetMethod.ParameterTypes[i].SystemType);
                        }

                        action.Arguments[i] = new SerializableArgument(value,
                                                                       targetMethod.ParameterTypes[i].SystemType,
                                                                       targetMethod.ParameterNames[i]);
                    }
                }
                //Selected a field
                else
                {
                    var targetField = fields[newNameIdx - methods.Count - 1];
                    action.Target.TargetFieldSetter = targetField;
                    var arg = new SerializableArgument(DefaultValueFinder.CreateDefaultFor(targetField.FieldType),
                                                       targetField.FieldType,
                                                       "Value");
                    action.Arguments = new[] { arg };
                }
            }

            var changed          = EditorGUI.EndChangeCheck();
            var noMethodSelected = newNameIdx == 0;

            if (changed || noMethodSelected || action.Arguments.Length == 0)
            {
                if (changed)
                {
                    property.SetDirty();
                }
                return;
            }

            position = EditorUtil.NextPosition(position, EditorGUIUtility.singleLineHeight);
            EditorGUI.indentLevel += 2;

            var parameters = property.FindPropertyRelative("arguments");

            for (int i = 0; i < parameters.arraySize; i++)
            {
                var positionHeight = SerializableArgumentDrawer.GetHeightForType(action.Arguments[i].ParameterType.SystemType,
                                                                                 EditorGUIUtility.singleLineHeight, 0);
                position = EditorUtil.NextPosition(position, positionHeight);
                EditorGUI.PropertyField(position, parameters.GetArrayElementAtIndex(i), true);
            }
            property.serializedObject.ApplyModifiedProperties();

            EditorGUI.indentLevel -= 2;
        }