You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
297 lines
8.5 KiB
297 lines
8.5 KiB
5 years ago
|
using System;
|
||
|
using System.Collections;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Rendering;
|
||
|
#if UNITY_EDITOR
|
||
|
using UnityEditor;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
namespace UTJ.FrameCapturer
|
||
|
{
|
||
|
[ExecuteInEditMode]
|
||
|
public abstract class RecorderBase : MonoBehaviour
|
||
|
{
|
||
|
public enum ResolutionUnit
|
||
|
{
|
||
|
Percent,
|
||
|
Pixels,
|
||
|
}
|
||
|
|
||
|
public enum FrameRateMode
|
||
|
{
|
||
|
Variable,
|
||
|
Constant,
|
||
|
}
|
||
|
|
||
|
public enum CaptureControl
|
||
|
{
|
||
|
Manual,
|
||
|
FrameRange,
|
||
|
TimeRange,
|
||
|
}
|
||
|
|
||
|
|
||
|
[SerializeField] protected DataPath m_outputDir = new DataPath(DataPath.Root.Current, "Capture");
|
||
|
|
||
|
[SerializeField] protected ResolutionUnit m_resolution = ResolutionUnit.Percent;
|
||
|
[SerializeField] [Range(1,100)] protected int m_resolutionPercent = 100;
|
||
|
[SerializeField] protected int m_resolutionWidth = 1920;
|
||
|
|
||
|
[SerializeField] protected FrameRateMode m_framerateMode = FrameRateMode.Constant;
|
||
|
[SerializeField] protected int m_targetFramerate = 30;
|
||
|
[SerializeField] protected bool m_fixDeltaTime = true;
|
||
|
[SerializeField] protected bool m_waitDeltaTime = true;
|
||
|
[SerializeField] [Range(1,10)]protected int m_captureEveryNthFrame = 1;
|
||
|
|
||
|
[SerializeField] protected CaptureControl m_captureControl = CaptureControl.FrameRange;
|
||
|
[SerializeField] protected int m_startFrame = 0;
|
||
|
[SerializeField] protected int m_endFrame = 100;
|
||
|
[SerializeField] protected float m_startTime = 0.0f;
|
||
|
[SerializeField] protected float m_endTime = 10.0f;
|
||
|
|
||
|
protected bool m_recording = false;
|
||
|
protected bool m_aborted = false;
|
||
|
protected int m_initialFrame = 0;
|
||
|
protected float m_initialTime = 0.0f;
|
||
|
protected float m_initialRealTime = 0.0f;
|
||
|
protected int m_frame = 0;
|
||
|
protected int m_recordedFrames = 0;
|
||
|
protected int m_recordedSamples = 0;
|
||
|
#if UNITY_EDITOR
|
||
|
[SerializeField] bool m_recordOnStart = false;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
public DataPath outputDir
|
||
|
{
|
||
|
get { return m_outputDir; }
|
||
|
set { m_outputDir = value; }
|
||
|
}
|
||
|
|
||
|
public ResolutionUnit resolutionUnit
|
||
|
{
|
||
|
get { return m_resolution; }
|
||
|
set { m_resolution = value; }
|
||
|
}
|
||
|
public int resolutionPercent
|
||
|
{
|
||
|
get { return m_resolutionPercent; }
|
||
|
set { m_resolutionPercent = value; }
|
||
|
}
|
||
|
public int resolutionWidth
|
||
|
{
|
||
|
get { return m_resolutionWidth; }
|
||
|
set { m_resolutionWidth = value; }
|
||
|
}
|
||
|
|
||
|
public FrameRateMode framerateMode
|
||
|
{
|
||
|
get { return m_framerateMode; }
|
||
|
set { m_framerateMode = value; }
|
||
|
}
|
||
|
public int targetFramerate
|
||
|
{
|
||
|
get { return m_targetFramerate; }
|
||
|
set { m_targetFramerate = value; }
|
||
|
}
|
||
|
public bool fixDeltaTime
|
||
|
{
|
||
|
get { return m_fixDeltaTime; }
|
||
|
set { m_fixDeltaTime = value; }
|
||
|
}
|
||
|
public bool waitDeltaTime
|
||
|
{
|
||
|
get { return m_waitDeltaTime; }
|
||
|
set { m_waitDeltaTime = value; }
|
||
|
}
|
||
|
public int captureEveryNthFrame
|
||
|
{
|
||
|
get { return m_captureEveryNthFrame; }
|
||
|
set { m_captureEveryNthFrame = value; }
|
||
|
}
|
||
|
|
||
|
public CaptureControl captureControl
|
||
|
{
|
||
|
get { return m_captureControl; }
|
||
|
set { m_captureControl = value; }
|
||
|
}
|
||
|
public int startFrame
|
||
|
{
|
||
|
get { return m_startFrame; }
|
||
|
set { m_startFrame = value; }
|
||
|
}
|
||
|
public int endFrame
|
||
|
{
|
||
|
get { return m_endFrame; }
|
||
|
set { m_endFrame = value; }
|
||
|
}
|
||
|
public float startTime
|
||
|
{
|
||
|
get { return m_startTime; }
|
||
|
set { m_startTime = value; }
|
||
|
}
|
||
|
public float endTime
|
||
|
{
|
||
|
get { return m_endTime; }
|
||
|
set { m_endTime = value; }
|
||
|
}
|
||
|
public bool isRecording
|
||
|
{
|
||
|
get { return m_recording; }
|
||
|
set {
|
||
|
if (value) { BeginRecording(); }
|
||
|
else { EndRecording(); }
|
||
|
}
|
||
|
}
|
||
|
#if UNITY_EDITOR
|
||
|
public bool recordOnStart { set { m_recordOnStart = value; } }
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
public virtual bool BeginRecording()
|
||
|
{
|
||
|
if(m_recording) { return false; }
|
||
|
|
||
|
// delta time control
|
||
|
if (m_framerateMode == FrameRateMode.Constant && m_fixDeltaTime)
|
||
|
{
|
||
|
Time.maximumDeltaTime = (1.0f / m_targetFramerate);
|
||
|
if (!m_waitDeltaTime)
|
||
|
{
|
||
|
Time.captureFramerate = m_targetFramerate;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_initialFrame = Time.renderedFrameCount;
|
||
|
m_initialTime = Time.unscaledTime;
|
||
|
m_initialRealTime = Time.realtimeSinceStartup;
|
||
|
m_recordedFrames = 0;
|
||
|
m_recordedSamples = 0;
|
||
|
m_recording = true;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public virtual void EndRecording()
|
||
|
{
|
||
|
if (!m_recording) { return; }
|
||
|
|
||
|
if (m_framerateMode == FrameRateMode.Constant && m_fixDeltaTime)
|
||
|
{
|
||
|
if (!m_waitDeltaTime)
|
||
|
{
|
||
|
Time.captureFramerate = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_recording = false;
|
||
|
m_aborted = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
protected void GetCaptureResolution(ref int w, ref int h)
|
||
|
{
|
||
|
if(m_resolution == ResolutionUnit.Percent)
|
||
|
{
|
||
|
float scale = m_resolutionPercent * 0.01f;
|
||
|
w = (int)(w * scale);
|
||
|
h = (int)(h * scale);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
float aspect = (float)h / w;
|
||
|
w = m_resolutionWidth;
|
||
|
h = (int)(m_resolutionWidth * aspect);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected IEnumerator Wait()
|
||
|
{
|
||
|
yield return new WaitForEndOfFrame();
|
||
|
|
||
|
float wt = (1.0f / m_targetFramerate) * (Time.renderedFrameCount - m_initialFrame);
|
||
|
while (Time.realtimeSinceStartup - m_initialRealTime < wt)
|
||
|
{
|
||
|
System.Threading.Thread.Sleep(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if UNITY_EDITOR
|
||
|
protected virtual void OnValidate()
|
||
|
{
|
||
|
m_targetFramerate = Mathf.Max(1, m_targetFramerate);
|
||
|
m_startFrame = Mathf.Max(0, m_startFrame);
|
||
|
m_endFrame = Mathf.Max(m_startFrame, m_endFrame);
|
||
|
m_startTime = Mathf.Max(0.0f, m_startTime);
|
||
|
m_endTime = Mathf.Max(m_startTime, m_endTime);
|
||
|
}
|
||
|
#endif // UNITY_EDITOR
|
||
|
|
||
|
protected virtual void Start()
|
||
|
{
|
||
|
#if UNITY_EDITOR
|
||
|
if (EditorApplication.isPlaying && m_recordOnStart)
|
||
|
{
|
||
|
BeginRecording();
|
||
|
}
|
||
|
m_recordOnStart = false;
|
||
|
#endif
|
||
|
m_initialFrame = Time.renderedFrameCount;
|
||
|
m_initialTime = Time.unscaledTime;
|
||
|
m_initialRealTime = Time.realtimeSinceStartup;
|
||
|
}
|
||
|
|
||
|
protected virtual void OnDisable()
|
||
|
{
|
||
|
#if UNITY_EDITOR
|
||
|
if (EditorApplication.isPlaying)
|
||
|
#endif
|
||
|
{
|
||
|
EndRecording();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected virtual void Update()
|
||
|
{
|
||
|
#if UNITY_EDITOR
|
||
|
if (EditorApplication.isPlaying)
|
||
|
#endif
|
||
|
{
|
||
|
if (m_captureControl == CaptureControl.FrameRange)
|
||
|
{
|
||
|
if (!m_aborted && m_frame >= m_startFrame && m_frame <= m_endFrame)
|
||
|
{
|
||
|
if (!m_recording) { BeginRecording(); }
|
||
|
}
|
||
|
else if (m_recording)
|
||
|
{
|
||
|
EndRecording();
|
||
|
}
|
||
|
}
|
||
|
else if (m_captureControl == CaptureControl.TimeRange)
|
||
|
{
|
||
|
float time = Time.unscaledTime - m_initialTime;
|
||
|
if (!m_aborted && time >= m_startTime && time <= m_endTime)
|
||
|
{
|
||
|
if (!m_recording) { BeginRecording(); }
|
||
|
}
|
||
|
else if (m_recording)
|
||
|
{
|
||
|
EndRecording();
|
||
|
}
|
||
|
}
|
||
|
else if (m_captureControl == CaptureControl.Manual)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
if(m_framerateMode == FrameRateMode.Constant && m_fixDeltaTime && m_waitDeltaTime)
|
||
|
{
|
||
|
StartCoroutine(Wait());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|