Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
AssetReferenceAnalysis.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections;
5 using System.Collections.Generic;
6 using System.Runtime.CompilerServices;
7 
8 using SiliconStudio.Assets.Visitors;
9 using SiliconStudio.Core.IO;
10 using SiliconStudio.Core.Reflection;
11 using SiliconStudio.Core.Serialization;
12 
13 namespace SiliconStudio.Assets.Analysis
14 {
15  /// <summary>
16  /// This analysis provides a method for visiting asset and file references
17  /// (<see cref="IContentReference" /> or <see cref="UFile" /> or <see cref="UDirectory" />)
18  /// </summary>
20  {
21  private static readonly object CachingLock = new object();
22 
23  private static readonly Dictionary<object, List<AssetReferenceLink>> CachingReferences = new Dictionary<object, List<AssetReferenceLink>>();
24 
25  private static bool enableCaching;
26 
27  /// <summary>
28  /// Gets or sets the enable caching. Only used when loading packages
29  /// </summary>
30  /// <value>The enable caching.</value>
31  internal static bool EnableCaching
32  {
33  get
34  {
35  return enableCaching;
36  }
37  set
38  {
39  lock (CachingLock)
40  {
41  if (enableCaching != value)
42  {
43  CachingReferences.Clear();
44  }
45 
46  enableCaching = value;
47  }
48  }
49  }
50 
51  /// <summary>
52  /// Gets all references (subclass of <see cref="IContentReference" /> and <see cref="UFile" />) from the specified asset
53  /// </summary>
54  /// <param name="obj">The object.</param>
55  /// <returns>A list of references.</returns>
56  public static List<AssetReferenceLink> Visit(object obj)
57  {
58  if (obj == null) throw new ArgumentNullException("obj");
59 
60  List<AssetReferenceLink> assetReferences = null;
61 
62  lock (CachingLock)
63  {
64  if (enableCaching)
65  {
66  if (CachingReferences.TryGetValue(obj, out assetReferences))
67  {
68  assetReferences = new List<AssetReferenceLink>(assetReferences);
69  }
70  }
71  }
72 
73  if (assetReferences == null)
74  {
75  assetReferences = new List<AssetReferenceLink>();
76 
77  var assetReferenceVistor = new AssetReferenceVistor { References = assetReferences };
78  assetReferenceVistor.Visit(obj);
79 
80  lock (CachingLock)
81  {
82  if (enableCaching)
83  {
84  CachingReferences[obj] = assetReferences;
85  }
86  }
87  }
88 
89  return assetReferences;
90  }
91 
92  private class AssetReferenceVistor : AssetVisitorBase
93  {
94  public AssetReferenceVistor()
95  {
96  References = new List<AssetReferenceLink>();
97  }
98 
99  public List<AssetReferenceLink> References { get; set; }
100 
101  public override void VisitObject(object obj, ObjectDescriptor descriptor, bool visitMembers)
102  {
103  base.VisitObject(obj, descriptor, visitMembers);
104  var reference = obj as ContentReference;
105  if (reference != null)
106  {
107  AddLink(reference, (guid, location) =>
108  {
109  reference.Id = guid.HasValue ? guid.Value : reference.Id;
110  reference.Location = location;
111  return reference;
112  });
113  }
114  }
115 
116  public override void VisitArrayItem(Array array, ArrayDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor)
117  {
118  base.VisitArrayItem(array, descriptor, index, item, itemDescriptor);
119  var assetReference = item as AssetReference;
120  if (assetReference != null)
121  {
122  AddLink(item,
123  (guid, location) =>
124  {
125  var newValue = AssetReference.New(descriptor.ElementType, guid.HasValue ? guid.Value : assetReference.Id, location);
126  array.SetValue(newValue, index);
127  return newValue;
128  });
129  }
130  else
131  {
132  var assetBase = item as AssetBase;
133  if (assetBase != null)
134  {
135  AddLink(item,
136  (guid, location) =>
137  {
138  var newValue = new AssetBase(location, assetBase.Asset);
139  array.SetValue(newValue, index);
140  return newValue;
141  });
142  }
143  else if (item is UFile)
144  {
145  AddLink(item,
146  (guid, location) =>
147  {
148  var newValue = new UFile(location);
149  array.SetValue(newValue, index);
150  return newValue;
151  });
152  }
153  else if (item is UDirectory)
154  {
155  AddLink(item,
156  (guid, location) =>
157  {
158  var newValue = new UFile(location);
159  array.SetValue(newValue, index);
160  return newValue;
161  });
162  }
163  }
164  }
165 
166  public override void VisitCollectionItem(IEnumerable collection, CollectionDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor)
167  {
168  base.VisitCollectionItem(collection, descriptor, index, item, itemDescriptor);
169  var assetReference = item as AssetReference;
170  // TODO force support for IList in CollectionDescriptor
171  if (assetReference != null)
172  {
173  var list = (IList)collection;
174  AddLink(assetReference, (guid, location) => list[index] = AssetReference.New(descriptor.ElementType, guid.HasValue ? guid.Value : assetReference.Id, location));
175  }
176  else
177  {
178  var assetBase = item as AssetBase;
179  if (assetBase != null)
180  {
181  var list = (IList)collection;
182  AddLink(assetBase, (guid, location) => list[index] = new AssetBase(location, assetBase.Asset));
183  }
184  else if (item is UFile)
185  {
186  var list = (IList)collection;
187  AddLink(item, (guid, location) => list[index] = new UFile(location));
188  }
189  else if (item is UDirectory)
190  {
191  var list = (IList)collection;
192  AddLink(item, (guid, location) => list[index] = new UDirectory(location));
193  }
194  }
195  }
196 
197  public override void VisitDictionaryKeyValue(object dictionaryObj, DictionaryDescriptor descriptor, object key, ITypeDescriptor keyDescriptor, object value, ITypeDescriptor valueDescriptor)
198  {
199  base.VisitDictionaryKeyValue(dictionaryObj, descriptor, key, keyDescriptor, value, valueDescriptor);
200  var assetReference = value as AssetReference;
201  if (assetReference != null)
202  {
203  AddLink(assetReference,
204  (guid, location) =>
205  {
206  var newValue = AssetReference.New(descriptor.ValueType, guid.HasValue ? guid.Value : assetReference.Id, location);
207  descriptor.SetValue(dictionaryObj, key, newValue);
208  return newValue;
209  });
210  }
211  else
212  {
213  var assetBase = value as AssetBase;
214  if (assetBase != null)
215  {
216  AddLink(assetBase,
217  (guid, location) =>
218  {
219  var newValue = new AssetBase(location, assetBase.Asset);
220  descriptor.SetValue(dictionaryObj, key, newValue);
221  return newValue;
222  });
223  }
224  else if (value is UFile)
225  {
226  AddLink(value,
227  (guid, location) =>
228  {
229  var newValue = new UFile(location);
230  descriptor.SetValue(dictionaryObj, key, newValue);
231  return newValue;
232  });
233  }
234  else if (value is UDirectory)
235  {
236  AddLink(value,
237  (guid, location) =>
238  {
239  var newValue = new UDirectory(location);
240  descriptor.SetValue(dictionaryObj, key, newValue);
241  return newValue;
242  });
243  }
244  }
245  }
246 
247  public override void VisitObjectMember(object container, ObjectDescriptor containerDescriptor, IMemberDescriptor member, object value)
248  {
249  base.VisitObjectMember(container, containerDescriptor, member, value);
250  var assetReference = value as AssetReference;
251  if (assetReference != null)
252  {
253  AddLink(assetReference,
254  (guid, location) =>
255  {
256  var newValue = AssetReference.New(member.Type, guid.HasValue ? guid.Value : assetReference.Id, location);
257  member.Set(container, newValue);
258  return newValue;
259  });
260  }
261  else
262  {
263  var assetBase = value as AssetBase;
264  if (assetBase != null)
265  {
266  AddLink(assetBase,
267  (guid, location) =>
268  {
269  var newValue = new AssetBase(location, assetBase.Asset);
270  member.Set(container, newValue);
271  return newValue;
272  });
273  }
274  else if (value is UFile)
275  {
276  AddLink(value,
277  (guid, location) =>
278  {
279  var newValue = new UFile(location);
280  member.Set(container, newValue);
281  return newValue;
282  });
283  }
284  else if (value is UDirectory)
285  {
286  AddLink(value,
287  (guid, location) =>
288  {
289  var newValue = new UDirectory(location);
290  member.Set(container, newValue);
291  return newValue;
292  });
293  }
294  }
295  }
296 
297  private void AddLink(object value, Func<Guid?, string, object> updateReference)
298  {
299  References.Add(new AssetReferenceLink(CurrentPath.Clone(), value, updateReference));
300  }
301  }
302  }
303 }
Provides a descriptor for a System.Collections.ICollection.
This analysis provides a method for visiting asset and file references (IContentReference or UFile or...
Default implementation of a ITypeDescriptor.
Provides a descriptor for a System.Collections.IDictionary.
Defines a normalized directory path. See UPath for details. This class cannot be inherited.
Definition: UDirectory.cs:13
static List< AssetReferenceLink > Visit(object obj)
Gets all references (subclass of IContentReference and UFile) from the specified asset ...
Provides access members of a type.
Defines a normalized file path. See UPath for details. This class cannot be inherited.
Definition: UFile.cs:13