Files
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

632 lines
21 KiB
C++

//
// Copyright (C)
//
// File: rageMayaGeoInstance.cpp
//
// Dependency Graph Node: rageMayaGeoInstance
//
// Author: Maya Plug-in Wizard 2.0
//
#include "rageGeoDataSetCommands.h"
#include "rageMayaGeoInstance.h"
#define REQUIRE_IOSTREAM
#pragma warning(push)
#pragma warning(disable : 4668)
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MGlobal.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MDGMessage.h>
#include <maya/MSceneMessage.h>
#include <maya/MNodeMessage.h>
#include <maya/MDGModifier.h>
#include <maya/MItDependencyNodes.h>
#include <maya/MFileObject.h>
#pragma warning(pop)
#include <Windows.h>
#include <stdio.h>
#define CHECK_STATUS(x) \
{ \
MStatus _maya_status = (x); \
if ( MStatus::kSuccess != _maya_status ) \
{ \
MString obStrErrorMessage(__FILE__); \
obStrErrorMessage += ":"; \
obStrErrorMessage += __LINE__; \
obStrErrorMessage += ":"; \
_maya_status.perror (obStrErrorMessage); \
} \
} \
// You MUST change this to a unique value!!! The id is a 32bit value used
// to identify this type of node in the binary file format.
//
MTypeId rageMayaGeoInstance::id( 0x7021 );
bool rageMayaGeoInstance::m_bBetweenBeforeSceneOpenAndAfterSceneOpen = false;
// Attributes
//
MObject rageMayaGeoInstance::m_obGeoInstanceUIDAttribute;
MObject rageMayaGeoInstance::m_obGeoInstanceTypeAttribute;
MObject rageMayaGeoInstance::m_obGeoInstanceNameAttribute;
MObject rageMayaGeoInstance::m_obGeoInstanceContainerUIDAttribute;
MCallbackId rageMayaGeoInstance::m_NodeAddedCallbackId;
MCallbackId rageMayaGeoInstance::m_BeforeMayaSaveCallbackId;
MCallbackId rageMayaGeoInstance::m_BeforeOpenCallbackId;
MCallbackId rageMayaGeoInstance::m_BeforeNewCallbackId;
MCallbackId rageMayaGeoInstance::m_AfterNewCallbackId;
rageMayaGeoInstance::rageMayaGeoInstance()
{
// InitializeNodeCallbacks();
}
rageMayaGeoInstance::~rageMayaGeoInstance()
{
UninitializeNodeCallbacks();
MString strMyUID;
MPlug obMyUIDPlug(thisMObject(), m_obGeoInstanceUIDAttribute);
obMyUIDPlug.getValue(strMyUID);
// printf("%s is being destroyed\n", strMyUID.asChar());
// _flushall();
}
void rageMayaGeoInstance::postConstructor()
{
InitializeNodeCallbacks();
// Was I just created during a file load? If so, commit suicide
m_bNodeWasCreatedDuringFileOpenSoKillMe = false;
if(MFileIO::isReadingFile())
{
// Kill myself
m_bNodeWasCreatedDuringFileOpenSoKillMe = true;
//printf("Commiting suicide\n");
}
}
void* rageMayaGeoInstance::creator()
//
// Description:
// this method exists to give Maya a way to create new objects
// of this type.
//
// Return Value:
// a new object of this type
//
{
return new rageMayaGeoInstance();
}
MStatus rageMayaGeoInstance::initialize()
//
// Description:
// This method is called to create and initialize all of the attributes
// and attribute dependencies for this node type. This is only called
// once when the node type is registered with Maya.
//
// Return Values:
// MS::kSuccess
// MS::kFailure
//
{
MFnTypedAttribute tAttr;
MStatus status;
m_obGeoInstanceUIDAttribute = tAttr.create( "rageGeoInstanceUID", "UID", MFnData::kString, MObject::kNullObj , &status );
CHECK_STATUS( status );
//CHECK_STATUS( tAttr.setInternal( true ) );
CHECK_STATUS( tAttr.setHidden( true ) );
//CHECK_STATUS( tAttr.setReadable( true ) );
//CHECK_STATUS( tAttr.setWritable( false ) );
//CHECK_STATUS( tAttr.setInternal( true ) );
CHECK_STATUS( tAttr.setConnectable( false ) );
CHECK_STATUS( addAttribute( m_obGeoInstanceUIDAttribute ) );
m_obGeoInstanceTypeAttribute = tAttr.create( "rageGeoInstanceType", "Type", MFnData::kString, MObject::kNullObj , &status );
CHECK_STATUS( status );
//CHECK_STATUS( tAttr.setInternal( true ) );
CHECK_STATUS( tAttr.setHidden( true ) );
//CHECK_STATUS( tAttr.setReadable( true ) );
//CHECK_STATUS( tAttr.setWritable( false ) );
CHECK_STATUS( tAttr.setConnectable( false ) );
CHECK_STATUS( tAttr.setInternal( true ) );
CHECK_STATUS( addAttribute( m_obGeoInstanceTypeAttribute ) );
m_obGeoInstanceNameAttribute = tAttr.create( "rageGeoInstanceName", "Name", MFnData::kString, MObject::kNullObj , &status );
CHECK_STATUS( status );
//CHECK_STATUS( tAttr.setInternal( true ) );
CHECK_STATUS( tAttr.setHidden( true ) );
//CHECK_STATUS( tAttr.setReadable( true ) );
//CHECK_STATUS( tAttr.setWritable( false ) );
//CHECK_STATUS( tAttr.setInternal( true ) );
CHECK_STATUS( tAttr.setConnectable( false ) );
CHECK_STATUS( addAttribute( m_obGeoInstanceNameAttribute ) );
m_obGeoInstanceContainerUIDAttribute = tAttr.create( "rageGeoInstanceContainerUID", "ContainerUID", MFnData::kString, MObject::kNullObj , &status );
CHECK_STATUS( status );
//CHECK_STATUS( tAttr.setInternal( true ) );
CHECK_STATUS( tAttr.setHidden( false ) );
//CHECK_STATUS( tAttr.setReadable( true ) );
//CHECK_STATUS( tAttr.setWritable( false ) );
//CHECK_STATUS( tAttr.setInternal( true ) );
CHECK_STATUS( tAttr.setConnectable( true ) );
CHECK_STATUS( addAttribute( m_obGeoInstanceContainerUIDAttribute ) );
return MS::kSuccess;
}
void rageMayaGeoInstance::InitializeNodeCallbacks()
{
MStatus obStatus;
MObject obThisNode = thisMObject();
m_NodePreRemovalCallbackId = MNodeMessage::addNodePreRemovalCallback(obThisNode, NodePreRemovalCallback, this, &obStatus);
if(obStatus != MS::kSuccess)
{
MGlobal::displayError("An error occurred registering NodePreRemovalCallback : "+ obStatus.errorString());
}
m_AfterOpenCallbackId = MSceneMessage::addCallback(MSceneMessage::kAfterOpen, AfterOpenCallback, this);
m_AfterImportCallbackId = MSceneMessage::addCallback(MSceneMessage::kAfterImport, AfterImportCallback, this);
}
void rageMayaGeoInstance::UninitializeNodeCallbacks()
{
MMessage::removeCallback(m_NodePreRemovalCallbackId);
MMessage::removeCallback(m_AfterOpenCallbackId);
MMessage::removeCallback(m_AfterImportCallbackId);
}
void rageMayaGeoInstance::InitializeGlobalCallbacks()
{
m_NodeAddedCallbackId = MDGMessage::addNodeAddedCallback(NodeAddedCallback, "rageMayaGeoInstance");
m_BeforeMayaSaveCallbackId = MSceneMessage::addCallback(MSceneMessage::kBeforeSave, BeforeMayaSaveCallback);
m_BeforeOpenCallbackId = MSceneMessage::addCallback(MSceneMessage::kBeforeOpen, BeforeOpenCallback);
m_BeforeNewCallbackId = MSceneMessage::addCallback(MSceneMessage::kBeforeNew, BeforeNewCallback);
m_AfterNewCallbackId = MSceneMessage::addCallback(MSceneMessage::kAfterNew, AfterNewCallback);
}
void rageMayaGeoInstance::UninitializeGlobalCallbacks()
{
MMessage::removeCallback(m_NodeAddedCallbackId);
MMessage::removeCallback(m_BeforeMayaSaveCallbackId);
MMessage::removeCallback(m_BeforeOpenCallbackId);
MMessage::removeCallback(m_BeforeNewCallbackId);
MMessage::removeCallback(m_AfterNewCallbackId);
}
void rageMayaGeoInstance::BeforeMayaSaveCallback(void* /*thisPtr*/)
{
MGlobal::executeCommand("rageGeoInstance.SaveAll()", true);
}
void rageMayaGeoInstance::BeforeOpenCallback(void* /*thisPtr*/)
{
m_bBetweenBeforeSceneOpenAndAfterSceneOpen = true;
}
void rageMayaGeoInstance::AfterOpenCallback(void* thisPtr)
{
m_bBetweenBeforeSceneOpenAndAfterSceneOpen = false;
// Kill myself
rageMayaGeoInstance* pobThis = (rageMayaGeoInstance*)thisPtr;
MGlobal::executeCommandOnIdle("delete "+ MFnDependencyNode(pobThis->thisMObject()).name(), false);
}
void rageMayaGeoInstance::AfterImportCallback(void* thisPtr)
{
m_bBetweenBeforeSceneOpenAndAfterSceneOpen = false;
rageMayaGeoInstance* pobThis = (rageMayaGeoInstance*)thisPtr;
//// Update the container parameters
UpdateContainerParameters(pobThis->thisMObject());
GiveGraphicalRepresentation(pobThis->thisMObject());
}
void rageMayaGeoInstance::BeforeNewCallback(void* /*thisPtr*/)
{
m_bBetweenBeforeSceneOpenAndAfterSceneOpen = true;
}
void rageMayaGeoInstance::AfterNewCallback(void* /*thisPtr*/)
{
m_bBetweenBeforeSceneOpenAndAfterSceneOpen = false;
}
void rageMayaGeoInstance::NodeAddedCallback(MObject& obNode, void* /*thisPtr*/)
{
// Get the type of it
MFnDependencyNode obFnNode(obNode);
MPlug obGeoInstanceTypePlug = obFnNode.findPlug("rageGeoInstanceType");
MString strGeoType;
obGeoInstanceTypePlug.getValue(strGeoType);
if(strGeoType != "")
{
// const char* pcGeoType = strGeoType.asChar();
// cout<<"obGeoInstanceTypePlug = "<<pcGeoType<<endl;
SetToNewInstanceOfType(obNode, strGeoType);
}
obGeoInstanceTypePlug.setLocked(true);
}
MStatus rageMayaGeoInstance::connectionMade(const MPlug& obPlug, const MPlug& obOtherPlug, bool bAsSource)
{
if(rageMayaGeoInstance::ActDumb()) return MStatus::kUnknownParameter;
//printf("rageMayaGeoInstance::connectionMade\n");
//printf("obPlug = %s\n", obPlug.info().asChar());
//printf("obOtherPlug = %s\n", obOtherPlug.info().asChar());
//printf("bAsSource = %d\n", bAsSource);
//_flushall();
if((obPlug == m_obGeoInstanceContainerUIDAttribute) && (!bAsSource))
{
// Something was just connected to my container UID attribute, that means that I am now contained within something else
// Get the UID of the container on the other node
MString strUIDOfContainer;
obOtherPlug.getValue(strUIDOfContainer);
// Get the UID of the other node
MString strUIDOfContainerNode;
MPlug obOtherNodeUIDPlug(obOtherPlug.node(), m_obGeoInstanceUIDAttribute);
obOtherNodeUIDPlug.getValue(strUIDOfContainerNode);
// Get my UID
MString strMyUID;
MPlug obMyUIDPlug(thisMObject(), m_obGeoInstanceUIDAttribute);
obMyUIDPlug.getValue(strMyUID);
//printf("%s is now contained in container %s inside instance %s\n", strMyUID.asChar(), strUIDOfContainer.asChar(), strUIDOfContainerNode.asChar());
//_flushall();
// Move the Instance
MGlobal::executeCommand("GeoMoveInstance \""+ strUIDOfContainerNode +"\" \""+ strUIDOfContainer +"\" \""+ strMyUID +"\"", true, false);
}
return MStatus::kUnknownParameter;
}
MStatus rageMayaGeoInstance::connectionBroken(const MPlug& obPlug, const MPlug& obOtherPlug, bool bAsSource)
{
if(rageMayaGeoInstance::ActDumb()) return MStatus::kUnknownParameter;
//printf("rageMayaGeoInstance::connectionMade\n");
//printf("obPlug = %s\n", obPlug.info().asChar());
//printf("obOtherPlug = %s\n", obOtherPlug.info().asChar());
//printf("bAsSource = %d\n", bAsSource);
//_flushall();
if((obPlug == m_obGeoInstanceContainerUIDAttribute) && (!bAsSource))
{
// Something was just disconnected from my container UID attribute, that means that I am now not contained within something else
// Get the UID of the container on the other node
MString strUIDOfContainer;
obOtherPlug.getValue(strUIDOfContainer);
// Get the UID of the other node
MString strUIDOfContainerNode;
MPlug obOtherNodeUIDPlug(obOtherPlug.node(), m_obGeoInstanceUIDAttribute);
obOtherNodeUIDPlug.getValue(strUIDOfContainerNode);
// Get my UID
MString strMyUID;
MPlug obMyUIDPlug(thisMObject(), m_obGeoInstanceUIDAttribute);
obMyUIDPlug.getValue(strMyUID);
//printf("%s is no longer contained in container %s inside instance %s\n", strMyUID.asChar(), strUIDOfContainer.asChar(), strUIDOfContainerNode.asChar());
//_flushall();
// Move the Instance
MGlobal::executeCommand("GeoMoveInstance \"\" \"\" \""+ strMyUID +"\"", true, false);
}
return MStatus::kUnknownParameter;
}
void rageMayaGeoInstance::NodePreRemovalCallback(MObject& obNode, void* thisPtr)
{
rageMayaGeoInstance* pobThis = (rageMayaGeoInstance*)thisPtr;
if(pobThis->ActDumb()) return;
MString strMyUID;
MPlug obMyUIDPlug(obNode, m_obGeoInstanceUIDAttribute);
obMyUIDPlug.getValue(strMyUID);
// printf("%s is being removed and MFileIO::isReadingFile() = %d\n", strMyUID.asChar(), MFileIO::isReadingFile());
// _flushall();
MGlobal::executeCommand("GeoDeleteInstance -typeid \""+ strMyUID + "\"", true);
}
MStatus rageMayaGeoInstance::legalConnection(const MPlug& obPlug, const MPlug& obOtherPlug, bool bAsSource, bool& bResult ) const
{
//printf("rageMayaGeoInstance::connectionMade\n");
//printf("obPlug = %s\n", obPlug.info().asChar());
//printf("obOtherPlug = %s\n", obOtherPlug.info().asChar());
//printf("bAsSource = %d\n", bAsSource);
//_flushall();
// Unless I specify otherwise, connections are allowed so the default is...
bResult = true;
// Next check if it is a case I don't allow
if((obPlug == m_obGeoInstanceContainerUIDAttribute) && (!bAsSource))
{
// Something was just connected to my container UID attribute, that means that I am now contained within something else
// Get the UID of the container on the other node
MString strUIDOfContainer;
obOtherPlug.getValue(strUIDOfContainer);
// Get the UID of the other node
MString strUIDOfContainerNode;
MPlug obOtherNodeUIDPlug(obOtherPlug.node(), m_obGeoInstanceUIDAttribute);
obOtherNodeUIDPlug.getValue(strUIDOfContainerNode);
// Get my UID
MString strMyUID;
MPlug obMyUIDPlug(thisMObject(), m_obGeoInstanceUIDAttribute);
obMyUIDPlug.getValue(strMyUID);
//printf("Testing to see if %s can be contained in container %s inside instance %s\n", strMyUID.asChar(), strUIDOfContainer.asChar(), strUIDOfContainerNode.asChar());
//_flushall();
// Is it legal?
int bLegal = true;
MGlobal::executeCommand("GeoCanContainerHoldGeoInstance \""+ strUIDOfContainerNode +"\" \""+ strUIDOfContainer +"\" \""+ strMyUID +"\"", bLegal, true, false);
bResult = (bLegal != 0);
}
return MStatus::kSuccess;
}
void rageMayaGeoInstance::UpdateContainerParameters(const MObject& obNode)
{
// Get UID
// Get my UID
MString strMyUID;
MPlug obMyUIDPlug(obNode, m_obGeoInstanceUIDAttribute);
obMyUIDPlug.getValue(strMyUID);
//const char* pcUID = strMyUID.asChar();
//cout<<"Got UID attribute as : "<<pcUID<<endl;
// Do I have a valid UID?
if(strMyUID != "")
{
// Add container attributes
// Get the list of container attributes
MStringArray astrContainerNames;
MGlobal::executeCommand("GeoGetInstanceContainerNamesFromUUID \""+ strMyUID +"\"", astrContainerNames, true);
MStringArray astrContainerUUIDs;
MGlobal::executeCommand("GeoGetInstanceContainerUUIDsFromUUID \""+ strMyUID +"\"", astrContainerUUIDs, true);
if(astrContainerNames.length() > 0)
{
// I have containers, so add them
// Add one attribute for each container, for connection purposes
MFnDependencyNode obFnThisNode(obNode);
for(unsigned i=0; i<astrContainerNames.length(); i++)
{
// Get UI safe name
MString strContainerName;
MGlobal::executeCommand("rageValidateGEONameUI(\""+ astrContainerNames[i] +"\")", strContainerName, true);
// Do I already have this container attribute
if(obFnThisNode.findPlug("rageGeoContainer_"+ strContainerName).isNull())
{
// Add the attribute
MFnTypedAttribute nAttr;
MStatus status;
MObject obAttribute = nAttr.create( "rageGeoContainer_"+ strContainerName, "rageGeoContainer_"+ strContainerName +"s", MFnData::kString, MObject::kNullObj, &status );
nAttr.setStorable( true );
nAttr.setHidden( true );
nAttr.setReadable( true );
nAttr.setWritable( true );
nAttr.setInternal( false );
MDGModifier obModifier;
obModifier.addAttribute(obNode, obAttribute);
obModifier.doIt();
// Set the value
MPlug obContainerPlug(obNode, obAttribute);
// Displayf("Setting value of container attribute %s to be %s", obContainerPlug.name().asChar(), astrContainerUUIDs[i].asChar());
obContainerPlug.setValue(astrContainerUUIDs[i]);
}
}
}
}
}
// ActDumb is used to turn off all the clever interfacing with the GEO Dataset, this is required to manipulate the nodes when loading scenes
bool rageMayaGeoInstance::ActDumb()
{
if(OldSceneIsBeingCleared()) return true;
if(NewSceneIsBeingOpened()) return true;
if(MFileIO::isReadingFile()) return true;
if(m_bNodeWasCreatedDuringFileOpenSoKillMe) return true;
// int bActDumb;
// MGlobal::executeCommand("rageGeoInstance.ActDumb()", bActDumb, true);
// if(bActDumb) return true;
return false;
}
void rageMayaGeoInstance::SetToNewInstanceOfType(const MObject& obNode, const MString& strGeoType)
{
// Get plugs
MStatus obStatus;
MFnDependencyNode obFnNode(obNode);
MPlug obGeoInstanceUIDPlug = obFnNode.findPlug("rageGeoInstanceUID");
MPlug obGeoInstanceNamePlug = obFnNode.findPlug("rageGeoInstanceName");
MPlug obGeoInstanceTypePlug = obFnNode.findPlug("rageGeoInstanceType");
// Create new GEO Instance
MStringArray astrNewNameAndUUID;
MGlobal::executeCommand("GeoCreateInstanceOfType \""+ strGeoType +"\"", astrNewNameAndUUID, true, false);
// Set Attrs
MString strType = strGeoType;
obGeoInstanceUIDPlug.setLocked(false);
obGeoInstanceNamePlug.setLocked(false);
obGeoInstanceTypePlug.setLocked(false);
obGeoInstanceNamePlug.setValue(astrNewNameAndUUID[0]);
obGeoInstanceUIDPlug.setValue(astrNewNameAndUUID[1]);
obGeoInstanceTypePlug.setValue(strType);
obGeoInstanceUIDPlug.setLocked(true);
obGeoInstanceNamePlug.setLocked(true);
obGeoInstanceTypePlug.setLocked(true);
// Update the container parameters
UpdateContainerParameters(obNode);
// Update the graphical representation
GiveGraphicalRepresentation(obNode);
}
void rageMayaGeoInstance::HuntColladaFiles(const MString& obFolder, MStringArray& astrColladaFiles)
{
// Get all the Collada files in this folder
LPWIN32_FIND_DATAA pData = new WIN32_FIND_DATAA();
char acSearchString[512];
strcpy_s(acSearchString, obFolder.asChar());
strcat_s(acSearchString, "/*.dae");
HANDLE fHandle = FindFirstFileA(acSearchString, pData);
while(fHandle != INVALID_HANDLE_VALUE)
{
if( (pData->cFileName[0] != '.') &&
(!(pData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) )
{
// Bingo! Found a collada file
astrColladaFiles.append(obFolder +"/"+ pData->cFileName);
}
if(!FindNextFileA(fHandle, pData))
{
break;
}
}
// Recurse
strcpy_s(acSearchString, obFolder.asChar());
strcat_s(acSearchString, "/*");
fHandle = FindFirstFileA(acSearchString, pData);
while(fHandle != INVALID_HANDLE_VALUE)
{
if((pData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (pData->cFileName[0] != '.'))
{
// Bingo! Found a folder
HuntColladaFiles(obFolder +"/"+ pData->cFileName, astrColladaFiles);
}
if(!FindNextFileA(fHandle, pData))
{
break;
}
}
delete pData;
}
void rageMayaGeoInstance::GiveGraphicalRepresentation(const MObject& obNode)
{
MStatus obStatus;
MFnDependencyNode obFnNode(obNode);
// Get type
MPlug obGeoInstanceTypePlug = obFnNode.findPlug("rageGeoInstanceType");
MString strGeoType;
obGeoInstanceTypePlug.getValue(strGeoType);
// cout<<"strGeoType = "<<strGeoType.asChar()<<endl;
// Is there a proxy?
MStringArray astrColladaFiles;
MString strBaseGeoFolder = rageGeoDataSetCommands::GetBaseGeoFolder();
// cout<<"strBaseGeoFolder = "<<strBaseGeoFolder.asChar()<<endl;
MString strProxyFile = strBaseGeoFolder +"GEOInstanceProxies/"+ strGeoType +".dae";
MFileObject obProxyFile;
obProxyFile.setFullName(strProxyFile);
if(obProxyFile.exists())
{
// Got a proxy file, so use it
astrColladaFiles.append(strProxyFile);
}
else
{
// No proxy found, so look elsewhere
HuntColladaFiles(strBaseGeoFolder +"GEOTypes/"+ strGeoType, astrColladaFiles);
}
// Add all the collada file
for(unsigned int c=0; c<astrColladaFiles.length(); c++)
{
// Create node
MDagModifier obDagModifier;
MObject obColladaNode = obDagModifier.createNode("rageMayaColladaLocator", obNode);
obDagModifier.doIt();
// Set attr
MFnDependencyNode obFnColladaNode(obColladaNode);
MPlug obColladaPathAndFilenamePlug = obFnColladaNode.findPlug("ColladaPathAndFilename");
obColladaPathAndFilenamePlug.setValue(astrColladaFiles[c]);
}
// Finally layer me
MString strGeoTemplateName = rageGeoDataSetCommands::GetTemplateNameFromTypeName(strGeoType);
// Does a layer exist with this name?
MObject obLayerNode = MObject::kNullObj;
for(MItDependencyNodes obIt(MFn::kDisplayLayer); !obIt.isDone(); obIt.next())
{
// Does it have a GEO template attribute?
MPlug obGeoTemplatePlug = MFnDependencyNode(obIt.item()).findPlug("rageGeoTemplateLayer");
if(!obGeoTemplatePlug.isNull())
{
// Got the attribute, do I care?
MString strGeoTemplateOnThisLayer;
obGeoTemplatePlug.getValue(strGeoTemplateOnThisLayer);
if(strGeoTemplateOnThisLayer == strGeoTemplateName)
{
// Bingo!
obLayerNode = obIt.item();
break;
}
}
}
if(obLayerNode == MObject::kNullObj)
{
// No layer found, so create one
MString strLayerNodeName;
MGlobal::executeCommand("createDisplayLayer -name \""+ strGeoTemplateName +"\" -empty", strLayerNodeName, true);
MSelectionList obTempSelectionList;
obStatus = obTempSelectionList.add(strLayerNodeName);
obStatus = obTempSelectionList.getDependNode(0, obLayerNode);
// Add the attribute
MFnTypedAttribute nAttr;
MStatus status;
MObject obAttribute = nAttr.create( "rageGeoTemplateLayer", "rageGTempLayer", MFnData::kString, MObject::kNullObj, &status );
nAttr.setStorable( true );
nAttr.setHidden( true );
nAttr.setReadable( true );
nAttr.setWritable( true );
nAttr.setInternal( false );
MDGModifier obModifier;
obModifier.addAttribute(obLayerNode, obAttribute);
obModifier.doIt();
// Set the value
MPlug obGeoTemplatePlug = MFnDependencyNode(obLayerNode).findPlug("rageGeoTemplateLayer");
obGeoTemplatePlug.setValue(strGeoTemplateName);
// Give it a random colour
MPlug obColourPlug = MFnDependencyNode(obLayerNode).findPlug("color");
int iRandomColor = 4 + (rand() % 27);
// cout<<"iRandomColor = "<<iRandomColor<<endl;
obColourPlug.setValue(iRandomColor);
}
// Add this geo to the layer
MGlobal::executeCommand("editDisplayLayerMembers -noRecurse "+ MFnDependencyNode(obLayerNode).name() +" {\""+ obFnNode.name() +"\"}", true);
}