include/cinder/app/App.h
Go to the documentation of this file.
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