The new ver­sion puts a fo­cus on us­ab­il­ity with tweak­able con­stants for live cod­ing, Dear ImGui in­teg­ra­tion, new pack­ages, Gradle-less An­droid de­vel­op­ment, com­pile time spee­dup and oth­er gen­er­al pol­ish­ing.

Tweak­able con­stants for live cod­ing

While Mag­num sup­por­ted code hot-re­load through its Plu­gin­Man­ager lib­rary from the very be­gin­ning, now there’s a new, much faster — but also more re­stric­ted — coun­ter­part to it. In the con­text of live cod­ing, 90% it­er­a­tions is done on the data, fid­dling with val­ues un­til they feel right. Even wait­ing few seconds for code to re­com­pile after each such it­er­a­tion is still very time-con­sum­ing and of­ten the pro­cess is ab­ruptly ended when the value is “good enough”. So, what if we wouldn’t need to re­com­pile?

Util­ity::Tweak­able is re­spons­ible for all the ma­gic shown in the above video and the gist of it is an abil­ity to up­date a run­ning ap­plic­a­tion with con­stants from mod­i­fied source code — without re­com­pil­a­tion. The video also shows an ad­vanced IDE in­teg­ra­tion with a col­or pick­er, how­ever the ba­sic ap­proach of code changes be­ing re­flec­ted im­me­di­ately works with any ed­it­or.

This fea­ture is still very ex­per­i­ment­al, on the roadmap is a sup­port for hot code re­load and tweak­able con­stants un­der Em­scripten and on An­droid, we also plan on re­leas­ing IDE in­teg­ra­tion plu­gins sim­il­ar to the one above once they reach a more ma­ture state.

Dear ImGui in­teg­ra­tion is now of­fi­cial

In­teg­ra­tion of Dear ImGui in­to Mag­num star­ted as a com­munity pro­ject and got so widely used with mul­tiple forked ver­sions that it made sense to turn it in­to an of­fi­cially main­tained lib­rary. It’s now avail­able as ImGui­In­teg­ra­tion, part of the mag­num-in­teg­ra­tion re­pos­it­ory. The cor­res­pond­ing ex­ample is in­teg­rated as well and has a WebGL 2 ver­sion avail­able:

Dear ImGui example screenshot
Dear ImGui Ex­ample webgl1 ui
HiDPI-en­abled im­me­di­ate-mode GUI ren­der­ing us­ing the Dear ImGui lib­rary.

In­stead of hav­ing the Dear ImGui sources bundled with Mag­num, there’s a new Find­ImGui.cmake mod­ule that takes care of find­ing the sources and com­pil­ing them as part of ImGui­In­teg­ra­tion. That gives you the pos­sib­il­ity of al­ways be­ing on ex­actly the ver­sion (or a fork) you need and the flex­ib­il­ity to bundle it your own way. Some pack­aging sys­tems (such as Vcp­kg) provide Dear ImGui as a lib­rary, that’s sup­por­ted too.

An­im­a­tion eas­ings lib­rary

The an­im­a­tion lib­rary, which de­b­uted in the 2018.10 re­lease, re­ceived a col­lec­tion of vari­ous eas­ing func­tions to add life to your an­im­a­tions. To provide a com­plete and cor­rect ref­er­ence for not just Mag­num users, the func­tions are also well-doc­u­mented, with a cor­res­pond­ing math equa­tion, plot and the equi­val­ent Bézi­er rep­res­ent­a­tion, if it ex­ists. See the An­im­a­tion::Eas­ing namespace for your­self. Us­age is straigh­for­ward — simply modi­fy the in­ter­pol­a­tion factor para­met­er with them:

Vector3 result = Math::lerp(a, b, Animation::Easing::bounceIn(t));
Animation::Easing documentation

An­droid de­vel­op­ment, but without the pain

Con­trary to pop­u­lar be­lief, neither An­droid Stu­dio nor Gradle is re­quired to de­vel­op apps for An­droid. With 2019.01, there’s a new CMake macro android_create_apk() that al­lows you to cre­ate an APK dir­ectly from CMake, without need­ing to touch Gradle at all:

find_package(Magnum REQUIRED AndroidApplication)

add_library(my-application SHARED MyApp.cpp)
target_link_libraries(my-application PRIVATE
    Magnum::Magnum
    Magnum::Application)

android_create_apk(my-application AndroidManifest.xml)

As a bo­nus, us­ing this macro also adds a new build tar­get which al­lows you to build, in­stall, pack­age, sign and de­ploy an APK to a device with a single com­mand — for ex­ample when us­ing Ninja:

$ ninja my-application-deploy
[5/5] Installing my-application.apk
Success

This func­tion­al­ity is cur­rently ex­per­i­ment­al and very lim­ited, but it can save you sev­er­al seconds on each de­ploy com­pared to equi­val­ent work­flow us­ing Gradle. See the very ex­tens­ive An­droid build­ing docs for more in­form­a­tion.

Drop­ping GCC 4.7 and CMake 2.8.12 sup­port

