#include <stdio.h>
#define OPENMAYA_EXPORT
#include <maya/MIOStream.h>
#include <maya/MGlobal.h>
#include <maya/MString.h>
#include <maya/MStringArray.h>
#include <maya/MEventMessage.h>
#include <maya/MUiMessage.h>
#include <maya/MFnPlugin.h>
#include <maya/MPxCommand.h>
#include <maya/MSyntax.h>
#include <maya/MArgDatabase.h>
#include <maya/MArgList.h>
#include <maya/M3dView.h>
#include <maya/MPoint.h>
#include <maya/MImage.h>
#include <stdio.h>
class refreshCompute;
static refreshCompute* currentRefreshCompute[4] = { 0, 0, 0, 0 };
enum MbufferOperation {
kInvertColorBuffer,
kDrawDepthBuffer
};
class viewCallbackTest : public MPxCommand
{
public:
viewCallbackTest();
virtual ~viewCallbackTest();
MStatus doIt( const MArgList& args );
static MSyntax newSyntax();
static void* creator();
private:
MStatus parseArgs( const MArgList& args );
MString mPanelName;
MbufferOperation mBufferOperation;
};
class refreshCompute
{
public:
refreshCompute(const MString &panelName, MbufferOperation bufferOperation);
~refreshCompute();
const MString &panelName() const { return mPanelName; }
void setPanelName(const MString &panelName) { mPanelName = panelName; }
MbufferOperation bufferOperation() const { return mBufferOperation; }
void setBufferOperation(const MbufferOperation operation) { mBufferOperation = operation; }
void clearCallbacks();
protected:
static void deleteCB(const MString& panelName, void * data);
static void preRenderCB(const MString& panelName, void * data);
static void postRenderCB(const MString& panelName, void * data);
MCallbackId mDeleteId;
MCallbackId mPreRenderId;
MCallbackId mPostRenderId;
MString mPanelName;
MbufferOperation mBufferOperation;
};
viewCallbackTest::viewCallbackTest()
{
mPanelName = MString("");
mBufferOperation = kInvertColorBuffer;
}
viewCallbackTest::~viewCallbackTest()
{
}
void* viewCallbackTest::creator()
{
return (void *) (new viewCallbackTest);
}
const char *bufferOperationShortName = "-bo";
const char *bufferOperationLongName = "-bufferOperation";
#define _NUMBER_BUFFER_OPERATIONS_ 2
const MString bufferOperationStrings[_NUMBER_BUFFER_OPERATIONS_ ] =
{ MString("invert"), MString("showDepth") };
const MbufferOperation bufferOperations[_NUMBER_BUFFER_OPERATIONS_] =
{ kInvertColorBuffer, kDrawDepthBuffer };
MSyntax viewCallbackTest::newSyntax()
{
MSyntax syntax;
syntax.addFlag(bufferOperationShortName, bufferOperationLongName, MSyntax::kString);
syntax.addArg(MSyntax::kString);
return syntax;
}
MStatus viewCallbackTest::parseArgs(const MArgList& args)
{
MStatus status;
MArgDatabase argData(syntax(), args);
mBufferOperation = kInvertColorBuffer;
MString operationString;
MString arg;
for ( unsigned int i = 0; i < args.length(); i++ )
{
arg = args.asString( i, &status );
if (!status)
continue;
if ( arg == MString(bufferOperationShortName) || arg == MString(bufferOperationLongName) )
{
if (i == args.length()-1) {
arg += ": must specify a buffer operation.";
displayError(arg);
return MS::kFailure;
}
i++;
args.get(i, operationString );
bool validOperation = false;
for (unsigned int k=0; k<_NUMBER_BUFFER_OPERATIONS_; k++)
{
if (bufferOperationStrings[i] == operationString)
{
mBufferOperation = bufferOperations[k];
validOperation = true;
}
}
if (!validOperation)
status.perror("Invalid operation specified. Using invert by default.");
}
}
status = argData.getCommandArgument(0, mPanelName);
if (!status)
{
status.perror("No panel name specified as command argument");
return status;
}
return MS::kSuccess;
}
MStatus viewCallbackTest::doIt(const MArgList& args)
{
MStatus status;
status = parseArgs(args);
if (!status)
{
return status;
}
try
{
refreshCompute *foundComputePtr = 0;
unsigned int i;
for (i=0; i<4; i++)
{
if (currentRefreshCompute[i] &&
(currentRefreshCompute[i])->panelName() == mPanelName)
{
foundComputePtr = currentRefreshCompute[i];
}
}
if (foundComputePtr)
{
foundComputePtr->setBufferOperation( mBufferOperation);
}
else
{
for (i=0; i<4; i++)
{
if (!currentRefreshCompute[i])
{
currentRefreshCompute[i] = new refreshCompute(mPanelName, mBufferOperation);
break;
}
}
}
}
catch(MStatus status)
{
return status;
}
catch(...)
{
throw;
}
return status;
}
refreshCompute::refreshCompute(const MString &panelName,
MbufferOperation postBufferOperation)
{
MStatus status;
mPanelName = panelName;
mBufferOperation = postBufferOperation;
mDeleteId
= MUiMessage::add3dViewDestroyMsgCallback(panelName,
&refreshCompute::deleteCB,
(void *) this, &status);
if (mDeleteId == 0)
status.perror(MString("Could not attach view deletion callback to panel ") +
panelName);
mPreRenderId
= MUiMessage::add3dViewPreRenderMsgCallback(panelName,
&refreshCompute::preRenderCB,
(void *) this, &status);
if (mPreRenderId == 0)
status.perror(MString("Could not attach view prerender callback to panel ") +
panelName);
mPostRenderId
= MUiMessage::add3dViewPostRenderMsgCallback(panelName,
&refreshCompute::postRenderCB,
(void *) this, &status);
if (mPostRenderId == 0)
status.perror(MString("Could not attach view postrender callback to panel ") +
panelName);
}
void refreshCompute::clearCallbacks()
{
if (mDeleteId)
MMessage::removeCallback(mDeleteId);
if (mPreRenderId)
MMessage::removeCallback(mPreRenderId);
if (mPostRenderId)
MMessage::removeCallback(mPostRenderId);
}
refreshCompute::~refreshCompute()
{
clearCallbacks();
for (unsigned int i=0; i<4; i++)
{
if (currentRefreshCompute[i] &&
(currentRefreshCompute[i])->panelName() == mPanelName)
{
currentRefreshCompute[i] = 0;
}
}
}
void refreshCompute::deleteCB(const MString& panelName, void * data)
{
refreshCompute *pf = (refreshCompute *) data;
cout<<"In delete view callback for view "<<panelName.asChar()
<<". Remove all callbacks."<<endl;
delete pf;
}
void refreshCompute::preRenderCB(const MString& panelName, void * data)
{
refreshCompute *thisCompute = (refreshCompute *) data;
if (!thisCompute)
return;
M3dView view;
MStatus status = M3dView::getM3dViewFromModelPanel(panelName, view);
if (status != MS::kSuccess)
return;
int width = 0, height = 0;
width = view.portWidth( &status );
if (status != MS::kSuccess || (width < 2))
return;
height = view.portHeight( &status );
if (status != MS::kSuccess || (height < 2))
return;
unsigned int vx,vy,vwidth,vheight;
vx = 0;
vy = 0;
vwidth = width / 2;
vheight = height / 2;
status = view.pushViewport (vx, vy, vwidth, vheight);
if (thisCompute->mBufferOperation != kDrawDepthBuffer)
{
M3dView view;
MStatus status = M3dView::getM3dViewFromModelPanel(panelName, view);
MPoint origin;
status = view.drawText( MString("Pre render callback: ") + panelName, origin );
}
}
void refreshCompute::postRenderCB(const MString& panelName, void * data)
{
refreshCompute *thisCompute = (refreshCompute *) data;
if (!thisCompute)
return;
M3dView view;
MStatus status = M3dView::getM3dViewFromModelPanel(panelName, view);
if (status != MS::kSuccess)
return;
view.popViewport();
if (thisCompute->mBufferOperation == kDrawDepthBuffer)
{
int width = 0, height = 0;
width = view.portWidth( &status ) / 2 ;
if (status != MS::kSuccess || (width < 2))
return;
height = view.portHeight( &status ) / 2 ;
if (status != MS::kSuccess || (height < 2))
return;
unsigned int numPixels = width * height;
float *depthPixels = new float[numPixels];
if (!depthPixels)
return;
unsigned char *colorPixels = new unsigned char[numPixels * 4];
if (!colorPixels)
{
delete depthPixels;
delete colorPixels;
}
status = view.readDepthMap( 0,0, width, height, (unsigned char *)depthPixels, M3dView::kDepth_Float );
if (status != MS::kSuccess)
{
delete depthPixels;
delete colorPixels;
return;
}
float *dPtr = depthPixels;
unsigned int i = 0;
float zmin = 100.0f;
float zmax = -100.0f;
for(i=0; i<numPixels; i++)
{
float val = *dPtr;
if(val < zmin) {
zmin = *dPtr;
}
if(val > zmax) {
zmax = *dPtr;
}
dPtr++;
}
float zrange = zmax - zmin;
unsigned char *cPtr = colorPixels;
dPtr = depthPixels;
for(i=0; i < numPixels; i++)
{
float val = *dPtr;
unsigned char depth = (unsigned char)(255.0f * (( (val)-zmin) / zrange) );
*cPtr = depth; cPtr++;
*cPtr = depth; cPtr++;
*cPtr = depth; cPtr++;
*cPtr = 0xff;
cPtr++;
dPtr++;
}
MImage image;
image.setPixels( colorPixels, width, height );
status = view.writeColorBuffer( image, 5, 5 );
if (depthPixels)
delete depthPixels;
if (colorPixels)
delete colorPixels;
}
else if (thisCompute->mBufferOperation == kInvertColorBuffer)
{
bool readAsRGBA = true;
MImage image;
status = view.readColorBuffer( image, readAsRGBA );
if (status != MS::kSuccess)
return;
status = view.writeColorBuffer( image, 5, 5 );
unsigned char *pixelPtr = (unsigned char*)image.pixels();
if (pixelPtr)
{
unsigned int width, height;
image.getSize( width, height );
MImage image2;
image2.create( width, height );
unsigned char *pixelPtr2 = (unsigned char*)image2.pixels();
unsigned int numPixels = width * height;
for (unsigned int i=0; i < numPixels; i++)
{
*pixelPtr2 = (255 - *pixelPtr);
pixelPtr2++; pixelPtr++;
*pixelPtr2 = (255 - *pixelPtr);
pixelPtr2++; pixelPtr++;
*pixelPtr2 = (255 - *pixelPtr);
pixelPtr2++; pixelPtr++;
*pixelPtr2 = 255;
pixelPtr2++; pixelPtr++;
}
status = view.writeColorBuffer( image2, 5, short(5+height/2) );
}
}
}
MStatus initializePlugin( MObject obj )
{
MStatus status;
MFnPlugin plugin( obj, PLUGIN_COMPANY, "6.5", "Any");
status = plugin.registerCommand("viewCallbackTest",
viewCallbackTest::creator,
viewCallbackTest::newSyntax);
if (!status)
{
status.perror("registerCommand");
}
return status;
}
MStatus uninitializePlugin( MObject obj)
{
MStatus status;
MFnPlugin plugin( obj );
for (unsigned int i=0; i<4; i++)
{
delete currentRefreshCompute[i];
currentRefreshCompute[i] = 0;
}
status = plugin.deregisterCommand("viewCallbackTest");
if (!status)
{
status.perror("deregisterCommand");
}
return status;
}