// This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would be // appreciated but is not required. // 2. Altered source versions must be plainly marked as such, and must not be // misrepresented as being the original software. // 3. This notice may not be removed or altered from any source distribution. // WHAT'S THIS // Extension to the imgui library v.1.21 wip (https://github.com/ocornut/imgui) // to support saving/loading imgui styles. // USAGE: /* 1) Compile this cpp file 2) In your main.cpp just add (without including any additional file: there's no header!): extern bool ImGuiSaveStyle(const char* filename,const ImGuiStyle& style); extern bool ImGuiLoadStyle(const char* filename,ImGuiStyle& style); 3) Use them together with ImGui::GetStyle() to save/load the current style. ImGui::GetStyle() returns a reference of the current style that can be set/get. Please note that other style options are not globally serializable because they are "window flags", that must be set on a per-window basis (for example border,titlebar,scrollbar,resizable,movable,per-window alpha). To edit and save a style, you can use the default ImGui example and append to the "Debug" window the following code: ImGui::Text("\n"); ImGui::Text("Please modify the current style in:"); ImGui::Text("ImGui Test->Window Options->Style Editor"); static bool loadCurrentStyle = false; static bool saveCurrentStyle = false; static bool resetCurrentStyle = false; loadCurrentStyle = ImGui::Button("Load Saved Style"); saveCurrentStyle = ImGui::Button("Save Current Style"); resetCurrentStyle = ImGui::Button("Reset Current Style"); if (loadCurrentStyle) { if (!ImGuiLoadStyle("./myimgui.style",ImGui::GetStyle())) { fprintf(stderr,"Warning: \"./myimgui.style\" not present.\n"); } } if (saveCurrentStyle) { if (!ImGuiSaveStyle("./myimgui.style",ImGui::GetStyle())) { fprintf(stderr,"Warning: \"./myimgui.style\" cannot be saved.\n"); } } if (resetCurrentStyle) ImGui::GetStyle() = ImGuiStyle(); */ #include // From :-------------------------------------------------------- #include // vsnprintf #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) static size_t ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) { va_list args; va_start(args, fmt); int w = vsnprintf(buf, buf_size, fmt, args); va_end(args); buf[buf_size-1] = 0; return (w == -1) ? buf_size : (size_t)w; } //--------------------------------------------------------------------------- #include bool ImGuiSaveStyle(const char* filename,const ImGuiStyle& style) { // Write .style file FILE* f = fopen(filename, "wt"); if (!f) return false; fprintf(f, "[Alpha]\n%1.3f\n", style.Alpha); fprintf(f, "[WindowPadding]\n%1.3f %1.3f\n", style.WindowPadding.x,style.WindowPadding.y); fprintf(f, "[WindowMinSize]\n%1.3f %1.3f\n", style.WindowMinSize.x,style.WindowMinSize.y); fprintf(f, "[FramePadding]\n%1.3f %1.3f\n", style.FramePadding.x,style.FramePadding.y); fprintf(f, "[FrameRounding]\n%1.3f\n", style.FrameRounding); fprintf(f, "[ItemSpacing]\n%1.3f %1.3f\n", style.ItemSpacing.x,style.ItemSpacing.y); fprintf(f, "[ItemInnerSpacing]\n%1.3f %1.3f\n", style.ItemInnerSpacing.x,style.ItemInnerSpacing.y); fprintf(f, "[TouchExtraPadding]\n%1.3f %1.3f\n", style.TouchExtraPadding.x,style.TouchExtraPadding.y); fprintf(f, "[AutoFitPadding]\n%1.3f %1.3f\n", style.AutoFitPadding.x,style.AutoFitPadding.y); fprintf(f, "[WindowFillAlphaDefault]\n%1.3f\n", style.WindowFillAlphaDefault); fprintf(f, "[WindowRounding]\n%1.3f\n", style.WindowRounding); fprintf(f, "[TreeNodeSpacing]\n%1.3f\n", style.TreeNodeSpacing); fprintf(f, "[ColumnsMinSpacing]\n%1.3f\n", style.ColumnsMinSpacing); fprintf(f, "[ScrollBarWidth]\n%1.3f\n", style.ScrollBarWidth); for (size_t i = 0; i != ImGuiCol_COUNT; i++) { const ImVec4& c = style.Colors[i]; fprintf(f, "[%s]\n", ImGui::GetStyleColName(i));//ImGuiColNames[i]); fprintf(f, "%1.3f %1.3f %1.3f %1.3f\n",c.x,c.y,c.z,c.w); } fprintf(f,"\n"); fclose(f); return true; } bool ImGuiLoadStyle(const char* filename,ImGuiStyle& style) { // Load .style file if (!filename) return false; // Load file into memory FILE* f; if ((f = fopen(filename, "rt")) == NULL) return false; if (fseek(f, 0, SEEK_END)) { fclose(f); return false; } const long f_size_signed = ftell(f); if (f_size_signed == -1) { fclose(f); return false; } size_t f_size = (size_t)f_size_signed; if (fseek(f, 0, SEEK_SET)) { fclose(f); return false; } char* f_data = (char*)ImGui::MemAlloc(f_size+1); f_size = fread(f_data, 1, f_size, f); // Text conversion alter read size so let's not be fussy about return value fclose(f); if (f_size == 0) { ImGui::MemFree(f_data); return false; } f_data[f_size] = 0; // Parse file in memory char name[128];name[0]='\0'; const char* buf_end = f_data + f_size; for (const char* line_start = f_data; line_start < buf_end; ) { const char* line_end = line_start; while (line_end < buf_end && *line_end != '\n' && *line_end != '\r') line_end++; if (name[0]=='\0' && line_start[0] == '[' && line_end > line_start && line_end[-1] == ']') { ImFormatString(name, IM_ARRAYSIZE(name), "%.*s", line_end-line_start-2, line_start+1); //fprintf(stderr,"name: %s\n",name); // dbg } else if (name[0]!='\0') { float *pf[4]= {0,0,0,0}; int npf = 0; // parsing 'name' here by filling the fields above { if (strcmp(name, "Alpha")==0) {npf=1;pf[0]=&style.Alpha;} else if (strcmp(name, "WindowPadding")==0) {npf=2;pf[0]=&style.WindowPadding.x;pf[1]=&style.WindowPadding.y;} else if (strcmp(name, "WindowMinSize")==0) {npf=2;pf[0]=&style.WindowMinSize.x;pf[1]=&style.WindowMinSize.y;} else if (strcmp(name, "FramePadding")==0) {npf=2;pf[0]=&style.FramePadding.x;pf[1]=&style.FramePadding.y;} else if (strcmp(name, "FrameRounding")==0) {npf=1;pf[0]=&style.FrameRounding;} else if (strcmp(name, "ItemSpacing")==0) {npf=2;pf[0]=&style.ItemSpacing.x;pf[1]=&style.ItemSpacing.y;} else if (strcmp(name, "ItemInnerSpacing")==0) {npf=2;pf[0]=&style.ItemInnerSpacing.x;pf[1]=&style.ItemInnerSpacing.y;} else if (strcmp(name, "TouchExtraPadding")==0) {npf=2;pf[0]=&style.TouchExtraPadding.x;pf[1]=&style.TouchExtraPadding.y;} else if (strcmp(name, "AutoFitPadding")==0) {npf=2;pf[0]=&style.AutoFitPadding.x;pf[1]=&style.AutoFitPadding.y;} else if (strcmp(name, "WindowFillAlphaDefault")==0) {npf=1;pf[0]=&style.WindowFillAlphaDefault;} else if (strcmp(name, "WindowRounding")==0) {npf=1;pf[0]=&style.WindowRounding;} else if (strcmp(name, "TreeNodeSpacing")==0) {npf=1;pf[0]=&style.TreeNodeSpacing;} else if (strcmp(name, "ColumnsMinSpacing")==0) {npf=1;pf[0]=&style.ColumnsMinSpacing;} else if (strcmp(name, "ScrollBarWidth")==0) {npf=1;pf[0]=&style.ScrollBarWidth;} // all the colors here else { for (int j=0;j to help parsing float x, y; int i; if (sscanf(line_start, "Pos=%f,%f", &x, &y) == 2) settings->Pos = ImVec2(x, y); else if (sscanf(line_start, "Size=%f,%f", &x, &y) == 2) settings->Size = ImMax(ImVec2(x, y), g.Style.WindowMinSize); else if (sscanf(line_start, "Collapsed=%d", &i) == 1) settings->Collapsed = (i != 0); */ //--------------------------------------------------------------------------------- name[0]='\0'; // mandatory } line_start = line_end+1; } // Release memory ImGui::MemFree(f_data); return true; }