123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- using UnityEngine;
- using System.IO;
- using System.Diagnostics;
- using System.Runtime.InteropServices;
- //-----------------------------------------------------------------------------
- // Copyright 2012-2022 RenderHeads Ltd. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace RenderHeads.Media.AVProMovieCapture
- {
- public class Utils
- {
- public static string[] WindowsImageSequenceFormatNames = new string[] { "PNG (uncompressed)" };
- public static string[] MacOSImageSequenceFormatNames = new string[] { "PNG", "JPEG", "TIFF", "HEIF" };
- public static string[] IOSImageSequenceFormatNames = new string[] { "PNG", "JPEG", "TIFF", "HEIF" };
- public static string[] AndroidImageSequenceFormatNames = new string[] { "PNG", "JPEG" };
- public static string[] GetNativeImageSequenceFormatNames()
- {
- string[] result = null;
- #if UNITY_EDITOR
- #if UNITY_EDITOR_WIN
- result = WindowsImageSequenceFormatNames;
- #elif UNITY_EDITOR_OSX
- result = MacOSImageSequenceFormatNames;
- #endif
- #else
- #if UNITY_STANDALONE_WIN
- result = WindowsImageSequenceFormatNames;
- #elif UNITY_STANDALONE_OSX
- result = MacOSImageSequenceFormatNames;
- #elif UNITY_IOS
- result = IOSImageSequenceFormatNames;
- #elif UNITY_ANDROID
- result = AndroidImageSequenceFormatNames;
- #endif
- #endif
- if (result == null)
- {
- result = new string[0];
- }
- return result;
- }
- public static bool HasAlphaChannel(RenderTextureFormat format)
- {
- bool result = false;
- switch (format)
- {
- case RenderTextureFormat.ARGB32:
- case RenderTextureFormat.BGRA32:
- case RenderTextureFormat.ARGB4444:
- case RenderTextureFormat.ARGB1555:
- case RenderTextureFormat.ARGB2101010:
- case RenderTextureFormat.ARGB64:
- case RenderTextureFormat.RGBAUShort:
- case RenderTextureFormat.ARGBInt:
- case RenderTextureFormat.ARGBFloat:
- case RenderTextureFormat.ARGBHalf:
- #if UNITY_2017_2_OR_NEWER
- case RenderTextureFormat.BGRA10101010_XR:
- #endif
- result = true;
- break;
- }
- return result;
- }
- public static RenderTextureFormat GetBestRenderTextureFormat(bool supportHDR, bool supportTransparency, bool favourSpeedOverQuality)
- {
- RenderTextureFormat result = RenderTextureFormat.Default;
- if (supportTransparency)
- {
- if (supportHDR)
- {
- // HDR Transparent
- result = RenderTextureFormat.DefaultHDR;
- if (favourSpeedOverQuality)
- {
- #if UNITY_2017_2_OR_NEWER
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.BGRA10101010_XR)) return RenderTextureFormat.BGRA10101010_XR;
- #endif
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf)) return RenderTextureFormat.ARGBHalf;
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBFloat)) return RenderTextureFormat.ARGBFloat;
- }
- else
- {
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBFloat)) return RenderTextureFormat.ARGBFloat;
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf)) return RenderTextureFormat.ARGBHalf;
- #if UNITY_2017_2_OR_NEWER
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.BGRA10101010_XR)) return RenderTextureFormat.BGRA10101010_XR;
- #endif
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB64)) return RenderTextureFormat.ARGB64;
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB2101010)) return RenderTextureFormat.ARGB2101010;
- }
- }
- else
- {
- // SDR Transparent
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB32)) return RenderTextureFormat.ARGB32;
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.BGRA32)) return RenderTextureFormat.BGRA32;
- }
- }
- else
- {
- if (supportHDR)
- {
- // HDR non-transparent
- result = RenderTextureFormat.DefaultHDR;
- /*if (favourSpeedOverQuality)
- {
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RGB111110Float)) return RenderTextureFormat.RGB111110Float;
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB2101010)) return RenderTextureFormat.ARGB2101010;
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf)) return RenderTextureFormat.ARGBHalf;
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBFloat)) return RenderTextureFormat.ARGBFloat;
- }
- else
- {
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBFloat)) return RenderTextureFormat.ARGBFloat;
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf)) return RenderTextureFormat.ARGBHalf;
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB2101010)) return RenderTextureFormat.ARGB2101010;
- if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RGB111110Float)) return RenderTextureFormat.RGB111110Float;
- }*/
- }
- }
- if (!SystemInfo.SupportsRenderTextureFormat(result))
- {
- UnityEngine.Debug.LogError("[AVProMovieCapture] Couldn't find suitable texture format " + result + " for " + supportHDR + " " + supportTransparency + " " + favourSpeedOverQuality);
- }
- return result;
- }
- /// <summary>
- /// The "main" camera isn't necessarily the one the gets rendered last to screen,
- /// so we sort all cameras by depth and find the one with no render target
- /// </summary>
- public static Camera GetUltimateRenderCamera()
- {
- Camera result = Camera.main;
- {
- // Iterate all enabled cameras
- float highestDepth = float.MinValue;
- Camera[] enabledCameras = Camera.allCameras;
- for (int cameraIndex = 0; cameraIndex < enabledCameras.Length; cameraIndex++)
- {
- Camera camera = enabledCameras[cameraIndex];
- // Ignore null cameras
- if (camera != null)
- {
- // Ignore cameras that are hidden or have a targetTexture
- bool isHidden = (camera.hideFlags & HideFlags.HideInHierarchy) == HideFlags.HideInHierarchy;
- if (!isHidden && camera.targetTexture == null)
- {
- // Ignore cameras that render nothing
- if (camera.pixelRect.width > 0f && camera.pixelHeight > 0f)
- {
- // Keep the one with highest depth
- // TODO: handle the case where camera depths are equal - which one is first then?
- if (camera.depth >= highestDepth)
- {
- highestDepth = camera.depth;
- result = camera;
- }
- }
- }
- }
- }
- }
- return result;
- }
- public static bool HasContributingCameras(Camera parentCamera)
- {
- bool result = true;
- // If the camera doesn't clear the target completely then it may have other contributing cameras
- if (parentCamera.rect == new Rect(0f, 0f, 1f, 1f))
- {
- if (parentCamera.clearFlags == CameraClearFlags.Skybox ||
- parentCamera.clearFlags == CameraClearFlags.Color)
- {
- result = false;
- }
- }
- return result;
- }
- /// <summary>
- /// Returns a list of cameras sorted in render order from first to last that contribute to the rendering to parentCamera
- /// </summary>
- public static Camera[] FindContributingCameras(Camera parentCamera)
- {
- System.Collections.Generic.List<Camera> validCameras = new System.Collections.Generic.List<Camera>(8);
- {
- // Iterate all enabled/disabled cameras (they may become enabled later on)
- Camera[] allCameras = (Camera[])Resources.FindObjectsOfTypeAll(typeof(Camera));
- for (int cameraIndex = 0; cameraIndex < allCameras.Length; cameraIndex++)
- {
- Camera camera = allCameras[cameraIndex];
- // Ignore null cameras and camera that is the parent
- if (camera != null && camera != parentCamera)
- {
- // Only allow cameras with depth less or equal to parent camera
- if (camera.depth <= parentCamera.depth)
- {
- // Ignore cameras that are hidden or have a targetTexture that doesn't match the parent
- bool isHidden = (camera.hideFlags & HideFlags.HideInHierarchy) == HideFlags.HideInHierarchy;
- if (!isHidden && camera.targetTexture == parentCamera.targetTexture)
- {
- // Ignore cameras that render nothing
- if (camera.pixelRect.width > 0 && camera.pixelHeight > 0)
- {
- validCameras.Add(camera);
- }
- }
- }
- }
- }
- }
- if (validCameras.Count > 1)
- {
- // Sort by depth (render order)
- // TODO: handle the case where camera depths are equal - which one is first then?
- validCameras.Sort(delegate (Camera a, Camera b)
- {
- if (a != b) // Pre .Net 4.6.2 Sort() can compare an elements with itself
- {
- if (a.depth < b.depth)
- {
- return -1;
- }
- else if (a.depth > b.depth)
- {
- return 1;
- }
- else if (a.depth == b.depth)
- {
- UnityEngine.Debug.LogWarning("[AVProMovieCapture] Cameras '" + a.name + "' and '" + b.name + "' have the same depth value - unable to determine render order: " + a.depth);
- }
- }
- return 0;
- });
- // Starting from the last camera to render, find the first one that clears the screen completely
- for (int i = (validCameras.Count - 1); i >= 0; i--)
- {
- if (validCameras[i].rect == new Rect(0f, 0f, 1f, 1f))
- {
- if (validCameras[i].clearFlags == CameraClearFlags.Skybox ||
- validCameras[i].clearFlags == CameraClearFlags.Color)
- {
- // Remove all cameras before this
- validCameras.RemoveRange(0, i);
- break;
- }
- }
- }
- }
- return validCameras.ToArray();
- }
- #if UNITY_EDITOR_OSX || (UNITY_STANDALONE_OSX && !UNITY_EDITOR)
- private static string PhotosScheme { get { return "photos://"; } }
- private static string FileScheme { get { return "file://"; } }
- #elif UNITY_IOS && !UNITY_EDITOR
- private static string PhotosScheme { get { return "photos-redirect://"; } }
- private static string FileScheme { get { return "shareddocuments://"; } }
- #endif
- private static string URLEscapePathByPercentEncoding(string path)
- {
- return path.Replace("%", "%25") // Escape percents first so escaped character's percents aren't themselves escaped
- .Replace(" ", "%20")
- .Replace("\"", "%22")
- .Replace("#", "%23")
- .Replace(";", "%3B")
- .Replace("<", "%3C")
- .Replace(">", "%3E")
- .Replace("?", "%3F")
- .Replace("[", "%5B")
- .Replace("\\", "%5C")
- .Replace("]", "%5D")
- .Replace("^", "%5E")
- .Replace("`", "%60")
- .Replace("{", "%7B")
- .Replace("|", "%7C")
- .Replace("}", "%7D");
- }
- public static bool ShowInExplorer(string itemPath)
- {
- bool result = false;
- #if UNITY_EDITOR_OSX || (!UNITY_EDITOR && (UNITY_STANDALONE_OSX || UNITY_IOS))
- string url;
- if (itemPath.StartsWith("avpmc-photolibrary://"))
- {
- // TODO: Find out how to open photos to a specific album/item
- url = PhotosScheme;
- }
- else
- {
- url = FileScheme + URLEscapePathByPercentEncoding(Directory.GetParent(itemPath).FullName);
- }
- UnityEngine.Debug.LogFormat("ShowInExplorer - opening URL: {0}", url);
- UnityEngine.Application.OpenURL(url);
- result = true;
- #else
- #if !UNITY_WEBPLAYER
- itemPath = Path.GetFullPath(itemPath.Replace(@"/", @"\")); // explorer doesn't like front slashes
- if (File.Exists(itemPath))
- {
- #if UNITY_EDITOR_WIN || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)
- Process.Start("explorer.exe", "/select," + itemPath);
- #else
- #endif
- result = true;
- }
- else if (Directory.Exists(itemPath))
- {
- // NOTE: We use OpenURL() instead of the explorer process so that it opens explorer inside the folder
- UnityEngine.Application.OpenURL(itemPath);
- result = true;
- }
- #endif
- #endif // UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
- return result;
- }
- public static bool OpenInDefaultApp(string itemPath)
- {
- bool result = false;
- #if UNITY_EDITOR_OSX || (!UNITY_EDITOR && (UNITY_STANDALONE_OSX || UNITY_IOS))
- string url;
- if (itemPath.StartsWith("avpmc-photolibrary://"))
- {
- // TODO: Find out how to open photos to a specific album/item
- url = PhotosScheme;
- }
- else
- {
- url = FileScheme + URLEscapePathByPercentEncoding(itemPath);
- }
- UnityEngine.Debug.LogFormat("OpenInDefaultApp - opening URL: {0}", url);
- UnityEngine.Application.OpenURL(url);
- result = true;
- #else
- itemPath = Path.GetFullPath(itemPath.Replace(@"/", @"\"));
- if (File.Exists(itemPath))
- {
- UnityEngine.Application.OpenURL(itemPath);
- result = true;
- }
- else if (Directory.Exists(itemPath))
- {
- UnityEngine.Application.OpenURL(itemPath);
- result = true;
- }
- #endif
- return result;
- }
- public static long GetFileSize(string filename)
- {
- #if UNITY_WEBPLAYER
- return 0;
- #else
- System.IO.FileInfo fi = new System.IO.FileInfo(filename);
- return fi.Length;
- #endif
- }
- #if UNITY_EDITOR_WIN || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- [return: MarshalAs(UnmanagedType.Bool)]
- private static extern bool GetDiskFreeSpaceEx(string lpDirectoryName,
- out ulong lpFreeBytesAvailable,
- out ulong lpTotalNumberOfBytes,
- out ulong lpTotalNumberOfFreeBytes);
- public static bool DriveFreeBytes(string folderName, out ulong freespace)
- {
- freespace = 0;
- if (string.IsNullOrEmpty(folderName))
- {
- throw new System.ArgumentNullException("folderName");
- }
- if (!folderName.EndsWith("\\"))
- {
- folderName += '\\';
- }
- ulong free = 0, dummy1 = 0, dummy2 = 0;
- if (GetDiskFreeSpaceEx(folderName, out free, out dummy1, out dummy2))
- {
- freespace = free;
- return true;
- }
- else
- {
- return false;
- }
- }
- #endif
- public static string GetImageFileExtension(ImageSequenceFormat format)
- {
- string result = string.Empty;
- switch (format)
- {
- case ImageSequenceFormat.PNG:
- result = "png";
- break;
- case ImageSequenceFormat.JPEG:
- result = "jpg";
- break;
- case ImageSequenceFormat.TIFF:
- result = "tiff";
- break;
- case ImageSequenceFormat.HEIF:
- result = "heif";
- break;
- }
- return result;
- }
- }
- }
|