Return references from Id lookups, and remove the glad dependency - #54
Conversation
…pendency Closes #52. channel(Id) and operator[](Id), const and non-const, returned Channel* but could never return nullptr: they resolve through unordered_map::at, which throws std::out_of_range on a miss. The pointer return only invited null checks that are dead code, and it was inconsistent with the index and name overloads, which return references. They now return references too. Miss behavior is unchanged; callers replace -> with . at the call site. Closes #53. glad 0.1.36 is the final 0.1.x release and declares cmake_minimum_required(VERSION 3.0), which CMake 4 rejects, so the examples carried a CMAKE_POLICY_VERSION_MINIMUM workaround. glad 2.x is not a drop-in: it has no root CMakeLists.txt and needs Python at configure time. Removing glad entirely turned out to be simpler than migrating. The ImGui backend already bundles its own loader and uses it when no loader macro is defined, and the only direct GL calls in curve_visualization are glViewport, glClearColor and glClear, which are OpenGL 1.1 core and come from the GL header GLFW includes. The workaround goes with it. Verified against CMake 4.4 with no policy override: library, tests and both examples build, and all 70 tests pass. The viewer was run before and after; both write an identical imgui.ini window layout, so the change is behavior-neutral. Also ignores imgui.ini, which the example writes into the working directory, and build-*/ for alternate build trees.
Running the example from a clean checkout showed no plot at all. The plot window was opened with no size, so ImGui auto-fitted it to its content. That content is ImPlot sized ImVec2(-1, -1), meaning fill the available space. On the first frame neither had a size to work from, so both resolved to nothing and the window collapsed to 32x39 behind the curve editor, which is docked at the same default position. ImGui then wrote that size to imgui.ini, so it stayed collapsed on every later run until the window was found and dragged out by hand. Both windows now get a first-run position and size derived from the viewport work area, side by side. ImGuiCond_FirstUseEver means a layout the user has arranged is still loaded from imgui.ini as before. This is long-standing behavior, not a regression: a build of bd5f9f9, before any change in this branch, writes the same 32x39 plot window. It was only ever masked by a saved imgui.ini.
Added: the example rendered no plot on a clean checkoutInvestigated whether this branch caused it. It did not — but it is a real bug Root cause. Not a regression. A build of
It was only ever masked by a saved Fix. Both windows get a first-run position and size derived from the After the fix, a clean first run gives: Verified visually: the plot renders with axes, all five curves, and their |
Ids could be fabricated by any caller. That was never a safety hole -- a made-up id resolves through the same map as a real one and simply throws when absent -- but ids come from a single counter shared by every Animation, so a hand-made id could silently match an unrelated channel. The constructor is now private, with Animation and Channel as friends. Callers obtain ids from Channel::id(), or Id::invalid() for a sentinel. No test needed friending. The tests that fabricated ids now use real ones, and the 'valid but not in this animation' cases take an id from a second Animation, which is what that case actually looks like in practice. A static_assert pins the constructor down. sort_channels() sorts by name; the overload taking a comparator covers any other ordering. Both are stable, so channels sharing a name keep their relative order. Only the owning pointers are reordered, so the Channel objects stay put: the id map remains valid and references taken before the sort keep working. That invariant is covered by a test. 72 tests pass, up from 70.
Removed comments about ImGui OpenGL3 backend loader.
Closes #52. Closes #53.
#52 —
channel(Id)returned a pointer that could never be nullBoth
Idoverloads resolve throughunordered_map::at, which throws on amiss, so the only outcomes were a valid non-null pointer or an exception. The
Channel*return invited null checks that are dead code, and it was the oddone out — the index and name overloads return references.
All four (
channel(Id)/operator[](Id), const and non-const) now returnreferences. Miss behavior is unchanged: still
std::out_of_range.Breaking for callers, mechanically:
->becomes..The test updates deliberately keep
&a == &bidentity comparisons rather thanrewriting to
a == b—Channel::operator==is value equality, so thesimpler-looking form would have silently weakened 49 assertions from identity
to equality.
#53 — glad removal, and the CMake 4 workaround goes with it
glad 0.1.36 is the last 0.1.x release and declares
cmake_minimum_required(VERSION 3.0), which CMake 4 rejects — hence theCMAKE_POLICY_VERSION_MINIMUM 3.5workaround. glad 2.x is not a drop-in: noroot
CMakeLists.txt, and it needs Python at configure time.Removing glad was simpler than migrating to it:
imgui_impl_opengl3_loader.hand uses it when noloader macro is defined — the
IMGUI_IMPL_OPENGL_LOADER_GLADdefinition wasthe only thing redirecting it to glad
curve_visualizationareglViewport,glClearColorandglClear, all OpenGL 1.1 core, available from the GLheader GLFW includes and already linked via
OpenGL::GLOne dependency and one workaround removed together.
Verification
Against CMake 4.4 with no policy override: configure, build of library +
tests + both examples, and 70/70 tests pass.
The viewer was launched from a build with glad and a build without, each
from a clean layout. Both write an identical
imgui.ini:###CurvesPlotPos=60,60 Size=32,39Pos=60,60 Size=32,39Curve EditorPos=60,60 Size=156,116Pos=60,60 Size=156,116So the change is behavior-neutral. Note this also documents a pre-existing
quirk, present on both sides and not addressed here: on a first run with no
saved layout the plot window auto-sizes to 32x39 and sits behind the Curve
Editor, so a new user sees no plot until they resize or dock it. Worth a
separate issue.
Also
imgui.iniis written into the working directory by the example and was notignored, so it appeared as untracked noise in the repo root. Now ignored, along
with
build-*/.