Skip to content

Commit

Permalink
Merge pull request #99 from KuraiAndras/develop
Browse files Browse the repository at this point in the history
9.0.2
  • Loading branch information
KuraiAndras authored Oct 7, 2022
2 parents a7a9449 + 65bc667 commit b6eebfa
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 77 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 9.0.2
- Fix override handling when running the editor tool

# 9.0.1
- Fix Serilog Template

Expand Down
2 changes: 1 addition & 1 deletion MainProject/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>

<CurrentVersion>9.0.1</CurrentVersion>
<CurrentVersion>9.0.2</CurrentVersion>

<Version>$(CurrentVersion)</Version>
<PakcageVersion>$(CurrentVersion)</PakcageVersion>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "com.injecter.hosting.unity",
"version": "9.0.1",
"version": "9.0.2",
"displayName": "Injecter.Hosting.Unity",
"license": "MIT",
"licensesUrl": "https://github.com/KuraiAndras/Injecter/blob/master/LICENSE.md",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Injecter.Unity.Editor
{
internal delegate bool FilterGameObject(GameObject gameObject);
internal delegate void PatchGameObject(GameObject gameObject, string location);

internal static class GameObjectPatcher
{
public static void AddComponentsToEveryPrefab(FilterGameObject filter, PatchGameObject patch)
{
foreach (var prefabPath in AssetDatabase.GetAllAssetPaths().Where(s => s.EndsWith(".prefab")))
{
var prefab = AssetDatabase.LoadMainAssetAtPath(prefabPath);

if (prefab is GameObject prefabObject)
{
AddScriptsToGameObject(prefabObject, filter, patch, $"prefab: {prefabPath}");
AssetDatabase.SaveAssets();
}
}
}

public static void AddComponentsToCurrentScene(FilterGameObject filter, PatchGameObject patch)
{
var sceneName = SceneManager.GetActiveScene().name;

var rootObjects = SceneManager
.GetActiveScene()
.GetRootGameObjects();

foreach (var gameObject in rootObjects)
{
AddScriptsToGameObject(gameObject, filter, patch, $"scene: {sceneName}");
}
}

public static void AddComponentsToEveryScene(FilterGameObject filter, PatchGameObject patch)
{
var dataPathFull = Path.GetFullPath(Application.dataPath);
var scenes = Directory
.EnumerateFiles(dataPathFull, "*.unity", SearchOption.AllDirectories)
.Select(s => s.Replace(dataPathFull, string.Empty))
.Select(s => $"Assets{s}")
.ToArray();

var originalScenePath = SceneManager.GetActiveScene().path;
EditorSceneManager.SaveOpenScenes();

foreach (var scene in scenes)
{
EditorSceneManager.OpenScene(scene);
AddComponentsToCurrentScene(filter, patch);
EditorSceneManager.SaveOpenScenes();
}

EditorSceneManager.OpenScene(originalScenePath);
}

public static void AddComponentsToEverything(FilterGameObject filter, PatchGameObject patch)
{
AddComponentsToEveryPrefab(filter, patch);
AddComponentsToEveryScene(filter, patch);
}

public static void EnsureComponentSafe<T>(MonoBehaviour instance, GameObject holder, string location) where T : Component
{
if (instance.TryGetComponent<T>(out _)) return;

var component = Undo.AddComponent<T>(holder);

if (component == null) return;

if (PrefabUtility.IsAddedComponentOverride(component) && !PrefabUtility.IsAddedGameObjectOverride(holder))
{
Undo.DestroyObjectImmediate(component);
}
else
{
Debug.Log($"Adding script: {typeof(T).Name} to GameObjec: {holder.name} at {location}", holder);
}
}

private static void AddScriptsToGameObject(GameObject gameObject, FilterGameObject filter, PatchGameObject patch, string location)
{
var instances = gameObject
.GetComponentsInChildren<Transform>(true)
.Where(t => t != null && filter(t.gameObject))
.Select(t => t.gameObject)
.ToArray();

for (var i = 0; i < instances.Length; i++)
{
var instance = instances[i];
if (instance == null) continue;
patch(instance, location);
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Injecter.Unity.Editor
{
Expand All @@ -15,99 +12,49 @@ public static class MonoInjecterFinder
private static readonly Dictionary<Type, bool> _typeCache = new Dictionary<Type, bool>();

[MenuItem("Tools / Injecter / Ensure injection scripts in every prefab")]
public static void AddComponentsToEveryPrefab()
{
foreach (var prefabPath in AssetDatabase.GetAllAssetPaths().Where(s => s.EndsWith(".prefab")))
{
var prefab = AssetDatabase.LoadMainAssetAtPath(prefabPath);

if (prefab is GameObject prefabObject)
{
AddScriptsToGameObject(prefabObject, $"prefab: {prefabPath}");
AssetDatabase.SaveAssets();
}
}
}
public static void AddComponentsToEveryPrefab() => GameObjectPatcher.AddComponentsToEveryPrefab(FilterInjectables, AddScriptsToGameObject);

[MenuItem("Tools / Injecter / Ensure injection scripts in current scene")]
public static void AddComponentsToCurrentScene()
{
var sceneName = SceneManager.GetActiveScene().name;
public static void AddComponentsToCurrentScene() => GameObjectPatcher.AddComponentsToCurrentScene(FilterInjectables, AddScriptsToGameObject);

var rootObjects = SceneManager
.GetActiveScene()
.GetRootGameObjects();
[MenuItem("Tools / Injecter / Ensure injection scripts in every scene")]
public static void AddComponentsToEveryScene() => GameObjectPatcher.AddComponentsToEveryScene(FilterInjectables, AddScriptsToGameObject);

foreach (var gameObject in rootObjects)
{
AddScriptsToGameObject(gameObject, $"scene: {sceneName}");
}
}
[MenuItem("Tools / Injecter / Ensure injection scripts on everyting")]
public static void AddComponentsToEverything() => GameObjectPatcher.AddComponentsToEverything(FilterInjectables, AddScriptsToGameObject);

[MenuItem("Tools / Injecter / Ensure injection scripts in every scene")]
public static void AddComponentsToEveryScene()
private static bool FilterInjectables(GameObject gameObject) => gameObject
.GetComponents<MonoBehaviour>()
.Any(b => CanBeInjected(b));

private static bool CanBeInjected(MonoBehaviour component)
{
var dataPathFull = Path.GetFullPath(Application.dataPath);
var scenes = Directory
.EnumerateFiles(dataPathFull, "*.unity", SearchOption.AllDirectories)
.Select(s => s.Replace(dataPathFull, string.Empty))
.Select(s => $"Assets{s}")
.ToArray();
if (component == null) return false;

var originalScenePath = SceneManager.GetActiveScene().path;
EditorSceneManager.SaveOpenScenes();
var type = component.GetType();

foreach (var scene in scenes)
if (!_typeCache.TryGetValue(type, out var isInjectable))
{
EditorSceneManager.OpenScene(scene);
AddComponentsToCurrentScene();
EditorSceneManager.SaveOpenScenes();
var members = TypeHelpers.GetInjectableMembers(type);
isInjectable = members.Count != 0;
_typeCache.Add(type, isInjectable);
}

EditorSceneManager.OpenScene(originalScenePath);
}

[MenuItem("Tools / Injecter / Ensure injection scripts on everyting")]
public static void AddComponentsToEverything()
{
AddComponentsToEveryPrefab();
AddComponentsToEveryScene();
return isInjectable;
}

private static void AddScriptsToGameObject(GameObject gameObject, string location)
{
var instances = gameObject
.GetComponentsInChildren<MonoBehaviour>(true)
.Where(b => b != null)
.Where(b =>
{
var type = b.GetType();

if (!_typeCache.TryGetValue(type, out var isInjectable))
{
var members = TypeHelpers.GetInjectableMembers(type);
isInjectable = members.Count != 0;
_typeCache.Add(type, isInjectable);
}

return isInjectable;
})
.Where(b => CanBeInjected(b))
.ToArray();

for (var i = 0; i < instances.Length; i++)
{
var instance = instances[i];
EnsureComponent<MonoInjector>(instance, location);
EnsureComponent<MonoDisposer>(instance, location);
}
}

private static void EnsureComponent<T>(MonoBehaviour instance, string location) where T : Component
{
if (!instance.gameObject.TryGetComponent<T>(out var _))
{
Debug.Log($"Adding script: {typeof(T).Name} to GameObjec: {instance.gameObject.name} at {location}");
Undo.AddComponent<T>(instance.gameObject);
GameObjectPatcher.EnsureComponentSafe<MonoInjector>(instance, gameObject, location);
GameObjectPatcher.EnsureComponentSafe<MonoDisposer>(instance, gameObject, location);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "com.injecter.unity",
"version": "9.0.1",
"version": "9.0.2",
"displayName": "Injecter.Unity",
"license": "MIT",
"licensesUrl": "https://github.com/KuraiAndras/Injecter/blob/master/LICENSE.md",
Expand Down

0 comments on commit b6eebfa

Please sign in to comment.