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::
do_remove_window(GraphicsOutput *window, Thread *current_thread) {
PT(GraphicsPipe) pipe = window->get_pipe();
window->_pipe = (GraphicsPipe *)NULL;
window->clear_pipe();
if (!_windows_sorted) {
do_resort_windows();

View File

@ -974,7 +974,7 @@ set_close_now() {
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::reset_window
// Access: Protected, Virtual
// Description: resets the window framebuffer from its derived
// Description: Resets the window framebuffer from its derived
// children. Does nothing here.
////////////////////////////////////////////////////////////////////
void GraphicsOutput::
@ -983,6 +983,18 @@ reset_window(bool swapchain) {
<< "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
// Access: Public, Virtual

View File

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

View File

@ -1492,6 +1492,7 @@ event_window_event(const Event *event, void *data) {
} else {
if (!win->is_valid()) {
// The window has been closed.
int window_index = self->find_window(win);
while (window_index != -1) {
self->close_window(window_index);
@ -1507,6 +1508,13 @@ event_window_event(const Event *event, void *data) {
<< "Last window was closed by user.\n";
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
// Access: Public

View File

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

View File

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

View File

@ -30,6 +30,12 @@ ConfigureFn(config_iphone) {
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
// Description: Initializes the library. This must be called at

View File

@ -12,30 +12,36 @@
//
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#import <UIKit/UIKit.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
class IPhoneGraphicsWindow;
/*
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.
Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel.
*/
@interface EAGLView : UIView {
@public
IPhoneGraphicsWindow *_window;
@private
/* The pixel dimensions of the backbuffer */
GLint backingWidth;
GLint backingHeight;
EAGLContext *context;
/* OpenGL names for the renderbuffer and framebuffers used to render to this view */
GLuint viewRenderbuffer, viewFramebuffer;
/* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
GLuint depthRenderbuffer;
/* The pixel dimensions of the backbuffer */
GLint backingWidth;
GLint backingHeight;
EAGLContext *context;
/* OpenGL names for the renderbuffer and framebuffers used to render to this view */
GLuint viewRenderbuffer, viewFramebuffer;
/* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
GLuint depthRenderbuffer;
}
- (void)presentView;

View File

@ -12,10 +12,14 @@
//
////////////////////////////////////////////////////////////////////
#import "EAGLView.h"
#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGLDrawable.h>
#import "EAGLView.h"
#include "pandabase.h"
#include "pnotify.h"
#include "iPhoneGraphicsWindow.h"
#define USE_DEPTH_BUFFER 1
@ -42,86 +46,95 @@
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Get the layer
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
if ((self = [super initWithFrame:frame])) {
// Get the layer
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = YES;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
return nil;
}
eaglLayer.opaque = YES;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
return nil;
}
return self;
_window = NULL;
viewFramebuffer = 0;
viewRenderbuffer = 0;
depthRenderbuffer = 0;
}
return self;
}
- (void)presentView {
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
- (void)layoutSubviews {
[EAGLContext setCurrentContext:context];
[self destroyFramebuffer];
[self createFramebuffer];
// [self drawView];
[EAGLContext setCurrentContext:context];
[self destroyFramebuffer];
[self createFramebuffer];
if (_window != NULL) {
_window->rotate_window();
}
}
- (BOOL)createFramebuffer {
glGenFramebuffersOES(1, &viewFramebuffer);
glGenRenderbuffersOES(1, &viewRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glGenFramebuffersOES(1, &viewFramebuffer);
glGenRenderbuffersOES(1, &viewRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
if (USE_DEPTH_BUFFER) {
glGenRenderbuffersOES(1, &depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
if (USE_DEPTH_BUFFER) {
glGenRenderbuffersOES(1, &depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
}
if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
return NO;
}
// Make sure the buffer is initially cleared, so we don't look at
// whatever happened to be in the framebuffer.
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
return YES;
}
if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
return NO;
}
// Make sure the buffer is initially cleared, so we don't look at
// whatever happened to be in the framebuffer.
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
return YES;
}
- (void)destroyFramebuffer {
if (viewFramebuffer != 0) {
glDeleteFramebuffersOES(1, &viewFramebuffer);
viewFramebuffer = 0;
}
if (viewRenderbuffer != 0) {
glDeleteRenderbuffersOES(1, &viewRenderbuffer);
viewRenderbuffer = 0;
}
if(depthRenderbuffer) {
glDeleteRenderbuffersOES(1, &depthRenderbuffer);
depthRenderbuffer = 0;
}
if (depthRenderbuffer) {
glDeleteRenderbuffersOES(1, &depthRenderbuffer);
depthRenderbuffer = 0;
}
}
- (void)dealloc {

View File

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

View File

@ -33,7 +33,7 @@ IPhoneGraphicsPipe() {
CGRect screenBounds = [ [ UIScreen mainScreen ] bounds ];
_window = [ [ UIWindow alloc ] initWithFrame: screenBounds ];
_view_controller = [ [ ControllerDemoViewController alloc ] init ];
_view_controller = [ [ ControllerDemoViewController alloc ] initWithPipe: this ];
[ _window addSubview:_view_controller.view ];
[ _window makeKeyAndVisible ];
@ -97,6 +97,22 @@ IPhoneGraphicsPipe::get_preferred_window_thread() const {
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

View File

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

View File

@ -17,10 +17,10 @@
// gets included later (in particular, TCP_NODELAY must not be a
// #define symbol for these headers to be included properly).
//#include <ApplicationServices/ApplicationServices.h>
#include <UIKit/UIKit.h>
#include "iPhoneGraphicsWindow.h"
#include "dcast.h"
#include "config_iphone.h"
#include "iPhoneGraphicsPipe.h"
#include "pStatTimer.h"
@ -53,6 +53,9 @@ IPhoneGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
GraphicsOutput *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;
GraphicsWindowInputDevice device =
@ -196,23 +199,24 @@ close_window() {
////////////////////////////////////////////////////////////////////
bool IPhoneGraphicsWindow::
open_window() {
iphone_cat.info() << "open_window\n";
nassertr(_gsg == (GraphicsStateGuardian *)NULL, false);
_gl_view = [ [ EAGLView alloc ] initWithFrame:
[ [ UIScreen mainScreen ] applicationFrame ]
];
_gl_view->_window = this;
IPhoneGraphicsPipe *iphonepipe = DCAST(IPhoneGraphicsPipe, _pipe);
nassertr(iphonepipe != NULL, false);
iphonepipe->_view_controller.view = _gl_view;
[ _gl_view layoutSubviews ];
WindowProperties req_properties = _properties;
_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_minimized(false);
_properties.set_open(true);
@ -262,3 +266,35 @@ set_properties_now(WindowProperties &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,
// so SpringBoard will see that the app has fully initialized and
// won't kill us if we take a while loading models.
WindowFramework *window = framework.open_window();
framework.open_window();
startup = 1;
} else if (startup == 1) {
@ -148,9 +148,14 @@ signal_handler(int i) {
}
}
- (void)dealloc {
- (void)applicationWillTerminate:
(UIApplication *)application
{
[self stopAnimation];
framework.close_framework();
}
- (void)dealloc {
[super dealloc];
}

View File

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

View File

@ -14,66 +14,43 @@
#import "viewController.h"
#include "pnotify.h"
#include "iPhoneGraphicsPipe.h"
#include "config_iphone.h"
@implementation ControllerDemoViewController
- (id)init {
self = [ super init ];
/*
if (self != nil) {
helloWorld = [ [ NSString alloc ] initWithString: @"Hello, World!" ];
woahDizzy = [ [ NSString alloc ] initWithString: @"Woah, I'm Dizzy!" ];
}
*/
return self;
}
- (void)loadView {
[ super loadView ];
/*
glView = [ [ EAGLView alloc ] initWithFrame:
[ [ UIScreen mainScreen ] applicationFrame ]
];
// [ glView startAnimation ];
self.view = glView;
*/
}
/*
-(BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
- (id)initWithPipe:
(IPhoneGraphicsPipe *)pipe
{
return YES;
self = [ super init ];
_pipe = pipe;
return self;
}
*/
- (void)didRotateFromInterfaceOrientation:
(UIInterfaceOrientation)fromInterfaceOrientation
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return iphone_autorotate_view;
}
- (void)didRotateFromInterfaceOrientation:
(UIInterfaceOrientation)fromInterfaceOrientation
{
_pipe->rotate_windows();
}
- (void)viewDidLoad {
[ super viewDidLoad ];
/* Add custom post-load code here */
[ super viewDidLoad ];
/* Add custom post-load code here */
}
- (void)didReceiveMemoryWarning {
[ super didReceiveMemoryWarning ];
/* Add custom low-memory code here */
nout << "low-memory handler in view controller\n";
[ super didReceiveMemoryWarning ];
/* Add custom low-memory code here */
nout << "low-memory handler in view controller\n";
}
- (void)dealloc {
/* Here, the objects we've allocated are released */
//[ helloWorld release ];
// [ woahDizzy release ];
// [ glView release ];
[ super dealloc ];
}