#ifndef _MPxMayaAsciiFilter
#define _MPxMayaAsciiFilter
//-
// ===========================================================================
// Copyright 2018 Autodesk, Inc. All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk license
// agreement provided at the time of installation or download, or which
// otherwise accompanies this software in either electronic or hard copy form.
// ===========================================================================
//+
//
// CLASS DESCRIPTION (MPxMayaAsciiFilter)
//
//  This class allows the output to the Maya Ascii (.ma) file format to be
//	filtered by a plug-in. This can be used to, for example, partition a scene
//	into several files which have been each filtered to write out different
//	parts of the scene.
//
// ****************************************************************************

#if defined __cplusplus

// ****************************************************************************
// INCLUDED HEADER FILES

#include <maya/MPxFileTranslator.h>
#include <maya/MFileObject.h>


OPENMAYA_MAJOR_NAMESPACE_OPEN

//! \ingroup OpenMaya MPx
//! \brief Wrapper for a Maya Ascii file output stream.
/*!
	MPxMayaAsciiFilterOutput is used in conjunction with MPxMayaAsciiFilter
	to allow output to the Maya ASCII file. Instances of this class may only be
	instantiated through the methods of MPxMayaAsciiFilter.
*/
class OPENMAYA_EXPORT MPxMayaAsciiFilterOutput
{
public:
	MPxMayaAsciiFilterOutput(void* outputFile);

	MPxMayaAsciiFilterOutput&		operator << (const char* data);

protected:
	// No protected members

private:
	void*				file;

};

// ****************************************************************************
// CLASS DECLARATION (MPxMayaAsciiFilter)

//! \ingroup OpenMaya MPx
//! \brief Translator to output filtered Maya ASCII files. 
/*!
MPxMayaAsciiFilter allows output to the Maya ASCII (.ma) file format to be
filtered by a plug-in. The file is output using the same internal mechanism
that is used for normal Maya ASCII output, but allows your plug-in to prevent
certain lines (such as createNodes or connectAttrs) from being output to the
file. In addition, it allows you to write directly to the file at specific
points during output.

MPxMayaAsciiFilter allows your plug-in to write out files similar to Maya ASCII
in a custom format. It can be used, for example, to partition a scene into several
files, each of which has been filtered to write out different parts of
the scene. Note that the order of the file cannot be changed - for example,
connectAttrs are always written after createNodes - but it does allow you to control
which connectAttrs and createNodes are output.

MPxMayaAsciiFilter inherits from MPxFileTranslator. It overrides the
haveWriteMethod(), haveReadMethod(), reader(), and writer() methods in
MPxFileTranslator in such a way that the internal Maya mechanism for reading and
writing Maya ASCII files is used. Because of this, it is not advised that you
override these methods in your plug-in. If you do, make sure you first call these
methods in MPxMayaAsciiFilter. A pseudo-code example is shown here:

\code
MyAsciiFilter::writer(...)
{
	// do something before writing to file here
	...

	// we will now write to the file

	MStatus result = MPxMayaAsciiFilter::writer(...);

	if (result == MStatus::kSuccess)
	{
		...	// do something after writing the file here
	}

	return result;
}
\endcode

To determine if a given line should be output, override the methods
writesCreateNode(), writesSetAttr() and so on. Each of these methods
takes as its arguments the relevant data which is about to be processed
and your plug-in can use this to determine whether or not the line will
be output.

For example, you may want to write out everything but render layer data.
The code to do this might look something like what is shown here:

\code
bool
MyAsciiFilter::writesCreateNode( const MObject& node )
{
	if (node.hasFn(MFn::kRenderLayer))
	{
		return true;
	}

	return false;
}

bool
MyAsciiFilter::writesConnectAttr( const MPlug& srcPlug,
								  const MPlug& destPlug )
{
	if (srcPlug.node().hasFn(MFn::kRenderLayer) ||
		dstPlug.node().hasFn(MFn::kRenderLayer))
	{
		return true;
	}

	return false;
}
\endcode

Note that writesConnectAttr() has to be overridden as well (as would
writesSetAttr(), writesSelectAttr(), and so on). This is because each line is
handled separately, and nothing clever is done in the base class' implementation
of writesConnectAttr(), such as having a default behaviour of only outputting
connectAttrs for nodes that are being output. This gives you the most flexible
control over what will be written.

If you were using this class to save a segmented file, a master file might have
to know about the locations of each of the segments. If your file saved everything
but render layers in one file, and render layers in another, the first file might
need to contain a pointer to the second, so that when the first file is loaded the
second gets read into memory too. To do this, you would use MPxMayaAsciiFilter's
ability to write directly to the stream during file output.

You can write to the stream during output by overriding the methods
writePreCreateNodesBlock(), writePostCreateNodesBlock() and so on. These give
you a simple mechanism to write directly to the file. Each of these methods
take an MPxMayaAsciiFilterOutput as its only argument. To write to the file,
simply use the output operator (MPxMayaAsciiFilterOutput::operator<<() )
and output the string you wish.

In the example above, the pointer to the render layer file might be inserted into
the main file after all nodes have been created. The code to do this would look
something like what is shown here:

\code
MStatus
MyAsciiFilter::writePostCreateNodesBlock( MPxMayaAsciiFilterOutput& fileIO )
{
	fileIO << "eval(\"importRenderLayerFile \\\"MyLayerFile.maf\\\";\")\n";
}
\endcode

In the above example, after the createNode block was output, the line

\code
eval("importRenderLayerFile \"MyLayerFile.maf\"");
\endcode

was output. When the file is read in, Maya would reach the line above
and execute it like any other MEL command. It is assumed in this
example that there would be a custom command plug-in called
importRenderLayerFile which would do the work of actually importing
the layer file.

Note:
MPxMayaAsciiFilter gives you the ability to create your own custom file formats
based on standard Maya ASCII files. However, Autodesk does not support such custom
files as they will not, by definition, be standard Maya ASCII files.
*/
class OPENMAYA_EXPORT MPxMayaAsciiFilter : public MPxFileTranslator
{
public:
						MPxMayaAsciiFilter ();
				virtual ~MPxMayaAsciiFilter ();
	virtual bool		haveWriteMethod() const;
	virtual bool		haveReadMethod() const;
	virtual MStatus		reader ( const MFileObject& file,
								 const MString& optionsString,
								 FileAccessMode mode);
	virtual MStatus		writer ( const MFileObject& file,
								 const MString& optionsString,
								 FileAccessMode mode);

protected:

