Worldstone
 All Classes Files Functions Variables Enumerations Enumerator Macros Pages
RendererApp.cpp
1 #include "RendererApp.h"
2 #include <FileStream.h>
3 #include <MpqArchive.h>
4 #include <bgfx/bgfx.h>
5 #include <dcc.h>
6 #include "DrawSprite.h"
7 #include "FileBrowser.h"
8 #include "imgui/imgui_bgfx.h"
9 
10 RendererApp::RendererApp() = default;
11 RendererApp::~RendererApp() = default;
12 
13 bool RendererApp::initAppThread()
14 {
15  if (!BaseApp::initAppThread()) return false;
16 
17  imguiCreate(imguiAllocator);
18 
19  ImGuiIO& io = ImGui::GetIO();
20  io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
21  io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
22  io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
23  io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
24  io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
25  io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
26  io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
27  io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
28  io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
29  io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
30  io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE;
31  io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE;
32  io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE;
33  io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN;
34  io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE;
35  io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A;
36  io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C;
37  io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V;
38  io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X;
39  io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y;
40  io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z;
41 
42  io.ConfigFlags = 0 | ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_NavEnableGamepad;
43 
44  io.SetClipboardTextFn = [](void*, const char* text) { SDL_SetClipboardText(text); };
45  io.GetClipboardTextFn = [](void*) -> const char* { return SDL_GetClipboardText(); };
46 
47  io.IniFilename = "imgui.ini";
48  io.LogFilename = nullptr; // "imgui_log.txt";
49 
51  if (!pal.decode("palettes/pal.dat")) return false;
52  spriteRenderer.init(pal);
53 
54  fileBrowser = std::make_unique<FileBrowser>();
55  return true;
56 }
57 
58 void RendererApp::shutdownAppThread()
59 {
60  fileBrowser.reset(nullptr);
61  spriteRenderer.shutdown();
62  imguiDestroy();
63  BaseApp::shutdownAppThread();
64 }
65 
66 void RendererApp::executeAppLoopOnce()
67 {
68  // Note: we should probably have an output queue too for events such as Mouse hide/show.
69  updateMouseAccordingToImgui();
70  // Input processing comes here
71  const Inputs inputs = inputsManager.receiveAndProcessEvents();
72 
73  // Ideally we would not set the imgui IO directly here as we should have a
74  // wrapper that parses SDL events
75  ImGuiIO& imguiIO = ImGui::GetIO();
76  for (const SDL_Event& event : inputs.events)
77  {
78  switch (event.type)
79  {
80  case SDL_QUIT: requireExit(); break;
81  case SDL_KEYDOWN:
82  if (event.key.keysym.sym == SDLK_F1) {
83  showBgfxStats = !showBgfxStats;
84  }
86  case SDL_KEYUP:
87  {
88  int key = event.key.keysym.scancode;
89  IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(imguiIO.KeysDown));
90  imguiIO.KeysDown[key] = (event.type == SDL_KEYDOWN);
91  imguiIO.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
92  imguiIO.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
93  imguiIO.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
94  imguiIO.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
95  break;
96  }
97  case SDL_MOUSEWHEEL: { float mouseWheelY = float(event.wheel.y);
98 #if SDL_VERSION_ATLEAST(2, 0, 4)
99  if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) mouseWheelY *= -1.f;
100 #endif
101  // Accumulate wheel if we have multiple events in one frame
102  imguiIO.MouseWheel += mouseWheelY;
103  break;
104  }
105  case SDL_TEXTINPUT: imguiIO.AddInputCharactersUTF8(event.text.text); break;
106  }
107  }
108 
109  // Logic update comes here
110 
111  // Imgui
112  const Inputs::MouseState& mouseState = inputs.mouseState;
113  imguiBeginFrame(
114  int32_t(mouseState.x), int32_t(mouseState.y),
115  0 | ((mouseState.buttonsMask & SDL_BUTTON(SDL_BUTTON_LEFT)) ? IMGUI_MBUT_LEFT : 0)
116  | ((mouseState.buttonsMask & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? IMGUI_MBUT_RIGHT : 0)
117  | ((mouseState.buttonsMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? IMGUI_MBUT_MIDDLE : 0),
118  uint16_t(windowWidth), uint16_t(windowHeight));
119 
120  ImGui::ShowDemoWindow();
121 
122  {
123  ImGui::Begin("Debug");
124  ImGui::Checkbox("Display bgfx stats", &showBgfxStats);
125  bgfx::setDebug(BGFX_DEBUG_TEXT | (showBgfxStats ? BGFX_DEBUG_STATS : 0));
126  ImGui::End();
127  }
128 
129  fileBrowser->display(spriteRenderer);
130 
131  imguiEndFrame();
132 
133  // Set view 0 default viewport.
134  bgfx::setViewRect(0, 0, 0, uint16_t(windowWidth), uint16_t(windowHeight));
135 
136  // This dummy draw call is here to make sure that view 0 is cleared
137  // if no other draw calls are submitted to view 0.
138  bgfx::touch(0);
139 
140  spriteRenderer.draw(windowWidth, windowHeight);
141 
142  // Advance to next frame. Rendering thread will be kicked to
143  // process submitted rendering primitives.
144  // This will also wait for the render thread to finish presenting the frame
145  bgfx::frame();
146 }
147 
148 static SDL_SystemCursor ImGuiMouseCursorToSDL(ImGuiMouseCursor imguiCursor)
149 {
150  switch (imguiCursor)
151  {
152  case ImGuiMouseCursor_Arrow: return SDL_SYSTEM_CURSOR_ARROW;
153  case ImGuiMouseCursor_TextInput: return SDL_SYSTEM_CURSOR_IBEAM;
154  case ImGuiMouseCursor_ResizeAll: return SDL_SYSTEM_CURSOR_SIZEALL;
155  case ImGuiMouseCursor_ResizeNS: return SDL_SYSTEM_CURSOR_SIZENS;
156  case ImGuiMouseCursor_ResizeEW: return SDL_SYSTEM_CURSOR_SIZEWE;
157  case ImGuiMouseCursor_ResizeNESW: return SDL_SYSTEM_CURSOR_SIZENESW;
158  case ImGuiMouseCursor_ResizeNWSE: return SDL_SYSTEM_CURSOR_SIZENWSE;
159  case ImGuiMouseCursor_Hand: return SDL_SYSTEM_CURSOR_HAND;
160 
161  case ImGuiMouseCursor_None:
162  case ImGuiMouseCursor_COUNT:
163  default: assert(false); return SDL_SYSTEM_CURSOR_ARROW;
164  }
165 }
166 
167 void RendererApp::updateMouseAccordingToImgui()
168 {
169 
170  const ImGuiIO& io = ImGui::GetIO();
171 
172  // Set OS mouse position if requested (rarely used, only when
173  // ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
174  if (io.WantSetMousePos)
175  SDL_WarpMouseInWindow(mainWindow, (int)io.MousePos.x, (int)io.MousePos.y);
176 
177  if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) return;
178 
179  const ImGuiMouseCursor imguiCursor = ImGui::GetMouseCursor();
180  if (io.MouseDrawCursor || imguiCursor == ImGuiMouseCursor_None) {
181  // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
182  SDL_ShowCursor(SDL_FALSE);
183  }
184  else
185  {
186  // Show OS mouse cursor
187  SDL_SetCursor(systemCursors[ImGuiMouseCursorToSDL(imguiCursor)]);
188  SDL_ShowCursor(SDL_TRUE);
189  }
190 }
Definition: Inputs.h:8
#define WS_FALLTHROUGH
Equivalent to the [[fallthrough]] attribute when supported Used to annotate implicit fallthroughs in ...
Definition: Platform.h:157
Implementation of a DCC file decoder.
Helper to load a Diablo 2 palette (.pal/.dat format)
Definition: Palette.h:21