mirror of
https://github.com/RHeavenStudio/HeavenStudio.git
synced 2025-06-13 01:37:40 +02:00
also use sourcegen for controller loaders
This commit is contained in:
130
Assets/Scripts/SourceGenerators/ControllerLoaderGenerator.cs
Normal file
130
Assets/Scripts/SourceGenerators/ControllerLoaderGenerator.cs
Normal file
@ -0,0 +1,130 @@
|
||||
using static SatorImaging.UnitySourceGenerator.USGFullNameOf;
|
||||
using SatorImaging.UnitySourceGenerator;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using Debug = UnityEngine.Debug;
|
||||
using Object = UnityEngine.Object;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
using HeavenStudio;
|
||||
using HeavenStudio.InputSystem;
|
||||
|
||||
// HOW TO USE: Add the following attribute to *target* class.
|
||||
// Note that target class must be defined as partial.
|
||||
//[UnitySourceGenerator(typeof(ControllerLoaderGenerator), OverwriteIfFileExists = false)]
|
||||
public partial class ControllerLoaderGenerator
|
||||
{
|
||||
#if UNITY_EDITOR // USG: class definition is required to avoid build error but methods are not.
|
||||
#pragma warning disable IDE0051
|
||||
|
||||
readonly static string MEMBER_ACCESS = "public static";
|
||||
readonly static string MAIN_MEMBER_NAME = "InitInputControllers";
|
||||
static string OutputFileName() => MAIN_MEMBER_NAME + ".cs"; // -> Name.<TargetClass>.<GeneratorClass>.g.cs
|
||||
|
||||
static bool Emit(USGContext context, StringBuilder sb)
|
||||
{
|
||||
List<PlayerInput.InputControllerInitializer> loadRunners = Assembly.GetExecutingAssembly()
|
||||
.GetTypes()
|
||||
.Where(x => x.Namespace == "HeavenStudio.InputSystem.Loaders" && x.GetMethod("Initialize", BindingFlags.Public | BindingFlags.Static) != null)
|
||||
.Select(t => (PlayerInput.InputControllerInitializer)Delegate.CreateDelegate(
|
||||
typeof(PlayerInput.InputControllerInitializer),
|
||||
null,
|
||||
t.GetMethod("Initialize", BindingFlags.Public | BindingFlags.Static),
|
||||
false
|
||||
))
|
||||
.ToList();
|
||||
|
||||
// USG: static classes are IsAbstract is set.
|
||||
if (!context.TargetClass.IsClass)
|
||||
return false; // return false to tell USG doesn't write file.
|
||||
|
||||
// USG: you can modify output path. default file name is that USG generated.
|
||||
// note that USG doesn't care the modified path is valid or not.
|
||||
//context.OutputPath += "_MyFirstTest.txt";
|
||||
|
||||
// USG: EditorUtility.DisplayDialog() or others don't work in batch mode.
|
||||
// throw if method depending on GUI based functions.
|
||||
//if (UnityEngine.Application.isBatchMode)
|
||||
// throw new System.NotSupportedException("GUI based functions do nothing in batch mode.");
|
||||
|
||||
// USG: write content into passed StringBuilder.
|
||||
sb.Append($@"
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using HeavenStudio.InputSystem;
|
||||
using HeavenStudio.InputSystem.Loaders;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
namespace {context.TargetClass.Namespace}
|
||||
{{
|
||||
partial class {context.TargetClass.Name}
|
||||
{{
|
||||
");
|
||||
// class open ----------------------------------------------------------------------
|
||||
|
||||
|
||||
#region // USG: MainMember
|
||||
sb.Append($@"
|
||||
{MEMBER_ACCESS} int {MAIN_MEMBER_NAME}()
|
||||
{{
|
||||
");
|
||||
sb.IndentLevel(3);
|
||||
|
||||
sb.Append($@"
|
||||
InputController[] controllers;
|
||||
PlayerInputRefresh = new();
|
||||
");
|
||||
|
||||
foreach (var loadRunner in loadRunners)
|
||||
{
|
||||
MethodInfo methodInfo = RuntimeReflectionExtensions.GetMethodInfo(loadRunner);
|
||||
string callingClass = methodInfo.DeclaringType.Name;
|
||||
string method = methodInfo.Name;
|
||||
string fullMethodLabel = $"{callingClass}.{method}";
|
||||
|
||||
sb.Append($@"
|
||||
controllers = {fullMethodLabel}();
|
||||
if (controllers != null)
|
||||
{{
|
||||
inputDevices.AddRange(controllers);
|
||||
}}
|
||||
else
|
||||
{{
|
||||
Debug.Log(""{fullMethodLabel} had no controllers to initialize."");
|
||||
}}
|
||||
");
|
||||
}
|
||||
|
||||
sb.Append($@"
|
||||
return inputDevices.Count;
|
||||
");
|
||||
|
||||
// USG: semicolon?
|
||||
sb.Append($@"
|
||||
}}
|
||||
");
|
||||
#endregion
|
||||
|
||||
|
||||
// class close ----------------------------------------------------------------------
|
||||
sb.Append($@"
|
||||
}}
|
||||
}}
|
||||
");
|
||||
|
||||
// USG: return true to tell USG to write content into OutputPath. false to do nothing.
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma warning restore IDE0051
|
||||
#endif
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 92162f67b41995a438008f78a72baba2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
118
Assets/Scripts/SourceGenerators/MinigameLoaderGenerator.cs
Normal file
118
Assets/Scripts/SourceGenerators/MinigameLoaderGenerator.cs
Normal file
@ -0,0 +1,118 @@
|
||||
using static SatorImaging.UnitySourceGenerator.USGFullNameOf;
|
||||
using SatorImaging.UnitySourceGenerator;
|
||||
using System.Text;
|
||||
using Debug = UnityEngine.Debug;
|
||||
using Object = UnityEngine.Object;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using HeavenStudio;
|
||||
|
||||
// HOW TO USE: Add the following attribute to *target* class.
|
||||
// Note that target class must be defined as partial.
|
||||
//[UnitySourceGenerator(typeof(MinigameLoaderGenerator), OverwriteIfFileExists = false)]
|
||||
public partial class MinigameLoaderGenerator
|
||||
{
|
||||
#if UNITY_EDITOR // USG: class definition is required to avoid build error but methods are not.
|
||||
#pragma warning disable IDE0051
|
||||
|
||||
readonly static string MEMBER_ACCESS = "public static";
|
||||
readonly static string MAIN_MEMBER_NAME = "LoadMinigames";
|
||||
static string OutputFileName() => MAIN_MEMBER_NAME + ".cs"; // -> Name.<TargetClass>.<GeneratorClass>.g.cs
|
||||
|
||||
static bool Emit(USGContext context, StringBuilder sb)
|
||||
{
|
||||
List<Func<EventCaller, Minigames.Minigame>> loadRunners = Assembly.GetExecutingAssembly()
|
||||
.GetTypes()
|
||||
.Where(x => x.Namespace == "HeavenStudio.Games.Loaders" && x.GetMethod("AddGame", BindingFlags.Public | BindingFlags.Static) != null)
|
||||
.Select(t => (Func<EventCaller, Minigames.Minigame>)Delegate.CreateDelegate(
|
||||
typeof(Func<EventCaller, Minigames.Minigame>),
|
||||
null,
|
||||
t.GetMethod("AddGame", BindingFlags.Public | BindingFlags.Static),
|
||||
false
|
||||
))
|
||||
.ToList();
|
||||
|
||||
// USG: static classes are IsAbstract is set.
|
||||
if (!context.TargetClass.IsClass)
|
||||
return false; // return false to tell USG doesn't write file.
|
||||
|
||||
// USG: you can modify output path. default file name is that USG generated.
|
||||
// note that USG doesn't care the modified path is valid or not.
|
||||
//context.OutputPath += "_MyFirstTest.txt";
|
||||
|
||||
// USG: EditorUtility.DisplayDialog() or others don't work in batch mode.
|
||||
// throw if method depending on GUI based functions.
|
||||
//if (UnityEngine.Application.isBatchMode)
|
||||
// throw new System.NotSupportedException("GUI based functions do nothing in batch mode.");
|
||||
|
||||
// USG: write content into passed StringBuilder.
|
||||
sb.Append($@"
|
||||
using Debug = UnityEngine.Debug;
|
||||
using HeavenStudio.Games.Loaders;
|
||||
|
||||
namespace {context.TargetClass.Namespace}
|
||||
{{
|
||||
static partial class {context.TargetClass.Name}
|
||||
{{
|
||||
");
|
||||
// class open ----------------------------------------------------------------------
|
||||
|
||||
|
||||
#region // USG: MainMember
|
||||
sb.Append($@"
|
||||
{MEMBER_ACCESS} void {MAIN_MEMBER_NAME}(EventCaller eventCaller)
|
||||
{{
|
||||
");
|
||||
sb.IndentLevel(3);
|
||||
|
||||
sb.Append($@"
|
||||
Minigames.Minigame game;
|
||||
");
|
||||
|
||||
foreach (var loadRunner in loadRunners)
|
||||
{
|
||||
MethodInfo methodInfo = RuntimeReflectionExtensions.GetMethodInfo(loadRunner);
|
||||
string callingClass = methodInfo.DeclaringType.Name;
|
||||
string method = methodInfo.Name;
|
||||
string fullMethodLabel = $"{callingClass}.{method}";
|
||||
|
||||
sb.Append($@"
|
||||
Debug.Log(""Running game loader {callingClass}"");
|
||||
game = {fullMethodLabel}(eventCaller);
|
||||
if (game != null)
|
||||
{{
|
||||
eventCaller.minigames.Add(game.name, game);
|
||||
}}
|
||||
else
|
||||
{{
|
||||
Debug.LogWarning(""Game loader {callingClass} failed!"");
|
||||
}}
|
||||
");
|
||||
}
|
||||
|
||||
// USG: semicolon?
|
||||
sb.Append($@"
|
||||
}}
|
||||
");
|
||||
#endregion
|
||||
|
||||
|
||||
// class close ----------------------------------------------------------------------
|
||||
sb.Append($@"
|
||||
}}
|
||||
}}
|
||||
");
|
||||
|
||||
// USG: return true to tell USG to write content into OutputPath. false to do nothing.
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma warning restore IDE0051
|
||||
#endif
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ca52f3b3768be34293826705b5cdf6c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user