1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-29 17:15:34 +00:00

Fix weapon sheathing for non-nif meshes

This commit is contained in:
Sam Hellawell 2024-03-25 21:01:46 +00:00
parent 012d10703f
commit 7897ff7ac9
5 changed files with 43 additions and 9 deletions

View file

@ -35,6 +35,7 @@
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "actorutil.hpp"
#include "vismask.hpp" #include "vismask.hpp"
namespace MWRender namespace MWRender
@ -144,8 +145,7 @@ namespace MWRender
if (mesh.empty()) if (mesh.empty())
return mesh; return mesh;
std::string holsteredName = mesh; const std::string holsteredName = addSuffixBeforeExtension(mesh, "_sh");
holsteredName = holsteredName.replace(holsteredName.size() - 4, 4, "_sh.nif");
if (mResourceSystem->getVFS()->exists(holsteredName)) if (mResourceSystem->getVFS()->exists(holsteredName))
{ {
osg::ref_ptr<osg::Node> shieldTemplate = mResourceSystem->getSceneManager()->getInstance(holsteredName); osg::ref_ptr<osg::Node> shieldTemplate = mResourceSystem->getSceneManager()->getInstance(holsteredName);
@ -222,8 +222,7 @@ namespace MWRender
std::string_view boneName = "Bip01 AttachShield"; std::string_view boneName = "Bip01 AttachShield";
osg::Vec4f glowColor = shield->getClass().getEnchantmentColor(*shield); osg::Vec4f glowColor = shield->getClass().getEnchantmentColor(*shield);
std::string holsteredName = mesh; const std::string holsteredName = addSuffixBeforeExtension(mesh, "_sh");
holsteredName = holsteredName.replace(holsteredName.size() - 4, 4, "_sh.nif");
bool isEnchanted = !shield->getClass().getEnchantment(*shield).empty(); bool isEnchanted = !shield->getClass().getEnchantment(*shield).empty();
// If we have no dedicated sheath model, use basic shield model as fallback. // If we have no dedicated sheath model, use basic shield model as fallback.
@ -340,14 +339,12 @@ namespace MWRender
showHolsteredWeapons = false; showHolsteredWeapons = false;
std::string mesh = weapon->getClass().getCorrectedModel(*weapon); std::string mesh = weapon->getClass().getCorrectedModel(*weapon);
std::string scabbardName = mesh;
std::string_view boneName = getHolsteredWeaponBoneName(*weapon); std::string_view boneName = getHolsteredWeaponBoneName(*weapon);
if (mesh.empty() || boneName.empty()) if (mesh.empty() || boneName.empty())
return; return;
// If the scabbard is not found, use the weapon mesh as fallback. // If the scabbard is not found, use the weapon mesh as fallback.
scabbardName = scabbardName.replace(scabbardName.size() - 4, 4, "_sh.nif"); const std::string scabbardName = addSuffixBeforeExtension(mesh, "_sh");
bool isEnchanted = !weapon->getClass().getEnchantment(*weapon).empty(); bool isEnchanted = !weapon->getClass().getEnchantment(*weapon).empty();
if (!mResourceSystem->getVFS()->exists(scabbardName)) if (!mResourceSystem->getVFS()->exists(scabbardName))
{ {

View file

@ -37,4 +37,16 @@ namespace MWRender
|| VFS::Path::pathEqual(Settings::models().mBaseanimfemale.get(), model) || VFS::Path::pathEqual(Settings::models().mBaseanimfemale.get(), model)
|| VFS::Path::pathEqual(Settings::models().mBaseanim.get(), model); || VFS::Path::pathEqual(Settings::models().mBaseanim.get(), model);
} }
std::string addSuffixBeforeExtension(const std::string& filename, const std::string& suffix)
{
size_t dotPos = filename.rfind('.');
// No extension found; return the original filename with suffix appended
if (dotPos == std::string::npos)
return filename + suffix;
// Insert the suffix before the dot (extension) and return the new filename
return filename.substr(0, dotPos) + suffix + filename.substr(dotPos);
}
} }

View file

@ -8,6 +8,7 @@ namespace MWRender
{ {
const std::string& getActorSkeleton(bool firstPerson, bool female, bool beast, bool werewolf); const std::string& getActorSkeleton(bool firstPerson, bool female, bool beast, bool werewolf);
bool isDefaultActorSkeleton(std::string_view model); bool isDefaultActorSkeleton(std::string_view model);
std::string addSuffixBeforeExtension(const std::string& filename, const std::string& suffix);
} }
#endif #endif

View file

@ -539,8 +539,7 @@ namespace MWRender
if (mesh.empty()) if (mesh.empty())
return std::string(); return std::string();
std::string holsteredName = mesh; const std::string holsteredName = addSuffixBeforeExtension(mesh, "_sh");
holsteredName = holsteredName.replace(holsteredName.size() - 4, 4, "_sh.nif");
if (mResourceSystem->getVFS()->exists(holsteredName)) if (mResourceSystem->getVFS()->exists(holsteredName))
{ {
osg::ref_ptr<osg::Node> shieldTemplate = mResourceSystem->getSceneManager()->getInstance(holsteredName); osg::ref_ptr<osg::Node> shieldTemplate = mResourceSystem->getSceneManager()->getInstance(holsteredName);

View file

@ -21,13 +21,36 @@ namespace SceneUtil
mFoundNode = &group; mFoundNode = &group;
return true; return true;
} }
// FIXME: can the nodes/bones be renamed at loading stage rather than each time?
// Convert underscores to whitespaces as a workaround for Collada (OpenMW's animation system uses
// whitespace-separated names)
std::string nodeName = group.getName();
std::replace(nodeName.begin(), nodeName.end(), '_', ' ');
if (Misc::StringUtils::ciEqual(nodeName, mNameToFind))
{
mFoundNode = &group;
return true;
}
return false; return false;
} }
void FindByClassVisitor::apply(osg::Node& node) void FindByClassVisitor::apply(osg::Node& node)
{ {
if (Misc::StringUtils::ciEqual(node.className(), mNameToFind)) if (Misc::StringUtils::ciEqual(node.className(), mNameToFind))
{
mFoundNodes.push_back(&node); mFoundNodes.push_back(&node);
}
else
{
// FIXME: can the nodes/bones be renamed at loading stage rather than each time?
// Convert underscores to whitespaces as a workaround for Collada (OpenMW's animation system uses
// whitespace-separated names)
std::string nodeName = node.className();
std::replace(nodeName.begin(), nodeName.end(), '_', ' ');
if (Misc::StringUtils::ciEqual(nodeName, mNameToFind))
mFoundNodes.push_back(&node);
}
traverse(node); traverse(node);
} }
@ -53,6 +76,8 @@ namespace SceneUtil
if (trans.libraryName() == std::string_view("osgAnimation")) if (trans.libraryName() == std::string_view("osgAnimation"))
{ {
std::string nodeName = trans.getName(); std::string nodeName = trans.getName();
// FIXME: can the nodes/bones be renamed at loading stage rather than each time?
// Convert underscores to whitespaces as a workaround for Collada (OpenMW's animation system uses // Convert underscores to whitespaces as a workaround for Collada (OpenMW's animation system uses
// whitespace-separated names) // whitespace-separated names)
std::replace(nodeName.begin(), nodeName.end(), '_', ' '); std::replace(nodeName.begin(), nodeName.end(), '_', ' ');