Skip to content

Commit

Permalink
Merge pull request #2 from innogames/v1.1.1
Browse files Browse the repository at this point in the history
V1.1.1
  • Loading branch information
pak762 authored Jul 3, 2020
2 parents 78cdaf0 + 0993e9f commit fde441f
Show file tree
Hide file tree
Showing 16 changed files with 93 additions and 57 deletions.
53 changes: 34 additions & 19 deletions AssetRelationsViewer/Editor/AssetRelationsViewerWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private class MergedNode
private int _maxHierarchyDepth = 64;

private VisualizationNode _nodeStructure = null;
private CacheStateContext _cacheStateContext = new CacheStateContext();
private NodeDependencyLookupContext _nodeDependencyLookupContext = new NodeDependencyLookupContext();
private Dictionary<string, VisualizationNodeData> _cachedVisualizationNodeDatas = new Dictionary<string, VisualizationNodeData>();
private Dictionary<string, AssetCacheData> _cachedNodes = new Dictionary<string, AssetCacheData>();

Expand Down Expand Up @@ -132,32 +132,34 @@ public void OnEnable()

SetHandlerSelection();

InitNodeHandlerContext();
SetNodeHandlerContext();
}

private void LoadDependencyCache(bool update = true)
{
_cacheStateContext.Reset();
_nodeDependencyLookupContext.Reset();

CacheUsageDefinitionList cacheUsageDefinitionList = CreateCacheUsageList();
ResolverUsageDefinitionList resolverUsageDefinitionList = CreateCacheUsageList();

ProgressBase progress = new ProgressBase(null);
progress.SetProgressFunction((title, info, value) => EditorUtility.DisplayProgressBar(title, info, value));

NodeDependencyLookupUtility.LoadDependencyLookupForCaches(_cacheStateContext, cacheUsageDefinitionList, progress, true, update);
NodeDependencyLookupUtility.LoadDependencyLookupForCaches(_nodeDependencyLookupContext, resolverUsageDefinitionList, progress, true, update);

SetNodeHandlerContext();
}

private void InitNodeHandlerContext()
private void SetNodeHandlerContext()
{
foreach (ITypeHandler handler in _typeHandlers)
{
handler.InitContext(_cacheStateContext, this);
handler.InitContext(_nodeDependencyLookupContext, this);
}
}

private CacheUsageDefinitionList CreateCacheUsageList()
private ResolverUsageDefinitionList CreateCacheUsageList()
{
CacheUsageDefinitionList cacheUsageDefinitionList = new CacheUsageDefinitionList();
ResolverUsageDefinitionList resolverUsageDefinitionList = new ResolverUsageDefinitionList();

foreach (CacheState state in _cacheStates)
{
Expand All @@ -176,13 +178,13 @@ private CacheUsageDefinitionList CreateCacheUsageList()
activeConnectionTypes.Add(connectionType);
}

cacheUsageDefinitionList.Add(state.Cache.GetType(), resolverState.Resolver.GetType(), activeConnectionTypes);
resolverUsageDefinitionList.Add(state.Cache.GetType(), resolverState.Resolver.GetType(), activeConnectionTypes);
}
}
}
}

return cacheUsageDefinitionList;
return resolverUsageDefinitionList;
}

