00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #pragma once
00025
00026 #include "cinder/Cinder.h"
00027 #include "cinder/app/Renderer.h"
00028 #include "cinder/app/Window.h"
00029 #include "cinder/Vector.h"
00030 #include "cinder/app/MouseEvent.h"
00031 #include "cinder/app/KeyEvent.h"
00032 #include "cinder/app/FileDropEvent.h"
00033 #include "cinder/Display.h"
00034 #include "cinder/DataSource.h"
00035 #include "cinder/Timer.h"
00036 #include "cinder/Function.h"
00037 #include "cinder/Thread.h"
00038 #if defined( CINDER_COCOA )
00039 #if defined( CINDER_COCOA_TOUCH )
00040 #if defined( __OBJC__ )
00041 #import <UIKit/UIKit.h>
00042 #import <CoreFoundation/CoreFoundation.h>
00043 #endif
00044 #else
00045 #include <ApplicationServices/ApplicationServices.h>
00046 #endif
00047 #if defined __OBJC__
00048 @class CinderView;
00049 @class NSBundle;
00050 #else
00051 class NSBundle;
00052 #endif
00053
00054 #elif defined( CINDER_MSW )
00055 #include "cinder/msw/OutputDebugStringStream.h"
00056 #endif
00057
00058 #include <vector>
00059 #include <algorithm>
00060
00061 namespace cinder {
00062 class Timeline;
00063 }
00064
00065 namespace boost { namespace asio {
00066 class io_service;
00067 } }
00068
00069 namespace cinder { namespace app {
00070
00071
00073 struct BooleanOrEventCombiner {
00074 typedef bool result_type;
00075
00076 template<typename InputIterator>
00077 bool operator()( InputIterator first, InputIterator last ) const
00078 {
00079 bool handled = ( first == last ) ? true : false;
00080 while( first != last )
00081 handled = *first++ || handled;
00082
00083 return handled;
00084 }
00085 };
00086
00088 struct BooleanAndEventCombiner {
00089 typedef bool result_type;
00090
00091 template<typename InputIterator>
00092 bool operator()( InputIterator first, InputIterator last ) const
00093 {
00094 bool result = true;
00095 while( first != last )
00096 result = *first++ && result;
00097
00098 return result;
00099 }
00100 };
00101
00103 template<typename T>
00104 struct BitwiseAndEventCombiner {
00105 typedef T result_type;
00106
00107 template<typename InputIterator>
00108 T operator()( InputIterator first, InputIterator last ) const
00109 {
00110 if( first == last )
00111 return 0;
00112 T mask = *first++;
00113 while( first != last )
00114 mask &= *first++;
00115
00116 return mask;
00117 }
00118 };
00119
00120 class App {
00121 public:
00122 class Settings {
00123 public:
00124
00125 bool isPrepared() const { return ! mShouldQuit; };
00126
00128 void setWindowSize( int windowSizeX, int windowSizeY ) { mDefaultWindowFormat.setSize( Vec2i( windowSizeX, windowSizeY ) ); }
00130 void setWindowSize( const Vec2i &size ) { mDefaultWindowFormat.setSize( size ); }
00132 Vec2i getWindowSize() const { return mDefaultWindowFormat.getSize(); }
00133
00135 Vec2i getWindowPos() const { return mDefaultWindowFormat.getPos(); }
00137 void setWindowPos( int windowPosX, int windowPosY ) { mDefaultWindowFormat.setPos( Vec2i( windowPosX, windowPosY ) ); }
00139 void setWindowPos( const Vec2i &windowPos ) { mDefaultWindowFormat.setPos( windowPos ); }
00141 bool isWindowPosSpecified() const { return mDefaultWindowFormat.isPosSpecified(); }
00143 void unspecifyWindowPos() { mDefaultWindowFormat.unspecifyPos(); }
00144
00146 bool isFullScreen() { return mDefaultWindowFormat.isFullScreen(); }
00148 void setFullScreen( bool fullScreen = true, const FullScreenOptions &options = FullScreenOptions() ) { mDefaultWindowFormat.setFullScreen( fullScreen, options ); }
00149
00151 bool isResizable() const { return mDefaultWindowFormat.isResizable(); }
00153 void setResizable( bool resizable = true ) { mDefaultWindowFormat.setResizable( resizable ); }
00155 bool isBorderless() const { return mDefaultWindowFormat.isBorderless(); }
00157 void setBorderless( bool borderless = true ) { mDefaultWindowFormat.setBorderless( borderless ); }
00159 bool isAlwaysOnTop() const { return mDefaultWindowFormat.isAlwaysOnTop(); }
00161 void setAlwaysOnTop( bool alwaysOnTop = true ) { mDefaultWindowFormat.setAlwaysOnTop( alwaysOnTop ); }
00162
00164 DisplayRef getDisplay() const { return mDefaultWindowFormat.getDisplay(); }
00166 void setDisplay( DisplayRef display ) { mDefaultWindowFormat.setDisplay( display ); }
00167
00168 void prepareWindow( const Window::Format &format );
00169 std::vector<Window::Format>& getWindowFormats() { return mWindowFormats; }
00170 const std::vector<Window::Format>& getWindowFormats() const { return mWindowFormats; }\
00171
00173 void enableHighDensityDisplay( bool enable = true ) { mEnableHighDensityDisplay = enable; }
00175 bool isHighDensityDisplayEnabled() const { return mEnableHighDensityDisplay; }
00176
00178 Window::Format getDefaultWindowFormat() const { return mDefaultWindowFormat; }
00180 void setDefaultWindowFormat( const Window::Format &format ) { mDefaultWindowFormat = format; }
00181
00183 void enableMultiTouch( bool enable = true ) { mEnableMultiTouch = enable; }
00185 bool isMultiTouchEnabled() const { return mEnableMultiTouch; }
00186
00188 void enablePowerManagement( bool aPowerManagement = true );
00190 bool isPowerManagementEnabled() const { return mPowerManagement; }
00191
00193 const std::string& getTitle() const { return mTitle; }
00195 void setTitle( const std::string &title ) { mTitle = title; }
00196
00198 void setFrameRate( float frameRate );
00200 void disableFrameRate();
00202 bool isFrameRateEnabled() const { return mFrameRateEnabled; }
00204 float getFrameRate() const { return mFrameRate; }
00205
00206 Settings();
00207 virtual ~Settings() {}
00208
00209 protected:
00210 bool mShouldQuit;
00211
00212
00213 std::vector<Window::Format> mWindowFormats;
00214
00215 Window::Format mDefaultWindowFormat;
00216
00217 bool mFrameRateEnabled;
00218 float mFrameRate;
00219 bool mPowerManagement;
00220 bool mEnableHighDensityDisplay;
00221 bool mEnableMultiTouch;
00222 std::string mTitle;
00223
00224 friend class App;
00225 };
00226
00227
00228 public:
00229
00230 App();
00231 virtual ~App();
00232
00234 virtual void setup() {}
00236 virtual void shutdown() {}
00237
00239 virtual void update() {}
00241 virtual void draw() {}
00242
00244 virtual void mouseDown( MouseEvent event ) {}
00246 virtual void mouseUp( MouseEvent event ) {}
00248 virtual void mouseWheel( MouseEvent event ) {}
00250 virtual void mouseMove( MouseEvent event ) {}
00252 virtual void mouseDrag( MouseEvent event ) {}
00253
00255 virtual void touchesBegan( TouchEvent event ) {}
00257 virtual void touchesMoved( TouchEvent event ) {}
00259 virtual void touchesEnded( TouchEvent event ) {}
00260
00262 virtual void keyDown( KeyEvent event ) {}
00264 virtual void keyUp( KeyEvent event ) {}
00266 virtual void resize() {}
00268 virtual void fileDrop( FileDropEvent event ) {}
00269
00271 virtual void quit() = 0;
00272
00274 signals::signal<void()>& getSignalUpdate() { return mSignalUpdate; }
00275
00277 signals::signal<void()>& getSignalShutdown() { return mSignalShutdown; }
00278 void emitShutdown();
00279
00280 const std::vector<TouchEvent::Touch>& getActiveTouches() const { return getWindow()->getActiveTouches(); }
00281
00282
00283 virtual const Settings& getSettings() const = 0;
00285 RendererRef getRenderer() const { return getWindow()->getRenderer(); }
00287 DisplayRef getDisplay() const { return getWindow()->getDisplay(); }
00288
00290 virtual WindowRef getWindow() const = 0;
00292 virtual size_t getNumWindows() const = 0;
00294 virtual WindowRef getWindowIndex( size_t index ) const = 0;
00295
00297 virtual void enablePowerManagement( bool powerManagement = true ) { mPowerManagement = powerManagement; }
00299 virtual bool isPowerManagementEnabled() const { return mPowerManagement; }
00300
00302 int getWindowWidth() const { return getWindow()->getWidth(); }
00304 int getWindowHeight() const { return getWindow()->getHeight(); }
00306 void setWindowSize( int windowWidth, int windowHeight ) { setWindowSize( Vec2i( windowWidth, windowHeight ) ); }
00308 void setWindowSize( const Vec2i &size ) { getWindow()->setSize( size ); }
00310
00311 Vec2f getWindowCenter() const { return Vec2f( (float)getWindowWidth(), (float)getWindowHeight() ) * 0.5f; }
00313 Vec2i getWindowSize() const { return Vec2i( getWindowWidth(), getWindowHeight() ); }
00315 float getWindowAspectRatio() const { return getWindowWidth() / (float)getWindowHeight(); }
00317
00318 Area getWindowBounds() const { return Area( 0, 0, getWindowWidth(), getWindowHeight() ); }
00320 float getWindowContentScale() const { return getWindow()->getContentScale(); }
00321
00323 Vec2i getWindowPos() const { return getWindow()->getPos(); }
00325 int getWindowPosX() const { return getWindow()->getPos().x; }
00327 int getWindowPosY() const { return getWindow()->getPos().y; }
00329 void setWindowPos( int x, int y ) { setWindowPos( Vec2i( x, y ) ); }
00331 virtual void setWindowPos( const Vec2i &windowPos ) { getWindow()->setPos( windowPos ); }
00332
00334 virtual float getFrameRate() const = 0;
00336 virtual void setFrameRate( float frameRate ) = 0;
00338 float getAverageFps() const { return mAverageFps; }
00340 double getFpsSampleInterval() const { return mFpsSampleInterval; }
00342 void setFpsSampleInterval( double sampleInterval ) { mFpsSampleInterval = sampleInterval; }
00343
00345 bool isFullScreen() const { return getWindow()->isFullScreen(); }
00347 void setFullScreen( bool aFullScreen, const FullScreenOptions &options = FullScreenOptions() ) { getWindow()->setFullScreen( aFullScreen, options ); }
00348
00350 double getElapsedSeconds() const { return mTimer.getSeconds(); }
00352 uint32_t getElapsedFrames() const { return mFrameCount; }
00353
00355 static Vec2i getMousePos();
00356
00357
00359 static DataSourceRef loadResource( const std::string &macPath, int mswID, const std::string &mswType );
00360 #if defined( CINDER_COCOA )
00361
00362 static DataSourceRef loadResource( const std::string &macPath );
00364 static fs::path getResourcePath( const fs::path &rsrcRelativePath );
00366 static fs::path getResourcePath();
00367 #else
00368
00369 static DataSourceRef loadResource( int mswID, const std::string &mswType );
00370 #endif
00371
00373 DataSourceRef loadAsset( const fs::path &relativePath );
00375 fs::path getAssetPath( const fs::path &relativePath );
00377 void addAssetDirectory( const fs::path &dirPath );
00378
00380 virtual fs::path getAppPath() const = 0;
00381 #if defined( CINDER_COCOA )
00382
00383 virtual NSBundle* getBundle() const;
00384 #endif
00385
00386
00389 fs::path getOpenFilePath( const fs::path &initialPath = "", std::vector<std::string> extensions = std::vector<std::string>() );
00391 fs::path getFolderPath(const fs::path &initialPath="");
00393
00396 fs::path getSaveFilePath( const fs::path &initialPath = "", std::vector<std::string> extensions = std::vector<std::string>() );
00397
00399 std::ostream& console();
00400
00402 Timeline& timeline() { return *mTimeline; }
00403
00405 static bool isPrimaryThread();
00406
00408 boost::asio::io_service& io_service() { return *mIo; }
00409
00410
00411
00413 void dispatchAsync( const std::function<void()> &fn );
00414
00415 template<typename T>
00416 typename std::result_of<T()>::type dispatchSync( T fn )
00417 {
00418 if( isPrimaryThread() )
00419 return fn();
00420 else {
00421 typedef typename std::result_of<T()>::type result_type;
00422 #if defined( _MSC_VER ) && ( _MSC_VER <= 1600 ) // slightly different signature with Boost.Thread
00423 std::packaged_task<result_type> task( std::move(fn) );
00424 #else
00425 std::packaged_task<result_type()> task( std::move(fn) );
00426 #endif
00427 auto fute = task.get_future();
00428 dispatchAsync( [&task]() { task(); } );
00429 return fute.get();
00430 }
00431 }
00432
00434 RendererRef getDefaultRenderer() const { return mDefaultRenderer; }
00436 Surface copyWindowSurface();
00438 Surface copyWindowSurface( const Area &area );
00440 void restoreWindowContext();
00441
00443 RendererRef findSharedRenderer( RendererRef searchRenderer ) const;
00444
00445
00447
00448 virtual void privateSetup__();
00449 virtual void privateUpdate__();
00451
00452 #if defined( CINDER_MSW )
00453
00454 virtual bool getsWindowsPaintEvents() = 0;
00455 #endif
00456
00457 virtual bool receivesEvents() const { return true; }
00458
00460 static App* get() { return sInstance; }
00461
00462 protected:
00464
00465 static void prepareLaunch();
00466 static void executeLaunch( App *app, RendererRef defaultRenderer, const char *title, int argc, char * const argv[] );
00467 static void cleanupLaunch();
00468
00469 virtual void launch( const char *title, int argc, char * const argv[] ) = 0;
00470
00472
00473 #if defined( CINDER_MSW )
00474 friend class AppImplMsw;
00475 std::shared_ptr<std::ostream> mOutputStream;
00476 #endif
00477
00478 private:
00479 void prepareAssetLoading();
00480 fs::path findAssetPath( const fs::path &relativePath );
00481
00482 #if defined( CINDER_COCOA )
00483 static void *sAutoReleasePool;
00484 #endif
00485
00486 Timer mTimer;
00487 uint32_t mFrameCount;
00488 float mAverageFps;
00489 uint32_t mFpsLastSampleFrame;
00490 double mFpsLastSampleTime;
00491 double mFpsSampleInterval;
00492
00493 std::shared_ptr<Timeline> mTimeline;
00494
00495 signals::signal<void()> mSignalUpdate, mSignalShutdown;
00496
00497 std::shared_ptr<boost::asio::io_service> mIo;
00498 std::shared_ptr<void> mIoWork;
00499
00500
00501 bool mAssetDirectoriesInitialized;
00502
00503 std::vector<fs::path> mAssetDirectories;
00504
00505 protected:
00506 static App* sInstance;
00507 RendererRef mDefaultRenderer;
00508 bool mPowerManagement;
00509 };
00510
00515 inline WindowRef getWindow() { return App::get()->getWindow(); }
00517 inline size_t getNumWindows() { return App::get()->getNumWindows(); }
00519 inline WindowRef getWindowIndex( size_t index ) { return App::get()->getWindowIndex( index ); }
00520
00522 inline int getWindowWidth() { return App::get()->getWindowWidth(); }
00524 inline void setWindowPos( const Vec2i &windowPos ) { App::get()->setWindowPos( windowPos); }
00526 inline void setWindowPos( int x, int y ) { setWindowPos( Vec2i( x, y ) ); }
00528 inline int getWindowHeight() { return App::get()->getWindowHeight(); }
00530 inline void setWindowSize( int windowWidth, int windowHeight ) { App::get()->setWindowSize( windowWidth, windowHeight ); }
00532
00533 inline Vec2f getWindowCenter() { return App::get()->getWindowCenter(); }
00535 inline Vec2i getWindowSize() { return App::get()->getWindowSize(); }
00537 inline Vec2i getWindowPos() { return App::get()->getWindowPos(); }
00539 inline float getWindowAspectRatio() { return App::get()->getWindowAspectRatio(); }
00541
00542 inline Area getWindowBounds() { return App::get()->getWindowBounds(); }
00544 inline float getWindowContentScale() { return App::get()->getWindowContentScale(); }
00546 inline float getFrameRate() { return App::get()->getFrameRate(); }
00548 inline void setFrameRate( float frameRate ) { App::get()->setFrameRate( frameRate ); }
00550 inline bool isFullScreen() { return App::get()->isFullScreen(); }
00552 inline void setFullScreen( bool fullScreen = true ) { App::get()->setFullScreen( fullScreen ); }
00553
00555 inline float toPixels( float s ) { return getWindow()->toPixels( s ); }
00557 inline Vec2f toPixels( Vec2f s ) { return getWindow()->toPixels( s ); }
00559 inline Vec2i toPixels( Vec2i s ) { return app::getWindow()->toPixels( s ); }
00561 inline Area toPixels( const Area &a ) { return getWindow()->toPixels( a ); }
00563 inline Rectf toPixels( const Rectf &a ) { return getWindow()->toPixels( a ); }
00565 inline float toPoints( float s ) { return getWindow()->toPoints( s ); }
00567 inline Vec2f toPoints( Vec2f s ) { return getWindow()->toPoints( s ); }
00569 inline Vec2i toPoints( Vec2i s ) { return getWindow()->toPoints( s ); }
00571 inline Area toPoints( const Area &a ) { return getWindow()->toPoints( a ); }
00573 inline Rectf toPoints( const Rectf &a ) { return getWindow()->toPoints( a ); }
00574
00576 inline double getElapsedSeconds() { return App::get()->getElapsedSeconds(); }
00578 inline uint32_t getElapsedFrames() { return App::get()->getElapsedFrames(); }
00579
00581 inline DataSourceRef loadResource( const std::string &macPath, int mswID, const std::string &mswType ) { return App::loadResource( macPath, mswID, mswType ); }
00582 #if defined( CINDER_COCOA )
00583
00584 inline DataSourceRef loadResource( const std::string &macPath ) { return App::loadResource( macPath ); }
00585 #else
00586
00587 inline DataSourceRef loadResource( int mswID, const std::string &mswType ) { return App::loadResource( mswID, mswType ); }
00588 #endif
00589
00591 inline DataSourceRef loadAsset( const fs::path &relativePath ) { return App::get()->loadAsset( relativePath ); }
00593 inline fs::path getAssetPath( const fs::path &relativePath ) { return App::get()->getAssetPath( relativePath ); }
00595 inline void addAssetDirectory( const fs::path &dirPath ) { App::get()->addAssetDirectory( dirPath ); }
00596
00598 inline fs::path getAppPath() { return App::get()->getAppPath(); }
00600
00603 inline fs::path getOpenFilePath( const fs::path &initialPath = "", std::vector<std::string> extensions = std::vector<std::string>() ) { return App::get()->getOpenFilePath( initialPath, extensions ); }
00605
00608 inline fs::path getSaveFilePath( const fs::path &initialPath = "", std::vector<std::string> extensions = std::vector<std::string>() ) { return App::get()->getSaveFilePath( initialPath, extensions ); }
00609
00611
00614 inline std::ostream& console() { return App::get()->console(); }
00615
00617 inline Timeline& timeline() { return App::get()->timeline(); }
00618
00620 inline Surface copyWindowSurface() { return App::get()->copyWindowSurface(); }
00622 inline Surface copyWindowSurface( const Area &area ) { return App::get()->copyWindowSurface( area ); }
00624 inline void restoreWindowContext() { return App::get()->restoreWindowContext(); }
00625
00626 #if defined( CINDER_COCOA )
00627
00628 inline ::CGContextRef createWindowCgContext() { return (std::dynamic_pointer_cast<Renderer2d>(App::get()->getRenderer()))->getCgContext(); }
00629 #endif
00630
00632
00634 class ResourceLoadExc : public Exception {
00635 public:
00636 #if defined( CINDER_COCOA )
00637 ResourceLoadExc( const std::string &macPath );
00638 #elif defined( CINDER_MSW )
00639 ResourceLoadExc( int mswID, const std::string &mswType );
00640 ResourceLoadExc( const std::string &macPath, int mswID, const std::string &mswType );
00641 #endif
00642
00643 virtual const char * what() const throw() { return mMessage; }
00644
00645 char mMessage[4096];
00646 };
00647
00649 class AssetLoadExc : public Exception {
00650 public:
00651 AssetLoadExc( const fs::path &relativePath );
00652
00653 virtual const char * what() const throw() { return mMessage; }
00654
00655 char mMessage[4096];
00656 };
00657
00658 } }