field support

This commit is contained in:
Az committed 2026-10-15 02:58:01 -04:00
1 parent f433454fe6
commit f08a00ded7
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;
type = holderType ?? groupType;
MemberName ??= $"{property.Name}{defaultSuffix}";
MemberName ??= property.Name + defaultSuffix;
if (type.IsAssignableTo(typeof(AbstractOptionGroup)))
{
@@ -59,13 +59,24 @@ public abstract class ModdedOptionMemberAttribute(string? memberName, Type? hold
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;
if (method is { IsStatic: true })
instanceGetter = null;
isStatic = method is { IsStatic: true };
}
if (isStatic)
instanceGetter = null;
return member;
}
@@ -186,8 +197,8 @@ public abstract class ModdedOptionMemberAttribute(string? memberName, Type? hold
baseParamTypes,
delegateType,
suffix,
forwardParameters: baseParamTypes.Length > 0,
postProcessCall: postProcessCall);
baseParamTypes.Length > 0,
postProcessCall);
return _ => sharedDelegate;
}
@@ -202,11 +213,16 @@ public abstract class ModdedOptionMemberAttribute(string? memberName, Type? hold
for (byte i = 0; i < baseParamTypes.Length; i++)
{
if (i == 0) il.Emit(OpCodes.Ldarg_0);
else if (i == 1) il.Emit(OpCodes.Ldarg_1);
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 (i == 0)
il.Emit(OpCodes.Ldarg_0);
else if (i == 1)
il.Emit(OpCodes.Ldarg_1);
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)
@@ -71,6 +71,32 @@ public sealed class ModdedOptionVisibilityAttribute(string? memberName = null, T
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
{
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();
if (indexParams.Length > 1)
{
Error($"Indexer {MemberName} has too many parameters.");
@@ -178,6 +205,43 @@ public sealed class ModdedOptionVisibilityAttribute(string? memberName = null, T
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
{
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.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
stringOption.Title = StringName;
stringOption.Values = (Data as StringGameSetting)?.Values ?? new Il2CppStructArray<StringNames>(0);