Centralizes shared ImGui styling for openFrameworks apps
README
ofxImGuiStyle

ofxImGuiStyle is an umbrella addon for ofxImGui that ships four independent, pure Dear ImGui sub-libraries plus a tiny openFrameworks-aware glue layer:ImTheme(ImTheme.{h,cpp}+ImThemeRegistry.{h,cpp})
Darcula, DarculaDarker, LightRounded, ImGuiColorsDark, MaterialFlat, ...) plus an open-ended RegisterCustom registry for addons / apps to contribute their own (tb303, tr808, tr909, wasp, ...), plus a ShowSelector / ShowThemeTweakGui UI. ImFonts(ImFonts.{h,cpp})
IconButton / IconButtonGhost widgets sized from the current row height. ImKnobs(ImKnobs.h+ vendoredsrc/imgui-knobs/)
ImLed(ImLed.{h,cpp})
ImMidi(ImMidi.h,ImMidiMapper.h,ImMidiRegistry.{h,cpp})
ofxMidi I/O when that addon is linked; otherwise use pushCC() yourself. IconsFontAwesome5.h— vendored constants from
Fonts and themes are deliberately kept in the same addon: in real apps the two are coupled (different themes presume specific x-height / weight, icon buttons depend on FA glyphs being merged into the active font).
Both APIs are pure Dear ImGui — they don't include any openFrameworks header. The only OF coupling lives in callers that already own an
ofxImGui::Gui (passed in by the caller for setDefaultFont / rebuildFontsTexture).Quick start
Add both addons to
addons.make:ofxImGui
ofxImGuiStyleThen load fonts + apply a theme after
ofxImGui::Gui::setup():#include "ofxImGui.h"
include "ImTheme.h>"
include "ImThemeRegistry.h"
include "ImFonts.h"
ofxImGui::Gui gui;
void ofApp::setup() {
gui.setup();
if (ImFont f = ImFonts::LoadDefaultFonts(ImGui::GetIO().Fonts, 15.f))
gui.setDefaultFont(f);
gui.rebuildFontsTexture();
// Theme + HiDPI scale in one call (DetectOsScale when uiScale <= 0).
ImTheme::Setup("DarculaDarker");
}Selecting + tweaking themes at runtime
static std::string themeId = "DarculaDarker";
if (ImTheme::ShowSelector(themeId)) { } // applies + re-commits scale
ImTheme::ShowThemeTweakGui(&tweaks);ShowSelector applies the picked theme and automatically snapshots the unscaled baseline and re-applies the stored UI scale — no extra calls needed.UI scale
float uiScale = ImTheme::UIScale();
if (ImGui::SliderFloat("Scale", &uiScale, 0.75f, 2.5f))
ImTheme::SetUIScale(uiScale);Setup, ApplyByName, and ShowSelector all re-commit scale when the theme changes. SetUIScale only rescales from the existing baseline (fast path for sliders).Hand-tweaking metrics
If you edit
ImGui::GetStyle() after a theme (extra padding, rounding, etc.), call Commit() once to snapshot and re-apply scale:ImTheme::Setup(ImTheme::Theme_DarculaDarker);
ImGui::GetStyle().WindowPadding = ImVec2(14, 12);
// ...
ImTheme::Commit();Registering a custom theme from an addon
ImTheme::RegisterCustom({
"myaddon",
"My Addon",
[] {
ImGui::GetStyle() = ImGuiStyle{};
ImGui::StyleColorsDark();
// ...
}
});
ImTheme::Setup("myaddon");Guard with
__has_include if the addon must build without ofxImGuiStyle (see ofx303 / 808 / 909 / Wasp).Style snapshot files (.bin)
ImTheme::SaveStyle(ofToDataPath("my_style.bin", true).c_str());
if (ImTheme::LoadStyle(path)) {
ImTheme::ApplyCompactMetrics();
ImTheme::Commit();
}JetBrains Mono (code + markdown)
Four faces are embedded and loaded via
LoadJetBrainsMono() or individually via LoadJetBrainsMonoFont(..., JetBrainsMonoVariant::Regular | Bold | Italic | BoldItalic).#include "ImFonts.h"
ImFont ui = ImFonts::LoadDefaultFonts(ImGui::GetIO().Fonts, 15.f);
gui.setDefaultFont(ui);
ImFont* code = ImFonts::LoadCodeEditorFont(ImGui::GetIO().Fonts, 14.f);
codeEditor->setFont(code);
// Or load Regular / Bold / Italic / BoldItalic together (e.g. for ofxImGuiMarkdown):
ImFonts::JetBrainsMonoFonts jbm = ImFonts::LoadJetBrainsMono(ImGui::GetIO().Fonts, 15.f);
renderer.regularFont = jbm.regular;
renderer.boldFont = jbm.bold;
renderer.italicFont = jbm.italic;
renderer.boldItalicFont = jbm.boldItalic;
renderer.monoFont = jbm.regular;
gui.rebuildFontsTexture();Regenerate embedded headers after updating the TTFs:
python addons/ofxImGuiStyle/src/gen_font_headers.pySource files are read from
addons/JetBrainsMono-2.304/fonts/ttf/.Icon buttons (ImFonts)
#include "ImFonts.h"
include "IconsFontAwesome5.h"
if (ImFonts::IconButtonGhost(visible ? ICON_FA_EYE : ICON_FA_EYE_SLASH, "##eye"))
visible = !visible;Knobs (ImKnobs)
#include "ImKnobs.h"
float cutoff = 0.5f;
if (ImGuiKnobs::Knob("Cutoff", &cutoff, 0.f, 1.f, 0.f, "%.2f",
ImGuiKnobVariant_WiperDot, 42.f))
{
// value changed
}Status LEDs (ImLed)
#include "ImLed.h"
// Any colour
ImLed::Draw(ImVec4(0.2f, 0.9f, 0.3f, 1.f), { .label = "Ready" });
// Presets
ImLed::Draw(ImLed::ColorsOk(), { .label = "Loaded" });
ImLed::Draw(ImLed::ColorsWarn(), { .label = "Pending" });
ImLed::Draw(ImLed::ColorsError());
// Full-screen grid (screen-space rectangle)
ImLed::DrawGrid(rectMin, rectMax, 32, 20, IM_COL32(255, 40, 40, 255));See
example_Led for a full-viewport LED matrix with colour + animation controls.MIDI mapping (ImMidi)
Requires ofxMidi in
addons.make for hardware ports. Wire in your app (e.g. tb303::midiBridge::setup() via tb303::kit::setupMidi()).#include "ImMidi.h"
ImMidi::Setup(ofToDataPath("midiMapper.json", true));
void ofApp::update() {
ImMidi::Update();
}
// inside ImGui:
ImGuiKnobs::Knob("Cutoff", &cutoff, 0.f, 1.f);
ImMidi::Mapper().watchLast("cutoff", &cutoff, 0.f, 1.f, "Cutoff");
ImMidi::DrawEditor(&showMidiMapper);Right-click any registered control → MIDI Learn… → move a hardware knob.
Examples
example_Basic— fonts, icons, knobs, theme selector, scale slider,.binI/O.example_Led— full-screen LED matrix; arbitrary colours, grid size, wave animation.example_LumaStudio— desktop-app mockup with custom padding +Commit().
Attribution
ImTheme.{h,cpp}— adapted from
IconsFontAwesome5.h— juliettef/IconFontCppHeaders (MIT).src/imgui-knobs/— altschuler/imgui-knobs (MIT).ImMidiMapper.h— ImMidiMapper (MIT).- Bundled fonts: Input Sans Regular, Font Awesome 5 Free Solid, and
ofxAddons