Collada loader now handles texture-names with escape characters.
Names like "my%20texture.png" will now load "my texture.png". Collada filenames are in xs:anyURI format. xs:anyURI is used in more places, but we don't support any other file-loading inside Collada so far, so that was the most important place to fix. Also added/fixed a few comments. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@5793 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
a450a0e391
commit
917379f453
|
@ -1,5 +1,6 @@
|
|||
--------------------------
|
||||
Changes in 1.9 (not yet released)
|
||||
- .dae/Collada reader/writer now handle whitespace in texture-filenames with escape characters (handle them as xs:anyURI).
|
||||
- Add function string::insert.
|
||||
- EditBox now still allows overwriting characters when the text-length is at max.
|
||||
- Bugfix: CMatrix4::transformPlane was calculating the wrong plane-normal before.
|
||||
|
@ -9,7 +10,7 @@ Changes in 1.9 (not yet released)
|
|||
- Bugfix: CCameraSceneNode resets the IsOrthogonal flag to false now when it recalculates a projection matrix.
|
||||
- SViewFrustum::setFrom and SViewFrustum constructor now use a parameter to allow to set the correct near clipping plane when the projection matrix doesn't use a target depth range of 0 to z, but for example -z to z. So OGL projections matrices can now also use it.
|
||||
- Remove code to read boundingbox element in Collada reader as it's not in Collada specification.
|
||||
- .dae/Collade reader now converts from Collada's right-handed to Irrlicht's left handed coordinate system (switching z to -z)
|
||||
- .dae/Collada reader now converts from Collada's right-handed to Irrlicht's left handed coordinate system (switching z to -z)
|
||||
- Add irr::string::eraseTrailingFloatZeros to kick out trailing 0's for strings generated from floats.
|
||||
- .dae/Collada writer now converts from Irrlicht's left-handed to Collada's right-handed coordinate system (switching z to -z)
|
||||
- Switch Collada writer to utf8 xml's.
|
||||
|
|
|
@ -154,6 +154,7 @@ namespace scene
|
|||
//! Callback interface to use custom names on collada writing.
|
||||
/** You can either modify names and id's written to collada or you can use
|
||||
this interface to just find out which names are used on writing.
|
||||
Names are often used later as xs:anyURI, so avoid whitespace, '#' and '%' in the names.
|
||||
*/
|
||||
class IColladaMeshWriterNames : public virtual IReferenceCounted
|
||||
{
|
||||
|
@ -165,7 +166,7 @@ namespace scene
|
|||
/** Note that names really must be unique here per mesh-pointer, so
|
||||
mostly it's a good idea to return the nameForMesh from
|
||||
IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow
|
||||
the xs::NCName standard to be valid, you can run them through
|
||||
the xs:NCName standard to be valid, you can run them through
|
||||
IColladaMeshWriter::toNCName to ensure that.
|
||||
\param mesh Pointer to the mesh which needs a name
|
||||
\param instance When E_COLLADA_GEOMETRY_WRITING is not ECGI_PER_MESH then
|
||||
|
@ -177,7 +178,7 @@ namespace scene
|
|||
/** Note that names really must be unique here per node-pointer, so
|
||||
mostly it's a good idea to return the nameForNode from
|
||||
IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow
|
||||
the xs::NCName standard to be valid, you can run them through
|
||||
the xs:NCName standard to be valid, you can run them through
|
||||
IColladaMeshWriter::toNCName to ensure that.
|
||||
*/
|
||||
virtual irr::core::stringc nameForNode(const scene::ISceneNode* node) = 0;
|
||||
|
@ -190,7 +191,7 @@ namespace scene
|
|||
instances per node are identical between different nodes you can reduce
|
||||
the number of exported materials using that knowledge by using identical
|
||||
names for such shared materials.
|
||||
Names must follow the xs::NCName standard to be valid, you can run them
|
||||
Names must follow the xs:NCName standard to be valid, you can run them
|
||||
through IColladaMeshWriter::toNCName to ensure that.
|
||||
*/
|
||||
virtual irr::core::stringc nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) = 0;
|
||||
|
@ -382,7 +383,7 @@ namespace scene
|
|||
return DefaultNameGenerator;
|
||||
}
|
||||
|
||||
//! Restrict the characters of oldString a set of allowed characters in xs::NCName and add the prefix.
|
||||
//! Restrict the characters of oldString a set of allowed characters in xs:NCName and add the prefix.
|
||||
/** A tool function to help when using a custom name generator to generative valid names for collada names and id's. */
|
||||
virtual irr::core::stringc toNCName(const irr::core::stringc& oldString, const irr::core::stringc& prefix=irr::core::stringc("_NC_")) const = 0;
|
||||
|
||||
|
|
|
@ -332,6 +332,22 @@ CColladaFileLoader::CColladaFileLoader(scene::ISceneManager* smgr,
|
|||
setDebugName("CColladaFileLoader");
|
||||
#endif
|
||||
|
||||
// Escape characters, see https://www.w3schools.com/tags/ref_urlencode.asp
|
||||
// TODO: There should be more, but usually people just escape the space character anyway.
|
||||
// And I'm not sure if our xml files are utf-8 or windows-1252, so let's avoid the ambiguous ones.
|
||||
EscapeCharsAnyURI.push_back(EscapeCharacterURL(' ', "%20"));
|
||||
EscapeCharsAnyURI.push_back(EscapeCharacterURL('"', "%22"));
|
||||
EscapeCharsAnyURI.push_back(EscapeCharacterURL('#', "%23"));
|
||||
EscapeCharsAnyURI.push_back(EscapeCharacterURL('$', "%24"));
|
||||
EscapeCharsAnyURI.push_back(EscapeCharacterURL('%', "%25"));
|
||||
EscapeCharsAnyURI.push_back(EscapeCharacterURL('&', "%26"));
|
||||
EscapeCharsAnyURI.push_back(EscapeCharacterURL('\'', "%27"));
|
||||
EscapeCharsAnyURI.push_back(EscapeCharacterURL('(', "%28"));
|
||||
EscapeCharsAnyURI.push_back(EscapeCharacterURL(')', "%29"));
|
||||
EscapeCharsAnyURI.push_back(EscapeCharacterURL('/', "%2F"));
|
||||
EscapeCharsAnyURI.push_back(EscapeCharacterURL('\\', "%5C"));
|
||||
|
||||
|
||||
TextureLoader = new CMeshTextureLoader( FileSystem, SceneManager->getVideoDriver() );
|
||||
}
|
||||
|
||||
|
@ -1209,6 +1225,7 @@ void CColladaFileLoader::readImage(io::IXMLReaderUTF8* reader)
|
|||
reader->read();
|
||||
image.Source = reader->getNodeData();
|
||||
image.Source.trim();
|
||||
unescape(image.Source);
|
||||
image.SourceIsFilename=true;
|
||||
}
|
||||
else
|
||||
|
@ -2742,8 +2759,8 @@ void CColladaFileLoader::clearData()
|
|||
//! changes the XML URI into an internal id
|
||||
void CColladaFileLoader::uriToId(core::stringc& str)
|
||||
{
|
||||
// currently, we only remove the # from the begin if there
|
||||
// because we simply don't support referencing other files.
|
||||
// Currently, we only remove the # from the beginning
|
||||
// as we don't support referencing other files.
|
||||
if (!str.size())
|
||||
return;
|
||||
|
||||
|
@ -2942,6 +2959,47 @@ core::matrix4 CColladaFileLoader::flipZAxis(const core::matrix4& m)
|
|||
return matrix;
|
||||
}
|
||||
|
||||
void CColladaFileLoader::unescape(irr::core::stringc& uri)
|
||||
{
|
||||
u32 len = uri.size();
|
||||
for (u32 i=0; i<len-1; ++i)
|
||||
{
|
||||
if (uri[i] == '%' )
|
||||
{
|
||||
if (uri[i+1] == '%')
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (u32 e = 0; e < EscapeCharsAnyURI.size(); ++e)
|
||||
{
|
||||
const irr::core::stringc& escapeString = EscapeCharsAnyURI[e].Escape;
|
||||
const u32 escapeLen = escapeString.size();
|
||||
bool equals = true;
|
||||
for ( u32 c = 1; c<escapeLen; ++c) // string compare (and we already know first on fits as always '%')
|
||||
{
|
||||
if ( uri[i+c] != escapeString[c] )
|
||||
{
|
||||
equals = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( equals )
|
||||
{
|
||||
uri[i] = EscapeCharsAnyURI[e].Character;
|
||||
// TODO: core::string has no erase function which erases more than one char at a time currently
|
||||
for ( u32 a=0;a<escapeLen-1; ++a)
|
||||
uri.erase(i+1);
|
||||
len -= escapeLen-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
|
|
@ -344,6 +344,9 @@ private:
|
|||
//! Note that function is symmetric (no difference if called before or after a transpose).
|
||||
core::matrix4 flipZAxis(const core::matrix4& m);
|
||||
|
||||
//! replace escape characters with the unescaped ones
|
||||
void unescape(irr::core::stringc& uri);
|
||||
|
||||
scene::ISceneManager* SceneManager;
|
||||
io::IFileSystem* FileSystem;
|
||||
|
||||
|
@ -369,6 +372,19 @@ private:
|
|||
core::array< core::array<irr::scene::IMeshBuffer*> > MeshesToBind;
|
||||
|
||||
bool CreateInstances;
|
||||
|
||||
struct EscapeCharacterURL
|
||||
{
|
||||
EscapeCharacterURL(irr::c8 c, const irr::c8* e)
|
||||
: Character(c)
|
||||
{
|
||||
Escape = e;
|
||||
}
|
||||
|
||||
irr::c8 Character; // unescaped (like ' ')
|
||||
irr::core::stringc Escape; // escaped (like '%20')
|
||||
};
|
||||
irr::core::array<EscapeCharacterURL> EscapeCharsAnyURI;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ irr::core::stringc CColladaMeshWriterNames::nameForMesh(const scene::IMesh* mesh
|
|||
irr::core::stringc CColladaMeshWriterNames::nameForNode(const scene::ISceneNode* node)
|
||||
{
|
||||
irr::core::stringc name;
|
||||
// Prefix, because xs::ID can't start with a number, also nicer name
|
||||
// Prefix, because xs:ID can't start with a number, also nicer name
|
||||
if ( node && node->getType() == ESNT_LIGHT )
|
||||
name = "light";
|
||||
else
|
||||
|
@ -1225,7 +1225,7 @@ bool CColladaMeshWriter::isXmlNameChar(c8 c) const
|
|||
*/
|
||||
}
|
||||
|
||||
// Restrict the characters to a set of allowed characters in xs::NCName.
|
||||
// Restrict the characters to a set of allowed characters in xs:NCName.
|
||||
irr::core::stringc CColladaMeshWriter::toNCName(const irr::core::stringc& oldString, const irr::core::stringc& prefix) const
|
||||
{
|
||||
irr::core::stringc result(prefix); // help to ensure id starts with a valid char and reduce chance of name-conflicts
|
||||
|
@ -1260,7 +1260,7 @@ const irr::core::stringc* CColladaMeshWriter::findGeometryNameForNode(ISceneNode
|
|||
return &colladaMesh.findGeometryNameForNode(node);
|
||||
}
|
||||
|
||||
// Restrict the characters to a set of allowed characters in xs::anyURI
|
||||
// Restrict the characters to a set of allowed characters in xs:anyURI
|
||||
irr::core::stringc CColladaMeshWriter::pathToURI(const irr::io::path& path) const
|
||||
{
|
||||
irr::core::stringc result;
|
||||
|
@ -1280,7 +1280,7 @@ irr::core::stringc CColladaMeshWriter::pathToURI(const irr::io::path& path) cons
|
|||
}
|
||||
result.append(path);
|
||||
|
||||
// Make correct URI (without whitespaces)
|
||||
// Make correct URI (without whitespace)
|
||||
u32 len = result.size();
|
||||
for (u32 i=0; i<len; ++i)
|
||||
{
|
||||
|
@ -1404,7 +1404,7 @@ void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringc& materialf
|
|||
// <init_from>internal_texturename</init_from>
|
||||
Writer->writeElement("init_from", false);
|
||||
irr::io::path p(FileSystem->getRelativeFilename(layer.Texture->getName().getPath(), Directory));
|
||||
Writer->writeText(toNCName(irr::core::stringc(p)).c_str());
|
||||
Writer->writeText(toNCName(irr::core::stringc(p)).c_str()); // same ID for internal name as in writeLibraryImages
|
||||
Writer->writeClosingTag("init_from");
|
||||
Writer->writeLineBreak();
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ public:
|
|||
//! writes a mesh
|
||||
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE) _IRR_OVERRIDE_;
|
||||
|
||||
// Restrict the characters of oldString a set of allowed characters in xs::NCName and add the prefix.
|
||||
// Restrict the characters of oldString a set of allowed characters in xs:NCName and add the prefix.
|
||||
virtual irr::core::stringc toNCName(const irr::core::stringc& oldString, const irr::core::stringc& prefix=irr::core::stringc("_NC_")) const _IRR_OVERRIDE_;
|
||||
|
||||
//! After export you can find out which name had been used for writing the geometry for this node.
|
||||
|
@ -269,8 +269,8 @@ protected:
|
|||
Escape = e;
|
||||
}
|
||||
|
||||
irr::c8 Character;
|
||||
irr::core::stringc Escape;
|
||||
irr::c8 Character; // unescaped (like ' ')
|
||||
irr::core::stringc Escape; // escaped (like '%20')
|
||||
};
|
||||
irr::core::array<EscapeCharacterURL> EscapeCharsAnyURI;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue