Exemplo n.º 1
0
//[-------------------------------------------------------]
//[ 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);
}
Exemplo n.º 2
0
/**
*  @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;
}
Exemplo n.º 3
0
/**
*  @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);
	}
}
Exemplo n.º 4
0
/**
*  @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);
						}
					}
				}
			}
		}
	}
}
Exemplo n.º 5
0
/**
*  @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);
	}
}
Exemplo n.º 6
0
/**
*  @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);
}
Exemplo n.º 7
0
/**
*  @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);
}
Exemplo n.º 8
0
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
	}
}
Exemplo n.º 9
0
void PLTools::XmlElementSetAttributeWithDefault(XmlElement &cXmlElement, const String &sName, const Point3 &cPoint, const Point3 &cDefault)
{
	// Is the given value equal to the given default value?
	if (cPoint.x != cDefault.x || cPoint.y != cDefault.y || cPoint.z != cDefault.z) {
		// Value to string
		const String sValue = String::Format("%f %f %f", cPoint.x, cPoint.y, cPoint.z);

		// Due to rounding errors the string may now or may not contain the given default value, check for this
		float fValues[3] = { 0.0f, 0.0f, 0.0f };
		ParseTools::ParseFloatArray(sValue, fValues, 3);
		if (fValues[0] != cDefault.x || fValues[1] != cDefault.y || fValues[2] != cDefault.z)
			cXmlElement.SetAttribute(sName, sValue);
	} else {
		// The given value is equal to the default value -> nothing to do
	}
}
Exemplo n.º 10
0
/**
*  @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);
		}
	}
}
Exemplo n.º 11
0
/**
*  @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);
						}
					}
				}
			}

			// Scale controller
			pController = pTMController->GetScaleController();
			if (pController) {
				// Are there any scale keyframes?
				bScaleKeyframes = PLTools::HasKeyControlInterface(*pController);
			}
		}

		// Export keyframes?
		if (bPositionKeyframes || bRotationKeyframes || bScaleKeyframes) {
			// Get timing
			Interval cInterval = GetCOREInterface()->GetAnimRange();
			int nTicksPerFrame = GetTicksPerFrame();
			int nFrameCount    = (cInterval.End() - cInterval.Start()) / nTicksPerFrame + 1;

			// Used to detect whether or not something is animated
			Point3 vFirstPos, vFirstScale;
			Quat qFirstRot;
			bool bUsePosition = false, bUseScale = false, bUseRotation = false;

			// Prepare the position chunk
			Chunk cPositionChunk;
			cPositionChunk.SetSemantic(Chunk::Position);
			cPositionChunk.Allocate(Chunk::Float, 3, nFrameCount);
			float *pfPositionData = reinterpret_cast<float*>(cPositionChunk.GetData());

			// Prepare the rotation chunk
			Chunk cRotationChunk;
			cRotationChunk.SetSemantic(Chunk::Rotation);
			cRotationChunk.Allocate(Chunk::Float, 4, nFrameCount);
			float *pfRotationData = reinterpret_cast<float*>(cRotationChunk.GetData());

			// Prepare the scale chunk
			Chunk cScaleChunk;
			cScaleChunk.SetSemantic(Chunk::Scale);
			cScaleChunk.Allocate(Chunk::Float, 3, nFrameCount);
			float *pfScaleData = reinterpret_cast<float*>(cScaleChunk.GetData());

			// Loop through all frames
			int nTime = cInterval.Start();
			for (int nFrame=0; nFrame<nFrameCount; nFrame++, nTime+=nTicksPerFrame) {
				// Get the position, rotation and scale
				Point3 vPos, vScale;
				Quat qRot;
				GetPosRotScale(vPos, qRot, vScale, nTime);

				// First frame?
				if (!nFrame) {
					vFirstPos   = vPos;
					vFirstScale = vScale;
					qFirstRot   = qRot;
				} else {
					if (!vFirstPos.Equals(vPos))
						bUsePosition = true;
					if (!vFirstScale.Equals(vScale))
						bUseScale = true;
					if (!qFirstRot.Equals(qRot))
						bUseRotation = true;
				}

				// Position
				if (bPositionKeyframes && pfPositionData) {
					// 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);

					// Get the position
					const Point3 vFinalPos = (GetType() != TypeScene && GetType() != TypeCell) ? vPos-vParentWorldSpaceCenter : static_cast<const PLSceneContainer*>(this)->GetWorldSpaceCenter();

					// x
					*pfPositionData = vFinalPos.x;
					pfPositionData++;

					// y
					*pfPositionData = vFinalPos.y;
					pfPositionData++;

					// z
					*pfPositionData = vFinalPos.z;
					pfPositionData++;
				}

				// Rotation
				if (bRotationKeyframes && pfRotationData) {

					// [TODO] Check this (why do we need it?)
					qRot.Invert();

					// w
					*pfRotationData = qRot.w;
					pfRotationData++;

					// x
					*pfRotationData = qRot.x;
					pfRotationData++;

					// y
					*pfRotationData = qRot.y;
					pfRotationData++;

					// z
					*pfRotationData = qRot.z;
					pfRotationData++;
				}

				// Scale
				if (bScaleKeyframes && pfScaleData) {
					// x
					*pfScaleData = vScale.x;
					pfScaleData++;

					// y
					*pfScaleData = vScale.y;
					pfScaleData++;

					// z
					*pfScaleData = vScale.z;
					pfScaleData++;
				}
			}

			// Create keyframe animation scene node modifiers
			if (bPositionKeyframes && bUsePosition) {
				// [TODO] Better (and safer) filename
				// Save chunk
				const String sPositionKeys = PLTools::GetResourceFilename(PLTools::ResourceKeyframes, String::Format("%s_PositionKeyframes.chunk", GetName().GetASCII()).GetASCII());
				if (SaveChunk(cPositionChunk, sApplicationDrive + sApplicationDir + sPositionKeys)) {
					// Add the modifier
					XmlElement *pModifierElement = new XmlElement("Modifier");

					// Set class attribute
					pModifierElement->SetAttribute("Class", "PLScene::SNMPositionKeyframeAnimation");

					// [TODO] Currently the frame rate is by default always 24
					// Set frames per second attribute
	//				pModifierElement->SetAttribute("FramesPerSecond", GetFrameRate());


					// Automatic animation playback?
					pModifierElement->SetAttribute("Speed", g_SEOptions.bAnimationPlayback ? "1.0" : "0.0");

					// Set keys attribute
					pModifierElement->SetAttribute("Keys", sPositionKeys);

					// Link modifier elements
					cSceneElement.LinkEndChild(*pModifierElement);
				}
			}
			if (bRotationKeyframes && bUseRotation) {
				// [TODO] Better (and safer) filename
				// Save chunk
				const String sRotationKeys = PLTools::GetResourceFilename(PLTools::ResourceKeyframes, String::Format("%s_RotationKeyframes.chunk", GetName().GetASCII()).GetASCII());
				if (SaveChunk(cRotationChunk, sApplicationDrive + sApplicationDir + sRotationKeys)) {
					// Add the modifier
					XmlElement *pModifierElement = new XmlElement("Modifier");

					// Set class attribute
					pModifierElement->SetAttribute("Class", "PLScene::SNMRotationKeyframeAnimation");

					// [TODO] Currently the frame rate is by default always 24
					// Set frames per second attribute
	//				pModifierElement->SetAttribute("FramesPerSecond", GetFrameRate());

					// Automatic animation playback?
					pModifierElement->SetAttribute("Speed", g_SEOptions.bAnimationPlayback ? "1.0" : "0.0");

					// Set keys attribute
					pModifierElement->SetAttribute("Keys", sRotationKeys);

					// Link modifier elements
					cSceneElement.LinkEndChild(*pModifierElement);
				}
			}
			if (bScaleKeyframes && bUseScale) {
				// [TODO] Better (and safer) filename
				// Save chunk
				const String sScaleKeys = PLTools::GetResourceFilename(PLTools::ResourceKeyframes, String::Format("%s_ScaleKeyframes.chunk", GetName().GetASCII()).GetASCII());
				if (SaveChunk(cScaleChunk, sApplicationDrive + sApplicationDir + sScaleKeys)) {
					// Add the modifier
					XmlElement *pModifierElement = new XmlElement("Modifier");

					// Set class attribute
					pModifierElement->SetAttribute("Class", "PLScene::SNMScaleKeyframeAnimation");

					// [TODO] Currently the frame rate is by default always 24
					// Set frames per second attribute
	//				pModifierElement->SetAttribute("FramesPerSecond", GetFrameRate());

					// Automatic animation playback?
					pModifierElement->SetAttribute("Speed", g_SEOptions.bAnimationPlayback ? "1.0" : "0.0");

					// Set keys attribute
					pModifierElement->SetAttribute("Keys", sScaleKeys);

					// Link modifier elements
					cSceneElement.LinkEndChild(*pModifierElement);
				}
			}
		}

		// Use modifiers?
		if (g_SEOptions.bUserPropModifiers) {
			// Check for modifiers
			MSTR sModifier;
			int nIndex = 1;
			TSTR s3dsMaxString;
			sModifier = _T("Mod");
			while (pMaxNode->GetUserPropString(sModifier, s3dsMaxString)) {
				// Add scene node modifier
				XmlElement *pModifierElement = new XmlElement("Modifier");

				// We really NEED a 'Class' attribute!
				bool bClassFound = false;

				// 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);

						// Set attribute
						pModifierElement->SetAttribute(sName, sValue);

						// Class variable already found?
						if (!bClassFound && sName == "Class")
							bClassFound = true;
					}
				}

				// Link modifier element?
				if (bClassFound)
					cSceneElement.LinkEndChild(*pModifierElement);
				else 
					delete pModifierElement;

				// Get next modifier
				sModifier.printf(_T("Mod%d"), nIndex);
				nIndex++;
			}
		}
	}
}
Exemplo n.º 12
0
/**
*  @brief
*    Constructor
*/
PLSceneTexture::PLSceneTexture(PLScene &cScene, const String &sName, bool bNormalMap_xGxR) :
	m_pScene(&cScene),
	m_sName(sName),
	m_nReferenceCount(0)
{
	// Cut of the path of the map name - if there's one
	String sAbsBitmapFilename = m_sName;

	// Get the texture name
	m_sName = sName;

	// Check options
	if (g_SEOptions.bCopyTextures) {
		// Can we use the given absolute filename?
		HANDLE hFile = CreateFileW(sAbsBitmapFilename.GetUnicode(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
		if (hFile == INVALID_HANDLE_VALUE) {
			// Get the current path of the loaded 3ds Max scene
			String sCurFilePath = Url(GetCOREInterface()->GetCurFilePath().data()).CutFilename();
			if (sCurFilePath.GetLength()) {
				// Compose absolute filename by just concatenating the two filenames (for relative filenames)
				String sBitmapFilename = sCurFilePath + sAbsBitmapFilename;
				hFile = CreateFileW(sBitmapFilename.GetUnicode(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
				if (hFile == INVALID_HANDLE_VALUE) {
					// Get the filename without any path information
					String sFilenameOnly  = Url(sName).GetFilename().GetASCII();

					// Compose absolute filename
					if (sFilenameOnly.GetLength()) {
						char nLastCharacter = sCurFilePath[sCurFilePath.GetLength()-1];
						if (nLastCharacter == '\\' || nLastCharacter == '/')
							sBitmapFilename = sCurFilePath + sFilenameOnly;
						else
							sBitmapFilename = sCurFilePath + "\\" + sFilenameOnly;
						hFile = CreateFileW(sBitmapFilename.GetUnicode(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
						if (hFile == INVALID_HANDLE_VALUE) {
							// Check map directories
							int nMapDirCount = TheManager->GetMapDirCount();
							for (int nMapDir=0; nMapDir<nMapDirCount; nMapDir++) {
								const String sMapDir = TheManager->GetMapDir(nMapDir);
								const uint32 nLength = sMapDir.GetLength();
								if (nLength) {
									nLastCharacter = sMapDir[nLength-1];
									if (nLastCharacter == '\\' || nLastCharacter == '/')
										sBitmapFilename = sMapDir + sFilenameOnly;
									else
										sBitmapFilename = sMapDir + '\\' + sFilenameOnly;
									hFile = CreateFileW(sBitmapFilename.GetUnicode(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
									if (hFile != INVALID_HANDLE_VALUE)
										break;
									else
										sAbsBitmapFilename = sBitmapFilename;
								}
							}
						} 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());
		}
	}
}
Exemplo n.º 13
0
//[-------------------------------------------------------]
//[ 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());
	}
}