开始开发
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cbd5e8cde9a31f840984899768932e65
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: MatVideo
|
||||
m_Shader: {fileID: 10752, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7e7287421125684092160210210c506
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,91 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: YUVTexture
|
||||
m_Shader: {fileID: 4800000, guid: 00d866b188488114283719ad682ee1a3, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _UTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _VTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bbd448ddc4cd0cb42a5f809e967a4477
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
Shader "Unlit/YUVTransRGB"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex("Texture", 2D) = "black" {}
|
||||
_UTex("U", 2D) = "black" {}
|
||||
_VTex("V", 2D) = "black" {}
|
||||
}
|
||||
SubShader
|
||||
{
|
||||
Tags { "RenderType" = "Opaque" }
|
||||
LOD 100
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct appdata
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float2 uv : TEXCOORD0;
|
||||
UNITY_FOG_COORDS(1)
|
||||
float4 vertex : SV_POSITION;
|
||||
};
|
||||
|
||||
sampler2D _MainTex;
|
||||
sampler2D _UTex;
|
||||
sampler2D _VTex;
|
||||
float4 _MainTex_ST;
|
||||
|
||||
v2f vert(appdata v)
|
||||
{
|
||||
v2f o;
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
|
||||
return o;
|
||||
}
|
||||
|
||||
fixed4 frag(v2f i) : SV_Target
|
||||
{
|
||||
fixed2 uv = fixed2(i.uv.x, i.uv.y);
|
||||
fixed4 ycol = tex2D(_MainTex, uv);
|
||||
fixed4 ucol = tex2D(_UTex, uv);
|
||||
fixed4 vcol = tex2D(_VTex, uv);
|
||||
|
||||
float r = ycol.a + 1.4022 * vcol.a - 0.7011;
|
||||
float g = ycol.a - 0.3456 * ucol.a - 0.7145 * vcol.a + 0.53005;
|
||||
float b = ycol.a + 1.771 * ucol.a - 0.8855;
|
||||
|
||||
fixed4 col = fixed4(b, g, r, 1);
|
||||
col.rgb = GammaToLinearSpace(col.rgb);
|
||||
return col;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00d866b188488114283719ad682ee1a3
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d86868521ba3954d99c23196bc13949
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17a0cbb09e9a6644f933eb06e9fdd525
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,154 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Unity.XR.XREAL.Samples
|
||||
{
|
||||
public enum ButtonState
|
||||
{
|
||||
Normal,
|
||||
Pressed,
|
||||
Hovered,
|
||||
Disabled
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class listens to button state changes and updates the text color accordingly.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Button))]
|
||||
public class ButtonTextColor : MonoBehaviour
|
||||
{
|
||||
private Text buttonText;
|
||||
private Button button;
|
||||
[SerializeField]
|
||||
private Color TextNormalColor;
|
||||
[SerializeField]
|
||||
private Color TextPressColor;
|
||||
[SerializeField]
|
||||
private Color TextHoverColor;
|
||||
[SerializeField]
|
||||
private Color TextDisableColor;
|
||||
|
||||
private ButtonStateListener buttonStateListener;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
button = GetComponent<Button>();
|
||||
if (button != null)
|
||||
{
|
||||
buttonStateListener = button.AddOrGetComponent<ButtonStateListener>();
|
||||
buttonStateListener.onButtonStateChanged += HandleButtonStateChange;
|
||||
}
|
||||
if (buttonText == null)
|
||||
{
|
||||
for (var i = 0; i < transform.childCount; ++i)
|
||||
{
|
||||
var text = transform.GetChild(i).GetComponent<Text>();
|
||||
if (text != null)
|
||||
{
|
||||
buttonText = text;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void HandleButtonStateChange(ButtonState state)
|
||||
{
|
||||
if (buttonText != null)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case ButtonState.Normal:
|
||||
buttonText.color = TextNormalColor;
|
||||
break;
|
||||
case ButtonState.Pressed:
|
||||
buttonText.color = TextPressColor;
|
||||
break;
|
||||
case ButtonState.Hovered:
|
||||
buttonText.color = TextHoverColor;
|
||||
break;
|
||||
case ButtonState.Disabled:
|
||||
buttonText.color = TextDisableColor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
buttonStateListener.onButtonStateChanged -= HandleButtonStateChange;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Listens to pointer events to determine the state of a button.
|
||||
/// </summary>
|
||||
[HideInInspector]
|
||||
public class ButtonStateListener : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler
|
||||
{
|
||||
public delegate void OnButtonStateChanged(ButtonState buttonState);
|
||||
|
||||
/// <summary>
|
||||
/// Event triggered when the button state changes.
|
||||
/// </summary>
|
||||
public event OnButtonStateChanged onButtonStateChanged;
|
||||
|
||||
private Button button;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
button = GetComponent<Button>();
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
UpdateState(button.interactable ? ButtonState.Normal : ButtonState.Disabled);
|
||||
}
|
||||
|
||||
public void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
if (button.interactable)
|
||||
{
|
||||
UpdateState(ButtonState.Hovered);
|
||||
Debug.Log("Button Highlighted (Pointer Enter)");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
if (button.interactable)
|
||||
{
|
||||
UpdateState(ButtonState.Normal);
|
||||
Debug.Log("Button Normal (Pointer Exit)");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (button.interactable)
|
||||
{
|
||||
UpdateState(ButtonState.Pressed);
|
||||
Debug.Log("Button Pressed (Pointer Down)");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
if (button.interactable)
|
||||
{
|
||||
UpdateState(ButtonState.Normal);
|
||||
Debug.Log("Button Released (Pointer Up)");
|
||||
}
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
UpdateState(ButtonState.Disabled);
|
||||
}
|
||||
|
||||
private void UpdateState(ButtonState newState)
|
||||
{
|
||||
onButtonStateChanged?.Invoke(newState);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 371b427884fde244a8e036ef34091480
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,593 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Unity.XR.XREAL.Samples
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
using GalleryDataProvider = NativeGalleryDataProvider;
|
||||
#else
|
||||
using GalleryDataProvider = MockGalleryDataProvider;
|
||||
#endif
|
||||
public class CaptureExample : MonoBehaviour
|
||||
{
|
||||
public enum ResolutionLevel
|
||||
{
|
||||
High,
|
||||
Middle,
|
||||
Low,
|
||||
}
|
||||
[SerializeField] private Button m_VideoButton;
|
||||
[SerializeField] private Button m_PhotoButton;
|
||||
|
||||
[SerializeField] private Slider m_SliderMic;
|
||||
[SerializeField] private Text m_TextMic;
|
||||
[SerializeField] private Slider m_SliderApp;
|
||||
[SerializeField] private Text m_TextApp;
|
||||
|
||||
[SerializeField] private Dropdown m_QualityDropDown;
|
||||
[SerializeField] private Dropdown m_RenderModeDropDown;
|
||||
[SerializeField] private Dropdown m_AudioStateDropDown;
|
||||
[SerializeField] private Dropdown m_CaptureSideDropDown;
|
||||
[SerializeField] private Toggle m_UseGreenBGToggle;
|
||||
|
||||
[SerializeField] private RawImage m_PreviewRawImage;
|
||||
|
||||
List<string> _ResolutionOptions = new List<string>() {
|
||||
ResolutionLevel.High.ToString(),
|
||||
ResolutionLevel.Middle.ToString(),
|
||||
ResolutionLevel.Low.ToString()
|
||||
};
|
||||
List<string> _RendermodeOptions = new List<string>() {
|
||||
BlendMode.Blend.ToString(),
|
||||
BlendMode.CameraOnly.ToString(),
|
||||
BlendMode.VirtualOnly.ToString()
|
||||
};
|
||||
List<string> _AudioStateOptions = new List<string>() {
|
||||
AudioState.MicAudio.ToString(),
|
||||
AudioState.ApplicationAudio.ToString(),
|
||||
AudioState.ApplicationAndMicAudio.ToString(),
|
||||
AudioState.None.ToString()
|
||||
};
|
||||
List<string> _CaptureSideOptions = new List<string>() {
|
||||
CaptureSide.Single.ToString(),
|
||||
CaptureSide.Both.ToString()
|
||||
};
|
||||
|
||||
public BlendMode blendMode = BlendMode.Blend;
|
||||
public ResolutionLevel resolutionLevel = ResolutionLevel.High;
|
||||
public AudioState audioState = AudioState.ApplicationAudio;
|
||||
public CaptureSide captureside = CaptureSide.Single;
|
||||
public bool useGreenBackGround = false;
|
||||
|
||||
/// <summary> Save the video to Application.persistentDataPath. </summary>
|
||||
/// <value> The full pathname of the video save file. </value>
|
||||
public string VideoSavePath
|
||||
{
|
||||
get
|
||||
{
|
||||
string timeStamp = Time.time.ToString().Replace(".", "").Replace(":", "");
|
||||
string filename = string.Format("Xreal_Record_{0}.mp4", timeStamp);
|
||||
return Path.Combine(Application.persistentDataPath, filename);
|
||||
}
|
||||
}
|
||||
|
||||
GalleryDataProvider galleryDataTool;
|
||||
|
||||
/// <summary> The video capture. </summary>
|
||||
XREALVideoCapture m_VideoCapture = null;
|
||||
|
||||
/// <summary> The photo capture object. </summary>
|
||||
private XREALPhotoCapture m_PhotoCapture;
|
||||
/// <summary> The camera resolution. </summary>
|
||||
private Resolution m_CameraResolution;
|
||||
private bool isOnPhotoProcess = false;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
m_QualityDropDown.options.Clear();
|
||||
m_QualityDropDown.AddOptions(_ResolutionOptions);
|
||||
int default_quality_index = 0;
|
||||
for (int i = 0; i < _ResolutionOptions.Count; i++)
|
||||
{
|
||||
if (_ResolutionOptions[i].Equals(resolutionLevel.ToString()))
|
||||
{
|
||||
default_quality_index = i;
|
||||
}
|
||||
}
|
||||
m_QualityDropDown.value = default_quality_index;
|
||||
m_QualityDropDown.onValueChanged.AddListener((index) =>
|
||||
{
|
||||
Enum.TryParse<ResolutionLevel>(_ResolutionOptions[index],
|
||||
out resolutionLevel);
|
||||
});
|
||||
|
||||
m_RenderModeDropDown.options.Clear();
|
||||
m_RenderModeDropDown.AddOptions(_RendermodeOptions);
|
||||
int default_blendmode_index = 0;
|
||||
for (int i = 0; i < _RendermodeOptions.Count; i++)
|
||||
{
|
||||
if (_RendermodeOptions[i].Equals(blendMode.ToString()))
|
||||
{
|
||||
default_blendmode_index = i;
|
||||
}
|
||||
}
|
||||
m_RenderModeDropDown.value = default_blendmode_index;
|
||||
m_RenderModeDropDown.onValueChanged.AddListener((index) =>
|
||||
{
|
||||
Enum.TryParse<BlendMode>(_RendermodeOptions[index],
|
||||
out blendMode);
|
||||
});
|
||||
|
||||
m_AudioStateDropDown.options.Clear();
|
||||
m_AudioStateDropDown.AddOptions(_AudioStateOptions);
|
||||
int default_audiostate_index = 0;
|
||||
for (int i = 0; i < _AudioStateOptions.Count; i++)
|
||||
{
|
||||
if (_AudioStateOptions[i].Equals(audioState.ToString()))
|
||||
{
|
||||
default_audiostate_index = i;
|
||||
}
|
||||
}
|
||||
m_AudioStateDropDown.value = default_audiostate_index;
|
||||
m_AudioStateDropDown.onValueChanged.AddListener((index) =>
|
||||
{
|
||||
Enum.TryParse<AudioState>(_AudioStateOptions[index],
|
||||
out audioState);
|
||||
});
|
||||
|
||||
m_CaptureSideDropDown.options.Clear();
|
||||
m_CaptureSideDropDown.AddOptions(_CaptureSideOptions);
|
||||
int default_captureside_index = 0;
|
||||
for (int i = 0; i < _CaptureSideOptions.Count; i++)
|
||||
{
|
||||
if (_CaptureSideOptions[i].Equals(captureside.ToString()))
|
||||
{
|
||||
default_captureside_index = i;
|
||||
}
|
||||
}
|
||||
m_CaptureSideDropDown.value = default_captureside_index;
|
||||
m_CaptureSideDropDown.onValueChanged.AddListener((index) =>
|
||||
{
|
||||
Enum.TryParse<CaptureSide>(_CaptureSideOptions[index],
|
||||
out captureside);
|
||||
});
|
||||
|
||||
m_UseGreenBGToggle.isOn = useGreenBackGround;
|
||||
m_UseGreenBGToggle.onValueChanged.AddListener((val) =>
|
||||
{
|
||||
useGreenBackGround = val;
|
||||
});
|
||||
|
||||
if (m_SliderMic != null)
|
||||
{
|
||||
m_SliderMic.maxValue = 5.0f;
|
||||
m_SliderMic.minValue = 0.1f;
|
||||
m_SliderMic.value = 1;
|
||||
m_SliderMic.onValueChanged.AddListener(OnSlideMicValueChange);
|
||||
}
|
||||
|
||||
if (m_SliderApp != null)
|
||||
{
|
||||
m_SliderApp.maxValue = 5.0f;
|
||||
m_SliderApp.minValue = 0.1f;
|
||||
m_SliderApp.value = 1;
|
||||
m_SliderApp.onValueChanged.AddListener(OnSlideAppValueChange);
|
||||
}
|
||||
|
||||
m_VideoButton.onClick.AddListener(RecordVideo);
|
||||
m_PhotoButton.onClick.AddListener(TakeAPhoto);
|
||||
|
||||
RefreshUIState();
|
||||
}
|
||||
|
||||
void OnSlideMicValueChange(float val)
|
||||
{
|
||||
if (m_VideoCapture != null)
|
||||
{
|
||||
VideoEncoder encoder = m_VideoCapture.GetContext().GetEncoder() as VideoEncoder;
|
||||
if (encoder != null)
|
||||
encoder.AdjustVolume(RecorderIndex.REC_MIC, val);
|
||||
}
|
||||
RefreshUIState();
|
||||
}
|
||||
|
||||
void OnSlideAppValueChange(float val)
|
||||
{
|
||||
if (m_VideoCapture != null)
|
||||
{
|
||||
VideoEncoder encoder = m_VideoCapture.GetContext().GetEncoder() as VideoEncoder;
|
||||
if (encoder != null)
|
||||
encoder.AdjustVolume(RecorderIndex.REC_APP, val);
|
||||
}
|
||||
RefreshUIState();
|
||||
}
|
||||
|
||||
void CreateVideoCapture(Action callback)
|
||||
{
|
||||
XREALVideoCaptureUtility.CreateAsync(false, delegate (XREALVideoCapture videoCapture)
|
||||
{
|
||||
Debug.Log("Created VideoCapture Instance!");
|
||||
if (videoCapture != null)
|
||||
{
|
||||
m_VideoCapture = videoCapture;
|
||||
callback?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to create VideoCapture Instance!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void RecordVideo()
|
||||
{
|
||||
if (m_VideoCapture == null)
|
||||
{
|
||||
CreateVideoCapture(() =>
|
||||
{
|
||||
StartVideoCapture();
|
||||
});
|
||||
}
|
||||
else if (m_VideoCapture.IsRecording)
|
||||
{
|
||||
this.StopVideoCapture();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.StartVideoCapture();
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshUIState()
|
||||
{
|
||||
var recordText = m_VideoButton.transform.Find("Text");
|
||||
if (recordText)
|
||||
{
|
||||
bool notStarted = m_VideoCapture == null || !m_VideoCapture.IsRecording;
|
||||
recordText.GetComponent<Text>().text = notStarted ? "Start Record" : "Stop Record";
|
||||
}
|
||||
|
||||
if (m_TextMic != null && m_SliderMic != null)
|
||||
m_TextMic.text = m_SliderMic.value.ToString("F1");
|
||||
if (m_TextApp != null && m_SliderApp != null)
|
||||
m_TextApp.text = m_SliderApp.value.ToString("F1");
|
||||
}
|
||||
|
||||
/// <summary> Starts video capture. </summary>
|
||||
public void StartVideoCapture()
|
||||
{
|
||||
if (m_VideoCapture == null || m_VideoCapture.IsRecording)
|
||||
{
|
||||
Debug.LogWarning("Can not start video capture!");
|
||||
return;
|
||||
}
|
||||
|
||||
CameraParameters cameraParameters = new CameraParameters();
|
||||
Resolution cameraResolution = GetResolutionByLevel(resolutionLevel);
|
||||
cameraParameters.cameraType = CameraType.RGB;
|
||||
cameraParameters.hologramOpacity = 0.0f;
|
||||
cameraParameters.frameRate = NativeConstants.RECORD_FPS_DEFAULT;
|
||||
cameraParameters.cameraResolutionWidth = cameraResolution.width;
|
||||
cameraParameters.cameraResolutionHeight = cameraResolution.height;
|
||||
cameraParameters.pixelFormat = CapturePixelFormat.PNG;
|
||||
cameraParameters.blendMode = blendMode;
|
||||
// Set audio state, audio record needs the permission of "android.permission.RECORD_AUDIO",
|
||||
// Add it to your "AndroidManifest.xml" file in "Assets/Plugin".
|
||||
cameraParameters.audioState = audioState;
|
||||
cameraParameters.captureSide = captureside;
|
||||
cameraParameters.backgroundColor = useGreenBackGround ? Color.green : Color.black;
|
||||
|
||||
m_VideoCapture.StartVideoModeAsync(cameraParameters, OnStartedVideoCaptureMode, true);
|
||||
}
|
||||
|
||||
private Resolution GetResolutionByLevel(ResolutionLevel level)
|
||||
{
|
||||
var resolutions = XREALVideoCaptureUtility.SupportedResolutions.OrderByDescending((res) => res.width * res.height);
|
||||
Resolution resolution = new Resolution();
|
||||
switch (level)
|
||||
{
|
||||
case ResolutionLevel.High:
|
||||
resolution = resolutions.ElementAt(0);
|
||||
break;
|
||||
case ResolutionLevel.Middle:
|
||||
resolution = resolutions.ElementAt(1);
|
||||
break;
|
||||
case ResolutionLevel.Low:
|
||||
resolution = resolutions.ElementAt(2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return resolution;
|
||||
}
|
||||
|
||||
/// <summary> Stops video capture. </summary>
|
||||
public void StopVideoCapture()
|
||||
{
|
||||
if (m_VideoCapture == null || !m_VideoCapture.IsRecording)
|
||||
{
|
||||
Debug.LogWarning("Can not stop video capture!");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("Stop Video Capture!");
|
||||
m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
|
||||
}
|
||||
|
||||
/// <summary> Executes the 'started video capture mode' action. </summary>
|
||||
/// <param name="result"> The result.</param>
|
||||
void OnStartedVideoCaptureMode(XREALVideoCapture.VideoCaptureResult result)
|
||||
{
|
||||
if (!result.success)
|
||||
{
|
||||
Debug.Log("Started Video Capture Mode faild!");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("Started Video Capture Mode!");
|
||||
if (m_SliderMic != null && m_SliderApp != null)
|
||||
{
|
||||
float volumeMic = m_SliderMic.value;
|
||||
float volumeApp = m_SliderApp.value;
|
||||
m_VideoCapture.StartRecordingAsync(VideoSavePath, OnStartedRecordingVideo, volumeMic, volumeApp);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_VideoCapture.StartRecordingAsync(VideoSavePath, OnStartedRecordingVideo);
|
||||
}
|
||||
|
||||
m_PreviewRawImage.texture = m_VideoCapture.PreviewTexture;
|
||||
}
|
||||
|
||||
/// <summary> Executes the 'started recording video' action. </summary>
|
||||
/// <param name="result"> The result.</param>
|
||||
void OnStartedRecordingVideo(XREALVideoCapture.VideoCaptureResult result)
|
||||
{
|
||||
if (!result.success)
|
||||
{
|
||||
Debug.Log("Started Recording Video Faild!");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("Started Recording Video!");
|
||||
RefreshUIState();
|
||||
}
|
||||
|
||||
/// <summary> Executes the 'stopped recording video' action. </summary>
|
||||
/// <param name="result"> The result.</param>
|
||||
void OnStoppedRecordingVideo(XREALVideoCapture.VideoCaptureResult result)
|
||||
{
|
||||
if (!result.success)
|
||||
{
|
||||
Debug.Log("Stopped Recording Video Faild!");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("Stopped Recording Video!");
|
||||
m_VideoCapture.StopVideoModeAsync(OnStoppedVideoCaptureMode);
|
||||
}
|
||||
|
||||
/// <summary> Executes the 'stopped video capture mode' action. </summary>
|
||||
/// <param name="result"> The result.</param>
|
||||
void OnStoppedVideoCaptureMode(XREALVideoCapture.VideoCaptureResult result)
|
||||
{
|
||||
Debug.Log("Stopped Video Capture Mode!");
|
||||
RefreshUIState();
|
||||
|
||||
var encoder = m_VideoCapture.GetContext().GetEncoder() as VideoEncoder;
|
||||
string path = encoder.EncodeConfig.outPutPath;
|
||||
string filename = string.Format("Xreal_Shot_Video_{0}.mp4", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString());
|
||||
|
||||
StartCoroutine(DelayInsertVideoToGallery(path, filename, "Record"));
|
||||
|
||||
// Release video capture resource.
|
||||
m_VideoCapture.Dispose();
|
||||
m_VideoCapture = null;
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
// Release video capture resource.
|
||||
m_VideoCapture?.Dispose();
|
||||
m_VideoCapture = null;
|
||||
|
||||
// Relase photo capture resource
|
||||
m_PhotoCapture?.Dispose();
|
||||
m_PhotoCapture = null;
|
||||
}
|
||||
|
||||
IEnumerator DelayInsertVideoToGallery(string originFilePath, string displayName, string folderName)
|
||||
{
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
InsertVideoToGallery(originFilePath, displayName, folderName);
|
||||
}
|
||||
|
||||
public void InsertVideoToGallery(string originFilePath, string displayName, string folderName)
|
||||
{
|
||||
Debug.LogFormat("InsertVideoToGallery: {0}, {1} => {2}", displayName, originFilePath, folderName);
|
||||
if (galleryDataTool == null)
|
||||
{
|
||||
galleryDataTool = new GalleryDataProvider();
|
||||
}
|
||||
|
||||
galleryDataTool.InsertVideo(originFilePath, displayName, folderName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Use this for initialization. </summary>
|
||||
void CreatePhotoCapture(Action<XREALPhotoCapture> onCreated)
|
||||
{
|
||||
if (m_PhotoCapture != null)
|
||||
{
|
||||
Debug.Log("[TakePicture] CreatePhotoCapture: The XREALPhotoCapture has already been created.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a PhotoCapture object
|
||||
XREALPhotoCapture.CreateAsync(false, delegate (XREALPhotoCapture captureObject)
|
||||
{
|
||||
m_CameraResolution = XREALPhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
|
||||
|
||||
if (captureObject == null)
|
||||
{
|
||||
Debug.LogError("Can not get a captureObject.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_PhotoCapture = captureObject;
|
||||
|
||||
CameraParameters cameraParameters = new CameraParameters();
|
||||
Resolution cameraResolution = GetResolutionByLevel(resolutionLevel);
|
||||
cameraParameters.cameraType = CameraType.RGB;
|
||||
cameraParameters.hologramOpacity = 0.0f;
|
||||
cameraParameters.frameRate = NativeConstants.RECORD_FPS_DEFAULT;
|
||||
cameraParameters.cameraResolutionWidth = cameraResolution.width;
|
||||
cameraParameters.cameraResolutionHeight = cameraResolution.height;
|
||||
cameraParameters.pixelFormat = CapturePixelFormat.PNG;
|
||||
cameraParameters.blendMode = blendMode;
|
||||
cameraParameters.audioState = AudioState.None;
|
||||
cameraParameters.captureSide = captureside;
|
||||
cameraParameters.backgroundColor = useGreenBackGround ? Color.green : Color.black;
|
||||
|
||||
// Activate the camera
|
||||
m_PhotoCapture.StartPhotoModeAsync(cameraParameters, delegate (XREALPhotoCapture.PhotoCaptureResult result)
|
||||
{
|
||||
Debug.Log("Start PhotoMode Async");
|
||||
if (result.success)
|
||||
{
|
||||
onCreated?.Invoke(m_PhotoCapture);
|
||||
}
|
||||
else
|
||||
{
|
||||
isOnPhotoProcess = false;
|
||||
this.ClosePhotoCapture();
|
||||
Debug.LogError("[TakePicture] CreatePhotoCapture: Start PhotoMode failed." + result.resultType);
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary> Take a photo. </summary>
|
||||
void TakeAPhoto()
|
||||
{
|
||||
if (isOnPhotoProcess)
|
||||
{
|
||||
Debug.LogWarning("[TakePicture] TakeAPhoto: Currently in the process of taking pictures, Can not take photo .");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
isOnPhotoProcess = true;
|
||||
|
||||
if (m_PhotoCapture == null)
|
||||
{
|
||||
this.CreatePhotoCapture((capture) =>
|
||||
{
|
||||
capture.TakePhotoAsync(OnCapturedPhotoToMemory);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
m_PhotoCapture.TakePhotoAsync(OnCapturedPhotoToMemory);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Executes the 'captured photo memory' action. </summary>
|
||||
/// <param name="result"> The result.</param>
|
||||
/// <param name="photoCaptureFrame"> The photo capture frame.</param>
|
||||
void OnCapturedPhotoToMemory(XREALPhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
|
||||
{
|
||||
Debug.Log("[TakePicture] OnCapturedPhotoToMemory");
|
||||
var targetTexture = new Texture2D(m_CameraResolution.width, m_CameraResolution.height);
|
||||
// Copy the raw image data into our target texture
|
||||
photoCaptureFrame.UploadImageDataToTexture(targetTexture);
|
||||
|
||||
SaveTextureAsPNG(photoCaptureFrame);
|
||||
SaveTextureToGallery(photoCaptureFrame);
|
||||
// Release camera resource after capture the photo.
|
||||
this.ClosePhotoCapture();
|
||||
}
|
||||
|
||||
void SaveTextureAsPNG(PhotoCaptureFrame photoCaptureFrame)
|
||||
{
|
||||
Debug.Log("[TakePicture] SaveTextureAsPNG");
|
||||
if (photoCaptureFrame.TextureData == null)
|
||||
{
|
||||
Debug.LogError("[TakePicture] SaveTextureAsPNG: TextureData is null");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
string filename = string.Format("Xreal_Shot_{0}.png", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString());
|
||||
string path = string.Format("{0}/XrealShots", Application.persistentDataPath);
|
||||
string filePath = string.Format("{0}/{1}", path, filename);
|
||||
|
||||
byte[] _bytes = photoCaptureFrame.TextureData;
|
||||
Debug.LogFormat("[TakePicture] Photo capture: {0}Kb was saved to [{1}]", _bytes.Length / 1024, filePath);
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
File.WriteAllBytes(string.Format("{0}/{1}", path, filename), _bytes);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Save picture failed! {e}");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Closes this object. </summary>
|
||||
void ClosePhotoCapture()
|
||||
{
|
||||
if (m_PhotoCapture == null)
|
||||
{
|
||||
Debug.LogError("The XREALPhotoCapture has not been created.");
|
||||
return;
|
||||
}
|
||||
// Deactivate our camera
|
||||
m_PhotoCapture.StopPhotoModeAsync(OnStoppedPhotoMode);
|
||||
}
|
||||
|
||||
/// <summary> Executes the 'stopped photo mode' action. </summary>
|
||||
/// <param name="result"> The result.</param>
|
||||
void OnStoppedPhotoMode(XREALPhotoCapture.PhotoCaptureResult result)
|
||||
{
|
||||
// Shutdown our photo capture resource
|
||||
m_PhotoCapture?.Dispose();
|
||||
m_PhotoCapture = null;
|
||||
isOnPhotoProcess = false;
|
||||
}
|
||||
|
||||
public void SaveTextureToGallery(PhotoCaptureFrame photoCaptureFrame)
|
||||
{
|
||||
Debug.Log("[TakePicture] SaveTextureToGallery");
|
||||
if (photoCaptureFrame.TextureData == null)
|
||||
return;
|
||||
try
|
||||
{
|
||||
string filename = string.Format("Xreal_Shot_{0}.png", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString());
|
||||
byte[] _bytes = photoCaptureFrame.TextureData;
|
||||
Debug.Log(_bytes.Length / 1024 + "Kb was saved as: " + filename);
|
||||
if (galleryDataTool == null)
|
||||
{
|
||||
galleryDataTool = new GalleryDataProvider();
|
||||
}
|
||||
|
||||
galleryDataTool.InsertImage(_bytes, filename, "Screenshots");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("[TakePicture] Save picture faild!");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0658699caa291c343b0fdfdcf85f0237
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,70 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Unity.XR.XREAL.Samples
|
||||
{
|
||||
public class RGBCameraExample : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private Text m_ImageFormatText;
|
||||
[SerializeField]
|
||||
private RawImage m_YUVImage;
|
||||
[SerializeField]
|
||||
private Button m_PlayButton;
|
||||
[SerializeField]
|
||||
private Button m_StopButton;
|
||||
|
||||
private XREALRGBCameraTexture m_RGBCameraTexture;
|
||||
|
||||
void Start()
|
||||
{
|
||||
Debug.Log($"[RGBCamera] Start");
|
||||
m_RGBCameraTexture = XREALRGBCameraTexture.CreateSingleton();
|
||||
m_PlayButton.onClick.AddListener(Play);
|
||||
m_StopButton.onClick.AddListener(Stop);
|
||||
InitUI();
|
||||
Play();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
var yuvTextures = m_RGBCameraTexture.GetYUVFormatTextures();
|
||||
if (yuvTextures[0] != null)
|
||||
{
|
||||
m_YUVImage.texture = yuvTextures[0];
|
||||
m_YUVImage.material.SetTexture("_UTex", yuvTextures[1]);
|
||||
m_YUVImage.material.SetTexture("_VTex", yuvTextures[2]);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Debug.Log($"[RGBCamera] OnDestroy");
|
||||
Stop();
|
||||
}
|
||||
|
||||
private void InitUI()
|
||||
{
|
||||
m_ImageFormatText.text = "YUV_420_888";
|
||||
m_YUVImage.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
public void Play()
|
||||
{
|
||||
if (!m_RGBCameraTexture.IsCapturing)
|
||||
{
|
||||
Debug.Log($"[RGBCamera] Play");
|
||||
m_RGBCameraTexture.StartCapture();
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (m_RGBCameraTexture.IsCapturing)
|
||||
{
|
||||
Debug.Log($"[RGBCamera] Stop");
|
||||
m_RGBCameraTexture.StopCapture();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c00e84ada4a57d94ab4f9bfd2a573fc2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user