#if UNITY_EDITOR #if UNITY_5_4_OR_NEWER || (UNITY_5 && !UNITY_5_0) #define AVPRO_MOVIECAPTURE_WINDOWTITLE_51 #define AVPRO_MOVIECAPTURE_GRAPHICSDEVICETYPE_51 #endif #if UNITY_5_4_OR_NEWER || (UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2) #define AVPRO_MOVIECAPTURE_SCENEMANAGER_53 #endif #if UNITY_5_4_OR_NEWER || UNITY_5 #define AVPRO_MOVIECAPTURE_DEFERREDSHADING #endif using UnityEngine; using UnityEditor; //----------------------------------------------------------------------------- // Copyright 2012-2017 RenderHeads Ltd. All rights reserved. //----------------------------------------------------------------------------- namespace RenderHeads.Media.AVProMovieCapture.Editor { /// /// Creates a dockable window in Unity that can be used for handy in-editor capturing /// public class CaptureEditorWindow : EditorWindow { private const string TempGameObjectName = "Temp_MovieCapture"; private const string SettingsPrefix = "AVProMovieCapture.EditorWindow."; private static bool _isTrialVersion = false; private CaptureBase _capture; private CaptureFromScreen _captureScreen; private CaptureFromCamera _captureCamera; private CaptureFromCamera360 _captureCamera360; private CaptureFromCamera360ODS _captureCamera360ODS; private static bool _isCreated = false; private static bool _isInit = false; private static bool _isFailedInit = false; private static bool _showAlpha = false; private static string[] _videoCodecNames = new string[0]; private static string[] _audioCodecNames = new string[0]; private static string[] _audioDeviceNames = new string[0]; private static bool[] _videoCodecConfigurable = new bool[0]; private static bool[] _audioCodecConfigurable = new bool[0]; private readonly string[] _downScales = { "Original", "Half", "Quarter", "Eighth", "Sixteenth", "Custom" }; private readonly string[] _captureModes = { "Realtime Capture", "Offline Render" }; private readonly string[] _outputFolders = { "Project Folder", "Persistent Data Folder", "Absolute Folder" }; private readonly string[] _sourceNames = { "Screen", "Camera", "Camera 360 (fast Stereo)", "Camera 360 (accurate ODS Stereo)" }; private enum SourceType { Screen, Camera, Camera360, Camera360ODS, } [SerializeField] private SourceType _sourceType = SourceType.Screen; private bool _startPaused = false; private Camera _cameraNode; private string _cameraName; private int _captureModeIndex; private int _outputFolderIndex; [SerializeField] private CaptureBase.OutputType _outputType = CaptureBase.OutputType.VideoFile; private bool _autoFilenamePrefixFromSceneName = true; private string _autoFilenamePrefix = "capture"; private string _autoFilenameExtension = "avi"; private string _outputFolderRelative = string.Empty; private string _outputFolderAbsolute = string.Empty; private bool _appendTimestamp = true; [SerializeField] private string _namedPipePath = @"\\.\pipe\pipename"; private int _downScaleIndex; private int _downscaleX; private int _downscaleY; private bool _captureMouseCursor = false; private Texture2D _mouseCursorTexture = null; [SerializeField] private CaptureBase.Resolution _renderResolution = CaptureBase.Resolution.Original; private Vector2 _renderSize; [SerializeField] private int _renderAntiAliasing; [SerializeField] private bool _useContributingCameras = true; [SerializeField] private CaptureBase.FrameRate _frameRate = CaptureBase.FrameRate.Thirty; private bool _supportAlpha = false; private bool _useMediaFoundationH264 = false; private int _videoCodecIndex; private bool _captureAudio; private int _audioCodecIndex; private int _audioDeviceIndex; private Vector2 _scroll = Vector2.zero; private bool _queueStart; private int _queueConfigureVideoCodec = -1; private int _queueConfigureAudioCodec = -1; private bool _useMotionBlur = false; private int _motionBlurSampleCount = 16; private int _cubemapResolution = 2048; private int _cubemapDepth = 24; private int _cubemapStereoPacking = 0; private float _cubemapStereoIPD = 0.064f; [SerializeField] private StopMode _stopMode = StopMode.None; private int _stopFrames = 300; private float _stopSeconds = 10f; private SerializedProperty _propSourceType; private SerializedProperty _propOutputType; private SerializedProperty _propNamedPipePath; private SerializedProperty _propFrameRate; private SerializedProperty _propStopMode; private SerializedProperty _propRenderResolution; private SerializedProperty _propUseContributingCameras; private SerializedProperty _propStereoIPD; private SerializedProperty _propRenderAntiAliasing; private SerializedProperty _propOdsCamera; private SerializedProperty _propOdsIPD; private SerializedProperty _propOdsPixelSliceSize; private SerializedProperty _propOdsPaddingSize; private SerializedProperty _propOdsCameraClearMode; private SerializedProperty _propOdsCameraClearColor; [SerializeField] private CaptureFromCamera360ODS.Settings _odsSettings = new CaptureFromCamera360ODS.Settings(); // TODO: we should actually be saving these parameters per-scene... private long _lastFileSize; private uint _lastEncodedMinutes; private uint _lastEncodedSeconds; private uint _lastEncodedFrame; private int _selectedTool; private int _selectedConfigTool; private bool _expandSectionTrial = true; private static Texture2D _icon; private string _pluginVersionWarningText = string.Empty; private SerializedObject _so; private const string LinkPluginWebsite = "http://renderheads.com/product/av-pro-movie-capture/"; private const string LinkForumPage = "http://forum.unity3d.com/threads/released-avpro-movie-capture.120717/"; private const string LinkAssetStorePage = "https://www.assetstore.unity3d.com/#!/content/2670"; private const string LinkFreeAssetStorePage = "https://www.assetstore.unity3d.com/#!/content/97562"; private const string LinkEmailSupport = "mailto:unitysupport@renderheads.com"; private const string LinkUserManual = "http://downloads.renderheads.com/docs/UnityAVProMovieCapture.pdf"; private const string SupportMessage = "If you are reporting a bug, please include any relevant files and details so that we may remedy the problem as fast as possible.\n\n" + "Essential details:\n" + "+ Error message\n" + " + The exact error message\n" + " + The console/output log if possible\n" + "+ Development environment\n" + " + Unity version\n" + " + Development OS version\n" + " + AVPro Movie Capture plugin version\n"; [MenuItem("Window/Open AVPro Movie Capture..")] public static void Init() { if (_isInit || _isCreated) { CaptureEditorWindow window = (CaptureEditorWindow)EditorWindow.GetWindow(typeof(CaptureEditorWindow)); window.Close(); return; } _isCreated = true; // Get existing open window or if none, make a new one: CaptureEditorWindow window2 = (CaptureEditorWindow)EditorWindow.GetWindow(typeof(CaptureEditorWindow)); if (window2 != null) { window2.SetupWindow(); } } public void SetupWindow() { _isCreated = true; if (Application.platform == RuntimePlatform.WindowsEditor) { this.minSize = new Vector2(200f, 48f); this.maxSize = new Vector2(340f, 620f); #if AVPRO_MOVIECAPTURE_WINDOWTITLE_51 if (_icon != null) { this.titleContent = new GUIContent("Movie Capture", _icon, "AVPro Movie Capture"); } else { this.titleContent = new GUIContent("Movie Capture", "AVPro Movie Capture"); } #else this.title = "Movie Capture"; #endif this.CreateGUI(); this.LoadSettings(); _so = new SerializedObject(this); if (_so == null) { Debug.LogError("[AVProMovieCapture] SO is null"); } _propSourceType = _so.FindProperty("_sourceType"); _propOutputType = _so.FindProperty("_outputType"); _propNamedPipePath = _so.FindProperty("_namedPipePath"); _propRenderResolution = _so.FindProperty("_renderResolution"); _propUseContributingCameras = _so.FindProperty("_useContributingCameras"); _propFrameRate = _so.FindProperty("_frameRate"); _propStopMode = _so.FindProperty("_stopMode"); _propRenderAntiAliasing = _so.FindProperty("_renderAntiAliasing"); _propOdsIPD = _so.FindProperty("_odsSettings.ipd"); _propOdsPixelSliceSize = _so.FindProperty("_odsSettings.pixelSliceSize"); _propOdsPaddingSize = _so.FindProperty("_odsSettings.paddingSize"); _propOdsCameraClearMode = _so.FindProperty("_odsSettings.cameraClearMode"); _propOdsCameraClearColor = _so.FindProperty("_odsSettings.cameraClearColor"); this.Repaint(); } } private void LoadSettings() { _sourceType = (SourceType)EditorPrefs.GetInt(SettingsPrefix + "SourceType", (int)_sourceType); _cameraName = EditorPrefs.GetString(SettingsPrefix + "CameraName", string.Empty); _captureModeIndex = EditorPrefs.GetInt(SettingsPrefix + "CaptureModeIndex", 0); _startPaused = EditorPrefs.GetBool(SettingsPrefix + "StartPaused", false); _captureMouseCursor = EditorPrefs.GetBool(SettingsPrefix + "CaptureMouseCursor", false); string mouseCursorGuid = EditorPrefs.GetString(SettingsPrefix + "CaptureMouseTexture", string.Empty); if (!string.IsNullOrEmpty(mouseCursorGuid)) { string mouseCursorPath = AssetDatabase.GUIDToAssetPath(mouseCursorGuid); if (!string.IsNullOrEmpty(mouseCursorPath)) { _mouseCursorTexture = (Texture2D)AssetDatabase.LoadAssetAtPath(mouseCursorPath, typeof(Texture2D)); } } _outputType = (CaptureBase.OutputType)EditorPrefs.GetInt(SettingsPrefix + "OutputType", (int)_outputType); _namedPipePath = EditorPrefs.GetString(SettingsPrefix + "NamedPipePath", _namedPipePath); _autoFilenamePrefixFromSceneName = EditorPrefs.GetBool(SettingsPrefix + "AutoFilenamePrefixFromScenename", _autoFilenamePrefixFromSceneName); _autoFilenamePrefix = EditorPrefs.GetString(SettingsPrefix + "AutoFilenamePrefix", "capture"); _autoFilenameExtension = EditorPrefs.GetString(SettingsPrefix + "AutoFilenameExtension", "avi"); _appendTimestamp = EditorPrefs.GetBool(SettingsPrefix + "AppendTimestamp", true); _outputFolderIndex = EditorPrefs.GetInt(SettingsPrefix + "OutputFolderIndex", 0); _outputFolderRelative = EditorPrefs.GetString(SettingsPrefix + "OutputFolderRelative", string.Empty); _outputFolderAbsolute = EditorPrefs.GetString(SettingsPrefix + "OutputFolderAbsolute", string.Empty); _downScaleIndex = EditorPrefs.GetInt(SettingsPrefix + "DownScaleIndex", 0); _downscaleX = EditorPrefs.GetInt(SettingsPrefix + "DownScaleX", 1); _downscaleY = EditorPrefs.GetInt(SettingsPrefix + "DownScaleY", 1); _frameRate = (CaptureBase.FrameRate)System.Enum.Parse(typeof(CaptureBase.FrameRate), EditorPrefs.GetString(SettingsPrefix + "FrameRate", "Thirty")); _supportAlpha = EditorPrefs.GetBool(SettingsPrefix + "SupportAlpha", false); _useMediaFoundationH264 = EditorPrefs.GetBool(SettingsPrefix + "UseMediaFoundationH264", false); _videoCodecIndex = EditorPrefs.GetInt(SettingsPrefix + "VideoCodecIndex", 0); _renderResolution = (CaptureBase.Resolution)EditorPrefs.GetInt(SettingsPrefix + "RenderResolution", (int)_renderResolution); _renderSize.x = EditorPrefs.GetInt(SettingsPrefix + "RenderWidth", 0); _renderSize.y = EditorPrefs.GetInt(SettingsPrefix + "RenderHeight", 0); _renderAntiAliasing = EditorPrefs.GetInt(SettingsPrefix + "RenderAntiAliasing", 0); _useContributingCameras = EditorPrefs.GetBool(SettingsPrefix + "UseContributingCameras", true); _captureAudio = EditorPrefs.GetBool(SettingsPrefix + "CaptureAudio", false); _audioCodecIndex = EditorPrefs.GetInt(SettingsPrefix + "AudioCodecIndex", 0); _audioDeviceIndex = EditorPrefs.GetInt(SettingsPrefix + "AudioDeviceIndex", 0); _useMotionBlur = EditorPrefs.GetBool(SettingsPrefix + "UseMotionBlur", false); _motionBlurSampleCount = EditorPrefs.GetInt(SettingsPrefix + "MotionBlurSampleCount", 16); _cubemapResolution = EditorPrefs.GetInt(SettingsPrefix + "CubemapResolution", 2048); _cubemapDepth = EditorPrefs.GetInt(SettingsPrefix + "CubemapDepth", 24); _cubemapStereoPacking = EditorPrefs.GetInt(SettingsPrefix + "CubemapStereoPacking", 0); _cubemapStereoIPD = EditorPrefs.GetFloat(SettingsPrefix + "CubemapStereoIPD", 0.064f); _stopMode = (StopMode)EditorPrefs.GetInt(SettingsPrefix + "StopMode", (int)_stopMode); _stopFrames = EditorPrefs.GetInt(SettingsPrefix + "StopFrames", _stopFrames); _stopSeconds = EditorPrefs.GetFloat(SettingsPrefix + "StopSeconds", _stopSeconds); if (!string.IsNullOrEmpty(_cameraName)) { Camera[] cameras = (Camera[])GameObject.FindObjectsOfType(typeof(Camera)); foreach (Camera cam in cameras) { if (cam.name == _cameraName) { _cameraNode = cam; break; } } } // Check ranges if (_videoCodecIndex >= _videoCodecNames.Length) { _videoCodecIndex = 0; } if (_audioDeviceIndex >= _audioDeviceNames.Length) { _audioDeviceIndex = 0; _captureAudio = false; } if (_audioCodecIndex >= _audioCodecNames.Length) { _audioCodecIndex = 0; _captureAudio = false; } _showAlpha = EditorPrefs.GetBool(SettingsPrefix + "ShowAlphaChannel", false); } private void SaveSettings() { EditorPrefs.SetInt(SettingsPrefix + "SourceType", (int)_sourceType); EditorPrefs.SetString(SettingsPrefix + "CameraName", _cameraName); EditorPrefs.SetInt(SettingsPrefix + "CaptureModeIndex", _captureModeIndex); EditorPrefs.SetBool(SettingsPrefix + "CaptureMouseCursor", _captureMouseCursor); EditorPrefs.SetBool(SettingsPrefix + "StartPaused", _startPaused); string mouseCursorGuid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(_mouseCursorTexture)); EditorPrefs.SetString(SettingsPrefix + "CaptureMouseTexture", mouseCursorGuid); EditorPrefs.SetInt(SettingsPrefix + "OutputType", (int)_outputType); EditorPrefs.SetString(SettingsPrefix + "NamedPipePath", _namedPipePath); EditorPrefs.SetBool(SettingsPrefix + "AutoFilenamePrefixFromScenename", _autoFilenamePrefixFromSceneName); EditorPrefs.SetString(SettingsPrefix + "AutoFilenamePrefix", _autoFilenamePrefix); EditorPrefs.SetString(SettingsPrefix + "AutoFilenameExtension", _autoFilenameExtension); EditorPrefs.SetBool(SettingsPrefix + "AppendTimestamp", _appendTimestamp); EditorPrefs.SetInt(SettingsPrefix + "OutputFolderIndex", _outputFolderIndex); EditorPrefs.SetString(SettingsPrefix + "OutputFolderRelative", _outputFolderRelative); EditorPrefs.SetString(SettingsPrefix + "OutputFolderAbsolute", _outputFolderAbsolute); EditorPrefs.SetInt(SettingsPrefix + "DownScaleIndex", _downScaleIndex); EditorPrefs.SetInt(SettingsPrefix + "DownScaleX", _downscaleX); EditorPrefs.SetInt(SettingsPrefix + "DownScaleY", _downscaleY); EditorPrefs.SetBool(SettingsPrefix + "SupportAlpha", _supportAlpha); EditorPrefs.SetBool(SettingsPrefix + "UseMediaFoundationH264", _useMediaFoundationH264); EditorPrefs.SetString(SettingsPrefix + "FrameRate", _frameRate.ToString()); EditorPrefs.SetInt(SettingsPrefix + "VideoCodecIndex", _videoCodecIndex); EditorPrefs.SetInt(SettingsPrefix + "RenderResolution", (int)_renderResolution); EditorPrefs.SetInt(SettingsPrefix + "RenderWidth", (int)_renderSize.x); EditorPrefs.SetInt(SettingsPrefix + "RenderHeight", (int)_renderSize.y); EditorPrefs.SetInt(SettingsPrefix + "RenderAntiAliasing", _renderAntiAliasing); EditorPrefs.SetBool(SettingsPrefix + "UseContributingCameras", _useContributingCameras); EditorPrefs.SetBool(SettingsPrefix + "CaptureAudio", _captureAudio); EditorPrefs.SetInt(SettingsPrefix + "AudioCodecIndex", _audioCodecIndex); EditorPrefs.SetInt(SettingsPrefix + "AudioDeviceIndex", _audioDeviceIndex); EditorPrefs.SetBool(SettingsPrefix + "UseMotionBlur", _useMotionBlur); EditorPrefs.SetInt(SettingsPrefix + "MotionBlurSampleCount", _motionBlurSampleCount); EditorPrefs.SetInt(SettingsPrefix + "CubemapResolution", _cubemapResolution); EditorPrefs.SetInt(SettingsPrefix + "CubemapDepth", _cubemapDepth); EditorPrefs.SetInt(SettingsPrefix + "CubemapStereoPacking", _cubemapStereoPacking); EditorPrefs.SetFloat(SettingsPrefix + "CubemapStereoIPD", _cubemapStereoIPD); EditorPrefs.SetInt(SettingsPrefix + "StopMode", (int)_stopMode); EditorPrefs.SetInt(SettingsPrefix + "StopFrames", _stopFrames); EditorPrefs.SetFloat(SettingsPrefix + "StopSeconds", _stopSeconds); EditorPrefs.SetBool(SettingsPrefix + "ShowAlphaChannel", _showAlpha); } private void ResetSettings() { _sourceType = SourceType.Screen; _cameraNode = null; _cameraName = string.Empty; _captureModeIndex = 0; _startPaused = false; _captureMouseCursor = false; _mouseCursorTexture = null; _outputType = CaptureBase.OutputType.VideoFile; _namedPipePath = @"\\.\pipe\pipename"; _autoFilenamePrefixFromSceneName = true; _autoFilenamePrefix = "capture"; _autoFilenameExtension = "avi"; _outputFolderIndex = 0; _outputFolderRelative = string.Empty; _outputFolderAbsolute = string.Empty; _appendTimestamp = true; _downScaleIndex = 0; _downscaleX = 1; _downscaleY = 1; _frameRate = CaptureBase.FrameRate.Thirty; _supportAlpha = false; _useMediaFoundationH264 = false; _videoCodecIndex = 0; _renderResolution = CaptureBase.Resolution.Original; _renderSize = Vector2.one; _renderAntiAliasing = 0; _useContributingCameras = true; _captureAudio = false; _audioCodecIndex = 0; _audioDeviceIndex = 0; _useMotionBlur = false; _motionBlurSampleCount = 16; _cubemapResolution = 2048; _cubemapDepth = 24; _cubemapStereoPacking = 0; _stopMode = StopMode.None; _cubemapStereoIPD = 0.064f; _stopFrames = 300; _stopSeconds = 10f; } private static CaptureBase.DownScale GetDownScaleFromIndex(int index) { CaptureBase.DownScale result = CaptureBase.DownScale.Original; switch (index) { case 0: result = CaptureBase.DownScale.Original; break; case 1: result = CaptureBase.DownScale.Half; break; case 2: result = CaptureBase.DownScale.Quarter; break; case 3: result = CaptureBase.DownScale.Eighth; break; case 4: result = CaptureBase.DownScale.Sixteenth; break; case 5: result = CaptureBase.DownScale.Custom; break; } return result; } private void Configure(CaptureBase capture) { capture._videoCodecPriority = null; capture._audioCodecPriority = null; capture._captureOnStart = false; capture._listVideoCodecsOnStart = false; capture._frameRate = _frameRate; capture._supportAlpha = _supportAlpha; capture._downScale = GetDownScaleFromIndex(_downScaleIndex); if (capture._downScale == CaptureBase.DownScale.Custom) { capture._maxVideoSize.x = _downscaleX; capture._maxVideoSize.y = _downscaleY; } capture._stopMode = _stopMode; capture._stopFrames = _stopFrames; capture._stopSeconds = _stopSeconds; capture._isRealTime = (_captureModeIndex == 0); capture._startPaused = _startPaused; capture._outputType = _outputType; if (_outputType == CaptureBase.OutputType.VideoFile) { capture._autoGenerateFilename = _appendTimestamp; capture._autoFilenamePrefix = _autoFilenamePrefix; capture._autoFilenameExtension = _autoFilenameExtension; if (!capture._autoGenerateFilename) { capture._forceFilename = _autoFilenamePrefix + "." + _autoFilenameExtension; } } else { capture._forceFilename = _namedPipePath; } capture._outputFolderType = CaptureBase.OutputPath.RelativeToProject; capture._outputFolderPath = _outputFolderRelative; if (_outputFolderIndex == 1) { capture._outputFolderType = CaptureBase.OutputPath.RelativeToPeristentData; capture._outputFolderPath = _outputFolderAbsolute; } if (_outputFolderIndex == 2) { capture._outputFolderType = CaptureBase.OutputPath.Absolute; capture._outputFolderPath = _outputFolderAbsolute; } capture._forceVideoCodecIndex = capture._codecIndex = Mathf.Max(-1, (_videoCodecIndex - 4)); capture._useMediaFoundationH264 = (_videoCodecIndex == 2); capture._noAudio = !_captureAudio; capture._forceAudioCodecIndex = capture._audioCodecIndex = Mathf.Max(-1, (_audioCodecIndex - 2)); capture._forceAudioDeviceIndex = capture._audioDeviceIndex = Mathf.Max(-1, (_audioDeviceIndex - 2)); if (_useMotionBlur && !capture._isRealTime && Camera.main != null) { capture._useMotionBlur = _useMotionBlur; capture._motionBlurSamples = _motionBlurSampleCount; capture._motionBlurCameras = new Camera[1]; capture._motionBlurCameras[0] = Camera.main; } else { capture._useMotionBlur = false; } if (_captureMouseCursor) { capture._captureMouseCursor = true; if (capture._mouseCursor == null) { capture._mouseCursor = capture.gameObject.AddComponent(); } if (capture._mouseCursor != null) { capture._mouseCursor.SetTexture(_mouseCursorTexture); } } else { capture._captureMouseCursor = false; if (capture._mouseCursor != null) { capture._mouseCursor.enabled = false; } } } private void CreateComponents() { switch (_sourceType) { case SourceType.Screen: _captureScreen = (CaptureFromScreen)GameObject.FindObjectOfType(typeof(CaptureFromScreen)); if (_captureScreen == null) { GameObject go = new GameObject(TempGameObjectName); _captureScreen = go.AddComponent(); } _capture = _captureScreen; break; case SourceType.Camera: _captureCamera = _cameraNode.gameObject.GetComponent(); if (_captureCamera == null) { _captureCamera = _cameraNode.gameObject.AddComponent(); } _captureCamera.SetCamera(_cameraNode, _useContributingCameras); _capture = _captureCamera; _capture._renderResolution = _renderResolution; _capture._renderSize = _renderSize; _capture._renderAntiAliasing = _renderAntiAliasing; break; case SourceType.Camera360: _captureCamera360 = _cameraNode.gameObject.GetComponent(); if (_captureCamera360 == null) { _captureCamera360 = _cameraNode.gameObject.AddComponent(); } _capture = _captureCamera360; _capture._renderResolution = _renderResolution; _capture._renderSize = _renderSize; _capture._renderAntiAliasing = _renderAntiAliasing; _captureCamera360._cubemapResolution = _cubemapResolution; _captureCamera360._cubemapDepth = _cubemapDepth; _captureCamera360._stereoRendering = (StereoPacking)_cubemapStereoPacking; _captureCamera360._ipd = _cubemapStereoIPD; break; case SourceType.Camera360ODS: _captureCamera360ODS = _cameraNode.gameObject.GetComponent(); if (_captureCamera360ODS == null) { _captureCamera360ODS = _cameraNode.gameObject.AddComponent(); } _capture = _captureCamera360ODS; _capture._renderResolution = _renderResolution; _capture._renderSize = _renderSize; _capture._renderAntiAliasing = _renderAntiAliasing; _captureCamera360ODS.Setup.camera = _cameraNode; _captureCamera360ODS.Setup.ipd = _odsSettings.ipd; _captureCamera360ODS.Setup.pixelSliceSize = _odsSettings.pixelSliceSize; _captureCamera360ODS.Setup.paddingSize = _odsSettings.paddingSize; _captureCamera360ODS.Setup.cameraClearMode = _odsSettings.cameraClearMode; _captureCamera360ODS.Setup.cameraClearColor= _odsSettings.cameraClearColor; break; } // TODO: Remove old components from previous captures if the mode or gameObject has changed } private void CreateGUI() { try { if (!NativePlugin.Init()) { Debug.LogError("[AVProMovieCapture] Failed to initialise"); return; } } catch (System.DllNotFoundException e) { _isFailedInit = true; string missingDllMessage = string.Empty; #if (UNITY_5 || UNITY_5_4_OR_NEWER) missingDllMessage = "Unity couldn't find the plugin DLL. Please select the native plugin files in 'Plugins/RenderHeads/AVProMovieCapture/Plugins' folder and select the correct platform in the Inspector."; #else missingDllMessage = "Unity couldn't find the plugin DLL, Unity 4.x requires the 'Plugins' folder to be at the root of your project. Please move the contents of the 'Plugins' folder (in Plugins/RenderHeads/AVProMovieCapture/Plugins) to the 'Plugins' folder in the root of your project."; #endif Debug.LogError("[AVProMovieCapture] " + missingDllMessage); #if UNITY_EDITOR UnityEditor.EditorUtility.DisplayDialog("Plugin files not found", missingDllMessage, "Ok"); #endif throw e; } // Video codec enumeration { int numVideoCodecs = Mathf.Max(0, NativePlugin.GetNumAVIVideoCodecs()); _videoCodecNames = new string[numVideoCodecs + 4]; _videoCodecNames[0] = "Uncompressed"; _videoCodecNames[1] = string.Empty; _videoCodecNames[2] = "Media Foundation H.264 (MP4)"; _videoCodecNames[3] = string.Empty; _videoCodecConfigurable = new bool[numVideoCodecs + 4]; _videoCodecConfigurable[0] = false; _videoCodecConfigurable[1] = false; _videoCodecConfigurable[2] = false; _videoCodecConfigurable[3] = false; for (int i = 0; i < numVideoCodecs; i++) { _videoCodecNames[i + 4] = i.ToString("D2") + ") " + NativePlugin.GetAVIVideoCodecName(i).Replace("/", "_"); _videoCodecConfigurable[i + 4] = NativePlugin.IsConfigureVideoCodecSupported(i); } } // Audio device enumeration { int numAudioDevices = Mathf.Max(0, NativePlugin.GetNumAVIAudioInputDevices()); _audioDeviceNames = new string[numAudioDevices + 2]; _audioDeviceNames[0] = "Unity"; _audioDeviceNames[1] = string.Empty; for (int i = 0; i < numAudioDevices; i++) { _audioDeviceNames[i + 2] = i.ToString("D2") + ") " + NativePlugin.GetAVIAudioInputDeviceName(i).Replace("/", "_"); } } // Audio codec enumeration { int numAudioCodecs = Mathf.Max(0, NativePlugin.GetNumAVIAudioCodecs()); _audioCodecNames = new string[numAudioCodecs + 2]; _audioCodecNames[0] = "Uncompressed"; _audioCodecNames[1] = string.Empty; _audioCodecConfigurable = new bool[numAudioCodecs + 2]; _audioCodecConfigurable[0] = false; _audioCodecConfigurable[1] = false; for (int i = 0; i < numAudioCodecs; i++) { _audioCodecNames[i + 2] = i.ToString("D2") + ") " + NativePlugin.GetAVIAudioCodecName(i).Replace("/", "_"); _audioCodecConfigurable[i + 2] = NativePlugin.IsConfigureAudioCodecSupported(i); } } _isInit = true; } private void OnEnable() { if (_icon == null) { _icon = Resources.Load("AVProMovieCaptureIcon"); } if (!_isCreated) { SetupWindow(); } _isTrialVersion = IsTrialVersion(); // Check that the plugin version number is not too old { float pluginVersion = NativePlugin.GetPluginVersion(); string pluginVersionString = pluginVersion.ToString("F2"); if (_isTrialVersion) { pluginVersionString += "t"; } _pluginVersionWarningText = string.Empty; if (pluginVersion.ToString("F2") != NativePlugin.ExpectedPluginVersion) { _pluginVersionWarningText = "Warning: Plugin version number " + pluginVersionString + " doesn't match the expected version number " + NativePlugin.ExpectedPluginVersion + ". It looks like the plugin didn't upgrade correctly. To resolve this please restart Unity and try to upgrade the package again."; } } } private void OnDisable() { SaveSettings(); StopCapture(); _isInit = false; _isCreated = false; Repaint(); } private void StartCapture() { _lastFileSize = 0; _lastEncodedSeconds = 0; _lastEncodedMinutes = 0; _lastEncodedFrame = 0; CreateComponents(); if (_capture != null) { Configure(_capture); _capture.SelectCodec(false); if (!_capture._noAudio) { _capture.SelectAudioCodec(false); _capture.SelectAudioDevice(false); } _capture.QueueStartCapture(); } } private void StopCapture(bool cancelCapture = false) { if (_capture != null) { if (_capture.IsCapturing()) { if (!cancelCapture) { _capture.StopCapture(); } else { _capture.CancelCapture(); } } _capture = null; _captureScreen = null; _captureCamera = null; } } // Updates 10 times/second void OnInspectorUpdate() { if (_capture != null) { if (Application.isPlaying) { _lastFileSize = _capture.GetCaptureFileSize(); if (!_capture._isRealTime) { _lastEncodedSeconds = (uint)Mathf.FloorToInt((float)_capture.NumEncodedFrames / (float)_capture._frameRate); } else { _lastEncodedSeconds = _capture.TotalEncodedSeconds; } _lastEncodedMinutes = _lastEncodedSeconds / 60; _lastEncodedSeconds = _lastEncodedSeconds % 60; _lastEncodedFrame = _capture.NumEncodedFrames % (uint)_capture._frameRate; // If the capture has stopped automatically, we need to update the UI if (_capture._stopMode != StopMode.None && _capture.NumEncodedFrames > 0 && !_capture.IsCapturing()) { StopCapture(); } } else { StopCapture(); } } else { if (_queueConfigureVideoCodec >= 0) { int configureVideoCodec = _queueConfigureVideoCodec; _queueConfigureVideoCodec = -1; NativePlugin.Init(); NativePlugin.ConfigureVideoCodec(configureVideoCodec); } if (_queueConfigureAudioCodec >= 0) { int configureAudioCodec = _queueConfigureAudioCodec; _queueConfigureAudioCodec = -1; NativePlugin.Init(); NativePlugin.ConfigureAudioCodec(configureAudioCodec); } if (_queueStart && Application.isPlaying) { _queueStart = false; StartCapture(); } } Repaint(); } private static bool ShowConfigList(string title, string[] items, bool[] isConfigurable, ref int itemIndex, bool showConfig = true, bool listEnabled = true) { bool result = false; if (itemIndex < 0 || items == null) return result; if (!string.IsNullOrEmpty(title)) { EditorGUILayout.LabelField(title, EditorStyles.boldLabel); } EditorGUI.BeginDisabledGroup(!listEnabled); EditorGUILayout.BeginHorizontal(); itemIndex = EditorGUILayout.Popup(itemIndex, items); if (showConfig && isConfigurable != null && itemIndex < isConfigurable.Length) { EditorGUI.BeginDisabledGroup(itemIndex == 0 || !isConfigurable[itemIndex]); if (GUILayout.Button("Configure")) { result = true; } EditorGUI.EndDisabledGroup(); } EditorGUILayout.EndHorizontal(); EditorGUI.EndDisabledGroup(); return result; } void OnGUI() { if (Application.platform != RuntimePlatform.WindowsEditor) { EditorGUILayout.LabelField("AVPro Movie Capture only works on the Windows platform."); return; } if (!_isInit) { if (_isFailedInit) { GUILayout.Label("Error", EditorStyles.boldLabel); GUI.enabled = false; string missingDllMessage = string.Empty; #if (UNITY_5 || UNITY_5_4_OR_NEWER) missingDllMessage = "Unity couldn't find the plugin DLL. Please select the native plugin files in 'Plugins/RenderHeads/AVProMovieCapture/Plugins' folder and select the correct platform in the Inspector."; #else missingDllMessage = "Unity couldn't find the plugin DLL, Unity 4.x requires the 'Plugins' folder to be at the root of your project. Please move the contents of the 'Plugins' folder (in Plugins/RenderHeads/AVProMovieCapture/Plugins) to the 'Plugins' folder in the root of your project."; #endif GUILayout.TextArea(missingDllMessage); GUI.enabled = true; return; } else { EditorGUILayout.LabelField("Initialising..."); return; } } if (!string.IsNullOrEmpty(_pluginVersionWarningText)) { GUI.color = Color.yellow; GUILayout.TextArea(_pluginVersionWarningText); GUI.color = Color.white; } if (_so == null) { return; } _so.Update(); #if AVPRO_MOVIECAPTURE_GRAPHICSDEVICETYPE_51 if (SystemInfo.graphicsDeviceType != UnityEngine.Rendering.GraphicsDeviceType.Direct3D11) { GUI.color = Color.yellow; GUILayout.TextArea("Consider switching to Direct3D11 for best capture results. You may need to change your Build platform to Windows."); GUI.color = Color.white; } #endif if (_isTrialVersion) { EditorUtils.DrawSectionColored("- AVPRO MOVIE CAPTURE - FREE TRIAL VERSION", ref _expandSectionTrial, DrawTrialMessage, Color.yellow, Color.yellow, Color.yellow); //EditorGUILayout.Space(); } DrawControlButtonsGUI(); EditorGUILayout.Space(); // Live Capture Stats if (Application.isPlaying && _capture != null && _capture.IsCapturing()) { if (_propStopMode.enumValueIndex != (int)StopMode.None) { Rect r = GUILayoutUtility.GetRect(128f, EditorStyles.label.CalcHeight(GUIContent.none, 32f), GUILayout.ExpandWidth(true)); float progress = _capture.GetProgress(); EditorGUI.ProgressBar(r, progress, (progress * 100f).ToString("F1") + "%"); } _scroll = EditorGUILayout.BeginScrollView(_scroll); DrawBaseCapturingGUI(_capture); DrawMoreCapturingGUI(); EditorGUILayout.EndScrollView(); } // Configuration else if (_capture == null) { string[] _toolNames = { "Settings", "About" }; _selectedTool = GUILayout.Toolbar(_selectedTool, _toolNames); switch (_selectedTool) { case 0: DrawConfigGUI_Toolbar(); _scroll = EditorGUILayout.BeginScrollView(_scroll); DrawConfigGUI(); EditorGUILayout.EndScrollView(); break; case 1: _scroll = EditorGUILayout.BeginScrollView(_scroll); DrawConfigGUI_About(); EditorGUILayout.EndScrollView(); break; } } if (_so.ApplyModifiedProperties()) { EditorUtility.SetDirty(this); } } private void DrawTrialMessage() { string message = "The free trial version is limited to 10 seconds of capture time. UPGRADE to the full package for unlimited use."; //GUI.backgroundColor = Color.yellow; //EditorGUILayout.BeginVertical(GUI.skin.box); //GUI.color = Color.yellow; //GUILayout.Label("AVPRO MOVIE CAPTURE - FREE TRIAL VERSION", EditorStyles.boldLabel); GUI.color = Color.white; GUILayout.Label(message, EditorStyles.wordWrappedLabel); if (GUILayout.Button("Upgrade Now")) { Application.OpenURL("https://www.assetstore.unity3d.com/en/#!/content/2670"); } //EditorGUILayout.EndVertical(); GUI.backgroundColor = Color.white; GUI.color = Color.white; } private void DrawControlButtonsGUI() { EditorGUILayout.BeginHorizontal(); if (_capture == null) { GUI.backgroundColor = Color.green; string startString = "Start Capture"; if (_captureModeIndex == 1) { startString = "Start Render"; } if (GUILayout.Button(startString, GUILayout.Height(32f))) { bool isReady = true; if (_sourceType == SourceType.Camera && _cameraNode == null) { Debug.LogError("[AVProMovieCapture] Please select a Camera to capture from, or select to capture from Screen."); isReady = false; } if (isReady) { if (!Application.isPlaying) { EditorApplication.isPlaying = true; _queueStart = true; } else { StartCapture(); Repaint(); } } } } else { GUI.backgroundColor = Color.cyan; if (GUILayout.Button("Cancel", GUILayout.Height(32f))) { StopCapture(true); Repaint(); } GUI.backgroundColor = Color.red; if (GUILayout.Button("Stop", GUILayout.Height(32f))) { StopCapture(false); Repaint(); } if (_capture != null) { if (_capture.IsPaused()) { GUI.backgroundColor = Color.green; if (GUILayout.Button("Resume", GUILayout.Height(32f))) { _capture.ResumeCapture(); Repaint(); } } else { GUI.backgroundColor = Color.yellow; if (GUILayout.Button("Pause", GUILayout.Height(32f))) { _capture.PauseCapture(); Repaint(); } } } } EditorGUILayout.EndHorizontal(); GUI.backgroundColor = Color.white; GUILayout.BeginHorizontal(); if (GUILayout.Button("Browse")) { if (!string.IsNullOrEmpty(CaptureBase.LastFileSaved)) { Utils.ShowInExplorer(CaptureBase.LastFileSaved); } } if (GUILayout.Button("View Last Capture")) { if (!string.IsNullOrEmpty(CaptureBase.LastFileSaved)) { Utils.OpenInDefaultApp(CaptureBase.LastFileSaved); } } GUILayout.EndHorizontal(); } public static void DrawBaseCapturingGUI(CaptureBase capture) { GUILayout.Space(8.0f); Texture texture = capture.GetPreviewTexture(); if (texture != null) { float width = Screen.width - (Screen.width / 8f); width = (Screen.width / 2f) - (Screen.width / 16f); float aspect = (float)texture.width / (float)texture.height; GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (_showAlpha) { width = (Screen.width / 2f) - (Screen.width / 16f); Rect textureRect = GUILayoutUtility.GetRect(width, width / aspect, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false)); EditorGUI.DrawPreviewTexture(textureRect, texture, null, ScaleMode.ScaleToFit); //textureRect = GUILayoutUtility.GetRect(width, width / aspect); textureRect = GUILayoutUtility.GetRect(width, width / aspect, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false)); ; EditorGUI.DrawTextureAlpha(textureRect, texture, ScaleMode.ScaleToFit); } else { Rect textureRect = GUILayoutUtility.GetRect(width, width / aspect, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false)); EditorGUI.DrawPreviewTexture(textureRect, texture, null, ScaleMode.ScaleToFit); } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); _showAlpha = GUILayout.Toggle(_showAlpha, "Show Alpha", GUILayout.ExpandWidth(false)); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(8.0f); } GUILayout.Label("Output", EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box"); EditorGUI.indentLevel++; GUILayout.Label("Recording to: " + System.IO.Path.GetFileName(capture.LastFilePath), EditorStyles.wordWrappedLabel); GUILayout.Space(8.0f); GUILayout.Label("Video"); EditorGUILayout.LabelField("Dimensions", capture.GetRecordingWidth() + "x" + capture.GetRecordingHeight() + " @ " + ((int)capture._frameRate).ToString() + "hz"); if (!capture._useMediaFoundationH264) { EditorGUILayout.LabelField("Codec", capture._codecName); } else { EditorGUILayout.LabelField("Codec", "Media Foundation H.264"); } if (!capture._noAudio && capture._isRealTime) { GUILayout.Label("Audio"); EditorGUILayout.LabelField("Source", capture._audioDeviceName); EditorGUILayout.LabelField("Codec", capture._audioCodecName); if (capture._audioDeviceName == "Unity") { EditorGUILayout.LabelField("Sample Rate", capture._unityAudioSampleRate.ToString() + "hz"); EditorGUILayout.LabelField("Channels", capture._unityAudioChannelCount.ToString()); } } EditorGUI.indentLevel--; EditorGUILayout.EndVertical(); GUILayout.Space(8.0f); GUILayout.Label("Stats", EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box"); EditorGUI.indentLevel++; if (capture.FPS > 0f) { Color originalColor = GUI.color; if (capture._isRealTime) { float fpsDelta = (capture.FPS - (int)capture._frameRate); GUI.color = Color.red; if (fpsDelta > -10) { GUI.color = Color.yellow; } if (fpsDelta > -2) { GUI.color = Color.green; } } EditorGUILayout.LabelField("Capture Rate", string.Format("{0:0.##} / {1} FPS", capture.FPS, (int)capture._frameRate)); GUI.color = originalColor; } else { EditorGUILayout.LabelField("Capture Rate", string.Format(".. / {0} FPS", (int)capture._frameRate)); } EditorGUILayout.LabelField("Encoded Frames", capture.NumEncodedFrames.ToString()); EditorGUI.indentLevel--; EditorGUILayout.EndVertical(); } public void DrawMoreCapturingGUI() { GUILayout.Label("More Stats", EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box"); EditorGUI.indentLevel++; EditorGUILayout.LabelField("File Size", ((float)_lastFileSize / (1024f * 1024f)).ToString("F1") + "MB"); EditorGUILayout.LabelField("Video Length", _lastEncodedMinutes.ToString("00") + ":" + _lastEncodedSeconds.ToString("00") + "." + _lastEncodedFrame.ToString("000")); GUILayout.Label("Dropped Frames"); EditorGUILayout.LabelField("In Unity", _capture.NumDroppedFrames.ToString()); EditorGUILayout.LabelField("In Encoder", _capture.NumDroppedEncoderFrames.ToString()); if (!_capture._noAudio && _capture._isRealTime) { if (_capture._audioCapture && _capture._audioDeviceName == "Unity") { EditorGUILayout.LabelField("Audio Overflows", _capture._audioCapture.OverflowCount.ToString()); } } EditorGUI.indentLevel--; EditorGUILayout.EndVertical(); } private void DrawConfigGUI_Toolbar() { string[] _toolNames = { "General", "Visual", "Audio", "Output" }; _selectedConfigTool = GUILayout.Toolbar(_selectedConfigTool, _toolNames); } private void DrawConfigGUI() { switch (_selectedConfigTool) { case 0: DrawConfigGUI_General(); break; case 1: DrawConfigGUI_Visual(); break; case 2: DrawConfigGUI_Audio(); break; case 3: DrawConfigGUI_Output(); break; } GUILayout.FlexibleSpace(); } public static void DrawConfigGUI_About() { string version = NativePlugin.GetPluginVersion().ToString("F2"); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (_icon == null) { _icon = Resources.Load("AVProMovieCaptureIcon"); } if (_icon != null) { GUILayout.Label(new GUIContent(_icon)); } GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUI.color = Color.yellow; GUILayout.Label("AVPro Movie Capture by RenderHeads Ltd", EditorStyles.boldLabel); GUI.color = Color.white; GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUI.color = Color.yellow; GUILayout.Label("version " + version + " (scripts v" + NativePlugin.ScriptVersion + ")"); GUI.color = Color.white; GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); // Links { GUILayout.Space(32f); GUI.backgroundColor = Color.white; EditorGUILayout.LabelField("AVPro Movie Capture Links", EditorStyles.boldLabel); GUILayout.Space(8f); EditorGUILayout.LabelField("Documentation"); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("User Manual", GUILayout.ExpandWidth(false))) { Application.OpenURL(LinkUserManual); } EditorGUILayout.EndHorizontal(); GUILayout.Space(16f); GUILayout.Label("Rate and Review (★★★★☆)", GUILayout.ExpandWidth(false)); if (GUILayout.Button("Unity Asset Store Page", GUILayout.ExpandWidth(false))) { if (!_isTrialVersion) { Application.OpenURL(LinkAssetStorePage); } else { Application.OpenURL(LinkFreeAssetStorePage); } } GUILayout.Space(16f); GUILayout.Label("Community"); if (GUILayout.Button("Unity Forum Page", GUILayout.ExpandWidth(false))) { Application.OpenURL(LinkForumPage); } GUILayout.Space(16f); GUILayout.Label("Homepage", GUILayout.ExpandWidth(false)); if (GUILayout.Button("AVPro Movie Capture Website", GUILayout.ExpandWidth(false))) { Application.OpenURL(LinkPluginWebsite); } GUILayout.Space(16f); GUILayout.Label("Bugs and Support"); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Email unitysupport@renderheads.com", GUILayout.ExpandWidth(false))) { Application.OpenURL(LinkEmailSupport); } EditorGUILayout.EndHorizontal(); } // Credits { GUILayout.Space(32f); EditorGUILayout.LabelField("Credits", EditorStyles.boldLabel); GUILayout.Space(8f); EditorUtils.CentreLabel("Programming", EditorStyles.boldLabel); EditorUtils.CentreLabel("Andrew Griffiths"); EditorUtils.CentreLabel("Sunrise Wang"); GUILayout.Space(8f); EditorUtils.CentreLabel("Graphics", EditorStyles.boldLabel); EditorUtils.CentreLabel("Jeff Rusch"); EditorUtils.CentreLabel("Luke Godward"); } // Bug reporting { GUILayout.Space(32f); EditorGUILayout.LabelField("Bug Reporting Notes", EditorStyles.boldLabel); EditorGUILayout.SelectableLabel(SupportMessage, EditorStyles.wordWrappedLabel, GUILayout.Height(180f)); } } private void DrawConfigGUI_General() { //GUILayout.Label("General", EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box"); //EditorGUI.indentLevel++; // Time { GUILayout.Space(8f); EditorGUILayout.LabelField("Time", EditorStyles.boldLabel); EditorGUI.indentLevel++; _captureModeIndex = EditorGUILayout.Popup("Capture Mode", _captureModeIndex, _captureModes); EditorUtils.EnumAsDropdown("Frame Rate", _propFrameRate, new string[] { "1", "10", "15", "24", "25", "30", "50", "60", "75", "90", "120" }); //_frameRate = (CaptureBase.FrameRate)EditorGUILayout.EnumPopup("Frame Rate", _frameRate); EditorGUI.indentLevel--; } // Source GUILayout.Space(8f); EditorGUILayout.LabelField("Source", EditorStyles.boldLabel); EditorGUI.indentLevel++; EditorUtils.EnumAsDropdown("Source", _propSourceType, _sourceNames); if (_sourceType == SourceType.Camera360ODS && _captureModeIndex == 0) { GUI.color = Color.yellow; GUILayout.TextArea("Warning: This source type is very slow and not suitable for 'Realtime Capture'. Consider changing the capture mode to 'Offline Render'."); GUI.color = Color.white; } //_sourceType = (SourceType)EditorGUILayout.EnumPopup("Type", _sourceType); if (_sourceType == SourceType.Camera || _sourceType == SourceType.Camera360 || _sourceType == SourceType.Camera360ODS) { if (_cameraNode == null) { _cameraNode = Utils.GetUltimateRenderCamera(); } _cameraNode = (Camera)EditorGUILayout.ObjectField("Camera", _cameraNode, typeof(Camera), true); if (_sourceType == SourceType.Camera && _cameraNode != null) { EditorGUILayout.PropertyField(_propUseContributingCameras, new GUIContent("Contributing Cameras")); } } EditorGUI.indentLevel--; // Screen options if (_sourceType == SourceType.Screen) { GUILayout.Space(8f); EditorGUILayout.LabelField("Cursor", EditorStyles.boldLabel); EditorGUI.indentLevel++; _captureMouseCursor = EditorGUILayout.Toggle("Capture Mouse Cursor", _captureMouseCursor); _mouseCursorTexture = (Texture2D)EditorGUILayout.ObjectField("Mouse Cursor Texture", _mouseCursorTexture, typeof(Texture2D), false); EditorGUI.indentLevel--; } // Camera overrides if (_sourceType == SourceType.Camera || _sourceType == SourceType.Camera360 || _sourceType == SourceType.Camera360ODS) { GUILayout.Space(8f); EditorGUILayout.LabelField("Camera Overrides", EditorStyles.boldLabel); EditorGUI.indentLevel++; { EditorUtils.EnumAsDropdown("Resolution", _propRenderResolution, CaptureBaseEditor.ResolutionStrings); } if (_renderResolution == CaptureBase.Resolution.Custom) { _renderSize = EditorGUILayout.Vector2Field("Size", _renderSize); _renderSize = new Vector2(Mathf.Clamp((int)_renderSize.x, 1, NativePlugin.MaxRenderWidth), Mathf.Clamp((int)_renderSize.y, 1, NativePlugin.MaxRenderHeight)); } { string currentAA = "None"; if (QualitySettings.antiAliasing > 1) { currentAA = QualitySettings.antiAliasing.ToString() + "x"; } EditorUtils.IntAsDropdown("Anti-aliasing", _propRenderAntiAliasing, new string[] { "Current (" + currentAA + ")", "None", "2x", "4x", "8x" }, new int[] { -1, 1, 2, 4, 8 }); } if (_cameraNode != null) { if (_cameraNode.actualRenderingPath == RenderingPath.DeferredLighting #if AVPRO_MOVIECAPTURE_DEFERREDSHADING || _cameraNode.actualRenderingPath == RenderingPath.DeferredShading #endif ) { GUI.color = Color.yellow; GUILayout.TextArea("Warning: Antialiasing by MSAA is not supported as camera is using deferred rendering path"); GUI.color = Color.white; _renderAntiAliasing = -1; } if (_cameraNode.clearFlags == CameraClearFlags.Nothing || _cameraNode.clearFlags == CameraClearFlags.Depth) { if (_renderResolution != CaptureBase.Resolution.Original || _renderAntiAliasing != -1) { GUI.color = Color.yellow; GUILayout.TextArea("Warning: Overriding camera resolution or anti-aliasing when clear flag is set to " + _cameraNode.clearFlags + " may result in incorrect captures"); GUI.color = Color.white; } } } EditorGUI.indentLevel--; } // 360 Cubemap if (_sourceType == SourceType.Camera360) { GUILayout.Space(8f); EditorGUILayout.LabelField("360 Camera", EditorStyles.boldLabel); EditorGUI.indentLevel++; { CaptureBase.CubemapResolution cubemapEnum = (CaptureBase.CubemapResolution)_cubemapResolution; _cubemapResolution = (int)((CaptureBase.CubemapResolution)EditorGUILayout.EnumPopup("Resolution", cubemapEnum)); } { CaptureBase.CubemapDepth depthEnum = (CaptureBase.CubemapDepth)_cubemapDepth; _cubemapDepth = (int)((CaptureBase.CubemapDepth)EditorGUILayout.EnumPopup("Depth", depthEnum)); } { StereoPacking stereoEnum = (StereoPacking)_cubemapStereoPacking; _cubemapStereoPacking = (int)((StereoPacking)EditorGUILayout.EnumPopup("Stereo Mode", stereoEnum)); } if (_cubemapStereoPacking != (int)StereoPacking.None) { _cubemapStereoIPD = EditorGUILayout.FloatField("Interpupillary distance", _cubemapStereoIPD); } EditorGUI.indentLevel--; } // 360 Cubemap ODS if (_sourceType == SourceType.Camera360ODS) { GUILayout.Space(8f); EditorGUI.indentLevel++; EditorGUILayout.LabelField("Source Options", EditorStyles.boldLabel); EditorGUI.indentLevel++; { EditorGUILayout.PropertyField(_propOdsIPD, new GUIContent("Interpupillary distance")); EditorGUILayout.PropertyField(_propOdsPixelSliceSize); EditorGUILayout.PropertyField(_propOdsPaddingSize); EditorGUILayout.PropertyField(_propOdsCameraClearMode); EditorGUILayout.PropertyField(_propOdsCameraClearColor); } EditorGUI.indentLevel--; EditorGUI.indentLevel--; } // Start / Stop { GUILayout.Space(8f); EditorGUILayout.LabelField("Start / Stop", EditorStyles.boldLabel); EditorGUI.indentLevel++; _startPaused = EditorGUILayout.Toggle("Start Paused", _startPaused); _stopMode = (StopMode)EditorGUILayout.EnumPopup("Stop Mode", _stopMode); if (_stopMode == StopMode.FramesEncoded) { _stopFrames = EditorGUILayout.IntField("Frames", _stopFrames); } else if (_stopMode == StopMode.SecondsElapsed || _stopMode == StopMode.SecondsEncoded) { _stopSeconds = EditorGUILayout.FloatField("Seconds", _stopSeconds); } EditorGUI.indentLevel--; } GUILayout.Space(8f); if (GUILayout.Button("Reset All Settings")) { ResetSettings(); } GUILayout.Space(4f); //EditorGUI.indentLevel--; EditorGUILayout.EndVertical(); } private void DrawConfigGUI_Output() { //GUILayout.Label("Target", EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box"); //EditorGUI.indentLevel++; EditorUtils.EnumAsDropdown("Output Type", _propOutputType, new string[] { "Video File", "Named Pipe" }); GUILayout.Space(8f); if (_propOutputType.enumValueIndex == (int)CaptureBase.OutputType.VideoFile) { // File path EditorGUILayout.LabelField("File Path", EditorStyles.boldLabel); EditorGUI.indentLevel++; _outputFolderIndex = EditorGUILayout.Popup("Relative to", _outputFolderIndex, _outputFolders); if (_outputFolderIndex == 0 || _outputFolderIndex == 1) { _outputFolderRelative = EditorGUILayout.TextField("SubFolder(s)", _outputFolderRelative); } else { EditorGUILayout.BeginHorizontal(); _outputFolderAbsolute = EditorGUILayout.TextField("Path", _outputFolderAbsolute); if (GUILayout.Button(">", GUILayout.Width(22))) { _outputFolderAbsolute = EditorUtility.SaveFolderPanel("Select Folder To Store Video Captures", System.IO.Path.GetFullPath(System.IO.Path.Combine(Application.dataPath, "../")), ""); EditorUtility.SetDirty(this); } EditorGUILayout.EndHorizontal(); } EditorGUI.indentLevel--; GUILayout.Space(8f); // File name EditorGUILayout.LabelField("File Name", EditorStyles.boldLabel); EditorGUI.indentLevel++; _autoFilenamePrefixFromSceneName = EditorGUILayout.Toggle("From Scene Name", _autoFilenamePrefixFromSceneName); if (_autoFilenamePrefixFromSceneName) { #if AVPRO_MOVIECAPTURE_SCENEMANAGER_53 string currentScenePath = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().path; #else string currentScenePath = EditorApplication.currentScene; #endif _autoFilenamePrefix = System.IO.Path.GetFileNameWithoutExtension(currentScenePath); if (string.IsNullOrEmpty(_autoFilenamePrefix)) { _autoFilenamePrefix = "capture"; } } EditorGUI.BeginDisabledGroup(_autoFilenamePrefixFromSceneName); _autoFilenamePrefix = EditorGUILayout.TextField("Prefix", _autoFilenamePrefix); EditorGUI.EndDisabledGroup(); _autoFilenameExtension = EditorGUILayout.TextField("Extension", _autoFilenameExtension); _appendTimestamp = EditorGUILayout.Toggle("Append Timestamp", _appendTimestamp); EditorGUI.indentLevel--; } else if (_propOutputType.enumValueIndex == (int)CaptureBase.OutputType.NamedPipe) { EditorGUILayout.PropertyField(_propNamedPipePath); } //EditorGUI.indentLevel--; EditorGUILayout.EndVertical(); } private void DrawConfigGUI_Visual() { //GUILayout.Label("Video", EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box"); //EditorGUI.indentLevel++; { Vector2 outSize = Vector2.zero; if (_sourceType == SourceType.Screen) { // We can't just use Screen.width and Screen.height because Unity returns the size of this window // So instead we look for a camera with no texture target and a valid viewport int inWidth = 1; int inHeight = 1; foreach (Camera cam in Camera.allCameras) { if (cam.targetTexture == null) { float rectWidth = Mathf.Clamp01(cam.rect.width + cam.rect.x) - Mathf.Clamp01(cam.rect.x); float rectHeight = Mathf.Clamp01(cam.rect.height + cam.rect.y) - Mathf.Clamp01(cam.rect.y); if (rectWidth > 0.0f && rectHeight > 0.0f) { inWidth = Mathf.FloorToInt(cam.pixelWidth / rectWidth); inHeight = Mathf.FloorToInt(cam.pixelHeight / rectHeight); //Debug.Log (rectWidth + " " + (cam.rect.height - cam.rect.y) + " " + cam.pixelHeight + " = " + inWidth + "x" + inHeight); break; } } } outSize = CaptureBase.GetRecordingResolution(inWidth, inHeight, GetDownScaleFromIndex(_downScaleIndex), new Vector2(_downscaleX, _downscaleY)); } else { if (_cameraNode != null) { int inWidth = Mathf.FloorToInt(_cameraNode.pixelRect.width); int inHeight = Mathf.FloorToInt(_cameraNode.pixelRect.height); if (_renderResolution != CaptureBase.Resolution.Original) { float rectWidth = Mathf.Clamp01(_cameraNode.rect.width + _cameraNode.rect.x) - Mathf.Clamp01(_cameraNode.rect.x); float rectHeight = Mathf.Clamp01(_cameraNode.rect.height + _cameraNode.rect.y) - Mathf.Clamp01(_cameraNode.rect.y); if (_renderResolution == CaptureBase.Resolution.Custom) { inWidth = (int)_renderSize.x; inHeight = (int)_renderSize.y; } else { CaptureBase.GetResolution(_renderResolution, ref inWidth, ref inHeight); inWidth = Mathf.FloorToInt(inWidth * rectWidth); inHeight = Mathf.FloorToInt(inHeight * rectHeight); } } outSize = CaptureBase.GetRecordingResolution(inWidth, inHeight, GetDownScaleFromIndex(_downScaleIndex), new Vector2(_downscaleX, _downscaleY)); } } GUILayout.Space(8f); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUI.color = Color.cyan; GUILayout.TextArea("Output: " + (int)outSize.x + " x " + (int)outSize.y + " @ " + (int)_frameRate); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(8f); GUI.color = Color.white; } _downScaleIndex = EditorGUILayout.Popup("Down Scale", _downScaleIndex, _downScales); if (_downScaleIndex == 5) { Vector2 maxVideoSize = new Vector2(_downscaleX, _downscaleY); maxVideoSize = EditorGUILayout.Vector2Field("Size", maxVideoSize); _downscaleX = Mathf.Clamp((int)maxVideoSize.x, 1, NativePlugin.MaxRenderWidth); _downscaleY = Mathf.Clamp((int)maxVideoSize.y, 1, NativePlugin.MaxRenderHeight); } _supportAlpha = EditorGUILayout.Toggle("Support Alpha", _supportAlpha); GUILayout.Space(8f); //EditorGUILayout.LabelField("Codec", EditorStyles.boldLabel); if (_outputType == CaptureBase.OutputType.VideoFile) { if (ShowConfigList("Codec", _videoCodecNames, _videoCodecConfigurable, ref _videoCodecIndex, true, true)) { _queueConfigureVideoCodec = Mathf.Max(-1, _videoCodecIndex - 4); } _useMediaFoundationH264 = (_videoCodecIndex == 2); if (_useMediaFoundationH264) { GUI.color = Color.yellow; GUILayout.TextArea("Warning: Make sure to set the file extension to .mp4"); GUI.color = Color.white; } else { if (_videoCodecIndex > 0 && ( _videoCodecNames[_videoCodecIndex].EndsWith("Cinepak Codec by Radius") || _videoCodecNames[_videoCodecIndex].EndsWith("DV Video Encoder") || _videoCodecNames[_videoCodecIndex].EndsWith("Microsoft Video 1") || _videoCodecNames[_videoCodecIndex].EndsWith("Microsoft RLE") || _videoCodecNames[_videoCodecIndex].EndsWith("Logitech Video (I420)") || _videoCodecNames[_videoCodecIndex].EndsWith("Intel IYUV codec") )) { GUI.color = Color.yellow; GUILayout.TextArea("Warning: Legacy codec, not recommended"); GUI.color = Color.white; } if (_videoCodecIndex >= 0 && (_videoCodecNames[_videoCodecIndex].Contains("Decoder") || _videoCodecNames[_videoCodecIndex].Contains("Decompressor"))) { GUI.color = Color.yellow; GUILayout.TextArea("Warning: Codec may contain decompressor only"); GUI.color = Color.white; } if (_videoCodecIndex >= 0 && _videoCodecNames[_videoCodecIndex].EndsWith("Uncompressed")) { GUI.color = Color.yellow; GUILayout.TextArea("Warning: Uncompressed may result in very large files"); GUI.color = Color.white; } if (_videoCodecNames.Length < 8) { GUI.color = Color.cyan; EditorGUILayout.TextArea("Low number of codecs, consider installing more"); GUI.color = Color.white; } } } else { GUI.color = Color.yellow; EditorGUILayout.TextArea("Codec selection not available when using named pipe output"); GUI.color = Color.white; } DrawConfigGUI_MotionBlur(); //EditorGUI.indentLevel--; EditorGUILayout.EndVertical(); } private void DrawConfigGUI_MotionBlur() { EditorGUI.BeginDisabledGroup(_captureModeIndex == 0); //EditorGUILayout.BeginVertical("box"); //EditorGUI.indentLevel++; GUILayout.Space(8f); GUILayout.Label("Motion Blur (beta)", EditorStyles.boldLabel); //EditorGUILayout.BeginVertical("box"); //EditorGUI.indentLevel++; if (_captureModeIndex == 0) { GUI.color = Color.yellow; EditorGUILayout.TextArea("Motion Blur only available in Offline Render mode"); GUI.color = Color.white; } _useMotionBlur = EditorGUILayout.Toggle("Use Motion Blur", _useMotionBlur); EditorGUI.BeginDisabledGroup(!_useMotionBlur); EditorGUILayout.PrefixLabel("Samples"); EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(false)); //EditorGUILayout.LabelField("moo", GUILayout.ExpandWidth(false)); _motionBlurSampleCount = EditorGUILayout.IntSlider(_motionBlurSampleCount, 0, 64); EditorGUILayout.EndHorizontal(); EditorGUI.EndDisabledGroup(); //EditorGUI.indentLevel--; //EditorGUILayout.EndVertical(); EditorGUI.EndDisabledGroup(); } private void DrawConfigGUI_Audio() { EditorGUI.BeginDisabledGroup(_captureModeIndex != 0 || _outputType != CaptureBase.OutputType.VideoFile); //GUILayout.Label("Audio", EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box"); //EditorGUI.indentLevel++; if (_captureModeIndex != 0) { GUI.color = Color.yellow; EditorGUILayout.TextArea("Audio capture not available in Offline Render mode"); GUI.color = Color.white; } if (_outputType == CaptureBase.OutputType.NamedPipe) { GUI.color = Color.yellow; EditorGUILayout.TextArea("Audio capture not available when using named pipe output"); GUI.color = Color.white; } _captureAudio = EditorGUILayout.Toggle("Capture Audio", _captureAudio); GUILayout.Space(8f); EditorGUI.BeginDisabledGroup(!_captureAudio); if (ShowConfigList("Source", _audioDeviceNames, null, ref _audioDeviceIndex, false)) { } GUILayout.Space(8f); if (ShowConfigList("Codec", _audioCodecNames, _audioCodecConfigurable, ref _audioCodecIndex)) { _queueConfigureAudioCodec = Mathf.Max(-1, _audioCodecIndex - 2); } if (_audioCodecIndex > 0 && (_audioCodecNames[_audioCodecIndex].EndsWith("MPEG Layer-3"))) { GUI.color = Color.yellow; GUILayout.TextArea("Warning: We have had reports that this codec doesn't work. Consider using a different codec"); GUI.color = Color.white; } EditorGUI.EndDisabledGroup(); //EditorGUI.indentLevel--; EditorGUILayout.EndVertical(); EditorGUI.EndDisabledGroup(); } private static bool IsTrialVersion() { return NativePlugin.IsTrialVersion(); } } } #endif