//- // ========================================================================== // Copyright (C) 1995 - 2005 Alias Systems Corp. and/or its licensors. All // rights reserved. // // The coded instructions, statements, computer programs, and/or related // material (collectively the "Data") in these files are provided by Alias // Systems Corp. ("Alias") and/or its licensors for the exclusive use of the // Customer (as defined in the Alias Software License Agreement that // accompanies this Alias software). Such Customer has the right to use, // modify, and incorporate the Data into other products and to distribute such // products for use by end-users. // // THE DATA IS PROVIDED "AS IS". ALIAS HEREBY DISCLAIMS ALL WARRANTIES // RELATING TO THE DATA, INCLUDING, WITHOUT LIMITATION, ANY AND ALL EXPRESS OR // IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. IN NO EVENT SHALL ALIAS BE LIABLE FOR ANY DAMAGES // WHATSOEVER, WHETHER DIRECT, INDIRECT, SPECIAL, OR PUNITIVE, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, OR IN EQUITY, // ARISING OUT OF ACCESS TO, USE OF, OR RELIANCE UPON THE DATA. // ========================================================================== //+ #include #define OPENMAYA_EXPORT #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Static pointer to the current refreshCompute per panel so we can delete // it if the plug-in is unloaded. // class refreshCompute; static refreshCompute* currentRefreshCompute[4] = { 0, 0, 0, 0 }; // Possible buffer operations supported enum MbufferOperation { kInvertColorBuffer, kDrawDepthBuffer }; /////////////////////////////////////////////////// // // Command class declaration // /////////////////////////////////////////////////// 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 ); // Name of panel to monitor MString mPanelName; MbufferOperation mBufferOperation; }; /////////////////////////////////////////////////// // // Refresh computation class implementation // /////////////////////////////////////////////////// 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(MString& panelName, void * data); static void preRenderCB(MString& panelName, void * data); static void postRenderCB(MString& panelName, void * data); MCallbackId mDeleteId; MCallbackId mPreRenderId; MCallbackId mPostRenderId; MString mPanelName; MbufferOperation mBufferOperation; }; /////////////////////////////////////////////////// // // Command class implementation // /////////////////////////////////////////////////// // Constructor // viewCallbackTest::viewCallbackTest() { mPanelName = MString(""); mBufferOperation = kInvertColorBuffer; } // Destructor // viewCallbackTest::~viewCallbackTest() { // Do nothing } // creator // void* viewCallbackTest::creator() { return (void *) (new viewCallbackTest); } // newSyntax // // Buffer operation = -bo/-bufferOperation = (invert | showDepth) 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); // Name of model panel to monitor // syntax.addArg(MSyntax::kString); return syntax; } // parseArgs // MStatus viewCallbackTest::parseArgs(const MArgList& args) { MStatus status; MArgDatabase argData(syntax(), args); // Buffer operation argument variables 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."); } } // Read off the panel name status = argData.getCommandArgument(0, mPanelName); if (!status) { status.perror("No panel name specified as command argument"); return status; } return MS::kSuccess; } // doIt // MStatus viewCallbackTest::doIt(const MArgList& args) { MStatus status; status = parseArgs(args); if (!status) { return status; } try { // Only allow one computation per panel at this time. refreshCompute *foundComputePtr = 0; for (unsigned int i=0; i<4; i++) { if (currentRefreshCompute[i] && (currentRefreshCompute[i])->panelName() == mPanelName) { foundComputePtr = currentRefreshCompute[i]; } } // If alread exists, just change the operator if it differs. if (foundComputePtr) { foundComputePtr->setBufferOperation( kInvertColorBuffer ); } else { for (unsigned int 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 implementation // /////////////////////////////////////////////////// refreshCompute::refreshCompute(const MString &panelName, MbufferOperation postBufferOperation) { MStatus status; // Set panel name and operator for post rendering mPanelName = panelName; mBufferOperation = postBufferOperation; // Add the callbacks // 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); } // Clear all callbacks for this compute void refreshCompute::clearCallbacks() { if (mDeleteId) MMessage::removeCallback(mDeleteId); if (mPreRenderId) MMessage::removeCallback(mPreRenderId); if (mPostRenderId) MMessage::removeCallback(mPostRenderId); } refreshCompute::~refreshCompute() { clearCallbacks(); // Reset any global pointer pointing to this compute for (unsigned int i=0; i<4; i++) { if (currentRefreshCompute[i] && (currentRefreshCompute[i])->panelName() == mPanelName) { currentRefreshCompute[i] = 0; } } } // Delete callback // void refreshCompute::deleteCB(MString& panelName, void * data) { refreshCompute *pf = (refreshCompute *) data; printf("In delete view callback for view %s. Remove all callbacks.\n", panelName.asChar()); // Delete callback. delete pf; } // Pre-render callback // void refreshCompute::preRenderCB(MString& panelName, void * data) { refreshCompute *thisCompute = (refreshCompute *) data; if (!thisCompute) return; if (thisCompute->mBufferOperation != kDrawDepthBuffer) { M3dView view; MStatus status = M3dView::getM3dViewFromModelPanel(panelName, view); MPoint origin; status = view.drawText( MString("Pre render callback: ") + panelName, origin ); } } // Post-render callback // void refreshCompute::postRenderCB(MString& panelName, void * data) { refreshCompute *thisCompute = (refreshCompute *) data; if (!thisCompute) return; // Get the view if any for the panel M3dView view; MStatus status = M3dView::getM3dViewFromModelPanel(panelName, view); if (status != MS::kSuccess) return; if (thisCompute->mBufferOperation == kDrawDepthBuffer) { 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 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; } // Read into a float buffer status = view.readDepthMap( 0,0, width, height, (unsigned char *)depthPixels, M3dView::kDepth_Float ); if (status != MS::kSuccess) { delete depthPixels; delete colorPixels; return; } // Find depth range and remap normalized depth range into 0...255 // for color. float *dPtr = depthPixels; unsigned int i = 0; float zmin=1.0f; float zmax=0.0f; for(i=0; i zmax) { zmax = *dPtr; } dPtr++; } float zrange = zmax - zmin; unsigned char *cPtr = colorPixels; dPtr = depthPixels; for(i=0; i < numPixels; i++) { unsigned char depth = ( 255 - (unsigned char)(255.0f * (( (*dPtr)-zmin) / zrange) + zmin ) ); *cPtr = depth; cPtr++; *cPtr = depth; cPtr++; *cPtr = depth; cPtr++; *cPtr = '\255'; cPtr++; dPtr++; } MImage image; image.setPixels( colorPixels, width, height ); // Uncomment next line to test writing buffer to file. //image.writeToFile( "C:\\temp\\dumpDepth.iff" ); // Write all pixels back. The origin of the image (lower left) // is used status = view.writeColorBuffer( image, 0, 0 ); if (depthPixels) delete depthPixels; if (colorPixels) delete colorPixels; } // Do a simple color invert operation on all pixels // else if (thisCompute->mBufferOperation == kInvertColorBuffer) { // Read the RGB values from the color buffer MImage image; status = view.readColorBuffer( image ); if (status != MS::kSuccess) return; unsigned char *pixelPtr = (unsigned char*)image.pixels(); if (pixelPtr) { unsigned int width, height; image.getSize( width, height ); unsigned int numPixels = width * height; for (unsigned int i=0; i < numPixels; i++) { *pixelPtr = (255 - *pixelPtr); pixelPtr++; *pixelPtr = (255 - *pixelPtr); pixelPtr++; *pixelPtr = (255 - *pixelPtr); pixelPtr++; *pixelPtr = 255; pixelPtr++; } } // Write all pixels back. The origin of the image (lower left) // is used status = view.writeColorBuffer( image, 0, 0 ); } } /////////////////////////////////////////////////// // // Plug-in functions // /////////////////////////////////////////////////// MStatus initializePlugin( MObject obj ) { MStatus status; MFnPlugin plugin( obj, "Alias", "6.5", "Any"); // Register the command so we can actually do some work // status = plugin.registerCommand("viewCallbackTest", viewCallbackTest::creator, viewCallbackTest::newSyntax); if (!status) { status.perror("registerCommand"); } return status; } MStatus uninitializePlugin( MObject obj) { MStatus status; MFnPlugin plugin( obj ); // Remove all computation class + callbacks for (unsigned int i=0; i<4; i++) { delete currentRefreshCompute[i]; currentRefreshCompute[i] = 0; } // Deregister the command // status = plugin.deregisterCommand("viewCallbackTest"); if (!status) { status.perror("deregisterCommand"); } return status; }