With Ubuntu 14.04 go­ing away even on Trav­is CI, it was a time to say good­bye to com­pat­ib­il­ity with the old CMake 2.8.12. How­ever, ver­sion 3.0 had some is­sues with im­por­ted tar­gets, so the min­im­al re­quired ver­sion is now 3.1. All suf­fi­ciently mod­ern Linux dis­tri­bu­tions (ex­cept Debi­an Jessie) are already on ver­sions past 3.1, so this should not be a prob­lem — and if not, you can al­ways down­load and use an of­fi­cial CMake bin­ary on af­fected sys­tems.

While at it, sup­port for GCC 4.7 was dropped as well, since this is the last com­piler that didn’t sup­port rvalue over­loads for this. Min­im­al ver­sion is now 4.8.1, since 4.8 is still used on Cen­tOS 7 and we don’t want to pre­vent Mag­num from be­ing used on serv­er side as well.

As far as C++ stand­ard goes, Mag­num is go­ing to stay on C++11 for the fore­see­able fu­ture. Ex­cept for ex­ten­ded constexpr, neither C++14 nor C++17 of­fers any­thing that would lead to sig­ni­fic­ant im­prove­ments on the lib­rary side and the minor ad­vant­ages are not worth the com­pile time slow­downs due to in­crease in STL head­er bloat. How­ever, Mag­num is not for­bid­ding you to jump to new­er C++ stand­ards — if you need the re­cent fea­tures, feel free to use them.

On­go­ing com­pile-time and bin­ary size im­prove­ments

Speak­ing of STL head­er bloat, and not en­tirely un­re­lated to the re­cent out­rage about “The State Of C++”, Mag­num is un­der­go­ing a gen­er­al up­date that aims for shortened com­pile times and smal­ler bin­ary sizes, es­pe­cially in WebAssembly builds. Right now, this is mainly about re­du­cing the amount of STL in­cludes in head­ers and be­cause not all ba­sic­ally no STL con­tain­ers can be eas­ily for­ward-de­clared, it means re­pla­cing them with cus­tom al­tern­at­ives.

As not all up­dates can be made in a back­wards-com­pat­ible way, the change is hap­pen­ing gradu­ally — this re­lease re­places most uses of std::unique_ptr and std::ref­er­en­ce_wrap­per with Con­tain­ers::Point­er and Con­tain­ers::Ref­er­en­ce in or­der to avoid heavy <memory> and <functional> in­cludes and the work will con­tin­ue in fu­ture re­leases.

As with all oth­er design de­cisions in Mag­num, this doesn’t mean the en­gine will now un­con­di­tion­ally force you to use some ali­en types. In­stead, you have a choice — if you feel more com­fort­able us­ing stand­ard types, your team is not ready to learn yet an­oth­er API or you’re in­ter­act­ing with a 3rd party lib that uses them any­way, just keep us­ing them, the new Mag­num point­er and ref­er­ence types are im­pli­citly con­vert­ible to and from the STL equi­val­ents. On the oth­er hand, if you really care about your com­pile times and de­bug per­form­ance, the new types are for you — and you’re en­cour­aged to use them else­where as well, not just when in­ter­act­ing with Mag­num.

Single-head­er ver­sions of Mag­num APIs

A re­lated on­go­ing pro­ject, which is ba­sic­ally a side-product of the above “head­er diet” work, is avail­ab­il­ity of vari­ous Mag­num APIs as single-head­er lib­rar­ies — with a fo­cus on ease of in­teg­ra­tion, fast com­pile times and small file sizes, while in­her­it­ing >99% test cov­er­age and ex­tens­ive doc­u­ment­a­tion that’s own to the Mag­num pro­ject it­self.

Com­bin­ing all that is only pos­sible be­cause the func­tion­al­ity is primar­ily main­tained, doc­u­mented and tested as part of Mag­num, where it can make use of all the in­fra­struc­ture and tool­ing. Se­lec­ted func­tion­al­ity is then ex­trac­ted via a script that strips it of com­ments, verb­ose doc­u­ment­a­tion blocks and rarely used func­tion­al­ity. The res­ult is a small self-con­tained file, how­ever still with the con­fid­ence of all code paths be­ing prop­erly tested and doc­u­mented.

The mag­num-singles re­pos­it­ory is a new home for the single-head­er ver­sions of vari­ous Mag­num APIs. At the mo­ment the fol­low­ing low-level con­tain­ers are present:

Lib­rary LoC Pre­pro­cessed LoC De­scrip­tion
Cor­rade­Op­tion­al.h 328 2742 See Con­tain­ers::Op­tion­al docs
Cor­rade­Point­er.h 259 2321 See Con­tain­ers::Point­er docs
Cor­radeRefer­en­ce.h 115 1639 See Con­tain­ers::Ref­er­en­ce docs
Cor­ra­de­Scope­Guard.h 108 26 See Con­tain­ers::Scope­Guard docs

