Sources/Classes/Application/View/Toolkit/OpenGLView.m
/* |
File: OpenGLView.m |
Abstract: |
OpenGL view class with text labels and added utility methods. |
Version: 1.2 |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple |
Inc. ("Apple") in consideration of your agreement to the following |
terms, and your use, installation, modification or redistribution of |
this Apple software constitutes acceptance of these terms. If you do |
not agree with these terms, please do not use, install, modify or |
redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and |
subject to these terms, Apple grants you a personal, non-exclusive |
license, under Apple's copyrights in this original Apple software (the |
"Apple Software"), to use, reproduce, modify and redistribute the Apple |
Software, with or without modifications, in source and/or binary forms; |
provided that if you redistribute the Apple Software in its entirety and |
without modifications, you must retain this notice and the following |
text and disclaimers in all such redistributions of the Apple Software. |
Neither the name, trademarks, service marks or logos of Apple Inc. may |
be used to endorse or promote products derived from the Apple Software |
without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or |
implied, are granted by Apple herein, including but not limited to any |
patent rights that may be infringed by your derivative works or by other |
works in which the Apple Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
Copyright (C) 2013 Apple Inc. All Rights Reserved. |
*/ |
//--------------------------------------------------------------------------------------- |
//--------------------------------------------------------------------------------------- |
#import "QTMediaSampleNotifications.h" |
#import "OpenGLView.h" |
//--------------------------------------------------------------------------------------- |
//--------------------------------------------------------------------------------------- |
enum OpenGLViewFlags |
{ |
kOpenGLViewResized = 0, |
kOpenGLViewStopObjectRotation, |
kOpenGLViewCaptureEnabled, |
kOpenGLViewCaptureWriting, |
kOpenGLViewDisplayCounter, |
kOpenGLViewDisplayPrefTimer, |
kOpenGLViewDisplayRenderer, |
kOpenGLViewDisplayBounds |
}; |
typedef enum OpenGLViewFlags OpenGLViewFlags; |
//--------------------------------------------------------------------------------------- |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
//--------------------------------------------------------------------------------------- |
@implementation OpenGLView |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
#pragma mark Post Notification |
//--------------------------------------------------------------------------------------- |
- (void) postOpenGLViewNotifications |
{ |
[[NSNotificationCenter defaultCenter] addObserver:self |
selector:@selector(viewWillTerminate:) |
name:@"NSApplicationWillTerminateNotification" |
object:NSApp]; |
[[NSNotificationCenter defaultCenter] addObserver:self |
selector:@selector(suspendObjectRotation:) |
name:QTMediaSampleAuthorIsSuspended |
object:nil]; |
[[NSNotificationCenter defaultCenter] addObserver:self |
selector:@selector(resumeObjectRotation:) |
name:QTMediaSampleAuthorIsResumed |
object:nil]; |
} // postOpenGLViewNotifications |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
#pragma mark Labels Initialization |
//--------------------------------------------------------------------------------------- |
- (void) initPrefTimerLabel:(const NSRect *)theBounds |
textColor:(NSColor *)theTextColor |
boxColor:(NSColor *)theBoxColor |
borderColor:(NSColor *)theBorderColor |
{ |
NSPoint prefTimerInfoCoordinates = NSMakePoint(10.0f, 32.0f); |
mpLabelPrefTimer = [[OpenGLPrefTimerLabel alloc] initLabelWithFormat:nil |
fontName:@"Helvetica" |
fontSize:20.0f |
textColor:theTextColor |
boxColor:theBoxColor |
borderColor:theBorderColor |
coordinates:&prefTimerInfoCoordinates |
bounds:theBounds]; |
} // initPrefTimerLabel |
//--------------------------------------------------------------------------------------- |
- (void) initRendererLabel:(const NSRect *)theBounds |
textColor:(NSColor *)theTextColor |
boxColor:(NSColor *)theBoxColor |
borderColor:(NSColor *)theBorderColor |
{ |
NSRect bounds = [self bounds]; |
NSPoint infoCoordinates = NSMakePoint(10.0f, bounds.size.height - 52.0f); |
mpLabelRenderer = [[OpenGLRendererLabel alloc] initLabelWithFontName:@"Helvetica" |
fontSize:12.0 |
textColor:theTextColor |
boxColor:theBoxColor |
borderColor:theBorderColor |
coordinates:&infoCoordinates |
bounds:theBounds]; |
} // initRendererLabel |
//--------------------------------------------------------------------------------------- |
- (void) initViewBoundsLabel:(const NSRect *)theBounds |
textColor:(NSColor *)theTextColor |
boxColor:(NSColor *)theBoxColor |
borderColor:(NSColor *)theBorderColor |
{ |
NSPoint infoCoordinates = NSMakePoint(10.0f, 10.0f); |
mpLabelViewBounds = [[OpenGLViewBoundsLabel alloc] initLabelWithFormat:nil |
fontName:@"Helvetica" |
fontSize:12.0 |
textColor:theTextColor |
boxColor:theBoxColor |
borderColor:theBorderColor |
coordinates:&infoCoordinates |
bounds:theBounds]; |
} // initViewBoundsLabel |
//--------------------------------------------------------------------------------------- |
- (void) initLabels:(const NSRect *)theBounds |
{ |
NSColor *textColor = [NSColor colorWithDeviceRed:1.0f |
green:1.0f |
blue:1.0f |
alpha:1.0f]; |
NSColor *boxColor = [NSColor colorWithDeviceRed:0.5f |
green:0.5f |
blue:0.5f |
alpha:0.5f]; |
NSColor *borderColor = [NSColor colorWithDeviceRed:0.8f |
green:0.8f |
blue:0.8f |
alpha:0.8f]; |
[self initPrefTimerLabel:theBounds |
textColor:textColor |
boxColor:boxColor |
borderColor:borderColor]; |
[self initRendererLabel:theBounds |
textColor:textColor |
boxColor:boxColor |
borderColor:borderColor]; |
[self initViewBoundsLabel:theBounds |
textColor:textColor |
boxColor:boxColor |
borderColor:borderColor]; |
} // initLabels |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
#pragma mark Designated initializer |
//--------------------------------------------------------------------------------------- |
// |
// Create an OpenGL Context to use - i.e. init the animated view superclass |
// |
//--------------------------------------------------------------------------------------- |
- (id) initWithFrame:(NSRect)theFrame |
pixelFormat:(NSOpenGLPixelFormat *)thePixelFormat |
{ |
self = [super initWithFrame:theFrame |
pixelFormat:thePixelFormat]; |
if( self ) |
{ |
// Instantiate label objects for displaying |
// performance timer and view bounds |
[self initLabels:&theFrame]; |
mpSnapshot = nil; |
mpCapture = nil; |
mpDirectory = nil; |
m_ViewFlags[kOpenGLViewResized] = NO; |
m_ViewFlags[kOpenGLViewStopObjectRotation] = NO; |
m_ViewFlags[kOpenGLViewCaptureEnabled] = NO; |
m_ViewFlags[kOpenGLViewCaptureWriting] = NO; |
m_ViewFlags[kOpenGLViewDisplayPrefTimer] = YES; |
m_ViewFlags[kOpenGLViewDisplayRenderer] = YES; |
m_ViewFlags[kOpenGLViewDisplayBounds] = YES; |
[self postOpenGLViewNotifications]; |
} // if |
return( self ); |
} // initWithFrame |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
#pragma mark Deallocating Resources |
//--------------------------------------------------------------------------------------- |
- (void) releaseOpenGLViewCapture |
{ |
if( mpCapture ) |
{ |
[mpCapture release]; |
mpCapture = nil; |
} // if |
} // releaseOpenGLViewCapture |
//--------------------------------------------------------------------------------------- |
- (void) releaseOpenGLViewSnapshot |
{ |
if( mpSnapshot ) |
{ |
[mpSnapshot release]; |
mpSnapshot = nil; |
} // if |
} // releaseOpenGLViewSnapshot |
//--------------------------------------------------------------------------------------- |
- (void) releaseOpenGLPrefTimerLabel |
{ |
if( mpLabelPrefTimer ) |
{ |
[mpLabelPrefTimer release]; |
mpLabelPrefTimer = nil; |
} // if |
} // releaseOpenGLPrefTimerLabel |
//--------------------------------------------------------------------------------------- |
- (void) releaseOpenGLRendererLabel |
{ |
if( mpLabelRenderer ) |
{ |
[mpLabelRenderer release]; |
mpLabelRenderer = nil; |
} // if |
} // releaseOpenGLRendererLabel |
//--------------------------------------------------------------------------------------- |
- (void) releaseOpenGLViewBoundsLabel |
{ |
if( mpLabelViewBounds ) |
{ |
[mpLabelViewBounds release]; |
mpLabelViewBounds = nil; |
} // if |
} // releaseOpenGLViewBoundsLabel |
//--------------------------------------------------------------------------------------- |
- (void) releaseMovieDirectoryPathname |
{ |
if( mpDirectory ) |
{ |
[mpDirectory release]; |
mpDirectory = nil; |
} // if |
} // releaseMovieDirectoryPathname |
//--------------------------------------------------------------------------------------- |
- (void) cleanUpOpenGLView |
{ |
// Release the renderer's label |
[self releaseOpenGLRendererLabel]; |
// Release the view bounds' label |
[self releaseOpenGLViewBoundsLabel]; |
// Release perf timer's label |
[self releaseOpenGLPrefTimerLabel]; |
// Release the view snapshot object |
[self releaseOpenGLViewSnapshot]; |
// Release the view capture object |
[self releaseOpenGLViewCapture]; |
// Release the directory pathname string |
[self releaseMovieDirectoryPathname]; |
} // cleanUpOpenGLView |
//--------------------------------------------------------------------------------------- |
- (void) dealloc |
{ |
[self cleanUpOpenGLView]; |
// Dealloc the superclass |
[super dealloc]; |
} // dealloc |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
#pragma mark Accessor |
//--------------------------------------------------------------------------------------- |
- (BOOL) viewResized |
{ |
return( m_ViewFlags[kOpenGLViewResized] ); |
} // viewResized |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
#pragma mark Capturing from a View |
//--------------------------------------------------------------------------------------- |
- (void) viewCaptureCreate |
{ |
if( mpCapture == nil ) |
{ |
NSRect bounds = [self bounds]; |
mpCapture = [[OpenGLViewCapture alloc] initViewCaptureWithFrame:&bounds |
directory:mpDirectory |
prefix:@"capture"]; |
} // if |
else |
{ |
[mpCapture setMovieDirectory:mpDirectory]; |
} // else |
if( mpCapture ) |
{ |
m_ViewFlags[kOpenGLViewCaptureEnabled] = YES; |
} // if |
} // viewCaptureCreate |
//--------------------------------------------------------------------------------------- |
- (void) viewCaptureEnable:(NSString *)theMovieDirectory |
{ |
if( theMovieDirectory ) |
{ |
[self releaseMovieDirectoryPathname]; |
if( mpDirectory == nil ) |
{ |
mpDirectory = [[NSString alloc] initWithString:theMovieDirectory]; |
} // if |
[self viewCaptureCreate]; |
} // if |
} // viewCaptureEnable |
//--------------------------------------------------------------------------------------- |
- (void) viewCaptureSetDirectory:(NSString *)theMovieDirectory |
{ |
[mpCapture setMovieDirectory:theMovieDirectory]; |
} // viewCaptureSetDirectory |
//--------------------------------------------------------------------------------------- |
- (void) viewCaptureDisable |
{ |
[self releaseOpenGLViewCapture]; |
if( mpCapture == nil ) |
{ |
m_ViewFlags[kOpenGLViewCaptureEnabled] = NO; |
} // if |
} // viewCaptureDisable |
//--------------------------------------------------------------------------------------- |
- (void) viewCaptureStart |
{ |
m_ViewFlags[kOpenGLViewStopObjectRotation] = NO; |
[mpCapture start]; |
} // viewCaptureRestart |
//--------------------------------------------------------------------------------------- |
- (void) viewCaptureStop |
{ |
m_ViewFlags[kOpenGLViewStopObjectRotation] = YES; |
[mpCapture stop]; |
} // viewCaptureStop |
//--------------------------------------------------------------------------------------- |
- (void) viewCapturePause |
{ |
[mpCapture pause]; |
} // viewCapturePause |
//--------------------------------------------------------------------------------------- |
- (NSUInteger) viewCaptureCount |
{ |
return( [mpCapture count] ); |
} // viewCaptureCount |
//--------------------------------------------------------------------------------------- |
- (BOOL) viewCaptureIsSuspended |
{ |
return( [mpCapture isSuspended] ); |
} // viewCaptureIsSuspended |
//--------------------------------------------------------------------------------------- |
- (void) viewCaptureEnableColorCorrection |
{ |
[mpCapture enableColorCorrection]; |
} // viewCaptureEnableColorCorrection |
//--------------------------------------------------------------------------------------- |
- (void) viewCaptureDisableColorCorrection |
{ |
[mpCapture disableColorCorrection]; |
} // viewCaptureDisableColorCorrection |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
#pragma mark Capturing from a View |
//--------------------------------------------------------------------------------------- |
- (void) viewSnapshot:(NSString *)theDocPath |
type:(NSNumber *)theDocFormat |
compression:(NSNumber *)theDocCompression |
title:(NSString *)theDocTitle |
author:(NSString *)theDocAuthor |
subject:(NSString *)theDocSubject |
creator:(NSString *)theDocCreator |
{ |
if( mpSnapshot == nil ) |
{ |
NSRect frame = [self bounds]; |
mpSnapshot = [[OpenGLViewSnapshot alloc] initViewSnapshotWithFrame:&frame |
view:self]; |
} // if |
[mpSnapshot setDocumentTitle:theDocTitle]; |
[mpSnapshot setDocumentAuthor:theDocAuthor]; |
[mpSnapshot setDocumentSubject:theDocSubject]; |
[mpSnapshot setDocumentCreator:theDocCreator]; |
if( theDocFormat ) |
{ |
[mpSnapshot setFormat:[theDocFormat unsignedIntValue]]; |
} // if |
if( theDocCompression ) |
{ |
[mpSnapshot setCompression:[theDocCompression floatValue]]; |
} // if |
[mpSnapshot saveAs:theDocPath]; |
} // viewSnapshot |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
#pragma mark Showing/Hiding Labels |
//--------------------------------------------------------------------------------------- |
- (void) prefTimerDisplayLabel:(const BOOL)theDisplayFlag |
{ |
m_ViewFlags[kOpenGLViewDisplayPrefTimer] = theDisplayFlag; |
} // prefTimerLabelSetDisplay |
//--------------------------------------------------------------------------------------- |
- (void) rendererDisplayLabel:(const BOOL)theDisplayFlag |
{ |
m_ViewFlags[kOpenGLViewDisplayRenderer] = theDisplayFlag; |
} // rendererLabelSetDisplay |
//--------------------------------------------------------------------------------------- |
- (void) viewBoundsDisplayLabel:(const BOOL)theDisplayFlag |
{ |
m_ViewFlags[kOpenGLViewDisplayBounds] = theDisplayFlag; |
} // viewBoundsSetDisplay |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
#pragma mark Preformance Timer Utilities |
//--------------------------------------------------------------------------------------- |
- (void) prefTimerEnable |
{ |
[mpLabelPrefTimer labelSetNeedsDisplay:YES]; |
} // prefTimerEnable |
//--------------------------------------------------------------------------------------- |
- (void) prefTimerDisable |
{ |
[mpLabelPrefTimer labelSetNeedsDisplay:NO]; |
} // prefTimerDisable |
//--------------------------------------------------------------------------------------- |
- (void) prefTimerMoveTo:(const NSPoint *)thePoint |
{ |
[mpLabelPrefTimer moveTo:thePoint]; |
} // prefTimerMoveTo |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
#pragma mark View Updates |
//--------------------------------------------------------------------------------------- |
// |
// Handles resizing of OpenGL view, if the window dimensions change, window dimensions |
// update, viewports reset, and projection matrix update. |
// |
//--------------------------------------------------------------------------------------- |
- (void) viewResize |
{ |
m_ViewFlags[kOpenGLViewResized] = [self viewUpdate]; |
if( m_ViewFlags[kOpenGLViewResized] ) |
{ |
// OpenGL text objects needs to know the view bounds |
// have changed as well. |
NSRect viewBounds = [self viewBounds]; |
// Get a new backing store for our view's snapshot |
[mpSnapshot setFrame:&viewBounds]; |
// Resize the capture object |
if( m_ViewFlags[kOpenGLViewCaptureEnabled] ) |
{ |
[mpCapture setBounds:&viewBounds]; |
} // if |
// Notify all labels that their bounds have changed |
[mpLabelViewBounds viewSetBounds:&viewBounds]; |
[mpLabelRenderer viewSetBounds:&viewBounds]; |
[mpLabelPrefTimer viewSetBounds:&viewBounds]; |
} // if |
} // viewResize |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
#pragma mark Draw Utilities |
//--------------------------------------------------------------------------------------- |
- (void) drawBegin |
{ |
// Make the OpenGL context the current context |
[self contextMakeCurrent]; |
// Forces projection matrix update (does test for size changes) |
[self viewResize]; |
// Clear our drawable |
[self viewClear]; |
} // drawBegin |
//--------------------------------------------------------------------------------------- |
// |
// Display the view bounds label |
// |
//--------------------------------------------------------------------------------------- |
- (void) drawViewBoundsLabel |
{ |
if( m_ViewFlags[kOpenGLViewDisplayBounds] ) |
{ |
[mpLabelViewBounds labelDraw]; |
} // if |
} // drawViewBoundsLabel |
//--------------------------------------------------------------------------------------- |
// |
// Display the pref timer label |
// |
//--------------------------------------------------------------------------------------- |
- (void) drawPrefTimerLabel |
{ |
if( m_ViewFlags[kOpenGLViewDisplayPrefTimer] ) |
{ |
[mpLabelPrefTimer labelSetNeedsUpdate:[self rotation]]; |
[mpLabelPrefTimer labelDraw]; |
} // if |
} // drawPrefTimerLabel |
//--------------------------------------------------------------------------------------- |
// |
// Display the renderer label |
// |
//--------------------------------------------------------------------------------------- |
- (void) drawRendererLabel |
{ |
if( m_ViewFlags[kOpenGLViewDisplayRenderer] ) |
{ |
[mpLabelRenderer labelDraw]; |
} // if |
} // drawRendererLabel |
//--------------------------------------------------------------------------------------- |
- (void) drawEnd |
{ |
// Take a snapshot of the view |
[mpSnapshot snapshot]; |
// Start recording from a frame |
m_ViewFlags[kOpenGLViewCaptureWriting] = [mpCapture capture]; |
// Draw the view bounds |
[self drawViewBoundsLabel]; |
// Draw the pref timer |
[self drawPrefTimerLabel]; |
// Draw the renderer's info |
[self drawRendererLabel]; |
// Flush the current context |
[self contextFlushBuffer]; |
} // drawEnd |
//--------------------------------------------------------------------------------------- |
- (BOOL) isWriting |
{ |
return m_ViewFlags[kOpenGLViewCaptureWriting]; |
} // isWriting |
//--------------------------------------------------------------------------------------- |
#pragma mark - |
#pragma mark Notification |
//--------------------------------------------------------------------------------------- |
// |
// It's important to clean up our rendering objects before we terminate -- Cocoa will |
// not specifically release everything on application termination, so we explicitly |
// call our clean up routine ourselves. |
// |
//--------------------------------------------------------------------------------------- |
- (void) viewWillTerminate:(NSNotification *)notification |
{ |
[self cleanUpOpenGLView]; |
} // viewWillTerminate |
//--------------------------------------------------------------------------------------- |
// |
// When flushing media author queue one needs to stop object rotation. |
// |
//--------------------------------------------------------------------------------------- |
- (void) suspendObjectRotation:(NSNotification *)notification |
{ |
if( !m_ViewFlags[kOpenGLViewStopObjectRotation] ) |
{ |
[self rotationStop]; |
m_ViewFlags[kOpenGLViewStopObjectRotation] = YES; |
} // if |
} // suspendObjectRotation |
//--------------------------------------------------------------------------------------- |
// |
// When media sample authoring is restarted, one needs to restart object rotation. |
// |
//--------------------------------------------------------------------------------------- |
- (void) resumeObjectRotation:(NSNotification *)notification |
{ |
if( m_ViewFlags[kOpenGLViewStopObjectRotation] && !m_ViewFlags[kOpenGLViewCaptureWriting] ) |
{ |
[self rotationStart]; |
m_ViewFlags[kOpenGLViewStopObjectRotation] = NO; |
} // if |
} // resumeObjectRotation |
//--------------------------------------------------------------------------------------- |
@end |
//--------------------------------------------------------------------------------------- |
//--------------------------------------------------------------------------------------- |
Copyright © 2013 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2013-01-02