public static Image LoadImageFromIcon(this ResourceManager resourceManager, string path)
        {
            return(resourceManager.LoadImage(path, textureLoader => new LazyImage(resourceManager.DefaultImage, () =>
            {
                var _log = Log.Get <ResourceManager>();

                try
                {
                    // Normalize path
                    path = Path.GetFullPath(path);

                    _log.Info($"Loading image from icon at path '{path}'...");

                    using (var bmpStream = new MemoryStream())
                    {
                        var bmp = ThumbnailLoader.GetThumbnail(path, 50, 50, ThumbnailOptions.None);
                        bmp.Save(bmpStream, System.Drawing.Imaging.ImageFormat.Bmp);

                        // Convert to texture
                        return textureLoader.Load(bmpStream.ToArray());
                    }
                }
                catch (Exception ex)
                {
                    _log.Error($"Could not load image from icon: '{ex.Message}'.", ex);
                    return ResourceManager.Instance.DefaultImage;
                }
            })));
        }
Beispiel #2
0
 public void Setup()
 {
     _fileSystem  = new Mock <IFileSystem>();
     _imageLoader = new Mock <IImageLoader>();
     _storage     = new Mock <IAttributeStorage>();
     _loader      = new ThumbnailLoader(_imageLoader.Object, _storage.Object, _fileSystem.Object);
 }
Beispiel #3
0
        public string Generate(IYoutubeJob job)
        {
            var tags = "";

            if (job.Video.Tags.Count > 0)
            {
                tags = job.Video.Tags.First();
            }

            for (int i = 1; i < job.Video.Tags.Count; i++)
            {
                tags = $"{tags},{job.Video.Tags.ElementAt(i)}";
            }

            var privacy = string.Empty;

            switch (job.Video.Privacy)
            {
            case Youtube.Interfaces.Model.Enums.PrivacyStatus.Public:
                privacy = "Öffentlich";
                break;

            case Youtube.Interfaces.Model.Enums.PrivacyStatus.Unlisted:
                privacy = "Nicht gelistet";
                break;

            case Youtube.Interfaces.Model.Enums.PrivacyStatus.Private:
                privacy = "Privat";
                break;
            }

            return(string.Format(
                       template,
                       HttpUtility.HtmlEncode(job.Video.Title),
                       HttpUtility.HtmlEncode(job.Account.Title),
                       HttpUtility.HtmlEncode(job.Video.Privacy.ToString()),
                       job.Video.PublishAt != null ? job.Video.PublishAt.Value.ToString("dd.MM.yyyy HH:mm") : "keine Ver&ouml;ffentlichung geplant",
                       job.Video.Description.Length <= 500 ? job.Video.Description : $"{job.Video.Description.Substring(0, 497)}...",
                       tags,
                       ThumbnailLoader.LoadAsBase64(job.Video.ThumbnailPath, 192, 108)
                       ));
        }
Beispiel #4
0
        public string Generate(IYoutubeJob job)
        {
            var tags = "";

            if (job.Video.Tags.Count > 0)
            {
                tags = job.Video.Tags.First();
            }

            for (int i = 1; i < job.Video.Tags.Count; i++)
            {
                tags = $"{tags},{job.Video.Tags.ElementAt(i)}";
            }

            var privacy = string.Empty;

            switch (job.Video.Privacy)
            {
            case Youtube.Interfaces.Model.Enums.PrivacyStatus.Public:
                privacy = "Öffentlich";
                break;

            case Youtube.Interfaces.Model.Enums.PrivacyStatus.Unlisted:
                privacy = "Nicht gelistet";
                break;

            case Youtube.Interfaces.Model.Enums.PrivacyStatus.Private:
                privacy = "Privat";
                break;
            }

            return(string.Format(
                       template,
                       HttpUtility.HtmlEncode(job.Video.Title),
                       HttpUtility.HtmlEncode(job.Account.Title),
                       ThumbnailLoader.LoadAsBase64(job.Video.ThumbnailPath, 192, 108)
                       ));
        }
Beispiel #5
0
        public static IEnumerator MakeThumbnail(IEnumerable <ItemInfo> itemList, string outputDirectory, bool manualMode, bool dark)
        {
            Texture2D thumbBackground;

            try
            {
                if (manualMode && !Chainloader.PluginInfos.ContainsKey("KK_OrthographicCamera"))
                {
                    throw new ArgumentException("Manual mode needs the OrthographicCamera plugin to work");
                }

                if (itemList == null)
                {
                    throw new ArgumentNullException(nameof(itemList));
                }
                if (outputDirectory == null)
                {
                    throw new ArgumentNullException(nameof(outputDirectory));
                }
                if (!Directory.Exists(outputDirectory))
                {
                    throw new DirectoryNotFoundException("Output directory was not found: " + outputDirectory);
                }

                thumbBackground = ResourceUtils.GetEmbeddedResource(dark ? "thumb_background_dark.png" : "thumb_background.png").LoadTexture();
            }
            catch (Exception ex)
            {
                QuickAccessBox.Logger.Log(LogLevel.Message | LogLevel.Error, "Failed to make thumbs: " + ex.Message);
                yield break;
            }

            RemoveAllItems();
            yield return(null);

            // Spawn new image board > rectangle
            Singleton <Studio.Studio> .Instance.AddItem(1, 38, 671);

            yield return(null);

            var root = GameObject.Find("CommonSpace").transform;

            // Setup thumbnail pane
            var origPlane = root.Find("p_koi_stu_plane00_00");

            foreach (var component in origPlane.GetComponents <MonoBehaviour>())
            {
                // Needed to prevent kkpe from crashing the Object.Instantiate call below
                if (component.GetType().Name == "PoseController")
                {
                    Object.DestroyImmediate(component);
                }
            }
            var copyPlane = Object.Instantiate(origPlane);

            copyPlane.gameObject.SetActive(true);

            RemoveAllItems();

            var mat = copyPlane.GetComponent <MeshRenderer>().material;

            mat.mainTexture = thumbBackground;

            var camera        = Camera.main;
            var cameraControl = camera.GetComponent <Studio.CameraControl>();
            var alphaShot     = camera.GetComponent <AlphaShot2>();

            camera.orthographic   = true;
            cameraControl.enabled = false;

            var createdCount = 0;

            foreach (var itemInfo in itemList)
            {
                if (itemInfo.IsSFX)
                {
                    continue;
                }

                var thumbPath = Path.Combine(outputDirectory, itemInfo.CacheId + ".png");
                if (File.Exists(thumbPath))
                {
                    continue;
                }

                if (ThumbnailLoader.CustomThumbnailAvailable(itemInfo))
                {
                    continue;
                }

                yield return(null);

                Console.WriteLine($"Spawning: FullName={itemInfo.FullName} FileName={itemInfo.FileName}");

                itemInfo.AddItem();
                createdCount++;

                yield return(null);

                var targets = root.Children();
                var b       = Utils.CalculateBounds(targets);

                if (b != null)
                {
                    var bounds = b.Value;

                    const float objectSizeAdjust = 0.5f;

                    var objectSize = bounds.size.magnitude;
                    var targetObj  = targets.First();

                    if (_shootFromFrontGroups.Contains(itemInfo.GroupNo))
                    {
                        // Look at the object from front, better for flat effects
                        // Move the camera a long way away from the objects to avoid clipping
                        // todo anything better? Not reliable
                        camera.transform.position = (targetObj.position + targetObj.forward * objectSize) * 8;
                    }
                    else
                    {
                        // Use isometric angle since it has best chance of showing the object in an usable way
                        // Move the camera a long way away from the objects to avoid clipping
                        camera.transform.position = (bounds.center - targetObj.forward * objectSize - targetObj.right * objectSize + targetObj.up * objectSize) * 8;
                    }

                    camera.transform.LookAt(bounds.center);
                    camera.orthographicSize = objectSize * objectSizeAdjust;

                    void UpdateBackgroundPlane()
                    {
                        // Move the thumbnail pane in the opposite way from the camera and scale/align it so that it fills the camera view behind the item
                        copyPlane.position = camera.transform.position + camera.transform.forward * (camera.transform.position - bounds.center).magnitude * 2;
                        copyPlane.LookAt(camera.transform);
                        copyPlane.localScale = new Vector3(objectSize / (16 / 9f) * 1.325F, objectSize * 1.325F, 1) * objectSizeAdjust;
                    }

                    if (manualMode)
                    {
                        cameraControl.enabled = true;
                        yield return(new WaitUntil(() =>
                        {
                            // Adjust for the new camera position
                            objectSize = camera.orthographicSize / objectSizeAdjust;
                            UpdateBackgroundPlane();
                            return Input.GetKeyDown(KeyCode.LeftShift) || Input.GetKey(KeyCode.Escape);
                        }));

                        cameraControl.enabled = false;
                    }

                    UpdateBackgroundPlane();

                    var result = alphaShot.Capture(64, 64, 1, true);

                    try { File.WriteAllBytes(thumbPath, result); }
                    catch (SystemException ex) { QuickAccessBox.Logger.Log(LogLevel.Message | LogLevel.Error, "Failed to write thumbnail file - " + ex.Message); }
                }
                else
                {
                    QuickAccessBox.Logger.Log(LogLevel.Info, "No renderers to take capture of - " + itemInfo.FullName);
                }

                yield return(null);

                RemoveAllItems();

                if (createdCount % 400 == 0)
                {
                    Resources.UnloadUnusedAssets();
                }

                if (Input.GetKey(KeyCode.Escape))
                {
                    break;
                }
            }

            cameraControl.enabled = true;
            camera.orthographic   = false;

            Object.Destroy(thumbBackground);
            Object.Destroy(copyPlane.gameObject);

            QuickAccessBox.Logger.Log(LogLevel.Message, "Finished taking thumbnails!");
        }