More lib­rar­ies are to come as the head­er cleanup ad­vances fur­ther. The gen­er­al rule for ex­pos­ing a fea­ture as a single-head­er lib­rary is how much it in­flates after pre­pro­cess­ing — cur­rently the soft up­per lim­it is 10k lines. For com­par­is­on, not even the <string> head­er fits in there, as it has 12k; on the oth­er hand I’m pretty con­fid­ent I can squeeze the whole Math lib­rary un­der this lim­it.

Vulkan++

As an­oth­er small piece of the Vulkan puzzle, the new Mag­num/Vk/In­teg­ra­tion.h head­er provides con­ver­sion between ba­sic Vulkan types and their equi­val­ents from the Math lib­rary, to­geth­er with enum trans­la­tion con­trib­ut­ing to a smooth­er in­ter­ac­tion with raw Vulkan code.

VkOffset2D a{64, 32};
Vector2i b(a);

using namespace Math::Literals;
VkClearColorValue c = VkClearColorValue(0x5297d7_srgbf);

Since Mag­num now provides math in­teg­ra­tion for quite a few lib­rar­ies, in­clud­ing ImGui, there’s a full list provid­ing de­tailed in­form­a­tion about avail­able con­ver­sions for every third-party API.

Qual­ity-of-Life im­prove­ments in the doc­u­ment­a­tion

The Mag­num doc­u­ment­a­tion re­ceived a lar­ger up­date, mainly re­lated to search func­tion­al­ity. It’s now also show­ing the cor­res­pond­ing #include for each API — and that’s not just classes, but also free func­tions, types and single-file namespaces. De­tails in this art­icle.

Include information for free namespace members

Hunter, MSYS2 and Con­an pack­ages

Thanks to our ded­ic­ated com­munity, Cor­rade, Mag­num and Mag­num Plu­gins now have MSYS2 pack­ages. These are based off the Arch­Linux PKGBUILDs (since both use pacman as the pack­age man­ager) and there’s both a in-source pack­age, build­ing the cur­rently checked out work­ing tree; and a stable one, down­load­ing a re­lease tar­ball.

Apart from MSYS2, Mag­num is now avail­able in both Con­an and Hunter pack­age man­agers. While Hunter is CMake-based and works dir­ectly from in­side the CMake build dir­ect­ory without any ad­di­tion­al de­pend­en­cies, Con­an is build­sys­tem-in­de­pend­ent, but re­quires you to in­stall the Con­an cli­ent first. Note that while Cor­rade for Con­an is already there, the Mag­num pack­age is still work-in-pro­gress.

Homebrew and Vcp­kg pack­ages are already on the latest ver­sion, Arch­Linux pack­ages are sched­uled to be up­dated soon.

Up­dat­ing from pre­vi­ous ver­sions

If you build Mag­num with BUILD_DE­PREC­ATED en­abled (the de­fault), most of the above-men­tioned changes re­lated to std::unique_ptr, std::ref­er­en­ce_wrap­per etc. should not res­ult in any source-break­ing changes — stand­ard types used in your code will still work as be­fore. How­ever, due to the gen­er­al head­er cleanup, you might end up with a bunch of “in­com­plete type” er­rors, as definitons formerly trans­it­ively in­cluded from oth­er head­ers won’t be present any­more. In par­tic­u­lar, due to re­mov­al of long-de­prec­ated fea­tures, the Con­tain­ers::Op­tion­al type is now only for­ward-de­clared in all im­port­er plu­gin APIs, and sim­il­arly it is with Con­tain­ers::Ref­er­en­ce, so you may need to add some of these to your code­bases:

#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Reference.h>

In or­der to keep your code for­ward com­pat­ible, the rule should be to al­ways ex­pli­citly in­clude all types that you use in the par­tic­u­lar source file and not rely on the defin­i­tions be­ing present due to in­tern­al en­gine head­er struc­ture. In prac­tice this is quite hard to achieve, on the oth­er hand due to the evolving nature of the lib­rary, there’s not much Mag­num it­self can do to pre­vent such break­ages.

This ver­sion also starts to re­move APIs de­prec­ated in 2018.02 (the first re­lease after three years without stable up­dates), mean­ing if you still have code­bases that are from be­fore this ver­sion, these will def­in­itely not work any­more. The re­com­men­ded up­grade path is, as al­ways, go­ing through the stable ver­sions one-by-one and fix­ing er­rors and de­prec­a­tion warn­ings as they ap­pear — jump­ing straight to latest won’t be nowhere near a smooth up­grade ex­per­i­ence.

For a com­plete over­view of newly de­prec­ated fea­tures and pos­sible com­pat­ib­il­ity break­ages, check the changelogs lis­ted be­low.

Com­plete changelog

There’s many more little things — im­proved constexpr sup­port for ar­ray view classes, new im­port­er plu­gin for AAC au­dio files, abil­ity to switch to the stand­ard C assert() macro for as­ser­tions etc. See the full changelogs for more:

Spe­cial thanks

Many things in this re­lease wouldn’t be pos­sible without ded­ic­a­tion of sev­er­al con­trib­ut­ors: