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 }