Exemple #1
0
        protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
        {
            // load the sound thumbnail image from the resources
            using (var imageStream = new MemoryStream(staticImageData))
                using (var image = Image.Load(imageStream))
                    using (var texTool = new TextureTool())
                        using (var texImage = texTool.Load(image, Parameters.SRgb))
                        {
                            // Rescale image so that it fits the thumbnail asked resolution
                            texTool.Decompress(texImage, texImage.Format.IsSRgb());
                            texTool.Resize(texImage, thumbnailSize.X, thumbnailSize.Y, Filter.Rescaling.Lanczos3);

                            // Save
                            using (var outputImageStream = MicrothreadLocalDatabases.DatabaseFileProvider.OpenStream(Url, VirtualFileMode.Create, VirtualFileAccess.Write))
                                using (var outputImage = texTool.ConvertToXenkoImage(texImage))
                                {
                                    ThumbnailBuildHelper.ApplyThumbnailStatus(outputImage, DependencyBuildStatus);

                                    outputImage.Save(outputImageStream, ImageFileType.Png);

                                    commandContext.Logger.Verbose($"Thumbnail creation successful [{Url}] to ({outputImage.Description.Width}x{outputImage.Description.Height},{outputImage.Description.Format})");
                                }
                        }

            return(Task.FromResult(ResultStatus.Successful));
        }
Exemple #2
0
        /// <summary>
        /// Applies the build status on top of a thumbnail image (using overlay icons).
        /// </summary>
        /// <param name="thumbnailImage">The thumbnail image.</param>
        /// <param name="dependencyBuildStatus">The dependency build status.</param>
        public static void ApplyThumbnailStatus(Image thumbnailImage, LogMessageType dependencyBuildStatus)
        {
            // No warning or error, nothing to do (or maybe we should display a logo for "info"?)
            if (dependencyBuildStatus < LogMessageType.Warning)
            {
                return;
            }

            using (var thumbnailBuilderHelper = new ThumbnailBuildHelper())
            {
                if (errorTexture == null)
                {
                    // Load status textures
                    errorTexture   = TextureExtensions.FromFileData(thumbnailBuilderHelper.GraphicsDevice, DefaultThumbnails.ThumbnailDependencyError);
                    warningTexture = TextureExtensions.FromFileData(thumbnailBuilderHelper.GraphicsDevice, DefaultThumbnails.ThumbnailDependencyWarning);
                }

                var texture = dependencyBuildStatus == LogMessageType.Warning ? warningTexture : errorTexture;
                using (var thumbnailTexture = Texture.New(thumbnailBuilderHelper.GraphicsDevice, thumbnailImage))
                {
                    thumbnailBuilderHelper.CombineTextures(thumbnailTexture, texture, thumbnailImage.Description.Width - texture.Width - 4, thumbnailImage.Description.Height - texture.Height - 4);
                }

                // Read back result to image
                thumbnailBuilderHelper.RenderTarget.GetData(thumbnailBuilderHelper.GraphicsContext.CommandList, thumbnailBuilderHelper.RenderTargetStaging, new DataPointer(thumbnailImage.PixelBuffer[0].DataPointer, thumbnailImage.PixelBuffer[0].BufferStride));
                thumbnailImage.Description.Format = thumbnailBuilderHelper.RenderTarget.Format; // In case channels are swapped
            }
        }
        public static byte[] HandleBrokenThumbnail()
        {
            // Load broken asset thumbnail
            var assetBrokenThumbnail = Image.Load(DefaultThumbnails.AssetBrokenThumbnail);

            // Apply thumbnail status in corner
            ThumbnailBuildHelper.ApplyThumbnailStatus(assetBrokenThumbnail, LogMessageType.Error);
            var memoryStream = new MemoryStream();

            assetBrokenThumbnail.Save(memoryStream, ImageFileType.Png);

            return(memoryStream.ToArray());
        }
Exemple #4
0
        /// <summary>
        /// The micro-thread in charge of processing the thumbnail build requests and creating the thumbnails.
        /// </summary>
        private ResultStatus ProcessThumbnailRequests(ThumbnailBuildRequest request)
        {
            var status = ResultStatus.Successful;

            // Global lock so that only one rendering happens at the same time
            lock (lockObject)
            {
                try
                {
                    lock (AssetBuilderService.OutOfMicrothreadDatabaseLock)
                    {
                        MicrothreadLocalDatabases.MountCommonDatabase();

                        // set the master output
                        var renderTarget = GraphicsContext.Allocator.GetTemporaryTexture2D(request.Size.X, request.Size.Y, request.ColorSpace == ColorSpace.Linear ? PixelFormat.R8G8B8A8_UNorm_SRgb : PixelFormat.R8G8B8A8_UNorm, TextureFlags.ShaderResource | TextureFlags.RenderTarget);
                        var depthStencil = GraphicsContext.Allocator.GetTemporaryTexture2D(request.Size.X, request.Size.Y, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil);

                        try
                        {
                            // Fake presenter
                            // TODO GRAPHICS REFACTOR: Try to remove that
                            GraphicsDevice.Presenter = new RenderTargetGraphicsPresenter(GraphicsDevice, renderTarget, depthStencil.ViewFormat);

                            // Always clear the state of the GraphicsDevice to make sure a scene doesn't start with a wrong setup
                            GraphicsCommandList.ClearState();

                            // Setup the color space when rendering a thumbnail
                            GraphicsDevice.ColorSpace = request.ColorSpace;

                            // render the thumbnail
                            thumbnailScene.Children.Add(request.Scene);

                            // Store the graphics compositor to use, so we can dispose it when disposing this ThumbnailGenerator
                            thumbnailGraphicsCompositors.Add(request.GraphicsCompositor);
                            sceneSystem.GraphicsCompositor = request.GraphicsCompositor;

                            // Render once to setup render processors
                            // TODO GRAPHICS REFACTOR: Should not require two rendering
                            GraphicsContext.ResourceGroupAllocator.Reset(GraphicsContext.CommandList);
                            gameSystems.Draw(nullGameTime);

                            // Draw
                            gameSystems.Update(nullGameTime);
                            GraphicsContext.ResourceGroupAllocator.Reset(GraphicsContext.CommandList);
                            gameSystems.Draw(nullGameTime);

                            // write the thumbnail to the file
                            using (var thumbnailImage = renderTarget.GetDataAsImage(GraphicsCommandList))
                                using (var outputImageStream = request.FileProvider.OpenStream(request.Url, VirtualFileMode.Create, VirtualFileAccess.Write))
                                {
                                    request.PostProcessThumbnail?.Invoke(thumbnailImage);

                                    ThumbnailBuildHelper.ApplyThumbnailStatus(thumbnailImage, request.DependencyBuildStatus);

                                    thumbnailImage.Save(outputImageStream, ImageFileType.Png);

                                    request.Logger.Info($"Thumbnail creation successful [{request.Url}] to ({thumbnailImage.Description.Width}x{thumbnailImage.Description.Height},{thumbnailImage.Description.Format})");
                                }
                        }
                        finally
                        {
                            // Cleanup the scene
                            thumbnailScene.Children.Clear();
                            sceneSystem.GraphicsCompositor = null;

                            GraphicsContext.Allocator.ReleaseReference(depthStencil);
                            GraphicsContext.Allocator.ReleaseReference(renderTarget);
                        }

                        MicrothreadLocalDatabases.UnmountDatabase();
                    }
                }
                catch (Exception e)
                {
                    status = ResultStatus.Failed;
                    request.Logger.Error("An exception occurred while processing thumbnail request.", e);
                }
            }

            return(status);
        }