#include "cgfxShaderCommon.h"
#include "cgfxShaderCmd.h"
#include "cgfxShaderNode.h"
#include "cgfxProfile.h"
#include "cgfxFindImage.h"
#include <maya/MArgDatabase.h>
#include <maya/MCommandResult.h>
#include <maya/MDagPath.h>
#include <maya/MFeedbackLine.h>
#include <maya/MFnDagNode.h>
#include <maya/MGlobal.h>
#define kMaxTexCoordsFlag "-mtc"
#define kMaxTexCoordsFlagLong "-maxTexCoords"
#define kPluginPathFlag "-pp"
#define kPluginPathFlagLong "-pluginPath"
#define kFxFlag "-fx"
#define kFxFlagLong "-fxFile"
#define kFxPathFlag "-fxp"
#define kFxPathFlagLong "-fxPath"
#define kFxTechniqueFlag "-t"
#define kFxTechniqueFlagLong "-technique"
#define kFxProfileFlag "-pr"
#define kFxProfileFlagLong "-profile"
#define kNameFlag "-n"
#define kNameFlagLong "-name"
#define kListTechniquesFlag "-lt"
#define kListTechniquesFlagLong "-listTechniques"
#define kListProfilesFlag "-lpr"
#define kListProfilesFlagLong "-listProfiles"
#define kListParametersFlag "-lp"
#define kListParametersFlagLong "-listParameters"
#define kParameterFlag "-p"
#define kParameterFlagLong "-parameter"
#define kTexCoordSourceFlag "-tcs"
#define kTexCoordSourceFlagLong "-texCoordSource"
#if MAYA_API_VERSION >= 700
#define kColorSourceFlag "-cs"
#define kColorSourceFlagLong "-colorSource"
#endif
#define kEmptyUVFlag "-euv"
#define kEmptyUVFlagLong "-emptyUV"
#define kEmptyUVShapesFlag "-eus"
#define kEmptyUVShapesFlagLong "-emptyUVShapes"
#define kCaseInsensitiveFlag "-ci"
#define kCaseInsensitiveFlagLong "-caseInsensitive"
#define kDescriptionFlag "-des"
#define kDescriptionFlagLong "-description"
MString cgfxShaderCmd::sPluginPath;
cgfxShaderCmd::doIt(
const MArgList& args )
{
try
{
stat = doCmd( args );
}
catch ( cgfxShaderCommon::InternalError* e )
{
reportInternalError( __FILE__, (size_t)e );
stat = MS::kFailure;
}
catch ( ... )
{
reportInternalError( __FILE__, __LINE__ );
stat = MS::kFailure;
}
return stat;
}
cgfxShaderCmd::redoIt()
{
#ifdef KH_DEBUG
ss += fArgString;
ss += "\n";
::OutputDebugString( ss.
asChar() );
#endif
try
{
stat = fNodeSelection.getDependNode( 0, oNode );
M_CHECK( stat );
M_CHECK( stat && fnNode.typeId() == cgfxShaderNode::sId );
cgfxShaderNode* pNode = (cgfxShaderNode*)fnNode.userNode();
M_CHECK( pNode );
stat = redoCmd( oNode, fnNode, pNode );
}
catch ( cgfxShaderCommon::InternalError* e )
{
reportInternalError( __FILE__, (size_t)e );
stat = MS::kFailure;
}
catch ( ... )
{
reportInternalError( __FILE__, __LINE__ );
stat = MS::kFailure;
}
#ifdef KH_DEBUG
ss = " .. redone\n";
::OutputDebugString( ss.
asChar() );
#endif
return stat;
}
cgfxShaderCmd::undoIt()
{
#ifdef KH_DEBUG
ss += fArgString;
ss += "\n";
::OutputDebugString( ss.
asChar() );
#endif
try
{
stat = undoCmd();
}
catch ( cgfxShaderCommon::InternalError* e )
{
reportInternalError( __FILE__, (size_t)e );
stat = MS::kFailure;
}
catch ( ... )
{
reportInternalError( __FILE__, __LINE__ );
stat = MS::kFailure;
}
#ifdef KH_DEBUG
ss = " .. undone\n";
::OutputDebugString( ss.
asChar() );
#endif
return stat;
}
cgfxShaderCmd::doCmd(
const MArgList& args)
{
#if defined(_WIN32) && defined(CGFX_DEBUG_MEMORY)
if (tmpFlag == -1)
{
tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF;
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag( tmpFlag );
}
#endif
status = parseArgs(args, selList);
if (!status)
{
return status;
}
if ( fPluginPath )
{
setResult( sPluginPath );
return MS::kSuccess;
}
if ( fListProfiles )
{
setResult( cgfxProfile::getProfileList() );
return status;
}
if ( fMaxTexCoords )
{
GLint mtc = 0;
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
{
glGetIntegerv( GL_MAX_TEXTURE_COORDS_ARB, &mtc );
GLint mic = 0;
glGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &mic );
if (mic < mtc)
mtc = mic;
if ( mtc < 1 )
mtc = 1;
else if ( mtc > CGFXSHADERNODE_GL_TEXTURE_MAX )
mtc = CGFXSHADERNODE_GL_TEXTURE_MAX;
}
_OPENMAYA_POP_WARNING
setResult( (int)mtc );
return MS::kSuccess;
}
cgfxShaderNode* pNode = NULL;
if ( fIsEdit || fIsQuery )
{
{
status = MS::kNotFound;
return status;
}
fNodeName = tmpList[0];
if ( fNodeName.length() )
{
sWho += " \"";
sWho += fNodeName;
sWho += "\"";
}
if (!status)
{
return status;
}
if (!status)
{
sFeedback = sWho;
sFeedback += " is not a cgfxShader node.";
return status;
}
if (fnNode.
typeId() != cgfxShaderNode::sId)
{
status = MS::kInvalidParameter;
sFeedback = sWho;
sFeedback += " is not a cgfxShader node.";
return status;
}
pNode = (cgfxShaderNode*)fnNode.
userNode();
if (!pNode)
{
status = MS::kInvalidParameter;
sFeedback = sWho;
sFeedback += " is not cgfxShader node.";
return status;
}
}
if ( fIsQuery ) {
if ( fFxFile )
{
MString path = pNode->shaderFxFile();
setResult( path );
return MS::kSuccess;
}
if ( fFxPath )
{
MString path = cgfxFindFile(pNode->shaderFxFile());
setResult( path );
return MS::kSuccess;
}
if ( fTechnique )
{
MString path = pNode->getTechnique();
setResult( path );
return MS::kSuccess;
}
if ( fProfile )
{
MString path = pNode->getProfile();
setResult( path );
return MS::kSuccess;
}
if ( fListTechniques )
{
setResult( pNode->getTechniqueList() );
return status;
}
if ( fListParameters )
{
cgfxRCPtr<cgfxAttrDefList> list = cgfxAttrDef::attrsFromNode( oNode );
for ( cgfxAttrDefList::iterator it = list; it; ++it )
{
cgfxAttrDef* aDef = *it;
if ( fDescription )
{
sResult = aDef->fName.
length() ? aDef->fName :
" ";
sResult += "\t";
sTemp = aDef->typeName();
sResult += sTemp.
length() ? sTemp :
" ";
sResult += "\t";
sResult += aDef->fSemantic.
length() ? aDef->fSemantic :
" ";
sResult += "\t";
sResult += aDef->fDescription.
length() ? aDef->fDescription :
" ";
sResult += "\t";
const char* suffix = aDef->getExtraAttrSuffix();
sResult += suffix ? suffix : " ";
}
else
sResult = aDef->fName;
}
setResult( saResult );
return status;
}
if ( fParameterName.length() > 0 )
{
cgfxRCPtr<cgfxAttrDefList> list = cgfxAttrDef::attrsFromNode( oNode );
cgfxAttrDefList::iterator it;
if ( fCaseInsensitive )
it = list->findInsensitive( fParameterName );
else
it = list->find( fParameterName );
if ( fDescription )
{
if ( it )
{
cgfxAttrDef* aDef = *it;
saResult.
append( aDef->fName );
saResult.
append( aDef->typeName() );
saResult.
append( aDef->fSemantic );
saResult.
append( aDef->fDescription );
const char* suffix = aDef->getExtraAttrSuffix();
saResult.
append( suffix ? suffix :
"" );
}
setResult( saResult );
}
else
{
if ( it )
sResult = (*it)->typeName();
setResult( sResult );
}
return status;
}
if ( fEmptyUV )
{
setResult( pNode->getEmptyUVSets() );
return MS::kSuccess;
}
if ( fEmptyUVShapes )
{
const MObjectArray& oaShapes = pNode->getEmptyUVSetShapes();
for (
unsigned iShape = 0; iShape < oaShapes.
length(); ++iShape )
{
}
setResult( saResult );
return MS::kSuccess;
}
if ( fTexCoordSource )
{
setResult( pNode->getTexCoordSource() );
return MS::kSuccess;
}
#if MAYA_API_VERSION >= 700
if ( fColorSource )
{
setResult( pNode->getColorSource() );
return MS::kSuccess;
}
#endif
return MS::kInvalidParameter;
}
if (!fFxFile && pNode)
fNewFxFile = pNode->shaderFxFile();
if (!fTechnique && pNode)
fNewTechnique = pNode->getTechnique();
if (!fProfile && pNode)
fNewProfile = pNode->getProfile();
if (fFxFile)
{
MString file = cgfxFindFile(fNewFxFile);
MString projectFile = cgfxFindFile(fNewFxFile,
true);
fNewEffect = cgfxEffect::loadEffect(file, cgfxProfile::getProfile(fNewProfile));
if (fNewEffect->isValid())
{
if ( !status ) return status;
fNewFxFile = projectFile;
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
{
MString es =
"There is no active view to bind " + sWho +
" to.";
return MS::kSuccess;
}
_OPENMAYA_POP_WARNING
}
if (fNewEffect->isValid())
{
sFeedback = sWho;
sFeedback += " loaded effect \"";
sFeedback += file;
sFeedback += "\"";
}
else
{
sFeedback = sWho;
sFeedback += " unable to load effect \"";
sFeedback += file.
length() ? file : fNewFxFile;
sFeedback += "\"";
return MS::kFailure;
}
}
if ( !fIsEdit )
{
oNode = fDagMod->createNode(cgfxShaderNode::sId, &status);
M_CHECK( status );
if ( fNodeName.length() > 0 )
{
status = fDagMod->renameNode(oNode, fNodeName);
M_CHECK( status );
}
M_CHECK( status && fnNode.
typeId() == cgfxShaderNode::sId );
pNode = (cgfxShaderNode*)fnNode.
userNode();
M_CHECK( pNode );
M_CHECK( status );
}
if (fFxFile) {
fOldFxFile = pNode->shaderFxFile();
fOldEffect = pNode->effect();
cgfxShaderNode::NodeList nodes;
getNodesToUpdate(fOldEffect, pNode, nodes);
cgfxShaderNode::NodeList::const_iterator it = nodes.begin();
cgfxShaderNode::NodeList::const_iterator itEnd = nodes.end();
for(; it != itEnd; ++it)
{
cgfxShaderNode* node = *it;
cgfxRCPtr<cgfxAttrDefList> &oldAttrDefList = fOldAttrDefList[node];
cgfxRCPtr<cgfxAttrDefList> &newAttrDefList = fNewAttrDefList[node];
node->getAttributeList( oldAttributeList );
oldAttrDefList = node->attrDefList();
cgfxAttrDef::updateNode( fNewEffect,
node,
fDagMod,
newAttrDefList,
newAttributeList );
}
}
status = fNodeSelection.add( oNode );
M_CHECK( status );
fOldTechnique = pNode->getTechnique();
fOldProfile = pNode->getProfile();
return redoCmd( oNode, fnNode, pNode );
}
cgfxShaderCmd::redoCmd(
MObject& oNode,
cgfxShaderNode* pNode )
{
if (!fOldAttrDefList.empty()) {
NodeAttrDefList::iterator it = fOldAttrDefList.begin();
NodeAttrDefList::iterator itEnd = fOldAttrDefList.end();
for(; it != itEnd; ++it)
{
cgfxRCPtr<cgfxAttrDefList> &attrDefList = it->second;
if(!attrDefList.isNull())
attrDefList->releaseTextures();
}
}
if (fFxFile) {
pNode->setAttrDefList( cgfxRCPtr<cgfxAttrDefList>() );
cgfxRCPtr<cgfxAttrDefList> currNodeAttrDefList;
status = fDagMod->doIt();
M_CHECK( status );
cgfxShaderNode::NodeList nodes;
getNodesToUpdate(fOldEffect, pNode, nodes);
cgfxShaderNode::NodeList::const_iterator it = nodes.begin();
cgfxShaderNode::NodeList::const_iterator itEnd = nodes.end();
for(; it != itEnd; ++it)
{
cgfxShaderNode* node = *it;
cgfxRCPtr<cgfxAttrDefList> &attrDefList = fNewAttrDefList[node];
if(node == pNode)
currNodeAttrDefList = attrDefList;
node->setAttributeList(attributeList);
node->setAttrDefList(attrDefList);
node->setShaderFxFileChanged(true);
node->setEffect(fNewEffect);
}
cgfxAttrDef::initializeAttributes( oNode, currNodeAttrDefList, false, fDagMod);
}
else {
status = fDagMod->doIt();
M_CHECK( status );
}
if (fTechnique) {
}
if (fProfile) {
}
if ( !fIsEdit )
{
fNodeName = fnNode.
name();
}
return MS::kSuccess;
}
cgfxShaderCmd::undoCmd()
{
status = fNodeSelection.getDependNode(0, oNode);
M_CHECK( status );
M_CHECK( status && fnNode.
typeId() == cgfxShaderNode::sId );
cgfxShaderNode* pNode = (cgfxShaderNode*)fnNode.
userNode();
M_CHECK( pNode );
if (!fNewAttrDefList.empty()) {
NodeAttrDefList::iterator it = fNewAttrDefList.begin();
NodeAttrDefList::iterator itEnd = fNewAttrDefList.end();
for(; it != itEnd; ++it)
{
cgfxRCPtr<cgfxAttrDefList> &attrDefList = it->second;
if(!attrDefList.isNull())
attrDefList->releaseTextures();
}
}
if (fFxFile) {
pNode->setAttrDefList( cgfxRCPtr<cgfxAttrDefList>() );
}
status = fDagMod->undoIt();
M_CHECK( status );
if ( fIsEdit )
{
if (fFxFile) {
cgfxRCPtr<cgfxAttrDefList> currNodeAttrDefList;
cgfxShaderNode::NodeList nodes;
getNodesToUpdate(fNewEffect, pNode, nodes);
cgfxShaderNode::NodeList::const_iterator it = nodes.begin();
cgfxShaderNode::NodeList::const_iterator itEnd = nodes.end();
for(; it != itEnd; ++it)
{
cgfxShaderNode* node = *it;
cgfxRCPtr<cgfxAttrDefList> &attrDefList = fOldAttrDefList[node];
if(node == pNode)
currNodeAttrDefList = attrDefList;
node->setAttributeList(attributeList);
node->setAttrDefList(attrDefList);
node->setShaderFxFileChanged(true);
node->setEffect(fOldEffect);
}
cgfxAttrDef::initializeAttributes( oNode, currNodeAttrDefList, true, fDagMod);
}
if (fTechnique) {
}
if (fProfile) {
}
}
else
{
}
return MS::kSuccess;
}
{
syntax.
addFlag( kPluginPathFlag, kPluginPathFlagLong );
syntax.
addFlag( kMaxTexCoordsFlag, kMaxTexCoordsFlagLong );
syntax.
addFlag( kListTechniquesFlag, kListTechniquesFlagLong );
syntax.
addFlag( kListProfilesFlag, kListProfilesFlagLong );
syntax.
addFlag(kListParametersFlag, kListParametersFlagLong);
syntax.
addFlag( kEmptyUVFlag, kEmptyUVFlagLong );
syntax.
addFlag( kEmptyUVShapesFlag, kEmptyUVShapesFlagLong );
syntax.
addFlag( kTexCoordSourceFlag, kTexCoordSourceFlagLong );
#if MAYA_API_VERSION >= 700
syntax.
addFlag( kColorSourceFlag, kColorSourceFlagLong );
#endif
syntax.
addFlag( kCaseInsensitiveFlag, kCaseInsensitiveFlagLong );
syntax.
addFlag( kDescriptionFlag, kDescriptionFlagLong );
return syntax;
}
void* cgfxShaderCmd::creator()
{
return new cgfxShaderCmd();
}
cgfxShaderCmd::cgfxShaderCmd()
: fIsEdit( false )
, fIsQuery( false )
, fMaxTexCoords( false )
, fFxFile( false )
, fFxPath( false )
, fTechnique( false )
, fProfile( false )
, fPluginPath( false )
, fEmptyUV( false )
, fEmptyUVShapes( false )
, fListParameters(false)
, fListTechniques( false )
, fListProfiles( false )
, fTexCoordSource( false )
#if MAYA_API_VERSION >= 700
, fColorSource( false )
#endif
, fCaseInsensitive( false )
, fDescription( false )
, fOldEffect(0)
, fNewEffect(0)
, fDagMod(0)
{ }
cgfxShaderCmd::~cgfxShaderCmd()
{
try
{
#ifdef KH_DEBUG
if ( !fIsQuery )
{
ss += fArgString;
ss += "\n";
::OutputDebugString( ss.
asChar() );
}
#endif
fNewAttrDefList.clear();
delete fDagMod;
}
catch ( cgfxShaderCommon::InternalError* e )
{
reportInternalError( __FILE__, (size_t)e );
}
catch ( ... )
{
reportInternalError( __FILE__, __LINE__ );
}
}
bool cgfxShaderCmd::isUndoable() const
{
return !fIsQuery;
}
{
for (
unsigned iArg = 0; iArg < args.
length(); ++iArg )
{
if ( iArg > 0 )
fArgString += " ";
}
#ifdef KH_DEBUG
ss += fArgString;
ss += "\n";
::OutputDebugString( ss.
asChar() );
#endif
if ( !status )
return status;
bool bCgfxShaderNodeRequired = true;
fIsEdit = argData.isEdit();
fIsQuery = argData.isQuery();
if ( argData.isFlagSet( kMaxTexCoordsFlag ) )
{
bCgfxShaderNodeRequired = false;
fMaxTexCoords = true;
fIsQuery = true;
}
if ( argData.isFlagSet( kPluginPathFlag ) )
{
bCgfxShaderNodeRequired = false;
fPluginPath = true;
fIsQuery = true;
}
if ( argData.isFlagSet( kEmptyUVFlag ) )
{
fEmptyUV = true;
fIsQuery = true;
}
if ( argData.isFlagSet( kEmptyUVShapesFlag ) )
{
fEmptyUVShapes = true;
fIsQuery = true;
}
if ( argData.isFlagSet( kTexCoordSourceFlag ) )
{
fTexCoordSource = true;
fIsQuery = true;
}
#if MAYA_API_VERSION >= 700
if ( argData.isFlagSet( kColorSourceFlag ) )
{
fColorSource = true;
fIsQuery = true;
}
#endif
if (argData.isFlagSet(kFxFlag))
{
fFxFile = true;
if (!fIsQuery) {
argData.getFlagArgument(kFxFlag, 0, fNewFxFile);
}
}
if (argData.isFlagSet(kFxPathFlag))
{
fFxPath = true;
fIsQuery = true;
}
if (argData.isFlagSet(kFxTechniqueFlag))
{
fTechnique = true;
if (!fIsQuery) {
argData.getFlagArgument( kFxTechniqueFlag, 0, fNewTechnique );
}
}
if (argData.isFlagSet(kFxProfileFlag))
{
fProfile = true;
if (!fIsQuery) {
argData.getFlagArgument( kFxProfileFlag, 0, fNewProfile );
}
}
if (argData.isFlagSet(kNameFlag))
{
argData.getFlagArgument(kNameFlag, 0, fNodeName);
}
if (argData.isFlagSet(kListParametersFlag))
{
fListParameters = true;
fIsQuery = true;
}
if ( argData.isFlagSet( kListTechniquesFlag ) )
{
fListTechniques = true;
fIsQuery = true;
}
if ( argData.isFlagSet( kListProfilesFlag ) )
{
bCgfxShaderNodeRequired = false;
fListProfiles = true;
fIsQuery = true;
}
if (argData.isFlagSet(kParameterFlag))
{
argData.getFlagArgument(kParameterFlag, 0, fParameterName);
fIsQuery = true;
}
if ( argData.isFlagSet( kCaseInsensitiveFlag ) )
{
fCaseInsensitive = true;
fIsQuery = true;
}
if ( argData.isFlagSet( kDescriptionFlag ) )
{
fDescription = true;
fIsQuery = true;
}
if ( fIsQuery &&
fIsEdit )
{
MString es =
"cgfxShader: invalid use of -e/-edit flag";
return MS::kInvalidParameter;
}
if ( bCgfxShaderNodeRequired )
{
argData.getObjects(selList);
{
sMsg = "Exactly one node must be specified or selected for command: cgfxShader ";
sMsg += fArgString;
status = MS::kInvalidParameter;
}
}
return status;
}
void cgfxShaderCmd::getNodesToUpdate(const cgfxRCPtr<const cgfxEffect>& effect, cgfxShaderNode* currNode, cgfxShaderNode::NodeList& nodes) const
{
bool isReload = (fNewFxFile == fOldFxFile);
if(isReload)
{
cgfxShaderNode::getNodesUsingEffect(effect, nodes);
}
else
{
nodes.insert(currNode);
}
}
void
cgfxShaderCmd::reportInternalError( const char* sFile, size_t errcode )
{
MString es =
"cgfxShader internal error ";
es += (int)errcode;
if (fArgString.length() > 0)
{
es += " with args: ";
es += fArgString;
}
#ifdef _WINDOWS
::OutputDebugString( es.
asChar() );
::OutputDebugString( "\n" );
#endif
}