I am working on the unity version of the video playback sample. I have added the Video Playback Event Handler script in the inspecter and checked the M Full Screen mode. By default the orientation is Landscape right. I am trying to achieve auto rotation on the full screen playback so that when I turn the device, it changes orientation and so on. I have tried the suggestions regarding this problem, such as tinkering with the player settings etc. but it didn't work.
My second problem is the back button in the navigation bar. When my video is playing, I have to press the back button twice to go back to the camera. I want to kill the full screen playback as soon as I press the back button. How to do this.
I have tried tinkering with the following code (VideoPlaybackUIEventHandler.cs):
/*==============================================================================
* Copyright (c) 2012-2014 Qualcomm Connected Experiences, Inc. All Rights Reserved.
* ==============================================================================*/
using UnityEngine;
using System.Collections;
using Vuforia;
/// <summary>
/// UI Event Handler class that handles events generated by user-tap actions
/// over the UI Options Menu
/// </summary>
public class VideoPlaybackUIEventHandler : ISampleAppUIEventHandler
{
#region PUBLIC_MEMBER_VARIABLES
public override event System.Action CloseView;
public override event System.Action GoToAboutPage;
public bool mFullScreenMode;
#endregion PUBLIC_MEMBER_VARIABLES
#region PRIVATE_MEMBER_VARIABLES
private static bool sExtendedTrackingIsEnabled;
private VideoPlaybackUIView mView;
private bool mCameraFacingFront;
#endregion PRIVATE_MEMBER_VARIABLES
#region PUBLIC_MEMBER_PROPERTIES
public VideoPlaybackUIView View
{
get
{
if (mView == null)
{
mView = new VideoPlaybackUIView();
mView.LoadView();
}
return mView;
}
}
/// <summary>
/// Currently, there is no mechanism to query the SDK to know whether or not extended tracking is enabled/disabled.
/// Therefore, it needs to be handled at the app layer.
/// </value>
public static bool ExtendedTrackingIsEnabled
{
get
{
return sExtendedTrackingIsEnabled;
}
}
#endregion PUBLIC_MEMBER_PROPERTIES
#region PUBLIC_METHODS
public override void UpdateView(bool tf)
{
this.View.UpdateUI(tf);
}
public override void Bind()
{
this.View.mExtendedTracking.TappedOn += OnTappedToTurnOnTraking;
this.View.mCameraFlashSettings.TappedOn += OnTappedToTurnOnFlash;
this.View.mAutoFocusSetting.TappedOn += OnTappedToTurnOnAutoFocus;
this.View.mCameraFacing.TappedOnOption += OnTappedToTurnCameraFacing;
this.View.mCloseButton.TappedOn += OnTappedOnCloseButton;
this.View.mAboutLabel.TappedOn += OnTappedOnAboutButton;
this.View.mPlayFullscreeSettings.TappedOn += OnTappedOnFullscreenButton;
// register qcar started callback
QCARAbstractBehaviour qcarBehaviour = (QCARAbstractBehaviour)FindObjectOfType(typeof(QCARAbstractBehaviour));
if (qcarBehaviour)
{
qcarBehaviour.RegisterQCARStartedCallback(EnableContinuousAutoFocus);
qcarBehaviour.RegisterOnPauseCallback(OnPause);
}
}
public override void UnBind()
{
this.View.mExtendedTracking.TappedOn -= OnTappedToTurnOnTraking;
this.View.mCameraFlashSettings.TappedOn -= OnTappedToTurnOnFlash;
this.View.mAutoFocusSetting.TappedOn -= OnTappedToTurnOnAutoFocus;
this.View.mCameraFacing.TappedOnOption -= OnTappedToTurnCameraFacing;
this.View.mCloseButton.TappedOn -= OnTappedOnCloseButton;
this.View.mAboutLabel.TappedOn -= OnTappedOnAboutButton;
this.View.mPlayFullscreeSettings.TappedOn -= OnTappedOnFullscreenButton;
// unregister qcar started callback
QCARAbstractBehaviour qcarBehaviour = (QCARAbstractBehaviour)FindObjectOfType(typeof(QCARAbstractBehaviour));
if (qcarBehaviour)
{
qcarBehaviour.UnregisterQCARStartedCallback(EnableContinuousAutoFocus);
qcarBehaviour.UnregisterOnPauseCallback(OnPause);
}
this.View.UnLoadView();
}
//SingleTap Gestures are captured by AppManager and calls this method for TapToFocus
public override void TriggerAutoFocus()
{
StartCoroutine(TriggerAutoFocusAndEnableContinuousFocusIfSet());
}
#endregion PUBLIC_METHODS
#region PRIVATE_METHODS
/// <summary>
/// Activating trigger autofocus mode unsets continuous focus mode (if was previously enabled from the UI Options Menu)
/// So, we wait for a second and turn continuous focus back on (if options menu shows as enabled)
/// </returns>
private IEnumerator TriggerAutoFocusAndEnableContinuousFocusIfSet()
{
//triggers a single autofocus operation
if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_TRIGGERAUTO))
{
this.View.FocusMode = CameraDevice.FocusMode.FOCUS_MODE_TRIGGERAUTO;
}
yield return new WaitForSeconds(1.0f);
//continuous focus mode is turned back on if it was previously enabled from the options menu
if (this.View.mAutoFocusSetting.IsEnabled)
{
if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO))
{
this.View.FocusMode = CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO;
}
}
Debug.Log(this.View.FocusMode);
}
private void OnPause(bool pause)
{
if (!pause && this.View.mAutoFocusSetting.IsEnabled)
{
// set to continous autofocus
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
}
//On hitting the home button, the app tends to turn off the flash
//So, setting the UI to reflect that
this.View.mCameraFlashSettings.Enable(pause);
}
private void OnTappedOnAboutButton(bool tf)
{
if (this.GoToAboutPage != null)
{
this.GoToAboutPage();
}
}
//We want autofocus to be enabled when the app starts
private void EnableContinuousAutoFocus()
{
if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO))
{
this.View.FocusMode = CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO;
this.View.mAutoFocusSetting.Enable(true);
}
}
private void OnTappedToTurnOnTraking(bool tf)
{
if (!ExtendedTracking(tf))
{
this.View.mExtendedTracking.Enable(false);
VideoPlaybackUIEventHandler.sExtendedTrackingIsEnabled = false;
}
else
{
this.View.mExtendedTracking.Enable(tf);
VideoPlaybackUIEventHandler.sExtendedTrackingIsEnabled = tf;
}
OnTappedToClose();
}
private void OnTappedToTurnOnFlash(bool tf)
{
if (tf)
{
if (!CameraDevice.Instance.SetFlashTorchMode(true) || mCameraFacingFront)
{
this.View.mCameraFlashSettings.Enable(false);
}
}
else
{
CameraDevice.Instance.SetFlashTorchMode(false);
}
OnTappedToClose();
}
/// <summary>
/// If the video is already playing on texture, enabling it will bring the video to full-screen
/// otherwise, the video will play on fullscreen the next time user taps on the texture.
/// </summary>
/// <param name="tf"></param>
private void OnTappedOnFullscreenButton(bool tf)
{
mFullScreenMode = tf;
if (tf)
{
VideoPlaybackBehaviour video = PickVideo();
if (video != null)
{
if (video.VideoPlayer.IsPlayableFullscreen())
{
//On Android, we use Unity's built in player, so Unity application pauses before going to fullscreen.
//So we have to handle the orientation from within Unity.
#if UNITY_ANDROID
Screen.orientation = ScreenOrientation.Portrait;
#endif
// Pause the video if it is currently playing
video.VideoPlayer.Pause();
// Seek the video to the beginning();
video.VideoPlayer.SeekTo(0.0f);
// Display the busy icon
video.ShowBusyIcon();
// Play the video full screen
StartCoroutine ( PlayVideo.PlayFullscreenVideoAtEndOfFrame(video) );
//Flash turns off automatically on fullscreen videoplayback mode, so we need to update the UI accordingly
this.View.mCameraFlashSettings.Enable(false);
}
}
}
OnTappedToClose();
}
private VideoPlaybackBehaviour PickVideo()
{
VideoPlaybackBehaviour[] behaviours = GameObject.FindObjectsOfType(typeof(VideoPlaybackBehaviour)) as VideoPlaybackBehaviour[];
VideoPlaybackBehaviour video = null;
foreach (VideoPlaybackBehaviour bhvr in behaviours)
{
if (bhvr.CurrentState == VideoPlayerHelper.MediaState.PLAYING)
{
video = bhvr;
}
}
return video;
}
private void OnTappedToTurnOnAutoFocus(bool tf)
{
if (tf)
{
if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO))
{
this.View.FocusMode = CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO;
}
else
{
this.View.mAutoFocusSetting.Enable(false);
}
}
else
{
if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL))
{
this.View.FocusMode = CameraDevice.FocusMode.FOCUS_MODE_NORMAL;
}
}
OnTappedToClose();
}
private void OnTappedToTurnCameraFacing(int val)
{
if (val == 0)
{
//internally, flash is always turned off everytime it tries to switch to front camera
//so updating the UI options to reflect that.
this.View.mCameraFlashSettings.Enable(false);
if (ChangeCameraDirection(CameraDevice.CameraDirection.CAMERA_FRONT))
{
mCameraFacingFront = true;
}
else
{
ChangeCameraDirection(CameraDevice.CameraDirection.CAMERA_BACK);
mCameraFacingFront = false;
this.View.mCameraFacing.EnableIndex(1);
}
}
else
{
ChangeCameraDirection(CameraDevice.CameraDirection.CAMERA_BACK);
mCameraFacingFront = false;
}
OnTappedToClose();
}
private bool stopRunningObjectTracker()
{
bool needsObjectTrackerRestart = false;
ObjectTracker objectTracker = TrackerManager.Instance.GetTracker<ObjectTracker>();
if (objectTracker != null)
{
if (objectTracker.IsActive)
{
objectTracker.Stop();
needsObjectTrackerRestart = true;
}
}
return needsObjectTrackerRestart;
}
private bool restartRunningObjectTracker()
{
bool hasObjectTrackerRestarted = false;
ObjectTracker objectTracker = TrackerManager.Instance.GetTracker<ObjectTracker>();
if (objectTracker != null)
{
if (!objectTracker.IsActive)
{
hasObjectTrackerRestarted = objectTracker.Start();
}
}
return hasObjectTrackerRestarted;
}
private void ResetCameraFacingToBack()
{
bool needsObjectTrackerRestart = stopRunningObjectTracker();
CameraDevice.Instance.Stop();
CameraDevice.Instance.Init(CameraDevice.CameraDirection.CAMERA_BACK);
CameraDevice.Instance.Start();
mCameraFacingFront = false;
if (needsObjectTrackerRestart)
restartRunningObjectTracker();
}
private bool ChangeCameraDirection(CameraDevice.CameraDirection direction)
{
bool directionSupported = false;
bool needsObjectTrackerRestart = stopRunningObjectTracker();
CameraDevice.Instance.Stop();
CameraDevice.Instance.Deinit();
if (CameraDevice.Instance.Init(direction))
{
directionSupported = true;
}
CameraDevice.Instance.Start();
if (needsObjectTrackerRestart)
restartRunningObjectTracker();
return directionSupported;
}
private void OnTappedToClose()
{
if (this.CloseView != null)
{
this.CloseView();
}
}
private void OnTappedOnCloseButton()
{
OnTappedToClose();
}
/// <summary>
/// This method turns extended tracking on or off for all currently available targets.
/// Extended tracking allows to track targets when they are not in view.
/// Returns true of extended tracking is supported; false otherwise
/// </summary>
private bool ExtendedTracking(bool tf)
{
// the StateManager gives access to all available TrackableBehavours
StateManager stateManager = TrackerManager.Instance.GetStateManager();
// We iterate over all TrackableBehaviours to start or stop extended tracking for the targets they represent.
bool extendedTrackingStateChanged = true;
foreach (var behaviour in stateManager.GetTrackableBehaviours())
{
var imageBehaviour = behaviour as ImageTargetBehaviour;
if (imageBehaviour != null)
{
if (tf)
{
//only if extended tracking is supported
if (!imageBehaviour.ImageTarget.StartExtendedTracking())
{
extendedTrackingStateChanged = false;
}
}
else
{
if (!imageBehaviour.ImageTarget.StopExtendedTracking())
{
extendedTrackingStateChanged = false;
}
}
}
}
if (!extendedTrackingStateChanged)
{
Debug.LogWarning("Extended Tracking Failed!");
}
return extendedTrackingStateChanged;
}
#endregion PRIVATE_METHODS
}
and this code as well (PlayVideo.cs):
/*==============================================================================
* Copyright (c) 2012-2014 Qualcomm Connected Experiences, Inc. All Rights Reserved.
* ==============================================================================*/
using UnityEngine;
using System.Collections;
using Vuforia;
/// <summary>
/// Demonstrates how to play the video on texture and full-screen mode.
/// Single tapping on texture will play the video on texture (if the 'Play FullScreen' Mode in the UIMenu is turned off)
/// or play full screen (if the option is enabled in the UIMenu)
/// At any time during the video playback, it can be brought to full-screen by enabling the options from the UIMenu.
/// </summary>
public class PlayVideo : MonoBehaviour
{
private bool mVideoIsPlaying;
private VideoPlaybackBehaviour currentVideo;
#region UNITY_MONOBEHAVIOUR_METHODS
void Start()
{
InputController.SingleTapped += HandleSingleTap;
InputController.DoubleTapped += HandleDoubleTap;
}
void OnApplicationPause(bool tf)
{
//When the video finishes playing on fullscreen mode, Unity application unpauses and that's when we need to switch to potrait
//in order to display the UI menu options properly
#if UNITY_ANDROID
if(!tf) {
Screen.orientation = ScreenOrientation.Portrait;
}
#endif
}
#endregion UNITY_MONOBEHAVIOUR_METHODS
#region PRIVATE_METHODS
/// <summary>
/// Just in case the device is in any other mode at the time the user double taps to bring up the UI menu, we force it to go to potrait
/// because the UI menu supports only potrait for now.
/// </summary>
private void HandleDoubleTap()
{
if (Screen.orientation != ScreenOrientation.Portrait)
{
Screen.orientation = ScreenOrientation.Portrait;
}
}
/// <summary>
/// Handle single tap event
/// </summary>
private void HandleSingleTap()
{
if (QCARRuntimeUtilities.IsPlayMode())
{
if (PickVideo(Input.mousePosition) != null)
Debug.LogWarning("Playing videos is currently not supported in Play Mode.");
}
// Find out which video was tapped, if any
currentVideo = PickVideo(Input.mousePosition);
if (currentVideo != null)
{
if (IsFullScreenModeEnabled())
{
if (currentVideo.VideoPlayer.IsPlayableFullscreen())
{
//On Android, we use Unity's built in player, so Unity application pauses before going to fullscreen.
//So we have to handle the orientation from within Unity.
#if UNITY_ANDROID
Screen.autorotateToPortrait = true;
Screen.autorotateToPortraitUpsideDown = true;
Screen.orientation = ScreenOrientation.AutoRotation;
#endif
// Pause the video if it is currently playing
currentVideo.VideoPlayer.Pause();
// Seek the video to the beginning();
currentVideo.VideoPlayer.SeekTo(0.0f);
// Display the busy icon
currentVideo.ShowBusyIcon();
// Play the video full screen
StartCoroutine( PlayFullscreenVideoAtEndOfFrame(currentVideo) );
UpdateFlashSettingsInUIView();
}
}
else
{
if (currentVideo.VideoPlayer.IsPlayableOnTexture())
{
// This video is playable on a texture, toggle playing/paused
VideoPlayerHelper.MediaState state = currentVideo.VideoPlayer.GetStatus();
if (state == VideoPlayerHelper.MediaState.PAUSED ||
state == VideoPlayerHelper.MediaState.READY ||
state == VideoPlayerHelper.MediaState.STOPPED)
{
// Pause other videos before playing this one
PauseOtherVideos(currentVideo);
// Play this video on texture where it left off
currentVideo.VideoPlayer.Play(false, currentVideo.VideoPlayer.GetCurrentPosition());
}
else if (state == VideoPlayerHelper.MediaState.REACHED_END)
{
// Pause other videos before playing this one
PauseOtherVideos(currentVideo);
// Play this video from the beginning
currentVideo.VideoPlayer.Play(false, 0);
}
else if (state == VideoPlayerHelper.MediaState.PLAYING)
{
// Video is already playing, pause it
currentVideo.VideoPlayer.Pause();
}
}
else
{
// Display the busy icon
currentVideo.ShowBusyIcon();
// This video cannot be played on a texture, play it full screen
StartCoroutine( PlayFullscreenVideoAtEndOfFrame(currentVideo) );
}
}
}
}
public static IEnumerator PlayFullscreenVideoAtEndOfFrame(VideoPlaybackBehaviour video)
{
Screen.orientation = ScreenOrientation.AutoRotation;
Screen.autorotateToPortrait = true;
Screen.autorotateToPortraitUpsideDown = true;
Screen.autorotateToLandscapeLeft = true;
Screen.autorotateToLandscapeRight = true;
yield return new WaitForEndOfFrame ();
// we wait a bit to allow the ScreenOrientation.AutoRotation to become effective
yield return new WaitForSeconds (0.3f);
video.VideoPlayer.Play(true, 0);
}
//Flash turns off automatically on fullscreen videoplayback mode, so we need to update the UI accordingly
private void UpdateFlashSettingsInUIView()
{
VideoPlaybackUIEventHandler handler = GameObject.FindObjectOfType(typeof(VideoPlaybackUIEventHandler)) as VideoPlaybackUIEventHandler;
if (handler != null)
{
handler.View.mCameraFlashSettings.Enable(false);
}
}
/// <summary>
/// Checks to see if the 'Play FullScreen' Mode is enabled/disabled in the UI Menu
/// </summary>
/// <returns></returns>
private bool IsFullScreenModeEnabled()
{
VideoPlaybackUIEventHandler handler = FindObjectOfType(typeof(VideoPlaybackUIEventHandler)) as VideoPlaybackUIEventHandler;
if (handler != null)
{
return handler.mFullScreenMode;
}
return false;
}
/// <summary>
/// Find the video object under the screen point
/// </summary>
private VideoPlaybackBehaviour PickVideo(Vector3 screenPoint)
{
VideoPlaybackBehaviour[] videos = (VideoPlaybackBehaviour[])
FindObjectsOfType(typeof(VideoPlaybackBehaviour));
GameObject go = QCARManager.Instance.ARCameraTransform.gameObject;
Camera[] cam = go.GetComponentsInChildren<Camera> ();
Ray ray = cam[0].ScreenPointToRay(screenPoint);
RaycastHit hit = new RaycastHit();
foreach (VideoPlaybackBehaviour video in videos)
{
if (video.GetComponent<Collider>().Raycast(ray, out hit, 10000))
{
return video;
}
}
return null;
}
/// <summary>
/// Pause all videos except this one
/// </summary>
private void PauseOtherVideos(VideoPlaybackBehaviour currentVideo)
{
VideoPlaybackBehaviour[] videos = (VideoPlaybackBehaviour[])
FindObjectsOfType(typeof(VideoPlaybackBehaviour));
foreach (VideoPlaybackBehaviour video in videos)
{
if (video != currentVideo)
{
if (video.CurrentState == VideoPlayerHelper.MediaState.PLAYING)
{
video.VideoPlayer.Pause();
}
}
}
}
#endregion // PRIVATE_METHODS
}
In Both of these codes, the part where you'll see #IF UNITY_ANDROID in the HandleSingleTap method and OnTappedOnFullScreen method, I tried playing around the with Screen.orientation in Unity Scripting. To be specific, I tried the following to achieve auto-rotation but it didn't help:
Screen.autorotateToPortrait = true;
Screen.autorotateToPortraitUpsideDown = true;
Screen.autorotateToLandscapeLeft = true;
Screen.autorotateToLandscapeRight = true;
Screen.orientation = ScreenOrientation.AutoRotation;
When I did just one orientation, like they did in the code, for instance: Screen.orientation = ScreenOrientation.LandscapeRight, the orientation changed. But that is not what I wanted.
Any help/tips would be appeciated!
Thank you.
To address your first problem, I would suggest you have two separate orientation layouts for your Landscape and Portrait orientations. So when that's done you could use a script to detect whether the device is Landscape or Portrait and accordingly
SetActive
that layout.Here's how a sample code would look like:
To smoothen things out between scenes you need to make sure that the Object you assign the next script is not destroyed so use:
And then this GameObject can go on to use this script which contains two methods for the rest:
Choose any one and you should be gold.
And then on regarding your Multiple tap issue:-
Check if there are anyother GUI nearby or overlapping. In my question, I had found out that the two
P
andL
GameObjects hadRaycasters
/Colliders
on top of each other, hence Unity seemed to be flickering between the two.