Page 1 of 1

[iOS] What is the correct way to handle orientation changes

Posted: Thu Oct 17, 2013 2:53 pm
by simedj
I'm running Ogre 1.9 and whichever initial orientation is selected, it works fine. But as soon as you change the orientation, everything gets squished/squashed and input events appear messed up too.

I'm using a very simple iOS-Ogre setup where I create a RenderWindow manually.

I have seen threads in the past about this, but can't remember if Ogre is supposed to handle this automatically, or if I need some additional event handler to do it. The most detailed thread I found was 2-3 years old and I know iOS support has improved a LOT since Ogre 1.7 :)

Thankyou for any help.

Re: [iOS] What is the correct way to handle orientation chan

Posted: Fri Oct 18, 2013 5:31 am
by masterfalcon
Interesting. I haven't seen that happen in a long time. Are you using GL ES 1 or 2? Even with a manually created window the render buffers should get recreated with the proper dimensions and input should also be correct. How old are the dependencies that you are using?

Re: [iOS] What is the correct way to handle orientation chan

Posted: Fri Oct 18, 2013 8:28 am
by simedj
Built within the last few weeks - I finally switched from the supplied pre-built dependencies to building my own from source too.

Actually, I haven't tested this since doing that...

...aha. Now I do see the Ogre viewport toggle. It's a bit ugly as it rotates and stretches, then pops back afterwards, but it is working.

However my GUI stuff is still being messed up. Now this isn't Ogre's responsibility - you're off the hook ;) - but I still need to fix it. So I think I still need to catch some event and handle it, either an iOS event or an Ogre one. How is Ogre internally handling this - catching an orientation change notification and translating it to a window-resize action maybe? If you can tell me how Ogre is automatically handling orientation changes maybe I can dig through the code to see myself, but I'd still appreciate any higher-level advice.

Just for background, I'm using MyGUI for my GUI stuff as this is cross-compiling Win32 and iOS. I checked and on Win32 I can resize my window without this problem so either Ogre isn't treating them the same, or I have inadvertently coded different behaviour on my side.

Re: [iOS] What is the correct way to handle orientation chan

Posted: Sat Oct 19, 2013 8:42 am
by masterfalcon
We listen for shouldAutorotateToInterfaceOrientation in our ViewController which in turn calls setNeedsDisplay. This tells views to redo their layout, at this point layoutSubviews is called, which does the actual GL context resizing.

Re: [iOS] What is the correct way to handle orientation chan

Posted: Sat Oct 19, 2013 3:42 pm
by simedj
So if I need to do something additional - can/should I also be handling shouldAutorotateToInterfaceOrientation? I'll dig into the code when on the right computer but I think my biggest question is: does all of this end up with my RenderWindow acting as if it has been resized - i.e. I can catch this happening through rendersystem-independent Ogre listeners?

Re: [iOS] What is the correct way to handle orientation chan

Posted: Sat Oct 19, 2013 4:29 pm
by masterfalcon
Yeah, you probably can. You could create a RenderTargetListener and check the size at the beginning or ending of each frame.

Re: [iOS] What is the correct way to handle orientation chan

Posted: Sat Oct 19, 2013 6:10 pm
by simedj
But it won't fire a window-resized event - it doesn't treat an orientation change like simply resizing? That would be kind of ideal :)

Re: [iOS] What is the correct way to handle orientation chan

Posted: Sun Oct 20, 2013 6:13 am
by masterfalcon
What window resized event are you referring to?

Re: [iOS] What is the correct way to handle orientation chan

Posted: Sun Oct 20, 2013 4:52 pm
by simedj
I'm meaning Ogre::WindowEventListener, I think.

Re: [iOS] What is the correct way to handle orientation chan

Posted: Tue Oct 22, 2013 9:00 pm
by simedj
OK, so from looking at MyGUI code and from their own sub-forum (http://www.ogre3d.org/addonforums/viewt ... 17&t=30089) it would seem that MyGUI relies on Ogre::WindowEventListener events, specifically windowResized(Ogre::RenderWindow* _window), to know when it needs to update its layout, MyGUI's implementation looks like this in case that's useful:

Code: Select all

	void OgreRenderManager::windowResized(Ogre::RenderWindow* _window)
	{
		if (_window->getNumViewports() > mActiveViewport)
		{
			Ogre::Viewport* port = _window->getViewport(mActiveViewport);
#if OGRE_VERSION >= MYGUI_DEFINE_VERSION(1, 7, 0) && OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0
			Ogre::OrientationMode orient = port->getOrientationMode();
			if (orient == Ogre::OR_DEGREE_90 || orient == Ogre::OR_DEGREE_270)
				mViewSize.set(port->getActualHeight(), port->getActualWidth());
			else
				mViewSize.set(port->getActualWidth(), port->getActualHeight());
#else
			mViewSize.set(port->getActualWidth(), port->getActualHeight());
#endif

			// обновить всех
			mUpdate = true;

			updateRenderInfo();

			onResizeView(mViewSize);
		}
	}
However, from testing it appears Ogre::WindowEventListener::windowResized simply isn't called in an iOS orientation change event.

Is that how it has always been, or has something changed here - because it looks like the MyGUI code was written with at least some consideration of orientation events in mind?

Re: [iOS] What is the correct way to handle orientation chan

Posted: Tue Oct 22, 2013 10:23 pm
by simedj
Looking at the GLES2 subsystem, I think the key function is in OgreEAGL2View.mm:

Code: Select all

- (void)layoutSubviews ()
{
<snip>

        // Get the window size and initialize temp variables
        unsigned int w = 0, h = 0;
        unsigned int width = (uint)self.bounds.size.width;
        unsigned int height = (uint)self.bounds.size.height;

        if (UIDeviceOrientationIsLandscape(deviceOrientation))
        {
            w = std::max(width, height);
            h = std::min(width, height);
        }
        else
        {
            h = std::max(width, height);
            w = std::min(width, height);
        }

        width = w;
        height = h;

        // Resize the window
        window->resize(width, height);
        
        // After rotation the aspect ratio of the viewport has changed, update that as well.
        if(window->getNumViewports() > 0)
        {
            Ogre::Viewport *viewPort = window->getViewport(0);
            viewPort->getCamera()->setAspectRatio((Real) width / (Real) height);
        }
This logic looks very similar to what I do in my windowResized() event handler on Windows, where I update the camera aspect ratio. However It means I don't get a chance to do other stuff at the same time.

It does look like Viewport::Listener::viewportDimensionsChanged() should be called though from inside window->resize() - I'll have to check this out. Maybe this is an option.