pikaImgui.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. #include <glad/glad.h>
  2. #include <pikaImgui/pikaImgui.h>
  3. #include <GLFW/glfw3.h>
  4. #include "IconsForkAwesome.h"
  5. #include <pikaAllocator/freeListAllocator.h>
  6. #include <logs/assert.h>
  7. #include <compilerIntrinsics.h>
  8. #include <stringManipulation/stringManipulation.h>
  9. #include "imgui_internal.h"
  10. //todo macro to remove imgui impl
  11. #if !(PIKA_SHOULD_REMOVE_IMGUI)
  12. void *pika::pikaImgui::imguiCustomAlloc(size_t sz, void *user_data)
  13. {
  14. pika::memory::FreeListAllocator *allocator = (pika::memory::FreeListAllocator *)user_data;
  15. PIKA_DEVELOPMENT_ONLY_ASSERT(allocator, "no allocator for imgui");
  16. return allocator->allocate(sz);
  17. }
  18. void pika::pikaImgui::imguiCustomFree(void *ptr, void *user_data)
  19. {
  20. pika::memory::FreeListAllocator *allocator = (pika::memory::FreeListAllocator *)user_data;
  21. PIKA_DEVELOPMENT_ONLY_ASSERT(allocator, "no allocator for imgui");
  22. allocator->free(ptr);
  23. }
  24. void pika::pikaImgui::setImguiAllocator(pika::memory::FreeListAllocator &allocator)
  25. {
  26. ::ImGui::SetAllocatorFunctions(imguiCustomAlloc, imguiCustomFree, &allocator);
  27. }
  28. void pika::pikaImgui::initImgui(PikaContext &pikaContext)
  29. {
  30. setImguiAllocator(pikaContext.imguiAllocator);
  31. auto context = ::ImGui::CreateContext();
  32. //ImGui::StyleColorsDark();
  33. imguiThemes::embraceTheDarkness();
  34. ImGuiIO &io = ::ImGui::GetIO();
  35. io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
  36. //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
  37. io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
  38. io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
  39. //io.ConfigViewportsNoAutoMerge = true;
  40. //io.ConfigViewportsNoTaskBarIcon = true;
  41. io.FontGlobalScale = 2;
  42. ImGuiStyle &style = ::ImGui::GetStyle();
  43. if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
  44. {
  45. //style.WindowRounding = 0.0f;
  46. style.Colors[ImGuiCol_WindowBg].w = 0.f;
  47. style.Colors[ImGuiCol_DockingEmptyBg].w = 0.f;
  48. }
  49. ImGui_ImplGlfw_InitForOpenGL(pikaContext.wind, true);
  50. ImGui_ImplOpenGL3_Init("#version 330");
  51. pikaContext.ImGuiContext = context;
  52. //https://pixtur.github.io/mkdocs-for-imgui/site/FONTS/
  53. //https://github.com/juliettef/IconFontCppHeaders
  54. //https://fontawesome.com/v4/icons/
  55. io.Fonts->AddFontFromFileTTF(PIKA_RESOURCES_PATH "arial.ttf", 16);
  56. //ImVector<ImWchar> ranges;
  57. //ImFontGlyphRangesBuilder builder;
  58. //builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters)
  59. //builder.AddChar(0x7262); // Add a specific character
  60. //builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
  61. //builder.BuildRanges(&ranges);
  62. ImFontConfig config;
  63. config.MergeMode = true;
  64. config.GlyphMinAdvanceX = 16.0f; // Use if you want to make the icon monospaced
  65. static const ImWchar icon_ranges[] = {ICON_MIN_FK, ICON_MAX_FK, 0};
  66. io.Fonts->AddFontFromFileTTF(PIKA_RESOURCES_PATH "fontawesome-webfont.ttf", 16.0f, &config, icon_ranges);
  67. {
  68. ImVector<ImWchar> ranges;
  69. ImFontGlyphRangesBuilder builder;
  70. builder.AddChar(0xf016);//ICON_FK_FILE_O
  71. builder.AddChar(0xf114);//ICON_FK_FOLDER_O
  72. builder.BuildRanges(&ranges);
  73. io.Fonts->AddFontFromFileTTF(PIKA_RESOURCES_PATH "fontawesome-webfont.ttf",
  74. 150.f/ io.FontGlobalScale, 0, ranges.Data);
  75. }
  76. io.Fonts->Build();
  77. }
  78. void pika::pikaImgui::setImguiContext(PikaContext pikaContext)
  79. {
  80. ::ImGui::SetCurrentContext(pikaContext.ImGuiContext);
  81. }
  82. void pika::pikaImgui::imguiStartFrame(PikaContext pikaContext)
  83. {
  84. setImguiContext(pikaContext);
  85. ImGui_ImplOpenGL3_NewFrame();
  86. ImGui_ImplGlfw_NewFrame();
  87. ::ImGui::NewFrame();
  88. ::ImGui::DockSpaceOverViewport(::ImGui::GetMainViewport());
  89. }
  90. void pika::pikaImgui::imguiEndFrame(PikaContext pikaContext)
  91. {
  92. setImguiContext(pikaContext);
  93. ::ImGui::Render();
  94. int display_w = 0, display_h = 0;
  95. glfwGetFramebufferSize(pikaContext.wind, &display_w, &display_h);
  96. glViewport(0, 0, display_w, display_h);
  97. ImGui_ImplOpenGL3_RenderDrawData(::ImGui::GetDrawData());
  98. ImGuiIO &io = ::ImGui::GetIO();
  99. // Update and Render additional Platform Windows
  100. // (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere.
  101. // For this specific demo app we could also call glfwMakeContextCurrent(window) directly)
  102. if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
  103. {
  104. //GLFWwindow *backup_current_context = glfwGetCurrentContext();
  105. //ImGui::UpdatePlatformWindows();
  106. //ImGui::RenderPlatformWindowsDefault();
  107. //glfwMakeContextCurrent(backup_current_context);
  108. ::ImGui::UpdatePlatformWindows();
  109. ::ImGui::RenderPlatformWindowsDefault();
  110. pikaContext.glfwMakeContextCurrentPtr(pikaContext.wind); //idea create a class with some functions
  111. }
  112. }
  113. bool pika::pikaImgui::redButton(const char *label, const ImVec2 &size_arg)
  114. {
  115. return colouredButton(label, {1,0,0,1}, size_arg);
  116. }
  117. bool pika::pikaImgui::greenButton(const char *label, const ImVec2 &size_arg)
  118. {
  119. return colouredButton(label, {0,1,0,1}, size_arg);
  120. }
  121. void addColorButton(const char *id, const ImVec4 &col, float outCol[4])
  122. {
  123. if (ImGui::ColorButton(id, col))
  124. {
  125. outCol[0] = col.x;
  126. outCol[1] = col.y;
  127. outCol[2] = col.z;
  128. outCol[3] = col.w;
  129. }
  130. }
  131. bool pika::pikaImgui::ColorEdit4Swatches(const char *label, float col[4], ImGuiColorEditFlags flags)
  132. {
  133. bool rez = ::ImGui::ColorEdit4(label, col);
  134. ::ImGui::BeginGroup();
  135. ::ImGui::PushID(label);
  136. if (::ImGui::BeginPopup("picker"))
  137. {
  138. addColorButton("0", {0,0,0,1}, col); ImGui::SameLine();
  139. addColorButton("1", {1,0,0,1}, col); ImGui::SameLine();
  140. addColorButton("2", {0,1,0,1}, col); ImGui::SameLine();
  141. addColorButton("3", {0,0,1,1}, col); ImGui::SameLine();
  142. addColorButton("4", {1,1,0,1}, col); ImGui::SameLine();
  143. addColorButton("5", {1,0,1,1}, col); ImGui::SameLine();
  144. addColorButton("6", {0,1,1,1}, col); ImGui::SameLine();
  145. addColorButton("7", {1,1,1,1}, col);
  146. ::ImGui::EndPopup();
  147. }
  148. ::ImGui::PopID();
  149. ::ImGui::EndGroup();
  150. return rez;
  151. }
  152. bool pika::pikaImgui::blueButton(const char *label, const ImVec2 &size_arg)
  153. {
  154. return colouredButton(label, {0,0,1,1}, size_arg);
  155. }
  156. bool pika::pikaImgui::colouredButton(const char *label, glm::vec4 color,
  157. const ImVec2 &size_arg)
  158. {
  159. ::ImGui::PushStyleColor(ImGuiCol_Button, {color.r, color.g, color.b, color.a});
  160. auto rez = ::ImGui::Button(label, size_arg);
  161. ::ImGui::PopStyleColor();
  162. return rez;
  163. }
  164. bool pika::pikaImgui::BeginChildFrameColoured(ImGuiID id,
  165. glm::vec4 color, const ImVec2 &size, ImGuiWindowFlags extra_flags)
  166. {
  167. ImGuiContext &g = *::ImGui::GetCurrentContext();
  168. const ImGuiStyle &style = ::ImGui::GetStyle();
  169. ::ImGui::PushStyleColor(ImGuiCol_ChildBg, {color.x,color.y,color.z,color.w});
  170. ::ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding);
  171. ::ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize);
  172. ::ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding);
  173. bool ret = ::ImGui::BeginChild(id, size, true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags);
  174. ::ImGui::PopStyleVar(3);
  175. ::ImGui::PopStyleColor();
  176. return ret;
  177. }
  178. void pika::pikaImgui::addErrorSymbol()
  179. {
  180. ::ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
  181. ::ImGui::Text(ICON_FK_TIMES_CIRCLE " ");
  182. ::ImGui::PopStyleColor();
  183. }
  184. void pika::pikaImgui::addWarningSymbol()
  185. {
  186. ::ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 255, 0, 255));
  187. ::ImGui::Text(ICON_FK_EXCLAMATION_TRIANGLE " ");
  188. ::ImGui::PopStyleColor();
  189. }
  190. void pika::pikaImgui::helpMarker(const char *desc)
  191. {
  192. ::ImGui::TextDisabled("(?)");
  193. if (::ImGui::IsItemHovered())
  194. {
  195. ::ImGui::BeginTooltip();
  196. ::ImGui::PushTextWrapPos(::ImGui::GetFontSize() * 35.0f);
  197. ::ImGui::TextUnformatted(desc);
  198. ::ImGui::PopTextWrapPos();
  199. ::ImGui::EndTooltip();
  200. }
  201. }
  202. //https://github.com/ocornut/imgui/discussions/3862
  203. void pika::pikaImgui::alignForWidth(float width, float alignment)
  204. {
  205. ImGuiStyle &style = ::ImGui::GetStyle();
  206. float avail = ::ImGui::GetContentRegionAvail().x;
  207. float off = (avail - width) * alignment;
  208. if (off > 0.0f)
  209. ::ImGui::SetCursorPosX(::ImGui::GetCursorPosX() + off);
  210. }
  211. static int sizesType = 0;
  212. void pika::pikaImgui::displayMemorySizeValue(size_t value)
  213. {
  214. switch (sizesType)
  215. {
  216. case 0:
  217. ImGui::Text("%" IM_PRIu64 " (bytes)", value);
  218. break;
  219. case 1:
  220. ImGui::Text("%f (KB)", pika::BYTES_TO_KB(value));
  221. break;
  222. case 2:
  223. ImGui::Text("%f (MB)", pika::BYTES_TO_MB(value));
  224. break;
  225. case 3:
  226. ImGui::Text("%f (GB)", pika::BYTES_TO_GB(value));
  227. break;
  228. default:
  229. PIKA_UNREACHABLE();
  230. }
  231. //ImGui::Text("%" IM_PRIu64 " (bytes)", value);
  232. }
  233. void pika::pikaImgui::displayMemorySizeToggle()
  234. {
  235. ImGui::Combo("Sizes type##pika", &sizesType, "Bytes\0KB\0MB\0GB\0");
  236. }
  237. void pika::pikaImgui::removeFocusToCurrentWindow()
  238. {
  239. auto *g = ::ImGui::GetCurrentContext();
  240. if (g)
  241. {
  242. g->NavWindow = 0;
  243. }
  244. }
  245. void pika::pikaImgui::FileSelector::setInfo(std::string title, std::string pwd, std::vector<std::string> typeFilters)
  246. {
  247. fileBrowser.SetTitle(std::move(title));
  248. fileBrowser.SetPwd(std::move(pwd));
  249. if (!typeFilters.empty())
  250. {
  251. fileBrowser.SetTypeFilters(std::move(typeFilters));
  252. }
  253. }
  254. bool pika::pikaImgui::FileSelector::run(int id)
  255. {
  256. ImGui::PushID(id);
  257. bool r = ImGui::InputText(fileBrowser.getTitle().c_str(), this->file, sizeof(file), ImGuiInputTextFlags_EnterReturnsTrue);
  258. ImGui::SameLine();
  259. if (ImGui::Button("Select file"))
  260. {
  261. fileBrowser.Open();
  262. }
  263. fileBrowser.Display();
  264. if (fileBrowser.HasSelected())
  265. {
  266. pika::strlcpy(file, fileBrowser.GetSelected().string(), sizeof(file));
  267. fileBrowser.ClearSelected();
  268. fileBrowser.Close();
  269. r = true;
  270. }
  271. ImGui::PopID();
  272. return r;
  273. }
  274. #else
  275. void pika::pikaImgui::alignForWidth(float width, float alignment) {};
  276. void pika::pikaImgui::helpMarker(const char *desc) {};
  277. void pika::pikaImgui::addWarningSymbol() {};
  278. void pika::pikaImgui::addErrorSymbol() {};
  279. void pika::pikaImgui::imguiEndFrame(PikaContext pikaContext) {};
  280. void pika::pikaImgui::imguiStartFrame(PikaContext pikaContext) {};
  281. void pika::pikaImgui::setImguiContext(PikaContext pikaContext) {};
  282. void pika::pikaImgui::initImgui(PikaContext &pikaContext) {};
  283. void pika::pikaImgui::setImguiAllocator(pika::memory::FreeListAllocator &allocator) {};
  284. bool pika::pikaImgui::FileSelector::run(int id) { return false; };
  285. void pika::pikaImgui::FileSelector::setInfo(std::string title, std::string pwd, std::vector<std::string> typeFilters) {};
  286. #endif