00001 /* 00002 Copyright (c) 2010, The Barbarian Group 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that 00006 the following conditions are met: 00007 00008 * Redistributions of source code must retain the above copyright notice, this list of conditions and 00009 the following disclaimer. 00010 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 00011 the following disclaimer in the documentation and/or other materials provided with the distribution. 00012 00013 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 00014 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00015 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00016 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00017 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00018 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00019 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00020 POSSIBILITY OF SUCH DAMAGE. 00021 */ 00022 00023 #pragma once 00024 00025 #include "cinder/Cinder.h" 00026 #include "cinder/app/Renderer.h" 00027 #include "cinder/Vector.h" 00028 #include "cinder/app/MouseEvent.h" 00029 #include "cinder/app/KeyEvent.h" 00030 #include "cinder/app/FileDropEvent.h" 00031 #include "cinder/app/ResizeEvent.h" 00032 #include "cinder/Stream.h" 00033 #include "cinder/Display.h" 00034 #include "cinder/DataSource.h" 00035 #include "cinder/Timer.h" 00036 #include "cinder/Function.h" 00037 #if defined( CINDER_COCOA ) 00038 #if defined( CINDER_COCOA_TOUCH ) 00039 #if defined( __OBJC__ ) 00040 #import <UIKit/UIKit.h> 00041 #import <CoreFoundation/CoreFoundation.h> 00042 #endif 00043 #else 00044 #include <ApplicationServices/ApplicationServices.h> 00045 #endif 00046 #if defined __OBJC__ 00047 @class CinderView; 00048 @class AppImplCocoaRendererQuartz; 00049 @class AppImplCocoaRendererGl; 00050 #else 00051 class AppImplCocoaRendererQuartz; 00052 class AppImplCocoaRendererGl; 00053 #endif 00054 // class CinderView; 00055 #elif defined( CINDER_MSW ) 00056 #include "cinder/msw/OutputDebugStringStream.h" 00057 #endif 00058 00059 #include <vector> 00060 #include <algorithm> 00061 00062 namespace cinder { namespace app { 00063 00064 class App { 00065 public: 00066 class Settings { 00067 public: 00068 // whether or not the app should terminate prior to launching 00069 bool isPrepared() const { return !mShouldQuit; }; 00070 00072 void setWindowSize( int aWindowSizeX, int aWindowSizeY ); 00073 00075 void setFrameRate( float aFrameRate ); 00076 00078 void enablePowerManagement( bool aPowerManagement = true ); 00079 00081 bool isFullScreen() const { return mFullScreen; } 00083 int getWindowWidth() const { return mWindowSizeX; } 00085 int getWindowHeight() const { return mWindowSizeY; } 00087 Vec2i getWindowSize() const { return Vec2i( mWindowSizeX, mWindowSizeY ); } 00089 Area getWindowBounds() const { return Area( 0, 0, mWindowSizeX, mWindowSizeY ); } 00090 00092 const std::string& getTitle() const { return mTitle; } 00094 void setTitle( const std::string &title ) { mTitle = title; } 00095 00097 float getFrameRate() const { return mFrameRate; } 00099 bool isResizable() const { return mResizable; } 00101 bool getPowerManagement() const { return mPowerManagement; } 00102 00103 protected: 00104 Settings(); 00105 virtual ~Settings() {} 00106 00107 bool mShouldQuit; // defaults to false, facilitates early termination 00108 int mWindowSizeX, mWindowSizeY; // default: 640x480 00109 bool mFullScreen; // window covers screen. default: false 00110 float mFrameRate; 00111 bool mResizable; // window is Resizable. default: true 00112 bool mPowerManagement; // allow screensavers or power management to hide app. default: false 00113 std::string mTitle; 00114 }; 00115 00116 00117 public: 00118 // interface 00119 App(); 00120 virtual ~App(); 00121 00123 virtual void setup() {} 00125 virtual void shutdown() {} 00126 00128 virtual void update() {} 00130 virtual void draw() {} 00131 00133 virtual void mouseDown( MouseEvent event ) {} 00135 virtual void mouseUp( MouseEvent event ) {} 00137 virtual void mouseWheel( MouseEvent event ) {} 00139 virtual void mouseMove( MouseEvent event ) {} 00141 virtual void mouseDrag( MouseEvent event ) {} 00143 virtual void keyDown( KeyEvent event ) {} 00145 virtual void keyUp( KeyEvent event ) {} 00147 virtual void resize( ResizeEvent event ) {} 00149 virtual void fileDrop( FileDropEvent event ) {} 00150 00152 virtual void quit() = 0; 00153 00155 CallbackId registerMouseDown( std::function<bool (MouseEvent)> callback ) { return mCallbacksMouseDown.registerCb( callback ); } 00157 template<typename T> 00158 CallbackId registerMouseDown( T *obj, bool (T::*callback)(MouseEvent) ) { return mCallbacksMouseDown.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00160 void unregisterMouseDown( CallbackId id ) { mCallbacksMouseDown.unregisterCb( id ); } 00161 00163 CallbackId registerMouseUp( std::function<bool (MouseEvent)> callback ) { return mCallbacksMouseUp.registerCb( callback ); } 00165 template<typename T> 00166 CallbackId registerMouseUp( T *obj, bool (T::*callback)(MouseEvent) ) { return mCallbacksMouseUp.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00168 void unregisterMouseUp( CallbackId id ) { mCallbacksMouseUp.unregisterCb( id ); } 00169 00171 CallbackId registerMouseWheel( std::function<bool (MouseEvent)> callback ) { return mCallbacksMouseWheel.registerCb( callback ); } 00173 template<typename T> 00174 CallbackId registerMouseWheel( T *obj, bool (T::*callback)(MouseEvent) ) { return mCallbacksMouseWheel.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00176 void unregisterMouseWheel( CallbackId id ) { mCallbacksMouseWheel.unregisterCb( id ); } 00177 00179 CallbackId registerMouseMove( std::function<bool (MouseEvent)> callback ) { return mCallbacksMouseMove.registerCb( callback ); } 00181 template<typename T> 00182 CallbackId registerMouseMove( T *obj, bool (T::*callback)(MouseEvent) ) { return mCallbacksMouseMove.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00184 void unregisterMouseMove( CallbackId id ) { mCallbacksMouseMove.unregisterCb( id ); } 00185 00187 CallbackId registerMouseDrag( std::function<bool (MouseEvent)> callback ) { return mCallbacksMouseDrag.registerCb( callback ); } 00189 template<typename T> 00190 CallbackId registerMouseDrag( T *obj, bool (T::*callback)(MouseEvent) ) { return mCallbacksMouseDrag.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00192 void unregisterMouseDrag( CallbackId id ) { mCallbacksMouseDrag.unregisterCb( id ); } 00193 00195 CallbackId registerKeyDown( std::function<bool (KeyEvent)> callback ) { return mCallbacksKeyDown.registerCb( callback ); } 00197 template<typename T> 00198 CallbackId registerKeyDown( T *obj, bool (T::*callback)(KeyEvent) ) { return mCallbacksKeyDown.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00200 void unregisterKeyDown( CallbackId id ) { mCallbacksKeyDown.unregisterCb( id ); } 00201 00203 CallbackId registerKeyUp( std::function<bool (KeyEvent)> callback ) { return mCallbacksKeyUp.registerCb( callback ); } 00205 template<typename T> 00206 CallbackId registerKeyUp( T *obj, bool (T::*callback)(KeyEvent) ) { return mCallbacksKeyUp.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00208 void unregisterKeyUp( CallbackId id ) { mCallbacksKeyUp.unregisterCb( id ); } 00209 00211 CallbackId registerResize( std::function<bool (ResizeEvent)> callback ) { return mCallbacksResize.registerCb( callback ); } 00213 template<typename T> 00214 CallbackId registerResize( T *obj, bool (T::*callback)(ResizeEvent) ) { return mCallbacksResize.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00216 void unregisterResize( CallbackId id ) { mCallbacksResize.unregisterCb( id ); } 00217 00219 CallbackId registerFileDrop( std::function<bool (FileDropEvent)> callback ) { return mCallbacksFileDrop.registerCb( callback ); } 00221 template<typename T> 00222 CallbackId registerFileDrop( T *obj, bool (T::*callback)(FileDropEvent) ) { return mCallbacksFileDrop.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00224 void unregisterFileDrop( CallbackId id ) { mCallbacksFileDrop.unregisterCb( id ); } 00225 00226 // Accessors 00227 virtual const Settings& getSettings() const = 0; 00228 Renderer* getRenderer() const { return mRenderer.get(); } 00229 00231 virtual int getWindowWidth() const = 0; 00233 virtual void setWindowWidth( int windowWidth ) = 0; 00235 virtual int getWindowHeight() const = 0; 00237 virtual void setWindowHeight( int windowHeight ) = 0; 00239 virtual void setWindowSize( int windowWidth, int windowHeight ) = 0; 00241 void setWindowSize( const Vec2i &size ) { setWindowSize( size.x, size.y ); } 00243 00244 Vec2f getWindowCenter() const { return Vec2f( (float)getWindowWidth(), (float)getWindowHeight() ) * 0.5f; } 00246 Vec2i getWindowSize() const { return Vec2i( getWindowWidth(), getWindowHeight() ); } 00248 float getWindowAspectRatio() const { return getWindowWidth() / (float)getWindowHeight(); } 00250 00251 Area getWindowBounds() const { return Area( 0, 0, getWindowWidth(), getWindowHeight() ); } 00253 virtual float getFrameRate() const = 0; 00255 virtual void setFrameRate( float aFrameRate ) = 0; 00257 float getAverageFps() const { return mAverageFps; } 00259 double getFpsSampleInterval() const { return mFpsSampleInterval; } 00261 void setFpsSampleInterval( double sampleInterval ) { mFpsSampleInterval = sampleInterval; } 00262 00264 virtual bool isFullScreen() const = 0; 00266 virtual void setFullScreen( bool aFullScreen ) = 0; 00267 00269 double getElapsedSeconds() const { return mTimer.getSeconds(); } 00271 uint32_t getElapsedFrames() const { return mFrameCount; } 00272 00273 // utilities 00275 static DataSourceRef loadResource( const std::string &macPath, int mswID, const std::string &mswType ); 00276 #if defined( CINDER_COCOA ) 00277 00278 static DataSourcePathRef loadResource( const std::string &macPath ); 00280 static std::string getResourcePath( const std::string &rsrcRelativePath ); 00282 static std::string getResourcePath(); 00283 #else 00284 00285 static DataSourceBufferRef loadResource( int mswID, const std::string &mswType ); 00286 #endif 00287 00289 virtual std::string getAppPath() = 0; 00291 00294 std::string getOpenFilePath( const std::string &initialPath = "", std::vector<std::string> extensions = std::vector<std::string>() ); 00296 std::string getFolderPath(const std::string &initialPath=""); 00298 00301 std::string getSaveFilePath( const std::string &initialPath = "", std::vector<std::string> extensions = std::vector<std::string>() ); 00302 00304 std::ostream& console(); 00305 00307 Surface copyWindowSurface(); 00309 Surface copyWindowSurface( const Area &area ); 00311 void restoreWindowContext(); 00312 00313 00314 // DO NOT CALL - should be private but aren't for esoteric reasons 00316 // Internal handlers - these are called into by AppImpl's. If you are calling one of these, you have likely strayed far off the path. 00317 void privateMouseDown__( const MouseEvent &event ); 00318 void privateMouseUp__( const MouseEvent &event ); 00319 void privateMouseWheel__( const MouseEvent &event ); 00320 void privateMouseMove__( const MouseEvent &event ); 00321 void privateMouseDrag__( const MouseEvent &event ); 00322 void privateKeyDown__( const KeyEvent &event ); 00323 void privateKeyUp__( const KeyEvent &event ); 00324 void privateFileDrop__( const FileDropEvent &event ); 00325 00326 virtual void privateSetup__(); 00327 virtual void privateResize__( const ResizeEvent &event ); 00328 virtual void privateUpdate__(); 00329 virtual void privateDraw__(); 00330 virtual void privateShutdown__(); 00332 00333 #if defined( CINDER_MSW ) 00334 // Not all Windows target types receive paint events, and the AppImplMswRenderer* needs to know that. 00335 virtual bool getsWindowsPaintEvents() = 0; 00336 #endif 00337 00338 virtual bool receivesEvents() const { return true; } 00339 00341 static App* get() { return sInstance; } 00342 00343 protected: 00345 // These are called by application instantation macros and are only used in the launch process 00346 static void prepareLaunch(); 00347 static void executeLaunch( App *app, class Renderer *renderer, const char *title, int argc, char * const argv[] ); 00348 static void cleanupLaunch(); 00349 00350 virtual void launch( const char *title, int argc, char * const argv[] ) = 0; 00352 00353 private: 00354 00355 #if defined( CINDER_MSW ) 00356 friend class AppImplMsw; 00357 shared_ptr<cinder::msw::dostream> mOutputStream; 00358 #else 00359 static void *sAutoReleasePool; 00360 #endif 00361 00362 Timer mTimer; 00363 uint32_t mFrameCount; 00364 float mAverageFps; 00365 uint32_t mFpsLastSampleFrame; 00366 double mFpsLastSampleTime; 00367 double mFpsSampleInterval; 00368 00369 shared_ptr<Renderer> mRenderer; 00370 00371 CallbackMgr<bool (MouseEvent)> mCallbacksMouseDown, mCallbacksMouseUp, mCallbacksMouseWheel, mCallbacksMouseMove, mCallbacksMouseDrag; 00372 CallbackMgr<bool (KeyEvent)> mCallbacksKeyDown, mCallbacksKeyUp; 00373 CallbackMgr<bool (ResizeEvent)> mCallbacksResize; 00374 CallbackMgr<bool (FileDropEvent)> mCallbacksFileDrop; 00375 00376 static App* sInstance; 00377 }; 00378 00383 00384 inline int getWindowWidth() { return App::get()->getWindowWidth(); } 00386 inline void setWindowWidth( int windowWidth ) { App::get()->setWindowWidth( windowWidth ); } 00388 inline int getWindowHeight() { return App::get()->getWindowHeight(); } 00390 inline void setWindowHeight( int windowHeight ) { App::get()->setWindowHeight( windowHeight ); } 00392 inline void setWindowSize( int windowWidth, int windowHeight ) { App::get()->setWindowSize( windowWidth, windowHeight ); } 00394 00395 inline Vec2f getWindowCenter() { return App::get()->getWindowCenter(); } 00397 inline Vec2i getWindowSize() { return App::get()->getWindowSize(); } 00399 inline float getWindowAspectRatio() { return App::get()->getWindowAspectRatio(); } 00401 00402 inline Area getWindowBounds() { return App::get()->getWindowBounds(); } 00404 inline float getFrameRate() { return App::get()->getFrameRate(); } 00406 inline void setFrameRate( float frameRate ) { App::get()->setFrameRate( frameRate ); } 00408 inline bool isFullScreen() { return App::get()->isFullScreen(); } 00410 inline void setFullScreen( bool fullScreen = true ) { App::get()->setFullScreen( fullScreen ); } 00411 00413 inline double getElapsedSeconds() { return App::get()->getElapsedSeconds(); } 00415 inline uint32_t getElapsedFrames() { return App::get()->getElapsedFrames(); } 00416 00418 inline DataSourceRef loadResource( const std::string &macPath, int mswID, const std::string &mswType ) { return App::loadResource( macPath, mswID, mswType ); } 00419 #if defined( CINDER_COCOA ) 00420 00421 inline DataSourcePathRef loadResource( const std::string &macPath ) { return App::loadResource( macPath ); } 00422 #else 00423 00424 inline DataSourceBufferRef loadResource( int mswID, const std::string &mswType ) { return App::loadResource( mswID, mswType ); } 00425 #endif 00426 00428 inline std::string getAppPath() { return App::get()->getAppPath(); } 00430 00433 inline std::string getOpenFilePath( const std::string &initialPath = "", std::vector<std::string> extensions = std::vector<std::string>() ) { return App::get()->getOpenFilePath( initialPath, extensions ); } 00435 00438 inline std::string getSaveFilePath( const std::string &initialPath = "", std::vector<std::string> extensions = std::vector<std::string>() ) { return App::get()->getSaveFilePath( initialPath, extensions ); } 00439 00441 00444 inline std::ostream& console() { return App::get()->console(); } 00445 00447 inline Surface copyWindowSurface() { return App::get()->copyWindowSurface(); } 00449 inline Surface copyWindowSurface( const Area &area ) { return App::get()->copyWindowSurface( area ); } 00451 inline void restoreWindowContext() { return App::get()->restoreWindowContext(); } 00452 00453 #if defined( CINDER_COCOA ) 00454 00455 inline ::CGContextRef createWindowCgContext() { return ((Renderer2d*)(App::get()->getRenderer()))->getCgContext(); } 00456 #endif 00457 00459 00461 class ResourceLoadExc : public Exception { 00462 public: 00463 #if defined( CINDER_COCOA ) 00464 ResourceLoadExc( const std::string &macPath ); 00465 #elif defined( CINDER_MSW ) 00466 ResourceLoadExc( int mswID, const std::string &mswType ); 00467 ResourceLoadExc( const std::string &macPath, int mswID, const std::string &mswType ); 00468 #endif 00469 00470 virtual const char * what() const throw() { return mMessage; } 00471 00472 char mMessage[4096]; 00473 }; 00474 00475 } } // namespace cinder::app