	const MFileObject	file() const;
	virtual MStatus		processReadOptions	(const MString& optionsString);
	virtual MStatus		processWriteOptions	(const MString& optionsString);
	virtual	bool		writesRequirements	(  ) const;
	virtual	bool		writesMetadata		(  ) const;
	virtual	bool		writesCreateNode	( const MObject& node ) const;
	virtual	bool		writesSetAttr		( const MPlug& srcPlug ) const;
	virtual	bool		writesConnectAttr	( const MPlug& srcPlug,
											  const MPlug& destPlug ) const;
	virtual	bool		writesDisconnectAttr( const MPlug& srcPlug,
											  const MPlug& destPlug ) const;
	virtual	bool		writesParentNode	( const MDagPath& parent, const MDagPath& child ) const;
	virtual	bool		writesSelectNode	( const MObject& node ) const;
	virtual	bool		writesFileReference	( const MFileObject& referenceFile ) const;
	virtual MStatus		writePostHeader		( MPxMayaAsciiFilterOutput& fileIO );
	virtual MStatus		writePostRequires	( MPxMayaAsciiFilterOutput& fileIO );
	virtual MStatus		writePreCreateNodesBlock( MPxMayaAsciiFilterOutput& fileIO );
	virtual MStatus		writePostCreateNodesBlock( MPxMayaAsciiFilterOutput& fileIO );
	virtual MStatus		writePreConnectAttrsBlock( MPxMayaAsciiFilterOutput& fileIO );
	virtual MStatus		writePostConnectAttrsBlock( MPxMayaAsciiFilterOutput& fileIO );
	virtual MStatus		writePreTrailer( MPxMayaAsciiFilterOutput& fileIO );

private:

	MFileObject			fileObject;

};

OPENMAYA_NAMESPACE_CLOSE

#endif /* __cplusplus */
#endif /* _MPxMayaAsciiFilter */
