Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
AssetItem.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 SiliconStudio.Assets.Analysis;
6 using SiliconStudio.Core;
7 using SiliconStudio.Core.IO;
8 using SiliconStudio.Core.Reflection;
9 
10 namespace SiliconStudio.Assets
11 {
12 
13  /// <summary>
14  /// An asset item part of a <see cref="Package"/> accessible through <see cref="SiliconStudio.Assets.Package.Assets"/>.
15  /// </summary>
16  [DataContract("AssetItem")]
17  public sealed class AssetItem : IFileSynchronizable
18  {
19  private UFile location;
20  private Asset asset;
21  private bool isDirty;
22  private Package package;
23  private UDirectory sourceFolder;
24 
25  /// <summary>
26  /// The default comparer use only the id of an assetitem to match assets.
27  /// </summary>
28  public static readonly IEqualityComparer<AssetItem> DefaultComparerById = new AssetItemComparerById();
29 
30  /// <summary>
31  /// Initializes a new instance of the <see cref="AssetItem" /> class.
32  /// </summary>
33  /// <param name="location">The location.</param>
34  /// <param name="asset">The asset.</param>
35  /// <exception cref="System.ArgumentNullException">location</exception>
36  /// <exception cref="System.ArgumentException">asset</exception>
37  public AssetItem(UFile location, Asset asset)
38  {
39  if (location == null) throw new ArgumentNullException("location");
40  if (asset == null) throw new ArgumentException("asset");
41  this.location = location;
42  this.asset = asset;
43  isDirty = true;
44  }
45 
46  /// <summary>
47  /// Gets the location of this asset.
48  /// </summary>
49  /// <value>The location.</value>
50  public UFile Location
51  {
52  get
53  {
54  return location;
55  }
56  internal set
57  {
58  if (value == null) throw new ArgumentNullException("value");
59  this.location = value;
60  }
61  }
62 
63  /// <summary>
64  /// Gets the directory where the assets will be stored on the disk relative to the <see cref="Package"/>. The directory
65  /// will update the list found in <see cref="PackageProfile.AssetFolders"/>
66  /// </summary>
67  /// <value>The directory.</value>
68  public UDirectory SourceFolder
69  {
70  get
71  {
72  return sourceFolder;
73  }
74  set
75  {
76  sourceFolder = value;
77  }
78  }
79 
80  /// <summary>
81  /// Gets the unique identifier of this asset.
82  /// </summary>
83  /// <value>The unique identifier.</value>
84  public Guid Id
85  {
86  get
87  {
88  return asset.Id;
89  }
90  }
91 
92  /// <summary>
93  /// Gets the package where this asset is stored.
94  /// </summary>
95  /// <value>The package.</value>
96  public Package Package
97  {
98  get
99  {
100  return package;
101  }
102  internal set
103  {
104  package = value;
105  }
106  }
107 
108  /// <summary>
109  /// Converts this item to a reference.
110  /// </summary>
111  /// <returns>AssetReference.</returns>
113  {
114  return new AssetReference<Asset>(Id, Location);
115  }
116 
117  /// <summary>
118  /// Clones this instance without the attached package.
119  /// </summary>
120  /// <param name="newLocation">The new location that will be used in the cloned <see cref="AssetItem"/>. If this parameter
121  /// is null, it keeps the original location of the asset.</param>
122  /// <param name="newAsset">The new asset that will be used in the cloned <see cref="AssetItem"/>. If this parameter
123  /// is null, it clones the original asset. otherwise, the specified asset is used as-is in the new <see cref="AssetItem"/>
124  /// (no clone on newAsset is performed)</param>
125  /// <returns>A clone of this instance.</returns>
126  public AssetItem Clone(UFile newLocation = null, Asset newAsset = null)
127  {
128  return Clone(false, newLocation, newAsset);
129  }
130 
131  /// <summary>
132  /// Clones this instance without the attached package.
133  /// </summary>
134  /// <param name="newLocation">The new location that will be used in the cloned <see cref="AssetItem" />. If this parameter
135  /// is null, it keeps the original location of the asset.</param>
136  /// <param name="newAsset">The new asset that will be used in the cloned <see cref="AssetItem" />. If this parameter
137  /// is null, it clones the original asset. otherwise, the specified asset is used as-is in the new <see cref="AssetItem" />
138  /// (no clone on newAsset is performed)</param>
139  /// <param name="copyPackage">if set to <c>true</c> copy package information, only used by the <see cref="AssetDependencyManager" />.</param>
140  /// <returns>A clone of this instance.</returns>
141  internal AssetItem Clone(bool copyPackage, UFile newLocation = null, Asset newAsset = null)
142  {
143  var item = new AssetItem(newLocation ?? location, newAsset ?? (Asset)AssetCloner.Clone(Asset))
144  {
145  isDirty = isDirty,
146  SourceFolder = SourceFolder
147  };
148 
149  // Set the package after the new AssetItem(), to make sure that isDirty is not going to call a notification on the
150  // package
151  if (copyPackage)
152  {
153  item.Package = Package;
154  }
155  return item;
156  }
157 
158  /// <summary>
159  /// Gets the full absolute path of this asset on the disk, taking into account the <see cref="SourceFolder"/>, and the
160  /// <see cref="SiliconStudio.Assets.Package.RootDirectory"/>. See remarks.
161  /// </summary>
162  /// <value>The full absolute path of this asset on the disk.</value>
163  /// <remarks>
164  /// This value is only valid if this instance is attached to a <see cref="Package"/>, and that the package has
165  /// a non null <see cref="SiliconStudio.Assets.Package.RootDirectory"/>.
166  /// </remarks>
167  public UFile FullPath
168  {
169  get
170  {
171  var localSourceFolder = SourceFolder ?? (Package != null ? Package.GetDefaultAssetFolder() : UDirectory.This );
172 
173  // Root directory of package
174  var rootDirectory = Package != null && Package.RootDirectory != null ? Package.RootDirectory : null;
175 
176  // If the source folder is absolute, make it relative to the root directory
177  if (localSourceFolder.IsAbsolute)
178  {
179  if (rootDirectory != null)
180  {
181  localSourceFolder = localSourceFolder.MakeRelative(rootDirectory);
182  }
183  }
184 
185  rootDirectory = rootDirectory != null ? UPath.Combine(rootDirectory, localSourceFolder) : localSourceFolder;
186 
187  var locationAndExtension = new UFile(Location + AssetRegistry.GetDefaultExtension(Asset.GetType()));
188  return rootDirectory != null ? UPath.Combine(rootDirectory, locationAndExtension) : locationAndExtension;
189  }
190  }
191 
192  /// <summary>
193  /// Gets or sets the asset.
194  /// </summary>
195  /// <value>The asset.</value>
196  public Asset Asset
197  {
198  get
199  {
200  return asset;
201  }
202  internal set
203  {
204  if (value == null) throw new ArgumentNullException("value");
205  asset = value;
206  }
207  }
208 
209  /// <summary>
210  /// Gets the modified time. See remarks.
211  /// </summary>
212  /// <value>The modified time.</value>
213  /// <remarks>
214  /// By default, contains the last modified time of the asset from the disk. If IsDirty is also updated from false to true
215  /// , this time will get current time of modification.
216  /// </remarks>
217  public DateTime ModifiedTime { get; internal set; }
218 
219  /// <summary>
220  /// Gets or sets a value indicating whether this instance is dirty. See remarks.
221  /// </summary>
222  /// <value><c>true</c> if this instance is dirty; otherwise, <c>false</c>.</value>
223  /// <remarks>
224  /// When an asset is modified, this property must be set to true in order to track assets changes.
225  /// </remarks>
226  public bool IsDirty
227  {
228  get
229  {
230  return isDirty;
231  }
232  set
233  {
234  if (value && !isDirty)
235  {
236  ModifiedTime = DateTime.Now;
237  }
238 
239  isDirty = value;
240  if (Package != null)
241  {
242  Package.OnAssetDirtyChanged(asset);
243  }
244  }
245  }
246 
247  public override string ToString()
248  {
249  return string.Format("{0}{1} => {2}", string.Format("[{0}] ", Asset.GetType().Name), location, Id);
250  }
251 
252  /// <summary>
253  /// Creates a child asset that is inheriting the values of this asset.
254  /// </summary>
255  /// <returns>A new asset inheriting the values of this asset.</returns>
257  {
258  // Clone this asset
259  var assetBase = (Asset)AssetCloner.Clone(Asset);
260 
261  // Remove the base
262  assetBase.Base = null;
263 
264  // Clone it again without the base and without overrides (as we want all parameters to inherit from base)
265  var newAsset = (Asset)AssetCloner.Clone(assetBase, true);
266 
267  // Sets a new identifier for this asset
268  newAsset.Id = Guid.NewGuid();
269 
270  // Create the base of this asset
271  newAsset.Base = new AssetBase(Location, assetBase);
272  return newAsset;
273  }
274 
275  /// <summary>
276  /// Finds the base item referenced by this item from the current session (using the <see cref="Package"/> setup
277  /// on this instance)
278  /// </summary>
279  /// <returns>The base item or null if not found.</returns>
281  {
282  if (Package == null || Package.Session == null || Asset.Base == null || Asset.Base.IsRootImport)
283  {
284  return null;
285  }
286  var session = Package.Session;
287  return session.FindAsset(Asset.Base.Id);
288  }
289 
290  /// <summary>
291  /// This methods returns all assets that would be changed when trying to change this asset.
292  /// </summary>
293  /// <param name="path">The path.</param>
294  /// <param name="action">The action.</param>
295  /// <param name="value">The value.</param>
296  /// <returns>LoggerResult.</returns>
297  /// <exception cref="System.ArgumentNullException">path</exception>
299  {
300  if (path == null) throw new ArgumentNullException("path");
301 
302  var result = new List<AssetItem>();
303 
304  FindAssetsFromChange(path, action, value, result);
305  return result;
306  }
307 
308  private void FindAssetsFromChange(MemberPath path, MemberPathAction action, object value, List<AssetItem> items)
309  {
310  object oldValue;
311  var pathSucceeded = path.TryGetValue(Asset, out oldValue);
312 
313  // If the path exists and value changed or we are doing another operation (remove key...etc.)
314  // then add the items as a list of item to change
315  if (pathSucceeded && (action != MemberPathAction.ValueSet || value != oldValue))
316  {
317  items.Add(this);
318  }
319 
320  if (Package != null && Package.Session != null)
321  {
322  var itemsToDetect = Package.Session.DependencyManager.FindAssetsInheritingFrom(Id);
323  foreach (var item in itemsToDetect)
324  {
325  item.FindAssetsFromChange(path, action, value, items);
326  }
327  }
328  }
329 
330  private class AssetItemComparerById : IEqualityComparer<AssetItem>
331  {
332  public bool Equals(AssetItem x, AssetItem y)
333  {
334  if (ReferenceEquals(x, y))
335  return true;
336 
337  if (x == null || y == null)
338  {
339  return false;
340  }
341 
342  if (ReferenceEquals(x.Asset, y.Asset))
343  {
344  return true;
345  }
346 
347  return x.Id == y.Id;
348  }
349 
350  public int GetHashCode(AssetItem obj)
351  {
352  return obj.Id.GetHashCode();
353  }
354  }
355  }
356 }
AssetReference ToReference()
Converts this item to a reference.
Definition: AssetItem.cs:112
AssetItem(UFile location, Asset asset)
Initializes a new instance of the AssetItem class.
Definition: AssetItem.cs:37
AssetItem FindBase()
Finds the base item referenced by this item from the current session (using the Package setup on this...
Definition: AssetItem.cs:280
Base class for Asset.
Definition: Asset.cs:14
AssetBase Base
Gets or sets the base.
Definition: Asset.cs:69
A registry for file extensions, IAssetImporter, IAssetFactory and aliases associated with assets...
An asset item part of a Package accessible through Package.Assets.
Definition: AssetBase.cs:16
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
Definition: DirectXTexP.h:191
static readonly UDirectory This
A this '.' directory.
Definition: UDirectory.cs:23
An asset item part of a Package accessible through SiliconStudio.Assets.Package.Assets.
Definition: AssetItem.cs:17
AssetItem Clone(UFile newLocation=null, Asset newAsset=null)
Clones this instance without the attached package.
Definition: AssetItem.cs:126
Defines a normalized directory path. See UPath for details. This class cannot be inherited.
Definition: UDirectory.cs:13
PackageSession Session
Gets the session.
Definition: Package.cs:219
override string ToString()
Definition: AssetItem.cs:247
Allows to get/set a property/field value on a deeply nested object instance (supporting members...
Definition: MemberPath.cs:14
static string GetDefaultExtension(Type assetType)
Gets the default extension associated with an asset.
List< AssetItem > FindAssetsFromChange(MemberPath path, MemberPathAction action, object value)
This methods returns all assets that would be changed when trying to change this asset.
Definition: AssetItem.cs:298
object Clone()
Clones the current value of this cloner with the specified new shadow registry (optional) ...
Definition: AssetCloner.cs:43
Identify an object that is associated with an anchor file on the disk where all the UPath members of ...
Asset CreateChildAsset()
Creates a child asset that is inheriting the values of this asset.
Definition: AssetItem.cs:256
bool IsRootImport
Gets a value indicating whether this instance is a root import base (the original import)...
Definition: AssetBase.cs:88
A package managing assets.
Definition: Package.cs:28
MemberPathAction
A type of action used by MemberPath.Apply
Allows to clone an asset or values stored in an asset.
Definition: AssetCloner.cs:14
Defines a normalized file path. See UPath for details. This class cannot be inherited.
Definition: UFile.cs:13