コード例 #1
0
        private static void GetStateDelegate(StateInfo state, Type type)
        {
            var method = type.GetMethod(state.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(float) }, null);

            if (method != null)
            {
                state.InvokeWithTimeDelegate = (OpenDelegate <float>)OpenDelegate.Create(method as MethodInfo);
                return;
            }

            method = type.GetMethod(state.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null);
            if (method != null)
            {
                state.InvokeDelegate = (OpenDelegate)OpenDelegate.Create(method as MethodInfo);
                return;
            }

            if (type.BaseType != null)
            {
                GetStateDelegate(state, type.BaseType);
            }
        }
コード例 #2
0
        /// <summary>
        /// Attempt to add a transition to the given transitions list
        /// </summary>
        private static StateTransitionInfo CreateTransition(StateMachineInfo info, StateInfo from, StateInfo to)
        {
            if (from == to)
            {
                return(null);
            }

            // Check for the transition method
            var methodInfo = info.TargetType.GetMethod(
                $"On{from?.Name??"Any"}To{to?.Name??"Any"}",
                BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

            if (methodInfo == null)
            {
                return(null);
            }

            return(new StateTransitionInfo
            {
                From = from,
                To = to,
                InvokeDelegate = OpenDelegate.Create(methodInfo)
            });
        }
コード例 #3
0
        /// <summary>
        /// Create state machine info for a given type
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static StateMachineInfo Create(Type type, Type statesType)
        {
            var typeName = type.FullName;

            if (_cache.TryGetValue(typeName, out var info))
            {
                return(info);
            }

            var values = Enum.GetValues(statesType);
            var states = new StateInfo[values.Length];

            foreach (var value in values)
            {
                var index = (int)value;
                var name  = value.ToString();

                if (index < 0 || index >= states.Length)
                {
                    throw new UnityException("State enum must be sequential and start from zero");
                }

                states[index] = new StateInfo {
                    Name = value.ToString(), Mask = (1UL << index), Index = index
                };
            }

            // Create a new state machine info
            info                   = new StateMachineInfo();
            info.TargetType        = type;
            info.States            = states;
            info._transitionStride = states.Length + 1;
            _cache.Add(typeName, info);

            // Get state method and transitions
            info._transitions = new StateTransitionInfo[states.Length * info._transitionStride];
            foreach (var stateToInfo in states)
            {
                // State method?
                var stateMethod = type.GetMethod($"On{stateToInfo.Name}", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
                if (null != stateMethod)
                {
                    var parameters = stateMethod.GetParameters();
                    if (parameters.Length == 0)
                    {
                        stateToInfo.InvokeDelegate = OpenDelegate.Create(stateMethod);
                    }
                    else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(float))
                    {
                        stateToInfo.InvokeWithTimeDelegate = OpenDelegate <float> .Create(stateMethod);
                    }
                    else
                    {
                        throw new UnityException($"method for state '{stateToInfo.Name}' does not match a valid state signature");
                    }
                }

                // Add the "Any" to state transition
                info._transitions[info.GetTransitionIndex(-1, stateToInfo.Index)] = CreateTransition(info, null, stateToInfo);

                // Add transition from all other states
                foreach (var stateFromInfo in states)
                {
                    info._transitions[info.GetTransitionIndex(stateFromInfo.Index, stateToInfo.Index)] =
                        CreateTransition(info, stateFromInfo, stateToInfo);
                }
            }

            return(info);
        }
コード例 #4
0
        private static void GetInfo(Type type, List <StateInfo> states, List <StateTriggerInfo> triggers, List <StateTransitionInfo> transitions)
        {
            // Recurse through all parent types as well
            if (type.BaseType != null)
            {
                GetInfo(type.BaseType, states, triggers, transitions);
            }

            // Get all public and private methods
            var members = type.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            foreach (var member in members)
            {
                switch (member.MemberType)
                {
                case MemberTypes.Field:
                case MemberTypes.Property:
                {
                    foreach (var attr in member.GetCustomAttributes <StateTriggerAttribute>())
                    {
                        var trigger = new StateTriggerInfo();
                        trigger.From        = GetState(states, attr.From);
                        trigger.To          = GetState(states, attr.To);
                        trigger.TargetValue = attr.Value;
                        trigger.Getter      = (FastGetter <bool>)FastGetter.Create(member);

                        if (trigger.To == null)
                        {
                            throw new InvalidOperationException("trigger to state must not be null");
                        }

                        triggers.Add(trigger);
                    }
                    break;
                }

                case MemberTypes.Method:
                {
                    // Get transitions
                    foreach (var attr in member.GetCustomAttributes <StateTransitionAttribute>())
                    {
                        var trans = new StateTransitionInfo();
                        trans.From = GetState(states, attr.From);
                        trans.To   = GetState(states, attr.To);
                        if (((member as MethodInfo).GetParameters()).Length == 0)
                        {
                            trans.InvokeDelegate = (OpenDelegate)OpenDelegate.Create(member as MethodInfo);
                        }
                        else
                        {
                            throw new InvalidOperationException("state transitions must return void and take no parameter or one parameter as a float");
                        }

                        if (trans.To == null)
                        {
                            throw new InvalidOperationException("transition to state must not be null");
                        }

                        transitions.Add(trans);
                    }

#if false
                    // Get states
                    foreach (var attr in member.GetCustomAttributes <StateAttribute>())
                    {
                        var state      = GetState(states, attr.Name ?? member.Name);
                        var parameters = (member as MethodInfo).GetParameters();
                        if (parameters.Length == 0)
                        {
                            state.InvokeDelegate = (OpenDelegate)OpenDelegate.Create(member as MethodInfo);
                        }
                        else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(float))
                        {
                            state.InvokeWithTimeDelegate = (OpenDelegate <float>)OpenDelegate.Create(member as MethodInfo);
                        }
                        else
                        {
                            throw new InvalidOperationException("states must return void and take no parameter or one parameter as a float");
                        }
                    }
#endif
                    break;
                }
                }
            }
        }