Beispiel #6
0
        public static IEnumerator MakeThumbnail(IEnumerable <ItemInfo> itemList, string outputDirectory, bool manualMode, bool dark)
        {
            Texture2D thumbBackground;

            try
            {
                if (manualMode && !(Chainloader.PluginInfos.TryGetValue("KK_OrthographicCamera", out var plug) && plug.Metadata.Version >= new Version("1.1.1")))
                {
                    throw new ArgumentException("Manual mode needs the OrthographicCamera plugin (at least v1.1.1) to work");
                }

                if (itemList == null)
                {
                    throw new ArgumentNullException(nameof(itemList));
                }
                if (outputDirectory == null)
                {
                    throw new ArgumentNullException(nameof(outputDirectory));
                }
                if (!Directory.Exists(outputDirectory))
                {
                    throw new DirectoryNotFoundException("Output directory was not found: " + outputDirectory);
                }

                thumbBackground = ResourceUtils.GetEmbeddedResource(dark ? "thumb_background_dark.png" : "thumb_background.png").LoadTexture();
            }
            catch (Exception ex)
            {
                QuickAccessBox.Logger.Log(BepInEx.Logging.LogLevel.Message | BepInEx.Logging.LogLevel.Error, "Failed to make thumbs: " + ex.Message);
                yield break;
            }

            RemoveAllItems();
            yield return(null);

            // Spawn new image board > rectangle
            Singleton <Studio.Studio> .Instance.AddItem(0, 18, 636);

            yield return(null);

            var root = GameObject.Find("CommonSpace").transform;

            // Setup thumbnail pane
            var origPlane = root.Find("p_ai_stu_kihon14_00alfa");

            foreach (var component in origPlane.GetComponents <MonoBehaviour>())
            {
                // Needed to prevent kkpe from crashing the Object.Instantiate call below
                if (component.GetType().Name == "PoseController")
                {
                    Object.DestroyImmediate(component);
                }
            }
            var copyPlane = Object.Instantiate(origPlane, null);

            copyPlane.gameObject.SetActive(true);
            copyPlane.gameObject.name = "thumb_background";
            var thumbRend = copyPlane.GetComponent <MeshRenderer>();

            thumbRend.sortingOrder = -10;
            var thumbMat = thumbRend.material;

            thumbMat.mainTexture = thumbBackground;
            Object.DestroyImmediate(copyPlane.gameObject.GetComponent <ItemComponent>());

            RemoveAllItems();

            var camera        = Camera.main;
            var cameraControl = camera.GetComponent <Cinemachine.CinemachineBrain>();

            cameraControl.enabled = false;
            camera.orthographic   = true;
            camera.farClipPlane   = 1500000;
            var postProcessing = camera.GetComponent <PostProcessLayer>();

            var screencap = (Screencap.ScreenshotManager)Chainloader.PluginInfos[Screencap.ScreenshotManager.GUID].Instance;

            byte[] RunCapture()
            {
                postProcessing.enabled             = false;
                RenderSettings.ambientSkyColor     = Color.white;
                RenderSettings.ambientEquatorColor = Color.white;
                RenderSettings.ambientGroundColor  = Color.white;

                var cap   = screencap.Capture(64, 64, 1, true);
                var cap2D = cap.ToTexture2D();
                var bytes = cap2D.EncodeToPNG();

                RenderTexture.ReleaseTemporary(cap);
                Object.Destroy(cap2D);
                return(bytes);
            }

            var createdCount = 0;

            foreach (var itemInfo in itemList)
            {
                if (itemInfo.IsSFX)
                {
                    continue;
                }

                var thumbPath = Path.Combine(outputDirectory, itemInfo.CacheId + ".png");
                if (File.Exists(thumbPath))
                {
                    continue;
                }

                if (ThumbnailLoader.CustomThumbnailAvailable(itemInfo))
                {
                    continue;
                }

                yield return(null);

                Console.WriteLine($"Spawning: FullName={itemInfo.FullName} FileName={itemInfo.FileName}");

                itemInfo.AddItem();
                createdCount++;

                yield return(null);

                var targets = root.Children();
                var b       = Utils.CalculateBounds(targets);

                if (b != null)
                {
                    var bounds = b.Value;

                    const float objectSizeAdjust = 0.5f;

                    var objectSize = bounds.size.magnitude;
                    var targetObj  = targets.First();

                    if (_shootFromFrontGroups.Contains(itemInfo.GroupNo))
                    {
                        // Look at the object from front, better for flat effects
                        // Move the camera a long way away from the objects to avoid clipping
                        // todo anything better? Not reliable
                        camera.transform.position = (targetObj.position + targetObj.forward * objectSize) * 8;
                    }
                    else
                    {
                        // Use isometric angle since it has best chance of showing the object in an usable way
                        // Move the camera a long way away from the objects to avoid clipping
                        camera.transform.position = (bounds.center - targetObj.forward * objectSize - targetObj.right * objectSize + targetObj.up * objectSize) * 8;
                    }

                    camera.transform.LookAt(bounds.center);
                    camera.orthographicSize = objectSize * objectSizeAdjust;

                    void UpdateBackgroundPlane()
                    {
                        // Move the thumbnail pane in the opposite way from the camera and scale/align it so that it fills the camera view behind the item
                        copyPlane.position = camera.transform.position + camera.transform.forward * (camera.transform.position - bounds.center).magnitude * 2;
                        copyPlane.LookAt(camera.transform);
                        copyPlane.Rotate(90, 0, 0);
                        copyPlane.localScale = new Vector3(objectSize * 0.508f, 1, objectSize * 0.508f) * objectSizeAdjust;
                    }

                    if (manualMode)
                    {
                        cameraControl.enabled = true;
                        yield return(new WaitUntil(() =>
                        {
                            // Adjust for the new camera position
                            objectSize = camera.orthographicSize / objectSizeAdjust;
                            UpdateBackgroundPlane();
                            return Input.GetKeyDown(KeyCode.LeftShift) || Input.GetKey(KeyCode.Escape);
                        }));

                        cameraControl.enabled = false;
                    }

                    UpdateBackgroundPlane();

                    var result = RunCapture();

                    try { File.WriteAllBytes(thumbPath, result); }
                    catch (SystemException ex) { QuickAccessBox.Logger.Log(BepInEx.Logging.LogLevel.Message | BepInEx.Logging.LogLevel.Error, "Failed to write thumbnail file - " + ex.Message); }
                }
                else
                {
                    QuickAccessBox.Logger.LogInfo($"No renderers to take capture of for {itemInfo.FullName} - GroupNo:{itemInfo.GroupNo} CategoryNo:{itemInfo.CategoryNo} ItemNo:{itemInfo.ItemNo}");
                }

                yield return(null);

                RemoveAllItems();

                if (createdCount % 400 == 0)
                {
                    Resources.UnloadUnusedAssets();
                }

                if (Input.GetKey(KeyCode.Escape))
                {
                    break;
                }
            }

            cameraControl.enabled = true;
            camera.orthographic   = false;

            Object.Destroy(thumbBackground);
            Object.Destroy(copyPlane.gameObject);

            QuickAccessBox.Logger.LogMessage("Finished taking thumbnails!");
        }