#if UNITY_EDITOR
#if UNITY_2017_3_OR_NEWER
#define AVPRO_MOVIECAPTURE_OFFLINE_AUDIOCAPTURE
#endif
#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
#if UNITY_2017_1_OR_NEWER
#define AVPRO_MOVIECAPTURE_PLAYABLES_SUPPORT
#endif
#if UNITY_2018_1_OR_NEWER
// Unity 2018.1 introduces stereo cubemap render methods
#define AVPRO_MOVIECAPTURE_UNITY_STEREOCUBEMAP_RENDER
#endif
#if !UNITY_2018_3_OR_NEWER
#define SUPPORT_SCENE_VIEW_GIZMOS_CAPTURE
#endif
using UnityEngine;
using UnityEditor;
//-----------------------------------------------------------------------------
// Copyright 2012-2022 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 = "Temp97435_MovieCapture";
private const string SettingsPrefix = "AVProMovieCapture.EditorWindow.";
private const string SelectorPrefix = SettingsPrefix + "CameraSelector.";
private GameObject _gameObject;
private CaptureBase _capture;
private CaptureFromScreen _captureScreen;
private CaptureFromCamera _captureCamera;
private CaptureFromCamera360 _captureCamera360;
private CaptureFromCamera360ODS _captureCamera360ODS;
private CameraSelector _cameraSelector;
#if AVPRO_MOVIECAPTURE_PLAYABLES_SUPPORT
private TimelineController _timelineController;
#endif
private static bool _isTrialVersion = false;
private static bool _isCreated = false;
private static bool _isInit = false;
private static bool _isFailedInit = false;
private static bool _showAlpha = false;
private static int _superSizeIndex = 0;
[SerializeField] string _screenshotFolder = "Captures/Shots/";
[SerializeField] EditorScreenshot.Options _screenshotOptions = new EditorScreenshot.Options();
private static string[] _fileExtensions = new string[0];
private static string[] _audioDeviceNames = new string[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", "Desktop", "Pictures", "Videos" }; // NOTE: PhotoLibrary is not included as Unity Editor doesn't have permission to use it anyway
private readonly string[] _sourceNames = { "Screen", "Camera", "Camera 360 (Mono+Stereo)", "Camera 360 (experimental ODS Stereo)" };
private readonly string[] _tabNames = { "Capture", "Visual", "Audio", "Encoding" };
private readonly static GUIContent _guiBlankSpace = new GUIContent(" ");
private readonly static GUIContent _guiCameraSelectorTag = new GUIContent("Tag");
private readonly static GUIContent _guiCameraSelectorName = new GUIContent("Name");
private readonly static GUIContent _guiContributingCameras = new GUIContent("Contributing Cameras");
private readonly static GUIContent _guiCaptureWorldSpaceUI= new GUIContent("Capture Worldspace UI");
private readonly static GUIContent _guiCameraRotation = new GUIContent("Camera Rotation");
private readonly static GUIContent _guiInterpupillaryDistance = new GUIContent("Interpupillary distance");
private readonly static GUIContent _guiStartDelay = new GUIContent("Start Delay");
private readonly static GUIContent _guiSeconds = new GUIContent("Seconds");
private readonly static GUIContent _guiStartFrame = new GUIContent("Start Frame");
private readonly static GUIContent _guiZeroDigits = new GUIContent("Zero Digits");
private readonly static GUIContent _guiStereoPacking = new GUIContent("Stereo Packing");
private readonly static GUIContent _guiSphericalLayout = new GUIContent("Spherical Layout");
private enum SourceType
{
Screen,
Camera,
Camera360,
Camera360ODS,
}
private enum ConfigTabs
{
Capture = 0,
Visual = 1,
Audio = 2,
Encoding = 3,
}
[SerializeField] SourceType _sourceType = SourceType.Screen;
private Camera _cameraNode;
private string _cameraName;
private int _captureModeIndex;
private int _outputFolderIndex;
[SerializeField] OutputTarget _outputTarget = OutputTarget.VideoFile;
[SerializeField] ImageSequenceFormat _imageSequenceFormat = ImageSequenceFormat.PNG;
private bool _filenamePrefixFromSceneName = true;
private string _filenamePrefix = "capture";
private string _filenameExtension = "mp4";
private int _fileContainerIndex = 0;
[SerializeField] int _imageSequenceStartFrame = 0;
[SerializeField, Range(2, 12)] int _imageSequenceZeroDigits = 6;
private string _outputFolderRelative = "Captures";
private string _outputFolderAbsolute = string.Empty;
private bool _appendTimestamp = true;
[SerializeField] string _namedPipePath = @"\\.\pipe\pipename";
private int _downScaleIndex;
private int _downscaleX;
private int _downscaleY;
private bool _captureMouseCursor = false;
private Texture2D _mouseCursorTexture = null;
[SerializeField] CaptureBase.Resolution _renderResolution = CaptureBase.Resolution.Original;
private Vector2 _renderSize;
[SerializeField] int _renderAntiAliasing;
[SerializeField] bool _useContributingCameras = true;
[SerializeField] float _frameRate = 30f;
[SerializeField] int _timelapseScale = 1;
private AudioCaptureSource _audioCaptureSource = AudioCaptureSource.None;
[SerializeField, Range(8000, 96000)] int _manualAudioSampleRate = 48000;
[SerializeField, Range(1, 8)] int _manualAudioChannelCount = 2;
private Vector2 _scroll = Vector2.zero;
private bool _queueStart;
private Codec _queueConfigureVideoCodec = null;
private Codec _queueConfigureAudioCodec = null;
private bool _useMotionBlur = false;
private int _motionBlurSampleCount = 16;
private int _cubemapResolution = 2048;
private int _cubemapDepth = 24;
[SerializeField] bool _render180Degrees = false;
[SerializeField] bool _captureWorldSpaceGUI = false;
[SerializeField] bool _supportCameraRotation = false;
[SerializeField] bool _onlyLeftRightRotation = false;
private int _cubemapStereoPacking = 0;
private float _cubemapStereoIPD = 0.064f;
[SerializeField] StartDelayMode _startDelay = StartDelayMode.None;
[SerializeField] float _startDelaySeconds = 0f;
[SerializeField] StopMode _stopMode = StopMode.None;
private int _stopFrames = 300;
private float _stopSeconds = 10f;
[SerializeField] CameraSelector.SelectByMode _selectBy = CameraSelector.SelectByMode.HighestDepthCamera;
[SerializeField] CameraSelector.ScanFrequencyMode _scanFrequency = CameraSelector.ScanFrequencyMode.SceneLoad;
[SerializeField] bool _scanHiddenCameras = false;
[SerializeField] string _selectCameraTag = "MainCamera";
[SerializeField] string _selectCameraName = "Main Camera";
private SerializedProperty _propCameraSelectorSelectBy;
private SerializedProperty _propCameraSelectorScanFrequency;
private SerializedProperty _propCameraSelectorScanHiddenCameras;
private SerializedProperty _propCameraSelectorTag;
private SerializedProperty _propCameraSelectorName;
private SerializedProperty _propSourceType;
private SerializedProperty _propOutputTarget;
private SerializedProperty _propImageSequenceFormat;
private SerializedProperty _propImageSequenceStartFrame;
private SerializedProperty _propImageSequenceZeroDigits;
private SerializedProperty _propNamedPipePath;
private SerializedProperty _propFrameRate;
[Tooltip("Timelapse scale makes the frame capture run at a fraction of the target frame rate. Default value is 1")]
private SerializedProperty _propTimelapseScale;
private SerializedProperty _propStartDelay;
private SerializedProperty _propStartDelaySeconds;
private SerializedProperty _propStopMode;
private SerializedProperty _propRenderResolution;
private SerializedProperty _propUseContributingCameras;
private SerializedProperty _propRender180Degrees;
private SerializedProperty _propCaptureWorldSpaceGUI;
private SerializedProperty _propSupportCameraRotation;
private SerializedProperty _propOnlyLeftRightRotation;
private SerializedProperty _propManualAudioSampleRate;
private SerializedProperty _propManualAudioChannelCount;
private SerializedProperty _propRenderAntiAliasing;
private SerializedProperty _propOdsRender180Degrees;
private SerializedProperty _propOdsCamera;
private SerializedProperty _propOdsIPD;
private SerializedProperty _propOdsPixelSliceSize;
private SerializedProperty _propOdsPaddingSize;
private SerializedProperty _propOdsCameraClearMode;
private SerializedProperty _propOdsCameraClearColor;
[SerializeField] CaptureFromCamera360ODS.Settings _odsSettings = new CaptureFromCamera360ODS.Settings();
private SerializedProperty _propVideoHintsAverageBitrate;
#if UNITY_EDITOR_WIN
private SerializedProperty _propVideoHintsMaximumBitrate;
#endif
private SerializedProperty _propVideoHintsQuality;
private SerializedProperty _propVideoHintsKeyframeInterval;
private SerializedProperty _propVideoHintsAllowFastStart;
private SerializedProperty _propVideoHintsTransparency;
#if UNITY_EDITOR_WIN
private SerializedProperty _propVideoHintsUseHardwareEncoding;
#elif UNITY_EDITOR_OSX
private SerializedProperty _propVideoHintsEnableFragmentedWriting;
private SerializedProperty _propVideoHintsMovieFragmentInterval;
#endif
private SerializedProperty _propVideoHintsInjectStereoPacking;
private SerializedProperty _propVideoHintsStereoPacking;
private SerializedProperty _propVideoHintsInjectSphericalVideoLayout;
private SerializedProperty _propVideoHintsSphericalVideoLayout;
#if UNITY_EDITOR_OSX
private SerializedProperty _propImageHintsQuality;
#endif
private SerializedProperty _propImageHintsTransparency;
private SerializedProperty _propScreenshotFolder;
private SerializedProperty _propScreenshotOptions;
[SerializeField] EncoderHints _encoderHints = new EncoderHints();
// TODO: we should actually be saving these parameters per-scene...
private Codec _videoCodec = null;
private Codec _audioCodec = null;
private Device _audioInputDevice = null;
private long _lastFileSize;
private uint _lastEncodedMinutes;
private uint _lastEncodedSeconds;
private uint _lastEncodedFrame;
private int _selectedTool;
private int _selectedConfigTab;
private bool _expandSectionTrial = true;
private static Texture2D _icon;
private string _pluginVersionWarningText = string.Empty;
private SerializedObject _so;
private const string LinkPluginWebsite = "http://renderheads.com/products/avpro-movie-capture/";
private const string LinkForumPage = "http://forum.unity3d.com/threads/released-avpro-movie-capture.120717/";
private const string LinkAssetStorePage = "https://assetstore.unity.com/packages/tools/video/avpro-movie-capture-151061?aid=1101lcNgx";
private const string LinkSupport = "https://github.com/RenderHeads/UnityPlugin-AVProMovieCapture/issues";
private const string LinkUserManual = "https://www.renderheads.com/content/docs/AVProMovieCapture/articles/download.html";
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)
|| (Application.platform == RuntimePlatform.OSXEditor))
{
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] SerializedObject is null");
}
_propSourceType = _so.AssertFindProperty("_sourceType");
_propOutputTarget = _so.AssertFindProperty("_outputTarget");
_propImageSequenceFormat = _so.AssertFindProperty("_imageSequenceFormat");
_propImageSequenceStartFrame = _so.AssertFindProperty("_imageSequenceStartFrame");
_propImageSequenceZeroDigits = _so.AssertFindProperty("_imageSequenceZeroDigits");
_propNamedPipePath = _so.AssertFindProperty("_namedPipePath");
_propRenderResolution = _so.AssertFindProperty("_renderResolution");
_propUseContributingCameras = _so.AssertFindProperty("_useContributingCameras");
_propRender180Degrees = _so.AssertFindProperty("_render180Degrees");
_propCaptureWorldSpaceGUI = _so.AssertFindProperty("_captureWorldSpaceGUI");
_propSupportCameraRotation = _so.AssertFindProperty("_supportCameraRotation");
_propOnlyLeftRightRotation = _so.AssertFindProperty("_onlyLeftRightRotation");
// Audio
_propManualAudioSampleRate = _so.AssertFindProperty("_manualAudioSampleRate");
_propManualAudioChannelCount = _so.AssertFindProperty("_manualAudioChannelCount");
// Time
_propFrameRate = _so.AssertFindProperty("_frameRate");
_propTimelapseScale = _so.AssertFindProperty("_timelapseScale");
// Start/Stop
_propStopMode = _so.AssertFindProperty("_stopMode");
_propStartDelay = _so.AssertFindProperty("_startDelay");
_propStartDelaySeconds = _so.AssertFindProperty("_startDelaySeconds");
// Camera Selector
_propCameraSelectorSelectBy = _so.AssertFindProperty("_selectBy");
_propCameraSelectorScanFrequency = _so.AssertFindProperty("_scanFrequency");
_propCameraSelectorScanHiddenCameras = _so.AssertFindProperty("_scanHiddenCameras");
_propCameraSelectorTag = _so.AssertFindProperty("_selectCameraTag");
_propCameraSelectorName = _so.AssertFindProperty("_selectCameraName");
_propRenderAntiAliasing = _so.AssertFindProperty("_renderAntiAliasing");
_propOdsIPD = _so.AssertFindProperty("_odsSettings.ipd");
_propOdsRender180Degrees = _so.AssertFindProperty("_odsSettings.render180Degrees");
_propOdsPixelSliceSize = _so.AssertFindProperty("_odsSettings.pixelSliceSize");
_propOdsPaddingSize = _so.AssertFindProperty("_odsSettings.paddingSize");
_propOdsCameraClearMode = _so.AssertFindProperty("_odsSettings.cameraClearMode");
_propOdsCameraClearColor = _so.AssertFindProperty("_odsSettings.cameraClearColor");
_propVideoHintsAverageBitrate = _so.AssertFindProperty("_encoderHints.videoHints.averageBitrate");
#if UNITY_EDITOR_WIN
_propVideoHintsMaximumBitrate = _so.AssertFindProperty("_encoderHints.videoHints.maximumBitrate");
#endif
_propVideoHintsQuality = _so.AssertFindProperty("_encoderHints.videoHints.quality");
_propVideoHintsKeyframeInterval = _so.AssertFindProperty("_encoderHints.videoHints.keyframeInterval");
_propVideoHintsAllowFastStart = _so.AssertFindProperty("_encoderHints.videoHints.allowFastStartStreamingPostProcess");
_propVideoHintsTransparency = _so.AssertFindProperty("_encoderHints.videoHints.transparency");
#if UNITY_EDITOR_WIN
_propVideoHintsUseHardwareEncoding = _so.AssertFindProperty("_encoderHints.videoHints.useHardwareEncoding");
#elif UNITY_EDITOR_OSX
_propVideoHintsEnableFragmentedWriting = _so.AssertFindProperty("_encoderHints.videoHints.enableFragmentedWriting");
_propVideoHintsMovieFragmentInterval = _so.AssertFindProperty("_encoderHints.videoHints.movieFragmentInterval");
#endif
_propVideoHintsInjectStereoPacking = _so.AssertFindProperty("_encoderHints.videoHints.injectStereoPacking");
_propVideoHintsStereoPacking = _so.AssertFindProperty("_encoderHints.videoHints.stereoPacking");
_propVideoHintsInjectSphericalVideoLayout = _so.AssertFindProperty("_encoderHints.videoHints.injectSphericalVideoLayout");
_propVideoHintsSphericalVideoLayout = _so.AssertFindProperty("_encoderHints.videoHints.sphericalVideoLayout");
#if UNITY_EDITOR_OSX
_propImageHintsQuality = _so.AssertFindProperty("_encoderHints.imageHints.quality");
#endif
_propImageHintsTransparency = _so.AssertFindProperty("_encoderHints.imageHints.transparency");
_propScreenshotOptions = _so.AssertFindProperty("_screenshotOptions");
_propScreenshotFolder = _so.AssertFindProperty("_screenshotFolder");
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);
_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));
}
}
_outputTarget = (OutputTarget)EditorPrefs.GetInt(SettingsPrefix + "OutputTarget", (int)_outputTarget);
_imageSequenceFormat = (ImageSequenceFormat)EditorPrefs.GetInt(SettingsPrefix + "ImageSequenceFormat", (int)_imageSequenceFormat);
_namedPipePath = EditorPrefs.GetString(SettingsPrefix + "NamedPipePath", _namedPipePath);
_filenamePrefixFromSceneName = EditorPrefs.GetBool(SettingsPrefix + "FilenamePrefixFromScenename", _filenamePrefixFromSceneName);
_filenamePrefix = EditorPrefs.GetString(SettingsPrefix + "FilenamePrefix", "capture");
_filenameExtension = EditorPrefs.GetString(SettingsPrefix + "FilenameExtension", _filenameExtension);
_fileContainerIndex = EditorPrefs.GetInt(SettingsPrefix + "FileContainerIndex", _fileContainerIndex);
_appendTimestamp = EditorPrefs.GetBool(SettingsPrefix + "AppendTimestamp", true);
_imageSequenceStartFrame = EditorPrefs.GetInt(SettingsPrefix + "ImageSequenceStartFrame", 0);
_imageSequenceZeroDigits = EditorPrefs.GetInt(SettingsPrefix + "ImageSequenceZeroDigits", 6);
_outputFolderIndex = EditorPrefs.GetInt(SettingsPrefix + "OutputFolderIndex", (int)CaptureBase.OutputPath.RelativeToProject);
_outputFolderRelative = EditorPrefs.GetString(SettingsPrefix + "OutputFolderRelative", "Captures");
_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 = EditorPrefs.GetFloat(SettingsPrefix + "FrameRate", _frameRate);
_timelapseScale = EditorPrefs.GetInt(SettingsPrefix + "TimelapseScale", 1);
_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);
_audioCaptureSource = (AudioCaptureSource)EditorPrefs.GetInt(SettingsPrefix + "AudioCaptureSource", (int)_audioCaptureSource);
_audioInputDevice = DeviceManager.AudioInputDevices.FindDevice(EditorPrefs.GetString(SettingsPrefix + "AudioInputDeviceName", ""));
_manualAudioChannelCount = Mathf.Clamp(EditorPrefs.GetInt(SettingsPrefix + "ManualAudioChannelCount", (int)_manualAudioChannelCount), 1, 8);
_manualAudioSampleRate = Mathf.Clamp(EditorPrefs.GetInt(SettingsPrefix + "ManualAudioSampleRate", (int)_manualAudioSampleRate), 8000, 96000);
_useMotionBlur = EditorPrefs.GetBool(SettingsPrefix + "UseMotionBlur", false);
_motionBlurSampleCount = EditorPrefs.GetInt(SettingsPrefix + "MotionBlurSampleCount", 16);
_render180Degrees = EditorPrefs.GetBool(SettingsPrefix + "Render180Degrees", false);
_captureWorldSpaceGUI = EditorPrefs.GetBool(SettingsPrefix + "CaptureWorldSpaceGUI", false);
_supportCameraRotation = EditorPrefs.GetBool(SettingsPrefix + "SupportCameraRotation", false);
_onlyLeftRightRotation = EditorPrefs.GetBool(SettingsPrefix + "OnlyLeftRightRotation", false);
_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);
_startDelay = (StartDelayMode)EditorPrefs.GetInt(SettingsPrefix + "StartDelay", (int)_startDelay);
_startDelaySeconds = EditorPrefs.GetFloat(SettingsPrefix + "StartDelaySeconds", _startDelaySeconds);
_stopMode = (StopMode)EditorPrefs.GetInt(SettingsPrefix + "StopMode", (int)_stopMode);
_stopFrames = EditorPrefs.GetInt(SettingsPrefix + "StopFrames", _stopFrames);
_stopSeconds = EditorPrefs.GetFloat(SettingsPrefix + "StopSeconds", _stopSeconds);
_encoderHints.videoHints.averageBitrate = (uint)EditorPrefs.GetInt(SettingsPrefix + "EncoderHints.VideoHints.AverageBitrate", (int)_encoderHints.videoHints.averageBitrate);
_encoderHints.videoHints.maximumBitrate = (uint)EditorPrefs.GetInt(SettingsPrefix + "EncoderHints.VideoHints.MaximumBitrate", (int)_encoderHints.videoHints.maximumBitrate);
_encoderHints.videoHints.quality = EditorPrefs.GetFloat(SettingsPrefix + "EncoderHints.VideoHints.Quality", _encoderHints.videoHints.quality);
_encoderHints.videoHints.keyframeInterval = (uint)EditorPrefs.GetInt(SettingsPrefix + "EncoderHints.VideoHints.KeyframeInterval", (int)_encoderHints.videoHints.keyframeInterval);
_encoderHints.videoHints.allowFastStartStreamingPostProcess = EditorPrefs.GetBool(SettingsPrefix + "EncoderHints.VideoHints.AllowFastStart", _encoderHints.videoHints.allowFastStartStreamingPostProcess);
_encoderHints.videoHints.transparency = (Transparency)EditorPrefs.GetInt(SettingsPrefix + "EncoderHints.VideoHints.Transparency", (int)_encoderHints.videoHints.transparency);
_encoderHints.videoHints.useHardwareEncoding = EditorPrefs.GetBool(SettingsPrefix + "EncoderHints.VideoHints.UseHardwareEncoding", _encoderHints.videoHints.useHardwareEncoding);
_encoderHints.videoHints.enableFragmentedWriting = EditorPrefs.GetBool(SettingsPrefix + "EncoderHints.VideoHints.EnableFragmentedWriting", _encoderHints.videoHints.enableFragmentedWriting);
_encoderHints.videoHints.movieFragmentInterval = (double)EditorPrefs.GetFloat(SettingsPrefix + "EncoderHints.VideoHints.MovieFragmentInterval", (float)_encoderHints.videoHints.movieFragmentInterval);
_encoderHints.videoHints.injectStereoPacking = (NoneAutoCustom)EditorPrefs.GetInt(SettingsPrefix + "EncoderHints.VideoHints.InjectStereoPacking", (int)_encoderHints.videoHints.injectStereoPacking);
_encoderHints.videoHints.stereoPacking = (StereoPacking)EditorPrefs.GetInt(SettingsPrefix + "EncoderHints.VideoHints.StereoPacking", (int)_encoderHints.videoHints.stereoPacking);
_encoderHints.videoHints.injectSphericalVideoLayout = (NoneAutoCustom)EditorPrefs.GetInt(SettingsPrefix + "EncoderHints.VideoHints.InjectSphericalVideoLayout", (int)_encoderHints.videoHints.injectSphericalVideoLayout);
_encoderHints.videoHints.sphericalVideoLayout = (SphericalVideoLayout)EditorPrefs.GetInt(SettingsPrefix + "EncoderHints.VideoHints.SphericalVideoLayout", (int)_encoderHints.videoHints.sphericalVideoLayout);
_encoderHints.imageHints.quality = EditorPrefs.GetFloat(SettingsPrefix + "EncoderHints.ImageHints.Quality", _encoderHints.imageHints.quality);
_encoderHints.imageHints.transparency = (Transparency)EditorPrefs.GetInt(SettingsPrefix + "EncoderHints.ImageHints.Transparency", (int)_encoderHints.imageHints.transparency);
if (!string.IsNullOrEmpty(_cameraName))
{
Camera[] cameras = (Camera[])GameObject.FindObjectsOfType(typeof(Camera));
foreach (Camera cam in cameras)
{
if (cam.name == _cameraName)
{
_cameraNode = cam;
break;
}
}
}
_showAlpha = EditorPrefs.GetBool(SettingsPrefix + "ShowAlphaChannel", false);
_superSizeIndex = EditorPrefs.GetInt(SettingsPrefix + "SuperSizeIndex", 0);
_screenshotFolder = EditorPrefs.GetString(SettingsPrefix + "ScreenshotFolder", _screenshotFolder);
_screenshotOptions.exrPrecision = (EditorScreenshot.ExrPrecision)EditorPrefs.GetInt(SettingsPrefix + "ScreenshotOptions.ExrPrecision", (int)_screenshotOptions.exrPrecision);
_screenshotOptions.exrCompression = (EditorScreenshot.ExrCompression)EditorPrefs.GetInt(SettingsPrefix + "ScreenshotOptions.ExrCompression", (int)_screenshotOptions.exrCompression);
_screenshotOptions.jpgQuality = EditorPrefs.GetInt(SettingsPrefix + "ScreenshotOptions.JpgQuality", (int)_screenshotOptions.jpgQuality);
// Codecs
_videoCodec = CodecManager.VideoCodecs.FindCodec(EditorPrefs.GetString(SettingsPrefix + "VideoCodecName", ""));
_audioCodec = CodecManager.AudioCodecs.FindCodec(EditorPrefs.GetString(SettingsPrefix + "AudioCodecName", ""));
UpdateSelectedCodec();
// Camera selector
_selectBy = (CameraSelector.SelectByMode)EditorPrefs.GetInt(SelectorPrefix + "SelectBy", (int)_selectBy);
_scanFrequency = (CameraSelector.ScanFrequencyMode)EditorPrefs.GetInt(SelectorPrefix + "ScanFrequency", (int)_scanFrequency);
_scanHiddenCameras = EditorPrefs.GetBool(SelectorPrefix + "ScanHiddenCameras", _scanHiddenCameras);
_selectCameraTag = EditorPrefs.GetString(SelectorPrefix + "Tag", _selectCameraTag);
_selectCameraName = EditorPrefs.GetString(SelectorPrefix + "Name", _selectCameraName);
}
private void SaveSettings()
{
EditorPrefs.SetInt(SettingsPrefix + "SourceType", (int)_sourceType);
EditorPrefs.SetString(SettingsPrefix + "CameraName", _cameraName);
EditorPrefs.SetInt(SettingsPrefix + "CaptureModeIndex", _captureModeIndex);
EditorPrefs.SetBool(SettingsPrefix + "CaptureMouseCursor", _captureMouseCursor);
string mouseCursorGuid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(_mouseCursorTexture));
EditorPrefs.SetString(SettingsPrefix + "CaptureMouseTexture", mouseCursorGuid);
EditorPrefs.SetInt(SettingsPrefix + "OutputTarget", (int)_outputTarget);
EditorPrefs.SetInt(SettingsPrefix + "ImageSequenceFormat", (int)_imageSequenceFormat);
EditorPrefs.SetString(SettingsPrefix + "NamedPipePath", _namedPipePath);
EditorPrefs.SetBool(SettingsPrefix + "FilenamePrefixFromScenename", _filenamePrefixFromSceneName);
EditorPrefs.SetString(SettingsPrefix + "FilenamePrefix", _filenamePrefix);
EditorPrefs.SetString(SettingsPrefix + "FilenameExtension", _filenameExtension);
EditorPrefs.SetInt(SettingsPrefix + "FileContainerIndex", _fileContainerIndex);
EditorPrefs.SetBool(SettingsPrefix + "AppendTimestamp", _appendTimestamp);
EditorPrefs.SetInt(SettingsPrefix + "ImageSequenceStartFrame", _imageSequenceStartFrame);
EditorPrefs.SetInt(SettingsPrefix + "ImageSequenceZeroDigits", _imageSequenceZeroDigits);
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.SetFloat(SettingsPrefix + "FrameRate", _frameRate);
EditorPrefs.SetInt(SettingsPrefix + "TimelapseScale", _timelapseScale);
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.SetString(SettingsPrefix + "VideoCodecName", (_videoCodec != null)?_videoCodec.Name:string.Empty);
EditorPrefs.SetString(SettingsPrefix + "AudioCodecName", (_audioCodec != null)?_audioCodec.Name:string.Empty);
EditorPrefs.SetInt(SettingsPrefix + "AudioCaptureSource", (int)_audioCaptureSource);
EditorPrefs.SetString(SettingsPrefix + "AudioInputDeviceName", (_audioInputDevice != null)?_audioInputDevice.Name:string.Empty);
EditorPrefs.SetInt(SettingsPrefix + "ManualAudioChannelCount", _manualAudioChannelCount);
EditorPrefs.SetInt(SettingsPrefix + "ManualAudioSampleRate", _manualAudioSampleRate);
EditorPrefs.SetBool(SettingsPrefix + "UseMotionBlur", _useMotionBlur);
EditorPrefs.SetInt(SettingsPrefix + "MotionBlurSampleCount", _motionBlurSampleCount);
EditorPrefs.SetBool(SettingsPrefix + "Render180Degrees", _render180Degrees);
EditorPrefs.SetBool(SettingsPrefix + "CaptureWorldSpaceGUI", _captureWorldSpaceGUI);
EditorPrefs.SetBool(SettingsPrefix + "SupportCameraRotation", _supportCameraRotation);
EditorPrefs.SetBool(SettingsPrefix + "OnlyLeftRightRotation", _onlyLeftRightRotation);
EditorPrefs.SetInt(SettingsPrefix + "CubemapResolution", _cubemapResolution);
EditorPrefs.SetInt(SettingsPrefix + "CubemapDepth", _cubemapDepth);
EditorPrefs.SetInt(SettingsPrefix + "CubemapStereoPacking", _cubemapStereoPacking);
EditorPrefs.SetFloat(SettingsPrefix + "CubemapStereoIPD", _cubemapStereoIPD);
EditorPrefs.SetInt(SettingsPrefix + "StartDelay", (int)_startDelay);
EditorPrefs.SetFloat(SettingsPrefix + "StartDelaySeconds", _startDelaySeconds);
EditorPrefs.SetInt(SettingsPrefix + "StopMode", (int)_stopMode);
EditorPrefs.SetInt(SettingsPrefix + "StopFrames", _stopFrames);
EditorPrefs.SetFloat(SettingsPrefix + "StopSeconds", _stopSeconds);
EditorPrefs.SetInt(SettingsPrefix + "EncoderHints.VideoHints.AverageBitrate", (int)_encoderHints.videoHints.averageBitrate);
EditorPrefs.SetInt(SettingsPrefix + "EncoderHints.VideoHints.MaximumBitrate", (int)_encoderHints.videoHints.maximumBitrate);
EditorPrefs.SetFloat(SettingsPrefix + "EncoderHints.VideoHints.Quality", _encoderHints.videoHints.quality);
EditorPrefs.SetInt(SettingsPrefix + "EncoderHints.VideoHints.KeyframeInterval", (int)_encoderHints.videoHints.keyframeInterval);
EditorPrefs.SetBool(SettingsPrefix + "EncoderHints.VideoHints.AllowFastStart", _encoderHints.videoHints.allowFastStartStreamingPostProcess);
EditorPrefs.SetInt(SettingsPrefix + "EncoderHints.VideoHints.Transparency", (int)_encoderHints.videoHints.transparency);
EditorPrefs.SetBool(SettingsPrefix + "EncoderHints.VideoHints.UseHardwareEncoding", _encoderHints.videoHints.useHardwareEncoding);
EditorPrefs.SetBool(SettingsPrefix + "EncoderHints.VideoHints.EnableFragmentedWriting", _encoderHints.videoHints.enableFragmentedWriting);
EditorPrefs.SetFloat(SettingsPrefix + "EncoderHints.VideoHints.MovieFragmentInterval", (float)_encoderHints.videoHints.movieFragmentInterval);
EditorPrefs.SetInt(SettingsPrefix + "EncoderHints.VideoHints.InjectStereoPacking", (int)_encoderHints.videoHints.injectStereoPacking);
EditorPrefs.SetInt(SettingsPrefix + "EncoderHints.VideoHints.StereoPacking", (int)_encoderHints.videoHints.stereoPacking);
EditorPrefs.SetInt(SettingsPrefix + "EncoderHints.VideoHints.InjectSphericalVideoLayout", (int)_encoderHints.videoHints.injectSphericalVideoLayout);
EditorPrefs.SetInt(SettingsPrefix + "EncoderHints.VideoHints.SphericalVideoLayout", (int)_encoderHints.videoHints.sphericalVideoLayout);
EditorPrefs.SetFloat(SettingsPrefix + "EncoderHints.ImageHints.Quality", _encoderHints.imageHints.quality);
EditorPrefs.SetInt(SettingsPrefix + "EncoderHints.ImageHints.Transparency", (int)_encoderHints.imageHints.transparency);
EditorPrefs.SetBool(SettingsPrefix + "ShowAlphaChannel", _showAlpha);
EditorPrefs.SetInt(SettingsPrefix + "SuperSizeIndex", _superSizeIndex);
EditorPrefs.SetString(SettingsPrefix + "ScreenshotFolder", _screenshotFolder);
EditorPrefs.SetInt(SettingsPrefix + "ScreenshotOptions.ExrPrecision", (int)_screenshotOptions.exrPrecision);
EditorPrefs.SetInt(SettingsPrefix + "ScreenshotOptions.ExrCompression", (int)_screenshotOptions.exrCompression);
EditorPrefs.SetInt(SettingsPrefix + "ScreenshotOptions.JpgQuality", _screenshotOptions.jpgQuality);
// Camera selector
EditorPrefs.SetInt(SelectorPrefix + "SelectBy", (int)_selectBy);
EditorPrefs.SetInt(SelectorPrefix + "ScanFrequency", (int)_scanFrequency);
EditorPrefs.SetBool(SelectorPrefix + "ScanHiddenCameras", _scanHiddenCameras);
EditorPrefs.SetString(SelectorPrefix + "Tag", _selectCameraTag);
EditorPrefs.SetString(SelectorPrefix + "Name", _selectCameraName);
}
private void ResetSettings()
{
_sourceType = SourceType.Screen;
_cameraNode = null;
_cameraName = string.Empty;
_captureModeIndex = 0;
_captureMouseCursor = false;
_mouseCursorTexture = null;
_outputTarget = OutputTarget.VideoFile;
_imageSequenceFormat = ImageSequenceFormat.PNG;
_namedPipePath = @"\\.\pipe\test_pipe";
_filenamePrefixFromSceneName = true;
_filenamePrefix = "capture";
_filenameExtension = "mp4";
_imageSequenceStartFrame = 0;
_imageSequenceZeroDigits = 6;
_outputFolderIndex = (int)CaptureBase.OutputPath.RelativeToProject;
_outputFolderRelative = "Captures";
_outputFolderAbsolute = string.Empty;
_appendTimestamp = true;
_downScaleIndex = 0;
_downscaleX = 1;
_downscaleY = 1;
_frameRate = 30f;
_timelapseScale = 1;
_videoCodec = null;
_audioCodec = null;
_renderResolution = CaptureBase.Resolution.Original;
_renderSize = Vector2.one;
_renderAntiAliasing = 0;
_useContributingCameras = true;
_audioCaptureSource = AudioCaptureSource.None;
_audioInputDevice = null;
_manualAudioChannelCount = 2;
_manualAudioSampleRate = 48000;
_useMotionBlur = false;
_motionBlurSampleCount = 16;
_render180Degrees = false;
_captureWorldSpaceGUI = false;
_supportCameraRotation = false;
_onlyLeftRightRotation = false;
_cubemapResolution = 2048;
_cubemapDepth = 24;
_cubemapStereoPacking = 0;
_startDelay = StartDelayMode.None;
_startDelaySeconds = 0f;
_stopMode = StopMode.None;
_cubemapStereoIPD = 0.064f;
_stopFrames = 300;
_stopSeconds = 10f;
_encoderHints = new EncoderHints();
_odsSettings = new CaptureFromCamera360ODS.Settings();
UpdateSelectedCodec();
// Camera selector
_selectBy = CameraSelector.SelectByMode.HighestDepthCamera;
_scanFrequency = CameraSelector.ScanFrequencyMode.SceneLoad;
_scanHiddenCameras = false;
_selectCameraTag = "MainCamera";
_selectCameraName = "Main Camera";
}
private void Configure(CaptureBase capture)
{
capture.VideoCodecPriorityWindows = new string[0];
capture.VideoCodecPriorityMacOS = new string[0];
capture.AudioCodecPriorityWindows = new string[0];
capture.AudioCodecPriorityMacOS = new string[0];
capture.FrameRate = _frameRate;
capture.TimelapseScale = _timelapseScale;
capture.ResolutionDownScale = GetDownScaleFromIndex(_downScaleIndex);
if (capture.ResolutionDownScale == CaptureBase.DownScale.Custom)
{
capture.ResolutionDownscaleCustom = new Vector2(_downscaleX, _downscaleY);
}
capture.StartDelay = _startDelay;
capture.StartDelaySeconds = _startDelaySeconds;
capture.StopMode = _stopMode;
capture.StopAfterFramesElapsed = _stopFrames;
capture.StopAfterSecondsElapsed = _stopSeconds;
capture.SetEncoderHints(_encoderHints);
capture.IsRealTime = IsCaptureRealTime();
capture.OutputTarget = _outputTarget;
if (_outputTarget == OutputTarget.VideoFile)
{
capture.FilenamePrefix = _filenamePrefix;
capture.AppendFilenameTimestamp = _appendTimestamp;
capture.AllowManualFileExtension = true;
capture.FilenameExtension = _filenameExtension;
}
else if (_outputTarget == OutputTarget.NamedPipe)
{
capture.NamedPipePath = _namedPipePath;
}
else if (_outputTarget == OutputTarget.ImageSequence)
{
capture.NativeImageSequenceFormat = _imageSequenceFormat;
capture.ImageSequenceStartFrame = _imageSequenceStartFrame;
capture.ImageSequenceZeroDigits = _imageSequenceZeroDigits;
capture.FilenamePrefix = _filenamePrefix;
}
if (_outputFolderIndex == (int)CaptureBase.OutputPath.RelativeToPeristentData)
{
capture.OutputFolder = CaptureBase.OutputPath.RelativeToPeristentData;
capture.OutputFolderPath = _outputFolderRelative;
}
else if (_outputFolderIndex == (int)CaptureBase.OutputPath.Absolute)
{
capture.OutputFolder = CaptureBase.OutputPath.Absolute;
capture.OutputFolderPath = _outputFolderAbsolute;
}
else if (_outputFolderIndex == (int)CaptureBase.OutputPath.RelativeToDesktop)
{
capture.OutputFolder = CaptureBase.OutputPath.RelativeToDesktop;
capture.OutputFolderPath = _outputFolderRelative;
}
else if (_outputFolderIndex == (int)CaptureBase.OutputPath.RelativeToPictures)
{
capture.OutputFolder = CaptureBase.OutputPath.RelativeToPictures;
capture.OutputFolderPath = _outputFolderRelative;
}
else if (_outputFolderIndex == (int)CaptureBase.OutputPath.RelativeToVideos)
{
capture.OutputFolder = CaptureBase.OutputPath.RelativeToVideos;
capture.OutputFolderPath = _outputFolderRelative;
}
else if (_outputFolderIndex == (int)CaptureBase.OutputPath.PhotoLibrary)
{
capture.OutputFolder = CaptureBase.OutputPath.PhotoLibrary;
capture.OutputFolderPath = _outputFolderRelative;
}
else
{
capture.OutputFolder = CaptureBase.OutputPath.RelativeToProject;
capture.OutputFolderPath = _outputFolderRelative;
}
capture.NativeForceVideoCodecIndex = (_videoCodec != null)?_videoCodec.Index:-1;
capture.AudioCaptureSource = IsAudioCaptured()?_audioCaptureSource:AudioCaptureSource.None;
if (capture.AudioCaptureSource != AudioCaptureSource.None)
{
capture.NativeForceAudioCodecIndex = (_audioCodec != null)?_audioCodec.Index:-1;
if (capture.AudioCaptureSource == AudioCaptureSource.Microphone)
{
capture.ForceAudioInputDeviceIndex = (_audioInputDevice != null)?_audioInputDevice.Index:-1;
}
else if (capture.AudioCaptureSource == AudioCaptureSource.Manual)
{
capture.ManualAudioChannelCount = _manualAudioChannelCount;
capture.ManualAudioSampleRate = _manualAudioSampleRate;
}
}
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 (_captureScreen != null)
{
// Toggle mouse cursor
if (_captureMouseCursor)
{
_captureScreen.CaptureMouseCursor = true;
if (_captureScreen.MouseCursor == null)
{
_captureScreen.MouseCursor = capture.gameObject.AddComponent();
}
if (_captureScreen.MouseCursor != null)
{
_captureScreen.MouseCursor.SetTexture(_mouseCursorTexture);
}
}
else
{
_captureScreen.CaptureMouseCursor = false;
if (_captureScreen.MouseCursor != null)
{
_captureScreen.MouseCursor.enabled = false;
}
}
}
}
private void CreateComponents()
{
// Create hidden gameobject
if (_gameObject == null)
{
_gameObject = GameObject.Find(TempGameObjectName);
if (_gameObject == null)
{
_gameObject = new GameObject(TempGameObjectName);
_gameObject.hideFlags = HideFlags.HideAndDontSave;
#if UNITY_5 || UNITY_5_4_OR_NEWER
_gameObject.hideFlags |= HideFlags.DontSaveInBuild|HideFlags.DontSaveInEditor|HideFlags.DontUnloadUnusedAsset;
#endif
Object.DontDestroyOnLoad(_gameObject);
}
}
// Remove old capture component if different
if (_captureScreen != null && _sourceType != SourceType.Screen)
{
Destroy(_captureScreen);
_captureScreen = null;
}
if (_captureCamera != null && _sourceType != SourceType.Camera)
{
Destroy(_captureCamera);
_captureCamera = null;
}
if (_captureCamera360 != null && _sourceType != SourceType.Camera360)
{
Destroy(_captureCamera360);
_captureCamera360 = null;
}
if (_captureCamera360ODS != null && _sourceType != SourceType.Camera360ODS)
{
Destroy(_captureCamera360ODS);
_captureCamera360ODS = null;
}
if (_cameraSelector != null && _sourceType == SourceType.Screen)
{
Destroy(_cameraSelector);
_cameraSelector = null;
}
#if AVPRO_MOVIECAPTURE_PLAYABLES_SUPPORT
// Remove timelineController for realtime captures
if (IsCaptureRealTime())
{
if (_timelineController != null)
{
Destroy(_timelineController);
_timelineController = null;
}
}
// Add timelineController for non-realtime captures
else
{
if (_timelineController == null)
{
_timelineController = _gameObject.AddComponent();
}
}
#endif
switch (_sourceType)
{
case SourceType.Screen:
if (_captureScreen == null)
{
_captureScreen = _gameObject.AddComponent();
}
_capture = _captureScreen;
break;
case SourceType.Camera:
if (_captureCamera == null)
{
_captureCamera = _gameObject.AddComponent();
}
if (_cameraSelector == null)
{
_cameraSelector = _gameObject.AddComponent();
}
SetupCameraSelector();
_captureCamera.SetCamera(_cameraNode, _useContributingCameras);
_captureCamera.CameraSelector = _cameraSelector;
_capture = _captureCamera;
_capture.CameraRenderResolution = _renderResolution;
_capture.CameraRenderCustomResolution = _renderSize;
_capture.CameraRenderAntiAliasing = _renderAntiAliasing;
break;
case SourceType.Camera360:
if (_captureCamera360 == null)
{
_captureCamera360 = _gameObject.AddComponent();
}
if (_cameraSelector == null)
{
_cameraSelector = _gameObject.AddComponent();
}
SetupCameraSelector();
_capture = _captureCamera360;
_capture.CameraRenderResolution = _renderResolution;
_capture.CameraRenderCustomResolution = _renderSize;
_capture.CameraRenderAntiAliasing = _renderAntiAliasing;
_captureCamera360.SetCamera(_cameraNode);
_captureCamera360.CameraSelector = _cameraSelector;
_captureCamera360.Render180Degrees = _render180Degrees;
_captureCamera360.SupportCameraRotation = _supportCameraRotation;
_captureCamera360.OnlyLeftRightRotation = _onlyLeftRightRotation;
_captureCamera360.SupportGUI = _captureWorldSpaceGUI;
_captureCamera360.CubemapFaceResolution = (CaptureBase.CubemapResolution)_cubemapResolution;
_captureCamera360.CubemapDepthResolution = (CaptureBase.CubemapDepth)_cubemapDepth;
_captureCamera360.StereoRendering = (StereoPacking)_cubemapStereoPacking;
_captureCamera360.IPD = _cubemapStereoIPD;
break;
case SourceType.Camera360ODS:
if (_captureCamera360ODS == null)
{
_captureCamera360ODS = _gameObject.AddComponent();
}
if (_cameraSelector == null)
{
_cameraSelector = _gameObject.AddComponent();
}
SetupCameraSelector();
_capture = _captureCamera360ODS;
_capture.CameraRenderResolution = _renderResolution;
_capture.CameraRenderCustomResolution = _renderSize;
_capture.CameraRenderAntiAliasing = _renderAntiAliasing;
_captureCamera360ODS.Setup.camera = _cameraNode;
_captureCamera360ODS.Setup.cameraSelector = _cameraSelector;
_captureCamera360ODS.Setup.render180Degrees = _odsSettings.render180Degrees;
_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;
}
#if AVPRO_MOVIECAPTURE_PLAYABLES_SUPPORT
if (_capture != null)
{
_capture.TimelineController = _timelineController;
}
#endif
}
private void SetupCameraSelector()
{
if (_cameraSelector == null) return;
_cameraSelector.SelectBy = _selectBy;
_cameraSelector.ScanFrequency = _scanFrequency;
_cameraSelector.ScanHiddenCameras = _scanHiddenCameras;
if (_selectBy == CameraSelector.SelectByMode.Tag)
{
_cameraSelector.SelectTag = _selectCameraTag;
}
else if (_selectBy == CameraSelector.SelectByMode.Name)
{
_cameraSelector.SelectName = _selectCameraName;
}
else if (_selectBy == CameraSelector.SelectByMode.Manual)
{
_cameraSelector.Camera = _cameraNode;
}
}
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;
}
// Audio device enumeration
{
int numAudioDevices = Mathf.Max(0, NativePlugin.GetAudioInputDeviceCount());
_audioDeviceNames = new string[numAudioDevices];
for (int i = 0; i < numAudioDevices; i++)
{
_audioDeviceNames[i] = i.ToString("D2") + ") " + NativePlugin.GetAudioInputDeviceName(i).Replace("/", "_");
}
}
_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
{
string pluginVersionString = NativePlugin.GetPluginVersionString();
_pluginVersionWarningText = string.Empty;
if (!pluginVersionString.StartsWith(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();
if (_gameObject != null)
{
DestroyImmediate(_gameObject);
_gameObject = null;
_capture = null;
_captureScreen = null;
_captureCamera = null;
_captureCamera360 = null;
_captureCamera360ODS = null;
_cameraSelector = null;
#if AVPRO_MOVIECAPTURE_PLAYABLES_SUPPORT
_timelineController = null;
#endif
}
_isInit = false;
_isCreated = false;
Repaint();
}
private void StartCapture()
{
_lastFileSize = 0;
_lastEncodedSeconds = 0;
_lastEncodedMinutes = 0;
_lastEncodedFrame = 0;
CreateComponents();
if (_capture != null)
{
Configure(_capture);
_capture.SelectVideoCodec();
if (_capture.AudioCaptureSource != AudioCaptureSource.None)
{
_capture.SelectAudioCodec();
_capture.SelectAudioInputDevice();
}
_capture.QueueStartCapture();
}
}
private void StopCapture(bool cancelCapture = false)
{
if (_capture != null)
{
if (_capture.IsCapturing())
{
if (!cancelCapture)
{
_capture.StopCapture();
}
else
{
_capture.CancelCapture();
}
}
_capture = null;
}
}
// Updates 10 times/second
void OnInspectorUpdate()
{
if (_capture != null)
{
if (Application.isPlaying)
{
if (_capture.IsCapturing())
{
_lastFileSize = _capture.GetCaptureFileSize();
}
if (!_capture.IsRealTime)
{
_lastEncodedSeconds = (uint)Mathf.FloorToInt((float)_capture.CaptureStats.NumEncodedFrames / _capture.FrameRate);
}
else
{
_lastEncodedSeconds = _capture.CaptureStats.TotalEncodedSeconds;
}
_lastEncodedMinutes = _lastEncodedSeconds / 60;
_lastEncodedSeconds = _lastEncodedSeconds % 60;
_lastEncodedFrame = _capture.CaptureStats.NumEncodedFrames % (uint)_capture.FrameRate;
// If the capture has stopped automatically, we need to update the UI
if (!_capture.IsPrepared() || (_capture.StopMode != StopMode.None && _capture.CaptureStats.NumEncodedFrames > 0 && !_capture.IsCapturing() && !_capture.IsStartCaptureQueued()))
{
StopCapture();
}
}
else
{
StopCapture();
}
}
else
{
if (_queueConfigureVideoCodec != null)
{
Codec tempCodec = _queueConfigureVideoCodec;
_queueConfigureVideoCodec = null;
tempCodec.ShowConfigWindow();
}
if (_queueConfigureAudioCodec != null)
{
Codec tempCodec = _queueConfigureAudioCodec;
_queueConfigureAudioCodec = null;
tempCodec.ShowConfigWindow();
}
if (_queueStart && Application.isPlaying)
{
_queueStart = false;
StartCapture();
}
}
Repaint();
}
private struct MediaApiItemMenuData
{
public MediaApiItemMenuData(IMediaApiItem item)
{
this.item = item;
}
public IMediaApiItem item;
}
private void MediaApiItemMenuCallback_Select(object obj)
{
if (((MediaApiItemMenuData)obj).item is Codec)
{
Codec codec = (Codec)((MediaApiItemMenuData)obj).item;
if (codec.CodecType == CodecType.Video)
{
_videoCodec = codec;
}
else if (codec.CodecType == CodecType.Audio)
{
_audioCodec = codec;
}
}
else if (((MediaApiItemMenuData)obj).item is Device)
{
Device device = (Device)((MediaApiItemMenuData)obj).item;
if (device.DeviceType == DeviceType.AudioInput)
{
_audioInputDevice = device;
}
}
UpdateSelectedCodec();
}
private GenericMenu CreateMediaItemMenu(System.Collections.IEnumerable items, IMediaApiItem selectedItem, IMediaApiItem matchMediaType)
{
GenericMenu menu = new GenericMenu();
#if UNITY_EDITOR_WIN
MediaApi lastApi = MediaApi.Unknown;
#endif
foreach (IMediaApiItem item in items)
{
bool isEnabled = (matchMediaType == null || matchMediaType.MediaApi == item.MediaApi);
#if UNITY_EDITOR_WIN
if (isEnabled && item.MediaApi != lastApi)
{
string title = string.Empty;
switch (item.MediaApi)
{
case MediaApi.DirectShow:
title = "DirectShow Legacy API:";
break;
case MediaApi.MediaFoundation:
title = "Media Foundation API:";
break;
}
menu.AddSeparator("");
menu.AddDisabledItem(new GUIContent(title));
lastApi = item.MediaApi;
}
#endif
if (isEnabled)
{
// Have to replace '/' as Unity context menu uses to this indicate a sub-menu
string displayName = item.Name.Replace("/", "⁄");
menu.AddItem(new GUIContent(displayName), item == selectedItem, MediaApiItemMenuCallback_Select, new MediaApiItemMenuData(item));
}
else
{
//menu.AddDisabledItem(new GUIContent(item.Name));
}
}
return menu;
}
private bool ShowMediaItemList(string title, System.Collections.IEnumerable itemList, IMediaApiItem selectedItem, IMediaApiItem matchMediaType = null)
{
bool result = false;
if (itemList == null || selectedItem == null)
{
return result;
}
if (!string.IsNullOrEmpty(title))
{
EditorGUILayout.LabelField(title, EditorStyles.boldLabel);
}
EditorGUILayout.BeginHorizontal();
var rect = EditorGUILayout.GetControlRect(false);
if (EditorGUI.DropdownButton(rect, new GUIContent(selectedItem.Name), FocusType.Keyboard))
{
CreateMediaItemMenu(itemList, selectedItem, matchMediaType).DropDown(rect);
}
#if UNITY_EDITOR_WIN
if (selectedItem is Codec)
{
EditorGUI.BeginDisabledGroup(!((Codec)selectedItem).HasConfigwindow);
if (GUILayout.Button("Configure"))
{
result = true;
}
EditorGUI.EndDisabledGroup();
}
#endif
EditorGUILayout.EndHorizontal();
return result;
}
private static bool ShowConfigList(string title, string[] items, bool[] isConfigurable, ref Codec codec, ref int itemIndex, ref bool itemChanged, 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();
int newItemIndex = EditorGUILayout.Popup(itemIndex, items);
itemChanged = (newItemIndex != itemIndex);
itemIndex = newItemIndex;
#if UNITY_EDITOR_WIN
if (showConfig && isConfigurable != null && itemIndex < isConfigurable.Length)
{
EditorGUI.BeginDisabledGroup(itemIndex == 0 || !isConfigurable[itemIndex]);
if (GUILayout.Button("Configure"))
{
result = true;
}
EditorGUI.EndDisabledGroup();
}
#endif
EditorGUILayout.EndHorizontal();
EditorGUI.EndDisabledGroup();
return result;
}
void OnGUI()
{
if ((Application.platform != RuntimePlatform.WindowsEditor)
&& (Application.platform != RuntimePlatform.OSXEditor))
{
EditorGUILayout.LabelField("AVPro Movie Capture Window only works on the Windows and macOS platforms.");
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 && UNITY_EDITOR_WIN
if (SystemInfo.graphicsDeviceType != UnityEngine.Rendering.GraphicsDeviceType.Direct3D11 &&
SystemInfo.graphicsDeviceType != UnityEngine.Rendering.GraphicsDeviceType.Direct3D12)
{
GUI.color = Color.yellow;
GUILayout.TextArea("Consider switching to D3D11 or D3D12 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 - TRIAL VERSION", ref _expandSectionTrial, DrawTrialMessage, Color.magenta, Color.magenta, Color.magenta);
//EditorGUILayout.Space();
}
DrawControlButtonsGUI();
EditorGUILayout.Space();
// Live Capture Stats
if (Application.isPlaying && _capture != null && (_capture.IsCapturing() || _capture.IsStartCaptureQueued()))
{
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", "Screenshot", "Help" };
_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_Screenshot();
EditorGUILayout.EndScrollView();
break;
case 2:
_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 watermarked. Upgrade to the full package to remove the watermark.";
//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(LinkAssetStorePage);
}
//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 (!IsCaptureRealTime())
{
startString = "Start Render";
}
if (GUILayout.Button(startString, GUILayout.Height(32f)))
{
bool isReady = true;
if (_sourceType == SourceType.Camera &&
_cameraNode == null &&
_selectBy == CameraSelector.SelectByMode.Manual)
{
if ((ConfigTabs)_selectedConfigTab != ConfigTabs.Capture)
{
_cameraNode = Utils.GetUltimateRenderCamera();
}
if (_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);
}
}
{
Color prevColor = GUI.color;
GUI.color = Color.cyan;
if (GUILayout.Button("View Last Capture"))
{
if (!string.IsNullOrEmpty(CaptureBase.LastFileSaved))
{
Utils.OpenInDefaultApp(CaptureBase.LastFileSaved);
}
}
GUI.color = prevColor;
}
GUILayout.EndHorizontal();
}
public static void DrawBaseCapturingGUI(CaptureBase capture)
{
GUILayout.Space(8.0f);
Texture texture = capture.GetPreviewTexture();
if (texture != null)
{
float aspect = (float)texture.width / (float)texture.height;
GUILayout.BeginHorizontal();
Transparency captureTransparency = capture.Transparency;
bool sideBySideTransparency = ( captureTransparency == Transparency.TopBottom || captureTransparency == Transparency.LeftRight );
//if (Event.current.type == EventType.Repaint)
{
if( _showAlpha && !sideBySideTransparency )
{
Rect textureRect = GUILayoutUtility.GetAspectRect(aspect);//(width, width / aspect, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(false));
EditorGUI.DrawPreviewTexture(textureRect, texture, null, ScaleMode.ScaleToFit);
textureRect = GUILayoutUtility.GetAspectRect(aspect);//width, width / aspect, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false)); ;
EditorGUI.DrawTextureAlpha(textureRect, texture, ScaleMode.ScaleToFit);
}
else
{
if( sideBySideTransparency )
{
Texture sideBySideTexture = capture.GetSideBySideTexture();
if( sideBySideTexture )
{
float sideBySideAspect = (float)sideBySideTexture.width / (float)sideBySideTexture.height;
Rect textureRect = GUILayoutUtility.GetAspectRect( sideBySideAspect/*, GUILayout.MaxHeight(256.0f)*/);
EditorGUI.DrawPreviewTexture(textureRect, sideBySideTexture, null, ScaleMode.StretchToFill);
}
}
else
{
Rect textureRect = GUILayoutUtility.GetAspectRect(aspect, GUILayout.MaxHeight(256f));//width, width / aspect, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false));
EditorGUI.DrawPreviewTexture(textureRect, texture, null, ScaleMode.ScaleToFit);
}
}
}
GUILayout.EndHorizontal();
if( !sideBySideTransparency )
{
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(GUI.skin.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() + " @ " + capture.FrameRate.ToString("F2") + "hz");
if (capture.OutputTarget == OutputTarget.VideoFile)
{
EditorGUILayout.LabelField("Codec", (capture.SelectedVideoCodec != null)?capture.SelectedVideoCodec.Name:"None");
}
else if (capture.OutputTarget == OutputTarget.ImageSequence)
{
EditorGUILayout.LabelField("Codec", capture.NativeImageSequenceFormat.ToString());
}
if (capture.AudioCaptureSource != AudioCaptureSource.None)
{
GUILayout.Label("Audio");
if (capture.AudioCaptureSource == AudioCaptureSource.Unity && capture.UnityAudioCapture != null)
{
EditorGUILayout.LabelField("Source", "Unity");
}
else if (capture.AudioCaptureSource == AudioCaptureSource.Microphone)
{
EditorGUILayout.LabelField("Source", (capture.SelectedAudioInputDevice != null)?capture.SelectedAudioInputDevice.Name:"None");
}
else if (capture.AudioCaptureSource == AudioCaptureSource.Wwise && capture.UnityAudioCapture != null)
{
EditorGUILayout.LabelField("Source", "Wwise");
}
EditorGUILayout.LabelField("Codec", (capture.SelectedAudioCodec!= null)?capture.SelectedAudioCodec.Name:"None");
if (capture.UnityAudioCapture != null && (capture.AudioCaptureSource == AudioCaptureSource.Unity || capture.AudioCaptureSource == AudioCaptureSource.Wwise))
{
EditorGUILayout.LabelField("Sample Rate", (capture.CaptureStats.UnityAudioSampleRate/1000f).ToString("F1") + "Khz");
EditorGUILayout.LabelField("Channels", capture.CaptureStats.UnityAudioChannelCount.ToString());
}
}
EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
GUILayout.Space(8.0f);
GUILayout.Label("Stats", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(GUI.skin.box);
EditorGUI.indentLevel++;
if (capture.CaptureStats.FPS > 0f)
{
Color originalColor = GUI.color;
if (capture.IsRealTime)
{
float fpsDelta = (capture.CaptureStats.FPS - 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:F2} FPS", capture.CaptureStats.FPS, capture.FrameRate));
GUI.color = originalColor;
}
else
{
EditorGUILayout.LabelField("Capture Rate", string.Format(".. / {0:F2} FPS", capture.FrameRate));
}
EditorGUILayout.LabelField("Encoded Frames", capture.CaptureStats.NumEncodedFrames.ToString());
EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
}
public void DrawMoreCapturingGUI()
{
GUILayout.Label("More Stats", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(GUI.skin.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"));
EditorGUILayout.LabelField("Avg Bitrate", (8f * ((float)_lastFileSize / (1024f * 1024f)) / (float)((_lastEncodedMinutes * 60) + _lastEncodedSeconds)).ToString("F2") + "Mb/s");
EditorGUILayout.PrefixLabel("Dropped Frames");
EditorGUI.indentLevel++;
EditorGUILayout.LabelField("In Unity", _capture.CaptureStats.NumDroppedFrames.ToString());
EditorGUILayout.LabelField("In Encoder", _capture.CaptureStats.NumDroppedEncoderFrames.ToString());
EditorGUI.indentLevel--;
if (IsAudioCaptured())
{
if (_capture.AudioCaptureSource == AudioCaptureSource.Unity && _capture.UnityAudioCapture != null)
{
EditorGUILayout.LabelField("Audio Overflows", _capture.UnityAudioCapture.OverflowCount.ToString());
}
}
EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
}
private void DrawConfigGUI_Toolbar()
{
_selectedConfigTab = GUILayout.Toolbar(_selectedConfigTab, _tabNames);
}
private void DrawConfigGUI()
{
switch ((ConfigTabs)_selectedConfigTab)
{
case ConfigTabs.Encoding:
DrawConfigGUI_Encoding();
break;
case ConfigTabs.Capture:
DrawConfigGUI_Capture();
break;
case ConfigTabs.Visual:
DrawConfigGUI_Visual();
break;
case ConfigTabs.Audio:
DrawConfigGUI_Audio();
break;
}
GUILayout.FlexibleSpace();
}
public void DrawConfigGUI_Screenshot()
{
EditorGUILayout.PropertyField(_propScreenshotFolder, new GUIContent("Folder"));
EditorGUILayout.PropertyField(_propScreenshotOptions, new GUIContent("Format Options"));
EditorGUILayout.Space();
string folder = System.IO.Path.GetFullPath(System.IO.Path.Combine(Application.dataPath, "../" + _screenshotFolder));
{
EditorGUILayout.BeginVertical(GUI.skin.box);
int superSize = 1;
switch (_superSizeIndex)
{
case 1:
superSize = 2;
break;
case 2:
superSize = 4;
break;
}
Vector2 captureSize = EditorScreenshot.GetGameViewSize() * superSize;
GUILayout.BeginHorizontal();
GUILayout.Label("GameView", EditorStyles.boldLabel, GUILayout.ExpandWidth(false));
GUILayout.Label(string.Format("({0}x{1})", (int)captureSize.x, (int)captureSize.y));
GUILayout.EndHorizontal();
EditorGUILayout.Space();
GUILayout.BeginHorizontal();
GUILayout.Label("Supersample");
_superSizeIndex = GUILayout.SelectionGrid(_superSizeIndex, new string[]{"1x", "2x", "4x"}, 4);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Capture PNG"))
{
EditorScreenshot.ImageFormat format = EditorScreenshot.ImageFormat.PNG;
string filePath = EditorScreenshot.GenerateFilename("Screen", format, (int)captureSize.x, (int)captureSize.y);
filePath = EditorScreenshot.GenerateFilePath(folder, filePath);
EditorScreenshot.GameViewToPNG(filePath, superSize);
}
{
EditorGUI.BeginDisabledGroup(!EditorScreenshot.SupportsGameViewJPGTGAEXR());
if (GUILayout.Button("Capture JPG"))
{
EditorScreenshot.ImageFormat format = EditorScreenshot.ImageFormat.JPG;
string filePath = EditorScreenshot.GenerateFilename("Screen", format, (int)captureSize.x, (int)captureSize.y);
filePath = EditorScreenshot.GenerateFilePath(folder, filePath);
EditorScreenshot.GameViewToFile(filePath, format, _screenshotOptions, superSize);
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
{
EditorGUI.BeginDisabledGroup(!EditorScreenshot.SupportsTGA());
if (GUILayout.Button("Capture TGA"))
{
EditorScreenshot.ImageFormat format = EditorScreenshot.ImageFormat.TGA;
string filePath = EditorScreenshot.GenerateFilename("Screen", format, (int)captureSize.x, (int)captureSize.y);
filePath = EditorScreenshot.GenerateFilePath(folder, filePath);
EditorScreenshot.GameViewToFile(filePath, format, _screenshotOptions, superSize);
}
EditorGUI.EndDisabledGroup();
}
{
EditorGUI.BeginDisabledGroup(!EditorScreenshot.SupportsGameViewEXR());
if (GUILayout.Button("Capture EXR"))
{
EditorScreenshot.ImageFormat format = EditorScreenshot.ImageFormat.EXR;
string filePath = EditorScreenshot.GenerateFilename("Screen", format, (int)captureSize.x, (int)captureSize.y);
filePath = EditorScreenshot.GenerateFilePath(folder, filePath);
EditorScreenshot.GameViewToFile(filePath, format, _screenshotOptions, superSize);
}
EditorGUI.EndDisabledGroup();
}
EditorGUI.EndDisabledGroup();
}
GUILayout.EndHorizontal();
GUILayout.EndVertical();
}
EditorGUILayout.Space();
{
EditorGUILayout.BeginVertical(GUI.skin.box);
GUILayout.BeginHorizontal();
RenderTexture sceneViewTexture = EditorScreenshot.GetSceneViewTexture();
GUILayout.Label("Scene View", EditorStyles.boldLabel, GUILayout.ExpandWidth(false));
if (sceneViewTexture != null)
{
GUILayout.Label(string.Format("({0}x{1})", sceneViewTexture.width, sceneViewTexture.height));
}
else
{
GUI.color = Color.red;
GUILayout.Label("*Missing*", EditorStyles.boldLabel);
GUI.color = Color.white;
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Capture PNG"))
{
EditorScreenshot.SceneViewToFile("Scene", folder, EditorScreenshot.ImageFormat.PNG, _screenshotOptions);
}
if (GUILayout.Button("Capture JPG"))
{
EditorScreenshot.SceneViewToFile("Scene", folder, EditorScreenshot.ImageFormat.JPG, _screenshotOptions);
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Capture TGA"))
{
EditorScreenshot.SceneViewToFile("Scene", folder, EditorScreenshot.ImageFormat.TGA, _screenshotOptions);
}
if (GUILayout.Button("Capture EXR"))
{
EditorScreenshot.SceneViewToFile("Scene", folder, EditorScreenshot.ImageFormat.EXR, _screenshotOptions);
}
GUILayout.EndHorizontal();
GUILayout.EndVertical();
}
EditorGUILayout.Space();
{
GUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("Cameras", EditorStyles.boldLabel);
if (GUILayout.Button("Refresh"))
{
_cameras = Resources.FindObjectsOfTypeAll();
}
if (_cameras != null && _cameras.Length > 0)
{
_cameraIndex = (int)GUILayout.HorizontalSlider(_cameraIndex, 0, _cameras.Length - 1, GUILayout.ExpandWidth(true));
EditorGUILayout.Space();
Camera camera = _cameras[_cameraIndex];
string desc = _cameraIndex + "/" + _cameras.Length + ": ";
Texture texture = Texture2D.blackTexture;
if (camera != null)
{
desc += camera.name;
if (camera.targetTexture != null)
{
desc += " " + camera.targetTexture.width + "x" + camera.targetTexture.height;
#if UNITY_2019_1_OR_NEWER
desc += " " + camera.targetTexture.graphicsFormat;
#endif
texture = camera.targetTexture;
}
}
GUILayout.Label(desc);
Rect textureRect = GUILayoutUtility.GetRect(256f, 256f);
GUI.DrawTexture(textureRect, texture, ScaleMode.ScaleToFit);
}
if (_cameras != null && _cameras.Length > 0)
{
RenderTexture rt = _cameras[_cameraIndex].targetTexture;
if (rt != null)
{
GUILayout.BeginHorizontal();
if (GUILayout.Button("Capture PNG"))
{
EditorScreenshot.ImageFormat format = EditorScreenshot.ImageFormat.PNG;
string filePath = EditorScreenshot.GenerateFilename("RT-" + rt.name, format, rt.width, rt.height);
filePath = EditorScreenshot.GenerateFilePath(folder, filePath);
EditorScreenshot.RenderTextureToFile(filePath, format, _screenshotOptions, rt);
}
if (GUILayout.Button("Capture EXR"))
{
EditorScreenshot.ImageFormat format = EditorScreenshot.ImageFormat.EXR;
string filePath = EditorScreenshot.GenerateFilename("RT-" + rt.name, format, rt.width, rt.height);
filePath = EditorScreenshot.GenerateFilePath(folder, filePath);
EditorScreenshot.RenderTextureToFile(filePath, format, _screenshotOptions, rt);
}
GUILayout.EndHorizontal();
}
}
GUILayout.EndVertical();
}
EditorGUILayout.Space();
{
GUILayout.BeginVertical(GUI.skin.box);
GUILayout.Label("RenderTextures", EditorStyles.boldLabel);
if (GUILayout.Button("Refresh"))
{
_rts = Resources.FindObjectsOfTypeAll();
}
if (_rts != null && _rts.Length > 0)
{
_rtIndex = (int)GUILayout.HorizontalSlider(_rtIndex, 0, _rts.Length - 1, GUILayout.ExpandWidth(true));
EditorGUILayout.Space();
RenderTexture rt = _rts[_rtIndex];
string desc = _rtIndex + "/" + _rts.Length + ": ";
Texture texture = Texture2D.blackTexture;
if (rt != null)
{
desc += rt.name + " " + rt.width + "x" + rt.height;
#if UNITY_2019_1_OR_NEWER
desc += " " + rt.graphicsFormat;
#endif
texture = rt;
}
GUILayout.Label(desc);
Rect textureRect = GUILayoutUtility.GetRect(256f, 256f);
GUI.DrawTexture(textureRect, texture, ScaleMode.ScaleToFit);
}
if (_rts != null && _rts.Length > 0)
{
RenderTexture rt = _rts[_rtIndex];
if (rt != null)
{
GUILayout.BeginHorizontal();
if (GUILayout.Button("Capture PNG"))
{
EditorScreenshot.ImageFormat format = EditorScreenshot.ImageFormat.PNG;
string filePath = EditorScreenshot.GenerateFilename("RT-" + rt.name, format, rt.width, rt.height);
filePath = EditorScreenshot.GenerateFilePath(folder, filePath);
EditorScreenshot.RenderTextureToFile(filePath, format, _screenshotOptions, rt);
}
if (GUILayout.Button("Capture EXR"))
{
EditorScreenshot.ImageFormat format = EditorScreenshot.ImageFormat.EXR;
string filePath = EditorScreenshot.GenerateFilename("RT-" + rt.name, format, rt.width, rt.height);
filePath = EditorScreenshot.GenerateFilePath(folder, filePath);
EditorScreenshot.RenderTextureToFile(filePath, format, _screenshotOptions, rt);
}
GUILayout.EndHorizontal();
}
}
GUILayout.EndVertical();
}
}
private static int _rtIndex;
private static int _cameraIndex;
private static RenderTexture[] _rts;
private static Camera[] _cameras;
public static void DrawConfigGUI_About()
{
string version = NativePlugin.GetPluginVersionString();
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");
if (GUILayout.Button("User Manual", GUILayout.ExpandWidth(false)))
{
Application.OpenURL(LinkUserManual);
}
GUILayout.Space(16f);
GUILayout.Label("Bugs and Support");
if (GUILayout.Button("GitHub Issues", GUILayout.ExpandWidth(false)))
{
Application.OpenURL(LinkSupport);
}
GUILayout.Space(16f);
GUILayout.Label("Rate and Review (★★★★☆)", GUILayout.ExpandWidth(false));
if (GUILayout.Button("Asset Store Page", GUILayout.ExpandWidth(false)))
{
Application.OpenURL(LinkAssetStorePage);
}
GUILayout.Space(16f);
GUILayout.Label("Community");
if (GUILayout.Button("Forum Thread", GUILayout.ExpandWidth(false)))
{
Application.OpenURL(LinkForumPage);
}
GUILayout.Space(16f);
GUILayout.Label("Website", GUILayout.ExpandWidth(false));
if (GUILayout.Button("Official Website", GUILayout.ExpandWidth(false)))
{
Application.OpenURL(LinkPluginWebsite);
}
}
// Credits
{
GUILayout.Space(32f);
EditorGUILayout.LabelField("Credits", EditorStyles.boldLabel);
GUILayout.Space(8f);
EditorUtils.CentreLabel("Programming", EditorStyles.boldLabel);
EditorUtils.CentreLabel("Andrew Griffiths");
EditorUtils.CentreLabel("Morris Butler");
EditorUtils.CentreLabel("Richard Turnbull");
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_Capture()
{
//GUILayout.Label("Capture", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(GUI.skin.box);
//EditorGUI.indentLevel++;
// Time
{
GUILayout.Space(8f);
EditorGUILayout.LabelField("Time", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
_captureModeIndex = EditorGUILayout.Popup("Capture Mode", _captureModeIndex, _captureModes);
GUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(_propFrameRate, GUILayout.ExpandWidth(false));
_propFrameRate.floatValue = Mathf.Clamp(_propFrameRate.floatValue, 0.01f, 240f);
EditorUtils.FloatAsPopup("▶", "Common Frame Rates", _so, _propFrameRate, EditorUtils.CommonFrameRateNames, EditorUtils.CommonFrameRateValues);
GUILayout.EndHorizontal();
if (IsCaptureRealTime())
{
EditorGUILayout.PropertyField(_propTimelapseScale);
_propTimelapseScale.intValue = Mathf.Max(1, _propTimelapseScale.intValue);
}
EditorGUI.indentLevel--;
}
// Source
GUILayout.Space(8f);
EditorGUILayout.LabelField("Source", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
EditorUtils.EnumAsDropdown("Source", _propSourceType, _sourceNames);
if (_sourceType == SourceType.Camera360ODS && IsCaptureRealTime())
{
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;
}
EditorGUI.indentLevel--;
//_sourceType = (SourceType)EditorGUILayout.EnumPopup("Type", _sourceType);
if (_sourceType == SourceType.Camera || _sourceType == SourceType.Camera360 || _sourceType == SourceType.Camera360ODS)
{
GUILayout.Space(8f);
EditorGUILayout.LabelField("Camera Selector", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(_propCameraSelectorSelectBy);
if (_propCameraSelectorSelectBy.enumValueIndex == (int)CameraSelector.SelectByMode.Name)
{
EditorGUILayout.PropertyField(_propCameraSelectorName, _guiCameraSelectorName);
}
else if (_propCameraSelectorSelectBy.enumValueIndex == (int)CameraSelector.SelectByMode.Tag)
{
EditorGUILayout.PropertyField(_propCameraSelectorTag, _guiCameraSelectorTag);
}
else if (_propCameraSelectorSelectBy.enumValueIndex == (int)CameraSelector.SelectByMode.Manual)
{
if (_cameraNode == null)
{
_cameraNode = Utils.GetUltimateRenderCamera();
}
_cameraNode = (Camera)EditorGUILayout.ObjectField("Camera", _cameraNode, typeof(Camera), true);
}
#if !SUPPORT_SCENE_VIEW_GIZMOS_CAPTURE
else if (_propCameraSelectorSelectBy.enumValueIndex == (int)CameraSelector.SelectByMode.EditorSceneView)
{
GUI.color = Color.yellow;
GUILayout.TextArea("Warning: Scene View capture only currently supports gizmo capture up to Unity 2018.2.x");
GUI.color = Color.white;
}
#endif
if (_sourceType == SourceType.Camera && _cameraNode != null)
{
EditorGUILayout.PropertyField(_propUseContributingCameras, _guiContributingCameras);
}
EditorGUILayout.PropertyField(_propCameraSelectorScanFrequency);
EditorGUILayout.PropertyField(_propCameraSelectorScanHiddenCameras);
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++;
EditorGUILayout.PropertyField(_propRender180Degrees);
{
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)
{
#if AVPRO_MOVIECAPTURE_UNITY_STEREOCUBEMAP_RENDER
if (!PlayerSettings.enable360StereoCapture)
{
GUI.color = Color.yellow;
GUILayout.TextArea("Warning: 360 Stereo Capture needs to be enabled in PlayerSettings");
GUI.color = Color.white;
if (GUILayout.Button("Enable 360 Stereo Capture"))
{
PlayerSettings.enable360StereoCapture = true;
}
}
#endif
_cubemapStereoIPD = EditorGUILayout.FloatField("Interpupillary distance", _cubemapStereoIPD);
}
EditorGUILayout.PropertyField(_propCaptureWorldSpaceGUI, _guiCaptureWorldSpaceUI);
EditorGUILayout.PropertyField(_propSupportCameraRotation, _guiCameraRotation);
if (_propSupportCameraRotation.boolValue)
{
EditorGUILayout.PropertyField(_propOnlyLeftRightRotation);
}
EditorGUI.indentLevel--;
}
// 360 Cubemap ODS
if (_sourceType == SourceType.Camera360ODS)
{
GUILayout.Space(8f);
EditorGUI.indentLevel++;
EditorGUILayout.LabelField("Source Options", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
{
EditorGUILayout.PropertyField(_propOdsRender180Degrees);
EditorGUILayout.PropertyField(_propOdsIPD, _guiInterpupillaryDistance);
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++;
EditorGUILayout.PropertyField(_propStartDelay, _guiStartDelay);
if ((StartDelayMode)_propStartDelay.enumValueIndex == StartDelayMode.RealSeconds ||
(StartDelayMode)_propStartDelay.enumValueIndex == StartDelayMode.GameSeconds)
{
EditorGUILayout.PropertyField(_propStartDelaySeconds, _guiSeconds);
}
EditorGUILayout.Separator();
_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_Encoding()
{
//GUILayout.Label("Target", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(GUI.skin.box);
//EditorGUI.indentLevel++;
EditorUtils.EnumAsDropdown("Output Target", _propOutputTarget, EditorUtils.OutputTargetNames);
GUILayout.Space(8f);
if (_propOutputTarget.enumValueIndex == (int)OutputTarget.VideoFile ||
_propOutputTarget.enumValueIndex == (int)OutputTarget.ImageSequence)
{
bool isImageSequence = (_propOutputTarget.enumValueIndex == (int)OutputTarget.ImageSequence);
if (isImageSequence)
{
EditorUtils.EnumAsDropdown("Format", _propImageSequenceFormat, Utils.GetNativeImageSequenceFormatNames());
GUILayout.Space(8f);
}
// File path
EditorGUILayout.LabelField("File Path", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
_outputFolderIndex = EditorGUILayout.Popup("Relative to", _outputFolderIndex, _outputFolders);
if (_outputFolderIndex != (int)CaptureBase.OutputPath.Absolute)
{
_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++;
_filenamePrefixFromSceneName = EditorGUILayout.Toggle("From Scene Name", _filenamePrefixFromSceneName);
if (_filenamePrefixFromSceneName)
{
#if AVPRO_MOVIECAPTURE_SCENEMANAGER_53
string currentScenePath = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().path;
#else
string currentScenePath = EditorApplication.currentScene;
#endif
_filenamePrefix = System.IO.Path.GetFileNameWithoutExtension(currentScenePath);
if (string.IsNullOrEmpty(_filenamePrefix))
{
_filenamePrefix = "capture";
}
}
EditorGUI.BeginDisabledGroup(_filenamePrefixFromSceneName);
_filenamePrefix = EditorGUILayout.TextField("Prefix", _filenamePrefix);
EditorGUI.EndDisabledGroup();
if (!isImageSequence)
{
_appendTimestamp = EditorGUILayout.Toggle("Append Timestamp", _appendTimestamp);
}
else
{
EditorGUILayout.PropertyField(_propImageSequenceStartFrame, _guiStartFrame);
EditorGUILayout.PropertyField(_propImageSequenceZeroDigits, _guiZeroDigits);
}
EditorGUI.indentLevel--;
GUILayout.Space(8f);
// File container
if (!isImageSequence)
{
EditorGUILayout.LabelField("File Container", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
_fileContainerIndex = EditorGUILayout.Popup("Extension", _fileContainerIndex, _fileExtensions);
if (_fileContainerIndex >= 0 && _fileContainerIndex < _fileExtensions.Length)
{
_filenameExtension = _fileExtensions[_fileContainerIndex].ToLower();
}
EditorGUI.indentLevel--;
}
}
else if (_propOutputTarget.enumValueIndex == (int)OutputTarget.NamedPipe)
{
EditorGUILayout.PropertyField(_propNamedPipePath);
}
DrawVisualCodecList();
DrawAudioCodecList();
if (_propOutputTarget.enumValueIndex == (int)OutputTarget.VideoFile ||
_propOutputTarget.enumValueIndex == (int)OutputTarget.ImageSequence)
{
GUILayout.Space(8f);
EditorGUILayout.LabelField("Encoder Hints", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
if (_propOutputTarget.enumValueIndex == (int)OutputTarget.VideoFile)
{
EditorUtils.BitrateField("Average Bitrate", _propVideoHintsAverageBitrate);
#if UNITY_EDITOR_WIN
EditorUtils.BitrateField("Maxiumum Bitrate", _propVideoHintsMaximumBitrate);
// Ensure that the maximum value is larger than the average value, or zero
if (_propVideoHintsMaximumBitrate.intValue != 0)
{
_propVideoHintsMaximumBitrate.intValue = Mathf.Max(_propVideoHintsMaximumBitrate.intValue, _propVideoHintsAverageBitrate.intValue);
}
#endif
EditorGUILayout.PropertyField(_propVideoHintsQuality);
EditorGUILayout.PropertyField(_propVideoHintsKeyframeInterval);
EditorGUILayout.PropertyField(_propVideoHintsTransparency);
#if UNITY_EDITOR_WIN
EditorGUILayout.PropertyField(_propVideoHintsUseHardwareEncoding, new GUIContent("Hardware Encoding"));
#elif UNITY_EDITOR_OSX
EditorGUILayout.PropertyField(_propVideoHintsEnableFragmentedWriting);
if (_propVideoHintsEnableFragmentedWriting.boolValue)
{
EditorGUILayout.PropertyField(_propVideoHintsMovieFragmentInterval);
}
#endif
}
else if (_propOutputTarget.enumValueIndex == (int)OutputTarget.ImageSequence)
{
#if UNITY_EDITOR_OSX
EditorGUILayout.PropertyField(_propImageHintsQuality);
#endif
EditorGUILayout.PropertyField(_propImageHintsTransparency);
}
EditorGUI.indentLevel--;
if (_propOutputTarget.enumValueIndex == (int)OutputTarget.VideoFile)
{
GUILayout.Space(8f);
EditorGUILayout.LabelField("Post Process", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(_propVideoHintsAllowFastStart);
EditorGUILayout.PropertyField(_propVideoHintsInjectStereoPacking, _guiStereoPacking);
if (_propVideoHintsInjectStereoPacking.enumValueIndex == (int)NoneAutoCustom.Custom)
{
EditorGUILayout.PropertyField(_propVideoHintsStereoPacking, _guiBlankSpace);
}
EditorGUILayout.PropertyField(_propVideoHintsInjectSphericalVideoLayout, _guiSphericalLayout);
if (_propVideoHintsInjectSphericalVideoLayout.enumValueIndex == (int)NoneAutoCustom.Custom)
{
EditorGUILayout.PropertyField(_propVideoHintsSphericalVideoLayout, _guiBlankSpace);
}
}
}
//EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
}
private void DrawConfigGUI_Visual()
{
//GUILayout.Label("Video", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(GUI.skin.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 + " @ " + _frameRate.ToString("F2"));
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);
}
GUILayout.Space(8f);
//EditorGUILayout.LabelField("Codec", EditorStyles.boldLabel);
DrawConfigGUI_MotionBlur();
//EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
}
private void UpdateSelectedCodec()
{
// Assign the first codec if none is selected
if (_videoCodec == null && CodecManager.VideoCodecs.Count > 0)
{
_videoCodec = CodecManager.VideoCodecs.Codecs[0];
}
if (_videoCodec != null)
{
// Ensure the audio codec uses the same API as the video codec,
// otherwise assign the first audio codec
if (_audioCodec == null || (_audioCodec != null && _audioCodec.MediaApi != _videoCodec.MediaApi))
{
_audioCodec = CodecManager.AudioCodecs.GetFirstWithMediaApi(_videoCodec.MediaApi);
}
if (_audioInputDevice == null || (_audioInputDevice != null && _audioInputDevice.MediaApi != _videoCodec.MediaApi))
{
_audioInputDevice = DeviceManager.AudioInputDevices.GetFirstWithMediaApi(_videoCodec.MediaApi);
}
}
// Select the appropriate file extension based on the selected codecs
UpdateFileExtension();
}
private void UpdateFileExtension()
{
// There are cases where the plugin is deinitalised, so it needs to be inited to be able to query the file extension
if (NativePlugin.GetVideoCodecCount() <= 0)
{
NativePlugin.Init();
}
_fileExtensions = GetSuitableFileExtensions(_videoCodec, IsAudioCaptured()?_audioCodec:null);
if (_fileContainerIndex >= _fileExtensions.Length)
{
_fileContainerIndex = 0;
}
if (_fileContainerIndex < _fileExtensions.Length)
{
_filenameExtension = _fileExtensions[_fileContainerIndex].ToLower();
}
}
private void DrawVisualCodecList()
{
GUILayout.Space(8f);
if (_outputTarget == OutputTarget.VideoFile)
{
if (_videoCodec == null && CodecManager.VideoCodecs.Count > 0)
{
_videoCodec = CodecManager.VideoCodecs.Codecs[0];
}
if (_audioCodec == null && CodecManager.AudioCodecs.Count > 0)
{
_audioCodec = CodecManager.AudioCodecs.Codecs[0];
}
if (ShowMediaItemList("Video Codec", CodecManager.VideoCodecs, _videoCodec, null))
{
_queueConfigureVideoCodec = _videoCodec;
}
if (_videoCodec != null)
{
#if UNITY_EDITOR_WIN
if (_videoCodec.MediaApi == MediaApi.DirectShow)
{
if (_videoCodec.Name.EndsWith("Cinepak Codec by Radius")
|| _videoCodec.Name.EndsWith("DV Video Encoder")
|| _videoCodec.Name.EndsWith("Microsoft Video 1")
|| _videoCodec.Name.EndsWith("Microsoft RLE")
|| _videoCodec.Name.EndsWith("Logitech Video (I420)")
|| _videoCodec.Name.EndsWith("Intel IYUV codec")
)
{
GUI.color = Color.yellow;
GUILayout.TextArea("Warning: Legacy codec, not recommended");
GUI.color = Color.white;
}
if (_videoCodec.Name.Contains("Decoder") || _videoCodec.Name.Contains("Decompressor"))
{
GUI.color = Color.yellow;
GUILayout.TextArea("Warning: Codec may contain decompressor only");
GUI.color = Color.white;
}
if (CodecManager.VideoCodecs.Count < 6)
{
GUI.color = Color.cyan;
GUILayout.TextArea("Low number of codecs, consider installing more");
GUI.color = Color.white;
}
}
#endif
if (_videoCodec.Name.EndsWith("Uncompressed"))
{
GUI.color = Color.yellow;
GUILayout.TextArea("Warning: Uncompressed may result in very large files");
GUI.color = Color.white;
}
}
}
}
private bool IsCaptureRealTime()
{
return (_captureModeIndex == 0);
}
private bool IsAudioCaptured()
{
return (_outputTarget == OutputTarget.VideoFile && _audioCaptureSource != AudioCaptureSource.None && (IsCaptureRealTime() || _audioCaptureSource != AudioCaptureSource.Manual));
}
private void DrawAudioCodecList()
{
if (_outputTarget != OutputTarget.VideoFile)
{
return;
}
GUILayout.Space(8f);
EditorGUI.BeginDisabledGroup(!IsAudioCaptured());
if (ShowMediaItemList("Audio Codec", CodecManager.AudioCodecs, _audioCodec, _videoCodec))
{
_queueConfigureAudioCodec = _audioCodec;
}
#if UNITY_EDITOR_WIN
if (_audioCodec != null && (_audioCodec.Name.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;
}
#endif
EditorGUI.EndDisabledGroup();
}
private void DrawConfigGUI_MotionBlur()
{
EditorGUI.BeginDisabledGroup(IsCaptureRealTime());
//EditorGUILayout.BeginVertical(GUI.skin.box);
//EditorGUI.indentLevel++;
GUILayout.Space(8f);
GUILayout.Label("Motion Blur (beta)", EditorStyles.boldLabel);
//EditorGUILayout.BeginVertical(GUI.skin.box);
//EditorGUI.indentLevel++;
if (IsCaptureRealTime())
{
GUI.color = Color.yellow;
GUILayout.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));
_motionBlurSampleCount = EditorGUILayout.IntSlider(_motionBlurSampleCount, 0, 64);
EditorGUILayout.EndHorizontal();
EditorGUI.EndDisabledGroup();
//EditorGUI.indentLevel--;
//EditorGUILayout.EndVertical();
EditorGUI.EndDisabledGroup();
}
private void DrawConfigGUI_Audio()
{
bool showAudioSources = true;
if (_outputTarget != OutputTarget.VideoFile)
{
GUI.color = Color.yellow;
GUILayout.TextArea("Audio capture only available when outputing to video file");
GUI.color = Color.white;
showAudioSources = false;
}
if (showAudioSources)
{
EditorGUILayout.BeginVertical(GUI.skin.box);
_audioCaptureSource = (AudioCaptureSource)EditorGUILayout.EnumPopup("Audio Source", _audioCaptureSource);
if (_audioCaptureSource != AudioCaptureSource.None)
{
bool showAudioOptions = true;
#if AVPRO_MOVIECAPTURE_OFFLINE_AUDIOCAPTURE
if (!IsCaptureRealTime() && _audioCaptureSource != AudioCaptureSource.Manual && _audioCaptureSource != AudioCaptureSource.Unity && _audioCaptureSource != AudioCaptureSource.Wwise)
{
GUI.color = Color.yellow;
GUILayout.TextArea("Only Manual, Unity and Wwise Audio Sources are available in offline capture mode");
GUI.color = Color.white;
showAudioOptions = false;
}
#else
if (!IsCaptureRealTime() && _audioCaptureSource != AudioCaptureSource.Manual && _audioCaptureSource != AudioCaptureSource.Wwise)
{
GUI.color = Color.yellow;
GUILayout.TextArea("Only Manual and Wwise Audio Source is available in offline capture mode");
GUI.color = Color.white;
showAudioOptions = false;
}
#endif
if (IsCaptureRealTime() && _audioCaptureSource == AudioCaptureSource.Wwise)
{
GUI.color = Color.yellow;
GUILayout.TextArea("Wwise Audio Source is not available in realtime capture mode");
GUI.color = Color.white;
showAudioOptions = false;
}
#if !AVPRO_MOVIECAPTURE_WWISE_SUPPORT
if (!IsCaptureRealTime() && _audioCaptureSource == AudioCaptureSource.Wwise)
{
GUI.color = Color.red;
GUILayout.TextArea("To support Wwise audio capture: add AVPRO_MOVIECAPTURE_WWISE_SUPPORT to script defines in Player Settings");
GUI.color = Color.white;
showAudioOptions = false;
}
#endif
if (showAudioOptions)
{
if (_audioCaptureSource == AudioCaptureSource.Microphone)
{
GUILayout.Space(8f);
ShowMediaItemList("Microphone", DeviceManager.AudioInputDevices, _audioInputDevice, _videoCodec);
GUILayout.Space(8f);
}
else if (_audioCaptureSource == AudioCaptureSource.Manual)
{
EditorUtils.IntAsDropdown("Sample Rate", _propManualAudioSampleRate, EditorUtils.CommonAudioSampleRateNames, EditorUtils.CommonAudioSampleRateValues);
EditorGUILayout.PropertyField(_propManualAudioChannelCount, new GUIContent("Channels"));
}
}
}
EditorGUILayout.EndVertical();
}
}
private static string[] GetSuitableFileExtensions(Codec videoCodec, Codec audioCodec = null)
{
string[] result = null;
if (videoCodec != null)
{
int audioCodecIndex = -1;
if (audioCodec != null)
{
audioCodecIndex = audioCodec.Index;
}
result = NativePlugin.GetContainerFileExtensions(videoCodec.Index, audioCodecIndex);
}
if (result != null)
{
for (int i = 0; i < result.Length; i++)
{
result[i] = result[i].ToUpper();
}
}
else
{
result = new string[0];
}
return result;
}
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 static bool IsTrialVersion()
{
return NativePlugin.IsTrialVersion();
}
}
}
#endif