1 module des.gui.sdlgl.context; 2 3 import des.gui.sdlgl.base; 4 5 import des.gui.sdlgl.window; 6 import des.gui.sdlgl.canvas; 7 8 class DiSDLGLContext : DesObject, DiContext 9 { 10 mixin DES; 11 12 package: 13 14 SDL_GLContext context = null; 15 16 DiSDLGLWindow current; 17 18 DiSDLGLWindow[DiWidget] windows; 19 20 bool is_running; 21 22 public: 23 24 this() 25 { 26 if( !DerelictSDL2.isLoaded ) 27 DerelictSDL2.load(); 28 29 if( !DerelictGL3.isLoaded ) 30 DerelictGL3.load(); 31 32 if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK ) < 0 ) 33 throw new DiContextException( "Error initializing SDL: " ~ toDString( SDL_GetError() ) ); 34 35 SDL_GL_SetAttribute( SDL_GL_BUFFER_SIZE, 32 ); 36 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 ); 37 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); 38 39 is_running = true; 40 } 41 42 /// 43 bool step() 44 { 45 if( context is null ) 46 { 47 logger.warn( "no windows" ); 48 return false; 49 } 50 51 if( !procEvents() ) return false; 52 53 foreach( win; windows ) win.step(); 54 55 return true; 56 } 57 58 /// 59 bool isRunning() @property { return is_running; } 60 61 DiCanvas createTop( DiWidget w ) 62 { 63 windows[w] = registerChildEMM( createWindow(w) ); 64 return windows[w].canvas; 65 } 66 67 void removeTop( DiWidget w ) 68 { 69 if( w in windows ) 70 { 71 windows[w].destroy(); 72 windows.remove(w); 73 } 74 } 75 76 void startTextInput() { SDL_StartTextInput(); } 77 void stopTextInput() { SDL_StopTextInput(); } 78 79 /// 80 void quit() { is_running = false; } 81 82 protected: 83 84 DiSDLGLWindow createWindow( DiWidget w ) 85 { 86 auto ret = new DiSDLGLWindow( this, w ); 87 88 if( context is null ) 89 { 90 context = SDL_GL_CreateContext( ret.win ); 91 92 if( context is null ) 93 throw new DiContextException( "Couldn't create GL context: " ~ toDString( SDL_GetError() ) ); 94 95 DerelictGL3.reload(); 96 } 97 98 ret.prepare(); 99 return ret; 100 } 101 102 bool procEvents() 103 { 104 SDL_Event ev; 105 106 while( SDL_PollEvent( &ev ) ) 107 { 108 switch( ev.type ) 109 { 110 case SDL_QUIT: return false; 111 // set current window 112 case SDL_WINDOWEVENT: setCurrent( ev.window.windowID ); break; 113 case SDL_KEYDOWN: setCurrent( ev.key.windowID ); break; 114 case SDL_KEYUP: setCurrent( ev.key.windowID ); break; 115 case SDL_TEXTEDITING: setCurrent( ev.edit.windowID ); break; 116 case SDL_TEXTINPUT: setCurrent( ev.text.windowID ); break; 117 case SDL_MOUSEMOTION: setCurrent( ev.motion.windowID ); break; 118 case SDL_MOUSEBUTTONDOWN: setCurrent( ev.button.windowID ); break; 119 case SDL_MOUSEBUTTONUP: setCurrent( ev.button.windowID ); break; 120 case SDL_MOUSEWHEEL: setCurrent( ev.wheel.windowID ); break; 121 default: break; 122 } 123 124 if( current !is null ) 125 current.procEvent( ev ); 126 } 127 128 return true; 129 } 130 131 /// 132 void setCurrent( uint winID ) 133 { 134 current = null; 135 foreach( win; windows ) 136 if( win.id == winID ) 137 { 138 current = win; 139 break; 140 } 141 } 142 143 override void selfDestroy() 144 { 145 destroyContext(); 146 shutdown(); 147 } 148 149 void destroyContext() 150 { 151 if( context !is null ) 152 SDL_GL_DeleteContext( context ); 153 context = null; 154 debug logger.Debug("pass"); 155 } 156 157 void shutdown() 158 { if( SDL_Quit !is null ) SDL_Quit(); } 159 }