mirror of
https://github.com/All-Of-Us-Mods/MiraAPI.git
synced 2026-10-20 01:46:15 +00:00
field support
This commit is contained in:
3 files changed
+95
-11
No files matched your search
@@ -38,7 +38,7 @@ public abstract class ModdedOptionMemberAttribute(string? memberName, Type? hold
|
|||||||
var flags = BindingFlags.Static | BindingFlags.Public;
|
var flags = BindingFlags.Static | BindingFlags.Public;
|
||||||
|
|
||||||
type = holderType ?? groupType;
|
type = holderType ?? groupType;
|
||||||
MemberName ??= $"{property.Name}{defaultSuffix}";
|
MemberName ??= property.Name + defaultSuffix;
|
||||||
|
|
||||||
if (type.IsAssignableTo(typeof(AbstractOptionGroup)))
|
if (type.IsAssignableTo(typeof(AbstractOptionGroup)))
|
||||||
{
|
{
|
||||||
@@ -59,13 +59,24 @@ public abstract class ModdedOptionMemberAttribute(string? memberName, Type? hold
|
|||||||
|
|
||||||
var member = type.GetMember(MemberName, flags).FirstOrDefault();
|
var member = type.GetMember(MemberName, flags).FirstOrDefault();
|
||||||
|
|
||||||
if (instanceGetter != null)
|
if (instanceGetter == null)
|
||||||
|
return member;
|
||||||
|
|
||||||
|
bool isStatic;
|
||||||
|
|
||||||
|
if (member is FieldInfo field)
|
||||||
|
{
|
||||||
|
isStatic = field.IsStatic;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
var method = (member as PropertyInfo)?.GetGetMethod(true) ?? member as MethodInfo;
|
var method = (member as PropertyInfo)?.GetGetMethod(true) ?? member as MethodInfo;
|
||||||
if (method is { IsStatic: true })
|
isStatic = method is { IsStatic: true };
|
||||||
instanceGetter = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isStatic)
|
||||||
|
instanceGetter = null;
|
||||||
|
|
||||||
return member;
|
return member;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,8 +197,8 @@ public abstract class ModdedOptionMemberAttribute(string? memberName, Type? hold
|
|||||||
baseParamTypes,
|
baseParamTypes,
|
||||||
delegateType,
|
delegateType,
|
||||||
suffix,
|
suffix,
|
||||||
forwardParameters: baseParamTypes.Length > 0,
|
baseParamTypes.Length > 0,
|
||||||
postProcessCall: postProcessCall);
|
postProcessCall);
|
||||||
|
|
||||||
return _ => sharedDelegate;
|
return _ => sharedDelegate;
|
||||||
}
|
}
|
||||||
@@ -202,11 +213,16 @@ public abstract class ModdedOptionMemberAttribute(string? memberName, Type? hold
|
|||||||
|
|
||||||
for (byte i = 0; i < baseParamTypes.Length; i++)
|
for (byte i = 0; i < baseParamTypes.Length; i++)
|
||||||
{
|
{
|
||||||
if (i == 0) il.Emit(OpCodes.Ldarg_0);
|
if (i == 0)
|
||||||
else if (i == 1) il.Emit(OpCodes.Ldarg_1);
|
il.Emit(OpCodes.Ldarg_0);
|
||||||
else if (i == 2) il.Emit(OpCodes.Ldarg_2);
|
else if (i == 1)
|
||||||
else if (i == 3) il.Emit(OpCodes.Ldarg_3);
|
il.Emit(OpCodes.Ldarg_1);
|
||||||
else il.Emit(OpCodes.Ldarg_S, i);
|
else if (i == 2)
|
||||||
|
il.Emit(OpCodes.Ldarg_2);
|
||||||
|
else if (i == 3)
|
||||||
|
il.Emit(OpCodes.Ldarg_3);
|
||||||
|
else
|
||||||
|
il.Emit(OpCodes.Ldarg_S, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasIndexParameter)
|
if (hasIndexParameter)
|
||||||
|
|||||||
@@ -71,6 +71,32 @@ public sealed class ModdedOptionVisibilityAttribute(string? memberName = null, T
|
|||||||
|
|
||||||
targetMethod = vMethod;
|
targetMethod = vMethod;
|
||||||
}
|
}
|
||||||
|
else if (member is FieldInfo field)
|
||||||
|
{
|
||||||
|
if (field.FieldType != typeof(bool))
|
||||||
|
{
|
||||||
|
Error($"Field {MemberName} is not a bool.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dynamicMethod = new DynamicMethod($"GetVisibility_{type.Name}_{field.Name}", typeof(bool), Type.EmptyTypes, type, true);
|
||||||
|
|
||||||
|
var il = dynamicMethod.GetILGenerator();
|
||||||
|
|
||||||
|
if (instanceGetter != null)
|
||||||
|
{
|
||||||
|
il.Emit(OpCodes.Ldarg_0);
|
||||||
|
il.Emit(OpCodes.Call, instanceGetter);
|
||||||
|
il.Emit(OpCodes.Ldfld, field);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
il.Emit(OpCodes.Ldsfld, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
il.Emit(OpCodes.Ret);
|
||||||
|
return dynamicMethod.CreateDelegate<Func<bool>>();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Error($"Member {MemberName} of {type.FullName} is not valid for Visible function.");
|
Error($"Member {MemberName} of {type.FullName} is not valid for Visible function.");
|
||||||
@@ -118,6 +144,7 @@ public sealed class ModdedOptionVisibilityAttribute(string? memberName = null, T
|
|||||||
}
|
}
|
||||||
|
|
||||||
var indexParams = vProperty.GetIndexParameters();
|
var indexParams = vProperty.GetIndexParameters();
|
||||||
|
|
||||||
if (indexParams.Length > 1)
|
if (indexParams.Length > 1)
|
||||||
{
|
{
|
||||||
Error($"Indexer {MemberName} has too many parameters.");
|
Error($"Indexer {MemberName} has too many parameters.");
|
||||||
@@ -178,6 +205,43 @@ public sealed class ModdedOptionVisibilityAttribute(string? memberName = null, T
|
|||||||
|
|
||||||
targetMethod = vMethod;
|
targetMethod = vMethod;
|
||||||
}
|
}
|
||||||
|
else if (member is FieldInfo field)
|
||||||
|
{
|
||||||
|
if (field.FieldType.IsAssignableTo(typeof(IList<bool>)))
|
||||||
|
{
|
||||||
|
postProcess = il =>
|
||||||
|
{
|
||||||
|
il.Emit(OpCodes.Ldarg_0);
|
||||||
|
il.Emit(OpCodes.Callvirt, ListBoolIndexerGetter);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (field.FieldType != typeof(bool))
|
||||||
|
{
|
||||||
|
Error($"Field {MemberName} is not a bool or a list of bools.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dynamicMethod = new DynamicMethod($"GetListVisibility_{type.Name}_{field.Name}", typeof(bool), [typeof(int)], type, true);
|
||||||
|
var il = dynamicMethod.GetILGenerator();
|
||||||
|
|
||||||
|
if (instanceGetter != null)
|
||||||
|
{
|
||||||
|
il.Emit(OpCodes.Ldarg_0);
|
||||||
|
il.Emit(OpCodes.Call, instanceGetter);
|
||||||
|
il.Emit(OpCodes.Ldfld, field);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
il.Emit(OpCodes.Ldsfld, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
postProcess?.Invoke(il);
|
||||||
|
|
||||||
|
il.Emit(OpCodes.Ret);
|
||||||
|
|
||||||
|
var func = dynamicMethod.CreateDelegate<Func<int, bool>>();
|
||||||
|
return index => () => func(index);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Error($"Member {MemberName} of {type.FullName} is not valid for Visibility function.");
|
Error($"Member {MemberName} of {type.FullName} is not valid for Visibility function.");
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ public class ModdedEnumOption : ModdedOption<int>
|
|||||||
stringOption.SetUpFromData(Data, 20);
|
stringOption.SetUpFromData(Data, 20);
|
||||||
stringOption.OnValueChanged = (Il2CppSystem.Action<OptionBehaviour>)ValueChanged;
|
stringOption.OnValueChanged = (Il2CppSystem.Action<OptionBehaviour>)ValueChanged;
|
||||||
|
|
||||||
|
// Changing the button text to make them more distinct from number options
|
||||||
|
stringOption.MinusBtn.ChangeButtonText("<");
|
||||||
|
stringOption.PlusBtn.ChangeButtonText(">");
|
||||||
|
|
||||||
// SetUpFromData method doesn't work correctly so we must set the values manually
|
// SetUpFromData method doesn't work correctly so we must set the values manually
|
||||||
stringOption.Title = StringName;
|
stringOption.Title = StringName;
|
||||||
stringOption.Values = (Data as StringGameSetting)?.Values ?? new Il2CppStructArray<StringNames>(0);
|
stringOption.Values = (Data as StringGameSetting)?.Values ?? new Il2CppStructArray<StringNames>(0);
|
||||||
|
|||||||
Reference in new issue
Block a user