Skip to content
This repository has been archived by the owner on Sep 5, 2023. It is now read-only.

Display issue on modal presenting #319

Open
bill350 opened this issue May 4, 2018 · 7 comments
Open

Display issue on modal presenting #319

bill350 opened this issue May 4, 2018 · 7 comments

Comments

@bill350
Copy link

bill350 commented May 4, 2018

Hi Google VR team,

We have some issues with displaying the GVRPlayer correctly on a UIViewController which is displayed into a UINavigationController (which is displayed in modal).

Use case: the player is firstly embedded in our UIViewController (as it is in your sample code, the only difference is that it is embedded into a VRVideoViewController. See source below), and we want to display/switch the video in full screen next.

The final issue is that when we tap on fullscreen / cardboard, the player don't switch to fullscreen mode. We've tried to push the player in the current UINavigationController stack (displayed in modal mode), but the OpenGL video rendering is still broken, and lens not correctly fit the entire size of the screen.

Here our code integration extract for the player configuration :

protocol VRVideoViewControllerDelegate: class {
  func playerIsReady()
}

/// This controller contains a GVRRendererViewController from the GVRKit by Google
final class VRVideoViewController: ViewController {
  
  fileprivate(set) var vrPlayer: AVPlayer?
  fileprivate var vrVideoPlayerController: GVRRendererViewController?
  fileprivate var vrRendererView: GVRRendererView?
  
  weak var delegate: VRVideoViewControllerDelegate?
  
  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }
  
  init(with url: String) {
    super.init(nibName: nil, bundle: nil)
    
    if OpenGLUtils.isOpenGL3Compliant() {
      
      if let url = URL(string: url) {
        self.vrPlayer = AVPlayer(url: url)
      }
      
      self.vrPlayer?.actionAtItemEnd = .none
      
      self.vrVideoPlayerController = GVRRendererViewController()
      // Be careful here, just after the delegate is set, GVR SDK Call the method "renderer()"
      // in the GVRRendererViewControllerDelegate implementation
      self.vrVideoPlayerController?.delegate = self
      if let vrVideoPlayerController = vrVideoPlayerController {
        self.ex.addChildViewController(vrVideoPlayerController, in: self.view)
      }
      
      let sceneRenderer = self.vrVideoPlayerController?.rendererView.renderer as? GVRSceneRenderer
      let videoRenderer = sceneRenderer?.renderList.object(at: 0) as? GVRVideoRenderer
      videoRenderer?.player = self.vrPlayer
      self.vrRendererView = self.vrVideoPlayerController?.view as? GVRRendererView
    } else {
      let placeholder = VRVideoPlaceholder(frame: self.view.frame)
      self.view.ex.addSubview(placeholder)
    }
    
  }
  
  override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.delegate?.playerIsReady()
  }
}

// MARK: - GVRRendererViewControllerDelegate
extension VRVideoViewController: GVRRendererViewControllerDelegate {
  
  func shouldHideTransitionView() -> Bool {
    return true
  }
  
  func renderer(for displayMode: GVRDisplayMode) -> GVRRenderer! {
    
    let videoRenderer = GVRVideoRenderer()
    videoRenderer.player = self.vrPlayer
    
    // Monoscopic = panorama style
    // TopBottom = Video splitted and duplicated in two parts, vertically
    // LeftRight = Video splitted and duplicated in two parts, horizontally
    videoRenderer.setSphericalMeshOfRadius(50,
                                           latitudes: 12,
                                           longitudes: 24,
                                           verticalFov: 180,
                                           horizontalFov: 360,
                                           meshType: GVRMeshType.monoscopic)
    
    let sceneRenderer = GVRSceneRenderer()
    sceneRenderer.renderList.add(videoRenderer)
    
    if displayMode == .embedded {
      sceneRenderer.hidesReticle = true
    }
    
    videoRenderer.player?.play()
    
    return sceneRenderer
  }
}

Could you please update the sample code with a modal example, similar to the root UIViewController which is used today?
We have tested your sample with modal display and we have the same rendering issue, any idea?

Thanks

@bill350 bill350 changed the title Display issue on modal Display issue on modal presenting May 4, 2018
@Performador
Copy link

I was not able to repo this. Are you sure you are laying out the vrVideoViewController.view in the view[Will/Did]LayoutSubviews?

Try the following code where the only difference is that I had to implement self.ex.addChildViewController.

protocol VRVideoViewControllerDelegate: class {
  func playerIsReady()
}

/// This controller contains a GVRRendererViewController from the GVRKit by Google
final class VRVideoViewController: ViewController, GVRRendererViewControllerDelegate {