private void HandleFirstStartup()
Expand Down Expand Up @@ -230,6 +232,13 @@ public void InvalidateNodeStructure()
public void OnAssetSelectionChanged()
{
string assetPath = AssetDatabase.GetAssetPath(Selection.activeObject);

// Make sure Selection.activeObject is an asset
if (string.IsNullOrEmpty(assetPath))
{
return;
}

string guid = AssetDatabase.AssetPathToGUID(assetPath);

ChangeSelection(guid, "Asset");
Expand Down Expand Up @@ -705,7 +714,7 @@ private void PrepareSubTree(RelationType relationType)

private void DrawHierarchy()
{
if (_cacheStateContext == null)
if (_nodeDependencyLookupContext == null)
{
DrawNotLoadedError();
return;
Expand All @@ -717,7 +726,7 @@ private void DrawHierarchy()
return;
}

Node entry = _cacheStateContext.RelationsLookup.GetNode(_selectedId, _selectedType);
Node entry = _nodeDependencyLookupContext.RelationsLookup.GetNode(_selectedId, _selectedType);

if (entry == null)
{
Expand Down Expand Up @@ -746,12 +755,12 @@ private VisualizationNodeData AddNodeCacheForNode(string id, string type)
ITypeHandler typeHandler = GetTypeHandlerForType(type);

VisualizationNodeData data = typeHandler.CreateNodeCachedData(id);
_cacheStateContext.NodeHandlerLookup = GetNodeHandlerLookup();
_nodeDependencyLookupContext.NodeHandlerLookup = GetNodeHandlerLookup();

if (_showThumbnails || DisplayData.ShowAdditionalInformation)
{
data.OwnSize = NodeDependencyLookupUtility.GetNodeSize(true, false, id, type, new HashSet<string>(), _cacheStateContext);
data.HierarchySize = NodeDependencyLookupUtility.GetNodeSize(true, true, id, type, new HashSet<string>(), _cacheStateContext);
data.OwnSize = NodeDependencyLookupUtility.GetNodeSize(true, false, id, type, new HashSet<string>(), _nodeDependencyLookupContext);
data.HierarchySize = NodeDependencyLookupUtility.GetNodeSize(true, true, id, type, new HashSet<string>(), _nodeDependencyLookupContext);
}

data.Id = id;
Expand All @@ -762,7 +771,7 @@ private VisualizationNodeData AddNodeCacheForNode(string id, string type)

data.Name = typeHandler.GetName(id);
data.IsEditorAsset = nodeHandler.IsNodeEditorOnly(id, type);
data.IsPackedToApp = NodeDependencyLookupUtility.IsNodePackedToApp(id, type, _cacheStateContext, new HashSet<string>());
data.IsPackedToApp = NodeDependencyLookupUtility.IsNodePackedToApp(id, type, _nodeDependencyLookupContext, new HashSet<string>());

_cachedVisualizationNodeDatas.Add(key, data);
}
Expand Down Expand Up @@ -857,7 +866,7 @@ public static RelationType InvertRelationType(RelationType relationType)

public Color GetConnectionColorForType(string typeId)
{
return _cacheStateContext.ConnectionTypeLookup.GetDependencyType(typeId).Colour;
return _nodeDependencyLookupContext.ConnectionTypeLookup.GetDependencyType(typeId).Colour;
}

private void InvalidateNodePositionData(VisualizationNodeBase node, RelationType relationType)
Expand Down Expand Up @@ -1069,9 +1078,15 @@ public void CreateNodeHierarchyRec(HashSet<string> addedVisualizationNodes, Stac
private void AddBidirConnection(RelationType relationType, VisualizationNodeBase node, VisualizationNodeBase target,
List<VisualizationConnection.Data> datas, bool isRecursion)
{
if (_nodeDisplayOptions.ShowPropertyPathes && VisualizationConnection.HasPathSegments(datas))
if (_nodeDisplayOptions.ShowPropertyPathes)
{
PathVisualizationNode pathVisualizationNode = new PathVisualizationNode();

if (!VisualizationConnection.HasPathSegments(datas))
{
datas = new List<VisualizationConnection.Data>();
datas.Add(new VisualizationConnection.Data("UnknownPath", new []{new PathSegment("Unknown Path", PathSegmentType.Unknown)}));
}

node.AddRelation(relationType, new VisualizationConnection(datas, pathVisualizationNode, false));
pathVisualizationNode.AddRelation(InvertRelationType(relationType), new VisualizationConnection(datas, node, false));
Expand Down
2 changes: 1 addition & 1 deletion AssetRelationsViewer/Editor/AssetTypeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void OnSelectAsset(string id, string type)
}
}

public void InitContext(CacheStateContext cacheStateContext, AssetRelationsViewerWindow window)
public void InitContext(NodeDependencyLookupContext nodeDependencyLookupContext, AssetRelationsViewerWindow window)
{
_viewerWindow = window;
_filteredNodes = CreateFilter(_filterString);
Expand Down
2 changes: 1 addition & 1 deletion AssetRelationsViewer/Editor/ITypeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public interface ITypeHandler

void OnSelectAsset(string id, string type);

void InitContext(CacheStateContext cacheStateContext, AssetRelationsViewerWindow viewerWindow);
void InitContext(NodeDependencyLookupContext nodeDependencyLookupContext, AssetRelationsViewerWindow viewerWindow);

bool HandlesCurrentNode();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public override void Draw(int depth, RelationType relationType, ITypeColorProvid

if (displayData.ShowAdditionalInformation)
{
string text = string.Format("Own: {0} kb | Tree: {1} kb ", NodeData.OwnSize, NodeData.HierarchySize);
string text = string.Format("Size: {0}kb | TreeSize: {1}kb ", NodeData.OwnSize, NodeData.HierarchySize);
GUI.Label(new Rect(position.x + assetPreviewSize, position.y + 16, 200, 16), text);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ public override void TraverseObject(string id, Object obj, Stack<PathSegment> st

do
{
if (property.type == "char")
{
continue;
}

if (!onlyOverriden || property.prefabOverride)
{
string propertyPath = property.propertyPath;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ namespace Com.Innogames.Core.Frontend.NodeDependencyLookup
* The CacheStateContext holds all information after the Caches updates
* This is to reduce the amount of parameters needing to be passed to the functions because most of the time they need all member values
*/
public class CacheStateContext
public class NodeDependencyLookupContext
{
private static Dictionary<string, CacheStateContext> m_stateContexts = new Dictionary<string, CacheStateContext>();
private static Dictionary<string, NodeDependencyLookupContext> m_stateContexts = new Dictionary<string, NodeDependencyLookupContext>();

public RelationLookup.RelationsLookup RelationsLookup = new RelationLookup.RelationsLookup();
public Dictionary<string, INodeHandler> NodeHandlerLookup = new Dictionary<string, INodeHandler>();
public ConnectionTypeLookup ConnectionTypeLookup;
public Dictionary<string, CreatedDependencyCache> CreatedCaches = new Dictionary<string, CreatedDependencyCache>();

public static CacheStateContext GetStateContextForName(string name)
public static NodeDependencyLookupContext GetStateContextForName(string name)
{
if(!m_stateContexts.ContainsKey(name))
m_stateContexts.Add(name, new CacheStateContext());
m_stateContexts.Add(name, new NodeDependencyLookupContext());

return m_stateContexts[name];
}
Expand All @@ -37,11 +37,11 @@ public void Reset()
ConnectionTypeLookup = null;
}

public void UpdateFromDefinition(CacheUsageDefinitionList definitionList)
public void UpdateFromDefinition(ResolverUsageDefinitionList definitionList)
{
ResetCacheUsages();

foreach (CacheUsageDefinitionList.Entry entry in definitionList.CacheUsages)
foreach (ResolverUsageDefinitionList.Entry entry in definitionList.CacheUsages)
{
string cacheTypeFullName = entry.CacheType.FullName;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ public class ObjectSerializedDependencyResolver : IAssetDependencyResolver

public void GetDependenciesForId(string guid, List<Dependency> dependencies)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
string[] assetDatabaseDependencies = AssetDatabase.GetDependencies(path, false).Select(AssetDatabase.AssetPathToGUID).ToArray();

List<Dependency> subSystemDependencies = new List<Dependency>();
HashSet<string> foundDependenciesHashSet = new HashSet<string>();

Expand All @@ -36,15 +33,6 @@ public void GetDependenciesForId(string guid, List<Dependency> dependencies)
foundDependenciesHashSet.Add(dependency.Id);
dependencies.Add(dependency);
}

foreach (string dguid in assetDatabaseDependencies)
{
if (!foundDependenciesHashSet.Contains(dguid))
{
PathSegment pathSegment = new PathSegment("Unknown Path", PathSegmentType.Unknown);
dependencies.Add(new Dependency(dguid, ResolvedType, NodeType, new []{pathSegment}));
}
}
}

public void GetDependenciesForIdFromSerializedPropertyTraverser(string guid, List<Dependency> dependencies)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Com.Innogames.Core.Frontend.NodeDependencyLookup
///List to store which resolvers will be used when creating the dependency structure.
///Only the given resolvers will be executed instead of executing all available ones
///</summary>
public class CacheUsageDefinitionList
public class ResolverUsageDefinitionList
{
internal class Entry
{
Expand Down
4 changes: 2 additions & 2 deletions NodeDependencyLookup/Editor/NodeHandler/AssetNodeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public string[] GetHandledNodeTypes()
return HandledTypes;
}

public int GetOwnFileSize(string id, string type, CacheStateContext stateContext)
public int GetOwnFileSize(string id, string type, NodeDependencyLookupContext stateContext)
{
return NodeDependencyLookupUtility.GetPackedAssetSize(id);
}
Expand Down Expand Up @@ -54,7 +54,7 @@ public bool ContributesToTreeSize()
return true;
}

public void InitContext(CacheStateContext cacheStateContext)
public void InitContext(NodeDependencyLookupContext nodeDependencyLookupContext)
{
// nothing to do
}
Expand Down
2 changes: 1 addition & 1 deletion NodeDependencyLookup/Editor/NodeHandler/INodeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public interface INodeHandler
// Returns which node types the handler handlers. For example "Asset"
string[] GetHandledNodeTypes();
// Returns the filesize if the node. In case of an asset it would be the serialized filesize
int GetOwnFileSize(string id, string type, CacheStateContext stateContext);
int GetOwnFileSize(string id, string type, NodeDependencyLookupContext stateContext);
// Returns if a node is packed to the app or not. Helpful to find out if an asset is actually used in the final game or not
bool IsNodePackedToApp(string id, string type);
// Returns if a node it just used within the editor. For assets this would be case if its in an editor folder
Expand Down
25 changes: 17 additions & 8 deletions NodeDependencyLookup/Editor/Utility/NodeDependencyLookupUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static void ClearCacheFiles()
[MenuItem("Window/Node Dependency Lookup/Clear Cached Contexts")]
public static void ClearCachedContexts()
{
CacheStateContext.ResetContexts();
NodeDependencyLookupContext.ResetContexts();
}

public static bool NeedsCacheUpdate(CreatedDependencyCache usage)
Expand All @@ -48,11 +48,11 @@ public static bool NeedsCacheUpdate(CreatedDependencyCache usage)
return false;
}

public static void LoadDependencyLookupForCaches(CacheStateContext stateContext,
CacheUsageDefinitionList cacheUsageDefinitionList, ProgressBase progress, bool loadCache = true,
public static void LoadDependencyLookupForCaches(NodeDependencyLookupContext stateContext,
ResolverUsageDefinitionList resolverUsageDefinitionList, ProgressBase progress, bool loadCache = true,
bool updateCache = true, bool saveCache = true, string fileDirectory = DEFAULT_CACHE_SAVE_PATH)
{
stateContext.UpdateFromDefinition(cacheUsageDefinitionList);
stateContext.UpdateFromDefinition(resolverUsageDefinitionList);

List<CreatedDependencyCache> caches = stateContext.GetCaches();

Expand Down Expand Up @@ -184,7 +184,16 @@ private static string GetAssetDatabaseVersion1LibraryDataPath(string guid)
/// Right now this only works if the asset or one of its parents (referencers) are in a packaged scene or in a resources folder.
/// If the asset is just in a bundle this is currently not tracked. Trying to find a solution for this.
/// </summary>
public static bool IsNodePackedToApp(string id, string type, CacheStateContext stateContext,
public static bool IsNodePackedToApp(string id, string type, NodeDependencyLookupContext stateContext)
{
return IsNodePackedToApp(id, type, stateContext, new HashSet<string>());
}

/// <summary>
/// Right now this only works if the asset or one of its parents (referencers) are in a packaged scene or in a resources folder.
/// If the asset is just in a bundle this is currently not tracked. Trying to find a solution for this.
/// </summary>
public static bool IsNodePackedToApp(string id, string type, NodeDependencyLookupContext stateContext,
HashSet<string> visitedKeys)
{
if (visitedKeys.Contains(id))
Expand Down Expand Up @@ -226,7 +235,7 @@ public static bool IsNodePackedToApp(string id, string type, CacheStateContext s
}

public static int GetNodeSize(bool own, bool tree, string id, string type, HashSet<string> traversedNodes,
CacheStateContext stateContext)
NodeDependencyLookupContext stateContext)
{
string key = GetNodeKey(id, type);

Expand Down Expand Up @@ -317,10 +326,10 @@ public static string GetNodeKey(string id, string type)
/**
* Return the dependency lookup for Objects using the SimpleObjectResolver
*/
public static void BuildDefaultAssetLookup(CacheStateContext stateContext, bool loadFromCache, string savePath,
public static void BuildDefaultAssetLookup(NodeDependencyLookupContext stateContext, bool loadFromCache, string savePath,
ProgressBase progress)
{
CacheUsageDefinitionList usageDefinitionList = new CacheUsageDefinitionList();
ResolverUsageDefinitionList usageDefinitionList = new ResolverUsageDefinitionList();
usageDefinitionList.Add<AssetDependencyCache, ObjectDependencyResolver>();

LoadDependencyLookupForCaches(stateContext, usageDefinitionList, progress, loadFromCache, true, false,
Expand Down
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,28 @@ The AssetRelationsViewer supports different resolvers to find dependencies for a
Uses Unitys internal AssetDatabase.GetDependencies() function to find dependencies for assets.
Its fast and reliable, but can only find dependencies between assets.

##### Known issues
Nested Prefabs or Prefab Variants arent handled correctly when using the ObjectDependencyResolver since it uses Unitys AssetDatabase.GetDependencies() function which wasnt updated for this.
The problem is that dependencies of nested prefabs will be shown as own for prefabs or scenes. This issue can be avoided by only using the SerializeObjectDependecyResolver which unfortunately is slower.
A feature request for Unity exists which hopefully fixed the mentioned issue with AssetDatabase.GetDependencies() in the future.

#### ObjectSerializedDependencyResolver
Uses own implementation which is based on SerializedObjects and SerializedProperties to find assets and other dependency types.
Since this solution is based on an own dependency search implementation, it is much slower than the ObjectDependencyResolver.

##### Known issues
The ObjectSerializedDependencyResolver can only find dependencies that are serialized in the asset. In theory it can be the case that AssetDatabase.GetDependencies() could return dependencies that cant be found by the ObjectSerializedDependencyResolver.

<br><br><br><br>
## Showing dependency pathes
If one wants to know where exactly in a scene, prefab, scriptable object a reference is done the "ObjectSerializedDependencyResolver" needs to be active and "Show Property Pathes" in the menu needs to be active.
Once active the whole path of the dependency (GameObject->Components->ClassMemberVariable) is shown.

#### Showing "Unknown Path" path nodes
This is due to the issue that the AssetDatabase.GetDependencies() function returns dependencies of nested prefabs as well as prefab variants even though the dependencies are not serialized within the asset itself.
This is why the ObjectSerializedDependencyResolver cant find these dependencies within the serialized properties of the asset itself while AssetDatabase.GetDependencies() still returns it for non recursive dependencies so the path is unknown.
First make sure to the ObjectSerializedDependencyResolver is activated since the ObjectDependencyResolver cant find any pathes so "Unknown path" is shown.
Also, if the ObjectSerializedDependencyResolver and ObjectDependencyResolver are active at the same time the ObjectDependencyResolver can find dependencies that the ObjectSerializedDependencyResolver didnt find.
This relates to the already mentioned issue with nested prefabs and the AssetDatabase.GetDependencies() function.


![](Docs~/Images/arv_example_pathes.png)

Expand All @@ -142,7 +152,10 @@ Support to display different connection and node types can be added by addons.

#### Addressable system
An addon is available to add support for showing addressables and also addressable groups from Unitys Addressables system.
The Package is called asset-relations-viewer-addressables
The Package is called asset-relations-viewer-addressables.
It can be found at https://github.com/innogames/asset-relations-viewer-addressables

#### Writing own addons to support custom connection- and nodetypes
Documentation on how to write own addons will be added later
Own addons can be also added so custom dependencies with any nodetype and dependency type can be added to be viewed inside the Asset Relations Viewer.
For seing how to add own addons, please have a look at the Addressable sytem addon source code.

Loading

0 comments on commit fde441f

Please sign in to comment.