Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
ThumbnailCompilerBase.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 
4 using System;
5 using System.IO;
6 using System.Threading.Tasks;
7 
8 using SiliconStudio.BuildEngine;
9 using SiliconStudio.Core.IO;
10 using SiliconStudio.Core.Serialization.Assets;
11 using SiliconStudio.Core.Storage;
12 
13 namespace SiliconStudio.Assets.Compiler
14 {
15  /// <summary>
16  /// Base implementation for <see cref="IAssetCompiler"/> suitable to build a thumbnail of a single type of <see cref="Asset"/>.
17  /// </summary>
18  /// <typeparam name="T">Type of the asset</typeparam>
19  public abstract class ThumbnailCompilerBase<T> : AssetDependenciesCompilerBase<T> where T : Asset
20  {
21  private class ThumbnailFailureBuildStep : BuildStep
22  {
23  public override string Title { get { return "FailureThumbnail"; } }
24 
25  public override Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
26  {
27  return Task.FromResult(ResultStatus.Failed);
28  }
29 
30  public override BuildStep Clone()
31  {
32  return new ThumbnailFailureBuildStep();
33  }
34 
35  public override string ToString()
36  {
37  return Title;
38  }
39  }
40 
41  public sealed override AssetCompilerResult Compile(CompilerContext context, AssetItem assetItem)
42  {
43  // This method is overriden only because of the issue in assignment of the AssetsSession property in the base method.
44  // In this implementation, the assignment is deferred in the try/catch block of the CompileOverride method.
45  // TODO: Remove this override once the issue in the bas method is fixed (and seal the base method if possible)
46  if (context == null) throw new ArgumentNullException("context");
47  if (assetItem == null) throw new ArgumentNullException("assetItem");
48 
49  Asset = (T)assetItem.Asset;
50  AssetItem = assetItem;
51 
52  var compilerResult = new AssetCompilerResult();
53  CompileOverride((AssetCompilerContext)context, compilerResult);
54  return compilerResult;
55  }
56 
57  protected sealed override AssetCompilerResult CompileOverride(AssetCompilerContext context, AssetCompilerResult compilerResult)
58  {
59  var thumbnailCompilerContext = (ThumbnailCompilerContext)context;
60 
61  // Build the path of the thumbnail in the storage
62  var assetStorageUrl = AssetItem.Location.GetDirectoryAndFileName();
63  var thumbnailStorageUrl = assetStorageUrl.Insert(0, "__THUMBNAIL__");
64 
65  try
66  {
67  // TODO: fix failures here (see TODOs in Compile and base.Compile)
68  AssetsSession = AssetItem.Package.Session;
69 
70  // Only use the path to the asset without its extension
71  Compile(thumbnailCompilerContext, thumbnailStorageUrl, AssetItem.FullPath, compilerResult);
72  }
73  catch (Exception)
74  {
75  // If an exception occurs, ensure that the build of thumbnail will fail.
76  compilerResult.BuildSteps = null;
77  }
78 
79  if (compilerResult.BuildSteps == null || compilerResult.HasErrors)
80  {
81  // if a problem occurs while compiling, we don't want to enqueue null because it would mean
82  // that there is no thumbnail to build, which is incorrect. So we return a special build step
83  // that will always fail. If we don't, some asset ids will never be removed from the in progress
84  // list and thus never be updated again.
85  compilerResult.BuildSteps = new ListBuildStep { new ThumbnailFailureBuildStep() };
86  }
87 
88  var currentAsset = AssetItem; // copy the current asset item and embrace it in the callback
89  compilerResult.BuildSteps.StepProcessed += (_, buildStepArgs) => OnThumbnailStepProcessed(thumbnailCompilerContext, currentAsset, thumbnailStorageUrl, buildStepArgs);
90  return compilerResult;
91  }
92 
93  private static void OnThumbnailStepProcessed(ThumbnailCompilerContext context, AssetItem assetItem, string thumbnailStorageUrl, BuildStepEventArgs buildStepEventArgs)
94  {
95  // returns immediately if the user has not subscribe to the event
96  if (!context.ShouldNotifyThumbnailBuilt)
97  return;
98 
99  // Retrieving build result
100  var result = ThumbnailBuildResult.Failed;
101  if (buildStepEventArgs.Step.Succeeded)
102  result = ThumbnailBuildResult.Succeeded;
103  else if (buildStepEventArgs.Step.Status == ResultStatus.Cancelled)
104  result = ThumbnailBuildResult.Cancelled;
105 
106  var changed = buildStepEventArgs.Step.Status != ResultStatus.NotTriggeredWasSuccessful;
107 
108  // Open the image data stream if the build succeeded
109  Stream thumbnailStream = null;
110  ObjectId thumbnailHash = ObjectId.Empty;
111 
112  if (buildStepEventArgs.Step.Succeeded)
113  {
114  thumbnailStream = AssetManager.FileProvider.OpenStream(thumbnailStorageUrl, VirtualFileMode.Open, VirtualFileAccess.Read);
115  thumbnailHash = AssetManager.FileProvider.AssetIndexMap[thumbnailStorageUrl];
116  }
117  context.NotifyThumbnailBuilt(assetItem, result, changed, thumbnailStream, thumbnailHash);
118 
119  // Close the image data stream if opened
120  if (thumbnailStream != null)
121  thumbnailStream.Dispose();
122  }
123 
124  /// <summary>
125  /// Compiles the asset from the specified package.
126  /// </summary>
127  /// <param name="context">The thumbnail compile context</param>
128  /// <param name="thumbnailStorageUrl">The absolute URL to the asset's thumbnail, relative to the storage.</param>
129  /// <param name="assetAbsolutePath">Absolute path of the asset on the disk</param>
130  /// <param name="result">The result where the commands and logs should be output.</param>
131  protected abstract void Compile(ThumbnailCompilerContext context, string thumbnailStorageUrl, UFile assetAbsolutePath, AssetCompilerResult result);
132  }
133 }
Result of a compilation of assets when using IAssetCompiler.Compile
ResultStatus Status
The status of the result.
Definition: BuildStep.cs:45
Base class for Asset.
Definition: Asset.cs:14
The context used when compiling an asset in a Package.
sealed override AssetCompilerResult Compile(CompilerContext context, AssetItem assetItem)
Compiles a list of assets from the specified package.
An asset item part of a Package accessible through SiliconStudio.Assets.Package.Assets.
Definition: AssetItem.cs:17
ResultStatus
Status of a command.
Definition: ResultStatus.cs:8
The context used when compiling an asset in a Package.
ListBuildStep BuildSteps
Gets or sets the build steps generated for the build engine. This can be null if LoggerResult.HasErrors is true.
bool Succeeded
Indicate whether the result corresponds to a successful execution (even if the command has not been t...
Definition: BuildStep.cs:55
UFile FullPath
Gets the full absolute path of this asset on the disk, taking into account the SourceFolder, and the SiliconStudio.Assets.Package.RootDirectory. See remarks.
Definition: AssetItem.cs:168
bool ShouldNotifyThumbnailBuilt
Indicate whether the fact that a thumbnail has been built should be notified with NotifyThumbnailBuil...
A hash to uniquely identify data.
Definition: ObjectId.cs:13
bool HasErrors
Gets or sets a value indicating whether this instance has errors.
Definition: Logger.cs:46
sealed override AssetCompilerResult CompileOverride(AssetCompilerContext context, AssetCompilerResult compilerResult)
Asset Asset
Gets or sets the asset.
Definition: AssetItem.cs:197
The context used when building the thumbnail of an asset in a Package.
Defines a normalized file path. See UPath for details. This class cannot be inherited.
Definition: UFile.cs:13