This commit is contained in:
jasonm-unity 2017-05-09 12:24:28 -04:00
Родитель 4f2475bbca
Коммит 91447d342d
70 изменённых файлов: 3368 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: a08b35c30775e274cacf0ab18c4d82cb
folderAsset: yes
timeCreated: 1491415339
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: d603226de9e3cc44e89a6c7354da487d
folderAsset: yes
timeCreated: 1491415339
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: a6b346140d4dd0c48b4431a7f27d450d
folderAsset: yes
timeCreated: 1491415339
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,109 @@
using System;
using UnityEngine;
using UnityEngine.Recorder.FrameRecorder;
namespace UnityEditor.Recorder.FrameRecorder
{
public abstract class DefaultImageRecorderSettingsEditor : RecorderSettingsEditor
{
string[] m_Displays;
protected override void OnEnable()
{
base.OnEnable();
var displayCount = Display.displays.Length;
m_Displays = new string[displayCount];
for (int i = 0; i < displayCount; i++)
m_Displays[i] = string.Format("Display {0}", i + 1);
}
protected override void OnInputGui()
{
var settingsObj = serializedObject.targetObject as ImageRecorderSettings;
m_LayoutHelper.AddEnumProperty("Source:", serializedObject, () => settingsObj.m_InputType);
switch (settingsObj.m_InputType)
{
case EImageSourceType.GameDisplay:
{
m_LayoutHelper.indentLevel++;
m_LayoutHelper.AddEnumProperty("Size:", serializedObject, () => settingsObj.m_SizeMode);
switch (settingsObj.m_SizeMode)
{
case EImageSizeMode.Dynamic:
break;
case EImageSizeMode.FullScreen:
break;
case EImageSizeMode.Width:
m_LayoutHelper.AddIntProperty("Resolution (width)", serializedObject, () => settingsObj.m_Width);
break;
case EImageSizeMode.Custom:
m_LayoutHelper.AddIntProperty("Resolution (width)", serializedObject, () => settingsObj.m_Width);
m_LayoutHelper.AddIntProperty("Resolution (height)", serializedObject, () => settingsObj.m_Height);
break;
}
m_LayoutHelper.indentLevel--;
break;
}
case EImageSourceType.RenderTexture:
{
OnCustomInputGui();
break;
}
case EImageSourceType.TaggedCamera:
{
m_LayoutHelper.indentLevel++;
m_LayoutHelper.AddStringProperty("Tags:", serializedObject, () => settingsObj.m_CameraTag);
m_LayoutHelper.indentLevel--;
break;
}
case EImageSourceType.MainCamera:
break;
}
base.OnInputGui();
}
protected override void OnEncodingGui()
{
//base.OnOutputGui();
//var settingsObj = target as ImageRecorderSettings;
/*
switch (settingsObj.m_InputType)
{
case EImageSourceType.GameDisplay:
{
m_LayoutHelper.AddBoolProperty("Scale image size", serializedObject, () => settingsObj.m_ScaleImage);
if (settingsObj.m_ScaleImage)
{
settingsObj.m_PreserveSourceAspectRatio = true;
m_LayoutHelper.AddIntProperty("Resolution (width)", serializedObject, () => settingsObj.m_Width);
}
break;
}
case EImageSourceType.MainCamera:
case EImageSourceType.TaggedCamera:
{
settingsObj.m_PreserveSourceAspectRatio = true;
m_LayoutHelper.AddIntProperty("Resolution (width)", serializedObject, () => settingsObj.m_Width);
break;
}
}
*/
}
protected virtual void OnCustomInputGui()
{
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 34dd54c4c05f9c7429eb3f50bcdac0f4
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,157 @@
using System;
using System.Resources;
using Assets.Unity.FrameRecorder.Scripts.Editor;
using UnityEngine.Recorder.FrameRecorder.Utilities;
using UnityEngine;
using UnityEngine.Recorder.FrameRecorder;
using UnityEngine.Recorder.FrameRecorder.Timeline;
using UnityEngine.Timeline;
namespace UnityEditor.Recorder.FrameRecorder.Timeline
{
[CustomEditor(typeof(FrameRecorderClip), true)]
public class RecorderClipEditor : Editor, IRecorderSelectorTarget
{
RecorderSettingsEditor m_SettingsEditor;
TimelineAsset m_Timeline;
RecorderSelector m_recorderSelector;
public void OnEnable()
{
m_recorderSelector = new RecorderSelector(this);
var shot = this.target as FrameRecorderClip;
var editorType = RecorderSettingsEditor.FindEditorForRecorder(shot.recorderType);
if (editorType != null)
{
m_SettingsEditor = Editor.CreateEditor(shot.m_Settings, editorType) as RecorderSettingsEditor;
}
}
public override void OnInspectorGUI()
{
if (target == null)
return;
m_recorderSelector.OnGui();
if (m_SettingsEditor != null)
{
m_SettingsEditor.showBounds = false;
m_Timeline = FindTimelineAsset();
PushTimelineIntoRecorder();
using (new EditorGUI.DisabledScope(EditorApplication.isPlaying))
{
EditorGUILayout.Separator();
using (new EditorGUI.DisabledScope(true))
{
GUILayout.BeginHorizontal();
GUILayout.Label("Settings ID:");
EditorGUILayout.TextField((m_SettingsEditor.target as FrameRecorderSettings).m_UniqueID);
GUILayout.EndHorizontal();
}
m_SettingsEditor.OnInspectorGUI();
EditorGUILayout.Separator();
PushRecorderIntoTimeline();
serializedObject.Update();
}
}
}
public string recorderCategory
{
get
{
var shot = this.target as FrameRecorderClip;
return shot.m_RecorderCategory;
}
set
{
var shot = this.target as FrameRecorderClip;
if (shot.m_RecorderCategory != value)
{
shot.m_RecorderCategory = value;
m_SettingsEditor = null;
shot.recorderType = null;
}
}
}
public string selectedRecorder
{
get
{
var shot = this.target as FrameRecorderClip;
return shot.m_RecorderTypeName;
}
}
public void SetRecorder(Type newRecorderType)
{
var clip = this.target as FrameRecorderClip;
if (newRecorderType == null || (m_SettingsEditor != null && m_SettingsEditor.target != null && clip.recorderType == newRecorderType))
return;
clip.recorderType = newRecorderType;
var editorType = RecorderSettingsEditor.FindEditorForRecorder(clip.recorderType);
if (editorType != null)
{
var assetGuid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(clip));
clip.m_Settings = RecordersInventory.CreateRecorderSettings(clip.recorderType, assetGuid, "TmLn-Clip:" + assetGuid);
m_SettingsEditor = CreateEditor(clip.m_Settings, editorType) as RecorderSettingsEditor;
}
else
Debug.LogError(string.Format("No editor class declared for recorder of type " + newRecorderType.FullName));
}
TimelineAsset FindTimelineAsset()
{
if (!AssetDatabase.Contains(target))
return null;
var path = AssetDatabase.GetAssetPath(target);
var objs = AssetDatabase.LoadAllAssetsAtPath(path);
foreach (var obj in objs)
{
if (obj != null && AssetDatabase.IsMainAsset(obj))
return obj as TimelineAsset;
}
return null;
}
void PushTimelineIntoRecorder()
{
if (m_Timeline == null)
return;
var settings = m_SettingsEditor.target as FrameRecorderSettings;
settings.m_DurationMode = DurationMode.Indefinite;
// Time
settings.m_FrameRate = m_Timeline.editorSettings.fps;
}
void PushRecorderIntoTimeline()
{
if (m_Timeline == null)
return;
var settings = m_SettingsEditor.target as FrameRecorderSettings;
settings.m_DurationMode = DurationMode.Indefinite;
// Time
m_Timeline.editorSettings.fps = (float)settings.m_FrameRate;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c7fe8472aebc45f4b93027b60a4003b3
timeCreated: 1491415344
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
using UnityEngine.Recorder.FrameRecorder;
namespace Assets.Unity.FrameRecorder.Scripts.Editor
{
interface IRecorderSelectorTarget
{
string recorderCategory { get; set; }
string selectedRecorder { get; }
void SetRecorder(Type newRecorderType);
}
class RecorderSelector
{
IRecorderSelectorTarget m_target;
string[] categoryRecorders;
public RecorderSelector(IRecorderSelectorTarget target)
{
m_target = target;
}
int GetCategoryIndex()
{
var categories = RecordersInventory.availableCategories;
for (int i = 0; i < categories.Length; i++)
if (categories[i] == m_target.recorderCategory)
return i;
if (categories.Length > 0)
return 0;
else
return -1;
}
bool SetCategoryFromIndex(int index)
{
if (index >= 0)
{
m_target.recorderCategory = RecordersInventory.availableCategories[index];
categoryRecorders = RecordersInventory.recordersByCategory[m_target.recorderCategory]
.Select(x => x.displayName)
.ToArray();
}
else
{
m_target.recorderCategory = string.Empty;
categoryRecorders = new string[0];
}
return index >= 0;
}
int GetRecorderIndex()
{
if (!RecordersInventory.recordersByCategory.ContainsKey(m_target.recorderCategory))
return -1;
var categoryRecorders = RecordersInventory.recordersByCategory[m_target.recorderCategory];
for (int i = 0; i < categoryRecorders.Count; i++)
if (categoryRecorders[i].recorder.AssemblyQualifiedName == m_target.selectedRecorder)
return i;
if (categoryRecorders.Count > 0)
return 0;
else
return -1;
}
Type GetRecorderFromIndex(int index)
{
if (index >= 0)
return RecordersInventory.recordersByCategory[m_target.recorderCategory][index].recorder;
return null;
}
public void OnGui()
{
// Group selection
EditorGUILayout.BeginHorizontal();
SetCategoryFromIndex(EditorGUILayout.Popup("Record what:", GetCategoryIndex(), RecordersInventory.availableCategories));
EditorGUILayout.EndHorizontal();
// Recorder in group selection
EditorGUILayout.BeginHorizontal();
var newIndex = EditorGUILayout.Popup("Using Recorder:", GetRecorderIndex(), categoryRecorders);
m_target.SetRecorder(GetRecorderFromIndex(newIndex));
EditorGUILayout.EndHorizontal();
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b94e4c4dfdb07cb43b93121a598b6e00
timeCreated: 1493839035
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,222 @@
using System;
using System.Collections.Generic;
using UnityEditor.Recorder.FrameRecorder.Utilities;
using UnityEngine;
using UnityEngine.Recorder.FrameRecorder;
using UnityEngine.Recorder.FrameRecorder.Utilities;
namespace UnityEditor.Recorder.FrameRecorder
{
public class RecorderEditorAttribute : Attribute
{
public Type recorderType { get; private set; }
public RecorderEditorAttribute(Type type)
{
recorderType = type;
}
}
public abstract class RecorderSettingsEditor : Editor
{
static SortedDictionary<string, Type> m_Editors;
internal LayoutHelper m_LayoutHelper;
public virtual Vector2 minSize
{
get { return new Vector2(0, 0); }
}
protected virtual void OnEnable()
{
m_LayoutHelper = new LayoutHelper(GUILayout.Width(175));
}
protected virtual void OnDisable() {}
protected virtual void Awake() {}
public bool isValid
{
get { return (target as FrameRecorderSettings).isValid; }
}
public bool showBounds { get; set; }
bool m_FoldoutInput = true;
bool m_FoldoutEncoder = true;
bool m_FoldoutTime = true;
bool m_FoldoutBounds = true;
bool m_FoldoutOutput = true;
public override void OnInspectorGUI()
{
if (target == null)
return;
m_LayoutHelper.indentLevel = 0;
EditorGUI.BeginChangeCheck();
serializedObject.Update();
OnInputGroupGui();
OnOutputGroupGui();
OnEncodingGroupGui();
OnTimeGroupGui();
OnBoundsGroupGui();
OnExtraGroupsGui();
var settingsObj = serializedObject.targetObject as FrameRecorderSettings;
m_LayoutHelper.AddBoolProperty("Verbose logging", serializedObject, () => settingsObj.m_Verbose);
serializedObject.ApplyModifiedProperties();
EditorGUI.EndChangeCheck();
}
protected virtual void OnInputGui()
{
m_LayoutHelper.AddIntProperty("Capture every n'th frame", serializedObject, () => (target as FrameRecorderSettings).m_CaptureEveryNthFrame);
}
protected virtual void OnOutputGui()
{
}
protected virtual void OnEncodingGui()
{
}
protected virtual void OnTimeGui()
{
var settingsObj = serializedObject.targetObject as FrameRecorderSettings;
m_LayoutHelper.AddEnumProperty("Frame rate mode", serializedObject, () => settingsObj.m_FrameRateMode);
m_LayoutHelper.indentLevel++;
var label = settingsObj.m_FrameRateMode == FrameRateMode.Fixed ? "Frame rate" : "Max frame rate";
m_LayoutHelper.AddDoubleProperty(label, serializedObject, () => settingsObj.m_FrameRate);
m_LayoutHelper.indentLevel--;
}
protected virtual void OnBounds()
{
var settingsObj = serializedObject.targetObject as FrameRecorderSettings;
m_LayoutHelper.AddEnumProperty("Recording Duration", serializedObject, () => settingsObj.m_DurationMode);
m_LayoutHelper.indentLevel++;
switch (settingsObj.m_DurationMode)
{
case DurationMode.Indefinite:
break;
case DurationMode.SingleFrame:
{
m_LayoutHelper.AddIntProperty("Frame", serializedObject, () => settingsObj.m_StartFrame, "Tooltip");
settingsObj.m_EndFrame = settingsObj.m_StartFrame;
break;
}
case DurationMode.FrameInterval:
{
EditorGUILayout.BeginHorizontal();
m_LayoutHelper.AddPropertyLabel("Frames");
m_LayoutHelper.AddIntProperty(serializedObject, () => settingsObj.m_StartFrame);
m_LayoutHelper.AddIntProperty(serializedObject, () => settingsObj.m_EndFrame);
EditorGUILayout.EndHorizontal();
break;
}
case DurationMode.TimeInterval:
{
EditorGUILayout.BeginHorizontal();
m_LayoutHelper.AddPropertyLabel("Time");
m_LayoutHelper.AddFloatProperty(serializedObject, () => settingsObj.m_StartTime);
m_LayoutHelper.AddFloatProperty(serializedObject, () => settingsObj.m_EndTime);
EditorGUILayout.EndHorizontal();
break;
}
}
m_LayoutHelper.indentLevel--;
}
protected virtual void OnInputGroupGui()
{
m_FoldoutInput = EditorGUILayout.Foldout(m_FoldoutInput, "Input");
if (m_FoldoutInput)
{
m_LayoutHelper.indentLevel++;
OnInputGui();
m_LayoutHelper.indentLevel--;
}
}
protected virtual void OnOutputGroupGui()
{
m_FoldoutOutput = EditorGUILayout.Foldout(m_FoldoutOutput, "Output");
if (m_FoldoutOutput)
{
m_LayoutHelper.indentLevel++;
OnOutputGui();
m_LayoutHelper.indentLevel--;
}
}
protected virtual void OnEncodingGroupGui()
{
m_FoldoutEncoder = EditorGUILayout.Foldout(m_FoldoutEncoder, "Encoding");
if (m_FoldoutEncoder)
{
m_LayoutHelper.indentLevel++;
OnEncodingGui();
m_LayoutHelper.indentLevel--;
}
}
protected virtual void OnTimeGroupGui()
{
m_FoldoutTime = EditorGUILayout.Foldout(m_FoldoutTime, "Time");
if (m_FoldoutTime)
{
m_LayoutHelper.indentLevel++;
OnTimeGui();
m_LayoutHelper.indentLevel--;
}
}
protected virtual void OnBoundsGroupGui()
{
if (showBounds)
{
m_FoldoutBounds = EditorGUILayout.Foldout(m_FoldoutBounds, "Bounds / Limits");
if (m_FoldoutBounds)
{
m_LayoutHelper.indentLevel++;
OnBounds();
m_LayoutHelper.indentLevel--;
}
}
}
protected virtual void OnExtraGroupsGui()
{
}
private static void Init()
{
if (m_Editors != null)
return;
m_Editors = new SortedDictionary<string, Type>();
foreach (var editor in ClassHelpers.FilterByAttribute<RecorderEditorAttribute>())
{
var attrib = editor.Value[0];
m_Editors.Add((attrib as RecorderEditorAttribute).recorderType.FullName, editor.Key);
}
}
public static Type FindEditorForRecorder(Type recorder)
{
Init();
return m_Editors.ContainsKey(recorder.FullName) ? m_Editors[recorder.FullName] : null;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c2d3ad15b5919624bbfcb237e18fd2ec
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Assets.Unity.FrameRecorder.Scripts.Editor;
using UnityEngine.Recorder.FrameRecorder.Utilities;
using UnityEngine;
using UnityEngine.Recorder.FrameRecorder;
namespace UnityEditor.Recorder.FrameRecorder
{
public class RecorderWindow : EditorWindow, IRecorderSelectorTarget
{
[SerializeField] string m_RecorderTypeName;
[SerializeField] string m_RecorderCategory;
[SerializeField] RecorderSettingsEditor m_SettingsEditor;
bool m_PendingStartRecording;
RecorderSelector m_recorderSelector;
Type recorderType
{
get { return Type.GetType(m_RecorderTypeName); }
set { m_RecorderTypeName = value == null ? string.Empty : value.AssemblyQualifiedName; }
}
public static void ShowAndPreselectCategory( string category )
{
var window = GetWindow(typeof(RecorderWindow), false, "Recorder") as RecorderWindow;
if( RecordersInventory.recordersByCategory.ContainsKey(category) )
window.m_RecorderCategory = category;
}
public void OnEnable()
{
m_recorderSelector = new RecorderSelector(this);
}
public void OnGUI()
{
if (m_PendingStartRecording && EditorApplication.isPlaying)
DelayedStartRecording();
var size = new Vector2(300, 400);
using (new EditorGUI.DisabledScope(EditorApplication.isPlaying))
m_recorderSelector.OnGui();
if (m_SettingsEditor != null)
{
m_SettingsEditor.showBounds = true;
using (new EditorGUI.DisabledScope(EditorApplication.isPlaying))
{
EditorGUILayout.Separator();
var editorMinSize = m_SettingsEditor.minSize;
if (editorMinSize.x > minSize.x) size.x = editorMinSize.x;
if (editorMinSize.y > minSize.y) size.y = editorMinSize.y;
m_SettingsEditor.OnInspectorGUI();
EditorGUILayout.Separator();
}
RecordButton();
}
minSize = size;
}
public void OnDestroy()
{
StopRecording();
UnityHelpers.Destroy(m_SettingsEditor);
}
void RecordButton()
{
var settings = (FrameRecorderSettings)m_SettingsEditor.target;
var recorderGO = FrameRecorderGOControler.FindRecorder(settings);
if (recorderGO == null)
{
using (new EditorGUI.DisabledScope(!m_SettingsEditor.isValid))
{
if (GUILayout.Button("Start Recording"))
StartRecording();
}
}
else
{
if (GUILayout.Button("Stop Recording"))
StopRecording();
}
}
void StartRecording()
{
if (!EditorApplication.isPlaying || EditorApplication.isPlaying)
{
m_PendingStartRecording = true;
EditorApplication.isPlaying = true;
return;
}
else
StartRecording(false);
}
void DelayedStartRecording()
{
m_PendingStartRecording = false;
StartRecording(true);
}
void StartRecording(bool autoExitPlayMode)
{
var settings = (FrameRecorderSettings)m_SettingsEditor.target;
var go = FrameRecorderGOControler.HookupRecorder(settings);
var session = new RecordingSession()
{
m_Recorder = RecordersInventory.InstantiateRecorder(recorderType, settings),
m_RecorderGO = go,
m_RecordingStartTS = Time.time / Time.timeScale,
m_FrameIndex = 0
};
var component = go.AddComponent<RecorderComponent>();
component.session = session;
component.autoExitPlayMode = autoExitPlayMode;
session.BeginRecording();
}
void StopRecording()
{
if (m_SettingsEditor != null)
{
var settings = (FrameRecorderSettings)m_SettingsEditor.target;
if (settings != null)
{
var recorderGO = FrameRecorderGOControler.FindRecorder(settings);
if (recorderGO != null)
{
UnityHelpers.Destroy(recorderGO);
}
}
}
}
public void SetRecorder(Type newRecorderType)
{
if (newRecorderType == null || (m_SettingsEditor != null && recorderType == newRecorderType))
return;
recorderType = newRecorderType;
var editorType = RecorderSettingsEditor.FindEditorForRecorder(recorderType);
if (editorType != null)
{
if (m_SettingsEditor != null)
{
UnityHelpers.Destroy(m_SettingsEditor.target);
UnityHelpers.Destroy(m_SettingsEditor);
m_SettingsEditor = null;
}
var settings = RecordersInventory.CreateRecorderSettings(recorderType, "N/A", "RecorderWindow");
m_SettingsEditor = UnityEditor.Editor.CreateEditor(settings, editorType) as RecorderSettingsEditor;
m_SettingsEditor.hideFlags = HideFlags.DontUnloadUnusedAsset; // <-- this means life time is manually managed by this class!!
}
else
Debug.LogError(string.Format("No editor class declared for recorder of type " + newRecorderType.FullName));
}
public string recorderCategory
{
get
{
return m_RecorderCategory;
}
set
{
if (m_RecorderCategory != value)
{
m_RecorderCategory = value;
m_SettingsEditor = null;
recorderType = null;
}
}
}
public string selectedRecorder
{
get { return m_RecorderTypeName; }
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d99962793b726bf4881e4b1719950d8f
timeCreated: 1491415344
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 2d548afd490f5254c9ca1d8b802ddff3
folderAsset: yes
timeCreated: 1491415339
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,259 @@
using System;
using System.Linq.Expressions;
using UnityEngine;
namespace UnityEditor.Recorder.FrameRecorder.Utilities
{
class LayoutHelper
{
public delegate T OnValueChangedDelegate<T>(T oldValue, T newValue);
private string[] m_Indents = new[] { "", " ", " ", " ", " "};
GUILayoutOption m_LableLayoutOption;
public LayoutHelper(GUILayoutOption lableLayoutOption)
{
m_LableLayoutOption = lableLayoutOption;
}
int m_IndentLevel;
public int indentLevel
{
get { return m_IndentLevel; }
set
{
m_IndentLevel = value;
if (m_IndentLevel < 0) m_IndentLevel = 0;
if (m_IndentLevel >= m_Indents.Length) m_IndentLevel = m_Indents.Length - 1;
}
}
public string indentation
{
get { return m_Indents[m_IndentLevel]; }
}
public void AddPropertyLabel(string text)
{
GUILayout.Label(m_Indents[m_IndentLevel] + text, m_LableLayoutOption);
}
public void AddPropertyLabel(string label, string tooltip)
{
GUILayout.Label(new GUIContent(m_Indents[m_IndentLevel] + label, tooltip), m_LableLayoutOption);
}
public bool AddEnumProperty(string label, SerializedObject serObj, Expression<Func<object>> propertySelector, string tooltip = "")
{
var property = serObj.FindProperty(propertySelector);
var ourRect = EditorGUILayout.BeginHorizontal();
EditorGUI.BeginProperty(ourRect, GUIContent.none, property);
AddPropertyLabel(label, tooltip);
var selectionFromInspector = property.intValue;
var actualSelected = EditorGUILayout.Popup(selectionFromInspector, property.enumDisplayNames);
var changed = actualSelected != property.intValue;
property.intValue = actualSelected;
EditorGUI.EndProperty();
EditorGUILayout.EndHorizontal();
return changed;
}
public bool AddFlagEnumProperty(string label, SerializedObject serObj, Expression<Func<object>> propertySelector, string tooltip = "")
{
var property = serObj.FindProperty(propertySelector);
var ourRect = EditorGUILayout.BeginHorizontal();
EditorGUI.BeginProperty(ourRect, GUIContent.none, property);
AddPropertyLabel(label, tooltip);
var selectionFromInspector = (int)Math.Log(property.intValue, 2);
var actualSelected = 1 << EditorGUILayout.Popup(selectionFromInspector, property.enumDisplayNames);
var changed = actualSelected != property.intValue;
property.intValue = actualSelected;
EditorGUI.EndProperty();
EditorGUILayout.EndHorizontal();
return changed;
}
public bool AddEnumProperty(string label, SerializedObject serObj, Expression<Func<object>> propertySelector, string[] values, string tooltip = "")
{
var property = serObj.FindProperty(propertySelector);
var ourRect = EditorGUILayout.BeginHorizontal();
EditorGUI.BeginProperty(ourRect, GUIContent.none, property);
AddPropertyLabel(label, tooltip);
var selectionFromInspector = property.intValue;
var actualSelected = EditorGUILayout.Popup(selectionFromInspector, values);
var changed = actualSelected != property.intValue;
property.intValue = actualSelected;
EditorGUI.EndProperty();
EditorGUILayout.EndHorizontal();
return changed;
}
public bool AddStringProperty(string label, SerializedObject serObj, Expression<Func<object>> propertySelector, string tooltip = "")
{
var property = serObj.FindProperty(propertySelector);
var ourRect = EditorGUILayout.BeginHorizontal();
EditorGUI.BeginProperty(ourRect, GUIContent.none, property);
AddPropertyLabel(label);
var orgValue = property.stringValue;
var newValue = EditorGUILayout.TextField(new GUIContent("", tooltip), orgValue);
var changed = orgValue != newValue;
property.stringValue = newValue;
EditorGUI.EndProperty();
EditorGUILayout.EndHorizontal();
return changed;
}
public bool AddIntProperty(string label, SerializedProperty property, string tooltip = "")
{
var ourRect = EditorGUILayout.BeginHorizontal();
EditorGUI.BeginProperty(ourRect, GUIContent.none, property);
AddPropertyLabel(label);
var orgValue = property.intValue;
var newValue = EditorGUILayout.IntField(new GUIContent("", tooltip), orgValue);
var changed = orgValue != newValue;
property.intValue = newValue;
EditorGUI.EndProperty();
EditorGUILayout.EndHorizontal();
return changed;
}
public bool AddIntProperty(string label, SerializedObject serObj, Expression<Func<object>> propertySelector, string tooltip = "")
{
return AddIntProperty(label, serObj.FindProperty(propertySelector), tooltip);
}
public bool AddIntProperty(SerializedProperty property)
{
var ourRect = EditorGUILayout.BeginHorizontal();
EditorGUI.BeginProperty(ourRect, GUIContent.none, property);
var orgValue = property.intValue;
var newValue = EditorGUILayout.IntField(orgValue);
var changed = orgValue != newValue;
property.intValue = newValue;
EditorGUI.EndProperty();
EditorGUILayout.EndHorizontal();
return changed;
}
public bool AddFloatProperty(SerializedObject serObj, Expression<Func<object>> propertySelector)
{
return AddFloatProperty(serObj.FindProperty(propertySelector));
}
public bool AddFloatProperty(SerializedProperty property)
{
var ourRect = EditorGUILayout.BeginHorizontal();
EditorGUI.BeginProperty(ourRect, GUIContent.none, property);
var orgValue = property.floatValue;
var newValue = EditorGUILayout.FloatField(orgValue);
var changed = orgValue != newValue;
property.floatValue = newValue;
EditorGUI.EndProperty();
EditorGUILayout.EndHorizontal();
return changed;
}
public bool AddIntProperty(SerializedObject serObj, Expression<Func<object>> propertySelector)
{
return AddIntProperty(serObj.FindProperty(propertySelector));
}
public bool AddIntProperty(SerializedProperty parentSerProp, Expression<Func<object>> propertySelector)
{
return AddIntProperty(parentSerProp.FindPropertyRelative(propertySelector));
}
public bool AddFloatProperty(string label, SerializedObject serObj, Expression<Func<object>> propertySelector, string tooltip = "")
{
var property = serObj.FindProperty(propertySelector);
var ourRect = EditorGUILayout.BeginHorizontal();
EditorGUI.BeginProperty(ourRect, GUIContent.none, property);
AddPropertyLabel(label);
var orgValue = property.floatValue;
var newValue = EditorGUILayout.FloatField(new GUIContent("", tooltip), orgValue);
var changed = orgValue != newValue;
property.floatValue = newValue;
EditorGUI.EndProperty();
EditorGUILayout.EndHorizontal();
return changed;
}
public bool AddDoubleProperty(string label, SerializedObject serObj, Expression<Func<object>> propertySelector, string tooltip = "")
{
var property = serObj.FindProperty(propertySelector);
var ourRect = EditorGUILayout.BeginHorizontal();
EditorGUI.BeginProperty(ourRect, GUIContent.none, property);
AddPropertyLabel(label);
var orgValue = property.doubleValue;
var newValue = EditorGUILayout.DoubleField(new GUIContent("", tooltip), orgValue);
var changed = orgValue != newValue;
property.doubleValue = newValue;
EditorGUI.EndProperty();
EditorGUILayout.EndHorizontal();
return changed;
}
public bool AddBoolProperty(string label, SerializedObject serObj, Expression<Func<object>> propertySelector, string tooltip = "")
{
var property = serObj.FindProperty(propertySelector);
var ourRect = EditorGUILayout.BeginHorizontal();
EditorGUI.BeginProperty(ourRect, GUIContent.none, property);
AddPropertyLabel(label);
var orgValue = property.boolValue;
var newValue = EditorGUILayout.Toggle(new GUIContent("", tooltip), orgValue);
var changed = orgValue != newValue;
property.boolValue = newValue;
EditorGUI.EndProperty();
EditorGUILayout.EndHorizontal();
return changed;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b25434794c2520040b7ec0687028cb7e
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,36 @@
using System;
using System.Linq.Expressions;
namespace UnityEditor.Recorder.FrameRecorder.Utilities
{
public static class SerializableObjHelper
{
public static SerializedProperty FindProperty(this SerializedObject obj, Expression<Func<object>> exp)
{
var body = exp.Body as MemberExpression;
if (body == null)
{
var ubody = (UnaryExpression)exp.Body;
body = ubody.Operand as MemberExpression;
}
var name = body.Member.Name;
return obj.FindProperty(name);
}
public static SerializedProperty FindPropertyRelative(this SerializedProperty obj, Expression<Func<object>> exp)
{
var body = exp.Body as MemberExpression;
if (body == null)
{
var ubody = (UnaryExpression)exp.Body;
body = ubody.Operand as MemberExpression;
}
var name = body.Member.Name;
return obj.FindPropertyRelative(name);
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b91f080b208afff4d94678e466eeecc4
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 465980b32e42e4a439d49f4d4bf0ef31
folderAsset: yes
timeCreated: 1491417212
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 6cbec5a6a20c2074e9b44e94a96092d6
folderAsset: yes
timeCreated: 1491415339
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,158 @@
using System;
using UnityEditor;
using UnityEngine.Recorder.FrameRecorder.Utilities;
using UnityEngine.Rendering;
namespace UnityEngine.Recorder.FrameRecorder.DataSource
{
public class CameraAsRenderTexture : RenderTextureSource
{
Shader m_shCopy;
Material m_mat_copy;
Mesh m_quad;
CommandBuffer m_cb;
Camera m_Camera;
bool m_cameraChanged;
protected int m_Width;
protected int m_Height;
protected EImageSizeMode m_SizeMode;
public Camera TargetCamera
{
get { return m_Camera; }
set
{
if (m_Camera != value)
{
ReleaseCamera();
m_Camera = value;
m_cameraChanged = true;
}
}
}
public Shader CopyShader
{
get
{
if (m_shCopy == null)
{
// TODO: make this Non Editor compatible
// Figure out where this shader should reside.
m_shCopy = AssetDatabase.LoadAssetAtPath<Shader>(AssetDatabase.GUIDToAssetPath("55d39f733f4029f4cbc92b5c2279e15b"));
}
return m_shCopy;
}
set { m_shCopy = value; }
}
public CameraAsRenderTexture(EImageSizeMode sizeMode, int width, int height)
{
m_SizeMode = sizeMode;
m_Width = width;
m_Height = height;
m_quad = CreateFullscreenQuad();
}
public void PrepareNewFrame()
{
// initialize scratch buffer
var newTexture = PrepFrameRenderTexture();
// initialize command buffer
if (m_Camera != null && m_cameraChanged || newTexture)
{
if (m_cb != null)
{
m_Camera.RemoveCommandBuffer(CameraEvent.AfterEverything, m_cb);
m_cb.Release();
}
// TODO: This should not be here!!!
m_mat_copy = new Material(CopyShader);
if (m_Camera.targetTexture != null)
m_mat_copy.EnableKeyword("OFFSCREEN");
var tid = Shader.PropertyToID("_TmpFrameBuffer");
m_cb = new CommandBuffer { name = "Frame Recorder: copy frame buffer" };
m_cb.GetTemporaryRT(tid, -1, -1, 0, FilterMode.Bilinear);
m_cb.Blit(BuiltinRenderTextureType.CurrentActive, tid);
m_cb.SetRenderTarget(buffer);
m_cb.DrawMesh(m_quad, Matrix4x4.identity, m_mat_copy, 0, 0);
m_cb.ReleaseTemporaryRT(tid);
m_Camera.AddCommandBuffer(CameraEvent.AfterEverything, m_cb);
m_cameraChanged = false;
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
ReleaseCamera();
}
base.Dispose(disposing);
}
protected virtual void ReleaseCamera()
{
if (m_cb != null)
{
if (m_Camera != null)
m_Camera.RemoveCommandBuffer(CameraEvent.AfterEverything, m_cb);
m_cb.Release();
m_cb = null;
}
if (m_mat_copy != null)
UnityHelpers.Destroy(m_mat_copy);
}
bool PrepFrameRenderTexture()
{
var height = (int)(m_Width / m_Camera.aspect);
if (buffer != null)
{
if (buffer.IsCreated() && buffer.width == m_Width && buffer.height == height)
{
return false;
}
ReleaseBuffer();
}
buffer = new RenderTexture(m_Width, height, 0, RenderTextureFormat.ARGB32)
{
wrapMode = TextureWrapMode.Repeat
};
buffer.Create();
return true;
}
public static Mesh CreateFullscreenQuad()
{
var vertices = new Vector3[4]
{
new Vector3(1.0f, 1.0f, 0.0f),
new Vector3(-1.0f, 1.0f, 0.0f),
new Vector3(-1.0f, -1.0f, 0.0f),
new Vector3(1.0f, -1.0f, 0.0f),
};
var indices = new[] { 0, 1, 2, 2, 3, 0 };
var r = new Mesh
{
vertices = vertices,
triangles = indices
};
return r;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 852b7afeb4df2254e81cc4c6d11ca313
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,36 @@
using System;
namespace UnityEngine.Recorder.FrameRecorder.DataSource
{
public class DisplayAsRenderTexture : CameraAsRenderTexture
{
public int m_DisplayID;
public void PrepareNewFrame(RecordingSession session)
{
if (TargetCamera != null && TargetCamera.targetDisplay != m_DisplayID)
TargetCamera = null;
if (TargetCamera == null)
{
var displayGO = new GameObject();
displayGO.name = "CameraHostGO-" + displayGO.GetInstanceID();
displayGO.transform.parent = session.m_RecorderGO.transform;
var camera = displayGO.AddComponent<Camera>();
camera.clearFlags = CameraClearFlags.Nothing;
camera.cullingMask = 0;
camera.renderingPath = RenderingPath.DeferredShading;
camera.targetDisplay = m_DisplayID;
camera.rect = new Rect(0, 0, 1, 1);
camera.depth = float.MaxValue;
TargetCamera = camera;
}
base.PrepareNewFrame();
}
public DisplayAsRenderTexture(int width)
: base( EImageSizeMode.Width, width, 0) {}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9eef97e3b03eb7d489aba82d5d15fb99
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine.Recorder.FrameRecorder.Utilities;
namespace UnityEngine.Recorder.FrameRecorder.DataSource
{
public class GameViewAsRenderTexture : CameraAsRenderTexture
{
GameViewWindow m_GameView;
public void PrepareNewFrame(RecordingSession session)
{
if (TargetCamera == null)
{
var displayGO = new GameObject();
displayGO.name = "CameraHostGO-" + displayGO.GetInstanceID();
displayGO.transform.parent = session.m_RecorderGO.transform;
var camera = displayGO.AddComponent<Camera>();
camera.clearFlags = CameraClearFlags.Nothing;
camera.cullingMask = 0;
camera.renderingPath = RenderingPath.DeferredShading;
camera.targetDisplay = 0;
camera.rect = new Rect(0, 0, 1, 1);
camera.depth = float.MaxValue;
TargetCamera = camera;
}
base.PrepareNewFrame();
}
public GameViewAsRenderTexture( EImageSizeMode sizeMode, int width, int height)
: base(sizeMode, width, height)
{
}
public void BeginRecording()
{
m_GameView = new GameViewWindow();
m_GameView.FullScreenGameWindow( m_SizeMode, m_Width, m_Height );
m_Width = (int)m_GameView.size.x;
m_Height = (int)m_GameView.size.y;
}
public void EndRecording()
{
if (m_GameView != null)
m_GameView.RestoreGameWindow();
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f1701eab2c131b34ebbfd0f24ee466b2
timeCreated: 1493928434
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,24 @@
using System;
namespace UnityEngine.Recorder.FrameRecorder.DataSource
{
public class RecorderSource : IDisposable
{
public int SourceID { get; set; }
~RecorderSource()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
GC.SuppressFinalize(this);
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9f956c0b0f15ce74aac4600909d4e55f
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,33 @@
using System;
namespace UnityEngine.Recorder.FrameRecorder.DataSource
{
public abstract class RenderTextureSource : RecorderSource
{
public RenderTexture buffer { get; set; }
public RenderTexture UnlinkBuffer()
{
var temp = buffer;
buffer = null;
return temp;
}
public void ReleaseBuffer()
{
if (buffer != null)
{
buffer.Release();
buffer = null;
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
ReleaseBuffer();
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1dd8c8968d3848743a824ed5191b2805
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
using System;
namespace UnityEngine.Recorder.FrameRecorder
{
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class FrameRecorderClassAttribute : Attribute
{
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ca62b38426adb1d47ad6cd6c94001b6a
timeCreated: 1491415344
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,63 @@
using System;
namespace UnityEngine.Recorder.FrameRecorder
{
public class FrameRecorderGOControler
{
const string k_HostGoName = "UnityEngine.Recorder.FrameRecorder";
public static GameObject GetGameObject()
{
return GameObject.Find(k_HostGoName) ?? new GameObject(k_HostGoName);
}
public static GameObject GetSettingsRoot()
{
var root = GetGameObject();
var settingsTr = root.transform.Find("Settings");
GameObject settingsGO;
if (settingsTr == null)
{
settingsGO = new GameObject("Settings");
settingsGO.transform.parent = root.transform;
}
else
settingsGO = settingsTr.gameObject;
return settingsGO;
}
public static GameObject GetRecordersRoot()
{
var root = GetGameObject();
var settingsTr = root.transform.Find("Recording");
GameObject settingsGO;
if (settingsTr == null)
{
settingsGO = new GameObject("Recording");
settingsGO.transform.parent = root.transform;
}
else
settingsGO = settingsTr.gameObject;
return settingsGO;
}
public static GameObject HookupRecorder(FrameRecorderSettings settings)
{
var ctrl = GetRecordersRoot();
var recorderGO = new GameObject(settings.m_UniqueID);
recorderGO.transform.parent = ctrl.transform;
return recorderGO;
}
public static GameObject FindRecorder(FrameRecorderSettings settings)
{
var ctrl = GetRecordersRoot();
var go = ctrl.transform.Find(settings.m_UniqueID);
return go == null ? null : go.gameObject;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e378e9c2cad5a7e48a6931f63edd1421
timeCreated: 1491415344
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,86 @@
using System;
using UnityEditor;
using UnityEngine.Recorder.FrameRecorder.Utilities;
namespace UnityEngine.Recorder.FrameRecorder
{
public enum EImageSourceType
{
GameDisplay,
SceneView,
MainCamera,
TaggedCamera,
RenderTexture
}
public enum FrameRateMode
{
Variable,
Fixed,
}
public enum DurationMode
{
Indefinite,
SingleFrame,
FrameInterval,
TimeInterval
}
public class FrameRecorderSettings : MonoBehaviour
{
public string m_UniqueID;
public string m_OwnerAssetID;
public int m_CaptureEveryNthFrame = 1;
public FrameRateMode m_FrameRateMode = FrameRateMode.Fixed;
public double m_FrameRate = 24.0;
public int m_StartFrame;
public int m_EndFrame = 1000;
public float m_StartTime = 0.0f;
public float m_EndTime = 1.0f;
public DurationMode m_DurationMode;
public bool m_Verbose = false;
public virtual bool isValid
{
get { return m_FrameRate > 0; }
}
public virtual void OnEnable()
{
GarbageCollect();
if (string.IsNullOrEmpty(m_UniqueID))
m_UniqueID = string.Format("{0}-{1}", GetType().Name, Guid.NewGuid());
}
public bool fixedDuration
{
get { return m_DurationMode != DurationMode.Indefinite; }
}
void GarbageCollect()
{
#if UNITY_EDITOR
if (string.IsNullOrEmpty(m_OwnerAssetID))
return;
try
{
var guid = new Guid(m_OwnerAssetID);
if (guid == Guid.Empty)
return;
}
catch
{
return;
}
// Check if it's associated asset, if there was one, still exists. If it does not: cleanup / delete this setting
if (string.IsNullOrEmpty(AssetDatabase.GUIDToAssetPath(m_OwnerAssetID)))
{
UnityHelpers.Destroy(gameObject);
}
#endif
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 180842267b7175e4c9dedaf1f548db0f
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,29 @@
using System;
namespace UnityEngine.Recorder.FrameRecorder
{
public enum EImageSizeMode
{
Dynamic,
FullScreen,
Width,
Custom
}
public class ImageRecorderSettings : FrameRecorderSettings
{
public EImageSizeMode m_SizeMode = EImageSizeMode.Dynamic;
public int m_Width = 1024;
public int m_Height = 768;
public EImageSourceType m_InputType = EImageSourceType.GameDisplay;
public int m_ScreenID = 0;
public string m_CameraTag;
public override bool isValid
{
get { return base.isValid && m_Width > 0 && m_Height > 0; }
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f3941bff05f4e88479d3c4741b63bbf1
timeCreated: 1491415344
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using UnityEngine.Recorder.FrameRecorder.DataSource;
namespace UnityEngine.Recorder.FrameRecorder
{
public enum ERecordingSessionStage
{
BeginRecording,
NewFrameStarting,
NewFrameReady,
FrameDone,
EndRecording,
}
public abstract class Recorder : ScriptableObject
{
double m_OriginalCaptureFrameRate;
public int recordedFramesCount { get; set; }
/// <summary>
/// Concept: container class for Recorder Source objects that assumes nothing on the contained source object
///
/// Motivation: let's recorders use any type of object as a source of data to record.
/// </summary>
protected struct BoxedSource
{
public System.Object m_Source;
public SortedDictionary<ERecordingSessionStage, Action<RecordingSession>> m_StageHandlers;
public BoxedSource(System.Object source)
{
m_Source = source;
m_StageHandlers = new SortedDictionary<ERecordingSessionStage, Action<RecordingSession>>();
}
public void SignalNewStage(ERecordingSessionStage stage, RecordingSession session)
{
if (m_StageHandlers.ContainsKey(stage))
m_StageHandlers[stage](session);
}
}
protected List<BoxedSource> m_BoxedSources;
public virtual void Reset()
{
recordedFramesCount = 0;
recording = false;
}
protected virtual void OnDestroy()
{
}
public abstract FrameRecorderSettings settings { get; set; }
// returns true if recording is starting. false if failed to begin recording or was already recording
public virtual bool BeginRecording(RecordingSession session)
{
if (recording)
return false;
if (settings.m_Verbose)
Debug.Log(string.Format("Recorder {0} starting to record", GetType().Name));
m_OriginalCaptureFrameRate = Time.captureFramerate;
var fixedRate = settings.m_FrameRateMode == FrameRateMode.Fixed ? (int)settings.m_FrameRate : m_OriginalCaptureFrameRate;
if (fixedRate != m_OriginalCaptureFrameRate)
{
if (Time.captureFramerate > 0)
Debug.LogWarning(string.Format("Frame Recorder {0} is set to record at a fixed rate and another component has already set a conflicting value for [Time.captureFramerate], new value being applied : {1}!", GetType().Name, fixedRate));
Time.captureFramerate = (int)fixedRate;
if (settings.m_Verbose)
Debug.Log("Frame recorder set fixed frame rate to " + fixedRate);
}
return true;
}
public virtual void EndRecording(RecordingSession ctx)
{
if (!recording)
return;
recording = false;
if (Time.captureFramerate != m_OriginalCaptureFrameRate)
{
Time.captureFramerate = (int)m_OriginalCaptureFrameRate;
if (settings.m_Verbose)
Debug.Log("Frame recorder resetting fixed frame rate to original value of " + m_OriginalCaptureFrameRate);
}
foreach (var source in m_BoxedSources)
{
if (source.m_Source is IDisposable)
(source.m_Source as IDisposable).Dispose();
}
Debug.Log(string.Format("{0} recording stopped, total frame count: {1}", GetType().Name, recordedFramesCount));
}
public abstract void RecordFrame(RecordingSession ctx);
public virtual void PrepareNewFrame(RecordingSession ctx)
{
}
public virtual bool SkipFrame(RecordingSession ctx)
{
return !recording || (ctx.m_FrameIndex % settings.m_CaptureEveryNthFrame) != 0;
}
public bool recording { get; protected set; }
public void SignalSourcesOfStage(ERecordingSessionStage stage, RecordingSession session)
{
if (m_BoxedSources != null)
{
foreach (var boxedSource in m_BoxedSources)
boxedSource.SignalNewStage(stage, session);
}
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 58fe471fc3009fb4d8cf266a5cc5a7a1
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,80 @@
using System;
using System.Collections;
namespace UnityEngine.Recorder.FrameRecorder
{
[ExecuteInEditMode]
public class RecorderComponent : MonoBehaviour
{
public bool autoExitPlayMode { get; set; }
public RecordingSession session { get; set; }
public void Update()
{
if (session != null && session.recording)
{
session.m_CurrentFrameStartTS = (Time.time / Time.timeScale) - session.m_RecordingStartTS;
session.m_FrameIndex++;
session.PrepareNewFrame();
}
}
IEnumerator RecordFrame()
{
yield return new WaitForEndOfFrame();
if (session != null && session.recording)
{
session.RecordFrame();
switch (session.m_Recorder.settings.m_DurationMode)
{
case DurationMode.Indefinite:
break;
case DurationMode.SingleFrame:
enabled = false;
break;
case DurationMode.FrameInterval:
if (session.m_FrameIndex >= session.settings.m_EndFrame)
enabled = false;
break;
case DurationMode.TimeInterval:
if (session.m_CurrentFrameStartTS >= session.settings.m_EndTime)
enabled = false;
break;
}
}
}
public void LateUpdate()
{
if (session != null && session.recording)
{
if (session.m_FrameIndex >= session.settings.m_StartFrame)
{
StartCoroutine(RecordFrame());
}
}
}
public void OnDisable()
{
if (session != null)
{
session.Dispose();
session = null;
#if UNITY_EDITOR
if (autoExitPlayMode)
UnityEditor.EditorApplication.isPlaying = false;
#endif
}
}
public void OnDestroy()
{
if (session != null)
session.Dispose();
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6122dab7ff1764c468a03aa29f49ea5b
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,225 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using UnityEngine.Recorder.FrameRecorder.Utilities;
namespace UnityEngine.Recorder.FrameRecorder
{
public class RecorderInfo
{
public Type recorder;
public Type settings;
public string category;
public string displayName;
public static RecorderInfo Instantiate<TRecoder, TSettings>(string category, string displayName)
where TRecoder : class
where TSettings : class
{
return new RecorderInfo()
{
recorder = typeof(TRecoder),
settings = typeof(TSettings),
category = category,
displayName = displayName
};
}
}
// to be internal once inside unity code base
public static class RecordersInventory
{
internal static SortedDictionary<string, RecorderInfo> recorders { get; private set; }
static void Init()
{
#if UNITY_EDITOR
if (RecordersInventory.recorders != null)
return;
RecordersInventory.recorders = new SortedDictionary<string, RecorderInfo>();
var recorders = ClassHelpers.FilterByAttribute<FrameRecorderClassAttribute>(false);
foreach (var recorder in recorders)
AddRecorder(recorder.Key);
#endif
}
#if UNITY_EDITOR
static SortedDictionary<string, List<RecorderInfo>> m_RecordersByCategory;
public static SortedDictionary<string, List<RecorderInfo>> recordersByCategory
{
get
{
Init();
return m_RecordersByCategory;
}
}
static string[] m_AvailableCategories;
public static string[] availableCategories
{
get
{
if (m_AvailableCategories == null)
{
m_AvailableCategories = RecordersInventory.ListRecorders()
.GroupBy(x => x.category)
.Select(x => x.Key)
.OrderBy(x => x)
.ToArray();
}
return m_AvailableCategories;
}
}
#endif
static bool AddRecorder(Type recorderType)
{
RecorderInfo recInfo = null;
var method = recorderType.GetMethod("GetRecorderInfo", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
if (method != null)
{
try
{
recInfo = method.Invoke(null, null) as RecorderInfo;
if (recInfo != null)
{
if (recorders == null)
recorders = new SortedDictionary<string, RecorderInfo>();
recorders.Add(recInfo.recorder.FullName, recInfo);
#if UNITY_EDITOR
if (m_RecordersByCategory == null)
m_RecordersByCategory = new SortedDictionary<string, List<RecorderInfo>>();
if (!m_RecordersByCategory.ContainsKey(recInfo.category))
m_RecordersByCategory.Add(recInfo.category, new List<RecorderInfo>());
m_RecordersByCategory[recInfo.category].Add(recInfo);
#endif
}
return true;
}
catch (Exception ex)
{
Debug.LogException(ex);
}
}
else
{
Debug.LogError(String.Format("The recorder class '{0}' need to provide method: static RecorderInfo GetRecorderInfo(...)", recorderType.FullName));
}
return false;
}
public static RecorderInfo GetRecorder<TRecorder>() where TRecorder : class
{
return GetRecorder(typeof(TRecorder));
}
static RecorderInfo GetRecorder(Type recorderType)
{
Init();
if (recorders.ContainsKey(recorderType.FullName))
return recorders[recorderType.FullName];
#if UNITY_EDITOR
return null;
#else
if (AddRecorder(recorderType))
return recorders[recorderType.FullName];
else
return null
#endif
}
public static IEnumerable<RecorderInfo> ListRecorders()
{
Init();
foreach (var recorderInfo in recorders)
{
yield return recorderInfo.Value;
}
}
public static Recorder InstantiateRecorder(Type recorderType, FrameRecorderSettings settings)
{
Init();
var factory = GetRecorder(recorderType);
if (factory != null)
{
var recorder = ScriptableObject.CreateInstance(recorderType) as Recorder;
recorder.Reset();
recorder.settings = settings;
return recorder;
}
else
throw new ArgumentException("No factory was registered for " + recorderType.Name);
}
public static FrameRecorderSettings CreateRecorderSettings(Type recorderType, string ownerAssetId, string uniqueId)
{
Init();
var recorderinfo = GetRecorder(recorderType);
if (recorderinfo != null)
{
var rootRecordingGO = FrameRecorderGOControler.GetSettingsRoot();
var transform = rootRecordingGO.transform.Find(uniqueId);
if (transform == null)
return New(recorderinfo.settings, ownerAssetId, uniqueId);
var settings = (FrameRecorderSettings)transform.GetComponent(recorderinfo.settings);
if (settings == null || settings.GetType() != recorderinfo.settings)
{
UnityHelpers.Destroy(transform.gameObject);
return New(recorderinfo.settings, ownerAssetId, uniqueId);
}
return settings;
}
else
throw new ArgumentException("No factory was registered for " + recorderType.Name);
}
public static void DeleteSettings(string uniqueId)
{
var bank = FrameRecorderGOControler.GetSettingsRoot();
GameObject settingsGO = null;
var t = bank.transform.Find(uniqueId);
if (t != null)
settingsGO = t.gameObject;
if (settingsGO == null)
return;
UnityHelpers.Destroy(settingsGO);
}
static FrameRecorderSettings New(Type type, string ownerAssetId, string uniqueId)
{
if (!string.IsNullOrEmpty(uniqueId))
DeleteSettings(uniqueId);
var bank = FrameRecorderGOControler.GetSettingsRoot();
var settingsGO = new GameObject();
settingsGO.transform.parent = bank.transform;
var settings = (FrameRecorderSettings)settingsGO.AddComponent(type);
settings.m_UniqueID = uniqueId;
settings.m_OwnerAssetID = ownerAssetId;
settingsGO.name = settings.m_UniqueID;
return settings;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e11d656cf6217cb41ba5443ff354aea7
timeCreated: 1491415344
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using UnityEngine.Recorder.FrameRecorder.Utilities;
namespace UnityEngine.Recorder.FrameRecorder
{
public class RecordingSession : IDisposable
{
public Recorder m_Recorder;
public GameObject m_RecorderGO;
public List<UnityEngine.Object> m_ObjsOfInterest;
public int m_FrameIndex; // count starts at 0.
public double m_CurrentFrameStartTS;
public double m_RecordingStartTS;
public FrameRecorderSettings settings { get { return m_Recorder.settings; } }
public bool recording { get { return m_Recorder.recording; } }
public bool BeginRecording()
{
if (!m_Recorder.BeginRecording(this))
return false;
m_Recorder.SignalSourcesOfStage(ERecordingSessionStage.BeginRecording, this);
return true;
}
public virtual void EndRecording()
{
m_Recorder.EndRecording(this);
m_Recorder.SignalSourcesOfStage(ERecordingSessionStage.EndRecording, this);
}
public void RecordFrame()
{
m_Recorder.SignalSourcesOfStage(ERecordingSessionStage.NewFrameReady, this);
if (!m_Recorder.SkipFrame(this))
{
m_Recorder.RecordFrame(this);
m_Recorder.recordedFramesCount++;
}
m_Recorder.SignalSourcesOfStage(ERecordingSessionStage.FrameDone, this);
}
public void PrepareNewFrame()
{
m_Recorder.SignalSourcesOfStage(ERecordingSessionStage.NewFrameStarting, this);
m_Recorder.PrepareNewFrame(this);
}
public void Dispose()
{
if (m_Recorder != null)
{
if (recording)
EndRecording();
UnityHelpers.Destroy(m_Recorder);
UnityHelpers.Destroy(m_RecorderGO);
}
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 061b0c1d04c01f54fa322b11b8662964
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,144 @@
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine.Recorder.FrameRecorder.DataSource;
namespace UnityEngine.Recorder.FrameRecorder
{
public abstract class RenderTextureRecorder<T> : Recorder where T : ImageRecorderSettings
{
[SerializeField]
protected T m_Settings;
public override FrameRecorderSettings settings
{
get { return m_Settings; }
set { m_Settings = (T)value; }
}
protected string m_OutputFile;
#if UNITY_EDITOR
public static EditorWindow GetMainGameView()
{
System.Type T = System.Type.GetType("UnityEditor.GameView,UnityEditor");
System.Reflection.MethodInfo GetMainGameView = T.GetMethod("GetMainGameView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
System.Object Res = GetMainGameView.Invoke(null, null);
return (EditorWindow)Res;
}
#endif
public override bool BeginRecording(RecordingSession session)
{
base.BeginRecording(session);
m_BoxedSources = new List<BoxedSource>();
// Targetting explicit cameras?
if (session.m_ObjsOfInterest != null)
{
foreach (var objOfInterest in session.m_ObjsOfInterest)
{
if (!(objOfInterest is Camera))
continue;
var source = new CameraAsRenderTexture( EImageSizeMode.Width, m_Settings.m_Width, 0)
{
TargetCamera = (Camera)objOfInterest
};
var boxedSource = new BoxedSource(source);
boxedSource.m_StageHandlers.Add(ERecordingSessionStage.NewFrameStarting, (x) => source.PrepareNewFrame());
m_BoxedSources.Add(boxedSource);
}
}
// Targetting a game display?
if (m_Settings.m_InputType == EImageSourceType.GameDisplay)
{
var source = new GameViewAsRenderTexture(m_Settings.m_SizeMode, m_Settings.m_Width, m_Settings.m_Height );
var boxedSource = new BoxedSource(source);
boxedSource.m_StageHandlers.Add(ERecordingSessionStage.NewFrameStarting, (x) => source.PrepareNewFrame(session) );
boxedSource.m_StageHandlers.Add(ERecordingSessionStage.BeginRecording, (x) => source.BeginRecording() );
boxedSource.m_StageHandlers.Add(ERecordingSessionStage.EndRecording, (x) => source.EndRecording() );
m_BoxedSources.Add(boxedSource);
}
// Targetting the scene view?
#if UNITY_EDITOR
/*
if (m_Settings.m_InputType == EImageSourceType.SceneView)
{
if (!m_Settings.m_ScaleImage)
{
m_Settings.m_Width = (int)SceneView.currentDrawingSceneView.position.width;
}
var source = new DisplayAsRenderTexture(m_Settings.m_Width);
var boxedSource = new BoxedSource(source);
boxedSource.m_StageHandlers.Add(ERecordingSessionStage.NewFrameStarting,
(x) =>
{
source.m_DisplayID = m_Settings.m_ScreenID;
source.PrepareNewFrame(session);
});
m_BoxedSources.Add(boxedSource);
}
*/
#endif
// Targetting "Main Camera"
if (m_Settings.m_InputType == EImageSourceType.MainCamera)
{
var source = new CameraAsRenderTexture(EImageSizeMode.Width, m_Settings.m_Width, 0);
var boxedSource = new BoxedSource(source);
boxedSource.m_StageHandlers.Add(ERecordingSessionStage.NewFrameStarting,
(x) =>
{
source.TargetCamera = Camera.main;
source.PrepareNewFrame();
});
m_BoxedSources.Add(boxedSource);
}
// Targetting a "tagged Camera"
if (m_Settings.m_InputType == EImageSourceType.TaggedCamera)
{
var source = new CameraAsRenderTexture(EImageSizeMode.Width, m_Settings.m_Width, 0);
var boxedSource = new BoxedSource(source);
boxedSource.m_StageHandlers.Add(ERecordingSessionStage.NewFrameStarting,
(x) =>
{
var candidates = GameObject.FindGameObjectsWithTag(m_Settings.m_CameraTag);
if (candidates.Length > 0)
{
foreach (var candidate in candidates)
{
var cam = candidate.GetComponent<Camera>();
if (cam != null)
{
source.TargetCamera = cam;
break;
}
}
}
else
{
Debug.LogError("No GameObject found with tag: " + m_Settings.m_CameraTag);
}
source.PrepareNewFrame();
});
m_BoxedSources.Add(boxedSource);
}
return recording = true;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e971ec30698b0bf41bd9afdd5694c8ba
timeCreated: 1491415344
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: d710ed9c46e2cf948ac52d735f4a83f0
folderAsset: yes
timeCreated: 1491415339
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,72 @@
using System;
using UnityEditor;
using UnityEngine.Recorder.FrameRecorder.Utilities;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
namespace UnityEngine.Recorder.FrameRecorder.Timeline
{
public class FrameRecorderClip : PlayableAsset, ITimelineClipAsset
{
[SerializeField] public string m_RecorderTypeName;
[SerializeField] public string m_RecorderCategory;
public FrameRecorderSettings m_Settings;
Type m_RecorderType;
void OnEnable()
{
if (string.IsNullOrEmpty(m_RecorderTypeName))
return;
var assetGuid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(this));
m_Settings = RecordersInventory.CreateRecorderSettings(recorderType, assetGuid, "TmLn-Clip:" + assetGuid);
}
public Type recorderType
{
get
{
if (m_RecorderType == null && !string.IsNullOrEmpty(m_RecorderTypeName))
m_RecorderType = Type.GetType(m_RecorderTypeName);
return m_RecorderType;
}
set
{
if (m_RecorderType != value)
{
m_RecorderType = value;
m_RecorderTypeName = value != null ? m_RecorderType.AssemblyQualifiedName : string.Empty;
}
}
}
public ClipCaps clipCaps
{
get { return ClipCaps.None; }
}
public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
{
var playable = ScriptPlayable<FrameRecorderPlayable>.Create( graph );
var behaviour = playable.GetBehaviour();
if (recorderType != null && UnityHelpers.IsPlaying())
{
behaviour.session = new RecordingSession()
{
m_Recorder = RecordersInventory.InstantiateRecorder(recorderType, m_Settings),
m_RecorderGO = FrameRecorderGOControler.HookupRecorder(m_Settings),
m_RecordingStartTS = Time.time,
m_FrameIndex = 0
};
}
return playable;
}
public virtual void OnDestroy()
{
RecordersInventory.DeleteSettings(m_Settings.m_UniqueID);
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f1e95aa6d658d694785bfde37c857fff
timeCreated: 1491415344
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,85 @@
using System;
using System.Collections;
using UnityEngine.Recorder.FrameRecorder.Utilities;
using UnityEngine.Playables;
namespace UnityEngine.Recorder.FrameRecorder.Timeline
{
/// <summary>
/// Note: Totally ignores the time info comming from the playable infrastructure. Only conciders scaled time.
/// </summary>
public class FrameRecorderPlayable : PlayableBehaviour
{
PlayState m_PlayState = PlayState.Paused;
public RecordingSession session { get; set; }
WaitForEndOfFrameComponent endOfFrameComp;
bool m_FirstOneSkipped;
public override void OnGraphStart(Playable playable)
{
if (session != null)
{
// does not support multiple starts...
session.BeginRecording();
m_PlayState = PlayState.Paused;
}
}
public override void OnGraphStop(Playable playable)
{
if (session != null)
session.EndRecording();
}
public override void PrepareFrame(Playable playable, FrameData info)
{
if (session != null && session.recording)
{
session.m_CurrentFrameStartTS = (Time.time / Time.timeScale) - session.m_RecordingStartTS;
session.PrepareNewFrame();
}
}
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
if (session != null)
{
if (endOfFrameComp == null)
{
endOfFrameComp = session.m_RecorderGO.AddComponent<WaitForEndOfFrameComponent>();
endOfFrameComp.m_playable = this;
}
if (session.recording)
session.m_FrameIndex++;
}
}
public override void OnBehaviourPlay(Playable playable, FrameData info)
{
if (session == null)
return;
// Assumption: OnPlayStateChanged( PlayState.Playing ) ONLY EVER CALLED ONCE for this type of playable.
session.m_RecordingStartTS = Time.time / Time.timeScale;
m_PlayState = PlayState.Playing;
}
public override void OnBehaviourPause(Playable playable, FrameData info)
{
if (session == null)
return;
if (session.recording && m_PlayState == PlayState.Playing)
session.EndRecording();
m_PlayState = PlayState.Paused;
}
public void FrameEnded()
{
if (session != null && session.recording)
session.RecordFrame();
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d580900d83be2664c9c035d6e50791fe
timeCreated: 1491415344
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,12 @@
using UnityEngine.Timeline;
namespace UnityEngine.Recorder.FrameRecorder.Timeline
{
[System.Serializable]
[TrackClipType(typeof(FrameRecorderClip))]
[TrackMediaType(TimelineAsset.MediaType.Script)]
[TrackColor(0.53f, 0.0f, 0.08f)]
public class FrameRecorderTrack : TrackAsset
{
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0e6cf5671577b7344ba25c25b4346ce4
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,25 @@
using System;
using System.Collections;
namespace UnityEngine.Recorder.FrameRecorder.Timeline
{
// the purpose of this class is to signal the FrameRecorderPlayable when frame is done.
[ExecuteInEditMode]
class WaitForEndOfFrameComponent : MonoBehaviour
{
[NonSerialized]
public FrameRecorderPlayable m_playable;
public IEnumerator WaitForEndOfFrame()
{
yield return new WaitForEndOfFrame();
if(m_playable != null)
m_playable.FrameEnded();
}
public void LateUpdate()
{
StartCoroutine(WaitForEndOfFrame());
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: fb0550cc97f23464f99f702c09306f21
timeCreated: 1491590881
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 9706f1322d8993d46b6110692af7e26b
folderAsset: yes
timeCreated: 1491415339
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace UnityEngine.Recorder.FrameRecorder.Utilities
{
public class ClassHelpers
{
public static IEnumerable<KeyValuePair<Type, object[]>> FilterByAttribute<T>(bool inherit = false)
{
var attribType = typeof(T);
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var t in a.GetTypes())
{
var attributes = t.GetCustomAttributes(attribType, inherit);
if (attributes.Length != 0)
yield return new KeyValuePair<Type, object[]>(t, attributes);
}
}
}
public static T GetAttribute<T>(Type type) where T : class
{
var attributes = type.GetCustomAttributes(typeof(T), true);
if (attributes.Length == 0)
return null;
else
return attributes[0] as T;
}
public static T GetAttribute<T>(MethodInfo methofInfo) where T : class
{
var attributes = methofInfo.GetCustomAttributes(typeof(T), true);
if (attributes.Length == 0)
return null;
else
return attributes[0] as T;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: bb4bca9c0585ca14fbd975b3380f946e
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,153 @@
using System;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace UnityEngine.Recorder.FrameRecorder.Utilities
{
public class GameViewWindow
{
public static class LayoutUtility {
private static MethodInfo _miLoadWindowLayout;
private static MethodInfo _miSaveWindowLayout;
private static MethodInfo _miReloadWindowLayoutMenu;
private static bool _available;
private static string _layoutsPath;
static LayoutUtility() {
Type tyWindowLayout = Type.GetType("UnityEditor.WindowLayout,UnityEditor");
Type tyEditorUtility = Type.GetType("UnityEditor.EditorUtility,UnityEditor");
Type tyInternalEditorUtility = Type.GetType("UnityEditorInternal.InternalEditorUtility,UnityEditor");
if (tyWindowLayout != null && tyEditorUtility != null && tyInternalEditorUtility != null) {
MethodInfo miGetLayoutsPath = tyWindowLayout.GetMethod("GetLayoutsPath", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
_miLoadWindowLayout = tyWindowLayout.GetMethod("LoadWindowLayout", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string) }, null);
_miSaveWindowLayout = tyWindowLayout.GetMethod("SaveWindowLayout", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string) }, null);
_miReloadWindowLayoutMenu = tyInternalEditorUtility.GetMethod("ReloadWindowLayoutMenu", BindingFlags.Public | BindingFlags.Static);
if (miGetLayoutsPath == null || _miLoadWindowLayout == null || _miSaveWindowLayout == null || _miReloadWindowLayoutMenu == null)
return;
_layoutsPath = (string)miGetLayoutsPath.Invoke(null, null);
if (string.IsNullOrEmpty(_layoutsPath))
return;
_available = true;
}
}
// Gets a value indicating whether all required Unity API
// functionality is available for usage.
public static bool IsAvailable {
get { return _available; }
}
// Gets absolute path of layouts directory.
// Returns `null` when not available.
public static string LayoutsPath {
get { return _layoutsPath; }
}
// Save current window layout to asset file.
// `assetPath` must be relative to project directory.
public static void SaveLayoutToAsset(string assetPath) {
SaveLayout(Path.Combine(Directory.GetCurrentDirectory(), assetPath));
}
// Load window layout from asset file.
// `assetPath` must be relative to project directory.
public static void LoadLayoutFromAsset(string assetPath) {
if (_miLoadWindowLayout != null) {
string path = Path.Combine(Directory.GetCurrentDirectory(), assetPath);
_miLoadWindowLayout.Invoke(null, new object[] { path });
}
}
// Save current window layout to file.
// `path` must be absolute.
public static void SaveLayout(string path) {
if (_miSaveWindowLayout != null)
_miSaveWindowLayout.Invoke(null, new object[] { path });
}
}
Rect m_OrgPosition;
Vector2 m_OrgSize;
Vector2 m_OrgMaxSize;
EImageSizeMode m_SizeMode = EImageSizeMode.Dynamic;
public Vector2 size { get; private set; }
//The size of the toolbar above the game view, excluding the OS border.
private static int tabHeight = 22;
static EditorWindow GetMainGameView()
{
EditorApplication.ExecuteMenuItem("Window/Game");
System.Type T = System.Type.GetType("UnityEditor.GameView,UnityEditor");
System.Reflection.MethodInfo GetMainGameView = T.GetMethod("GetMainGameView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
System.Object Res = GetMainGameView.Invoke(null, null);
return (EditorWindow)Res;
}
public void FullScreenGameWindow( EImageSizeMode sizeMode, int width, int height )
{
m_SizeMode = sizeMode;
var gameView = GetMainGameView();
m_OrgPosition = gameView.position;
m_OrgSize = gameView.minSize;
m_OrgMaxSize = gameView.maxSize;
switch (sizeMode)
{
case EImageSizeMode.Dynamic:
{
size = new Vector2(gameView.position.width, gameView.position.height);
return;
}
case EImageSizeMode.FullScreen:
{
width = Screen.currentResolution.width;
height = Screen.currentResolution.height;
break;
}
case EImageSizeMode.Width:
{
height = (int)((height / (double)Screen.currentResolution.width) * width);
break;
}
case EImageSizeMode.Custom:
break;
}
var newPos = new Rect(0, 0 - tabHeight, Screen.currentResolution.width, Screen.currentResolution.height + tabHeight);
gameView.position = newPos;
size = new Vector2(width, height);
gameView.minSize = size = new Vector2(width, height + tabHeight);;
gameView.maxSize = gameView.minSize;
gameView.position = newPos;
}
public void RestoreGameWindow()
{
if (m_SizeMode != EImageSizeMode.Dynamic)
{
var gameView = GetMainGameView();
gameView.Close();
gameView = GetMainGameView();
gameView.minSize = m_OrgSize;
gameView.maxSize = m_OrgMaxSize;
gameView.position = m_OrgPosition;
}
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1f428d7759a94b145b1aa0a53a11071f
timeCreated: 1493926581
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace UnityEngine.Recorder.FrameRecorder.Utilities
{
public static class RecordersCache
{
class CachedRecorder
{
public Type type { get; set; }
public string category { get; set; }
}
static List<RecorderInfo> m_RecordersCache;
static void Init()
{
if (m_RecordersCache == null)
{
m_RecordersCache = RecordersInventory.recorders
.OrderBy((x) => x.Key)
.Select((x) => x.Value)
.ToList();
}
}
public static int GroupedIndexOfRecorder(Type recorder, string category)
{
Init();
var skipped = 0;
var any = false;
for (var i = 0; i < m_RecordersCache.Count; i++)
{
if (string.Compare(category, m_RecordersCache[i].category, StringComparison.InvariantCultureIgnoreCase) == 0)
skipped++;
else if (m_RecordersCache[i].recorder == recorder)
return i - skipped;
else
any = true;
}
if (any)
return 0;
else
return -1;
}
public static Type RecorderFromGroupedIndex(int index, string category)
{
Init();
var filteredIndex = 0;
foreach (var t in m_RecordersCache)
{
if (string.Compare(category, t.category, StringComparison.InvariantCultureIgnoreCase) != 0)
continue;
if (index == filteredIndex)
return t.recorder;
filteredIndex++;
}
return null;
}
public static string[] GetNameOfRecordersInGroup(string category)
{
Init();
// count them
int count = 0;
foreach (var item in m_RecordersCache)
if (string.Compare(category, item.category, StringComparison.InvariantCultureIgnoreCase) == 0)
count++;
// store them
var result = new string[count];
if (count > 0)
{
count = 0;
foreach (var item in m_RecordersCache)
if (string.Compare(category, item.category, StringComparison.InvariantCultureIgnoreCase) == 0)
result[count++] = item.recorder.FullName;
}
return result;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9ea1d95d7f0add84091f7807bcbd2d82
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,31 @@
using Object = UnityEngine.Object;
namespace UnityEngine.Recorder.FrameRecorder.Utilities
{
public static class UnityHelpers
{
public static void Destroy(Object obj)
{
if (obj == null)
return;
#if UNITY_EDITOR
if (UnityEditor.EditorApplication.isPlaying)
Object.Destroy(obj);
else
Object.DestroyImmediate(obj);
#else
Object.Destroy(m_HostGO);
#endif
obj = null;
}
public static bool IsPlaying()
{
#if UNITY_EDITOR
return UnityEditor.EditorApplication.isPlaying;
#else
return true;
#endif
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 639bab1152ec3984184d25ab38abd226
timeCreated: 1491415343
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: a843bc4482baa5846971389324919dad
folderAsset: yes
timeCreated: 1491415339
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: d55140aa4996ef248b1e815274e1c193
folderAsset: yes
timeCreated: 1491415339
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,205 @@
Shader "Unity/FrameRecorder/TestGrabberShader" {
Properties{
}
CGINCLUDE
#include "UnityCG.cginc"
#pragma multi_compile ___ UNITY_HDR_ON
#pragma multi_compile ___ OFFSCREEN
sampler2D _TmpFrameBuffer;
sampler2D _CameraGBufferTexture0;
sampler2D _CameraGBufferTexture1;
sampler2D _CameraGBufferTexture2;
sampler2D _CameraGBufferTexture3;
sampler2D_float _CameraDepthTexture;
sampler2D _TmpRenderTarget;
struct v2f
{
float4 pos : POSITION;
float4 spos : TEXCOORD0;
};
v2f vert(appdata_img v)
{
v2f o;
o.pos = o.spos = v.vertex;
return o;
}
float2 get_texcoord(v2f i)
{
float2 t = i.spos.xy * 0.5 + 0.5;
return t;
}
float2 get_texcoord_gb(v2f i)
{
float2 t = i.spos.xy * 0.5 + 0.5;
#if !defined(UNITY_UV_STARTS_AT_TOP)
t.y = 1.0 - t.y;
#endif
return t;
}
half4 copy_framebuffer(v2f I) : SV_Target
{
float2 t = get_texcoord(I);
#if !defined(OFFSCREEN) || !defined(UNITY_UV_STARTS_AT_TOP)
t.y = 1.0 - t.y;
#endif
half4 O = tex2D(_TmpFrameBuffer, t);
O.a = 1.0;
return O;
}
// g-buffer
struct gbuffer_out
{
half4 diffuse : SV_Target0; // RT0: diffuse color (rgb), occlusion (a)
half4 spec_smoothness : SV_Target1; // RT1: spec color (rgb), smoothness (a)
half4 normal : SV_Target2; // RT2: normal (rgb), --unused, very low precision-- (a)
half4 emission : SV_Target3; // RT3: emission (rgb), --unused-- (a)
};
gbuffer_out copy_gbuffer(v2f I)
{
float2 t = get_texcoord_gb(I);
gbuffer_out O;
O.diffuse = tex2D(_CameraGBufferTexture0, t);
O.spec_smoothness = tex2D(_CameraGBufferTexture1, t);
O.normal = tex2D(_CameraGBufferTexture2, t);
O.emission = tex2D(_CameraGBufferTexture3, t);
#ifndef UNITY_HDR_ON
O.emission.rgb = -log2(O.emission.rgb);
#endif
return O;
}
// depth
float4 copy_depth(v2f I) : SV_Target
{
float4 O = tex2D(_CameraDepthTexture, get_texcoord_gb(I)).rrrr;
return O;
}
// render target (for offscreen-recorder)
half4 copy_rendertarget(v2f I) : SV_Target
{
half4 O = tex2D(_TmpRenderTarget, get_texcoord_gb(I));
return O;
}
// albedo, occlusion, specular, smoothness
struct aoss_out
{
half4 albedo : SV_Target0;
half4 occlusion : SV_Target1;
half4 specular : SV_Target2;
half4 smoothness : SV_Target3;
};
aoss_out copy_aoss(v2f I)
{
float2 t = get_texcoord_gb(I);
half4 ao = tex2D(_CameraGBufferTexture0, t);
half4 ss = tex2D(_CameraGBufferTexture1, t);
aoss_out O;
O.albedo = half4(ao.rgb, 1.0);
O.occlusion = ao.aaaa;
O.specular = half4(ss.rgb, 1.0);
O.smoothness = ss.aaaa;
return O;
}
// normal, emission, depth
struct ned_out
{
half4 normal : SV_Target0;
half4 emission : SV_Target1;
half4 depth : SV_Target2;
};
ned_out copy_ned(v2f I)
{
float2 t = get_texcoord_gb(I);
half4 normal = tex2D(_CameraGBufferTexture2, t);
half4 emission = tex2D(_CameraGBufferTexture3, t);
half4 depth = tex2D(_CameraDepthTexture, get_texcoord_gb(I));
ned_out O;
O.normal = half4(normal.rgb, 1.0);
O.emission = half4(emission.rgb, 1.0);
#ifndef UNITY_HDR_ON
O.emission.rgb = -log2(O.emission.rgb);
#endif
O.depth = depth.rrrr;
return O;
}
ENDCG
Subshader{
// Pass 0: framebuffer
Pass{
Blend Off Cull Off ZTest Off ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment copy_framebuffer
ENDCG
}
// Pass 1: g-buffer
Pass{
Blend Off Cull Off ZTest Off ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment copy_gbuffer
ENDCG
}
// Pass 2: depth
Pass{
Blend Off Cull Off ZTest Off ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment copy_depth
ENDCG
}
// Pass 3: render target
Pass{
Blend Off Cull Off ZTest Off ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment copy_rendertarget
ENDCG
}
// Pass 4: albedo, occlusion, specular, smoothness
Pass{
Blend Off Cull Off ZTest Off ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment copy_aoss
ENDCG
}
// Pass 5: normal, emission, depth
Pass{
Blend Off Cull Off ZTest Off ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment copy_ned
ENDCG
}
}
Fallback off
}

Просмотреть файл

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 55d39f733f4029f4cbc92b5c2279e15b
timeCreated: 1491415345
licenseType: Free
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant: