With this PR we refactor a `premultiplied alpha` user string set by `characterpreview.cpp` into a more flexible mechanism allowing us to assign any state to GUI textures. We can consider these changes more future proof than the previous approach.
This PR aims to spark the retirement of a questionable pattern I have found all over our code base. I will illustrate how this pattern encourages code duplication, lacks type safety, requires documentation and can be prone to bugs.
```
std::map<std::string, Object> mMap; // Stored in all lowercase for a case-insensitive lookup
std::string lowerKey = Misc::StringUtils::lowerCase(key);
mMap.emplace(lowerKey, object);
std::string lowerKey = Misc::StringUtils::lowerCase(key);
mMap.find(lowerKey);
mMap.find(key); // Not found. Oops!
```
An alternative approach produces no such issues.
```
std::unordered_map<std::string, Object, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> mMap;
mMap.emplace(key, object);
mMap.find(key);
```
Of course, such an alternative will work for a `map` as well, but an `unordered_map` is generally preferable over a `map` with these changes because we have moved `lowerCase` into the comparison operator.
In this PR I have refactored `Animation::mNodeMap` accordingly. I have reviewed and adapted all direct and indirect usage of `Animation::mNodeMap` to ensure we do not change behaviour with this PR.
This PR fixes a crash caused by the improperly ensured lifetime of RigGeometry::mSourceGeometry. mSourceGeometry was not adequate to ensure mSourceGeometry would outlive mGeometry because we extend mGeometrys lifetime beyond this lifetime by passing mGeometry to the draw traversal instead of this.
In addition,
We add important comments.
We detect and prevent generally unsafe operations in high level code.
We add a sprinkling of const to help clarify intentions.
Currently, we use an `UnrefQueue` which supposedly aims to transfer destruction costs to another thread. The implications of this unusual pattern can not be well understood because some allocators might free resources more efficiently if they are freed by the same thread that allocated them. In addition, `UnrefQueue` complicates the validation of thread safety in our engine. Lastly, our current usage of `UnrefQueue` triggers `ref()`, `unref()` atomic operations as objects are passed into the queue. These operations could be more expensive than the actual destruction.
With this PR we thus remove `UnrefQueue`. We can expect these changes to have a minor impact at most because we free most resources elsewhere in `ResourceSystem::updateCache`.
==16218== Conditional jump or move depends on uninitialised value(s)
==16218== at 0xCDBC27: MWPhysics::Object::commitPositionChange() (object.cpp:68)
==16218== by 0xCE5B64: MWPhysics::PhysicsTaskScheduler::updatePtrAabb(std::shared_ptr<MWPhysics::PtrHolder> const&) (mtphysics.cpp:446)
==16218== by 0xCE5CC3: operator() (mtphysics.cpp:432)
==16218== by 0xCE5CC3: for_each<std::_Rb_tree_const_iterator<std::shared_ptr<MWPhysics::PtrHolder> >, MWPhysics::PhysicsTaskScheduler::updateAabbs()::<lambda(const std::shared_ptr<MWPhysics::PtrHolder>&)> > (stl_algo.h:3820)
==16218== by 0xCE5CC3: MWPhysics::PhysicsTaskScheduler::updateAabbs() (mtphysics.cpp:431)
==16218== by 0xCE5E35: MWPhysics::PhysicsTaskScheduler::afterPreStep() (mtphysics.cpp:586)
==16218== by 0xCE6238: operator() (mtphysics.cpp:533)
==16218== by 0xCE6238: wait<MWPhysics::PhysicsTaskScheduler::doSimulation()::<lambda()> > (barrier.hpp:33)
==16218== by 0xCE6238: MWPhysics::PhysicsTaskScheduler::doSimulation() (mtphysics.cpp:533)
==16218== by 0xCE6377: MWPhysics::PhysicsTaskScheduler::worker() (mtphysics.cpp:464)
==16218== by 0x74523C3: execute_native_thread_routine (thread.cc:82)
==16218== by 0x76FF258: start_thread (in /usr/lib/libpthread-2.33.so)
==16218== by 0x78155E2: clone (in /usr/lib/libc-2.33.so)
==16218==
==16218== Conditional jump or move depends on uninitialised value(s)
==16218== at 0xCDBC30: MWPhysics::Object::commitPositionChange() (object.cpp:73)
==16218== by 0xCE5B64: MWPhysics::PhysicsTaskScheduler::updatePtrAabb(std::shared_ptr<MWPhysics::PtrHolder> const&) (mtphysics.cpp:446)
==16218== by 0xCE5CC3: operator() (mtphysics.cpp:432)
==16218== by 0xCE5CC3: for_each<std::_Rb_tree_const_iterator<std::shared_ptr<MWPhysics::PtrHolder> >, MWPhysics::PhysicsTaskScheduler::updateAabbs()::<lambda(const std::shared_ptr<MWPhysics::PtrHolder>&)> > (stl_algo.h:3820)
==16218== by 0xCE5CC3: MWPhysics::PhysicsTaskScheduler::updateAabbs() (mtphysics.cpp:431)
==16218== by 0xCE5E35: MWPhysics::PhysicsTaskScheduler::afterPreStep() (mtphysics.cpp:586)
==16218== by 0xCE6238: operator() (mtphysics.cpp:533)
==16218== by 0xCE6238: wait<MWPhysics::PhysicsTaskScheduler::doSimulation()::<lambda()> > (barrier.hpp:33)
==16218== by 0xCE6238: MWPhysics::PhysicsTaskScheduler::doSimulation() (mtphysics.cpp:533)
==16218== by 0xCE6377: MWPhysics::PhysicsTaskScheduler::worker() (mtphysics.cpp:464)
==16218== by 0x74523C3: execute_native_thread_routine (thread.cc:82)
==16218== by 0x76FF258: start_thread (in /usr/lib/libpthread-2.33.so)
==16218== by 0x78155E2: clone (in /usr/lib/libc-2.33.so)
==16218==