Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
AssetCollision.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.Generic;
5 using System.Linq;
6 
7 using SiliconStudio.Core.IO;
8 using SiliconStudio.Core.Serialization;
9 
10 namespace SiliconStudio.Assets.Analysis
11 {
12  public static class AssetCollision
13  {
14  /// <summary>
15  /// Cleans the specified input items.
16  /// </summary>
17  /// <param name="inputItems">The input items.</param>
18  /// <param name="outputItems">The output items.</param>
19  /// <param name="assetResolver">The asset resolver.</param>
20  /// <param name="cloneInput">if set to <c>true</c> [clone input].</param>
21  /// <exception cref="System.ArgumentNullException">
22  /// inputItems
23  /// or
24  /// outputItems
25  /// or
26  /// assetResolver
27  /// </exception>
28  /// <exception cref="System.ArgumentException">List cannot contain null items;inputItems</exception>
29  public static void Clean(ICollection<AssetItem> inputItems, ICollection<AssetItem> outputItems, AssetResolver assetResolver, bool cloneInput)
30  {
31  if (inputItems == null) throw new ArgumentNullException("inputItems");
32  if (outputItems == null) throw new ArgumentNullException("outputItems");
33  if (assetResolver == null) throw new ArgumentNullException("assetResolver");
34 
35  // Check that all items are non-null
36  if (inputItems.Any(item => item == null))
37  {
38  throw new ArgumentException("List cannot contain null items", "inputItems");
39  }
40 
41  var items = inputItems;
42  if (cloneInput)
43  {
44  items = inputItems.Select(item => item.Clone()).ToList();
45  }
46 
47  // Check if locations are conflicting
48  var locationConflicts = new Dictionary<AssetItem, UFile>();
49  foreach (var item in items)
50  {
51  UFile newLocation;
52  if (assetResolver.RegisterLocation(item.Location, out newLocation))
53  {
54  locationConflicts[item] = newLocation;
55  }
56  }
57 
58  // Check if ids are conflicting
59  var idConflicts = new Dictionary<AssetItem, Guid>();
60  foreach (var item in items)
61  {
62  Guid newGuid;
63  if (assetResolver.RegisterId(item.Id, out newGuid))
64  {
65  idConflicts[item] = newGuid;
66  }
67  }
68 
69  // Calculate final guid => guid remapping
70  // Because several asset items can have the same id, we are only using the first one for remapping
71  var idRemap = new Dictionary<Guid, Tuple<Guid, UFile>>();
72  var locationRemap = new Dictionary<UFile, UFile>();
73 
74  foreach (var item in items)
75  {
76  if (outputItems.Contains(item))
77  {
78  continue;
79  }
80 
81  outputItems.Add(item);
82 
83  Guid newGuid;
84  if (!idConflicts.TryGetValue(item, out newGuid))
85  {
86  newGuid = item.Id;
87  }
88 
89  UFile newLocation;
90  if (locationConflicts.TryGetValue(item, out newLocation) && !locationRemap.ContainsKey(item.Location))
91  {
92  locationRemap.Add(item.Location, newLocation);
93  }
94 
95  if (!idRemap.ContainsKey(item.Id))
96  {
97  idRemap.Add(item.Id, new Tuple<Guid, UFile>(newGuid, newLocation ?? item.Location));
98  }
99  }
100 
101  // Process assets
102  foreach (var item in outputItems)
103  {
104  // Replace Id
105  Guid newGuid;
106  if (idConflicts.TryGetValue(item, out newGuid))
107  {
108  item.Asset.Id = newGuid;
109  item.IsDirty = true;
110  }
111 
112  // Replace location
113  if (locationConflicts.ContainsKey(item))
114  {
115  item.Location = locationConflicts[item];
116  item.IsDirty = true;
117  }
118 
119  // The loop is a one or two-step.
120  // - If there is no link to update, and the asset has not been cloned, we can exist immediately
121  // - If there is links to update, and the asset has not been cloned, we need to clone it and re-enter the loop
122  // to perform the update of the clone asset
123  var links = AssetReferenceAnalysis.Visit(item.Asset).Where(link => link.Reference is IContentReference).ToList();
124 
125  foreach (var assetLink in links)
126  {
127  var assetReference = (IContentReference)assetLink.Reference;
128 
129  var newId = assetReference.Id;
130  var newLocation = assetReference.Location;
131 
132  bool requireUpdate = false;
133 
134  if (idRemap.ContainsKey(newId))
135  {
136  var newRemap = idRemap[newId];
137  newId = newRemap.Item1;
138  newLocation = newRemap.Item2;
139  requireUpdate = true;
140  }
141 
142  if (!requireUpdate && locationRemap.ContainsKey(newLocation))
143  {
144  newLocation = locationRemap[newLocation];
145  requireUpdate = true;
146  }
147 
148  if (requireUpdate)
149  {
150  assetLink.UpdateReference(newId, newLocation);
151  item.IsDirty = true;
152  }
153  }
154  }
155  }
156  }
157 }
Helper to find available new asset locations and identifiers.
static void Clean(ICollection< AssetItem > inputItems, ICollection< AssetItem > outputItems, AssetResolver assetResolver, bool cloneInput)
Cleans the specified input items.
An interface that provides a reference to an asset.
Defines a normalized file path. See UPath for details. This class cannot be inherited.
Definition: UFile.cs:13