iphone orientation

This commit is contained in:
David Rose 2009-04-25 23:14:12 +00:00
parent 44d9431d1a
commit 8358dfc7b7
17 changed files with 265 additions and 124 deletions

View File

@ -1907,7 +1907,7 @@ do_add_gsg(GraphicsStateGuardian *gsg, GraphicsPipe *pipe,
void GraphicsEngine:: void GraphicsEngine::
do_remove_window(GraphicsOutput *window, Thread *current_thread) { do_remove_window(GraphicsOutput *window, Thread *current_thread) {
PT(GraphicsPipe) pipe = window->get_pipe(); PT(GraphicsPipe) pipe = window->get_pipe();
window->_pipe = (GraphicsPipe *)NULL; window->clear_pipe();
if (!_windows_sorted) { if (!_windows_sorted) {
do_resort_windows(); do_resort_windows();

View File

@ -974,7 +974,7 @@ set_close_now() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::reset_window // Function: GraphicsOutput::reset_window
// Access: Protected, Virtual // Access: Protected, Virtual
// Description: resets the window framebuffer from its derived // Description: Resets the window framebuffer from its derived
// children. Does nothing here. // children. Does nothing here.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void GraphicsOutput:: void GraphicsOutput::
@ -983,6 +983,18 @@ reset_window(bool swapchain) {
<< "Resetting " << get_type() << "\n"; << "Resetting " << get_type() << "\n";
} }
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::clear_pipe
// Access: Protected, Virtual
// Description: Sets the window's _pipe pointer to NULL; this is
// generally called only as a precursor to deleting the
// window.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
clear_pipe() {
_pipe = (GraphicsPipe *)NULL;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::begin_frame // Function: GraphicsOutput::begin_frame
// Access: Public, Virtual // Access: Public, Virtual

View File

@ -195,6 +195,7 @@ public:
virtual void set_close_now(); virtual void set_close_now();
virtual void reset_window(bool swapchain); virtual void reset_window(bool swapchain);
virtual void clear_pipe();
void set_size_and_recalc(int x, int y); void set_size_and_recalc(int x, int y);

View File

@ -1492,6 +1492,7 @@ event_window_event(const Event *event, void *data) {
} else { } else {
if (!win->is_valid()) { if (!win->is_valid()) {
// The window has been closed.
int window_index = self->find_window(win); int window_index = self->find_window(win);
while (window_index != -1) { while (window_index != -1) {
self->close_window(window_index); self->close_window(window_index);
@ -1507,6 +1508,13 @@ event_window_event(const Event *event, void *data) {
<< "Last window was closed by user.\n"; << "Last window was closed by user.\n";
self->_exit_flag = true; self->_exit_flag = true;
} }
} else {
// Adjust aspect ratio.
for (int n = 0; n < (int)self->_windows.size(); n++) {
if (self->_windows[n]->get_graphics_output() == win) {
return self->_windows[n]->adjust_aspect_ratio();
}
}
} }
} }
} }

View File

@ -769,6 +769,49 @@ set_anim_controls(bool enable) {
} }
} }
////////////////////////////////////////////////////////////////////
// Function: WindowFramework::adjust_aspect_ratio
// Access: Public
// Description: Reevaluates the aspect ratio of the window,
// presumably after the window has been resized by the
// user or some other force. Adjusts the render film
// size and aspect2d scale as necessary according to the
// new window shape, or new config setting.
////////////////////////////////////////////////////////////////////
void WindowFramework::
adjust_aspect_ratio() {
float this_aspect_ratio = aspect_ratio;
int x_size = 0, y_size = 0;
if (this_aspect_ratio == 0.0f) {
// An aspect ratio of 0.0 means to try to infer it.
this_aspect_ratio = 1.0f;
if (_window->has_size()) {
x_size = _window->get_x_size();
y_size = _window->get_y_size();
if (y_size != 0) {
this_aspect_ratio = (float)x_size / (float)y_size;
}
}
}
if (!_aspect_2d.is_empty()) {
_aspect_2d.set_scale(1.0f / this_aspect_ratio, 1.0f, 1.0f);
}
Cameras::iterator ci;
for (ci = _cameras.begin(); ci != _cameras.end(); ++ci) {
Lens *lens = (*ci)->get_lens();
if (lens != (Lens *)NULL) {
if (y_size != 0) {
lens->set_film_size(x_size, y_size);
} else {
lens->set_aspect_ratio(this_aspect_ratio);
}
}
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: WindowFramework::split_window // Function: WindowFramework::split_window
// Access: Public // Access: Public

View File

@ -96,6 +96,7 @@ public:
void next_anim_control(); void next_anim_control();
void set_anim_controls(bool enable); void set_anim_controls(bool enable);
INLINE bool get_anim_controls() const; INLINE bool get_anim_controls() const;
void adjust_aspect_ratio();
enum BackgroundType { enum BackgroundType {
BT_other = 0, BT_other = 0,

View File

@ -19,6 +19,8 @@
NotifyCategoryDecl(iphone, EXPCL_PANDAGL, EXPTP_PANDAGL); NotifyCategoryDecl(iphone, EXPCL_PANDAGL, EXPTP_PANDAGL);
extern ConfigVariableBool iphone_autorotate_view;
extern EXPCL_PANDAGL void init_libiphone(); extern EXPCL_PANDAGL void init_libiphone();
extern "C" EXPCL_PANDAGL int get_pipe_type_iphone(); extern "C" EXPCL_PANDAGL int get_pipe_type_iphone();

View File

@ -30,6 +30,12 @@ ConfigureFn(config_iphone) {
init_libiphone(); init_libiphone();
} }
ConfigVariableBool iphone_autorotate_view
("iphone-autorotate-view", true,
PRC_DESC("Set this true to enable the iphone application to rotate its "
"view automatically according to the phone's orientation, or "
"false for its view to remain fixed."));
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: init_libiphone // Function: init_libiphone
// Description: Initializes the library. This must be called at // Description: Initializes the library. This must be called at

View File

@ -12,11 +12,14 @@
// //
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <OpenGLES/EAGL.h> #import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h> #import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h> #import <OpenGLES/ES1/glext.h>
class IPhoneGraphicsWindow;
/* /*
This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass. This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass.
The view content is basically an EAGL surface you render your OpenGL scene into. The view content is basically an EAGL surface you render your OpenGL scene into.
@ -24,7 +27,10 @@ Note that setting the view non-opaque will only work if the EAGL surface has an
*/ */
@interface EAGLView : UIView { @interface EAGLView : UIView {
@public
IPhoneGraphicsWindow *_window;
@private @private
/* The pixel dimensions of the backbuffer */ /* The pixel dimensions of the backbuffer */
GLint backingWidth; GLint backingWidth;
GLint backingHeight; GLint backingHeight;

View File

@ -12,10 +12,14 @@
// //
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
#import "EAGLView.h"
#import <QuartzCore/QuartzCore.h> #import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGLDrawable.h> #import <OpenGLES/EAGLDrawable.h>
#import "EAGLView.h" #include "pandabase.h"
#include "pnotify.h"
#include "iPhoneGraphicsWindow.h"
#define USE_DEPTH_BUFFER 1 #define USE_DEPTH_BUFFER 1
@ -42,7 +46,6 @@
- (id)initWithFrame:(CGRect)frame { - (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) { if ((self = [super initWithFrame:frame])) {
// Get the layer // Get the layer
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
@ -57,6 +60,10 @@
[self release]; [self release];
return nil; return nil;
} }
_window = NULL;
viewFramebuffer = 0;
viewRenderbuffer = 0;
depthRenderbuffer = 0;
} }
return self; return self;
} }
@ -71,12 +78,14 @@
[EAGLContext setCurrentContext:context]; [EAGLContext setCurrentContext:context];
[self destroyFramebuffer]; [self destroyFramebuffer];
[self createFramebuffer]; [self createFramebuffer];
// [self drawView];
if (_window != NULL) {
_window->rotate_window();
}
} }
- (BOOL)createFramebuffer { - (BOOL)createFramebuffer {
glGenFramebuffersOES(1, &viewFramebuffer); glGenFramebuffersOES(1, &viewFramebuffer);
glGenRenderbuffersOES(1, &viewRenderbuffer); glGenRenderbuffersOES(1, &viewRenderbuffer);
@ -112,11 +121,15 @@
- (void)destroyFramebuffer { - (void)destroyFramebuffer {
if (viewFramebuffer != 0) {
glDeleteFramebuffersOES(1, &viewFramebuffer); glDeleteFramebuffersOES(1, &viewFramebuffer);
viewFramebuffer = 0; viewFramebuffer = 0;
}
if (viewRenderbuffer != 0) {
glDeleteRenderbuffersOES(1, &viewRenderbuffer); glDeleteRenderbuffersOES(1, &viewRenderbuffer);
viewRenderbuffer = 0; viewRenderbuffer = 0;
}
if (depthRenderbuffer) { if (depthRenderbuffer) {
glDeleteRenderbuffersOES(1, &depthRenderbuffer); glDeleteRenderbuffersOES(1, &depthRenderbuffer);

View File

@ -17,10 +17,12 @@
#include "pandabase.h" #include "pandabase.h"
#include "graphicsPipe.h" #include "graphicsPipe.h"
#include "pset.h"
#import "viewController.h" #import "viewController.h"
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
class IPhoneGraphicsStateGuardian; class IPhoneGraphicsStateGuardian;
class IPhoneGraphicsWindow;
class PNMImage; class PNMImage;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -38,6 +40,8 @@ public:
static PT(GraphicsPipe) pipe_constructor(); static PT(GraphicsPipe) pipe_constructor();
virtual PreferredWindowThread get_preferred_window_thread() const; virtual PreferredWindowThread get_preferred_window_thread() const;
void rotate_windows();
protected: protected:
virtual PT(GraphicsOutput) make_output(const string &name, virtual PT(GraphicsOutput) make_output(const string &name,
const FrameBufferProperties &fb_prop, const FrameBufferProperties &fb_prop,
@ -53,6 +57,9 @@ public:
UIWindow *_window; UIWindow *_window;
ControllerDemoViewController *_view_controller; ControllerDemoViewController *_view_controller;
typedef pset<IPhoneGraphicsWindow *> GraphicsWindows;
GraphicsWindows _graphics_windows;
private: private:
static IPhoneGraphicsPipe *_global_ptr; static IPhoneGraphicsPipe *_global_ptr;

View File

@ -33,7 +33,7 @@ IPhoneGraphicsPipe() {
CGRect screenBounds = [ [ UIScreen mainScreen ] bounds ]; CGRect screenBounds = [ [ UIScreen mainScreen ] bounds ];
_window = [ [ UIWindow alloc ] initWithFrame: screenBounds ]; _window = [ [ UIWindow alloc ] initWithFrame: screenBounds ];
_view_controller = [ [ ControllerDemoViewController alloc ] init ]; _view_controller = [ [ ControllerDemoViewController alloc ] initWithPipe: this ];
[ _window addSubview:_view_controller.view ]; [ _window addSubview:_view_controller.view ];
[ _window makeKeyAndVisible ]; [ _window makeKeyAndVisible ];
@ -97,6 +97,22 @@ IPhoneGraphicsPipe::get_preferred_window_thread() const {
return PWT_app; return PWT_app;
} }
////////////////////////////////////////////////////////////////////
// Function: IPhoneGraphicsPipe::rotate_windows
// Access: Public, Virtual
// Description: Called in response to an orientation change event,
// this tells all of the windows created on the pipe to
// resize themselves according to the new orientation.
////////////////////////////////////////////////////////////////////
void IPhoneGraphicsPipe::
rotate_windows() {
GraphicsWindows::iterator gwi;
for (gwi = _graphics_windows.begin(); gwi != _graphics_windows.end(); ++gwi) {
IPhoneGraphicsWindow *win = (*gwi);
win->rotate_window();
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: IPhoneGraphicsPipe::make_output // Function: IPhoneGraphicsPipe::make_output

View File

@ -44,6 +44,9 @@ public:
virtual void process_events(); virtual void process_events();
virtual void set_properties_now(WindowProperties &properties); virtual void set_properties_now(WindowProperties &properties);
virtual void clear_pipe();
void rotate_window();
protected: protected:
virtual void close_window(); virtual void close_window();

View File

@ -17,10 +17,10 @@
// gets included later (in particular, TCP_NODELAY must not be a // gets included later (in particular, TCP_NODELAY must not be a
// #define symbol for these headers to be included properly). // #define symbol for these headers to be included properly).
//#include <ApplicationServices/ApplicationServices.h>
#include <UIKit/UIKit.h> #include <UIKit/UIKit.h>
#include "iPhoneGraphicsWindow.h" #include "iPhoneGraphicsWindow.h"
#include "dcast.h"
#include "config_iphone.h" #include "config_iphone.h"
#include "iPhoneGraphicsPipe.h" #include "iPhoneGraphicsPipe.h"
#include "pStatTimer.h" #include "pStatTimer.h"
@ -53,6 +53,9 @@ IPhoneGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
GraphicsOutput *host) : GraphicsOutput *host) :
GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host) GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
{ {
IPhoneGraphicsPipe *ipipe;
DCAST_INTO_V(ipipe, _pipe);
ipipe->_graphics_windows.insert(this);
_gl_view = nil; _gl_view = nil;
GraphicsWindowInputDevice device = GraphicsWindowInputDevice device =
@ -196,23 +199,24 @@ close_window() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool IPhoneGraphicsWindow:: bool IPhoneGraphicsWindow::
open_window() { open_window() {
iphone_cat.info() << "open_window\n";
nassertr(_gsg == (GraphicsStateGuardian *)NULL, false); nassertr(_gsg == (GraphicsStateGuardian *)NULL, false);
_gl_view = [ [ EAGLView alloc ] initWithFrame: _gl_view = [ [ EAGLView alloc ] initWithFrame:
[ [ UIScreen mainScreen ] applicationFrame ] [ [ UIScreen mainScreen ] applicationFrame ]
]; ];
_gl_view->_window = this;
IPhoneGraphicsPipe *iphonepipe = DCAST(IPhoneGraphicsPipe, _pipe); IPhoneGraphicsPipe *iphonepipe = DCAST(IPhoneGraphicsPipe, _pipe);
nassertr(iphonepipe != NULL, false); nassertr(iphonepipe != NULL, false);
iphonepipe->_view_controller.view = _gl_view; iphonepipe->_view_controller.view = _gl_view;
[ _gl_view layoutSubviews ]; [ _gl_view layoutSubviews ];
WindowProperties req_properties = _properties;
_gsg = new IPhoneGraphicsStateGuardian(_engine, _pipe, NULL); _gsg = new IPhoneGraphicsStateGuardian(_engine, _pipe, NULL);
CGRect bounds = [_gl_view bounds];
_properties.set_size(bounds.size.width, bounds.size.height);
_properties.set_foreground(true); _properties.set_foreground(true);
_properties.set_minimized(false); _properties.set_minimized(false);
_properties.set_open(true); _properties.set_open(true);
@ -262,3 +266,35 @@ set_properties_now(WindowProperties &properties) {
GraphicsWindow::set_properties_now(properties); GraphicsWindow::set_properties_now(properties);
} }
////////////////////////////////////////////////////////////////////
// Function: IPhoneGraphicsWindow::clear_pipe
// Access: Protected, Virtual
// Description: Sets the window's _pipe pointer to NULL; this is
// generally called only as a precursor to deleting the
// window.
////////////////////////////////////////////////////////////////////
void IPhoneGraphicsWindow::
clear_pipe() {
IPhoneGraphicsPipe *ipipe;
DCAST_INTO_V(ipipe, _pipe);
ipipe->_graphics_windows.erase(this);
GraphicsWindow::clear_pipe();
}
////////////////////////////////////////////////////////////////////
// Function: IPhoneGraphicsWindow::rotate_window
// Access: Public, Virtual
// Description: Called in response to an orientation change event,
// this tells the window to resize itself according to
// the new orientation.
////////////////////////////////////////////////////////////////////
void IPhoneGraphicsWindow::
rotate_window() {
CGRect bounds = [_gl_view bounds];
WindowProperties properties;
properties.set_size(bounds.size.width, bounds.size.height);
system_changed_properties(properties);
}

View File

@ -108,7 +108,7 @@ signal_handler(int i) {
// load the models. We have this funny deferred-window technique, // load the models. We have this funny deferred-window technique,
// so SpringBoard will see that the app has fully initialized and // so SpringBoard will see that the app has fully initialized and
// won't kill us if we take a while loading models. // won't kill us if we take a while loading models.
WindowFramework *window = framework.open_window(); framework.open_window();
startup = 1; startup = 1;
} else if (startup == 1) { } else if (startup == 1) {
@ -148,9 +148,14 @@ signal_handler(int i) {
} }
} }
- (void)dealloc { - (void)applicationWillTerminate:
(UIApplication *)application
{
[self stopAnimation]; [self stopAnimation];
framework.close_framework(); framework.close_framework();
}
- (void)dealloc {
[super dealloc]; [super dealloc];
} }

View File

@ -17,8 +17,13 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <UIKit/UITextView.h> #import <UIKit/UITextView.h>
class IPhoneGraphicsPipe;
@interface ControllerDemoViewController : UIViewController { @interface ControllerDemoViewController : UIViewController {
// NSString *helloWorld, *woahDizzy;
@private
IPhoneGraphicsPipe *_pipe;
} }
- (id)initWithPipe: (IPhoneGraphicsPipe *)pipe;
@end @end

View File

@ -14,48 +14,29 @@
#import "viewController.h" #import "viewController.h"
#include "pnotify.h" #include "pnotify.h"
#include "iPhoneGraphicsPipe.h"
#include "config_iphone.h"
@implementation ControllerDemoViewController @implementation ControllerDemoViewController
- (id)init { - (id)initWithPipe:
(IPhoneGraphicsPipe *)pipe
{
self = [ super init ]; self = [ super init ];
_pipe = pipe;
/*
if (self != nil) {
helloWorld = [ [ NSString alloc ] initWithString: @"Hello, World!" ];
woahDizzy = [ [ NSString alloc ] initWithString: @"Woah, I'm Dizzy!" ];
}
*/
return self; return self;
} }
- (void)loadView {
[ super loadView ];
/*
glView = [ [ EAGLView alloc ] initWithFrame:
[ [ UIScreen mainScreen ] applicationFrame ]
];
// [ glView startAnimation ];
self.view = glView;
*/
}
/*
- (BOOL)shouldAutorotateToInterfaceOrientation: - (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation (UIInterfaceOrientation)interfaceOrientation
{ {
return YES; return iphone_autorotate_view;
} }
*/
- (void)didRotateFromInterfaceOrientation: - (void)didRotateFromInterfaceOrientation:
(UIInterfaceOrientation)fromInterfaceOrientation (UIInterfaceOrientation)fromInterfaceOrientation
{ {
_pipe->rotate_windows();
} }
- (void)viewDidLoad { - (void)viewDidLoad {
@ -70,10 +51,6 @@
} }
- (void)dealloc { - (void)dealloc {
/* Here, the objects we've allocated are released */
//[ helloWorld release ];
// [ woahDizzy release ];
// [ glView release ];
[ super dealloc ]; [ super dealloc ];
} }