Ensure that absent bone names work
Achieved by refactoring the code to use `std::optional<std::string>` instead of `core::stringc`.
This commit is contained in:
		| @@ -14,6 +14,7 @@ | ||||
| #include "aabbox3d.h" | ||||
| #include "matrix4.h" | ||||
| #include "IAttributes.h" | ||||
|  | ||||
| #include <list> | ||||
| #include <optional> | ||||
|  | ||||
| @@ -117,23 +118,14 @@ namespace scene | ||||
|  | ||||
| 		//! Returns the name of the node. | ||||
| 		/** \return Name as character string. */ | ||||
| 		virtual const c8* getName() const | ||||
| 		virtual const std::optional<std::string> &getName() const | ||||
| 		{ | ||||
| 			return Name.c_str(); | ||||
| 			return Name; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		//! Sets the name of the node. | ||||
| 		/** \param name New name of the scene node. */ | ||||
| 		virtual void setName(const c8* name) | ||||
| 		{ | ||||
| 			Name = name; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		//! Sets the name of the node. | ||||
| 		/** \param name New name of the scene node. */ | ||||
| 		virtual void setName(const core::stringc& name) | ||||
| 		virtual void setName(const std::optional<std::string> &name) | ||||
| 		{ | ||||
| 			Name = name; | ||||
| 		} | ||||
| @@ -601,7 +593,7 @@ namespace scene | ||||
| 		} | ||||
|  | ||||
| 		//! Name of the scene node. | ||||
| 		core::stringc Name; | ||||
| 		std::optional<std::string> Name; | ||||
|  | ||||
| 		//! Absolute transformation of the node. | ||||
| 		core::matrix4 AbsoluteTransformation; | ||||
|   | ||||
| @@ -10,6 +10,8 @@ | ||||
| #include "IAnimatedMesh.h" | ||||
| #include "SSkinMeshBuffer.h" | ||||
|  | ||||
| #include <optional> | ||||
|  | ||||
| namespace irr | ||||
| { | ||||
| namespace scene | ||||
| @@ -41,12 +43,12 @@ namespace scene | ||||
| 		/** \param number: Zero based index of joint. The last joint | ||||
| 		has the number getJointCount()-1; | ||||
| 		\return Name of joint and null if an error happened. */ | ||||
| 		virtual const c8* getJointName(u32 number) const = 0; | ||||
| 		virtual const std::optional<std::string> &getJointName(u32 number) const = 0; | ||||
|  | ||||
| 		//! Gets a joint number from its name | ||||
| 		/** \param name: Name of the joint. | ||||
| 		\return Number of the joint or -1 if not found. */ | ||||
| 		virtual s32 getJointNumber(const c8* name) const = 0; | ||||
| 		virtual std::optional<u32> getJointNumber(const std::string &name) const = 0; | ||||
|  | ||||
| 		//! Use animation from another mesh | ||||
| 		/** The animation is linked (not copied) based on joint names | ||||
| @@ -136,7 +138,7 @@ namespace scene | ||||
| 			} | ||||
|  | ||||
| 			//! The name of this joint | ||||
| 			core::stringc Name; | ||||
| 			std::optional<std::string> Name; | ||||
|  | ||||
| 			//! Local matrix of this joint | ||||
| 			core::matrix4 LocalMatrix; | ||||
|   | ||||
| @@ -471,21 +471,21 @@ IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(const c8* jointName) | ||||
|  | ||||
| 	ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh; | ||||
|  | ||||
| 	const s32 number = skinnedMesh->getJointNumber(jointName); | ||||
| 	const std::optional<u32> number = skinnedMesh->getJointNumber(jointName); | ||||
|  | ||||
| 	if (number == -1) | ||||
| 	if (!number.has_value()) | ||||
| 	{ | ||||
| 		os::Printer::log("Joint with specified name not found in skinned mesh", jointName, ELL_DEBUG); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if ((s32)JointChildSceneNodes.size() <= number) | ||||
| 	if (JointChildSceneNodes.size() <= *number) | ||||
| 	{ | ||||
| 		os::Printer::log("Joint was found in mesh, but is not loaded into node", jointName, ELL_WARNING); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	return JointChildSceneNodes[number]; | ||||
| 	return JointChildSceneNodes[*number]; | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -12,6 +12,8 @@ | ||||
| #include "IFileSystem.h" | ||||
| #include "os.h" | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| #ifdef _DEBUG | ||||
| #define _B3D_READER_DEBUG | ||||
| #endif | ||||
| @@ -149,7 +151,7 @@ bool CB3DMeshFileLoader::load() | ||||
| bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *inJoint) | ||||
| { | ||||
| 	CSkinnedMesh::SJoint *joint = AnimatedMesh->addJoint(inJoint); | ||||
| 	readString(joint->Name); | ||||
| 	joint->Name = readString(); | ||||
|  | ||||
| #ifdef _B3D_READER_DEBUG | ||||
| 	core::stringc logStr; | ||||
| @@ -818,8 +820,8 @@ bool CB3DMeshFileLoader::readChunkTEXS() | ||||
| 		Textures.push_back(SB3dTexture()); | ||||
| 		SB3dTexture& B3dTexture = Textures.getLast(); | ||||
|  | ||||
| 		readString(B3dTexture.TextureName); | ||||
| 		B3dTexture.TextureName.replace('\\','/'); | ||||
| 		B3dTexture.TextureName = readString(); | ||||
| 		std::replace(B3dTexture.TextureName.begin(), B3dTexture.TextureName.end(), '\\', '/'); | ||||
| #ifdef _B3D_READER_DEBUG | ||||
| 		os::Printer::log("read Texture", B3dTexture.TextureName.c_str(), ELL_DEBUG); | ||||
| #endif | ||||
| @@ -872,10 +874,9 @@ bool CB3DMeshFileLoader::readChunkBRUS() | ||||
| 	{ | ||||
| 		// This is what blitz basic calls a brush, like a Irrlicht Material | ||||
|  | ||||
| 		core::stringc name; | ||||
| 		readString(name); | ||||
| 		auto name = readString(); | ||||
| #ifdef _B3D_READER_DEBUG | ||||
| 		os::Printer::log("read Material", name, ELL_DEBUG); | ||||
| 		os::Printer::log("read Material", name.c_str(), ELL_DEBUG); | ||||
| #endif | ||||
| 		Materials.push_back(SB3dMaterial()); | ||||
| 		SB3dMaterial& B3dMaterial=Materials.getLast(); | ||||
| @@ -1031,18 +1032,19 @@ bool CB3DMeshFileLoader::readChunkBRUS() | ||||
| } | ||||
|  | ||||
|  | ||||
| void CB3DMeshFileLoader::readString(core::stringc& newstring) | ||||
| std::string CB3DMeshFileLoader::readString() | ||||
| { | ||||
| 	newstring=""; | ||||
| 	std::string newstring = ""; | ||||
| 	while (true) | ||||
| 	{ | ||||
| 		c8 character; | ||||
| 		if (B3DFile->read(&character, sizeof(character)) == 0) | ||||
| 			return; // eof | ||||
| 			break; // eof | ||||
| 		if (character==0) | ||||
| 			return; | ||||
| 		newstring.append(character); | ||||
| 			break; | ||||
| 		newstring.push_back(character); | ||||
| 	} | ||||
| 	return newstring; | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -52,7 +52,7 @@ private: | ||||
| 	bool readChunkTEXS(); | ||||
| 	bool readChunkBRUS(); | ||||
|  | ||||
| 	void readString(core::stringc& newstring); | ||||
| 	std::string readString(); | ||||
| 	void readFloats(f32* vec, u32 count); | ||||
|  | ||||
| 	core::array<SB3dChunk> B3dStack; | ||||
|   | ||||
| @@ -4,6 +4,8 @@ | ||||
|  | ||||
| #include "CBoneSceneNode.h" | ||||
|  | ||||
| #include <optional> | ||||
|  | ||||
| namespace irr | ||||
| { | ||||
| namespace scene | ||||
| @@ -11,7 +13,7 @@ namespace scene | ||||
|  | ||||
| //! constructor | ||||
| CBoneSceneNode::CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, | ||||
| 	u32 boneIndex, const c8* boneName) | ||||
| 	u32 boneIndex, const std::optional<std::string> &boneName) | ||||
| : IBoneSceneNode(parent, mgr, id), BoneIndex(boneIndex), | ||||
| 	AnimationMode(EBAM_AUTOMATIC), SkinningSpace(EBSS_LOCAL) | ||||
| { | ||||
|   | ||||
| @@ -8,6 +8,8 @@ | ||||
|  | ||||
| #include "IBoneSceneNode.h" | ||||
|  | ||||
| #include <optional> | ||||
|  | ||||
| namespace irr | ||||
| { | ||||
| namespace scene | ||||
| @@ -19,7 +21,8 @@ namespace scene | ||||
|  | ||||
| 		//! constructor | ||||
| 		CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, | ||||
| 			s32 id=-1, u32 boneIndex=0, const c8* boneName=0); | ||||
| 			s32 id=-1, u32 boneIndex=0, | ||||
| 			const std::optional<std::string> &boneName = std::nullopt); | ||||
|  | ||||
| 		//! Returns the index of the bone | ||||
| 		u32 getBoneIndex() const override; | ||||
|   | ||||
| @@ -697,7 +697,8 @@ ISceneNode* CSceneManager::getSceneNodeFromName(const char* name, ISceneNode* st | ||||
| 	if (start == 0) | ||||
| 		start = getRootSceneNode(); | ||||
|  | ||||
| 	if (!strcmp(start->getName(),name)) | ||||
| 	auto startName = start->getName(); | ||||
| 	if (startName.has_value() && startName == name) | ||||
| 		return start; | ||||
|  | ||||
| 	ISceneNode* node = 0; | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| // For conditions of distribution and use, see copyright notice in irrlicht.h | ||||
|  | ||||
| #include "CSkinnedMesh.h" | ||||
| #include <optional> | ||||
| #include "CBoneSceneNode.h" | ||||
| #include "IAnimatedMeshSceneNode.h" | ||||
| #include "os.h" | ||||
| @@ -624,18 +625,18 @@ u32 CSkinnedMesh::getJointCount() const | ||||
| 	return AllJoints.size(); | ||||
| } | ||||
|  | ||||
|  | ||||
| //! Gets the name of a joint. | ||||
| const c8* CSkinnedMesh::getJointName(u32 number) const | ||||
| { | ||||
| 	if (number >= AllJoints.size()) | ||||
| 		return 0; | ||||
| 	return AllJoints[number]->Name.c_str(); | ||||
| const std::optional<std::string> &CSkinnedMesh::getJointName(u32 number) const { | ||||
| 	if (number >= getJointCount()) { | ||||
| 		static const std::optional<std::string> nullopt; | ||||
| 		return nullopt; | ||||
| 	} | ||||
| 	return AllJoints[number]->Name; | ||||
| } | ||||
|  | ||||
|  | ||||
| //! Gets a joint number from its name | ||||
| s32 CSkinnedMesh::getJointNumber(const c8* name) const | ||||
| std::optional<u32> CSkinnedMesh::getJointNumber(const std::string &name) const | ||||
| { | ||||
| 	for (u32 i=0; i<AllJoints.size(); ++i) | ||||
| 	{ | ||||
| @@ -643,7 +644,7 @@ s32 CSkinnedMesh::getJointNumber(const c8* name) const | ||||
| 			return i; | ||||
| 	} | ||||
|  | ||||
| 	return -1; | ||||
| 	return std::nullopt; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -1396,7 +1397,7 @@ void CSkinnedMesh::addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes, | ||||
| 	//Create new joints | ||||
| 	for (u32 i=0; i<AllJoints.size(); ++i) | ||||
| 	{ | ||||
| 		jointChildSceneNodes.push_back(new CBoneSceneNode(0, smgr, 0, i, AllJoints[i]->Name.c_str())); | ||||
| 		jointChildSceneNodes.push_back(new CBoneSceneNode(0, smgr, 0, i, AllJoints[i]->Name)); | ||||
| 	} | ||||
|  | ||||
| 	//Match up parents | ||||
|   | ||||
| @@ -8,9 +8,6 @@ | ||||
|  | ||||
| #include "ISkinnedMesh.h" | ||||
| #include "SMeshBuffer.h" | ||||
| #include "S3DVertex.h" | ||||
| #include "irrString.h" | ||||
| #include "matrix4.h" | ||||
| #include "quaternion.h" | ||||
|  | ||||
| namespace irr | ||||
| @@ -84,10 +81,10 @@ namespace scene | ||||
| 		u32 getJointCount() const override; | ||||
|  | ||||
| 		//! Gets the name of a joint. | ||||
| 		const c8* getJointName(u32 number) const override; | ||||
| 		const std::optional<std::string> &getJointName(u32 number) const override; | ||||
|  | ||||
| 		//! Gets a joint number from its name | ||||
| 		s32 getJointNumber(const c8* name) const override; | ||||
| 		std::optional<u32> getJointNumber(const std::string &name) const override; | ||||
|  | ||||
| 		//! uses animation from another mesh | ||||
| 		bool useAnimationFrom(const ISkinnedMesh *mesh) override; | ||||
|   | ||||
| @@ -594,16 +594,11 @@ bool CXMeshFileLoader::parseDataObjectFrame(CSkinnedMesh::SJoint *Parent) | ||||
|  | ||||
| 	CSkinnedMesh::SJoint *joint=0; | ||||
|  | ||||
| 	if (name.size()) | ||||
| 	{ | ||||
| 		for (u32 n=0; n < AnimatedMesh->getAllJoints().size(); ++n) | ||||
| 		{ | ||||
| 			if (AnimatedMesh->getAllJoints()[n]->Name==name) | ||||
| 			{ | ||||
| 				joint=AnimatedMesh->getAllJoints()[n]; | ||||
| 				JointID=n; | ||||
| 				break; | ||||
| 			} | ||||
| 	if (name.size()) { | ||||
| 		auto n = AnimatedMesh->getJointNumber(name.c_str()); | ||||
| 		if (n.has_value()) { | ||||
| 			JointID = *n; | ||||
| 			joint = AnimatedMesh->getAllJoints()[JointID]; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -613,7 +608,7 @@ bool CXMeshFileLoader::parseDataObjectFrame(CSkinnedMesh::SJoint *Parent) | ||||
| 		os::Printer::log("creating joint ", name.c_str(), ELL_DEBUG); | ||||
| #endif | ||||
| 		joint=AnimatedMesh->addJoint(Parent); | ||||
| 		joint->Name=name; | ||||
| 		joint->Name=name.c_str(); | ||||
| 		JointID=AnimatedMesh->getAllJoints().size()-1; | ||||
| 	} | ||||
| 	else | ||||
| @@ -1121,17 +1116,8 @@ bool CXMeshFileLoader::parseDataObjectSkinWeights(SXMesh &mesh) | ||||
|  | ||||
| 	mesh.HasSkinning=true; | ||||
|  | ||||
| 	CSkinnedMesh::SJoint *joint=0; | ||||
|  | ||||
| 	u32 n; | ||||
| 	for (n=0; n < AnimatedMesh->getAllJoints().size(); ++n) | ||||
| 	{ | ||||
| 		if (AnimatedMesh->getAllJoints()[n]->Name==TransformNodeName) | ||||
| 		{ | ||||
| 			joint=AnimatedMesh->getAllJoints()[n]; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	auto n = AnimatedMesh->getJointNumber(TransformNodeName.c_str()); | ||||
| 	CSkinnedMesh::SJoint *joint = n.has_value() ? AnimatedMesh->getAllJoints()[*n] : nullptr; | ||||
|  | ||||
| 	if (!joint) | ||||
| 	{ | ||||
| @@ -1140,7 +1126,7 @@ bool CXMeshFileLoader::parseDataObjectSkinWeights(SXMesh &mesh) | ||||
| #endif | ||||
| 		n = AnimatedMesh->getAllJoints().size(); | ||||
| 		joint=AnimatedMesh->addJoint(0); | ||||
| 		joint->Name=TransformNodeName; | ||||
| 		joint->Name=TransformNodeName.c_str(); | ||||
| 	} | ||||
|  | ||||
| 	// read vertex weights | ||||
| @@ -1157,7 +1143,7 @@ bool CXMeshFileLoader::parseDataObjectSkinWeights(SXMesh &mesh) | ||||
|  | ||||
| 	for (i=0; i<nWeights; ++i) | ||||
| 	{ | ||||
| 		mesh.WeightJoint.push_back(n); | ||||
| 		mesh.WeightJoint.push_back(*n); | ||||
| 		mesh.WeightNum.push_back(joint->Weights.size()); | ||||
|  | ||||
| 		CSkinnedMesh::SWeight *weight=AnimatedMesh->addWeight(joint); | ||||
| @@ -1668,41 +1654,33 @@ bool CXMeshFileLoader::parseDataObjectAnimation() | ||||
| #ifdef _XREADER_DEBUG | ||||
| 		os::Printer::log("frame name", FrameName.c_str(), ELL_DEBUG); | ||||
| #endif | ||||
| 		CSkinnedMesh::SJoint *joint=0; | ||||
| 		auto n = AnimatedMesh->getJointNumber(FrameName.c_str()); | ||||
|  | ||||
| 		u32 n; | ||||
| 		for (n=0; n < AnimatedMesh->getAllJoints().size(); ++n) | ||||
| 		{ | ||||
| 			if (AnimatedMesh->getAllJoints()[n]->Name==FrameName) | ||||
| 			{ | ||||
| 				joint=AnimatedMesh->getAllJoints()[n]; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (!joint) | ||||
| 		{ | ||||
| 		CSkinnedMesh::SJoint *joint; | ||||
| 		if (n.has_value()) { | ||||
| 			joint = AnimatedMesh->getAllJoints()[*n]; | ||||
| 		} else { | ||||
| #ifdef _XREADER_DEBUG | ||||
| 			os::Printer::log("creating joint for animation ", FrameName.c_str(), ELL_DEBUG); | ||||
| #endif | ||||
| 			joint=AnimatedMesh->addJoint(0); | ||||
| 			joint->Name=FrameName; | ||||
| 			joint->Name=FrameName.c_str(); | ||||
| 		} | ||||
|  | ||||
| 		joint->PositionKeys.reallocate(joint->PositionKeys.size()+animationDump.PositionKeys.size()); | ||||
| 		for (n=0; n<animationDump.PositionKeys.size(); ++n) | ||||
| 		for (u32 n=0; n<animationDump.PositionKeys.size(); ++n) | ||||
| 		{ | ||||
| 			joint->PositionKeys.push_back(animationDump.PositionKeys[n]); | ||||
| 		} | ||||
|  | ||||
| 		joint->ScaleKeys.reallocate(joint->ScaleKeys.size()+animationDump.ScaleKeys.size()); | ||||
| 		for (n=0; n<animationDump.ScaleKeys.size(); ++n) | ||||
| 		for (u32 n=0; n<animationDump.ScaleKeys.size(); ++n) | ||||
| 		{ | ||||
| 			joint->ScaleKeys.push_back(animationDump.ScaleKeys[n]); | ||||
| 		} | ||||
|  | ||||
| 		joint->RotationKeys.reallocate(joint->RotationKeys.size()+animationDump.RotationKeys.size()); | ||||
| 		for (n=0; n<animationDump.RotationKeys.size(); ++n) | ||||
| 		for (u32 n=0; n<animationDump.RotationKeys.size(); ++n) | ||||
| 		{ | ||||
| 			joint->RotationKeys.push_back(animationDump.RotationKeys[n]); | ||||
| 		} | ||||
|   | ||||
| @@ -39,7 +39,7 @@ struct SB3dChunk | ||||
|  | ||||
| struct SB3dTexture | ||||
| { | ||||
| 	core::stringc TextureName; | ||||
| 	std::string TextureName; | ||||
| 	s32 Flags; | ||||
| 	s32 Blend; | ||||
| 	f32 Xpos; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user