#include <QtCore/QObject>
#include <QtWidgets/QApplication>
#include <QtCore/QEvent>
#include <maya/MFnPlugin.h>
#include <maya/MIOStream.h>
#include <maya/MStatus.h>
#include <maya/MEvent.h>
#include <maya/MGlobal.h>
#include <maya/MItSelectionList.h>
#include <maya/MFnSingleIndexedComponent.h>
#include <maya/MDagPath.h>
#include <maya/MFn.h>
#include <maya/MFnMesh.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MMatrix.h>
#include <maya/MIntArray.h>
#include <maya/MFloatArray.h>
#include <maya/MUintArray.h>
#include <maya/MToolsInfo.h>
#include <maya/MUIDrawManager.h>
#include <maya/MFrameContext.h>
#include <maya/MColor.h>
#include <maya/MPxTexContext.h>
#include <maya/MPxContextCommand.h>
#include <maya/MPxPolyTweakUVInteractiveCommand.h>
{
public:
static void *creator() { return new UVUpdateCommand; };
};
struct BrushConfig
{
BrushConfig() : fSize(50.0f) {};
float size() const { return fSize; }
void setSize( float size ) { fSize = size; }
private:
float fSize;
};
{
public:
grabUVContext();
virtual ~grabUVContext() {} ;
bool doKeyPress( QKeyEvent* event );
bool doKeyRelease( QKeyEvent* event );
virtual bool eventFilter(QObject *object, QEvent *event);
float size() const;
void setSize( float size );
private:
enum DragMode
{
kNormal,
kBrushSize
};
BrushConfig fBrushConfig;
DragMode fDragMode;
bool fInStroke;
MPoint fBrushCenterScreenPoint;
UVUpdateCommand *fCommand;
};
grabUVContext::grabUVContext() :
fCommand(NULL),
fInStroke(false),
fDragMode(kNormal)
{
}
float grabUVContext::size() const
{
return fBrushConfig.size();
}
void grabUVContext::setSize( float size )
{
fBrushConfig.setSize( size );
}
void grabUVContext::toolOnSetup(
MEvent &event )
{
QCoreApplication *app = qApp;
app->installEventFilter(this);
}
void grabUVContext::toolOffCleanup()
{
QCoreApplication *app = qApp;
app->removeEventFilter(this);
}
bool grabUVContext::eventFilter( QObject * object, QEvent *event )
{
if( QKeyEvent* e = dynamic_cast<QKeyEvent*>(event) )
{
if( e->type() == QEvent::KeyPress )
doKeyPress( e );
else if( e->type() == QEvent::KeyRelease )
doKeyRelease( e );
}
return false;
}
bool grabUVContext::doKeyPress( QKeyEvent* event )
{
if( fInStroke )
return false;
if( event->key() == Qt::Key_B )
{
fDragMode = kBrushSize;
return true;
}
return false;
}
bool grabUVContext::doKeyRelease( QKeyEvent* event )
{
if( fInStroke )
return false;
if( fDragMode != kNormal )
{
fDragMode = kNormal;
return true;
}
return false;
}
{
!event.isModifierNone() )
return MS::kFailure;
fInStroke = true;
short x, y;
event.getPosition( x, y );
fCurrentScreenPoint =
MPoint( x, y );
fLastScreenPoint =
MPoint( x, y );
fBrushCenterScreenPoint =
MPoint( x, y );
double xView, yView;
portToView(x, y, xView, yView);
double portW, portH;
portSize(portW, portH);
double left, right, bottom, top;
viewRect(left, right, bottom, top);
double sizeInView = portW < 1e-5 ? 0.0 : ( fBrushConfig.size() * (right - left) / portW );
double sizeInViewSquare = sizeInView * sizeInView;
if( fDragMode == kNormal )
{
fCollectedUVs.clear();
const bool bPickSingle = false;
x + fBrushConfig.size(), y + fBrushConfig.size(),
mask, bPickSingle, true, selectionList );
if (bSelect)
{
selectionList.
getDagPath( 0, fDagPath, component );
fDagPath.extendToShape();
mesh.getCurrentUVSetName(currentUVSetName);
{
compFn.getElements( UVsToTest );
for (
unsigned int i = 0; i < UVsToTest.
length(); ++i)
{
float u, v;
MStatus bGetUV = mesh.getUV(UVsToTest[i], u, v, ¤tUVSetName);
if (bGetUV == MS::kSuccess)
{
float distSquare = ( u - xView ) * ( u - xView ) + ( v - yView ) * ( v - yView );
if ( distSquare < sizeInViewSquare )
fCollectedUVs.append(UVsToTest[i]);
}
}
}
fLastPoint =
MPoint( xView, yView, 0.0 );
fCurrentPoint =
MPoint( xView, yView, 0.0 );
}
}
return MS::kSuccess;
}
{
fInStroke = false;
if (fCommand)
fCommand->finalize();
fCommand = NULL;
return MS::kSuccess;
}
{
!event.isModifierNone() )
return MS::kFailure;
short x, y;
event.getPosition( x, y );
fLastScreenPoint = fCurrentScreenPoint;
fCurrentScreenPoint =
MPoint( x, y );
double xView, yView;
portToView(x, y, xView, yView);
fLastPoint = fCurrentPoint;
fCurrentPoint =
MPoint( xView, yView, 0.0 );
if( fDragMode == kBrushSize )
{
double dis = fCurrentScreenPoint.distanceTo( fLastScreenPoint );
if ( fCurrentScreenPoint[0] > fLastScreenPoint[0] )
setSize( size() + float(dis) );
else
setSize( std::max( size() - float(dis), 0.01f ) );
}
else
{
fBrushCenterScreenPoint =
MPoint( x, y );
const MVector vec = fCurrentPoint - fLastPoint;
if (!fCommand)
{
fCommand = (UVUpdateCommand *)(newToolCommand());
}
if (fCommand)
{
mesh.getCurrentUVSetName(currentUVSetName);
int nbUVs = mesh.numUVs(currentUVSetName);
mesh.getPinUVs(uvPinIds, pinData, ¤tUVSetName);
for (unsigned int i = 0; i < nbUVs; i++) {
fullPinData[i] = 0.0;
}
while( len-- > 0 ) {
fullPinData[uvPinIds[len]] = pinData[len];
}
float pinWeight = 0;
for (unsigned int i = 0; i < fCollectedUVs.length(); ++i)
{
float u, v;
MStatus bGetUV = mesh.getUV(fCollectedUVs[i], u, v, ¤tUVSetName);
if (bGetUV == MS::kSuccess)
{
pinWeight = fullPinData[fCollectedUVs[i]];
u += (float)vec[0]*(1-pinWeight);
v += (float)vec[1]*(1-pinWeight);
}
}
fCommand->setUVs( mesh.object(), fCollectedUVs, uValues, vValues, ¤tUVSetName );
}
}
return MS::kSuccess;
}
{
double portW, portH;
portSize(portW, portH);
short x, y;
event.getPosition( x, y );
y = short(portH) - y;
fCurrentScreenPoint =
MPoint( x, y );
fLastScreenPoint =
MPoint( x, y );
fBrushCenterScreenPoint =
MPoint( x, y );
return MS::kSuccess;
}
{
{
drawMgr.
circle2d(
MPoint(fBrushCenterScreenPoint.x, fBrushCenterScreenPoint.y), fBrushConfig.size());
}
return MS::kSuccess;
}
void grabUVContext::getClassName(
MString & name )
const
{
}
#define kSizeFlag "-sz"
#define kSizeFlagLong "-size"
{
public:
grabUVContextCommand();
static void* creator();
protected:
grabUVContext* fGrabUVContext;
};
grabUVContextCommand::grabUVContextCommand() {}
{
fGrabUVContext = new grabUVContext();
return fGrabUVContext;
}
void* grabUVContextCommand::creator()
{
return new grabUVContextCommand;
}
MStatus grabUVContextCommand::doEditFlags()
{
double size;
if (!status) {
status.
perror(
"size flag parsing failed.");
return status;
}
fGrabUVContext->setSize( float(size) );
}
return MS::kSuccess;
}
MStatus grabUVContextCommand::doQueryFlags()
{
setResult(fGrabUVContext->size());
}
return MS::kSuccess;
}
MStatus grabUVContextCommand::appendSyntax()
{
if (MS::kSuccess != mySyntax.
addFlag(kSizeFlag, kSizeFlagLong,
return MS::kFailure;
}
return MS::kSuccess;
}
#define CTX_CREATOR_NAME "grabUVContext"
#define TEX_COMMAND_NAME "uvUpdateCommand"
{
status = plugin.registerContextCommand(CTX_CREATOR_NAME, grabUVContextCommand::creator,
TEX_COMMAND_NAME, UVUpdateCommand::creator);
return status;
}
{
status = plugin.deregisterContextCommand(CTX_CREATOR_NAME, TEX_COMMAND_NAME);
return status;
}