1 module rpui.platform_sdl; 2 3 version(rpuiSdl2): 4 5 import std.utf; 6 import std.conv; 7 import std.array; 8 import std..string; 9 10 import derelict.sdl2.sdl; 11 import derelict.sdl2.ttf; 12 import derelict.sdl2.image; 13 14 import gapi.opengl; 15 16 import rpui.events; 17 import rpui.events_observer; 18 import rpui.input; 19 import rpui.platform; 20 21 extern(C) void platformShowSystemCursor() { 22 SDL_ShowCursor(SDL_ENABLE); 23 } 24 25 extern(C) void platformHideSystemCursor() { 26 SDL_ShowCursor(SDL_DISABLE); 27 } 28 29 extern(C) void platformSetMousePosition(void* window, in int x, in int y) { 30 SDL_WarpMouseInWindow(cast(SDL_Window*) window, x, y); 31 } 32 33 extern(C) float platformGetTicks() { 34 return SDL_GetTicks(); 35 } 36 37 extern(C) bool platformEventLoop(void* window, EventsObserver events) { 38 SDL_Event event; 39 40 while (SDL_PollEvent(&event)) { 41 if (event.type == SDL_QUIT) { 42 return false; 43 } 44 else if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { 45 import std.stdio; 46 int w, h; 47 SDL_GL_GetDrawableSize(cast(SDL_Window*) window, &w, &h); 48 writeln(w, "x", h); 49 events.notify(WindowResizeEvent(event.window.data1, event.window.data2, w, h)); 50 } 51 else if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_EXPOSED) { 52 events.notify(WindowExposedEvent()); 53 } 54 else if (event.type == SDL_MOUSEMOTION) { 55 const button = createMouseButtonFromSdlState(event.motion.state); 56 events.notify(MouseMoveEvent(event.motion.x, event.motion.y, button)); 57 } 58 else if (event.type == SDL_MOUSEBUTTONDOWN) { 59 const button = createMouseButtonFromButtonSdlEvent(event); 60 events.notify(MouseDownEvent(event.button.x, event.button.y, button)); 61 62 switch (event.button.clicks) { 63 case 2: 64 events.notify(DblClickEvent(event.button.x, event.button.y, button)); 65 break; 66 67 case 3: 68 events.notify(TripleClickEvent(event.button.x, event.button.y, button)); 69 break; 70 71 default: 72 // Ignore 73 } 74 } 75 else if (event.type == SDL_MOUSEBUTTONUP) { 76 const button = createMouseButtonFromButtonSdlEvent(event); 77 events.notify(MouseUpEvent(event.button.x, event.button.y, button)); 78 } 79 else if (event.type == SDL_MOUSEWHEEL) { 80 events.notify(MouseWheelEvent(event.wheel.x, event.wheel.y)); 81 } 82 else if (event.type == SDL_TEXTINPUT) { 83 events.notify(TextEnteredEvent(toUTF32(fromStringz(event.text.text.ptr)))); 84 } 85 else if (event.type == SDL_KEYDOWN) { 86 try { 87 const key = to!(KeyCode)(to!(int)(event.key.keysym.sym)); 88 setKeyPressed(key, true); 89 events.notify(KeyPressedEvent(key)); 90 } catch (Exception e) { 91 } 92 } 93 else if (event.type == SDL_KEYUP) { 94 try { 95 const key = to!(KeyCode)(to!(int)(event.key.keysym.sym)); 96 events.notify(KeyReleasedEvent(key)); 97 setKeyPressed(key, false); 98 } catch (Exception e) { 99 } 100 } 101 } 102 103 return true; 104 } 105 106 extern(C) void platformSwapWindow(void* window) { 107 SDL_GL_SwapWindow(cast(SDL_Window*) window); 108 } 109 110 extern(C) void platformGapiDeleteContext(void* context) { 111 SDL_GL_DeleteContext(context); 112 } 113 114 extern(C) void platformDestroyWindow(void* window) { 115 SDL_DestroyWindow(cast(SDL_Window*) window); 116 } 117 118 extern(C) void platformShutdown() { 119 SDL_Quit(); 120 TTF_Quit(); 121 } 122 123 extern(C) void platformInit() { 124 // Load shared libraries 125 DerelictGL3.load(); 126 DerelictSDL2.load(); 127 DerelictSDL2Image.load(); 128 DerelictSDL2TTF.load(); 129 130 // Init 131 if (SDL_Init(SDL_INIT_VIDEO) < 0) 132 throw new Error("Failed to init SDL"); 133 134 if (TTF_Init() < 0) 135 throw new Error("Failed to init SDL TTF"); 136 137 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); 138 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); 139 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 140 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 141 SDL_GL_SetSwapInterval(2); 142 } 143 144 extern(C) Window platformCreateWindow(in string title, uint width, uint height) { 145 auto window = SDL_CreateWindow( 146 toStringz(title), 147 SDL_WINDOWPOS_CENTERED, 148 SDL_WINDOWPOS_CENTERED, 149 width, 150 height, 151 SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI 152 ); 153 154 if (window == null) 155 throw new Error("SDL Error: " ~ to!string(SDL_GetError())); 156 157 auto glContext = SDL_GL_CreateContext(window); 158 159 if (glContext == null) 160 throw new Error("SDL Error: " ~ to!string(SDL_GetError())); 161 162 SDL_GL_SwapWindow(window); 163 DerelictGL3.reload(); 164 165 return Window(window, glContext); 166 } 167 168 extern(C) void platformSetClipboardTextUtf8(in string text) { 169 SDL_SetClipboardText(toStringz(text)); 170 } 171 172 extern(C) void platformSetClipboardTextUtf32(in dstring text) { 173 // writeln("PLATFORM COPY: ", data.charString); 174 175 SDL_SetClipboardText(toStringz(to!string(text))); 176 } 177 178 extern(C) string platformGetClipboardTextUtf8() { 179 return to!string(fromStringz(SDL_GetClipboardText())); 180 } 181 182 extern(C) dstring platformGetClipboardTextUtf32() { 183 return to!dstring(fromStringz(SDL_GetClipboardText())); 184 } 185 186 extern(C) bool hasClipboardText() { 187 return cast(bool) SDL_HasClipboardText(); 188 }