bool SMDImporter::Import ( char *in_szFilename )
{

	FILE *f = fopen ( in_szFilename, "rb" );

	if ( !f )
	{
		LPWSTR l_wszModelName;
		DSA2W(&l_wszModelName,in_szFilename);

		XSI::CString cstr = L"SMDImport: Cannot open the file ";
		cstr += l_wszModelName;

		XSILogMessage ( (unsigned short*)cstr.GetWideString(), XSI::siErrorMsg );
		return false;
	}
	
	memset ( m_szActionName, 0, 1024 );
	_splitpath ( in_szFilename, NULL, NULL, m_szActionName, NULL );

	char drive[1024];
	char dirc[1024];

	memset ( m_szDirectory, 0, 1024 );

	if ( strlen(___gTexturePathOverride))
	{
		sprintf ( ___gTexturePathOverride, "%s\\", ___gTexturePathOverride );
		_splitpath ( ___gTexturePathOverride, drive, dirc, NULL, NULL );
		sprintf ( m_szDirectory, "%s\\%s\\", drive, dirc );
	} else {
		_splitpath ( in_szFilename, drive, dirc, NULL, NULL );
		sprintf ( m_szDirectory, "%s\\%s\\", drive, dirc );
	}

	
	bool Success = Parse ( f );

	fclose (f);

	if ( !Success )
	{
		return Success;
	}

	DetectModel();

	CreateHierarchy();

	CreateGeometry();

	WeightGeometry();

	CreateShapeClips();

	CreateAnimationSource();

	return true;
}
void SMDNodeList::AddNode ( XSI::CString in_szName, int in_iParentID, XSI::X3DObject in_pModel, XSI::Kinematics	in_pHierarchyCompensation ,XSI::Kinematics	in_pHierarchyCompensation2 )
{

	char *pSzString = new char [ in_szName.Length() + 1 ];
	W2AHelper ( pSzString, in_szName.GetWideString() );
	
	AddNodeS ( pSzString, in_iParentID, in_pModel, in_pHierarchyCompensation ,in_pHierarchyCompensation2 );

	delete [] pSzString;

}
//-----------------------------------------------------------------------------
// Registers/deregisters all commands
//-----------------------------------------------------------------------------
bool CVsMayaCommandFactoryBase::RegisterAllCommands( XSI::PluginRegistrar& in_reg )
{
	CVsMayaCommandFactoryBase *pFactory;
	for ( pFactory = s_pFirstCommandFactory; pFactory; pFactory = pFactory->m_pNextFactory )
	{
		XSI::CString str;
		str.PutAsciiString( pFactory->GetCommandName() );
		pFactory->OnRegister( in_reg );
		in_reg.RegisterCommand( str );
	}

	return true;
}
void DependencyExporter::exportFile(XSI::CString directory, std::string fileName, const char *data, unsigned int dataLength){
	XSI::CString outputFile = directory + fileName.c_str();

	bool updateCanvasSize = fileName.compare("index.html")==0;
	if (updateCanvasSize){
		exportUpdateCanvasSize(outputFile, data, dataLength);
		return;
	}

    std::ofstream myFile (outputFile.GetWideString(), std::ios::out | std::ios::binary);
    myFile.write (data, dataLength);
	myFile.close();
}
void SMDNodeList::AddNode ( XSI::CString in_szName, XSI::CString  in_szParentName,  XSI::Kinematics	l_pHierarchyCompensation, XSI::Kinematics l_pHierarchyCompensation2)
{
	char *pString1 = new char [ in_szName.Length() + 1 ];
	char *pString2 = new char [ in_szParentName.Length() + 1 ];

	W2AHelper ( pString1, in_szName.GetWideString() );
	W2AHelper ( pString2, in_szParentName.GetWideString() );

	AddNode ( pString1, pString2, l_pHierarchyCompensation, l_pHierarchyCompensation2);


	delete [] pString1;
	delete [] pString2;


}
void deleteArchive(XSI::CString path)
{
  std::map<std::string,Alembic::Abc::IArchive *>::iterator it;
  it = gArchives.find(path.GetAsciiString());
  if(it == gArchives.end())
    return;
  delete(it->second);
  gArchives.erase(it);
}
void DependencyExporter::exportAllFiles(XSI::CString directory){
	if (directory.GetAt(directory.Length()-1) != '\\'){
		directory += L"\\" ;
	}
	exportFile(directory, res_Resource1::Filename, res_Resource1::Data,res_Resource1::Length);
	exportFile(directory, res_Resource2::Filename, res_Resource2::Data,res_Resource2::Length);
	exportFile(directory, res_Resource3::Filename, res_Resource3::Data,res_Resource3::Length);
	exportFile(directory, res_Resource4::Filename, res_Resource4::Data,res_Resource4::Length);
	exportFile(directory, res_Resource5::Filename, res_Resource5::Data,res_Resource5::Length);
	exportFile(directory, res_Resource6::Filename, res_Resource6::Data,res_Resource6::Length);
	exportFile(directory, res_Resource7::Filename, res_Resource7::Data,res_Resource7::Length);
	exportFile(directory, res_Resource8::Filename, res_Resource8::Data,res_Resource8::Length);
	exportFile(directory, res_Resource9::Filename, res_Resource9::Data,res_Resource9::Length);
	exportFile(directory, res_Resource10::Filename, res_Resource10::Data,res_Resource10::Length);
	exportFile(directory, res_Resource11::Filename, res_Resource11::Data,res_Resource11::Length);
	exportFile(directory, res_Resource12::Filename, res_Resource12::Data,res_Resource12::Length);
	exportFile(directory, res_Resource13::Filename, res_Resource13::Data,res_Resource13::Length);
	exportFile(directory, res_Resource14::Filename, res_Resource14::Data,res_Resource14::Length);
}
void DependencyExporter::exportUpdateCanvasSize(XSI::CString outputFile, const char *data, unsigned int dataLength){
	std::string htmlData(data,dataLength);

	htmlData = replace(htmlData, "width=\"1000\"", replace("width=\"1000\"","1000", toString(this->width)));
	htmlData = replace(htmlData, "height=\"500\"", replace("height=\"500\"","500", toString(this->height)));
	data = htmlData.c_str();
	dataLength = htmlData.length();
	std::ofstream myFile (outputFile.GetWideString(), std::ios::out | std::ios::binary);
    myFile.write (data, dataLength);
	myFile.close();
}
Alembic::Abc::IObject getObjectFromArchive(XSI::CString path, XSI::CString identifier)
{
  Alembic::Abc::IArchive * archive = getArchiveFromID(path);
  if(archive == NULL)
    return Alembic::Abc::IObject();

  // split the path
  std::string stdIdentifier(identifier.GetAsciiString());
  std::vector<std::string> parts;
  boost::split(parts, stdIdentifier, boost::is_any_of("/"));

  // recurse to find it
  Alembic::Abc::IObject obj = archive->getTop();
  for(size_t i=1;i<parts.size();i++)
  {
    Alembic::Abc::IObject child(obj,parts[i]);
    obj = child;
  }

  return obj;
}
void SMDImporter::CreateAnimationSource()
{
	XSI::ActionSource actionSource;

	float animStart = 9999;
	float animEnd = -9999;

	XSI::CString animatedObjects;

	for (int c=0;c<m_pNodes.GetUsed();c++)
	{
		SMDNode* node = m_pNodes[c];

		if ( node->m_pKeys.GetUsed() > 1 )
		{
			if ( !actionSource.IsValid() )
			{
				LPWSTR l_wszActionName;
				DSA2W(&l_wszActionName,m_szActionName);

				actionSource = m_pModel.AddActionSource( l_wszActionName );
			}

			XSI::Parameter x = node->m_x3d.GetParameters().GetItem( L"posx" );
			XSI::Parameter y = node->m_x3d.GetParameters().GetItem( L"posy" );
			XSI::Parameter z = node->m_x3d.GetParameters().GetItem( L"posz" );

			XSI::Parameter rx = node->m_x3d.GetParameters().GetItem( L"rotx" );
			XSI::Parameter ry = node->m_x3d.GetParameters().GetItem( L"roty" );
			XSI::Parameter rz = node->m_x3d.GetParameters().GetItem( L"rotz" );

			node->m_fOldX = x.GetValue();
			node->m_fOldY = y.GetValue();
			node->m_fOldZ = z.GetValue();
			node->m_fOldRX = rx.GetValue();
			node->m_fOldRY = ry.GetValue();
			node->m_fOldRZ = rz.GetValue();


			XSI::FCurve fcrvx;
			x.AddFCurve( XSI::siStandardFCurve, fcrvx	);
			XSI::FCurve fcrvy;
			y.AddFCurve( XSI::siStandardFCurve, fcrvy	);
			XSI::FCurve fcrvz;
			z.AddFCurve( XSI::siStandardFCurve, fcrvz	);
			XSI::FCurve fcrvrx;
			rx.AddFCurve( XSI::siStandardFCurve, fcrvrx	);
			XSI::FCurve fcrvry;
			ry.AddFCurve( XSI::siStandardFCurve, fcrvry	);
			XSI::FCurve fcrvrz;
			rz.AddFCurve( XSI::siStandardFCurve, fcrvrz	);
			
			XSI::CTimeArray time(node->m_pKeys.GetUsed());
			XSI::CValueArray xv(node->m_pKeys.GetUsed());
			XSI::CValueArray yv(node->m_pKeys.GetUsed());
			XSI::CValueArray zv(node->m_pKeys.GetUsed());
			
			XSI::CValueArray rxv(node->m_pKeys.GetUsed());
			XSI::CValueArray ryv(node->m_pKeys.GetUsed());
			XSI::CValueArray rzv(node->m_pKeys.GetUsed());
	
			if ( node->m_pParent ==NULL )
			{
				for (int k=0;k<node->m_pKeys.GetUsed();k++)
				{
				
					if ( node->GetKey(k)->m_fTime < animStart )
					{
						animStart = node->GetKey(k)->m_fTime;
					}

					if ( node->GetKey(k)->m_fTime > animEnd )
					{
						animEnd = node->GetKey(k)->m_fTime;
					}

					XSI::MATH::CTransformation xfo1;
					XSI::MATH::CTransformation xfo2;
					
					xfo1.SetRotationFromXYZAnglesValues ( node->GetKey(k)->m_vRotation.GetX(), node->GetKey(k)->m_vRotation.GetY(), node->GetKey(k)->m_vRotation.GetZ() );
					xfo1.SetTranslationFromValues ( node->GetKey(k)->m_vPosition.GetX(), node->GetKey(k)->m_vPosition.GetY(), node->GetKey(k)->m_vPosition.GetZ() );

					xfo2.SetRotationFromXYZAnglesValues ( -1.570796, 0.0, 0.0 );
					xfo1.MulInPlace(xfo2);

					double dx,dy,dz;
					double drx, dry, drz;

					xfo1.GetTranslationValues ( dx, dy, dz);
					xfo1.GetRotationFromXYZAnglesValues(drx, dry, drz);

					time[k] = k;
					xv[k] = dx;
					yv[k] = dy;
					zv[k] = dz;
					
					rxv[k] = drx * 57.29577951308232286465;
					ryv[k] = dry * 57.29577951308232286465;
					rzv[k] = drz * 57.29577951308232286465;

				}
				
			} else {
				
				for (int k=0;k<node->m_pKeys.GetUsed();k++)
				{
					
					if ( node->GetKey(k)->m_fTime < animStart )
					{
						animStart = node->GetKey(k)->m_fTime;
					}

					if ( node->GetKey(k)->m_fTime > animEnd )
					{
						animEnd = node->GetKey(k)->m_fTime;
					}

					time[k] = k;
					xv[k] = node->GetKey(k)->m_vPosition.GetX();
					yv[k] = node->GetKey(k)->m_vPosition.GetY();
					zv[k] = node->GetKey(k)->m_vPosition.GetZ();
					
					rxv[k] = node->GetKey(k)->m_vRotation.GetX() * 57.29577951308232286465;
					ryv[k] = node->GetKey(k)->m_vRotation.GetY() * 57.29577951308232286465;
					rzv[k] = node->GetKey(k)->m_vRotation.GetZ() * 57.29577951308232286465;
				}
			}

			fcrvx.SetKeys ( time, xv );
			fcrvy.SetKeys ( time, yv );
			fcrvz.SetKeys ( time, zv );

			fcrvrx.SetKeys ( time, rxv );
			fcrvry.SetKeys ( time, ryv );
			fcrvrz.SetKeys ( time, rzv );

			LPWSTR l_wszModelName;
			DSA2W(&l_wszModelName,FixName(node->m_szName));
			XSI::CString cname = l_wszModelName;

			actionSource.AddSourceItem ( cname + L".kine.local.posx", fcrvx, true ); 
			actionSource.AddSourceItem ( cname + L".kine.local.posy", fcrvy, true );
			actionSource.AddSourceItem ( cname + L".kine.local.posz", fcrvz, true );

			actionSource.AddSourceItem ( cname + L".kine.local.rotx", fcrvrx, true ); 
			actionSource.AddSourceItem ( cname + L".kine.local.roty", fcrvry, true );
			actionSource.AddSourceItem ( cname + L".kine.local.rotz", fcrvrz, true );
		
			// build up the string list of objects that we want to remove animation from
			if (animatedObjects.IsEmpty() == false) {
				animatedObjects += L", ";
			}
			animatedObjects += node->m_x3d.GetFullName();
		}
	}

	if ( actionSource.IsValid() )
	{
		actionSource.PutParameterValue(L"FrameStart", (double)animStart);
		actionSource.PutParameterValue(L"FrameEnd", (double)animEnd);
	}

	// remove animation on all objects that were imported
	// and animated
	if (animatedObjects.IsEmpty() == false) {
		XSI::Application app;
		XSI::CValue out;
		XSI::CValueArray args(4);

		args[0] = animatedObjects;
		args[1] = XSI::CValue();
		args[2] = (long)XSI::siBranch;
		args[3] = (long)(XSI::siFCurveSource);
		app.ExecuteCommand(L"RemoveAllAnimation", args, out);
	}
}