1 /* 2 Copyright © 2020, Inochi2D Project 3 Distributed under the 2-Clause BSD License, see LICENSE file. 4 5 Authors: Luna Nielsen 6 */ 7 module creator.core; 8 import creator.core.font; 9 import creator.panels; 10 import creator.windows; 11 import creator.utils.link; 12 import creator; 13 14 import std.exception; 15 16 import bindbc.sdl; 17 import bindbc.opengl; 18 import inochi2d; 19 import tinyfiledialogs; 20 import std.string; 21 import std.stdio; 22 23 public import bindbc.imgui; 24 public import bindbc.imgui.ogl; 25 public import creator.core.settings; 26 public import creator.core.actionstack; 27 public import creator.core.taskstack; 28 public import creator.core.path; 29 public import creator.core.font; 30 31 private { 32 SDL_GLContext gl_context; 33 SDL_Window* window; 34 ImGuiIO* io; 35 bool done = false; 36 ImGuiID viewportDock; 37 38 Texture inLogo; 39 40 ImFont* mainFont; 41 ImFont* iconFont; 42 ImFont* biggerFont; 43 44 bool isDarkMode = true; 45 string[] files; 46 } 47 48 bool incShowStatsForNerds; 49 50 51 /** 52 Finalizes everything by freeing imgui resources, etc. 53 */ 54 void incFinalize() { 55 igSaveIniSettingsToDisk(igGetIO().IniFilename); 56 57 // Cleanup 58 ImGuiOpenGLBackend.shutdown(); 59 ImGui_ImplSDL2_Shutdown(); 60 igDestroyContext(null); 61 62 SDL_GL_DeleteContext(gl_context); 63 SDL_DestroyWindow(window); 64 SDL_Quit(); 65 } 66 67 /** 68 Gets dockspace of the viewport 69 */ 70 ImGuiID incGetViewportDockSpace() { 71 return viewportDock; 72 } 73 74 /** 75 Initialize styling 76 */ 77 void incInitStyling() { 78 auto style = igGetStyle(); 79 //style.WindowBorderSize = 0; 80 style.ChildBorderSize = 1; 81 style.PopupBorderSize = 1; 82 style.FrameBorderSize = 1; 83 style.TabBorderSize = 1; 84 85 style.WindowRounding = 4; 86 style.ChildRounding = 0; 87 style.FrameRounding = 3; 88 style.PopupRounding = 6; 89 style.ScrollbarRounding = 18; 90 style.GrabRounding = 3; 91 style.LogSliderDeadzone = 6; 92 style.TabRounding = 6; 93 94 style.IndentSpacing = 10; 95 style.ItemSpacing.y = 3; 96 style.FramePadding.y = 4; 97 98 style.GrabMinSize = 13; 99 style.ScrollbarSize = 14; 100 style.ChildBorderSize = 1; 101 } 102 103 /** 104 Opens Window 105 */ 106 void incOpenWindow() { 107 108 import core.stdc.stdlib : exit; 109 110 auto sdlSupport = loadSDL(); 111 enforce(sdlSupport != SDLSupport.noLibrary, "SDL2 library not found!"); 112 enforce(sdlSupport != SDLSupport.badLibrary, "Bad SDL2 library found!"); 113 114 auto imSupport = loadImGui(); 115 enforce(imSupport != ImGuiSupport.noLibrary, "cimgui library not found!"); 116 enforce(imSupport != ImGuiSupport.badLibrary, "Bad cimgui library found!"); 117 118 SDL_Init(SDL_INIT_EVERYTHING); 119 120 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); 121 version(OSX) { 122 pragma(msg, "Building in macOS support mode..."); 123 124 // macOS only supports up to GL 4.1 with some extra stuff 125 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GLcontextFlag.SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); 126 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GLprofile.SDL_GL_CONTEXT_PROFILE_CORE); 127 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); 128 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); 129 } else { 130 131 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GLcontextFlag.SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); 132 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); 133 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); 134 } 135 debug SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GLcontextFlag.SDL_GL_CONTEXT_DEBUG_FLAG | SDL_GLcontextFlag.SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); 136 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 137 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 138 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); 139 140 SDL_WindowFlags flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; 141 142 if (incSettingsGet!bool("WinMax", false)) { 143 flags |= SDL_WINDOW_MAXIMIZED; 144 } 145 146 window = SDL_CreateWindow( 147 "Inochi Creator", 148 SDL_WINDOWPOS_UNDEFINED, 149 SDL_WINDOWPOS_UNDEFINED, 150 cast(uint)incSettingsGet!int("WinW", 1280), 151 cast(uint)incSettingsGet!int("WinH", 800), 152 flags 153 ); 154 155 gl_context = SDL_GL_CreateContext(window); 156 SDL_GL_MakeCurrent(window, gl_context); 157 SDL_GL_SetSwapInterval(1); 158 159 // Load GL 3 160 GLSupport support = loadOpenGL(); 161 switch(support) { 162 case GLSupport.noLibrary: 163 throw new Exception("OpenGL library could not be loaded!"); 164 165 case GLSupport.noContext: 166 throw new Exception("No valid OpenGL 4.2 context was found!"); 167 168 default: break; 169 } 170 171 import std.string : fromStringz; 172 debug { 173 writefln("GLInfo:\n\t%s\n\t%s\n\t%s\n\t%s\n\tgls=%s", 174 glGetString(GL_VERSION).fromStringz, 175 glGetString(GL_VENDOR).fromStringz, 176 glGetString(GL_RENDERER).fromStringz, 177 glGetString(GL_SHADING_LANGUAGE_VERSION).fromStringz, 178 support 179 ); 180 181 glEnable(GL_DEBUG_OUTPUT); 182 version(Posix) { 183 glDebugMessageCallback(&incDebugCallback, null); 184 } 185 } 186 187 // Setup Inochi2D 188 inInit(() { return igGetTime(); }); 189 190 incCreateContext(); 191 192 193 // Load image resources 194 inLogo = new Texture(ShallowTexture(cast(ubyte[])import("logo.png"))); 195 196 // Load Settings 197 incShowStatsForNerds = incSettingsCanGet("NerdStats") ? incSettingsGet!bool("NerdStats") : false; 198 199 import creator.widgets.titlebar : incSetUseNativeTitlebar, incGetUseNativeTitlebar, incCanUseAppTitlebar; 200 incCanUseAppTitlebar = SDL_SetWindowHitTest(incGetWindowPtr(), null, null) != -1; 201 incSetUseNativeTitlebar(incSettingsGet("UseNativeTitleBar", false)); 202 203 } 204 205 void incCreateContext() { 206 207 // Setup IMGUI 208 igCreateContext(null); 209 io = igGetIO(); 210 211 // Setup font handling 212 incInitFonts(); 213 214 import std.file : exists; 215 if (!exists(incGetAppImguiConfigFile())) { 216 // TODO: Setup a base config 217 } 218 219 220 // Copy string out of GC memory to make sure it doesn't get yeeted before imgui exits. 221 import core.stdc.stdlib : malloc; 222 import core.stdc.string : memcpy; 223 io.IniFilename = cast(char*)malloc(incGetAppImguiConfigFile().length+1); 224 memcpy(cast(void*)io.IniFilename, toStringz(incGetAppImguiConfigFile), incGetAppImguiConfigFile().length+1); 225 igLoadIniSettingsFromDisk(io.IniFilename); 226 227 incSetDarkMode(incSettingsGet!bool("DarkMode", true)); 228 229 io.ConfigFlags |= ImGuiConfigFlags.DockingEnable; // Enable Docking 230 io.ConfigFlags |= ImGuiConfigFlags.ViewportsEnable; // Enable Viewports (causes freezes) 231 //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Navigation 232 io.ConfigWindowsResizeFromEdges = true; // Enable Edge resizing 233 ImGui_ImplSDL2_InitForOpenGL(window, gl_context); 234 ImGuiOpenGLBackend.init(null); 235 236 incInitStyling(); 237 } 238 239 void incSetDarkMode(bool darkMode) { 240 auto style = igGetStyle(); 241 242 if (darkMode) { 243 style.Colors[ImGuiCol.Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); 244 style.Colors[ImGuiCol.TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); 245 style.Colors[ImGuiCol.WindowBg] = ImVec4(0.17f, 0.17f, 0.17f, 1.00f); 246 style.Colors[ImGuiCol.ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); 247 style.Colors[ImGuiCol.PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); 248 style.Colors[ImGuiCol.Border] = ImVec4(0.00f, 0.00f, 0.00f, 0.16f); 249 style.Colors[ImGuiCol.BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.16f); 250 style.Colors[ImGuiCol.FrameBg] = ImVec4(0.12f, 0.12f, 0.12f, 1.00f); 251 style.Colors[ImGuiCol.FrameBgHovered] = ImVec4(0.15f, 0.15f, 0.15f, 0.40f); 252 style.Colors[ImGuiCol.FrameBgActive] = ImVec4(0.22f, 0.22f, 0.22f, 0.67f); 253 style.Colors[ImGuiCol.TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f); 254 style.Colors[ImGuiCol.TitleBgActive] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); 255 style.Colors[ImGuiCol.TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); 256 style.Colors[ImGuiCol.MenuBarBg] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f); 257 style.Colors[ImGuiCol.ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f); 258 style.Colors[ImGuiCol.ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f); 259 style.Colors[ImGuiCol.ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); 260 style.Colors[ImGuiCol.ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f); 261 style.Colors[ImGuiCol.CheckMark] = ImVec4(0.76f, 0.76f, 0.76f, 1.00f); 262 style.Colors[ImGuiCol.SliderGrab] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 263 style.Colors[ImGuiCol.SliderGrabActive] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); 264 style.Colors[ImGuiCol.Button] = ImVec4(0.39f, 0.39f, 0.39f, 0.40f); 265 style.Colors[ImGuiCol.ButtonHovered] = ImVec4(0.44f, 0.44f, 0.44f, 1.00f); 266 style.Colors[ImGuiCol.ButtonActive] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); 267 style.Colors[ImGuiCol.Header] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 268 style.Colors[ImGuiCol.HeaderHovered] = ImVec4(0.28f, 0.28f, 0.28f, 0.80f); 269 style.Colors[ImGuiCol.HeaderActive] = ImVec4(0.44f, 0.44f, 0.44f, 1.00f); 270 style.Colors[ImGuiCol.Separator] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); 271 style.Colors[ImGuiCol.SeparatorHovered] = ImVec4(0.29f, 0.29f, 0.29f, 0.78f); 272 style.Colors[ImGuiCol.SeparatorActive] = ImVec4(0.47f, 0.47f, 0.47f, 1.00f); 273 style.Colors[ImGuiCol.ResizeGrip] = ImVec4(0.35f, 0.35f, 0.35f, 0.00f); 274 style.Colors[ImGuiCol.ResizeGripHovered] = ImVec4(0.40f, 0.40f, 0.40f, 0.00f); 275 style.Colors[ImGuiCol.ResizeGripActive] = ImVec4(0.55f, 0.55f, 0.56f, 0.00f); 276 style.Colors[ImGuiCol.Tab] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); 277 style.Colors[ImGuiCol.TabHovered] = ImVec4(0.34f, 0.34f, 0.34f, 0.80f); 278 style.Colors[ImGuiCol.TabActive] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 279 style.Colors[ImGuiCol.TabUnfocused] = ImVec4(0.14f, 0.14f, 0.14f, 0.97f); 280 style.Colors[ImGuiCol.TabUnfocusedActive] = ImVec4(0.17f, 0.17f, 0.17f, 1.00f); 281 style.Colors[ImGuiCol.DockingPreview] = ImVec4(0.62f, 0.68f, 0.75f, 0.70f); 282 style.Colors[ImGuiCol.DockingEmptyBg] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); 283 style.Colors[ImGuiCol.PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); 284 style.Colors[ImGuiCol.PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); 285 style.Colors[ImGuiCol.PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); 286 style.Colors[ImGuiCol.PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); 287 style.Colors[ImGuiCol.TableHeaderBg] = ImVec4(0.19f, 0.19f, 0.20f, 1.00f); 288 style.Colors[ImGuiCol.TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f); 289 style.Colors[ImGuiCol.TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f); 290 style.Colors[ImGuiCol.TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); 291 style.Colors[ImGuiCol.TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); 292 style.Colors[ImGuiCol.TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); 293 style.Colors[ImGuiCol.DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); 294 style.Colors[ImGuiCol.NavHighlight] = ImVec4(0.32f, 0.32f, 0.32f, 1.00f); 295 style.Colors[ImGuiCol.NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); 296 style.Colors[ImGuiCol.NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); 297 style.Colors[ImGuiCol.ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); 298 299 style.FrameBorderSize = 1; 300 style.TabBorderSize = 1; 301 } 302 else { 303 igStyleColorsLight(null); 304 style.Colors[ImGuiCol.Border] = ImVec4(0.8, 0.8, 0.8, 0.5); 305 style.Colors[ImGuiCol.BorderShadow] = ImVec4(0, 0, 0, 0.05); 306 307 style.FrameBorderSize = 1; 308 } 309 310 // Set Dark mode setting 311 incSettingsSet("DarkMode", darkMode); 312 isDarkMode = darkMode; 313 } 314 315 bool incGetDarkMode() { 316 return isDarkMode; 317 } 318 319 /** 320 Gets whether a frame should be processed 321 */ 322 bool incShouldProcess() { 323 return (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) == 0; 324 } 325 326 /** 327 Gets SDL Window Pointer 328 */ 329 SDL_Window* incGetWindowPtr() { 330 return window; 331 } 332 333 void incGetWindowSize(out int w, out int h) { 334 SDL_GetWindowSize(window, &w, &h); 335 } 336 337 void incFinishFileDrag() { 338 files.length = 0; 339 } 340 341 void incBeginLoopNoEv() { 342 // Start the Dear ImGui frame 343 ImGuiOpenGLBackend.new_frame(); 344 ImGui_ImplSDL2_NewFrame(); 345 346 int w, h; 347 SDL_GetWindowSize(window, &w, &h); 348 auto scale = incGetUIScale(); 349 auto io = igGetIO(); 350 io.DisplayFramebufferScale = ImVec2(scale, scale); 351 io.DisplaySize = ImVec2(w/scale, h/scale); 352 //io.MousePos = ImVec2(io.MousePos.x/scale, io.MousePos.y/scale); 353 354 igNewFrame(); 355 356 if (files.length > 0) { 357 if (igBeginDragDropSource(ImGuiDragDropFlags.SourceExtern)) { 358 igSetDragDropPayload("__PARTS_DROP", &files, files.sizeof); 359 igBeginTooltip(); 360 foreach(file; files) { 361 igText(file.toStringz); 362 } 363 igEndTooltip(); 364 igEndDragDropSource(); 365 } 366 } 367 368 // Add docking space 369 viewportDock = igDockSpaceOverViewport(null, cast(ImGuiDockNodeFlags)0, null); 370 if (!incSettingsCanGet("firstrun_complete")) { 371 incSetDefaultLayout(); 372 incSettingsSet("firstrun_complete", true); 373 } 374 } 375 376 void incSetDefaultLayout() { 377 import creator.panels; 378 379 igDockBuilderRemoveNodeChildNodes(viewportDock); 380 ImGuiID 381 dockMainID, dockIDNodes, dockIDInspector, dockIDHistory, dockIDParams, 382 dockIDLoggerAndTextureSlots; 383 384 dockMainID = viewportDock; 385 dockIDNodes = igDockBuilderSplitNode(dockMainID, ImGuiDir.Left, 0.10f, null, &dockMainID); 386 dockIDInspector = igDockBuilderSplitNode(dockIDNodes, ImGuiDir.Down, 0.60f, null, &dockIDNodes); 387 dockIDHistory = igDockBuilderSplitNode(dockMainID, ImGuiDir.Right, 0.10f, null, &dockMainID); 388 dockIDParams = igDockBuilderSplitNode(dockMainID, ImGuiDir.Left, 0.15f, null, &dockMainID); 389 dockIDLoggerAndTextureSlots = igDockBuilderSplitNode(dockMainID, ImGuiDir.Down, 0.10f, null, &dockMainID); 390 391 igDockBuilderDockWindow("###Nodes", dockIDNodes); 392 igDockBuilderDockWindow("###Inspector", dockIDInspector); 393 igDockBuilderDockWindow("###History", dockIDHistory); 394 igDockBuilderDockWindow("###Tracking", dockIDHistory); 395 igDockBuilderDockWindow("###Parameters", dockIDParams); 396 igDockBuilderDockWindow("###Texture Slots", dockIDLoggerAndTextureSlots); 397 igDockBuilderDockWindow("###Logger", dockIDLoggerAndTextureSlots); 398 399 igDockBuilderFinish(viewportDock); 400 } 401 402 /** 403 Begins the Inochi Creator rendering loop 404 */ 405 void incBeginLoop() { 406 SDL_Event event; 407 408 while(SDL_PollEvent(&event)) { 409 switch(event.type) { 410 case SDL_QUIT: 411 incExit(); 412 break; 413 414 case SDL_DROPFILE: 415 files ~= cast(string)event.drop.file.fromStringz; 416 SDL_RaiseWindow(window); 417 break; 418 419 default: 420 ImGui_ImplSDL2_ProcessEvent(&event); 421 if ( 422 event.type == SDL_WINDOWEVENT && 423 event.window.event == SDL_WINDOWEVENT_CLOSE && 424 event.window.windowID == SDL_GetWindowID(window) 425 ) incExit(); 426 break; 427 } 428 } 429 430 incTaskUpdate(); 431 432 // Begin loop post-event 433 incBeginLoopNoEv(); 434 } 435 436 /** 437 Ends the Inochi Creator rendering loop 438 */ 439 void incEndLoop() { 440 441 // Rendering 442 igRender(); 443 glViewport(0, 0, cast(int)io.DisplaySize.x, cast(int)io.DisplaySize.y); 444 glClearColor(0.5, 0.5, 0.5, 1); 445 glClear(GL_COLOR_BUFFER_BIT); 446 auto io = igGetIO(); 447 auto draw = igGetDrawData(); 448 auto scale = incGetUIScale(); 449 //draw.FramebufferScale = ImVec2(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y); 450 //draw.DisplaySize = ImVec2(/draw.FramebufferScale.x, io.DisplaySize.y/draw.FramebufferScale.y); 451 452 // ImDrawData_ScaleClipRects(draw, draw.FramebufferScale); 453 // foreach(i; 0..draw.CmdListsCount) { 454 // ImDrawList* list = draw.CmdLists[i]; 455 // foreach(vi; 0..list.VtxBuffer.Size) { 456 // ImDrawVert* v = &list.VtxBuffer.Data[vi]; 457 // v.pos.x += draw.FramebufferScale.x; 458 // v.pos.y += draw.FramebufferScale.y; 459 // } 460 // } 461 462 //ImDrawData_ScaleClipRects(draw, draw.FramebufferScale); 463 ImGuiOpenGLBackend.render_draw_data(draw); 464 465 if (io.ConfigFlags & ImGuiConfigFlags.ViewportsEnable) { 466 SDL_Window* currentWindow = SDL_GL_GetCurrentWindow(); 467 SDL_GLContext currentCtx = SDL_GL_GetCurrentContext(); 468 igUpdatePlatformWindows(); 469 470 471 // SDL_DisplayMode dm; 472 // SDL_GetCurrentDisplayMode(0, &dm); 473 // io.DisplaySize = ImVec2(dm.w/scale, dm.h/scale); 474 475 igRenderPlatformWindowsDefault(); 476 SDL_GL_MakeCurrent(currentWindow, currentCtx); 477 } 478 479 SDL_GL_SwapWindow(window); 480 } 481 482 /** 483 Gets whether Inochi Creator has requested the app to close 484 */ 485 bool incIsCloseRequested() { 486 return done; 487 } 488 489 /** 490 Exit Inochi Creator 491 */ 492 void incExit() { 493 done = true; 494 495 int w, h; 496 SDL_WindowFlags flags; 497 flags = SDL_GetWindowFlags(window); 498 SDL_GetWindowSize(window, &w, &h); 499 incSettingsSet("WinW", w); 500 incSettingsSet("WinH", h); 501 incSettingsSet!bool("WinMax", (flags & SDL_WINDOW_MAXIMIZED) > 0); 502 } 503 504 /** 505 Main font 506 */ 507 ImFont* incMainFont() { 508 return mainFont; 509 } 510 511 /** 512 Bigger sized font 513 */ 514 ImFont* incBiggerFont() { 515 return biggerFont; 516 } 517 518 /** 519 Bigger sized font 520 */ 521 ImFont* incIconFont() { 522 return iconFont; 523 } 524 525 /** 526 Gets the Inochi2D Logo 527 */ 528 GLuint incGetLogo() { 529 return inLogo.getTextureId; 530 } 531 532 void incHandleShortcuts() { 533 auto io = igGetIO(); 534 535 if (io.KeyCtrl && io.KeyShift && igIsKeyPressed(igGetKeyIndex(ImGuiKey.Z), true)) { 536 incActionRedo(); 537 } else if (io.KeyCtrl && igIsKeyPressed(igGetKeyIndex(ImGuiKey.Z), true)) { 538 incActionUndo(); 539 } 540 } 541 542 543 debug { 544 extern(C) 545 void incDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const(char)* message, void* userParam) nothrow { 546 import core.stdc.stdio : fprintf, stderr; 547 if (type == 0x8251) return; 548 549 // HACK: I have no clue what causes this error 550 // but everything seems to work nontheless 551 // I'll just quietly ignore it. 552 if (type == 0x824c) return; 553 554 fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", 555 ( type == GL_DEBUG_TYPE_ERROR ? cast(char*)"** GL ERROR **" : cast(char*)"" ), 556 type, severity, message ); 557 558 } 559 }