void UnFbx::FFbxImporter::ImportTexturesFromNode(FbxNode* Node)
{
	FbxProperty Property;
	int32 NbMat = Node->GetMaterialCount();

	// visit all materials
	int32 MaterialIndex;
	for (MaterialIndex = 0; MaterialIndex < NbMat; MaterialIndex++)
	{
		FbxSurfaceMaterial *Material = Node->GetMaterial(MaterialIndex);

		//go through all the possible textures
		if(Material)
		{
			int32 TextureIndex;
			FBXSDK_FOR_EACH_TEXTURE(TextureIndex)
			{
				Property = Material->FindProperty(FbxLayerElement::sTextureChannelNames[TextureIndex]);

				if( Property.IsValid() )
				{
					FbxTexture * lTexture= NULL;

					//Here we have to check if it's layered textures, or just textures:
					int32 LayeredTextureCount = Property.GetSrcObjectCount(FbxLayeredTexture::ClassId);
					FbxString PropertyName = Property.GetName();
					if(LayeredTextureCount > 0)
					{
						for(int32 LayerIndex=0; LayerIndex<LayeredTextureCount; ++LayerIndex)
						{
							FbxLayeredTexture *lLayeredTexture = FbxCast <FbxLayeredTexture>(Property.GetSrcObject(FbxLayeredTexture::ClassId, LayerIndex));
							int32 NbTextures = lLayeredTexture->GetSrcObjectCount(FbxTexture::ClassId);
							for(int32 TexIndex =0; TexIndex<NbTextures; ++TexIndex)
							{
								FbxFileTexture* Texture = FbxCast <FbxFileTexture> (lLayeredTexture->GetSrcObject(FbxFileTexture::ClassId,TexIndex));
								if(Texture)
								{
									ImportTexture(Texture, PropertyName == FbxSurfaceMaterial::sNormalMap || PropertyName == FbxSurfaceMaterial::sBump);
								}
							}
						}
					}
					else
					{
						//no layered texture simply get on the property
						int32 NbTextures = Property.GetSrcObjectCount(FbxTexture::ClassId);
						for(int32 TexIndex =0; TexIndex<NbTextures; ++TexIndex)
						{

							FbxFileTexture* Texture = FbxCast <FbxFileTexture> (Property.GetSrcObject(FbxFileTexture::ClassId,TexIndex));
							if(Texture)
							{
								ImportTexture(Texture, PropertyName == FbxSurfaceMaterial::sNormalMap || PropertyName == FbxSurfaceMaterial::sBump);
							}
						}
					}
				}
			}

		}//end if(Material)

	}// end for MaterialIndex
}
void FbxToHkxConverter::extractKeyFramesAndAnnotations(hkxScene *scene, FbxNode* fbxChildNode, hkxNode* newChildNode, int animStackIndex)
{
	FbxAMatrix bindPoseMatrix;
	FbxAnimStack* lAnimStack = NULL;
	int numAnimLayers = 0;
	FbxTimeSpan animTimeSpan;
	
	if (animStackIndex >= 0)
	{
		lAnimStack = m_curFbxScene->GetSrcObject<FbxAnimStack>(animStackIndex);
		numAnimLayers = lAnimStack->GetMemberCount<FbxAnimLayer>();
		animTimeSpan = lAnimStack->GetLocalTimeSpan();
	}

	// Find the time offset (in the "time space" of the FBX file) of the first animation frame
	FbxTime timePerFrame; timePerFrame.SetTime(0, 0, 0, 1, 0, m_curFbxScene->GetGlobalSettings().GetTimeMode());
	const FbxTime startTime = animTimeSpan.GetStart();
	const FbxTime endTime = animTimeSpan.GetStop();

	const hkReal startTimeSeconds = static_cast<hkReal>(startTime.GetSecondDouble());
	const hkReal endTimeSeconds = static_cast<hkReal>(endTime.GetSecondDouble());

	int numFrames = 0;
	bool staticNode = true;

	if (scene->m_sceneLength == 0)
	{
		bindPoseMatrix = fbxChildNode->EvaluateLocalTransform(startTime);
	}
	else
	{
		hkArray<hkStringOld> annotationStrings;
		hkArray<hkReal> annotationTimes;

		HK_ASSERT(0x0, newChildNode->m_keyFrames.getSize() == 0);

		// Sample each animation frame
		for (FbxTime time = startTime, priorSampleTime = endTime;
			 time < endTime;
			 priorSampleTime = time, time += timePerFrame, ++numFrames)
		{
			FbxAMatrix frameMatrix = fbxChildNode->EvaluateLocalTransform(time);
			staticNode = staticNode && (frameMatrix == bindPoseMatrix);

			hkMatrix4 mat;

			// Extract this frame's transform
			convertFbxXMatrixToMatrix4(frameMatrix, mat);
			newChildNode->m_keyFrames.pushBack(mat);

			// Extract all annotation strings for this frame using the deprecated
			// pipeline (new annotations are extracted when sampling attributes)
			if (m_options.m_exportAnnotations && numAnimLayers > 0)
			{
				FbxProperty prop = fbxChildNode->GetFirstProperty();
				while(prop.IsValid())
				{
					FbxString propName  = prop.GetName();
					FbxDataType lDataType = prop.GetPropertyDataType();
					hkStringOld name(propName.Buffer(), (int) propName.GetLen());
					if (name.asUpperCase().beginsWith("HK") && lDataType.GetType() == eFbxEnum)
					{
						FbxAnimLayer* lAnimLayer = lAnimStack->GetMember<FbxAnimLayer>(0);
						FbxAnimCurve* lAnimCurve = prop.GetCurve(lAnimLayer);

						int currentKeyIndex;
						const int keyIndex = (int) lAnimCurve->KeyFind(time, &currentKeyIndex);
						const int priorKeyIndex = (int) lAnimCurve->KeyFind(priorSampleTime);

						// Only store annotations on frames where they're explicitly keyframed, or if this is the first keyframe 
						if (priorKeyIndex != keyIndex)
						{
							const int currentEnumValueIndex = keyIndex < 0 ? (int) lAnimCurve->Evaluate(priorSampleTime) : (int) lAnimCurve->Evaluate(time);
							HK_ASSERT(0x0, currentEnumValueIndex < prop.GetEnumCount());
							const char* enumValue = prop.GetEnumValue(currentEnumValueIndex);
							hkxNode::AnnotationData& annotation = newChildNode->m_annotations.expandOne();
							annotation.m_time = (hkReal) (time - startTime).GetSecondDouble();
							annotation.m_description = (name + hkStringOld(enumValue, hkString::strLen(enumValue))).cString();
						}
					}
					prop = fbxChildNode->GetNextProperty(prop);
				}
			}
		}
	}

	// Replace animation key data for static nodes with just 1 or 2 frames of bind pose data
	if (staticNode)
	{
		// Static nodes in animated scene data are exported with two keys
		const bool exportTwoFramesForStaticNodes = (numFrames > 1);

		// replace transform
		newChildNode->m_keyFrames.setSize(exportTwoFramesForStaticNodes ? 2: 1);
		newChildNode->m_keyFrames.optimizeCapacity(0, true);

		// convert the bind pose transform to Havok format
		convertFbxXMatrixToMatrix4(bindPoseMatrix, newChildNode->m_keyFrames[0]);

		if (exportTwoFramesForStaticNodes)
		{
			newChildNode->m_keyFrames[1] = newChildNode->m_keyFrames[0];
		}
	}

	// Extract all times of actual keyframes for the current node... this can be used by Vision
	if ( m_options.m_storeKeyframeSamplePoints &&
		 newChildNode->m_keyFrames.getSize() > 2 &&
		 numAnimLayers > 0 )
	{
		FbxAnimLayer* lAnimLayer = lAnimStack->GetMember<FbxAnimLayer>(0);

		extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_TRANSLATION, newChildNode, startTimeSeconds, endTimeSeconds);
		extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_ROTATION, newChildNode, startTimeSeconds, endTimeSeconds);
		extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_SCALING, newChildNode, startTimeSeconds, endTimeSeconds);
		extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, newChildNode, startTimeSeconds, endTimeSeconds);
		extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, newChildNode, startTimeSeconds, endTimeSeconds);
		extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, newChildNode, startTimeSeconds, endTimeSeconds);

		if (newChildNode->m_linearKeyFrameHints.getSize() > 1)
		{
			hkSort(newChildNode->m_linearKeyFrameHints.begin(), newChildNode->m_linearKeyFrameHints.getSize());
		}
	}
}
void Tools::DisplayAnimation::DisplayChannels( FbxNode* i_node, FbxAnimLayer* i_animLayer, void (*DisplayCurve) (FbxAnimCurve* i_curve), void (*DisplayListCurve) (FbxAnimCurve* i_curve, FbxProperty* i_property), bool isSwitcher )
{
	FbxAnimCurve *animCurve = NULL;

	// Display general curves.
	if (!isSwitcher)
	{
		animCurve = i_node->LclTranslation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_X );
		if( animCurve )
		{
			FBXSDK_printf( "        TX\n" );
			DisplayCommon::DisplayString( "        TX" );
			DisplayCurve( animCurve );
		}
		animCurve = i_node->LclTranslation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Y );
		if( animCurve )
		{
			FBXSDK_printf( "        TY\n" );
			DisplayCommon::DisplayString( "        TY" );
			DisplayCurve( animCurve );
		}
		animCurve = i_node->LclTranslation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Z );
		if( animCurve )
		{
			FBXSDK_printf( "        TZ\n" );
			DisplayCommon::DisplayString( "        TZ" );
			DisplayCurve( animCurve );
		}

		animCurve = i_node->LclRotation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_X );
		if( animCurve )
		{
			FBXSDK_printf( "        RX\n" );
			DisplayCommon::DisplayString( "        RX" );
			DisplayCurve( animCurve );
		}
		animCurve = i_node->LclRotation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Y );
		if( animCurve )
		{
			FBXSDK_printf( "        RY\n" );
			DisplayCommon::DisplayString( "        RY" );
			DisplayCurve( animCurve );
		}
		animCurve = i_node->LclRotation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Z );
		if( animCurve )
		{
			FBXSDK_printf( "        RZ\n" );
			DisplayCommon::DisplayString( "        RZ" );
			DisplayCurve( animCurve );
		}

		animCurve = i_node->LclScaling.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_X );
		if( animCurve )
		{
			FBXSDK_printf( "        SX\n" );
			DisplayCommon::DisplayString( "        SX" );
			DisplayCurve( animCurve );
		}
		animCurve = i_node->LclScaling.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Y );
		if( animCurve )
		{
			FBXSDK_printf( "        SY\n" );
			DisplayCommon::DisplayString( "        SY" );
			DisplayCurve( animCurve );
		}
		animCurve = i_node->LclScaling.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Z );
		if( animCurve )
		{
			FBXSDK_printf( "        SZ\n" );
			DisplayCommon::DisplayString( "        SZ" );
			DisplayCurve( animCurve );
		}
	}

	// Display curves specific to a light or marker.
	FbxNodeAttribute *nodeAttribute = i_node->GetNodeAttribute();

	if( nodeAttribute )
	{
		animCurve = nodeAttribute->Color.GetCurve( i_animLayer, FBXSDK_CURVENODE_COLOR_RED );
		if( animCurve )
		{
			FBXSDK_printf( "        Red\n" );
			DisplayCommon::DisplayString( "        Red" );
			DisplayCurve( animCurve );
		}
		animCurve = nodeAttribute->Color.GetCurve( i_animLayer, FBXSDK_CURVENODE_COLOR_GREEN );
		if( animCurve )
		{
			FBXSDK_printf( "        Green\n" );
			DisplayCommon::DisplayString( "        Green" );
			DisplayCurve( animCurve );
		}
		animCurve = nodeAttribute->Color.GetCurve( i_animLayer, FBXSDK_CURVENODE_COLOR_BLUE );
		if( animCurve )
		{
			FBXSDK_printf( "        Blue\n" );
			DisplayCommon::DisplayString( "        Blue" );
			DisplayCurve( animCurve );
		}

		// Display curves specific to a light.
		FbxLight *light = i_node->GetLight();
		if( light )
		{
			animCurve = light->Intensity.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Intensity\n" );
				DisplayCommon::DisplayString( "        Intensity" );
				DisplayCurve( animCurve );
			}

			animCurve = light->OuterAngle.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Outer Angle\n" );
				DisplayCommon::DisplayString( "        Outer Angle" );
				DisplayCurve( animCurve );
			}

			animCurve = light->Fog.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Fog\n" );
				DisplayCommon::DisplayString( "        Fog" );
				DisplayCurve( animCurve );
			}
		}

		// Display curves specific to a camera.
		FbxCamera *camera = i_node->GetCamera();
		if( camera )
		{
			animCurve = camera->FieldOfView.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Field of View\n" );
				DisplayCommon::DisplayString( "        Field of View" );
				DisplayCurve( animCurve );
			}

			animCurve = camera->FieldOfViewX.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Field of View X\n" );
				DisplayCommon::DisplayString( "        Field of View X" );
				DisplayCurve( animCurve );
			}

			animCurve = camera->FieldOfViewY.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Field of View Y\n" );
				DisplayCommon::DisplayString( "        Field of View Y" );
				DisplayCurve( animCurve );
			}

			animCurve = camera->OpticalCenterX.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Optical Center X\n" );
				DisplayCommon::DisplayString( "        Optical Center X" );
				DisplayCurve( animCurve );
			}

			animCurve = camera->OpticalCenterY.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Optical Center Y\n" );
				DisplayCommon::DisplayString( "        Optical Center Y" );
				DisplayCurve( animCurve );
			}

			animCurve = camera->Roll.GetCurve( i_animLayer );
			if( animCurve )
			{
				FBXSDK_printf( "        Roll\n" );
				DisplayCommon::DisplayString( "        Roll" );
				DisplayCurve( animCurve );
			}
		}

		// Display curves specific to a geometry.
		if (nodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh ||
			nodeAttribute->GetAttributeType() == FbxNodeAttribute::eNurbs ||
			nodeAttribute->GetAttributeType() == FbxNodeAttribute::ePatch)
		{
			FbxGeometry *geometry = (FbxGeometry*) nodeAttribute;

			int blendShapeDeformerCount = geometry->GetDeformerCount( FbxDeformer::eBlendShape );
			for( int blendShapeIndex = 0; blendShapeIndex<blendShapeDeformerCount; blendShapeIndex++ )
			{
				FbxBlendShape *blendShape = (FbxBlendShape*)geometry->GetDeformer( blendShapeIndex, FbxDeformer::eBlendShape );

				int blendShapeChannelCount = blendShape->GetBlendShapeChannelCount();
				for( int channelIndex = 0; channelIndex<blendShapeChannelCount; channelIndex++ )
				{
					FbxBlendShapeChannel *channel = blendShape->GetBlendShapeChannel( channelIndex );
					const char *channelName = channel->GetName();

					animCurve = geometry->GetShapeChannel( blendShapeIndex, channelIndex, i_animLayer, true );
					if( animCurve )
					{
						FBXSDK_printf( "        Shape %s\n", channelName );
						DisplayCommon::DisplayString( "        Shape ", channelName );
						DisplayCurve( animCurve );
					}
				}
			}
		}
	}

	// Display curves specific to properties
	FbxProperty lProperty = i_node->GetFirstProperty();
	while( lProperty.IsValid() )
	{
		if( lProperty.GetFlag(FbxPropertyAttr::eUserDefined) )
		{
			FbxString lFbxFCurveNodeName  = lProperty.GetName();
			FbxAnimCurveNode* curveNode = lProperty.GetCurveNode( i_animLayer );

			if( !curveNode )
			{
				lProperty = i_node->GetNextProperty( lProperty );
				continue;
			}

			FbxDataType dataType = lProperty.GetPropertyDataType();
			if( dataType.GetType() == eFbxBool || dataType.GetType() == eFbxDouble || dataType.GetType() == eFbxFloat || dataType.GetType() == eFbxInt )
			{
				FbxString message;

				message =  "        Property ";
				message += lProperty.GetName();
				if( lProperty.GetLabel().GetLen() > 0 )
				{
					message += " (Label: ";
					message += lProperty.GetLabel();
					message += ")";
				};

				DisplayCommon::DisplayString( message );

				for( int c = 0; c < curveNode->GetCurveCount(0U); c++ )
				{
					animCurve = curveNode->GetCurve( 0U, c );
					if( animCurve )
						DisplayCurve( animCurve );
				}
			}
			else if( dataType.GetType() == eFbxDouble3 || dataType.GetType() == eFbxDouble4 || dataType.Is(FbxColor3DT) || dataType.Is(FbxColor4DT) )
			{
				char* componentName1 = (dataType.Is(FbxColor3DT) ||dataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_RED : (char*)"X";
				char* componentName2 = (dataType.Is(FbxColor3DT) ||dataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_GREEN : (char*)"Y";
				char* componentName3 = (dataType.Is(FbxColor3DT) ||dataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_BLUE  : (char*)"Z";
				FbxString message;

				message =  "        Property ";
				message += lProperty.GetName();
				if( lProperty.GetLabel().GetLen() > 0 )
				{
					message += " (Label: ";
					message += lProperty.GetLabel();
					message += ")";
				}
				DisplayCommon::DisplayString( message );

				for( int c = 0; c < curveNode->GetCurveCount(0U); c++ )
				{
					animCurve = curveNode->GetCurve( 0U, c );
					if( animCurve )
					{
						DisplayCommon::DisplayString( "        Component ", componentName1 );
						DisplayCurve( animCurve );
					}
				}

				for( int c = 0; c < curveNode->GetCurveCount(1U); c++ )
				{
					animCurve = curveNode->GetCurve(1U, c);
					if( animCurve )
					{
						DisplayCommon::DisplayString( "        Component ", componentName2 );
						DisplayCurve( animCurve );
					}
				}

				for( int c = 0; c < curveNode->GetCurveCount(2U); c++ )
				{
					animCurve = curveNode->GetCurve( 2U, c );
					if( animCurve )
					{
						DisplayCommon::DisplayString( "        Component ", componentName3 );
						DisplayCurve( animCurve );
					}
				}
			}
			else if( dataType.GetType() == eFbxEnum )
			{
				FbxString message;

				message =  "        Property ";
				message += lProperty.GetName();
				if( lProperty.GetLabel().GetLen() > 0 )
				{
					message += " (Label: ";
					message += lProperty.GetLabel();
					message += ")";
				};
				DisplayCommon::DisplayString( message );

				for( int c = 0; c < curveNode->GetCurveCount(0U); c++ )
				{
					animCurve = curveNode->GetCurve( 0U, c );
					if( animCurve )
						DisplayListCurve( animCurve, &lProperty );
				}
			}
		}

		lProperty = i_node->GetNextProperty( lProperty );
	} // while
}
void Tools::DisplayGenericInfo::DisplayProperties( FbxObject *i_object )
{
	DisplayCommon::DisplayString( "Name: ", (char *)i_object->GetName() );

	// Display all the properties
	int i, count = 0;
	FbxProperty lProperty = i_object->GetFirstProperty();
	while( lProperty.IsValid() )
	{
		count++;
		lProperty = i_object->GetNextProperty( lProperty );
	}

	FbxString lTitleStr = "    Property Count: ";

	if( count == 0 )
		return; // there are no properties to display

	DisplayCommon::DisplayInt( lTitleStr.Buffer(), count );

	i = 0;
	lProperty = i_object->GetFirstProperty();
	while( lProperty.IsValid() )
	{
		// exclude user properties
		FbxString string;
		DisplayCommon::DisplayInt( "        Property ", i );
		string = lProperty.GetLabel();
		DisplayCommon::DisplayString( "            Display Name: ", string );
		string = lProperty.GetName();
		DisplayCommon::DisplayString( "            Internal Name: ", string.Buffer() );
		string = lProperty.GetPropertyDataType().GetName();
		DisplayCommon::DisplayString( "            Type: ",string.Buffer() );
		if (lProperty.HasMinLimit())
			DisplayCommon::DisplayDouble( "            Min Limit: ", lProperty.GetMinLimit() );
		if (lProperty.HasMaxLimit())
			DisplayCommon::DisplayDouble( "            Max Limit: ", lProperty.GetMaxLimit() );
		DisplayCommon::DisplayBool( "            Is Animatable: ", lProperty.GetFlag(FbxPropertyAttr::eAnimatable) );

		switch( lProperty.GetPropertyDataType().GetType() )
		{
		case eFbxBool:
			DisplayCommon::DisplayBool( "            Default Value: ", lProperty.Get<FbxBool>() );
			break;

		case eFbxDouble:
			DisplayCommon::DisplayDouble( "            Default Value: ", lProperty.Get<FbxDouble>() );
			break;

		case eFbxDouble4:
			{
				FbxColor lDefault;
				char buffer[64];

				lDefault = lProperty.Get<FbxColor>();
				FBXSDK_sprintf( buffer, 64, "R=%f, G=%f, B=%f, A=%f", lDefault.mRed, lDefault.mGreen, lDefault.mBlue, lDefault.mAlpha );
				DisplayCommon::DisplayString( "            Default Value: ", buffer );
			}
			break;

		case eFbxInt:
			DisplayCommon::DisplayInt( "            Default Value: ", lProperty.Get<FbxInt>() );
			break;

		case eFbxDouble3:
			{
				FbxDouble3 lDefault;
				char buffer[64];

				lDefault = lProperty.Get<FbxDouble3>();
				FBXSDK_sprintf( buffer, 64, "X=%f, Y=%f, Z=%f", lDefault[0], lDefault[1], lDefault[2] );
				DisplayCommon::DisplayString( "            Default Value: ", buffer );
			}
			break;

			//case FbxEnumDT:
			//    DisplayInt("            Default Value: ", lProperty.Get<FbxEnum>());
			//    break;

		case eFbxFloat:
			DisplayCommon::DisplayDouble( "            Default Value: ", lProperty.Get<FbxFloat>() );
			break;

		case eFbxString:
			string = lProperty.Get<FbxString>();
			DisplayCommon::DisplayString( "            Default Value: ", string.Buffer() );
			break;

		default:
			DisplayCommon::DisplayString( "            Default Value: UNIDENTIFIED" );
			break;
		}
		i++;
		lProperty = i_object->GetNextProperty( lProperty );
	}
}