Alembic::Abc::IObject getObjectFromArchive(XSI::CString path, XSI::CString identifier) { Alembic::Abc::IArchive * archive = getArchiveFromID(path); if(archive == NULL) return Alembic::Abc::IObject(); // split the path std::string stdIdentifier(identifier.GetAsciiString()); std::vector<std::string> parts; boost::split(parts, stdIdentifier, boost::is_any_of("/")); // recurse to find it Alembic::Abc::IObject obj = archive->getTop(); for(size_t i=1;i<parts.size();i++) { Alembic::Abc::IObject child(obj,parts[i]); obj = child; } return obj; }
//-***************************************************************************** int main( int argc, char *argv[] ) { //float opt_fps = 24.0; bool opt_all = false; // show all option bool opt_long = false; // long listing option bool opt_meta = false; // metadata option bool opt_recursive = false; // recursive option bool opt_size = false; // array sample size option bool opt_time = false; // time info option bool opt_values = false; // show all 0th values int index = -1; // sample number, at tail of path std::string desc( "abcls [OPTION] FILE[/NAME] \n" " -a include property listings\n" " -f show time sampling as 24 fps\n" " -h, --help show this help message\n" " -l long listing format\n" " -m show archive metadata\n" " -r list entries recursively\n" " -s show the size of a data property sample\n" " -t show time sampling information\n" " -v show 0th value for all properties\n" ); /* sigaction if available */ #if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 199506L) // seg fault handler struct sigaction act; sigemptyset(&act.sa_mask); act.sa_handler = segfault_sigaction; act.sa_flags = SA_SIGINFO; sigaction(SIGSEGV, &act, NULL); /* signal if available */ #elif defined(_POSIX_VERSION) || defined(_MSC_VER) signal(SIGSEGV, segfault_sigaction); #else #error No signal interface available #endif //_POSIX_VERSION // check for min args if ( argc < 2 ) { std::cout << desc << std::endl; return 0; }; // parse args std::vector<std::string> arguments(argv, argv + argc); std::vector<std::string> options; std::vector<std::string> files; // separate file args from option args for ( std::size_t i = 1; i < arguments.size(); i++ ) { if ( arguments[ i ].substr( 0, 1 ) == "-" ) options.push_back( arguments[ i ] ); else files.push_back( arguments[ i ] ); } // help if ( argc < 2 || optionExists( options, "h" ) || optionExists( options, "help" ) ) { std::cout << desc << std::endl; return 0; }; // set some flags double fps = 1.0; opt_all = optionExists( options, "a" ); opt_long = optionExists( options, "l" ); opt_meta = optionExists( options, "m" ); opt_recursive = optionExists( options, "r" ); opt_size = optionExists( options, "s" ); opt_time = optionExists( options, "t" ); opt_values = optionExists( options, "v" ); if ( optionExists( options, "f" ) ) { fps = 24.0; opt_time = true; } // open each file for ( std::size_t i = 0; i < files.size(); i++ ) { if ( files.size() > 1 ) std::cout << BOLD << files[i] << ':' << RESETCOLOR << std::endl; std::stringstream ss( files[i] ); std::stringstream fp; std::string segment; std::vector<std::string> seglist; /* * separate file and object paths, e.g. * * ../dir1/foo.abc/bar/baz/index * \_____________/\______/\____/ * file obj sample */ int j = 0; while ( std::getline( ss, segment, '/' ) ) { if ( !isFile ( fp.str() ) ) { if ( j != 0 ) fp << "/"; fp << segment; } else { seglist.push_back( segment ); } ++j; } bool lastIsIndex = false; if (!seglist.empty() && is_digit( seglist.back() ) ) { index = atoi( seglist.back().c_str() ); lastIsIndex = true; } // open the iarchive Abc::IArchive archive; AbcF::IFactory factory; factory.setPolicy(Abc::ErrorHandler::kQuietNoopPolicy); AbcF::IFactory::CoreType coreType; archive = factory.getArchive(std::string( fp.str() ), coreType); // display file metadata if ( opt_meta && seglist.size() == 0 ) { std::cout << "Using " << Alembic::AbcCoreAbstract::GetLibraryVersion() << std::endl;; std::string appName; std::string libraryVersionString; Alembic::Util::uint32_t libraryVersion; std::string whenWritten; std::string userDescription; std::string coreName; GetArchiveInfo (archive, appName, libraryVersionString, libraryVersion, whenWritten, userDescription); if ( coreType == AbcF::IFactory::kOgawa ) { coreName = "Ogawa"; } else if ( coreType == AbcF::IFactory::kHDF5 ) { coreName = "HDF5"; } else { coreName = "Unknown"; }; if ( appName != "" ) { std::cout << " file written by: " << appName << std::endl; std::cout << " using Alembic : " << libraryVersionString << std::endl; std::cout << " written on : " << whenWritten << std::endl; std::cout << " user description : " << userDescription << std::endl; } else { std::cout << " (file doesn't have any ArchiveInfo)" << std::endl; } std::cout << " core type : " << coreName << std::endl; }; if ( opt_time && seglist.size() == 0 ) { uint32_t numTimes = archive.getNumTimeSamplings(); std::cout << std::endl << "Time Samplings: " << std::endl; for ( uint32_t k = 0; k < numTimes; ++k ) { AbcA::TimeSamplingPtr ts = archive.getTimeSampling( k ); index_t maxSample = archive.getMaxNumSamplesForTimeSamplingIndex( k ); std::cout << k << " "; printTimeSampling( ts, maxSample, fps ); } std::cout << std::endl; } // walk object hierarchy and find valid objects AbcG::IObject test = archive.getTop(); AbcG::IObject iObj = test; while ( test.valid() && seglist.size() > 0 ) { test = test.getChild( seglist.front() ); if ( test.valid() ) { iObj = test; seglist.erase( seglist.begin() ); } } // walk property hierarchy for most recent object Abc::ICompoundProperty props = iObj.getProperties(); const Abc::PropertyHeader* header; bool found = false; bool shouldPrintValue = false; for ( std::size_t i = 0; i < seglist.size(); ++i ) { header = props.getPropertyHeader( seglist[i] ); if ( header && header->isCompound() ) { Abc::ICompoundProperty ptest( props, header->getName() ); if ( ptest.valid() ) { props = ptest; found = true; } } else if ( header && header->isSimple() ) { found = true; // if the last value happens to be an index, and we are a // property then dont bother checking the last item in seglist if (lastIsIndex && i == seglist.size() - 2) { shouldPrintValue = true; break; } } else { std::cout << seglist[i] << ": Invalid object or property" << std::endl; return 1; } } // do stuff if ( shouldPrintValue ) { printValue( props, *header, index, opt_size, opt_time, fps ); } else { if ( found && header->isCompound() ) visit( props, opt_all, opt_long, opt_meta, opt_recursive, true, opt_values ); else if ( found && header->isSimple() ) printChild( props, *header, opt_all, opt_long, opt_values ); else visit( iObj, opt_all, opt_long, opt_meta, opt_recursive, true, opt_values ); std::cout << RESETCOLOR; if ( !opt_long ) std::cout << std::endl; } } return 0; }
int main(int argc, char *argv[]) { std::string toType; std::string inFile; std::string outFile; std::string forceStr; if (argc == 4) { toType = argv[1]; inFile = argv[2]; outFile = argv[3]; } else if (argc == 5) { forceStr = argv[1]; toType = argv[2]; inFile = argv[3]; outFile = argv[4]; } if ((argc == 4 || argc == 5) && (forceStr.empty() || forceStr == "-force")) { if (inFile == outFile) { printf("Error: inFile and outFile must not be the same!\n"); return 1; } if (toType != "-toHDF" && toType != "-toOgawa") { printf("Error: Unknown conversion type specified %s\n", toType.c_str()); printf("Currently only -toHDF and -toOgawa are supported.\n"); return 1; } Alembic::AbcCoreFactory::IFactory factory; Alembic::AbcCoreFactory::IFactory::CoreType coreType; Alembic::Abc::IArchive archive = factory.getArchive(inFile, coreType); if (!archive.valid()) { printf("Error: Invalid Alembic file specified: %s\n", inFile.c_str()); return 1; } else if ( forceStr != "-force" && ( (coreType == Alembic::AbcCoreFactory::IFactory::kHDF5 && toType == "-toHDF") || (coreType == Alembic::AbcCoreFactory::IFactory::kOgawa && toType == "-toOgawa")) ) { printf("Warning: Alembic file specified: %s\n",inFile.c_str()); printf("is already of the type you want to convert to.\n"); printf("Please specify -force if you want to do this anyway.\n"); return 1; } Alembic::Abc::IObject inTop = archive.getTop(); Alembic::Abc::OArchive outArchive; if (toType == "-toHDF") { outArchive = Alembic::Abc::OArchive( Alembic::AbcCoreHDF5::WriteArchive(), outFile, inTop.getMetaData(), Alembic::Abc::ErrorHandler::kThrowPolicy); } else if (toType == "-toOgawa") { outArchive = Alembic::Abc::OArchive( Alembic::AbcCoreOgawa::WriteArchive(), outFile, inTop.getMetaData(), Alembic::Abc::ErrorHandler::kThrowPolicy); } // start at 1, we don't need to worry about intrinsic default case for (Alembic::Util::uint32_t i = 1; i < archive.getNumTimeSamplings(); ++i) { outArchive.addTimeSampling(*archive.getTimeSampling(i)); } Alembic::Abc::OObject outTop = outArchive.getTop(); copyObject(inTop, outTop); return 0; } printf ("Usage: abcconvert [-force] OPTION inFile outFile\n"); printf ("Used to convert an Alembic file from one type to another.\n\n"); printf ("If -force is not provided and inFile happens to be the same\n"); printf ("type as OPTION no conversion will be done and a message will\n"); printf ("be printed out.\n"); printf ("OPTION has to be one of these:\n\n"); printf (" -toHDF Convert to HDF.\n"); printf (" -toOgawa Convert to Ogawa.\n"); return 1; }
MStatus AlembicNode::compute(const MPlug & plug, MDataBlock & dataBlock) { MStatus status; // update the frame number to be imported MDataHandle speedHandle = dataBlock.inputValue(mSpeedAttr, &status); double speed = speedHandle.asDouble(); MDataHandle offsetHandle = dataBlock.inputValue(mOffsetAttr, &status); double offset = offsetHandle.asDouble(); MDataHandle timeHandle = dataBlock.inputValue(mTimeAttr, &status); MTime t = timeHandle.asTime(); double inputTime = t.as(MTime::kSeconds); double fps = getFPS(); // scale and offset inputTime. inputTime = computeAdjustedTime(inputTime, speed, offset/fps); // this should be done only once per file if (mFileInitialized == false) { mFileInitialized = true; //Get list of input filenames MFnDependencyNode depNode(thisMObject()); MPlug layerFilesPlug = depNode.findPlug("abc_layerFiles"); MFnStringArrayData fnSAD( layerFilesPlug.asMObject() ); MStringArray storedFilenames = fnSAD.array(); //Legacy support for single-filename input if( storedFilenames.length() == 0 ) { MFileObject fileObject; MDataHandle dataHandle = dataBlock.inputValue(mAbcFileNameAttr); fileObject.setRawFullName(dataHandle.asString()); MString fileName = fileObject.resolvedFullName(); storedFilenames.append( fileName ); } std::vector<std::string> abcFilenames; for(unsigned int i = 0; i < storedFilenames.length(); i++) abcFilenames.push_back( storedFilenames[i].asChar() ); Alembic::Abc::IArchive archive; Alembic::AbcCoreFactory::IFactory factory; factory.setPolicy(Alembic::Abc::ErrorHandler::kQuietNoopPolicy); archive = factory.getArchive( abcFilenames ); if (!archive.valid()) { MString theError = "Error opening these alembic files: "; const unsigned int numFilenames = storedFilenames.length(); for( unsigned int i = 0; i < numFilenames; i++ ) { theError += storedFilenames[ i ]; if( i != (numFilenames - 1) ) theError += ", "; } printError(theError); } // initialize some flags for plug update mSubDInitialized = false; mPolyInitialized = false; // When an alembic cache will be imported at the first time using // AbcImport, we need to set mIncludeFilterAttr (filterHandle) to be // mIncludeFilterString for later use. When we save a maya scene(.ma) // mIncludeFilterAttr will be saved. Then when we load the saved // .ma file, mIncludeFilterString will be set to be mIncludeFilterAttr. MDataHandle includeFilterHandle = dataBlock.inputValue(mIncludeFilterAttr, &status); MString& includeFilterString = includeFilterHandle.asString(); if (mIncludeFilterString.length() > 0) { includeFilterHandle.set(mIncludeFilterString); dataBlock.setClean(mIncludeFilterAttr); } else if (includeFilterString.length() > 0) { mIncludeFilterString = includeFilterString; } MDataHandle excludeFilterHandle = dataBlock.inputValue(mExcludeFilterAttr, &status); MString& excludeFilterString = excludeFilterHandle.asString(); if (mExcludeFilterString.length() > 0) { excludeFilterHandle.set(mExcludeFilterString); dataBlock.setClean(mExcludeFilterAttr); } else if (excludeFilterString.length() > 0) { mExcludeFilterString = excludeFilterString; } MFnDependencyNode dep(thisMObject()); MPlug allSetsPlug = dep.findPlug("allColorSets"); CreateSceneVisitor visitor(inputTime, !allSetsPlug.isNull(), MObject::kNullObj, CreateSceneVisitor::NONE, "", mIncludeFilterString, mExcludeFilterString); visitor.walk(archive); if (visitor.hasSampledData()) { // information retrieved from the hierarchy traversal // and given to AlembicNode to provide update visitor.getData(mData); mData.getFrameRange(mSequenceStartTime, mSequenceEndTime); MDataHandle startFrameHandle = dataBlock.inputValue(mStartFrameAttr, &status); startFrameHandle.set(mSequenceStartTime*fps); MDataHandle endFrameHandle = dataBlock.inputValue(mEndFrameAttr, &status); endFrameHandle.set(mSequenceEndTime*fps); } } // Retime MDataHandle cycleHandle = dataBlock.inputValue(mCycleTypeAttr, &status); short playType = cycleHandle.asShort(); inputTime = computeRetime(inputTime, mSequenceStartTime, mSequenceEndTime, playType); clamp<double>(mSequenceStartTime, mSequenceEndTime, inputTime); // update only when the time lapse is big enough if (fabs(inputTime - mCurTime) > 0.00001) { mOutRead = std::vector<bool>(mOutRead.size(), false); mCurTime = inputTime; } if (plug == mOutPropArrayAttr) { if (mOutRead[0]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[0] = true; unsigned int propSize = static_cast<unsigned int>(mData.mPropList.size()); if (propSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutPropArrayAttr, &status); unsigned int outHandleIndex = 0; MDataHandle outHandle; // for all of the nodes with sampled attributes for (unsigned int i = 0; i < propSize; i++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(); } else { continue; } if (mData.mPropList[i].mArray.valid()) { readProp(mCurTime, mData.mPropList[i].mArray, outHandle); } else if (mData.mPropList[i].mScalar.valid()) { // for visibility only if (mData.mPropList[i].mScalar.getName() == Alembic::AbcGeom::kVisibilityPropertyName) { Alembic::Util::int8_t visVal = 1; mData.mPropList[i].mScalar.get(&visVal, Alembic::Abc::ISampleSelector(mCurTime, Alembic::Abc::ISampleSelector::kNearIndex )); outHandle.setGenericBool(visVal != 0, false); } else { // for all scalar props readProp(mCurTime, mData.mPropList[i].mScalar, outHandle); } } outArrayHandle.next(); } outArrayHandle.setAllClean(); } } else if (plug == mOutTransOpArrayAttr ) { if (mOutRead[1]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[1] = true; unsigned int xformSize = static_cast<unsigned int>(mData.mXformList.size()); if (xformSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutTransOpArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutTransOpArrayAttr); MDataHandle outHandle; unsigned int outHandleIndex = 0; for (unsigned int i = 0; i < xformSize; i++) { std::vector<double> sampleList; if (mData.mIsComplexXform[i]) { readComplex(mCurTime, mData.mXformList[i], sampleList); } else { Alembic::AbcGeom::XformSample samp; read(mCurTime, mData.mXformList[i], sampleList, samp); } unsigned int sampleSize = (unsigned int)sampleList.size(); for (unsigned int j = 0; j < sampleSize; j++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(&status); } else continue; outArrayHandle.next(); outHandle.set(sampleList[j]); } } outArrayHandle.setAllClean(); } } else if (plug == mOutLocatorPosScaleArrayAttr ) { if (mOutRead[8]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[8] = true; unsigned int locSize = static_cast<unsigned int>(mData.mLocList.size()); if (locSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutLocatorPosScaleArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutLocatorPosScaleArrayAttr); MDataHandle outHandle; unsigned int outHandleIndex = 0; for (unsigned int i = 0; i < locSize; i++) { std::vector< double > sampleList; read(mCurTime, mData.mLocList[i], sampleList); unsigned int sampleSize = (unsigned int)sampleList.size(); for (unsigned int j = 0; j < sampleSize; j++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(&status); } else continue; outArrayHandle.next(); outHandle.set(sampleList[j]); } } outArrayHandle.setAllClean(); } } else if (plug == mOutSubDArrayAttr) { if (mOutRead[2]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutSubDArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[2] = true; unsigned int subDSize = static_cast<unsigned int>(mData.mSubDList.size()); if (subDSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutSubDArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < subDSize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFnMesh fnMesh(obj); readSubD(mCurTime, fnMesh, obj, mData.mSubDList[j], mSubDInitialized); outHandle.set(obj); } } mSubDInitialized = true; outArrayHandle.setAllClean(); } // for the case where we don't have any nodes, we want to make sure // to push out empty meshes on our connections, this can happen if // the input file was offlined, currently we only need to do this for // meshes as Nurbs, curves, and the other channels don't crash Maya else { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutSubDArrayAttr, &status); if (outArrayHandle.elementCount() > 0) { do { MDataHandle outHandle = outArrayHandle.outputValue(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFloatPointArray emptyVerts; MIntArray emptyCounts; MIntArray emptyConnects; MFnMesh emptyMesh; emptyMesh.create(0, 0, emptyVerts, emptyCounts, emptyConnects, obj); outHandle.set(obj); } } while (outArrayHandle.next() == MS::kSuccess); } mSubDInitialized = true; outArrayHandle.setAllClean(); } } else if (plug == mOutPolyArrayAttr) { if (mOutRead[3]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutPolyArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[3] = true; unsigned int polySize = static_cast<unsigned int>(mData.mPolyMeshList.size()); if (polySize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutPolyArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < polySize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFnMesh fnMesh(obj); readPoly(mCurTime, fnMesh, obj, mData.mPolyMeshList[j], mPolyInitialized); outHandle.set(obj); } } mPolyInitialized = true; outArrayHandle.setAllClean(); } // for the case where we don't have any nodes, we want to make sure // to push out empty meshes on our connections, this can happen if // the input file was offlined, currently we only need to do this for // meshes as Nurbs, curves, and the other channels don't crash Maya else { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutPolyArrayAttr, &status); if (outArrayHandle.elementCount() > 0) { do { MDataHandle outHandle = outArrayHandle.outputValue(&status); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFloatPointArray emptyVerts; MIntArray emptyCounts; MIntArray emptyConnects; MFnMesh emptyMesh; emptyMesh.create(0, 0, emptyVerts, emptyCounts, emptyConnects, obj); outHandle.set(obj); } } while (outArrayHandle.next() == MS::kSuccess); } mPolyInitialized = true; outArrayHandle.setAllClean(); } } else if (plug == mOutCameraArrayAttr) { if (mOutRead[4]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[4] = true; unsigned int cameraSize = static_cast<unsigned int>(mData.mCameraList.size()); if (cameraSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutCameraArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutCameraArrayAttr); double angleConversion = 1.0; switch (MAngle::uiUnit()) { case MAngle::kRadians: angleConversion = 0.017453292519943295; break; case MAngle::kAngMinutes: angleConversion = 60.0; break; case MAngle::kAngSeconds: angleConversion = 3600.0; break; default: break; } MDataHandle outHandle; unsigned int index = 0; for (unsigned int cameraIndex = 0; cameraIndex < cameraSize; cameraIndex++) { Alembic::AbcGeom::ICamera & cam = mData.mCameraList[cameraIndex]; std::vector<double> array; read(mCurTime, cam, array); for (unsigned int dataIndex = 0; dataIndex < array.size(); dataIndex++, index++) { // skip over sparse elements if (index != outArrayHandle.elementIndex()) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); // not shutter angle index, so not an angle if (dataIndex != 11) { outHandle.set(array[dataIndex]); } else { outHandle.set(array[dataIndex] * angleConversion); } } // for the per camera data handles } // for each camera outArrayHandle.setAllClean(); } } else if (plug == mOutNurbsSurfaceArrayAttr) { if (mOutRead[5]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[5] = true; unsigned int nSurfaceSize = static_cast<unsigned int>(mData.mNurbsList.size()); if (nSurfaceSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < nSurfaceSize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) continue; outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kNurbsSurface)) { readNurbs(mCurTime, mData.mNurbsList[j], obj); outHandle.set(obj); } } outArrayHandle.setAllClean(); } } else if (plug == mOutNurbsCurveGrpArrayAttr) { if (mOutRead[6]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[6] = true; unsigned int nCurveGrpSize = static_cast<unsigned int>(mData.mCurvesList.size()); if (nCurveGrpSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status); MDataHandle outHandle; std::vector<MObject> curvesObj; for (unsigned int i = 0; i < nCurveGrpSize; ++i) { readCurves(mCurTime, mData.mCurvesList[i], mData.mNumCurves[i], curvesObj); } std::size_t numChild = curvesObj.size(); // not the best way to do this // only reading bunches of curves based on the connections would be // more efficient when there is a bunch of broken connections for (unsigned int i = 0; i < numChild; i++) { if (outArrayHandle.elementIndex() != i) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); status = outHandle.set(curvesObj[i]); } outArrayHandle.setAllClean(); } } else { return MS::kUnknownParameter; } dataBlock.setClean(plug); return status; }
int main(int argc, char *argv[]) { ConversionOptions options; bool doConversion = false; if (parseArgs( argc, argv, options, doConversion ) == false) return 1; if (doConversion) { for( std::vector<std::string>::const_iterator inFile = options.inFiles.begin(); inFile != options.inFiles.end(); inFile++ ) { if (*inFile == options.outFile) { printf("Error: inFile and outFile must not be the same!\n"); return 1; } } if (options.toType != IFactoryNS::kHDF5 && options.toType != IFactoryNS::kOgawa) { printf("Currently only -toHDF and -toOgawa are supported.\n"); return 1; } Alembic::AbcCoreFactory::IFactory factory; Alembic::AbcCoreFactory::IFactory::CoreType coreType; Alembic::Abc::IArchive archive; if(options.inFiles.size() == 1) { archive = factory.getArchive(*options.inFiles.begin(), coreType); if (!archive.valid()) { printf("Error: Invalid Alembic file specified: %s\n", options.inFiles.begin()->c_str()); return 1; } else if ( !options.force && ( (coreType == IFactoryNS::kHDF5 && options.toType == IFactoryNS::kHDF5) || (coreType == IFactoryNS::kOgawa && options.toType == IFactoryNS::kOgawa)) ) { printf("Warning: Alembic file specified: %s\n", options.inFiles.begin()->c_str()); printf("is already of the type you want to convert to.\n"); printf("Please specify -force if you want to do this anyway.\n"); return 1; } } else { archive = factory.getArchive(options.inFiles, coreType); } Alembic::Abc::IObject inTop = archive.getTop(); Alembic::Abc::OArchive outArchive; if (options.toType == IFactoryNS::kHDF5) { outArchive = Alembic::Abc::OArchive( Alembic::AbcCoreHDF5::WriteArchive(), options.outFile, inTop.getMetaData(), Alembic::Abc::ErrorHandler::kThrowPolicy); } else if (options.toType == IFactoryNS::kOgawa) { outArchive = Alembic::Abc::OArchive( Alembic::AbcCoreOgawa::WriteArchive(), options.outFile, inTop.getMetaData(), Alembic::Abc::ErrorHandler::kThrowPolicy); } // start at 1, we don't need to worry about intrinsic default case for (Alembic::Util::uint32_t i = 1; i < archive.getNumTimeSamplings(); ++i) { outArchive.addTimeSampling(*archive.getTimeSampling(i)); } Alembic::Abc::OObject outTop = outArchive.getTop(); copyObject(inTop, outTop); } return 0; }
//-***************************************************************************** int main( int argc, char *argv[] ) { bool opt_all = false; bool opt_meta = false; std::string desc( "abctree [OPTION] FILE[/NAME]\n" " -a include properties listings\n" " -h, --help prints this help message\n" " -m print metadata\n" ); // check for min args if ( argc < 2 ) { std::cout << desc << std::endl; return 0; }; // parse args std::vector<std::string> arguments(argv, argv + argc); std::vector<std::string> options; std::vector<std::string> files; // separate file args from option args for ( std::size_t i = 1; i < arguments.size(); i++ ) { if ( arguments[ i ].substr( 0, 1 ) == "-" ) options.push_back( arguments[ i ] ); else files.push_back( arguments[ i ] ); } // help if ( argc < 2 || optionExists( options, "h" ) || optionExists( options, "help" ) ) { std::cout << desc << std::endl; return 0; }; // set some flags opt_all = optionExists( options, "a"); opt_meta = optionExists( options, "m"); // open each file size_t count = 0; for ( std::size_t i = 0; i < files.size(); i++ ) { if ( files.size() > 1 ) std::cout << BOLD << files[i] << ':' << RESETCOLOR << std::endl; std::stringstream ss( files[i] ); std::stringstream fp; std::string segment; std::vector<std::string> seglist; /* * separate file and object paths, e.g. * * ../dir1/foo.abc/bar/baz * \_____________/\______/ * file obj */ int j = 0; while ( std::getline( ss, segment, '/' ) ) { if ( !isFile ( fp.str() ) ) { if ( j != 0 ) fp << "/"; fp << segment; } else { seglist.push_back( segment ); } ++j; } // open the iarchive Abc::IArchive archive; AbcF::IFactory factory; factory.setPolicy(Abc::ErrorHandler::kQuietNoopPolicy); AbcF::IFactory::CoreType coreType; archive = factory.getArchive(std::string( fp.str() ), coreType); // display file metadata if ( opt_meta ) { std::cout << "Using " << Alembic::AbcCoreAbstract::GetLibraryVersion () << std::endl;; std::string appName; std::string libraryVersionString; Alembic::Util::uint32_t libraryVersion; std::string whenWritten; std::string userDescription; std::string coreName; GetArchiveInfo (archive, appName, libraryVersionString, libraryVersion, whenWritten, userDescription); if ( coreType == AbcF::IFactory::kOgawa ) { coreName = "Ogawa"; } else if ( coreType == AbcF::IFactory::kHDF5 ) { coreName = "HDF5"; } else { coreName = "Unknown"; }; if ( appName != "" ) { std::cout << " file written by: " << appName << std::endl; std::cout << " using Alembic : " << libraryVersionString << std::endl; std::cout << " written on : " << whenWritten << std::endl; std::cout << " user description : " << userDescription << std::endl; } else { std::cout << " (file doesn't have any ArchiveInfo)" << std::endl; } std::cout << " core type : " << coreName << std::endl; }; // walk object hierarchy and find valid objects AbcG::IObject test = archive.getTop(); AbcG::IObject iObj = test; while ( test.valid() && seglist.size() > 0 ) { test = test.getChild( seglist.front() ); if ( test.valid() ) { iObj = test; seglist.erase( seglist.begin() ); } } // walk property hierarchy for most recent valid object Abc::ICompoundProperty props = iObj.getProperties(); const Abc::PropertyHeader* header; bool found = false; for ( std::size_t i = 0; i < seglist.size(); ++i ) { header = props.getPropertyHeader( seglist[i] ); if ( header && header->isCompound() ) { Abc::ICompoundProperty ptest( props, header->getName() ); if ( ptest.valid() ) { props = ptest; found = true; } } else if ( header && header->isSimple() ) { found = true; } else { std::cout << seglist[i] << ": Invalid object or property" << std::endl; return 1; } } // walk the archive tree if ( found ) if ( header->isCompound() ) tree( props ); else tree( Abc::IScalarProperty( props, header->getName() ) ); else tree( iObj, opt_all ); ++count; } return 0; }