diff --git a/CHANGELOG.md b/CHANGELOG.md index f1b8ff1f91..d5641fd18c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -179,6 +179,7 @@ Bug #6913: Constant effect enchanted items don't break invisibility Bug #6923: Dispose of corpse prevents respawning after load Bug #6937: Divided by Nix Hounds quest is broken + Bug #7008: Race condition on initializing a vector of reserved node names Feature #890: OpenMW-CS: Column filtering Feature #1465: "Reset" argument for AI functions Feature #2491: Ability to make OpenMW "portable" diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index 63319840bd..610aa6b506 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -619,6 +619,67 @@ namespace Resource return node; } + + std::vector makeSortedReservedNames() + { + static constexpr std::string_view names[] = { + "Head", + "Neck", + "Chest", + "Groin", + "Right Hand", + "Left Hand", + "Right Wrist", + "Left Wrist", + "Shield Bone", + "Right Forearm", + "Left Forearm", + "Right Upper Arm", + "Left Upper Arm", + "Right Foot", + "Left Foot", + "Right Ankle", + "Left Ankle", + "Right Knee", + "Left Knee", + "Right Upper Leg", + "Left Upper Leg", + "Right Clavicle", + "Left Clavicle", + "Weapon Bone", + "Tail", + "Bip01", + "Root Bone", + "BoneOffset", + "AttachLight", + "Arrow", + "Camera", + "Collision", + "Right_Wrist", + "Left_Wrist", + "Shield_Bone", + "Right_Forearm", + "Left_Forearm", + "Right_Upper_Arm", + "Left_Clavicle", + "Weapon_Bone", + "Root_Bone", + }; + + std::vector result; + result.reserve(std::size(names)); + + for (std::string_view name : names) + { + std::string prefixedName("Tri "); + prefixedName += name; + result.push_back(std::move(prefixedName)); + } + + std::sort(result.begin(), result.end(), Misc::StringUtils::ciLess); + + return result; + } } osg::ref_ptr load (const std::string& normalizedFilename, const VFS::Manager* vfs, Resource::ImageManager* imageManager, Resource::NifFileManager* nifFileManager) @@ -638,23 +699,9 @@ namespace Resource if (name.empty()) return false; - static std::vector reservedNames; - if (reservedNames.empty()) - { - const char* reserved[] = {"Head", "Neck", "Chest", "Groin", "Right Hand", "Left Hand", "Right Wrist", "Left Wrist", "Shield Bone", "Right Forearm", "Left Forearm", "Right Upper Arm", - "Left Upper Arm", "Right Foot", "Left Foot", "Right Ankle", "Left Ankle", "Right Knee", "Left Knee", "Right Upper Leg", "Left Upper Leg", "Right Clavicle", - "Left Clavicle", "Weapon Bone", "Tail", "Bip01", "Root Bone", "BoneOffset", "AttachLight", "Arrow", "Camera", "Collision", "Right_Wrist", "Left_Wrist", - "Shield_Bone", "Right_Forearm", "Left_Forearm", "Right_Upper_Arm", "Left_Clavicle", "Weapon_Bone", "Root_Bone"}; - - reservedNames = std::vector(reserved, reserved + sizeof(reserved)/sizeof(reserved[0])); - - for (unsigned int i=0; i reservedNames = makeSortedReservedNames(); - std::vector::iterator it = Misc::partialBinarySearch(reservedNames.begin(), reservedNames.end(), name); + const auto it = Misc::partialBinarySearch(reservedNames.begin(), reservedNames.end(), name); return it != reservedNames.end(); }