1 module grape.window; 2 3 import derelict.sdl2.sdl; 4 import derelict.opengl3.gl; 5 import derelict.opengl3.gl3; 6 7 import std.exception : enforce; 8 import std.stdio; 9 10 shared int WINDOW_WIDTH; 11 shared int WINDOW_HEIGHT; 12 13 enum WindowFlags { 14 FullScreen = SDL_WINDOW_FULLSCREEN, 15 FullScreenDesktop = SDL_WINDOW_FULLSCREEN_DESKTOP, 16 OpenGL = SDL_WINDOW_OPENGL, 17 Shown = SDL_WINDOW_SHOWN, 18 Hidden = SDL_WINDOW_HIDDEN, 19 Borderless = SDL_WINDOW_BORDERLESS, 20 Resizable = SDL_WINDOW_RESIZABLE, 21 Minimized = SDL_WINDOW_MINIMIZED, 22 Maximized = SDL_WINDOW_MAXIMIZED, 23 Grabbed = SDL_WINDOW_INPUT_GRABBED, 24 InputFocus = SDL_WINDOW_INPUT_FOCUS, 25 MouseFocus = SDL_WINDOW_MOUSE_FOCUS, 26 Foreign = SDL_WINDOW_FOREIGN 27 } 28 29 // TODO Windowと合体させるか。マルチウィンドウに対応する。 30 private final class WindowUnit { 31 public: 32 this(in string name, in int x, in int y, in int w, in int h, in WindowFlags flag) { 33 _flag = flag; 34 _window = SDL_CreateWindow(cast(char*)name, x, y, w, h, flag); 35 if (_flag == WindowFlags.OpenGL) { 36 _context = SDL_GL_CreateContext(_window); 37 load_opengl(); 38 } 39 enforce(_window, "create_window() faild"); 40 } 41 42 ~this() { 43 debug(tor) writeln("WindowsUnit dtor"); 44 if (_flag == WindowFlags.OpenGL) 45 SDL_GL_DeleteContext(_context); 46 SDL_DestroyWindow(_window); 47 } 48 49 void swap() { 50 SDL_GL_SwapWindow(_window); 51 } 52 53 // TODO 関数追加 54 55 private: 56 void load_opengl() { 57 DerelictGL.load(); 58 DerelictGL.reload(); // You must create OpenGL Context before calling this function 59 DerelictGL3.load(); 60 DerelictGL3.reload(); // You must create OpenGL Context before calling this function 61 } 62 63 SDL_Window* _window; 64 SDL_GLContext _context; 65 WindowFlags _flag; 66 } 67 68 /** 69 * Windowを管理するクラス 70 * 71 * TODO: 72 * マルチウィンドウ 73 */ 74 class Window { 75 public: 76 this(in int w, in int h) { 77 this("grape", 0, 0, w, h, WindowFlags.OpenGL); 78 } 79 80 this(in string name, in int w, in int h) { 81 this(name, 0, 0, w, h, WindowFlags.OpenGL); 82 } 83 84 this(in string name, in int x, in int y, in int w, in int h) { 85 this(name, x, y, w, h, WindowFlags.OpenGL); 86 } 87 88 /** 89 * Windowの初期化 90 * 91 * name: 画面のタイトル 92 * x: 画面左上のx座標 93 * y: 画面左上のy座標 94 * w: 画面の幅 95 * h: 画面の高さ 96 */ 97 this(in string name, in int x, in int y, in int w, in int h, in WindowFlags flag) { 98 if (!_initialized) { 99 _initialized = true; 100 DerelictSDL2.load(); 101 102 if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) 103 throw new Exception("SDL_InitSubSystem(SDL_INIT_VIDEO) failed"); 104 } 105 106 WINDOW_WIDTH = w; 107 WINDOW_HEIGHT = h; 108 109 _window = new WindowUnit(name, x, y, w, h, flag); 110 _instance ~= this; 111 } 112 113 ~this() { 114 debug(tor) writeln("Windows dtor"); 115 destroy(_window); 116 } 117 118 static ~this() { 119 debug(tor) writeln("Windows static dtor"); 120 if (_initialized) { 121 foreach (v; _instance) destroy(v); 122 SDL_QuitSubSystem(SDL_INIT_VIDEO); 123 } 124 } 125 126 /** 127 * 画面の更新 128 */ 129 void update() { 130 _window.swap(); 131 // other 132 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 133 } 134 135 /** 136 * Alphaチャンネルの有効化 137 * 138 * TODO: 139 * 他に移すかも 140 */ 141 void enable_alpha() { //TODO 142 glEnable(GL_ALPHA_TEST); 143 glEnable(GL_BLEND); 144 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 145 146 /* 147 glEnable(GL_DEPTH_TEST); 148 149 glEnable(GL_POLYGON_SMOOTH); 150 glEnable(GL_LINE_SMOOTH); 151 glEnable(GL_POINT_SMOOTH); 152 */ 153 } 154 155 private: 156 static Window[] _instance; 157 WindowUnit _window; 158 static bool _initialized = false; 159 } 160