Autodesk Maya API を使用するプログラムをコンパイルしていますが、このコンテキスト内でコンストラクターがプライベートであるというエラーが発生します。
/usr/autodesk/maya2013-x64/include/maya/MFnTransform.h: In member function ‘MayaEggGroup* MayaEggLoader::MakeGroup(EggGroup*, EggGroup*)’:
/usr/autodesk/maya2013-x64/include/maya/MFnTransform.h:181:2: error: ‘MFnTransform::MFnTransform(const MFnTransform&)’ is private
pandatool/src/mayaegg/mayaEggLoader.cxx:373:60: error: within this context
ちょっとした背景 - Maya 2013 を使用して、Ubuntu 12.04 で Panda3D (オープンソースのゲーム エンジン) を構築しています。Maya から Panda のモデル フォーマットにファイルを変換するエクスポータをコンパイルしているビルドの一部で窒息しています。
エラーの意味は(ある程度)理解できますが、解決方法はわかりません。奇妙なことに、同じコードが Maya 2011 と Maya 2012 で正常にコンパイルされ、クラス宣言 (MFnTransform) が Maya 2013 で変更されていないことがわかります。
完全な g++ コマンドは次のとおりです。
g++ -ftemplate-depth-30 -fPIC -c -o built/tmp/mayaegg2013_loader.o -Ibuilt/tmp -Ibuilt/include -I/usr/include/python2.7 -I/usr/include/eigen3 -I/usr/autodesk/maya2013-x64/include -DMAYAVERSION=MAYA2013 -DMAKEPANDA= -Ipandatool/src/mayaegg -Ipandatool/src/maya -pthread -msse2 -ggdb -D_DEBUG pandatool/src/mayaegg/mayaEggLoader.cxx
そして、関連するコードの一部。
mayaEggLoader.cxx では、エラーの発生場所は次のとおりです。
class MayaEggGroup
{
public:
string _name;
MObject _parent;
MObject _group;
bool _addedEggFlag;
};
MayaEggGroup *MayaEggLoader::MakeGroup(EggGroup *group, EggGroup *context)
{
MStatus status;
MayaEggGroup *result = new MayaEggGroup;
...
MFnTransform tFn = MFnTransform(result->_group, &status);
MFnTransform.h から、MFnTransform の定義の始まりを次に示します。
class OPENMAYA_EXPORT MFnTransform : public MFnDagNode
{
declareDagMFn( MFnTransform, MFn::kTransform );
public:
MObject create( MObject parent = MObject::kNullObj,MStatus * ReturnStatus = NULL );
...
プライベートコンストラクターが定義されている場所がまったくわかりません...どうすればそれを探すことができますか? それとも、そのエラーは実際には何か他のことが間違っていることを意味するのでしょうか?
アップデート:
これは、Maya 2013 C++ API で導入された既知のバグであることが判明しました。
MAYA-6512: MFnDependencyNode、MFnDagNode コピー コンストラクターは、プライベートではなくパブリックにする必要があります 回避策: 同じオブジェクトで動作する新しい関数セットを作成します。たとえば、次のようにします。関数セットを別のメソッドに渡したい場合は、代わりに参照を渡します。
わかりましたが、メンバー変数を設定する必要がある場合はどうすればよいでしょうか? これは、同じエラーが発生している別の場所です。
MayaBlendDesc::
MayaBlendDesc(MFnBlendShapeDeformer deformer, int weight_index)
{
_weight_index=weight_index;
_deformer=deformer;
ostringstream strm;
strm << _deformer.name().asChar() << "." << _weight_index;
set_name(strm.str());
_anim = (EggSAnimData *)NULL;
}
「_deformer=deformer」の行。
MayaBlendDesc の定義は次のとおりです。これは私が編集できるコードです。
////////////////////////////////////////////////////////////////////
// Class : MayaBlendDesc
// Description : A handle to a Maya blend shape description. This is
// just one target of a Maya BlendShape object, and
// thus corresponds more or less one-to-one with a
// single Egg morph target. (We don't attempt to
// support Maya's chained target shapes here; should we
// need to later, it would mean breaking each of those
// target shapes on the one continuous Maya slider into
// a separate MayaBlendDesc object, and synthesizing the
// egg slider values appropriately.)
////////////////////////////////////////////////////////////////////
class MayaBlendDesc : public ReferenceCount, public Namable {
public:
MayaBlendDesc(MFnBlendShapeDeformer deformer, int weight_index);
~MayaBlendDesc();
void set_slider(PN_stdfloat value);
PN_stdfloat get_slider() const;
private:
void clear_egg();
MFnBlendShapeDeformer _deformer;
int _weight_index;
EggSAnimData *_anim;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
ReferenceCount::init_type();
Namable::init_type();
register_type(_type_handle, "MayaBlendDesc",
ReferenceCount::get_class_type(),
Namable::get_class_type());
}
private:
static TypeHandle _type_handle;
friend class MayaNodeTree;
};
MFnBlendShape とその祖先 (Maya API の一部であり、触れることはできません) の定義は次のとおりです。
class OPENMAYAANIM_EXPORT MFnBlendShapeDeformer : public MFnDependencyNode
{
declareMFn(MFnBlendShapeDeformer, MFnDependencyNode );
public:
//! Specifies the space to use for the deformation origin.
enum Origin {
kLocalOrigin, //!< \nop
kWorldOrigin //!< \nop
};
//! Specifies where in the shape's history to place the deformer.
enum HistoryLocation {
kFrontOfChain, //!< \nop
kNormal //!< \nop
};
MObject create( MObject baseObject,
Origin originSpace = kLocalOrigin,
MStatus * ReturnStatus = NULL );
MObject create( const MObjectArray& baseObjects,
Origin originSpace = kLocalOrigin,
HistoryLocation = kNormal,
MStatus * ReturnStatus = NULL );
MStatus addBaseObject( MObject & object );
MStatus getBaseObjects( MObjectArray & objects ) const;
MStatus addTarget( const MObject & baseObject, int weightIndex,
const MObject & newTarget, double fullWeight );
MStatus removeTarget( const MObject & baseObject,
int weightIndex,
const MObject & target,
double fullWeight );
MStatus getTargets( MObject baseObject, int weightIndex,
MObjectArray & targetObjects ) const;
unsigned int numWeights( MStatus * ReturnStatus = NULL ) const;
MStatus weightIndexList( MIntArray& indexList ) const;
MStatus targetItemIndexList( unsigned int weightIndex,
MObject baseObject,
MIntArray& targetItemIndices ) const;
float weight( unsigned int index, MStatus * ReturnStatus = NULL ) const;
MStatus setWeight( unsigned int index, float weight );
float envelope( MStatus * ReturnStatus = NULL ) const;
MStatus setEnvelope( float envelope );
Origin origin( MStatus * ReturnStatus = NULL ) const;
MStatus setOrigin( Origin space );
BEGIN_NO_SCRIPT_SUPPORT:
declareMFnConstConstructor( MFnBlendShapeDeformer, MFnDependencyNode );
END_NO_SCRIPT_SUPPORT:
protected:
// No protected members
private:
// No private members
};
MFnDependencyNode:
// ****************************************************************************
// CLASS DECLARATION (MFnDependencyNode)
//! \ingroup OpenMaya MFn
//! \brief Dependency node function set.
/*!
MFnDependencyNode allows the creation and manipulation of dependency
graph nodes. Traversal of the dependency graph is possible using
the getConnections method.
This function set does not support creation or removal of connections.
MDGModifier should be used for that purpose.
*/
class OPENMAYA_EXPORT MFnDependencyNode : public MFnBase
{
declareMFn(MFnDependencyNode, MFnBase);
public:
//! Specifies the scope of the attribute.
enum MAttrClass {
kLocalDynamicAttr = 1, //!< Dynamically added, applies to this specific node.
kNormalAttr, //!< Static attribute which is part of the original definition for this node type.
kExtensionAttr, //!< Extension attribute which is part of all nodes of this or derived node types
kInvalidAttr //!< None of the above
};
MObject create( const MTypeId &typeId,
MStatus* ReturnStatus = NULL );
MObject create( const MTypeId &typeId,
const MString& name,
MStatus* ReturnStatus = NULL );
MObject create( const MString &type,
MStatus* ReturnStatus = NULL );
MObject create( const MString &type,
const MString& name,
MStatus* ReturnStatus = NULL );
MTypeId typeId( MStatus* ReturnStatus = NULL ) const;
MString typeName( MStatus* ReturnStatus = NULL ) const;
MString name( MStatus * ReturnStatus = NULL ) const;
MString pluginName( MStatus * ReturnStatus = NULL ) const;
MString setName( const MString &name,
bool createNamespace = false,
MStatus * ReturnStatus = NULL );
MStatus getConnections( MPlugArray& array ) const;
unsigned int attributeCount( MStatus* ReturnStatus=NULL) const;
MObject attribute( unsigned int index,
MStatus* ReturnStatus=NULL) const;
MObject reorderedAttribute( unsigned int index,
MStatus* ReturnStatus=NULL) const;
MObject attribute( const MString& attrName,
MStatus* ReturnStatus=NULL) const;
MAttrClass attributeClass( const MObject& attr,
MStatus* ReturnStatus=NULL) const;
MStatus getAffectedAttributes ( const MObject& attr,
MObjectArray& affectedAttributes ) const;
MStatus getAffectedByAttributes ( const MObject& attr,
MObjectArray& affectedByAttributes ) const;
MPlug findPlug( const MObject & attr, bool wantNetworkedPlug,
MStatus* ReturnStatus=NULL) const;
MPlug findPlug( const MString & attrName, bool wantNetworkedPlug,
MStatus* ReturnStatus=NULL) const;
// Obsolete
MPlug findPlug( const MObject & attr,
MStatus* ReturnStatus=NULL) const;
// Obsolete
MPlug findPlug( const MString & attrName,
MStatus* ReturnStatus=NULL) const;
MStatus addAttribute ( const MObject & attr );
MStatus removeAttribute ( const MObject & attr );
MPxNode * userNode( MStatus* ReturnStatus=NULL ) const;
bool isFromReferencedFile(MStatus* ReturnStatus=NULL) const;
bool isShared(MStatus* ReturnStatus=NULL) const;
bool hasUniqueName(MStatus* ReturnStatus=NULL) const;
MString parentNamespace(MStatus* ReturnStatus=NULL) const;
bool isLocked(MStatus* ReturnStatus=NULL) const;
MStatus setLocked( bool locked );
static MString classification( const MString & nodeTypeName );
bool isNewAttribute( const MObject& attr,
MStatus* ReturnStatus=NULL) const;
static unsigned int allocateFlag(
const MString pluginName, MStatus* ReturnStatus=NULL
);
static MStatus deallocateFlag(const MString pluginName, unsigned int flag);
static MStatus deallocateAllFlags(const MString pluginName);
MStatus setFlag(unsigned int flag, bool state);
bool isFlagSet(unsigned int flag, MStatus* ReturnStatus=NULL) const;
bool isDefaultNode(MStatus* ReturnStatus=NULL) const;
MStatus setDoNotWrite ( bool flag );
bool canBeWritten(MStatus* ReturnStatus=NULL) const;
bool hasAttribute(const MString& name, MStatus* ReturnStatus=NULL) const;
MObject getAliasAttr(bool force, MStatus* ReturnStatus=NULL);
bool setAlias(const MString& alias,const MString& name, const MPlug& plug, bool add=true,
MStatus* ReturnStatus=NULL);
bool findAlias(const MString& alias, MObject& attrObj, MStatus* ReturnStatus=NULL) const;
bool getAliasList(MStringArray& strArray, MStatus* ReturnStatus=NULL);
MString plugsAlias(const MPlug& plug, MStatus* ReturnStatus=NULL);
MStatus setIcon( const MString &filename );
MString icon( MStatus* ReturnStatus=NULL ) const;
BEGIN_NO_SCRIPT_SUPPORT:
//! OBSOLETE FUNCTION, NO SCRIPT SUPPORT
MString setName( const MString &name,
MStatus * ReturnStatus );
//! NO SCRIPT SUPPORT
declareMFnConstConstructor( MFnDependencyNode, MFnBase );
//! NO SCRIPT SUPPORT
bool getPlugsAlias(const MPlug& plug, MString& aliasName, MStatus* ReturnStatus=NULL);
END_NO_SCRIPT_SUPPORT:
// turn on timing on for all nodes in the DG
static void enableDGTiming(bool enable);
// For turning node timing on and off, and querying the state...
MStatus dgTimerOn();
MStatus dgTimerOff();
//! Possible states for the node's timer.
enum MdgTimerState {
kTimerOff, //!< \nop
kTimerOn, //!< \nop
kTimerUninitialized, //!< \nop
kTimerInvalidState //!< \nop
};
MdgTimerState dgTimerQueryState( MStatus* ReturnStatus = NULL );
// For resetting node timers to zero...
MStatus dgTimerReset();
//! The different timer metrics which can be queried.
enum MdgTimerMetric {
// Primary metrics. The qualities that we measure.
kTimerMetric_callback, //!< Time spent within node callbacks for this node.
kTimerMetric_compute, //!< Time spent within the compute method for this node.
kTimerMetric_dirty, //!< Time spent propogating dirty messages from this node.
kTimerMetric_draw, //!< Time spent drawing this node.
kTimerMetric_fetch, //!< Time spent fetching data from plugs.
// Sub metrics. These are finer-grained breakdowns of the primary
// metrics. There could be many combinations of the above metrics.
// Currently we only support the following.
kTimerMetric_callbackViaAPI, //!< Time spent in callbacks which were registered through the API.
kTimerMetric_callbackNotViaAPI, //!< Time spent in callbacks not registered through the API (i.e internal Maya callbacks).
kTimerMetric_computeDuringCallback, //!< Time spent in this node's compute while executing node callbacks on any node.
kTimerMetric_computeNotDuringCallback //!< Time spent in this nodes compute when not executing any node callbacks on any nodes.
};
//! The types of timers which can be queried.
enum MdgTimerType {
/*!
Time spent performing an operation, not including any time
spent by child operations. For example, if we are drawing a
node and that requires a compute, self time will only include
the time spent drawing and not the compute time. Self time
measures wall-clock time as opposed to CPU time and the values
are in seconds.
*/
kTimerType_self,
/*!
Time spent performing an operation including all time spent by
child operations. For example, if we are drawing a node and
that requires a compute, inclusive time is the time for the
draw plus compute. Inclusive time measure wall-clock time as
opposed to CPU time and the values are in seconds.
*/
kTimerType_inclusive,
/*!
The number of operations that occurred. Ideally we should
return an integer when this timer type is queried, but there
are two advantages to using a double. 1) it keeps the interface
consistent and 2) integer has a fixed upper bound of roughly
four billion so using a double allows us to exceed this.
*/
kTimerType_count
};
// Query the timer value given a given metric and timer type.
double dgTimer( const MdgTimerMetric timerMetric,
const MdgTimerType timerType,
MStatus* ReturnStatus = NULL ) const;
// Query the callback timer values.
MStatus dgCallbacks( const MdgTimerType type,
MStringArray &callbackName,
MDoubleArray &value );
// Query the callbackId timer values.
MStatus dgCallbackIds( const MdgTimerType type,
const MString &callbackName,
MCallbackIdArray &callbackId,
MDoubleArray &value );
// Obsolete
MStatus addAttribute ( const MObject & attr, MAttrClass type );
// Obsolete
MStatus removeAttribute ( const MObject & attr, MAttrClass type );
protected:
// No protected members
private:
// No private members
};
および MFnBase:
// ****************************************************************************
// CLASS DECLARATION (MFnBase)
//! \ingroup OpenMaya MFn
//! \brief Function Set Base Class.
/*!
Defines the interface for the API RTTI and Maya Object attachment
methods common to all Function Set Classes.
Implements the Function Set compatibility test methods for all
Function Sets.
The API provides access to Maya Objects as generic MObjects. Under
the C++ class scheme MObjects simply have type MObject with no base
or derived hierarchy. However, MObjects may be many different types
of model or scene objects, from Attributes to Transforms, within
Maya. This allows many different types of objects to be moved
across or accessed through the API without undue concern on the part
of plug-in developers for the type of object being manipulated.
Since it is impractical to provide every applicable method on
MObjects, the methods applicable to Maya Objects are encapsulated in
Function Sets. Function Sets can be attached to compatible MObjects
to provide an external interface to methods appropriate to that
MObject. All Function Sets provide a method setObject() which
attaches them to the specified Maya Object. Additionally, most
Function Sets provide a version of their constructor which attaches
the new Function Set to a specified MObject.
The link between an MObject and the role it performs as a Maya scene
or model object, as well as the compatibility between MObjects and
Function Sets is managed by the API Run-Time Type Identification
(RTTI) system. The two key concepts of this system are the Maya
Object type and the Function Set type (both are MFn::Type). All
MObjects have one and only one Maya Object type. All Function Sets
have one and only one Function Set type. MObjects may, however, be
compatible with many types of Function Sets. This compatibility
follows the class hierarchy of the Function Sets. Thus an MObject
with Maya Object type MFn::kNurbsSurface would be compatible with
MFnNurbsSurface, MFnDagNode, MFnDependencyNode, MFnNamedObject and
MFnBase.
Any MObject can be queried with the MObject::hasFn() method to
determine if it is comaptible with a given Function Set.
The purpose of the Base Function Set (MFnBase) is to provide methods for
determining whether or not a Function Set is compatible with a given Maya
Object (MObject) type (MFn::Type) or a specific MObject. See:
MFnBase::hasObj(MFn::Type)
and
MFnBase::hasObj(const MObject &)
As well, this Function Set provides virtual methods for determining the type
of a Function Set under the API RTTI system.
*/
class OPENMAYA_EXPORT MFnBase
{
public:
virtual ~MFnBase();
virtual MFn::Type type() const;
bool hasObj( MFn::Type ) const;
bool hasObj( const MObject & ) const;
MObject object( MStatus* ReturnStatus = NULL ) const;
virtual MStatus setObject( MObject & object );
BEGIN_NO_SCRIPT_SUPPORT:
//! NO SCRIPT SUPPORT
virtual MStatus setObject( const MObject & object );
END_NO_SCRIPT_SUPPORT:
static const char* className();
protected:
MFnBase();
void setPtr( MPtrBase* );
void setPtr( const MPtrBase* );
void setPtrNull();
virtual bool objectChanged( MFn::Type, MStatus * );
MPtrBase* f_ptr; // initialized/set with volatile
const MPtrBase* f_constptr; // initialized/set with volatile/const
// Specific for function sets which use internally reference
// counted objects! Only those function sets which use these
// objects need to set this to true. By default it is set to
// false.
//
// Classes which do not use internally reference counted objects
// must not tamper with this boolean value. Doing so can cause
// crashes when dealing with manually deleted objects.
//
bool fIsReferenceCounted;
private:
MFnBase( const MFnBase &rhs );
MFnBase & operator=( const MFnBase & );
MFnBase * operator& () const;
};
// ****************************************************************************
#define declareMinimalMFn( MFnClass ) \
public: \
virtual MFn::Type type() const; \
virtual ~MFnClass(); \
\
static const char* className(); \
\
private: \
MFnClass( const MFnClass &rhs ); \
MFnClass & operator=( const MFnClass & ); \
MFnClass * operator& () const;
#define declareMFn( MFnClass, MFnParentClass ) \
declareMinimalMFn( MFnClass ); \
public: \
MFnClass() {}; \
MFnClass( MObject & object, MStatus * ReturnStatus = NULL )
#define declareMFnConstConstructor( MFnClass, MFnParentClass ) \
MFnClass( const MObject & object, MStatus * ReturnStatus = NULL )
// Standard MFn class interface *without* the class constructor. This
// is to allow derived MFn classes to optionally specify their own
// custom constructor. For example if they wanted to declare that they
// use internally reference counted objects, they could set fIsReferenceCounted
// to true inside their own custom constructor.
//
#define declareMFnNoVoidConstructor( MFnClass, MFnParentClass ) \
declareMinimalMFn( MFnClass ); \
public: \
MFnClass( MObject & object, MStatus * ReturnStatus = NULL )
#define declareMFnNoVoidConstructorConstConstructor( MFnClass, MFnParentClass ) \
MFnClass( const MObject & object, MStatus * ReturnStatus = NULL )
#endif /* __cplusplus */
#endif /* _MFnBase */