Ejemplo n.º 1
0
 /// <summary>
 /// Adds a <see cref="ModChoiceOption"/> to the <see cref="ModOptions"/> menu.
 /// </summary>
 /// <param name="id"></param>
 /// <param name="label"></param>
 /// <param name="memberInfoMetadata">The metadata of the corresponding member.</param>
 /// <param name="choiceAttribute">The defined or generated <see cref="ChoiceAttribute"/> of the member.</param>
 private void BuildModChoiceOption(string id, string label,
                                   MemberInfoMetadata <T> memberInfoMetadata, ChoiceAttribute choiceAttribute)
 {
     if (memberInfoMetadata.ValueType.IsEnum && (choiceAttribute.Options == null || !choiceAttribute.Options.Any()))
     {
         // Enum-based choice where the values are parsed from the enum type
         string[] options = Enum.GetNames(memberInfoMetadata.ValueType);
         string   value   = memberInfoMetadata.GetValue(ConfigFileMetadata.Config).ToString();
         AddChoiceOption(id, label, options, value);
     }
     else if (memberInfoMetadata.ValueType.IsEnum)
     {
         // Enum-based choice where the values are defined as custom strings
         string[] options = choiceAttribute.Options;
         string   name    = memberInfoMetadata.GetValue(ConfigFileMetadata.Config).ToString();
         int      index   = Math.Max(Array.IndexOf(Enum.GetNames(memberInfoMetadata.ValueType), name), 0);
         AddChoiceOption(id, label, options, index);
     }
     else if (memberInfoMetadata.ValueType == typeof(string))
     {
         // string-based choice value
         string[] options = choiceAttribute.Options;
         string   value   = memberInfoMetadata.GetValue <string>(ConfigFileMetadata.Config);
         AddChoiceOption(id, label, options, value);
     }
     else if (memberInfoMetadata.ValueType == typeof(int))
     {
         // index-based choice value
         string[] options = choiceAttribute.Options;
         int      index   = memberInfoMetadata.GetValue <int>(ConfigFileMetadata.Config);
         AddChoiceOption(id, label, options, index);
     }
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Adds a <see cref="ModSliderOption"/> to the <see cref="ModOptions"/> menu.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="label"></param>
        /// <param name="memberInfoMetadata">The metadata of the corresponding member.</param>
        /// <param name="sliderAttribute">The defined or generated <see cref="SliderAttribute"/> of the member.</param>
        private void BuildModSliderOption(string id, string label,
                                          MemberInfoMetadata <T> memberInfoMetadata, SliderAttribute sliderAttribute)
        {
            float value = Convert.ToSingle(memberInfoMetadata.GetValue(ConfigFileMetadata.Config));

            float step = sliderAttribute.Step;

            if (memberInfoMetadata.ValueType == typeof(int))
            {
                step = Mathf.CeilToInt(step);
            }

            AddSliderOption(id, label, sliderAttribute.Min, sliderAttribute.Max,
                            Convert.ToSingle(value), sliderAttribute.DefaultValue,
                            sliderAttribute.Format, step);
        }
        /// <summary>
        /// Gets the metadata of every <typeparamref name="TAttribute"/> defined for a member.
        /// </summary>
        /// <typeparam name="TAttribute">
        /// The type of <see cref="ModOptionEventAttribute"/> attribute defined on the member to gather metadata for.
        /// </typeparam>
        /// <param name="memberInfo">The member to gather attribute metadata for.</param>
        /// <returns></returns>
        private IEnumerable <MemberInfoMetadata <T> > GetEventMetadata <TAttribute>(MemberInfo memberInfo)
            where TAttribute : ModOptionEventAttribute
        {
            var metadatas = new List <MemberInfoMetadata <T> >();

            foreach (TAttribute attribute in memberInfo.GetCustomAttributes <TAttribute>(true))
            {
                var methodMetadata = new MemberInfoMetadata <T>
                {
                    MemberType = MemberType.Method,
                    Name       = attribute.MethodName
                };
                methodMetadata.ParseMethodParameterTypes();
                metadatas.Add(methodMetadata);
            }
            return(metadatas);
        }
        /// <summary>
        /// Invoke the relevant method specified by a <see cref="ModOptionEventAttribute"/>
        /// and passes relevant parameters.
        /// </summary>
        /// <typeparam name="TSource">The type of the event args.</typeparam>
        /// <param name="memberInfoMetadata">The metadata for the method.</param>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="e">The event args from the event.</param>
        private void InvokeEvent <TSource>(MemberInfoMetadata <T> memberInfoMetadata, object sender, TSource e)
            where TSource : IModOptionEventArgs
        {
            if (!memberInfoMetadata.MethodValid)
            {
                // Method not found, log error and skip.
                Logger.Error($"[OptionsMenuBuilder] Could not find the specified method: {typeof(T)}.{memberInfoMetadata.Name}");
                return;
            }

            if (memberInfoMetadata.MethodParameterTypes is Type[] parameterTypes)
            {
                var parameters          = new object[parameterTypes.Length];
                var senderFound         = false;
                var eventArgsFound      = false;
                var modOptionEventFound = false;

                for (var i = 0; i < parameterTypes.Length; i++)
                {
                    if (!senderFound && parameterTypes[i] == typeof(object))
                    {
                        senderFound   = true;
                        parameters[i] = sender;
                    }
                    else if (!eventArgsFound && parameterTypes[i] == typeof(TSource))
                    {
                        eventArgsFound = true;
                        parameters[i]  = e;
                    }
                    else if (!modOptionEventFound && parameterTypes[i] == typeof(IModOptionEventArgs))
                    {
                        modOptionEventFound = true;
                        parameters[i]       = e;
                    }

                    if (senderFound && eventArgsFound && modOptionEventFound)
                    {
                        break;
                    }
                }

                memberInfoMetadata.InvokeMethod(Config, parameters);
            }
        }
        /// <summary>
        /// Sets the value in the <see cref="Config"/>, optionally saving the <see cref="Config"/> to disk if the
        /// <see cref="MenuAttribute.SaveEvents.ChangeValue"/> flag is set, before passing off to
        /// <see cref="InvokeOnChangeEvents{TSource}(ModOptionAttributeMetadata{T}, object, TSource)"/>
        /// to invoke any methods specified with an <see cref="OnChangeAttribute"/>.
        /// </summary>
        /// <param name="sender">The sender of the original slider changed event.</param>
        /// <param name="e">The <see cref="SliderChangedEventArgs"/> for the slider changed event.</param>
        public void HandleSliderChanged(object sender, SliderChangedEventArgs e)
        {
            if (TryGetMetadata(e.Id, out ModOptionAttributeMetadata <T> modOptionMetadata))
            {
                // Set the value in the Config
                MemberInfoMetadata <T> memberInfoMetadata = modOptionMetadata.MemberInfoMetadata;
                object value = Convert.ChangeType(e.Value, memberInfoMetadata.ValueType);
                memberInfoMetadata.SetValue(Config, value);

                // Optionally save the Config to disk
                if (MenuAttribute.SaveOn.HasFlag(MenuAttribute.SaveEvents.ChangeValue))
                {
                    Config.Save();
                }

                // Invoke any OnChange methods specified
                InvokeOnChangeEvents(modOptionMetadata, sender, e);
            }
        }
        /// <summary>
        /// Sets the value in the <see cref="Config"/>, optionally saving the <see cref="Config"/> to disk if the
        /// <see cref="MenuAttribute.SaveEvents.ChangeValue"/> flag is set, before passing off to
        /// <see cref="InvokeOnChangeEvents{TSource}(ModOptionAttributeMetadata{T}, object, TSource)"/>
        /// to invoke any methods specified with an <see cref="OnChangeAttribute"/>.
        /// </summary>
        /// <param name="sender">The sender of the original choice changed event.</param>
        /// <param name="e">The <see cref="ChoiceChangedEventArgs"/> for the choice changed event.</param>
        public void HandleChoiceChanged(object sender, ChoiceChangedEventArgs e)
        {
            if (TryGetMetadata(e.Id, out ModOptionAttributeMetadata <T> modOptionMetadata))
            {
                // Set the value in the Config
                MemberInfoMetadata <T> memberInfoMetadata = modOptionMetadata.MemberInfoMetadata;
                ChoiceAttribute        choiceAttribute    = modOptionMetadata.ModOptionAttribute as ChoiceAttribute;

                if (memberInfoMetadata.ValueType.IsEnum && (choiceAttribute.Options == null || !choiceAttribute.Options.Any()))
                {
                    // Enum-based choice where the values are parsed from the enum type
                    object value = Enum.Parse(memberInfoMetadata.ValueType, e.Value);
                    memberInfoMetadata.SetValue(Config, value);
                }
                else if (memberInfoMetadata.ValueType.IsEnum)
                {
                    // Enum-based choice where the values are defined as custom strings
                    object value = Enum.Parse(memberInfoMetadata.ValueType, Enum.GetNames(memberInfoMetadata.ValueType)[e.Index]);
                    memberInfoMetadata.SetValue(Config, value);
                }
                else if (memberInfoMetadata.ValueType == typeof(string))
                {
                    // string-based choice value
                    string value = e.Value;
                    memberInfoMetadata.SetValue(Config, value);
                }
                else if (memberInfoMetadata.ValueType == typeof(int))
                {
                    // index-based choice value
                    int value = e.Index;
                    memberInfoMetadata.SetValue(Config, value);
                }

                // Optionally save the Config to disk
                if (MenuAttribute.SaveOn.HasFlag(MenuAttribute.SaveEvents.ChangeValue))
                {
                    Config.Save();
                }

                // Invoke any OnChange methods specified
                InvokeOnChangeEvents(modOptionMetadata, sender, e);
            }
        }
        /// <summary>
        /// Invokes the relevant method(s) specified with the <see cref="OnChangeAttribute"/>(s)
        /// and passes parameters when a value is changed when loaded from disk.
        /// </summary>
        /// <param name="modOptionMetadata">The metadata for the mod option.</param>
        /// <param name="sender">The sender of the event.</param>
        private void InvokeOnChangeEvents(ModOptionAttributeMetadata <T> modOptionMetadata, object sender)
        {
            string id = modOptionMetadata.ModOptionAttribute.Id;
            MemberInfoMetadata <T> memberInfoMetadata = modOptionMetadata.MemberInfoMetadata;

            switch (modOptionMetadata.ModOptionAttribute)
            {
            case ChoiceAttribute choiceAttribute when memberInfoMetadata.ValueType.IsEnum &&
                (choiceAttribute.Options == null || !choiceAttribute.Options.Any()):
                // Enum-based choice where the values are parsed from the enum type
            {
                string[] options   = Enum.GetNames(memberInfoMetadata.ValueType);
                string   value     = memberInfoMetadata.GetValue(Config).ToString();
                var      eventArgs = new ChoiceChangedEventArgs(id, Array.IndexOf(options, value), value);
                InvokeOnChangeEvents(modOptionMetadata, sender, eventArgs);
            }
            break;

            case ChoiceAttribute _ when memberInfoMetadata.ValueType.IsEnum:
                // Enum-based choice where the values are defined as custom strings
            {
                string value     = memberInfoMetadata.GetValue(Config).ToString();
                int    index     = Math.Max(Array.IndexOf(Enum.GetValues(memberInfoMetadata.ValueType), value), 0);
                var    eventArgs = new ChoiceChangedEventArgs(id, index, value);
                InvokeOnChangeEvents(modOptionMetadata, sender, eventArgs);
            }
            break;

            case ChoiceAttribute choiceAttribute when memberInfoMetadata.ValueType == typeof(string):
                // string-based choice value
            {
                string[] options   = choiceAttribute.Options;
                string   value     = memberInfoMetadata.GetValue <string>(Config);
                var      eventArgs = new ChoiceChangedEventArgs(id, Array.IndexOf(options, value), value);
                InvokeOnChangeEvents(modOptionMetadata, sender, eventArgs);
            }
            break;

            case ChoiceAttribute choiceAttribute when memberInfoMetadata.ValueType == typeof(int):
                // index-based choice value
            {
                string[] options   = choiceAttribute.Options;
                int      index     = memberInfoMetadata.GetValue <int>(Config);
                var      eventArgs = new ChoiceChangedEventArgs(id, index, options[index]);
                InvokeOnChangeEvents(modOptionMetadata, sender, eventArgs);
            }
            break;

            case KeybindAttribute _:
            {
                var eventArgs = new KeybindChangedEventArgs(id, memberInfoMetadata.GetValue <KeyCode>(Config));
                InvokeOnChangeEvents(modOptionMetadata, sender, eventArgs);
            }
            break;

            case SliderAttribute _:
            {
                var eventArgs = new SliderChangedEventArgs(id, Convert.ToSingle(memberInfoMetadata.GetValue(Config)));
                InvokeOnChangeEvents(modOptionMetadata, sender, eventArgs);
            }
            break;

            case ToggleAttribute _:
            {
                var eventArgs = new ToggleChangedEventArgs(id, memberInfoMetadata.GetValue <bool>(Config));
                InvokeOnChangeEvents(modOptionMetadata, sender, eventArgs);
            }
            break;
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Adds a <see cref="ModToggleOption"/> to the <see cref="ModOptions"/> menu.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="label"></param>
        /// <param name="memberInfoMetadata">The metadata of the corresponding member.</param>
        private void BuildModToggleOption(string id, string label, MemberInfoMetadata <T> memberInfoMetadata)
        {
            bool value = memberInfoMetadata.GetValue <bool>(ConfigFileMetadata.Config);

            AddToggleOption(id, label, value);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Adds a <see cref="ModKeybindOption"/> to the <see cref="ModOptions"/> menu.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="label"></param>
        /// <param name="memberInfoMetadata">The metadata of the corresponding member.</param>
        private void BuildModKeybindOption(string id, string label, MemberInfoMetadata <T> memberInfoMetadata)
        {
            KeyCode value = memberInfoMetadata.GetValue <KeyCode>(ConfigFileMetadata.Config);

            AddKeybindOption(id, label, GameInput.Device.Keyboard, value);
        }