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 { 00063 class Timeline; 00064 } // namespace cinder 00065 00066 namespace cinder { namespace app { 00067 00068 class App { 00069 public: 00070 class Settings { 00071 public: 00072 // whether or not the app should terminate prior to launching 00073 bool isPrepared() const { return !mShouldQuit; }; 00074 00076 void setWindowSize( int aWindowSizeX, int aWindowSizeY ); 00077 00079 void setWindowPos( int windowPositionX, int windowPositionY ) { setWindowPos( Vec2i( windowPositionX, windowPositionY ) ); } 00081 void setWindowPos( const Vec2i &windowPos ); 00083 bool isWindowPosSpecified() const { return mWindowPosSpecified; } 00085 void unspecifyWindowPos() { mWindowPosSpecified = false; } 00086 00088 bool isBorderless() const { return mBorderless; } 00090 void setBorderless( bool borderless = true ) { mBorderless = borderless; } 00092 bool isAlwaysOnTop() const { return mAlwaysOnTop; } 00094 void setAlwaysOnTop( bool alwaysOnTop = true ) { mAlwaysOnTop = alwaysOnTop; } 00095 00096 00098 void setFrameRate( float aFrameRate ); 00099 00101 void enablePowerManagement( bool aPowerManagement = true ); 00102 00104 bool isFullScreen() const { return mFullScreen; } 00106 int getWindowWidth() const { return mWindowSizeX; } 00108 int getWindowHeight() const { return mWindowSizeY; } 00110 Vec2i getWindowSize() const { return Vec2i( mWindowSizeX, mWindowSizeY ); } 00112 Area getWindowBounds() const { return Area( 0, 0, mWindowSizeX, mWindowSizeY ); } 00113 00115 int getWindowPosX() const { return mWindowPositionX; } 00117 int getWindowPosY() const { return mWindowPositionY; } 00119 Vec2i getWindowPos() const { return Vec2i( mWindowPositionX, mWindowPositionY ); } 00120 00122 const std::string& getTitle() const { return mTitle; } 00124 void setTitle( const std::string &title ) { mTitle = title; } 00125 00127 float getFrameRate() const { return mFrameRate; } 00129 bool isResizable() const { return mResizable; } 00131 bool getPowerManagement() const { return mPowerManagement; } 00132 00133 protected: 00134 Settings(); 00135 virtual ~Settings() {} 00136 00137 bool mShouldQuit; // defaults to false, facilitates early termination 00138 int mWindowSizeX, mWindowSizeY; // default: 640x480 00139 00140 bool mWindowPosSpecified; 00141 int mWindowPositionX, mWindowPositionY; 00142 00143 bool mFullScreen; // window covers screen. default: false 00144 float mFrameRate; 00145 bool mResizable; // window is Resizable. default: true 00146 bool mBorderless; // window is borderless (frameless / chromeless). default: false 00147 bool mAlwaysOnTop; // window is always on top. default: false 00148 bool mPowerManagement; // allow screensavers or power management to hide app. default: false 00149 std::string mTitle; 00150 }; 00151 00152 00153 public: 00154 // interface 00155 App(); 00156 virtual ~App(); 00157 00159 virtual void setup() {} 00161 virtual void shutdown() {} 00162 00164 virtual void update() {} 00166 virtual void draw() {} 00167 00169 virtual void mouseDown( MouseEvent event ) {} 00171 virtual void mouseUp( MouseEvent event ) {} 00173 virtual void mouseWheel( MouseEvent event ) {} 00175 virtual void mouseMove( MouseEvent event ) {} 00177 virtual void mouseDrag( MouseEvent event ) {} 00179 virtual void keyDown( KeyEvent event ) {} 00181 virtual void keyUp( KeyEvent event ) {} 00183 virtual void resize( ResizeEvent event ) {} 00185 virtual void fileDrop( FileDropEvent event ) {} 00186 00188 virtual void quit() = 0; 00189 00191 CallbackId registerMouseDown( std::function<bool (MouseEvent)> callback ) { return mCallbacksMouseDown.registerCb( callback ); } 00193 template<typename T> 00194 CallbackId registerMouseDown( T *obj, bool (T::*callback)(MouseEvent) ) { return mCallbacksMouseDown.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00196 void unregisterMouseDown( CallbackId id ) { mCallbacksMouseDown.unregisterCb( id ); } 00197 00199 CallbackId registerMouseUp( std::function<bool (MouseEvent)> callback ) { return mCallbacksMouseUp.registerCb( callback ); } 00201 template<typename T> 00202 CallbackId registerMouseUp( T *obj, bool (T::*callback)(MouseEvent) ) { return mCallbacksMouseUp.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00204 void unregisterMouseUp( CallbackId id ) { mCallbacksMouseUp.unregisterCb( id ); } 00205 00207 CallbackId registerMouseWheel( std::function<bool (MouseEvent)> callback ) { return mCallbacksMouseWheel.registerCb( callback ); } 00209 template<typename T> 00210 CallbackId registerMouseWheel( T *obj, bool (T::*callback)(MouseEvent) ) { return mCallbacksMouseWheel.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00212 void unregisterMouseWheel( CallbackId id ) { mCallbacksMouseWheel.unregisterCb( id ); } 00213 00215 CallbackId registerMouseMove( std::function<bool (MouseEvent)> callback ) { return mCallbacksMouseMove.registerCb( callback ); } 00217 template<typename T> 00218 CallbackId registerMouseMove( T *obj, bool (T::*callback)(MouseEvent) ) { return mCallbacksMouseMove.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00220 void unregisterMouseMove( CallbackId id ) { mCallbacksMouseMove.unregisterCb( id ); } 00221 00223 CallbackId registerMouseDrag( std::function<bool (MouseEvent)> callback ) { return mCallbacksMouseDrag.registerCb( callback ); } 00225 template<typename T> 00226 CallbackId registerMouseDrag( T *obj, bool (T::*callback)(MouseEvent) ) { return mCallbacksMouseDrag.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00228 void unregisterMouseDrag( CallbackId id ) { mCallbacksMouseDrag.unregisterCb( id ); } 00229 00231 CallbackId registerKeyDown( std::function<bool (KeyEvent)> callback ) { return mCallbacksKeyDown.registerCb( callback ); } 00233 template<typename T> 00234 CallbackId registerKeyDown( T *obj, bool (T::*callback)(KeyEvent) ) { return mCallbacksKeyDown.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00236 void unregisterKeyDown( CallbackId id ) { mCallbacksKeyDown.unregisterCb( id ); } 00237 00239 CallbackId registerKeyUp( std::function<bool (KeyEvent)> callback ) { return mCallbacksKeyUp.registerCb( callback ); } 00241 template<typename T> 00242 CallbackId registerKeyUp( T *obj, bool (T::*callback)(KeyEvent) ) { return mCallbacksKeyUp.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00244 void unregisterKeyUp( CallbackId id ) { mCallbacksKeyUp.unregisterCb( id ); } 00245 00247 CallbackId registerResize( std::function<bool (ResizeEvent)> callback ) { return mCallbacksResize.registerCb( callback ); } 00249 template<typename T> 00250 CallbackId registerResize( T *obj, bool (T::*callback)(ResizeEvent) ) { return mCallbacksResize.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00252 void unregisterResize( CallbackId id ) { mCallbacksResize.unregisterCb( id ); } 00253 00255 CallbackId registerFileDrop( std::function<bool (FileDropEvent)> callback ) { return mCallbacksFileDrop.registerCb( callback ); } 00257 template<typename T> 00258 CallbackId registerFileDrop( T *obj, bool (T::*callback)(FileDropEvent) ) { return mCallbacksFileDrop.registerCb( std::bind1st( std::mem_fun( callback ), obj ) ); } 00260 void unregisterFileDrop( CallbackId id ) { mCallbacksFileDrop.unregisterCb( id ); } 00261 00262 // Accessors 00263 virtual const Settings& getSettings() const = 0; 00264 Renderer* getRenderer() const { return mRenderer.get(); } 00265 00267 virtual int getWindowWidth() const = 0; 00269 virtual void setWindowWidth( int windowWidth ) = 0; 00271 virtual int getWindowHeight() const = 0; 00273 virtual void setWindowHeight( int windowHeight ) = 0; 00275 virtual void setWindowSize( int windowWidth, int windowHeight ) = 0; 00277 void setWindowSize( const Vec2i &size ) { setWindowSize( size.x, size.y ); } 00279 00280 Vec2f getWindowCenter() const { return Vec2f( (float)getWindowWidth(), (float)getWindowHeight() ) * 0.5f; } 00282 Vec2i getWindowSize() const { return Vec2i( getWindowWidth(), getWindowHeight() ); } 00284 float getWindowAspectRatio() const { return getWindowWidth() / (float)getWindowHeight(); } 00286 00287 Area getWindowBounds() const { return Area( 0, 0, getWindowWidth(), getWindowHeight() ); } 00288 00290 virtual Vec2i getWindowPos() const { return Vec2i::zero(); } 00292 int getWindowPosX() const { return getWindowPos().x; } 00294 int getWindowPosY() const { return getWindowPos().y; } 00296 void setWindowPos( int x, int y ) { setWindowPos( Vec2i( x, y ) ); } 00298 virtual void setWindowPos( const Vec2i &windowPos ) {} 00299 00301 virtual float getFrameRate() const = 0; 00303 virtual void setFrameRate( float aFrameRate ) = 0; 00305 float getAverageFps() const { return mAverageFps; } 00307 double getFpsSampleInterval() const { return mFpsSampleInterval; } 00309 void setFpsSampleInterval( double sampleInterval ) { mFpsSampleInterval = sampleInterval; } 00310 00312 virtual bool isFullScreen() const = 0; 00314 virtual void setFullScreen( bool aFullScreen ) = 0; 00315 00317 virtual bool isBorderless() const { return false; } 00319 virtual void setBorderless( bool borderless = true ) { } 00321 virtual bool isAlwaysOnTop() const { return false; } 00323 virtual void setAlwaysOnTop( bool alwaysOnTop = true ) { } 00324 00326 double getElapsedSeconds() const { return mTimer.getSeconds(); } 00328 uint32_t getElapsedFrames() const { return mFrameCount; } 00329 00330 // utilities 00332 static DataSourceRef loadResource( const std::string &macPath, int mswID, const std::string &mswType ); 00333 #if defined( CINDER_COCOA ) 00334 00335 static DataSourceRef loadResource( const std::string &macPath ); 00337 static fs::path getResourcePath( const fs::path &rsrcRelativePath ); 00339 static fs::path getResourcePath(); 00340 #else 00341 00342 static DataSourceRef loadResource( int mswID, const std::string &mswType ); 00343 #endif 00344 00346 DataSourceRef loadAsset( const fs::path &relativePath ); 00348 fs::path getAssetPath( const fs::path &relativePath ); 00350 void addAssetDirectory( const fs::path &dirPath ); 00351 00353 virtual fs::path getAppPath() = 0; 00355 00358 fs::path getOpenFilePath( const fs::path &initialPath = "", std::vector<std::string> extensions = std::vector<std::string>() ); 00360 fs::path getFolderPath(const fs::path &initialPath=""); 00362 00365 fs::path getSaveFilePath( const fs::path &initialPath = "", std::vector<std::string> extensions = std::vector<std::string>() ); 00366 00368 std::ostream& console(); 00369 00371 Timeline& timeline() { return *mTimeline; } 00372 00374 Surface copyWindowSurface(); 00376 Surface copyWindowSurface( const Area &area ); 00378 void restoreWindowContext(); 00379 00380 00381 // DO NOT CALL - should be private but aren't for esoteric reasons 00383 // Internal handlers - these are called into by AppImpl's. If you are calling one of these, you have likely strayed far off the path. 00384 void privateMouseDown__( const MouseEvent &event ); 00385 void privateMouseUp__( const MouseEvent &event ); 00386 void privateMouseWheel__( const MouseEvent &event ); 00387 void privateMouseMove__( const MouseEvent &event ); 00388 void privateMouseDrag__( const MouseEvent &event ); 00389 void privateKeyDown__( const KeyEvent &event ); 00390 void privateKeyUp__( const KeyEvent &event ); 00391 void privateFileDrop__( const FileDropEvent &event ); 00392 00393 virtual void privateSetup__(); 00394 virtual void privateResize__( const ResizeEvent &event ); 00395 virtual void privateUpdate__(); 00396 virtual void privateDraw__(); 00397 virtual void privateShutdown__(); 00399 00400 #if defined( CINDER_MSW ) 00401 // Not all Windows target types receive paint events, and the AppImplMswRenderer* needs to know that. 00402 virtual bool getsWindowsPaintEvents() = 0; 00403 #endif 00404 00405 virtual bool receivesEvents() const { return true; } 00406 00408 static App* get() { return sInstance; } 00409 00410 protected: 00412 // These are called by application instantation macros and are only used in the launch process 00413 static void prepareLaunch(); 00414 static void executeLaunch( App *app, class Renderer *renderer, const char *title, int argc, char * const argv[] ); 00415 static void cleanupLaunch(); 00416 00417 virtual void launch( const char *title, int argc, char * const argv[] ) = 0; 00419 00420 private: 00421 void prepareAssetLoading(); 00422 fs::path findAssetPath( const fs::path &relativePath ); 00423 00424 #if defined( CINDER_MSW ) 00425 friend class AppImplMsw; 00426 std::shared_ptr<cinder::msw::dostream> mOutputStream; 00427 #else 00428 static void *sAutoReleasePool; 00429 #endif 00430 00431 Timer mTimer; 00432 uint32_t mFrameCount; 00433 float mAverageFps; 00434 uint32_t mFpsLastSampleFrame; 00435 double mFpsLastSampleTime; 00436 double mFpsSampleInterval; 00437 00438 std::shared_ptr<Timeline> mTimeline; 00439 00440 std::shared_ptr<Renderer> mRenderer; 00441 00442 CallbackMgr<bool (MouseEvent)> mCallbacksMouseDown, mCallbacksMouseUp, mCallbacksMouseWheel, mCallbacksMouseMove, mCallbacksMouseDrag; 00443 CallbackMgr<bool (KeyEvent)> mCallbacksKeyDown, mCallbacksKeyUp; 00444 CallbackMgr<bool (ResizeEvent)> mCallbacksResize; 00445 CallbackMgr<bool (FileDropEvent)> mCallbacksFileDrop; 00446 00447 // have we already setup the default path to assets? 00448 bool mAssetDirectoriesInitialized; 00449 // Path to directories which contain assets 00450 std::vector<fs::path> mAssetDirectories; 00451 00452 static App* sInstance; 00453 }; 00454 00459 00460 inline int getWindowWidth() { return App::get()->getWindowWidth(); } 00462 inline void setWindowPos( const Vec2i &windowPos ) { App::get()->setWindowPos( windowPos); } 00463 inline void setWindowPos( int x, int y ) { setWindowPos( Vec2i( x, y ) ); } 00465 inline void setWindowWidth( int windowWidth ) { App::get()->setWindowWidth( windowWidth ); } 00467 inline int getWindowHeight() { return App::get()->getWindowHeight(); } 00469 inline void setWindowHeight( int windowHeight ) { App::get()->setWindowHeight( windowHeight ); } 00471 inline void setWindowSize( int windowWidth, int windowHeight ) { App::get()->setWindowSize( windowWidth, windowHeight ); } 00473 00474 inline Vec2f getWindowCenter() { return App::get()->getWindowCenter(); } 00476 inline Vec2i getWindowSize() { return App::get()->getWindowSize(); } 00478 inline Vec2i getWindowPos() { return App::get()->getWindowPos(); } 00480 inline float getWindowAspectRatio() { return App::get()->getWindowAspectRatio(); } 00482 00483 inline Area getWindowBounds() { return App::get()->getWindowBounds(); } 00485 inline float getFrameRate() { return App::get()->getFrameRate(); } 00487 inline void setFrameRate( float frameRate ) { App::get()->setFrameRate( frameRate ); } 00489 inline bool isFullScreen() { return App::get()->isFullScreen(); } 00491 inline void setFullScreen( bool fullScreen = true ) { App::get()->setFullScreen( fullScreen ); } 00492 00494 inline double getElapsedSeconds() { return App::get()->getElapsedSeconds(); } 00496 inline uint32_t getElapsedFrames() { return App::get()->getElapsedFrames(); } 00497 00499 inline DataSourceRef loadResource( const std::string &macPath, int mswID, const std::string &mswType ) { return App::loadResource( macPath, mswID, mswType ); } 00500 #if defined( CINDER_COCOA ) 00501 00502 inline DataSourceRef loadResource( const std::string &macPath ) { return App::loadResource( macPath ); } 00503 #else 00504 00505 inline DataSourceRef loadResource( int mswID, const std::string &mswType ) { return App::loadResource( mswID, mswType ); } 00506 #endif 00507 00509 inline DataSourceRef loadAsset( const fs::path &relativePath ) { return App::get()->loadAsset( relativePath ); } 00511 inline fs::path getAssetPath( const fs::path &relativePath ) { return App::get()->getAssetPath( relativePath ); } 00513 inline void addAssetDirectory( const fs::path &dirPath ) { App::get()->addAssetDirectory( dirPath ); } 00514 00516 inline fs::path getAppPath() { return App::get()->getAppPath(); } 00518 00521 inline fs::path getOpenFilePath( const fs::path &initialPath = "", std::vector<std::string> extensions = std::vector<std::string>() ) { return App::get()->getOpenFilePath( initialPath, extensions ); } 00523 00526 inline fs::path getSaveFilePath( const fs::path &initialPath = "", std::vector<std::string> extensions = std::vector<std::string>() ) { return App::get()->getSaveFilePath( initialPath, extensions ); } 00527 00529 00532 inline std::ostream& console() { return App::get()->console(); } 00533 00535 inline Timeline& timeline() { return App::get()->timeline(); } 00536 00538 inline Surface copyWindowSurface() { return App::get()->copyWindowSurface(); } 00540 inline Surface copyWindowSurface( const Area &area ) { return App::get()->copyWindowSurface( area ); } 00542 inline void restoreWindowContext() { return App::get()->restoreWindowContext(); } 00543 00544 #if defined( CINDER_COCOA ) 00545 00546 inline ::CGContextRef createWindowCgContext() { return ((Renderer2d*)(App::get()->getRenderer()))->getCgContext(); } 00547 #endif 00548 00550 00552 class ResourceLoadExc : public Exception { 00553 public: 00554 #if defined( CINDER_COCOA ) 00555 ResourceLoadExc( const std::string &macPath ); 00556 #elif defined( CINDER_MSW ) 00557 ResourceLoadExc( int mswID, const std::string &mswType ); 00558 ResourceLoadExc( const std::string &macPath, int mswID, const std::string &mswType ); 00559 #endif 00560 00561 virtual const char * what() const throw() { return mMessage; } 00562 00563 char mMessage[4096]; 00564 }; 00565 00567 class AssetLoadExc : public Exception { 00568 public: 00569 AssetLoadExc( const fs::path &relativePath ); 00570 00571 virtual const char * what() const throw() { return mMessage; } 00572 00573 char mMessage[4096]; 00574 }; 00575 00576 } } // namespace cinder::app