Beispiel #1
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);
						}
					}
				}
			}
		}
	}
}
Beispiel #2
0
void SelectByChannel::FillOutListBox()
{


	int mapID;
	int subID;

	pblock->GetValue(pb_mapid,0,mapID,FOREVER);
	pblock->GetValue(pb_mapsubid,0,subID,FOREVER);

	MyEnumProc dep;              
	EnumDependents(&dep);

	INode *node = dep.Nodes[0];
	//reset the list box

	SendMessage(GetDlgItem(hWnd,IDC_SELCHANNELCOMBO),
				CB_RESETCONTENT ,0,0);

	channelList.ZeroCount();
	if (dep.Nodes.Count() > 0)
		{
		for (int i = 0; i < 99; i++)
			{
			for (int j = 0; j < 3; j++)
				{
				TSTR key, name;
				key.printf("MapChannel:%d(%d)",i,j);
				if (node->UserPropExists(key))
					{
					node->GetUserPropString(key,name);
					if (name.Length() > 0)
						{
						TSTR lname;
						if (j==0)
							lname.printf("%s %d-Red",name,i);
						if (j==1)
							lname.printf("%s %d-Green",name,i);
						if (j==2)
							lname.printf("%s %d-Blue",name,i);


						SendMessage(GetDlgItem(hWnd,IDC_SELCHANNELCOMBO),
							CB_ADDSTRING,0,(LPARAM)(TCHAR*)lname);					

						ChannelInfo data;
						data.mapID = i;
						data.subID = j;

						channelList.Append(1,&data);
						}
					}
				}
			}
		}

	int sel = -1;
	for (int i = 0; i < channelList.Count(); i++)
		{
		if ((mapID == channelList[i].mapID) && (subID == channelList[i].subID))
			sel = i;
		}

	SendMessage(GetDlgItem(hWnd,IDC_SELCHANNELCOMBO),CB_SETCURSEL  ,sel,0);


}
Beispiel #3
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++;
			}
		}
	}
}
Beispiel #4
0
/**
*  @brief
*    Constructor
*/
PLSceneNode::PLSceneNode(PLSceneContainer *pContainer, IGameNode *pIGameNode, const String &sName, EType nType, const String &sClassName) :
	m_pContainer(pContainer),
	m_pIGameNode(pIGameNode),
	m_sName(sName),
	m_nType(nType),
	m_sClassName(sClassName),
	m_sFlags(""),
	m_vPos(0.0f, 0.0f, 0.0f),
	m_vRot(0.0f, 0.0f, 0.0f),
	m_vScale(1.0f, 1.0f, 1.0f),
	m_nIsRotationFlipped(-1)
{
	// Check some universal flags
	INode *pMaxNode = GetMaxNode();
	if (pMaxNode) { // If this is not a container...
		TSTR sString;

		// Check whether the default PixelLight class is changed
		if (pMaxNode->GetUserPropString(_T("Class"), sString)) {
			m_sClassName = sString;

			// Erase all '"'
			int i = m_sClassName.IndexOf("\"");
			while (i >= 0) {
				m_sClassName.Delete(i, 1);
				i = m_sClassName.IndexOf("\"");
			}
		}

		// Is this 3ds Max node frozen?
		if (pMaxNode->IsFrozen())
			AddFlag("Frozen");

		// Is this 3ds Max node invisible?
		if (pMaxNode->IsHidden() || !pMaxNode->Renderable())
			AddFlag("Invisible");

		// Is this 3ds Max node excluded from lighting?
		INodeGIProperties *pINodeGIProperties = static_cast<INodeGIProperties*>(pMaxNode->GetInterface(NODEGIPROPERTIES_INTERFACE));
		if (pINodeGIProperties && pINodeGIProperties->GIGetIsExcluded())
			AddFlag("NoLighting");

		{ // Get the world space bounding box of the scene node. Because this is not 'trival' we're using
		  // the sample code from "3dsMaxSDK.chm" (3ds Max SDK) -> "The Pipeline and the INode TM Methods"
		  // to get it working correctly.
			::Object *pMaxObject = pMaxNode->GetObjectRef();
			if (pMaxObject) {
				TimeValue t = 0;
				Matrix3 mat;	// The Object TM

				// Determine if the object is in world space or object space
				// so we can get the correct TM. We can check this by getting
				// the Object TM after the world space modifiers have been
				// applied. It the matrix returned is the identity matrix the
				// points of the object have been transformed into world space.
				if (pMaxNode->GetObjTMAfterWSM(t).IsIdentity()) {
					// It's in world space, so put it back into object
					// space. We can do this by computing the inverse
					// of the matrix returned before any world space
					// modifiers were applied.
					mat = Inverse(pMaxNode->GetObjTMBeforeWSM(t));
				} else { 
					// It's in object space, get the Object TM
					mat = pMaxNode->GetObjectTM(t);
				}

				// Get the bound box, and affect it by just the scaling portion
				pMaxObject->GetDeformBBox(t, m_cBoundingBox, &mat);
			}
		}

		// We really need to flip the coordinates to OpenGL style
		m_cBoundingBox.pmin = PLTools::Convert3dsMaxVectorToOpenGLVector(m_cBoundingBox.pmin);
		m_cBoundingBox.pmax = PLTools::Convert3dsMaxVectorToOpenGLVector(m_cBoundingBox.pmax);

		// Validate minimum/maximum - I already had situations with incorrect values causing problems!
		PLTools::ValidateMinimumMaximum(m_cBoundingBox);
	}

	// Get the position, rotation and scale
	GetPosRotScale(m_vPos, m_vRot, m_vScale);
}