  fileprivate(set) var vrPlayer: AVPlayer?
  fileprivate var vrVideoPlayerController: GVRRendererViewController?
  fileprivate var vrRendererView: GVRRendererView?

  weak var delegate: VRVideoViewControllerDelegate?

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }

  init() {
    super.init(nibName: nil, bundle: nil)
  }

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated);

    if let url = URL(string: "[SOME_VIDEO_URL]") {
      self.vrPlayer = AVPlayer(url: url)
    }

    self.vrPlayer?.actionAtItemEnd = .none

    self.vrVideoPlayerController = GVRRendererViewController()
    // Be careful here, just after the delegate is set, GVR SDK Call the method "renderer()"
    // in the GVRRendererViewControllerDelegate implementation
    self.vrVideoPlayerController?.delegate = self
    if let vrVideoPlayerController = vrVideoPlayerController {

      //self.ex.addChildViewController(vrVideoPlayerController, in: self.view)
      self.addChildViewController(vrVideoPlayerController)
      self.view.addSubview(vrVideoPlayerController.view)
      vrVideoPlayerController.didMove(toParentViewController: self);
    }

    let sceneRenderer = self.vrVideoPlayerController?.rendererView.renderer as? GVRSceneRenderer
    let videoRenderer = sceneRenderer?.renderList.object(at: 0) as? GVRVideoRenderer
    videoRenderer?.player = self.vrPlayer
    self.vrRendererView = self.vrVideoPlayerController?.view as? GVRRendererView
  }

  override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.delegate?.playerIsReady()

    // bill350: Layout the child view controllers view here.
    vrVideoPlayerController?.view.frame = self.view.bounds
  }

  func shouldHideTransitionView() -> Bool {
    return true
  }

  func renderer(for displayMode: GVRDisplayMode) -> GVRRenderer! {
    let videoRenderer = GVRVideoRenderer()
    videoRenderer.player = self.vrPlayer

    // Monoscopic = panorama style
    // TopBottom = Video splitted and duplicated in two parts, vertically
    // LeftRight = Video splitted and duplicated in two parts, horizontally
    videoRenderer.setSphericalMeshOfRadius(50,
                                           latitudes: 12,
                                           longitudes: 24,
                                           verticalFov: 180,
                                           horizontalFov: 360,
                                           meshType: GVRMeshType.monoscopic)

    let sceneRenderer = GVRSceneRenderer()
    sceneRenderer.renderList.add(videoRenderer)

    if displayMode == .embedded {
      sceneRenderer.hidesReticle = true
    }

    videoRenderer.player?.play()

    return sceneRenderer
  }
}

@bill350
Copy link
Author

bill350 commented May 15, 2018

Thanks for reply @Performador. It still doesn't work.

I share with you a screen capture with the structure of the modal :

  • blue: the UIViewController displayed into a UINavigationController(navigation bar hidden in this context), modally ;
  • yellow: the text content (UICollectionView) of the UIViewController ;
  • red: the container view, above the UICollectionView, which contains the VRVideoViewController ;
  • the exclamation mark ⚠️indicates that the top oh the CardBoard button doesn't make any action. The cardboard controller is not displayed or the cardboard view is displayed but just inside the container view (and not in landscape full screen).

img_b1c0b40f5a7c-1

Is it more clear?

Thanks.

@Performador
Copy link

Ah, I see.

I think the problem is that you cannot have two modal VCs at the same time and GVRRendererViewController will call presentViewController if we are in the embedded mode (like the picture you shared).

@bill350
Copy link
Author

bill350 commented May 16, 2018

But it’s embedded into a navigation controller too, so it’s technically possible.
The SDK bust be fixed with this “classic” use case.

@Performador
Copy link

GVRRendererViewController will call it's parent VCs presentViewController method.

You can override this method in your VRVideoViewController and call [self.navigationController presentViewController ...] to route the modal presentation to the navigation controller.

@bill350
Copy link
Author

bill350 commented May 16, 2018

"You can override this method in your VRVideoViewController and call [self.navigationController presentViewController ...] to route the modal presentation to the navigation controller."

I'm not sure about this.

If I'm right, the isModal method is called first :
https://github.com/googlevr/gvr-ios-sdk/blob/master/Samples/GVRKit/GVRRendererViewController.m

- (void)didTapCardboardButton {
  // Toggle VR mode if we are being presented.
  if ([self isModal]) {
    self.rendererView.VRModeEnabled = !self.rendererView.VRModeEnabled;
  } else {
...
}

That's why the view switches from this state:
simple

to this state:
sample_2

@Performador
Copy link

Ah, yes, thanks for the explanation.

You are right. The SDK assumes that if we are modal, we are full screen but in your case, this is not true.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants