A series of posts describing the changes afoot for the Long Term Evolution of World Machine.
Welcome back! I hope everyone had a great holiday season.. the winter here in Seattle has been gloomy and rainy, but inside work has proceeded on LTE at a blistering pace.
Next up, let’s take a look at a feature we hinted at last time.
Full Edit History
Undo/Redo was not built into World Machine originally. Consequently, it has been the source of many bugs and issues over the years. For LTE, I wanted to not just make undo/redo rock-solid and dependable, but also turn a historical weakness into a strength.
This has been achieved. World Machine now keeps your full edit history intact:
Every action that modifies your world appears in the edit history. The history is quite granular; for example, changes to each device parameter are stored individually. Repeated edits are automatically grouped to keep your history neat, and eventually certain edits will automatically collapse to a single changeset (such as moving wires and devices around). You can also remove/ collapse old history if you don’t need it.
Edits can load/save with your project file, so for important worlds you can keep the full evolution and return to any revision you might want to see.
Full Build Results
You can quickly hop back and forth between edits and compare how they look at their full build resolution. Here’s a quick video showing the history feature in action:
I hope the above video makes you excited! Being able to step up and down the history list and see the full-res results change is a real game changing workflow feature.
Another thing: the build engine is history-aware, and each edit knows what changes and device invalidations occurred. As a result, you can initiate a build on an old version of your world, and all edits above that in the history list will inherit the build results if applicable.
And although not implemented currently, there’s no real reason why you couldn’t take historical results as the “before” in the 3D View’s A:B comparison. This would let you interactively explore how your world is evolving.. but that’s for later.
You can also take a snapshot to keep a named copy of your world at a point in time. This is really useful for making sure you can always re-build a certain version of an asset using the same settings, while letting you continue changing your world file. There will probably be a setting to auto-snapshot whenever you perform a final export.
Finally, all of this gives session files a new purpose: They can function as the disk store for all of the build results, etc resulting from all of this. Thus when you save and then reload a session, it should be just as if you never left the program; all of your build results, history, etc will remain just as you left it.
A Technical Aside
All of this is enabled by a fundamental change in the way data is handled in WM. The core of WM is now built around what’s called immutable data. When you perform a mutating action, you’re actually creating a new draft version of your world containing your changes. When the draft is committed to the history, it can no longer be changed.
This is a very powerful concept! The overhead of a copy is negligible in this case, and we immediately gain edit history almost for free. It also achieves my other main goal : The very stable and fast asynchronous build engine within WM LTE. Multi-threaded code is traditionally a huge source of bugs, and synchronization is slow. By having a guarantee that a particular copy of the world won’t change underneath us, we remove almost all traditional synchronization issues, improving both stability and performance.
This feature was one of the most technologically interesting ones to tackle in the LTE conversion, and was informed by Sean Parent’s talk ‘Inheritance is the Base Class of Evil‘. For fellow dev-nerds: the fundamental realization is that although mutable shared_ptrs can be very dangerous, a shared_ptr<const T> in fact has value semantics.
…Don’t worry if that last sentence is gibberish 🙂
For folks writing plugins, this has implications – in particular, the WM core now uses C++ const-ness to enforce this immutability.
That’s enough for now. Next time we’ll look at the improvements to viewports and the workview. See you then!