本文整理汇总了C++中XmlElement::SetAttribute方法的典型用法代码示例。如果您正苦于以下问题:C++ XmlElement::SetAttribute方法的具体用法?C++ XmlElement::SetAttribute怎么用?C++ XmlElement::SetAttribute使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类XmlElement
的用法示例。
在下文中一共展示了XmlElement::SetAttribute方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: WriteToFile
//[-------------------------------------------------------]
//[ Private virtual PLSceneNode functions ]
//[-------------------------------------------------------]
void PLSceneCellPortal::WriteToFile(XmlElement &cSceneElement, const String &sApplicationDrive, const String &sApplicationDir)
{
// Add scene node
XmlElement *pNodeElement = new XmlElement("Node");
pNodeElement->SetAttribute("Class", GetClassName());
pNodeElement->SetAttribute("Name", GetName());
// Write position, rotation, scale, bounding box and flags
WriteToFilePosRotScaleBoxFlags(*pNodeElement);
// Target cell
pNodeElement->SetAttribute("TargetCell", m_sTargetCell);
// [TODO] Check this again, within the Dungeon-Demo scene, this test fails for one portal...
// Check cell-portal direction and write a warning into the log if the direction looks wrong
float fDot = 0.0f;
PLSceneContainer *pContainer = GetContainer();
if (pContainer) {
// Get world space direction vector from cell-portal to owner cell
Point3 vDir = pContainer->GetWorldSpaceCenter() - m_vCenter;
vDir.Unify();
// Check whether the cell-portal looks into the owner cell
fDot = DotProd(m_vNormal, vDir);
if (fDot < 0.0f)
g_pLog->LogFLine(PLLog::Warning, "%s: The cell-portal doesn't look INTO the cell (%s) it is in!!", GetIGameNode()->GetName(), pContainer->GetName().GetASCII());
}
// Vertices
std::vector<Point3>::size_type nNumOfVertices = m_lstVertices.size();
String sVertices;
if (fDot < 0.0f && g_SEOptions.bCorrectPortals) {
// Invert vertex order
for (std::vector<Point3>::size_type i=nNumOfVertices; i>0; i--) {
const Point3 &vVertex = m_lstVertices[i-1];
if (i)
sVertices += String::Format("%f %f %f ", vVertex.x, vVertex.y, vVertex.z);
else
sVertices += String::Format("%f %f %f", vVertex.x, vVertex.y, vVertex.z);
}
} else {
for (std::vector<Point3>::size_type i=0; i<nNumOfVertices; i++) {
const Point3 &vVertex = m_lstVertices[i];
if (i < nNumOfVertices-1)
sVertices += String::Format("%f %f %f ", vVertex.x, vVertex.y, vVertex.z);
else
sVertices += String::Format("%f %f %f", vVertex.x, vVertex.y, vVertex.z);
}
}
pNodeElement->SetAttribute("Vertices", sVertices);
// Write flexible variables
WriteVariables(*pNodeElement);
// Write modifiers
WriteModifiers(*pNodeElement, sApplicationDrive, sApplicationDir);
// Link node element
cSceneElement.LinkEndChild(*pNodeElement);
}
示例2: Save
/**
* @brief
* Saves the material
*/
bool PLSceneMaterial::Save(const String &sApplicationDrive, const String &sApplicationDir)
{
// Create XML document
XmlDocument cDocument;
// Add declaration
XmlDeclaration *pDeclaration = new XmlDeclaration("1.0", "ISO-8859-1", "");
cDocument.LinkEndChild(*pDeclaration);
// Add material
XmlElement *pMaterialElement = new XmlElement("Material");
pMaterialElement->SetAttribute("Version", "1");
// Save the parameters
SaveParameters(*pMaterialElement);
// Link material element
cDocument.LinkEndChild(*pMaterialElement);
// Get the absolute material filename
const String sFilename = sApplicationDrive + sApplicationDir + PLTools::GetResourceFilename(PLTools::ResourceMaterial, m_sName);
{ // Before we safe, we need to ensure that the target directory is there, else 'Save()' will fail!
Url cUrl = sFilename;
Directory cDirectory(cUrl.CutFilename());
cDirectory.CreateRecursive();
}
// Save settings
cDocument.Save(sFilename);
// Done
return true;
}
示例3: WriteToFilePosRotScaleBoxFlags
/**
* @brief
* Writes the scene node position, rotation, scale, bounding box and flags into a file
*/
void PLSceneNode::WriteToFilePosRotScaleBoxFlags(XmlElement &cNodeElement) const
{
// Currently ONLY the center of the container the node is in use used to make it relative
const Point3 vParentWorldSpaceCenter = GetContainer() ? GetContainer()->GetWorldSpaceCenter() : Point3(0.0f, 0.0f, 0.0f);
// Write down the position
PLTools::XmlElementSetAttributeWithDefault(cNodeElement, "Position", (GetType() != TypeScene && GetType() != TypeCell) ? m_vPos-vParentWorldSpaceCenter : static_cast<const PLSceneContainer*>(this)->GetWorldSpaceCenter(), Point3(0.0f, 0.0f, 0.0f));
// Write down the rotation
PLTools::XmlElementSetAttributeWithDefault(cNodeElement, "Rotation", m_vRot, Point3(0.0f, 0.0f, 0.0f));
// Write down the scale
PLTools::XmlElementSetAttributeWithDefault(cNodeElement, "Scale", m_vScale, Point3(1.0f, 1.0f, 1.0f));
// Are there any flags?
if (m_sFlags.GetLength()) {
String sFlags = cNodeElement.GetAttribute("Flags");
if (sFlags.GetLength())
sFlags += '|' + m_sFlags;
else
sFlags = m_sFlags;
sFlags.Trim();
cNodeElement.SetAttribute("Flags", sFlags);
}
}
示例4: WriteVariables
/**
* @brief
* Writes the flexible scene node variables
*/
void PLSceneNode::WriteVariables(XmlElement &cNodeElement) const
{
// Export variables?
if (g_SEOptions.bUserPropVariables) {
// Is there a 3ds Max node (No 3ds Max node, no properties)
INode *pMaxNode = GetMaxNode();
if (pMaxNode) {
// Check for variables
TSTR s3dsMaxString;
if (pMaxNode->GetUserPropString(_T("Vars"), s3dsMaxString)) {
// Get all expressions
static RegEx cExpressionRegEx("\\s*((\\w*\\s*=\\s*\"[^\"]*\")|(\\w*\\s*=\\s*[\\w|]*))");
const String sString = s3dsMaxString;
uint32 nExpressionParsePos = 0;
while (cExpressionRegEx.Match(sString, nExpressionParsePos)) {
// Get expression
nExpressionParsePos = cExpressionRegEx.GetPosition();
const String sExpression = cExpressionRegEx.GetResult(0);
// Process the found expression
static RegEx cRegEx("\\s*(\\w*)\\s*=\\s*\"?\\s*([^\"]*)\\s*\"?");
if (cRegEx.Match(sExpression)) {
// Get name and value
const String sName = cRegEx.GetResult(0);
const String sValue = cRegEx.GetResult(1);
// Flags variable?
if (sName == "Flags") {
// Update attribute
String sFlags = cNodeElement.GetAttribute(sName);
if (sFlags.GetLength())
sFlags += '|' + sValue;
else
sFlags = sValue;
sFlags.Trim();
cNodeElement.SetAttribute(sName, sFlags);
} else {
// Set attribute
cNodeElement.SetAttribute(sName, sValue);
}
}
}
}
}
}
}
示例5: AppendInformation
/**
* @brief
* Appends the parsed information about a plugin to the given XML document
*/
void PLPluginInfo::AppendInformation(XmlDocument &cDocument) const
{
// Add declaration
XmlDeclaration *pDeclaration = new XmlDeclaration("1.0", "", "");
cDocument.LinkEndChild(*pDeclaration);
XmlElement *pRootElement = new XmlElement("Plugin");
pRootElement->SetAttribute("Version", m_sPluginFileVersion);
pRootElement->SetAttribute("PixelLightVersion", m_sPLVersion);
AddTextXmlElement(*pRootElement, "Active", m_bActive ? "1" : "0");
AddTextXmlElement(*pRootElement, "Delayed", m_bDelayed ? "1" : "0");
AddTextXmlElement(*pRootElement, "Name", m_sPluginName);
if (m_sModuleVersion.GetLength())
AddTextXmlElement(*pRootElement, "Version", m_sModuleVersion);
if (m_sVendor.GetLength())
AddTextXmlElement(*pRootElement, "Vendor", m_sVendor);
if (m_sLicense.GetLength())
AddTextXmlElement(*pRootElement, "License", m_sLicense);
if (m_sDescription.GetLength())
AddTextXmlElement(*pRootElement, "Description", m_sDescription);
cDocument.LinkEndChild(*pRootElement);
// Append the parsed information to the given XML element
m_cPluginPlatformInfo.Save(*pRootElement);
// Are there any classes?
if (!m_lstClasses.IsEmpty()) {
// Create the classes XML element instance
XmlElement *pClassesElement = new XmlElement("Classes");
// Iterate through all classes
ConstIterator<PLPluginClassInfo*> cIterator = m_lstClasses.GetConstIterator();
while (cIterator.HasNext())
cIterator.Next()->Save(*pClassesElement);
// Link the classes XML element instance to the XML root element
pRootElement->LinkEndChild(*pClassesElement);
}
}
示例6: WriteTargetRotationModifier
/**
* @brief
* Writes a target rotation scene node modifier
*/
void PLSceneNode::WriteTargetRotationModifier(XmlElement &cSceneElement, INode &cTarget, bool bFlip) const
{
// Get the PL scene node
String sTarget;
PLSceneNode *pSceneNode = GetScene().GetPLSceneNode(cTarget);
if (pSceneNode) {
// Same container?
if (pSceneNode->GetContainer() == GetContainer()) {
// Yeah, that was easy!
sTarget = pSceneNode->GetName();
} else {
// The exported supports only 'one' cell level, else this would be a bit more complex...
if (pSceneNode->GetContainer() == &GetScene()) {
sTarget += "Parent.";
sTarget += pSceneNode->GetName();
} else {
sTarget += "Parent.";
sTarget += pSceneNode->GetContainer()->GetName();
sTarget += '.';
sTarget += pSceneNode->GetName();
}
}
// Fallback: Use the 3ds Max node name
} else {
sTarget = cTarget.GetName();
g_pLog->LogFLine(PLLog::Warning, "'%s' target node: There's no PL scene node with the name '%s'", m_sName.GetASCII(), sTarget.GetASCII());
}
// Add scene node modifier
XmlElement *pModifierElement = new XmlElement("Modifier");
pModifierElement->SetAttribute("Class", "PLScene::SNMRotationTarget");
pModifierElement->SetAttribute("Target", sTarget);
if (bFlip)
pModifierElement->SetAttribute("Offset", "0 180 0");
// Link modifier element
cSceneElement.LinkEndChild(*pModifierElement);
}
示例7: WriteToFile
/**
* @brief
* Writes the scene container into a file
*/
void PLSceneContainer::WriteToFile(XmlElement &cSceneElement, const String &sApplicationDrive, const String &sApplicationDir, const String &sClass)
{
// Add scene node
XmlElement *pNodeElement = new XmlElement("Container");
pNodeElement->SetAttribute("Class", sClass);
pNodeElement->SetAttribute("Name", GetName());
// [TODO] Currently the bounding boxes are not correct
/* if (!PLTools::IsEmpty(m_cBoundingBox)) {
const Point3 vMin = m_cBoundingBox.pmin-m_vCenter;
const Point3 vMax = m_cBoundingBox.pmax-m_vCenter;
pNodeElement->SetAttribute("AABBMin", String::Format("%f %f %f", vMin.x, vMin.y, vMin.z));
pNodeElement->SetAttribute("AABBMax", String::Format("%f %f %f", vMax.x, vMax.y, vMax.z));
}
*/
// Write position, rotation, scale, bounding box and flags
WriteToFilePosRotScaleBoxFlags(*pNodeElement);
// Write flexible variables
WriteVariables(*pNodeElement);
// Write modifiers
WriteModifiers(*pNodeElement, sApplicationDrive, sApplicationDir);
// Are there any modifiers or scene nodes?
if (m_lstSceneNodes.size()) {
// Write down the child nodes
for (std::vector<PLSceneNode*>::size_type i=0; i<m_lstSceneNodes.size(); i++) {
PLSceneNode *pSceneNode = m_lstSceneNodes[i];
if (pSceneNode)
pSceneNode->WriteToFile(*pNodeElement, sApplicationDrive, sApplicationDir);
}
}
// Link node element
cSceneElement.LinkEndChild(*pNodeElement);
}
示例8: XmlElementSetAttributeWithDefault
void PLTools::XmlElementSetAttributeWithDefault(XmlElement &cXmlElement, const String &sName, float fValue, float fDefaultValue)
{
// Is the given value equal to the given default value?
if (fValue != fDefaultValue) {
// Value to string
const String sValue = String::Format("%f", fValue);
// Due to rounding errors the string may now or may not contain the given default value, check for this
if (sValue.GetFloat() != fDefaultValue)
cXmlElement.SetAttribute(sName, sValue);
} else {
// The given value is equal to the default value -> nothing to do
}
}
示例9: SaveTexture
/**
* @brief
* Saves a texture
*/
void PLSceneMaterial::SaveTexture(XmlElement &cMaterialElement, const String &sFilename, const String &sSemantic, bool bNormalMap_xGxR)
{
// Get known semantic
String sPLSemantic = sSemantic;
if (sPLSemantic.CompareNoCase("Ambient Color", 0, 13) || sPLSemantic.CompareNoCase("EmissiveMap", 0, 11))
sPLSemantic = "EmissiveMap";
else if (sPLSemantic.CompareNoCase("Diffuse Color", 0, 13) || sPLSemantic.CompareNoCase("DiffuseMap", 0, 10))
sPLSemantic = "DiffuseMap";
else if (sPLSemantic.CompareNoCase("Specular Color", 0, 14) || sPLSemantic.CompareNoCase("SpecularMap", 0, 11))
sPLSemantic = "SpecularMap";
else if (sPLSemantic.CompareNoCase("Self-Illumination", 0, 17) || sPLSemantic.CompareNoCase("LightMap", 0, 8))
sPLSemantic = "LightMap";
else if (sPLSemantic.CompareNoCase("Filter Color", 0, 12) || sPLSemantic.CompareNoCase("DetailNormalMap", 0, 15))
sPLSemantic = "DetailNormalMap";
else if (sPLSemantic.CompareNoCase("Bump", 0, 4) || sPLSemantic.CompareNoCase("NormalMap", 0, 9))
sPLSemantic = "NormalMap";
else if (sPLSemantic.CompareNoCase("Reflection", 0, 10) || sPLSemantic.CompareNoCase("ReflectionMap", 0, 13))
sPLSemantic = "ReflectionMap";
else if (sPLSemantic.CompareNoCase("Refraction", 0, 10) || sPLSemantic.CompareNoCase("ReflectivityMap", 0, 15))
sPLSemantic = "ReflectivityMap";
else if (sPLSemantic.CompareNoCase("Displacement", 0, 13) ||sPLSemantic.CompareNoCase("HeightMap", 0, 9))
sPLSemantic = "HeightMap";
else {
// Unknown to the exporter - just export it anyway so we don't loose important information
}
// Copy texture if there's a known semantic
if (sPLSemantic.GetLength()) {
PLSceneTexture *pTexture = m_pScene->CopyTexture(sFilename, bNormalMap_xGxR);
if (pTexture) {
// Add to material
XmlElement *pTextureElement = new XmlElement("Texture");
pTextureElement->SetAttribute("Name", sPLSemantic);
// Add value
XmlText *pValue = new XmlText(pTexture->GetName());
pTextureElement->LinkEndChild(*pValue);
// Link texture element
cMaterialElement.LinkEndChild(*pTextureElement);
}
}
}
示例10: WriteModifiers
/**
* @brief
* Writes the scene node modifiers
*/
void PLSceneNode::WriteModifiers(XmlElement &cSceneElement, const String &sApplicationDrive, const String &sApplicationDir)
{
// Is there a 3ds Max node? (no 3ds Max node, no properties)
INode *pMaxNode = GetMaxNode();
if (pMaxNode) {
// Has this 3ds Max node a target?
if (pMaxNode->GetTarget()) {
// Write down the scene node modifier
WriteTargetRotationModifier(cSceneElement, *pMaxNode->GetTarget(), false);
}
// Are there any position, rotation, scale keyframes?
bool bPositionKeyframes = false;
bool bRotationKeyframes = false;
bool bScaleKeyframes = false;
// Check 3ds Max node controllers
Control *pTMController = pMaxNode->GetTMController();
if (pTMController) {
// Position controller
Control *pController = pTMController->GetPositionController();
if (pController) {
// Are there any position keyframes?
bPositionKeyframes = PLTools::HasKeyControlInterface(*pController);
if (!bPositionKeyframes) {
// Is there a path controller?
IPathPosition *pPathController = GetIPathConstInterface(pController);
if (pPathController && pPathController->GetNumTargets() > 0) {
INode *pTarget = pPathController->GetNode(0);
if (pTarget) {
// Get path filename
const String sPathFilename = PLTools::GetResourceFilename(PLTools::ResourcePath, String(pTarget->GetName()) + ".path");
// Get the percentage along the path
float fPercentageAlongPath = 0.0f;
{
IParamBlock2 *pIParamBlock2 = pPathController->GetParamBlock(path_params);
int nRefNum = pIParamBlock2 ? pIParamBlock2->GetControllerRefNum(path_percent) : -1;
RefTargetHandle cRefTargetHandle = (nRefNum >= 0) ? pIParamBlock2->GetReference(nRefNum) : nullptr;
if (cRefTargetHandle)
fPercentageAlongPath = pIParamBlock2->GetFloat(path_percent, 0);
}
{ // Add scene node modifier
XmlElement *pModifierElement = new XmlElement("Modifier");
pModifierElement->SetAttribute("Class", "PLScene::SNMPositionPath");
pModifierElement->SetAttribute("Filename", sPathFilename);
pModifierElement->SetAttribute("Progress", String::Format("%f", fPercentageAlongPath));
// [TODO] Any change to setup speed inside 3ds Max?
static const float fSpeed = 0.03f;
// Automatic animation playback?
if (g_SEOptions.bAnimationPlayback)
pModifierElement->SetAttribute("Speed", String::Format("%f", (pPathController->GetFlip() ? -fSpeed : fSpeed)));
else
pModifierElement->SetAttribute("Speed", "0.0");
// Link modifier element
cSceneElement.LinkEndChild(*pModifierElement);
}
// Follow?
if (pPathController->GetFollow()) {
// Add scene node modifier
XmlElement *pModifierElement = new XmlElement("Modifier");
pModifierElement->SetAttribute("Class", "PLScene::SNMRotationMoveDirection");
// Link modifier element
cSceneElement.LinkEndChild(*pModifierElement);
}
}
}
}
}
// Rotation controller
pController = pTMController->GetRotationController();
if (pController) {
// Are there any rotation keyframes?
bRotationKeyframes = PLTools::HasKeyControlInterface(*pController);
if (!bRotationKeyframes) {
// Is there a look at controller?
ILookAtConstRotation *pLookAtController = GetILookAtConstInterface(pController);
if (pLookAtController && pLookAtController->GetNumTargets() > 0) {
INode *pTarget = pLookAtController->GetNode(0);
if (pTarget) {
// Check look at controller
bool bFlip = (pLookAtController->GetTargetAxisFlip() != 0);
// Write down the scene node modifier
WriteTargetRotationModifier(cSceneElement, *pTarget, bFlip);
}
}
}
}
//.........这里部分代码省略.........
示例11: cDirectory
//.........这里部分代码省略.........
} else {
sAbsBitmapFilename = sBitmapFilename;
}
}
} else {
sAbsBitmapFilename = sBitmapFilename;
}
}
}
if (hFile != INVALID_HANDLE_VALUE) {
// Get source file time and close it
FILETIME sSourceCreationTime;
FILETIME sSourceLastAccessTime;
FILETIME sSourceLastWriteTime;
GetFileTime(hFile, &sSourceCreationTime, &sSourceLastAccessTime, &sSourceLastWriteTime);
CloseHandle(hFile);
// Cut of the filename
String sFilename = Url(g_SEOptions.sFilename).CutFilename();
// Construct the absolute target filename
uint32 nLength = sFilename.GetLength();
if (nLength) {
sFilename = sFilename + m_sName;
// Is there already such a file? If yes, check the file times...
hFile = CreateFileW(sFilename.GetUnicode(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile != INVALID_HANDLE_VALUE) {
// Get target file time and close it
FILETIME sTargetCreationTime;
FILETIME sTargetLastAccessTime;
FILETIME sTargetLastWriteTime;
GetFileTime(hFile, &sTargetCreationTime, &sTargetLastAccessTime, &sTargetLastWriteTime);
CloseHandle(hFile);
// Compare file time
long nResult = CompareFileTime(&sTargetLastWriteTime, &sSourceLastWriteTime);
if (nResult >= 0)
return; // Nothing to do :)
}
{ // Before we copy, we need to ensure that the target directory is there, else 'CopyFile()' will fail!
Directory cDirectory(Url(sFilename).CutFilename());
cDirectory.CreateRecursive();
}
// Copy the texture (bitmap)
CopyFileW(sAbsBitmapFilename.GetUnicode(), sFilename.GetUnicode(), false);
// If there's a 'plt'-file for the texture, copy it, too
int nIndex = sFilename.LastIndexOf(".");
if (nIndex >= 0) {
sFilename.Delete(nIndex);
sFilename += ".plt";
nIndex = sAbsBitmapFilename.LastIndexOf(".");
if (nIndex >= 0) {
sAbsBitmapFilename.Delete(nIndex);
sAbsBitmapFilename += ".plt";
if (!CopyFileW(sAbsBitmapFilename.GetUnicode(), sFilename.GetUnicode(), false)) {
// Failed to copy the 'plt'-file...
if (bNormalMap_xGxR) {
// Create an automatic 'plt'-file...
// Create XML document
XmlDocument cDocument;
// Add declaration
XmlDeclaration *pDeclaration = new XmlDeclaration("1.0", "ISO-8859-1", "");
cDocument.LinkEndChild(*pDeclaration);
// Add texture
XmlElement *pTextureElement = new XmlElement("Texture");
// Setup attribute
pTextureElement->SetAttribute("Version", "1");
// Add general
XmlElement *pGeneralElement = new XmlElement("Node");
pGeneralElement->SetAttribute("Compression", "DXT5_xGxR");
// Link general element
pTextureElement->LinkEndChild(*pGeneralElement);
// Link material element
cDocument.LinkEndChild(*pTextureElement);
// Save settings
if (cDocument.Save(sFilename))
g_pLog->LogFLine(PLLog::Hint, "Created '%s'", sFilename.GetASCII());
else
g_pLog->LogFLine(PLLog::Error, "Can't create '%s'!", sFilename.GetASCII());
}
}
}
}
}
} else {
g_pLog->LogFLine(PLLog::Error, "Can't find texture (bitmap) '%s'!", m_sName.GetASCII());
}
}
}
示例12: WriteToFile
//[-------------------------------------------------------]
//[ Private virtual PLSceneNode functions ]
//[-------------------------------------------------------]
void PLSceneSpline::WriteToFile(XmlElement &cSceneElement, const String &sApplicationDrive, const String &sApplicationDir)
{
// Do NOT save it as scene node, it's just a 'resource'
// Get path filename
const String sFilename = sApplicationDrive + sApplicationDir + PLTools::GetResourceFilename(PLTools::ResourcePath, GetName() + ".path");
// Get the IGame spline object of the given IGame node
IGameObject *pIGameObject = GetIGameNode()->GetIGameObject();
if (pIGameObject) {
// Check the type of the IGame object
if (pIGameObject->GetIGameType() == IGameObject::IGAME_SPLINE && pIGameObject->InitializeData()) {
IGameSpline &cIGameSpline = *static_cast<IGameSpline*>(pIGameObject);
if (cIGameSpline.GetNumberOfSplines () > 0) {
// We only support spline 0
IGameSpline3D *pIGameSpline3D = cIGameSpline.GetIGameSpline3D(0);
if (pIGameSpline3D) {
// Get the local transform matrix
GMatrix mTransform = cIGameSpline.GetIGameObjectTM();
// Get the 3ds Max shape object
ShapeObject *pMaxShapeObject = static_cast<ShapeObject*>(pIGameObject->GetMaxObject()->ConvertToType(TIME_PosInfinity, Class_ID(GENERIC_SHAPE_CLASS_ID, 0)));
if (pMaxShapeObject != nullptr && pMaxShapeObject->NumberOfCurves() == cIGameSpline.GetNumberOfSplines()) {
// Create XML document
XmlDocument cDocument;
// Add declaration
XmlDeclaration *pDeclaration = new XmlDeclaration("1.0", "ISO-8859-1", "");
cDocument.LinkEndChild(*pDeclaration);
// Add path
XmlElement *pPathElement = new XmlElement("Path");
// Setup attributes
pPathElement->SetAttribute("Version", "1");
pPathElement->SetAttribute("Closed", String::Format("%d", pMaxShapeObject->CurveClosed(0, 0)));
// Add all nodes
for (int nKnot=0; nKnot<pIGameSpline3D->GetIGameKnotCount(); nKnot++) {
IGameKnot *pIGameKnot = pIGameSpline3D->GetIGameKnot(nKnot);
if (pIGameKnot) {
// Get knot point in object space (although it is not documented it looks like object space...)
Point3 cPoint = pIGameKnot->GetKnotPoint();
// We really need to flip the coordinates to OpenGL style, IGame is not doing this automatically...
cPoint = PLTools::Convert3dsMaxVectorToOpenGLVector(cPoint);
// Transform to world space
cPoint = cPoint*mTransform;
// If there's a parent container, make the position of this scene node relative to it
PLSceneContainer *pContainer = GetContainer();
if (pContainer)
cPoint -= pContainer->GetWorldSpaceCenter();
// Add node
XmlElement *pNodeElement = new XmlElement("Node");
pNodeElement->SetAttribute("Name", String::Format("%d", nKnot));
pNodeElement->SetAttribute("Position", String::Format("%f %f %f", cPoint.x, cPoint.y, cPoint.z));
// Link general element
pPathElement->LinkEndChild(*pNodeElement);
}
}
// Link material element
cDocument.LinkEndChild(*pPathElement);
// Save settings
if (cDocument.Save(sFilename))
g_pLog->LogFLine(PLLog::Hint, "Created '%s'", sFilename.GetASCII());
else
g_pLog->LogFLine(PLLog::Error, "Can't create '%s'!", sFilename.GetASCII());
}
}
}
} else {
g_pLog->LogFLine(PLLog::Error, "%s: IGame object is no known spline object!", GetIGameNode()->GetName());
}
// Release the IGame object
GetIGameNode()->ReleaseIGameObject();
} else {
g_pLog->LogFLine(PLLog::Error, "%s: IGame node has no IGame object!", GetIGameNode()->GetName());
}
}