浏览代码

Almost Working Call Tree WIndow

/main
Thomas ICHÉ 5 年前
当前提交
afb040d1
共有 7 个文件被更改,包括 603 次插入24 次删除
  1. 237
      Editor/CallTree/CallTreeWindow.cs
  2. 5
      Icons/Actions/ic-action-generic.png
  3. 110
      Icons/Actions/ic-action-generic.png.meta
  4. 4
      Icons/Events/ic-event-generic.png
  5. 115
      Icons/Events/ic-event-generic.png.meta
  6. 41
      Icons/Misc/ic-callable.png
  7. 115
      Icons/Misc/ic-callable.png.meta

237
Editor/CallTree/CallTreeWindow.cs


using System.Collections;
using System.Linq;
using System;
using System.Reflection;
using UnityEditor.SceneManagement;
using GameplayIngredients.Events;
using GameplayIngredients.Logic;
using GameplayIngredients.Actions;
using GameplayIngredients.StateMachines;
using UnityEngine.SceneManagement;
namespace GameplayIngredients
{

GetWindow<CallTreeWindow>();
}
protected List<MonoBehaviour> m_Watches;
m_Watches = new List<MonoBehaviour>();
m_TreeView = new CallTreeView(m_Watches);
m_TreeView.Reload();
nodeRoots = new List<CallTreeNode>();
m_TreeView = new CallTreeView(nodeRoots);
BuildCallTree();
EditorSceneManager.sceneOpened += Reload;
}
void Reload(Scene scene, OpenSceneMode mode)
{
BuildCallTree();
using(new GUILayout.HorizontalScope(EditorStyles.toolbar, GUILayout.Height(tbHeight)))
using (new GUILayout.HorizontalScope(EditorStyles.toolbar, GUILayout.Height(tbHeight)))
if(GUILayout.Button("Get",EditorStyles.toolbarButton))
if (GUILayout.Button("Update", EditorStyles.toolbarButton))
Debug.Log("Get");
BuildCallTree();
}
GUILayout.FlexibleSpace();
}

List<CallTreeNode> nodeRoots;
void BuildCallTree()
{
if (nodeRoots == null)
nodeRoots = new List<CallTreeNode>();
else
nodeRoots.Clear();
var allEvents = Resources.FindObjectsOfTypeAll<EventBase>().ToList();
var allStateMachines = Resources.FindObjectsOfTypeAll<StateMachine>().ToList();
foreach (var evt in allEvents)
{
nodeRoots.Add(GetNode(evt));
}
foreach (var sm in allStateMachines)
{
nodeRoots.Add(GetStateMachineNode(sm));
}
m_TreeView.Reload();
}
CallTreeNode GetNode(MonoBehaviour bhv)
{
var rootNode = new CallTreeNode(bhv, GetType(bhv), $"{bhv.gameObject.name} : {bhv.GetType().Name}");
var type = bhv.GetType();
foreach (var field in type.GetFields())
{
// Find Fields that are Callable[]
if (field.FieldType.IsAssignableFrom(typeof(Callable[])))
{
var node = new CallTreeNode(bhv, CallTreeNodeType.Callable, field.Name);
rootNode.Children.Add(node);
// Add Callables from this Callable[] array
var value = (Callable[])field.GetValue(bhv);
foreach (var call in value)
{
node.Children.Add(GetNode(call));
}
}
}
return rootNode;
}
CallTreeNode GetStateMachineNode(StateMachine sm)
{
var rootNode = new CallTreeNode(sm, CallTreeNodeType.StateMachine, sm.gameObject.name);
var type = sm.GetType();
foreach (var field in type.GetFields())
{
// Find Fields that are State[]
if (field.FieldType.IsAssignableFrom(typeof(State[])))
{
// Add Callables from this Callable[] array
var value = (State[])field.GetValue(sm);
foreach (var state in value)
{
rootNode.Children.Add(GetStateNode(state));
}
}
}
return rootNode;
}
CallTreeNode GetStateNode(State st)
{
var rootNode = new CallTreeNode(st, CallTreeNodeType.State, st.gameObject.name);
var type = st.GetType();
foreach (var field in type.GetFields())
{
// Find Fields that are Callable[]
if (field.FieldType.IsAssignableFrom(typeof(Callable[])))
{
var node = new CallTreeNode(st, CallTreeNodeType.Callable, field.Name);
rootNode.Children.Add(node);
// Add Callables from this Callable[] array
var value = (Callable[])field.GetValue(st);
foreach (var call in value)
{
node.Children.Add(GetNode(call));
}
}
}
return rootNode;
}
CallTreeNodeType GetType(MonoBehaviour bhv)
{
if (bhv == null)
return CallTreeNodeType.Callable;
if (bhv is EventBase)
return CallTreeNodeType.Event;
else if (bhv is LogicBase)
return CallTreeNodeType.Logic;
else if (bhv is ActionBase)
return CallTreeNodeType.Action;
else if (bhv is StateMachine)
return CallTreeNodeType.StateMachine;
else if (bhv is State)
return CallTreeNodeType.State;
else if (bhv is OnMessageEvent || bhv is SendMessageAction)
return CallTreeNodeType.Message;
else
return CallTreeNodeType.Callable;
}
public Texture Icon;
public GameObject Target;
public MonoBehaviour Target;
public enum CallTreeNodeType
public CallTreeNodeType Type;
public CallTreeNode(MonoBehaviour target, CallTreeNodeType type, string name = "")
Callable,
Event,
Logic,
Action,
Message,
StateMachine,
State
Name = string.IsNullOrEmpty(name) ? target.GetType().Name : name;
Target = target;
Type = type;
Children = new List<CallTreeNode>();
public enum CallTreeNodeType
{
Callable,
Event,
Logic,
Action,
Message,
StateMachine,
State
}
List<MonoBehaviour> m_Roots;
public CallTreeView(List<MonoBehaviour> roots) : base(new TreeViewState())
List<CallTreeNode> m_Roots;
Dictionary<int, CallTreeNode> m_Bindings;
public CallTreeView(List<CallTreeNode> roots) : base(new TreeViewState())
m_Bindings = new Dictionary<int, CallTreeNode>();
m_Bindings.Clear();
foreach(var bh in m_Roots)
foreach(var node in m_Roots)
var root_item = new TreeViewItem(id++, 0, bh.name);
treeRoot.AddChild(root_item);
treeRoot.AddChild(GetNode(node, ref id, 0));
}
TreeViewItem GetNode(CallTreeNode node, ref int id, int depth)
{
var item = new TreeViewItem(id++, depth, $"{node.Name} ({node.Type})");
item.icon = GetIcon(node.Type);
m_Bindings.Add(id, node);
foreach(var child in node.Children)
{
item.AddChild(GetNode(child, ref id, depth + 1));
}
return item;
}
Texture2D GetIcon(CallTreeNodeType type)
{
switch(type)
{
default:
case CallTreeNodeType.Callable:
return Styles.Callable;
case CallTreeNodeType.Action:
return Styles.Action;
case CallTreeNodeType.Logic:
return Styles.Logic;
case CallTreeNodeType.Event:
return Styles.Event;
case CallTreeNodeType.Message:
return Styles.Message;
case CallTreeNodeType.State:
return Styles.State;
case CallTreeNodeType.StateMachine:
return Styles.StateMachine;
}
}
protected override void SelectionChanged(IList<int> selectedIds)
{
base.SelectionChanged(selectedIds);
if (selectedIds.Count > 0)
Selection.activeObject = m_Bindings[selectedIds[0]].Target;
}
static class Styles
{
public static Texture2D Callable = Icon("Misc/ic-callable.png");
public static Texture2D Action = Icon("Actions/ic-action-generic.png");
public static Texture2D Logic = Icon("Logic/ic-generic-logic.png");
public static Texture2D Event = Icon("Events/ic-event-generic.png");
public static Texture2D Message = Icon("Events/ic-event-message .png");
public static Texture2D StateMachine = Icon("Misc/ic-StateMachine.png");
public static Texture2D State = Icon("Misc/ic-State.png");
static Texture2D Icon(string path)
{
return AssetDatabase.LoadAssetAtPath<Texture2D>($"Packages/net.peeweek.gameplay-ingredients/Icons/{path}");
}
}
}
}

5
Icons/Actions/ic-action-generic.png

之前 之后
宽度: 16  |  高度: 16  |  大小: 669 B

110
Icons/Actions/ic-action-generic.png.meta


fileFormatVersion: 2
guid: 68fdae855e346504b8884bfb6d7756cd
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

4
Icons/Events/ic-event-generic.png

之前 之后
宽度: 16  |  高度: 16  |  大小: 766 B

115
Icons/Events/ic-event-generic.png.meta


fileFormatVersion: 2
guid: 5beb76c73e9d9f34aa9f1092912301db
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

41
Icons/Misc/ic-callable.png

之前 之后
宽度: 16  |  高度: 16  |  大小: 1.7 KiB

115
Icons/Misc/ic-callable.png.meta


fileFormatVersion: 2
guid: 322030000d8e32240a902f51e3971ef3
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存