#pragma once // =========================================================================== // 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 (MPxTransform) // // **************************************************************************** #include #include #include #include #include #include #include #include class THcustomTransform; OPENMAYA_MAJOR_NAMESPACE_OPEN // **************************************************************************** // CLASS DECLARATION (MPxTransform) //! \ingroup OpenMaya MPx //! \brief Base class for user defined transforms. /*! MPxTransform allows the creation of user defined transform nodes. User defined transform nodes can introduce new transform types or change the transformation order. They are designed to be an extension of the standard Maya transform node and include all of the normal transform attributes. Standard behaviors such as limit enforcement and attribute locking are managed by this class, but may be overriden in derived classes. In general, a complete implementation of user defined transforms will require the deriving from two classes; MPxTransform defines the node while MPxTransformationMatrix describes the mathematical functions of the user defined transform. The MPxTransform class is registered using the MFnPlugin::registerTransform() method. Both the MPxTransform and the MPxTransformationMatrix classes are registered in the same method. This allows for a clear association between a MPxTransform and a MPxTransformationMatrix. Both the MPxTransform and the MPxTransformationMatrix classes need unique MTypeIds. MPxTransform nodes are DAG nodes and therefore a change to one element will affect every node beneath the changed node. Since this can involve quite a bit of calculation, DAG nodes internally handle clean and dirty differently than other nodes. What this means is that the updateMatrixAttrs() method should be used when getting one of the matrix attributes from a method on this node. Additionally, after a value is changed, the appropriate dirty method (i.e. dirtyTranslate(), dirtyRotate(), etc.) should be called. When in doubt, dirtyMatrix() will flag everything as needing to be updated. It is up to each transform node to determine if it will obey limits or not. Since transform attributes may have limits or may be involved in some sort of constraint, there needs to be a way to accept, reject, or modify a value when a plug is set on the node. The mustCallValidateAndSet() method allows for this kind of control. When an attribute is flagged with the mustCallValidateAndSet() method in the initialize() method, every plug change will call the validateAndSetValue() method for approval. From the validateAndSetValue() method things like limits and value locking can be enforced. It is important to note that for new attributes on the transform node, any locking or limits are left as an implementation detail. If any of the public methods are affected by the addition of transform components, or by the order of computation, they should be overriden in the derived class. Many of the public methods are used by internal Maya code and exist for more than just convenience. The createTransformationMatrix() class must be overloaded if a transformation matrix other than the default MPxTransformationMatrix is used. NOTES: 1) The setDependentsDirty() virtual method is available in this class since MPxTransform derives from MPxNode. During a call to MPxTransform::setDependentsDirty(), a plug-in should not invoke any of the dirty*() or updateMatrixAttrs() calls of this class. For example, the methods dirtyMatrix(), dirtyTranslation() or updateMatrixAttrs() should not be called. 2) Updating world space attributes is an expensive operation. Maya updates world space attributes on demand such as in the case of a getAttr being issued or a connection exists for the attribute. */ class OPENMAYA_EXPORT MPxTransform : public MPxNode { public: MPxTransform(); MPxTransform(const MPxTransform&)/* = default*/; MPxTransform& operator=(const MPxTransform&)/* = default*/; ~MPxTransform() override; void postConstructor() override; MPxNode::Type type() const override; virtual MPxTransformationMatrix *createTransformationMatrix(); virtual bool isBounded () const; virtual MBoundingBox boundingBox () const; virtual bool treatAsTransform() const; const MPxTransformationMatrix & transformationMatrix () const; MPxTransformationMatrix * transformationMatrixPtr () const; virtual void resetTransformation (const MMatrix &); virtual void resetTransformation (MPxTransformationMatrix *); MStatus compute(const MPlug& plug, MDataBlock& data) override; virtual MStatus computeLocalTransformation (MPxTransformationMatrix *, MDataBlock &) OPENMAYA_NO_OVERRIDE; virtual MStatus clearLimits (); bool isLimited (MFnTransform::LimitType, MStatus * ReturnStatus = NULL ) const; double limitValue (MFnTransform::LimitType, MStatus * ReturnStatus = NULL ) const; MStatus setLimit (MFnTransform::LimitType, double value); MStatus enableLimit (MFnTransform::LimitType, bool flag); // Method to validate input data. // virtual MStatus validateAndSetValue(const MPlug&, const MDataHandle&); // Matrix methods // virtual MMatrix getMatrix (MStatus *ReturnStatus = NULL) OPENMAYA_NO_OVERRIDE; virtual MMatrix getMatrixInverse(MStatus *ReturnStatus = NULL) OPENMAYA_NO_OVERRIDE; // Translation methods // virtual MVector getTranslation (MSpace::Space = MSpace::kTransform, MStatus *ReturnStatus = NULL) OPENMAYA_NO_OVERRIDE; virtual MStatus translateTo (const MVector&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; virtual MStatus translateBy (const MVector&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; // Rotation methods // virtual MQuaternion getRotation (MSpace::Space = MSpace::kTransform, MStatus *ReturnStatus = NULL) OPENMAYA_NO_OVERRIDE; virtual MEulerRotation getEulerRotation(MSpace::Space = MSpace::kTransform, MStatus *ReturnStatus = NULL) OPENMAYA_NO_OVERRIDE; virtual MStatus rotateTo (const MQuaternion&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; virtual MStatus rotateBy (const MQuaternion&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; virtual MStatus rotateTo (const MEulerRotation&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; virtual MStatus rotateBy (const MEulerRotation&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; // Scale methods // virtual MVector getScale(MSpace::Space = MSpace::kTransform, MStatus *ReturnStatus = NULL) OPENMAYA_NO_OVERRIDE; virtual MStatus scaleTo (const MVector&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; virtual MStatus scaleBy (const MVector&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; // Shear methods // virtual MVector getShear(MSpace::Space = MSpace::kTransform, MStatus *ReturnStatus = NULL) OPENMAYA_NO_OVERRIDE; virtual MStatus shearTo (const MVector&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; virtual MStatus shearBy (const MVector&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; // Pivot methods // virtual MPoint getScalePivot (MSpace::Space = MSpace::kTransform, MStatus *ReturnStatus = NULL) OPENMAYA_NO_OVERRIDE; virtual MPoint getRotatePivot (MSpace::Space = MSpace::kTransform, MStatus *ReturnStatus = NULL) OPENMAYA_NO_OVERRIDE; virtual MVector getScalePivotTranslation (MSpace::Space = MSpace::kTransform, MStatus *ReturnStatus = NULL) OPENMAYA_NO_OVERRIDE; virtual MVector getRotatePivotTranslation(MSpace::Space = MSpace::kTransform, MStatus *ReturnStatus = NULL) OPENMAYA_NO_OVERRIDE; virtual MStatus setScalePivot (const MPoint &, MSpace::Space = MSpace::kTransform, bool balance = true) OPENMAYA_NO_OVERRIDE; virtual MStatus setScalePivotTranslation (const MVector &, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; virtual MStatus setRotatePivot (const MPoint &, MSpace::Space = MSpace::kTransform, bool balance = true) OPENMAYA_NO_OVERRIDE; virtual MStatus setRotatePivotTranslation(const MVector &, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; // Rotation order methods // virtual MTransformationMatrix::RotationOrder getRotationOrder() OPENMAYA_NO_OVERRIDE; virtual MStatus setRotationOrder(MTransformationMatrix::RotationOrder ro, bool reorder = true) OPENMAYA_NO_OVERRIDE; // Rotation orientation methods // virtual MQuaternion getRotateOrientation(MSpace::Space apiSpace = MSpace::kTransform, MStatus *ReturnStatus = NULL) OPENMAYA_NO_OVERRIDE; virtual MStatus setRotateOrientation(const MQuaternion &q, MSpace::Space apiSpace = MSpace::kTransform, bool balance = true) OPENMAYA_NO_OVERRIDE; virtual MQuaternion getPreRotation() const; MStatus updateMatrixAttrs(); MStatus updateMatrixAttrs(MObject &attr); static void mustCallValidateAndSet(MObject &); static MStatus setNonAffineMatricesEnabled(bool); static bool isNonAffineMatricesEnabled(MStatus *ReturnStatus); void copyInternalData( MPxNode* ) override; // SCRIPT USE ONLY. MStatus _dirtyMatrix() { return dirtyMatrix(); } _OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute Translation") MStatus _dirtyTranslation(const MVector &v) { return dirtyTranslation(v); } OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute Rotation") MStatus _dirtyRotation(const MEulerRotation &e) { return dirtyRotation(e); } OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute Scale") MStatus _dirtyScale(const MVector &v) { return dirtyScale(v); } OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute Shear") MStatus _dirtyShear(const MVector &v) { return dirtyShear(v); } OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute RotateOrientation") MStatus _dirtyRotateOrientation(const MEulerRotation &e){ return dirtyRotateOrientation(e); } OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute ScalePivot") MStatus _dirtyScalePivot(const MPoint &p) { return dirtyScalePivot(p); } OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute RotatePivot") MStatus _dirtyRotatePivot(const MPoint &p) { return dirtyRotatePivot(p); } OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute ScalePivotTranslation") MStatus _dirtyScalePivotTranslation(const MVector &v) { return dirtyScalePivotTranslation(v); } OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute RotatePivotTranslation") MStatus _dirtyRotatePivotTranslation(const MVector &v) {return dirtyRotatePivotTranslation(v); } // _OPENMAYA_DEPRECATION_POP_WARNING protected: // // Methods for clamping and locking enforcement // virtual MVector applyTranslationLimits (const MVector &unclampedT, MDataBlock &, MStatus *ReturnStatus = NULL); virtual MVector applyTranslationLocks (const MVector &toTest, const MVector &savedT, MStatus *ReturnStatus = NULL); virtual MEulerRotation applyRotationLimits (const MEulerRotation &unclampedR, MDataBlock &, MStatus *ReturnStatus = NULL); virtual MEulerRotation applyRotationLocks (const MEulerRotation &toTest, const MEulerRotation &savedR, MStatus *ReturnStatus = NULL); virtual MVector applyScaleLimits (const MVector &unclampedS, MDataBlock &, MStatus *ReturnStatus = NULL); virtual MVector applyScaleLocks (const MVector &toTest, const MVector &savedS, MStatus *ReturnStatus = NULL); virtual MVector applyShearLocks (const MVector &toTest, const MVector &savedSh, MStatus *ReturnStatus = NULL); virtual MEulerRotation applyRotateOrientationLocks (const MEulerRotation &toTest, const MEulerRotation &savedRO, MStatus *ReturnStatus = NULL); virtual MVector applyScaleLocksPivot (const MPoint &toTest, const MPoint &savedSP, MStatus *ReturnStatus = NULL); virtual MVector applyRotatePivotLocks (const MPoint &toTest, const MPoint &savedRP, MStatus *ReturnStatus = NULL); virtual MVector applyScaleLocksPivotTranslate (const MVector &toTest, const MVector &savedSPT, MStatus *ReturnStatus = NULL); virtual MVector applyRotatePivotLocksTranslate (const MVector &toTest, const MVector &savedRPT, MStatus *ReturnStatus = NULL); // // Methods for marking the matrix dirty. // MStatus dirtyMatrix (); //!< USE _dirtyMatrix() IN SCRIPT OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute Translation") MStatus dirtyTranslation (const MVector &); //!< USE _dirtyTranslation() IN SCRIPT OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute Rotation") MStatus dirtyRotation (const MEulerRotation &); //!< USE _dirtyRotation() IN SCRIPT OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute Scale") MStatus dirtyScale (const MVector &); //!< USE _dirtyScale() IN SCRIPT OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute Shear") MStatus dirtyShear (const MVector &); //!< USE _dirtyShear() IN SCRIPT OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute RotateOrientation") MStatus dirtyRotateOrientation (const MEulerRotation &); //!< USE _dirtyRotateOrientation() IN SCRIPT OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute ScalePivot") MStatus dirtyScalePivot (const MPoint &); //!< USE _dirtyScalePivot() IN SCRIPT OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute RotatePivot") MStatus dirtyRotatePivot (const MPoint &); //!< USE _dirtyRotatePivot() IN SCRIPT OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute ScalePivotTranslation") MStatus dirtyScalePivotTranslation (const MVector &); //!< USE _dirtyScalePivotTranslation() IN SCRIPT OPENMAYA_DEPRECATED(2023, "MPxTransform should not manage built-in attribute RotatePivotTranslation") MStatus dirtyRotatePivotTranslation (const MVector &); //!< USE _dirtyRotatePivotTranslation() IN SCRIPT // // checkAndSet methods. These are called by the compute method. // virtual MStatus checkAndSetTranslation (MDataBlock &, const MPlug&, const MVector&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; virtual MStatus checkAndSetRotation (MDataBlock &, const MPlug&, const MEulerRotation&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; virtual MStatus checkAndSetScale (MDataBlock &, const MPlug&, const MVector&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; virtual MStatus checkAndSetShear (MDataBlock &, const MPlug&, const MVector&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; virtual MStatus checkAndSetRotateOrientation (MDataBlock &, const MPlug&, const MEulerRotation&, MSpace::Space = MSpace::kTransform, bool balance = true) OPENMAYA_NO_OVERRIDE; virtual MStatus checkAndSetRotatePivot (MDataBlock &, const MPlug&, const MPoint&, MSpace::Space = MSpace::kTransform, bool balance = true) OPENMAYA_NO_OVERRIDE; virtual MStatus checkAndSetRotatePivotTranslation(MDataBlock &, const MPlug&, const MVector&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; virtual MStatus checkAndSetScalePivot (MDataBlock &, const MPlug&, const MPoint&, MSpace::Space = MSpace::kTransform, bool = true) OPENMAYA_NO_OVERRIDE; virtual MStatus checkAndSetScalePivotTranslation (MDataBlock &, const MPlug&, const MVector&, MSpace::Space = MSpace::kTransform) OPENMAYA_NO_OVERRIDE; public: // Default attributes. static MObject nodeBoundingBox; //!