void AlembicVisibilityController::GetValueLocalTime(TimeValue t, void *ptr,
                                                    Interval &valid,
                                                    GetSetMethod method)
{
  ESS_CPP_EXCEPTION_REPORTING_START
  ESS_PROFILE_FUNC();

  Interval interval = FOREVER;

  MCHAR const *strPath = NULL;
  this->pblock->GetValue(AlembicVisibilityController::ID_PATH, t, strPath,
                         interval);

  MCHAR const *strIdentifier = NULL;
  this->pblock->GetValue(AlembicVisibilityController::ID_IDENTIFIER, t,
                         strIdentifier, interval);

  float fTime;
  this->pblock->GetValue(AlembicVisibilityController::ID_TIME, t, fTime,
                         interval);

  BOOL bMuted;
  this->pblock->GetValue(AlembicVisibilityController::ID_MUTED, t, bMuted,
                         interval);

  if (bMuted || !strPath || !strIdentifier) {
    return;
  }

  std::string szPath = EC_MCHAR_to_UTF8(strPath);
  std::string szIdentifier = EC_MCHAR_to_UTF8(strIdentifier);

  AbcG::IObject iObj = getObjectFromArchive(szPath, szIdentifier);

  if (!iObj.valid()) {
    return;
  }

  alembic_fillvis_options visOptions;
  visOptions.pIObj = &iObj;
  visOptions.dTicks = t;
  visOptions.bOldVisibility = m_bOldVisibility;
  AlembicImport_FillInVis(visOptions);

  float fBool = visOptions.bVisibility ? 1.0f : 0.0f;
  m_bOldVisibility = visOptions.bVisibility;

  valid = interval;

  if (method == CTRL_ABSOLUTE) {
    float *fInVal = (float *)ptr;
    *fInVal = fBool;
  }
  else {  // CTRL_RELATIVE
    float *fInVal = (float *)ptr;
    *fInVal = fBool * (*fInVal);
  }

  ESS_CPP_EXCEPTION_REPORTING_END
}
void AlembicNurbsModifier::ModifyObject (TimeValue t, ModContext &mc, ObjectState *os, INode *node) 
{
	ESS_CPP_EXCEPTION_REPORTING_START
ESS_PROFILE_FUNC();

	Interval interval = FOREVER;//os->obj->ObjectValidity(t);
	//ESS_LOG_INFO( "Interval Start: " << interval.Start() << " End: " << interval.End() );

    MCHAR const* strPath = NULL;
	this->pblock->GetValue( AlembicNurbsModifier::ID_PATH, t, strPath, interval);

	MCHAR const* strIdentifier = NULL;
	this->pblock->GetValue( AlembicNurbsModifier::ID_IDENTIFIER, t, strIdentifier, interval);
 
	float fTime;
	this->pblock->GetValue( AlembicNurbsModifier::ID_TIME, t, fTime, interval);

	BOOL bMuted;
	this->pblock->GetValue( AlembicNurbsModifier::ID_MUTED, t, bMuted, interval);
	
	BOOL bIgnoreSubframeSamples;
	this->pblock->GetValue( AlembicNurbsModifier::ID_IGNORE_SUBFRAME_SAMPLES, t, bIgnoreSubframeSamples, interval);

	//ESS_LOG_INFO( "AlembicNurbsModifier::ModifyObject strPath: " << strPath << " strIdentifier: " << strIdentifier << " fTime: " << fTime << 
	//	" bTopology: " << bTopology << " bGeometry: " << bGeometry << " bNormals: " << bNormals << " bUVs: " << bUVs << " bMuted: " << bMuted );

	if( bMuted || !strPath || !strIdentifier) {
		return;
	}

	std::string szPath = EC_MCHAR_to_UTF8( strPath );
	std::string szIdentifier = EC_MCHAR_to_UTF8( strIdentifier );

	AbcG::IObject iObj;
	try {
		iObj = getObjectFromArchive(szPath, szIdentifier);
	} catch( std::exception exp ) {
        extern bool g_hasModifierErrorOccurred;
        g_hasModifierErrorOccurred = true;
		ESS_LOG_ERROR( "Can not open Alembic data stream.  Path: " << szPath << " identifier: " << szIdentifier << " reason: " << exp.what() );
		return;
	}

	if(!iObj.valid()) {
        extern bool g_hasModifierErrorOccurred;
        g_hasModifierErrorOccurred = true;
		ESS_LOG_ERROR( "Not a valid Alembic data stream.  Path: " << szPath << " identifier: " << szIdentifier );
		return;
	}


	
	alembic_NURBSload_options options;
    options.pIObj =  &iObj;
    options.dTicks = GetTimeValueFromSeconds( fTime );
 
	if(bIgnoreSubframeSamples){
		options.nDataFillFlags |= ALEMBIC_DATAFILL_IGNORE_SUBFRAME_SAMPLES;
	}

	//SClass_ID superClassID = os->obj->SuperClassID();
	Class_ID classID = os->obj->ClassID();

    if(classID == EDITABLE_SURF_CLASS_ID){
        options.pObject = os->obj;
    }
	else {
        extern bool g_hasModifierErrorOccurred;
        g_hasModifierErrorOccurred = true;
		ESS_LOG_ERROR( "Can not convert internal object data into a ShapeObject, confused. (2)" );
	}

   try {
		AlembicImport_LoadNURBS_Internal(options);
   }
   catch(std::exception exp ) {
        extern bool g_hasModifierErrorOccurred;
        g_hasModifierErrorOccurred = true;
		ESS_LOG_ERROR( "Error reading shape from Alembic data stream.  Path: " << strPath << " identifier: " << strIdentifier << " reason: " << exp.what() );
		return;
   }

   os->obj = options.pObject;
   //os->obj->UnlockObject();

	os->obj->SetChannelValidity(TOPO_CHAN_NUM, interval);
	os->obj->SetChannelValidity(GEOM_CHAN_NUM, interval);
	os->obj->SetChannelValidity(TEXMAP_CHAN_NUM, interval);
	os->obj->SetChannelValidity(MTL_CHAN_NUM, interval);
	os->obj->SetChannelValidity(SELECT_CHAN_NUM, interval);
	os->obj->SetChannelValidity(SUBSEL_TYPE_CHAN_NUM, interval);
	os->obj->SetChannelValidity(DISP_ATTRIB_CHAN_NUM, interval);

   	ESS_CPP_EXCEPTION_REPORTING_END
}
void AlembicMeshGeomModifier::ModifyObject(TimeValue t, ModContext &mc,
                                           ObjectState *os, INode *node)
{
  ESS_CPP_EXCEPTION_REPORTING_START
  ESS_PROFILE_FUNC();

  Interval interval = FOREVER;  // os->obj->ObjectValidity(t);
  // ESS_LOG_INFO( "Interval Start: " << interval.Start() << " End: " <<
  // interval.End() );

  MCHAR const *strPath = NULL;
  this->pblock->GetValue(AlembicMeshGeomModifier::ID_PATH, t, strPath,
                         interval);

  MCHAR const *strIdentifier = NULL;
  this->pblock->GetValue(AlembicMeshGeomModifier::ID_IDENTIFIER, t,
                         strIdentifier, interval);

  float fTime;
  this->pblock->GetValue(AlembicMeshGeomModifier::ID_TIME, t, fTime, interval);

  BOOL bTopology = false;
  BOOL bGeometry = true;

  float fGeoAlpha;
  this->pblock->GetValue(AlembicMeshGeomModifier::ID_GEOALPHA, t, fGeoAlpha,
                         interval);

  BOOL bNormals = false;
  BOOL bUVs = false;

  BOOL bMuted;
  this->pblock->GetValue(AlembicMeshGeomModifier::ID_MUTED, t, bMuted,
                         interval);

  BOOL bAdditive;
  this->pblock->GetValue(AlembicMeshGeomModifier::ID_ADDITIVE, t, bAdditive,
                         interval);

  // ESS_LOG_INFO( "AlembicMeshGeomModifier::ModifyObject strPath: " << strPath
  // << " strIdentifier: " << strIdentifier << " fTime: " << fTime <<
  //	" bTopology: " << bTopology << " bGeometry: " << bGeometry << "
  // bNormals: " << bNormals << " bUVs: " << bUVs << " bMuted: " << bMuted );

  // IParamBlock2* pBlock = this->GetParamBlock(0);
  // if(pBlock){
  //   ESS_LOG_WARNING("ParamBlock: "<<pBlock->GetVersion());
  //}

  if (!bMuted && strPath && strIdentifier) {
    std::string szPath = EC_MCHAR_to_UTF8(strPath);
    std::string szIdentifier = EC_MCHAR_to_UTF8(strIdentifier);

    AbcG::IObject iObj;
    try {
      ESS_PROFILE_SCOPE("getObjectFromArchive");
      iObj = getObjectFromArchive(szPath, szIdentifier);
    }
    catch (std::exception exp) {
      extern bool g_hasModifierErrorOccurred;
      g_hasModifierErrorOccurred = true;
      ESS_LOG_ERROR("Can not open Alembic data stream.  Path: "
                    << szPath << " identifier: " << szIdentifier
                    << " reason: " << exp.what());
      return;
    }

    if (!iObj.valid()) {
      extern bool g_hasModifierErrorOccurred;
      g_hasModifierErrorOccurred = true;
      ESS_LOG_ERROR("Not a valid Alembic data stream.  Path: "
                    << szPath << " identifier: " << szIdentifier);
      return;
    }

    alembic_fillmesh_options options;
    options.fileName = szPath;
    options.pObjectCache = getObjectCacheFromArchive(szPath, szIdentifier);
    options.identifier = szIdentifier;
    options.pIObj = &iObj;
    options.dTicks = GetTimeValueFromSeconds(fTime);
    options.nDataFillFlags = 0;
    options.fVertexAlpha = fGeoAlpha;
    if (bAdditive == TRUE) {
      options.bAdditive = true;
    }
    else {
      options.bAdditive = false;
    }
    if (bTopology) {
      options.nDataFillFlags |= ALEMBIC_DATAFILL_FACELIST;
      options.nDataFillFlags |= ALEMBIC_DATAFILL_MATERIALIDS;
    }
    if (bGeometry) {
      options.nDataFillFlags |= ALEMBIC_DATAFILL_VERTEX;
    }
    if (bNormals) {
      options.nDataFillFlags |= ALEMBIC_DATAFILL_NORMALS;
    }
    if (bUVs) {
      options.nDataFillFlags |= ALEMBIC_DATAFILL_UVS;
    }

    options.pObject = os->obj;

    // Find out if we are modifying a poly object or a tri object
    if (os->obj->ClassID() == Class_ID(POLYOBJ_CLASS_ID, 0)) {
      ESS_PROFILE_SCOPE("reinterpret_cast1");
      PolyObject *pPolyObj = reinterpret_cast<PolyObject *>(os->obj);

      options.pMNMesh = &(pPolyObj->GetMesh());
    }
    else if (os->obj->CanConvertToType(Class_ID(POLYOBJ_CLASS_ID, 0))) {
      ESS_PROFILE_SCOPE("reinterpret_cast2");
      PolyObject *pPolyObj = reinterpret_cast<PolyObject *>(
          os->obj->ConvertToType(t, Class_ID(POLYOBJ_CLASS_ID, 0)));

      options.pMNMesh = &(pPolyObj->GetMesh());

      if (os->obj != pPolyObj) {
        os->obj = pPolyObj;
        os->obj->UnlockObject();
      }
    }
    else {
      ESS_LOG_ERROR(
          "Can not convert internal mesh data into a PolyObject, confused.");
      return;
    }

    try {
      AlembicImport_FillInPolyMesh(options);
    }
    catch (std::exception exp) {
      ESS_LOG_ERROR("Error reading mesh from Alembic data stream.  Path: "
                    << strPath << " identifier: " << strIdentifier
                    << " reason: " << exp.what());
      return;
    }
  }

  // update the validity channel
  if (bTopology) {
    ESS_PROFILE_SCOPE("UpdateValidity_Topology_Geom");
    os->obj->UpdateValidity(TOPO_CHAN_NUM, interval);
    os->obj->UpdateValidity(GEOM_CHAN_NUM, interval);
  }
  if (bGeometry) {
    ESS_PROFILE_SCOPE("UpdateValidity_Geom");
    os->obj->UpdateValidity(GEOM_CHAN_NUM, interval);
  }
  if (bUVs) {
    ESS_PROFILE_SCOPE("UpdateValidity_UV");
    os->obj->UpdateValidity(TEXMAP_CHAN_NUM, interval);
  }

  ESS_CPP_EXCEPTION_REPORTING_END
}
void AlembicSplineGeomModifier::ModifyObject(TimeValue t, ModContext &mc,
                                             ObjectState *os, INode *node)
{
  ESS_CPP_EXCEPTION_REPORTING_START
  ESS_PROFILE_FUNC();

  Interval interval = FOREVER;  // os->obj->ObjectValidity(t);
  // ESS_LOG_INFO( "Interval Start: " << interval.Start() << " End: " <<
  // interval.End() );

  MCHAR const *strPath = NULL;
  this->pblock->GetValue(AlembicSplineGeomModifier::ID_PATH, t, strPath,
                         interval);

  MCHAR const *strIdentifier = NULL;
  this->pblock->GetValue(AlembicSplineGeomModifier::ID_IDENTIFIER, t,
                         strIdentifier, interval);

  float fTime;
  this->pblock->GetValue(AlembicSplineGeomModifier::ID_TIME, t, fTime,
                         interval);

  BOOL bTopology = false;
  BOOL bGeometry = true;
  float fGeoAlpha = 1.0f;
  BOOL bNormals = false;
  BOOL bUVs = true;

  BOOL bMuted;
  this->pblock->GetValue(AlembicSplineGeomModifier::ID_MUTED, t, bMuted,
                         interval);

  // ESS_LOG_INFO( "AlembicSplineGeomModifier::ModifyObject strPath: " <<
  // strPath << " strIdentifier: " << strIdentifier << " fTime: " << fTime <<
  //	" bTopology: " << bTopology << " bGeometry: " << bGeometry << "
  // bNormals: " << bNormals << " bUVs: " << bUVs << " bMuted: " << bMuted );

  if (bMuted || !strPath || !strIdentifier) {
    return;
  }

  std::string szPath = EC_MCHAR_to_UTF8(strPath);
  std::string szIdentifier = EC_MCHAR_to_UTF8(strIdentifier);

  AbcG::IObject iObj;
  try {
    iObj = getObjectFromArchive(szPath, szIdentifier);
  }
  catch (std::exception exp) {
    extern bool g_hasModifierErrorOccurred;
    g_hasModifierErrorOccurred = true;
    ESS_LOG_ERROR("Can not open Alembic data stream.  Path: "
                  << szPath << " identifier: " << szIdentifier
                  << " reason: " << exp.what());
    return;
  }

  if (!iObj.valid()) {
    extern bool g_hasModifierErrorOccurred;
    g_hasModifierErrorOccurred = true;
    ESS_LOG_ERROR("Not a valid Alembic data stream.  Path: "
                  << szPath << " identifier: " << szIdentifier);
    return;
  }

  ShapeObject *shape = (ShapeObject *)os->obj;

  BezierShape bezierShape;
  PolyShape polyShape;

  alembic_fillshape_options options;
  options.pIObj = &iObj;
  options.pShapeObject = shape;
  options.dTicks = GetTimeValueFromSeconds(fTime);
  options.nDataFillFlags = 0;
  options.nDataFillFlags |= ALEMBIC_DATAFILL_VERTEX;
  options.nDataFillFlags |= ALEMBIC_DATAFILL_BOUNDINGBOX;

  SClass_ID superClassID = os->obj->SuperClassID();
  Class_ID classID = os->obj->ClassID();
  if (superClassID != SHAPE_CLASS_ID) {
    extern bool g_hasModifierErrorOccurred;
    g_hasModifierErrorOccurred = true;
    ESS_LOG_ERROR(
        "Can not convert internal object data into a ShapeObject, confused. "
        "(1)");
    return;
  }

  if (classID == Class_ID(SPLINESHAPE_CLASS_ID, 0)) {
    SplineShape *pSplineShape = (SplineShape *)os->obj;
    options.pBezierShape = &pSplineShape->shape;
  }
  else if (classID == Class_ID(LINEARSHAPE_CLASS_ID, 0)) {
    LinearShape *pLinearShape = (LinearShape *)os->obj;
    options.pPolyShape = &pLinearShape->shape;
  }
  else {
    extern bool g_hasModifierErrorOccurred;
    g_hasModifierErrorOccurred = true;
    ESS_LOG_ERROR(
        "Can not convert internal object data into a ShapeObject, confused. "
        "(2)");
  }

  try {
    AlembicImport_FillInShape(options);
  }
  catch (std::exception exp) {
    extern bool g_hasModifierErrorOccurred;
    g_hasModifierErrorOccurred = true;
    ESS_LOG_ERROR("Error reading shape from Alembic data stream.  Path: "
                  << strPath << " identifier: " << strIdentifier
                  << " reason: " << exp.what());
    return;
  }

  // update the validity channel
  if (bTopology) {
    os->obj->UpdateValidity(TOPO_CHAN_NUM, interval);
    os->obj->UpdateValidity(GEOM_CHAN_NUM, interval);
  }
  if (bGeometry) {
    os->obj->UpdateValidity(GEOM_CHAN_NUM, interval);
  }

  ESS_CPP_EXCEPTION_REPORTING_END
}
void AlembicFloatController::GetValueLocalTime(TimeValue t, void* ptr,
                                               Interval& valid,
                                               GetSetMethod method)
{
  ESS_CPP_EXCEPTION_REPORTING_START

  Interval interval = FOREVER;

  MCHAR const* strPath = NULL;
  this->pblock->GetValue(AlembicFloatController::ID_PATH, t, strPath, interval);

  MCHAR const* strIdentifier = NULL;
  this->pblock->GetValue(AlembicFloatController::ID_IDENTIFIER, t,
                         strIdentifier, interval);

  MCHAR const* strCategory = NULL;
  this->pblock->GetValue(AlembicFloatController::ID_CATEGORY, t, strCategory,
                         interval);

  MCHAR const* strProperty = NULL;
  this->pblock->GetValue(AlembicFloatController::ID_PROPERTY, t, strProperty,
                         interval);

  float fTime;
  this->pblock->GetValue(AlembicFloatController::ID_TIME, t, fTime, interval);

  BOOL bMuted;
  this->pblock->GetValue(AlembicFloatController::ID_MUTED, t, bMuted, interval);

  extern bool g_bVerboseLogging;

  if (g_bVerboseLogging) {
    ESS_LOG_WARNING("Param block at tick " << t << "-----------------------");
    ESS_LOG_WARNING("PATH: " << strPath);
    ESS_LOG_WARNING("IDENTIFIER: " << strIdentifier);
    ESS_LOG_WARNING("PROPERTY: " << strProperty);
    ESS_LOG_WARNING("TIME: " << fTime);
    ESS_LOG_WARNING("MUTED: " << bMuted);
    ESS_LOG_WARNING("Param block end -------------");
  }

  const float fDefaultVal = -1.0;

  std::string szPath = EC_MCHAR_to_UTF8(strPath);
  std::string szIdentifier = EC_MCHAR_to_UTF8(strIdentifier);
  std::string szProperty = EC_MCHAR_to_UTF8(strProperty);
  std::string szCategory = EC_MCHAR_to_UTF8(strCategory);

  if (szCategory.empty()) {  // default to standard properties for backwards
    // compatibility
    szCategory = std::string("standardProperties");
  }

  if (!strProperty || !strPath || !strIdentifier /*|| !strCategory*/) {
    return setController("1", szProperty, valid, interval, method, ptr,
                         fDefaultVal);
  }

  if (bMuted) {
    return setController("2", szProperty, valid, interval, method, ptr,
                         fDefaultVal);
  }

  // if( szCategory.size() == 0 ) {
  //   ESS_LOG_ERROR( "No category specified." );
  //   return setController("3a", szProperty, valid, interval,   method,   ptr,
  //   fDefaultVal);
  //}

  if (szProperty.size() == 0) {
    ESS_LOG_ERROR("No property specified.");
    return setController("3b", szProperty, valid, interval, method, ptr,
                         fDefaultVal);
  }

  AbcG::IObject iObj = getObjectFromArchive(szPath, szIdentifier);

  if (!iObj.valid()) {
    return setController("4", szProperty, valid, interval, method, ptr,
                         fDefaultVal);
  }

  TimeValue dTicks = GetTimeValueFromSeconds(fTime);
  double sampleTime = GetSecondsFromTimeValue(dTicks);

  float fSampleVal = fDefaultVal;

  if (boost::iequals(szCategory, "standardProperties")) {
    if (Alembic::AbcGeom::ICamera::matches(
            iObj.getMetaData())) {  // standard camera properties

      Alembic::AbcGeom::ICamera objCamera =
          Alembic::AbcGeom::ICamera(iObj, Alembic::Abc::kWrapExisting);

      SampleInfo sampleInfo =
          getSampleInfo(sampleTime, objCamera.getSchema().getTimeSampling(),
                        objCamera.getSchema().getNumSamples());
      Alembic::AbcGeom::CameraSample sample;
      objCamera.getSchema().get(sample, sampleInfo.floorIndex);

      double sampleVal;
      if (!getCameraSampleVal(objCamera, sampleInfo, sample, szProperty,
                              sampleVal)) {
        return setController("5", szProperty, valid, interval, method, ptr,
                             fDefaultVal);
      }

      // Blend the camera values, if necessary
      if (sampleInfo.alpha != 0.0) {
        objCamera.getSchema().get(sample, sampleInfo.ceilIndex);
        double sampleVal2 = 0.0;
        if (getCameraSampleVal(objCamera, sampleInfo, sample, szProperty,
                               sampleVal2)) {
          sampleVal = (1.0 - sampleInfo.alpha) * sampleVal +
                      sampleInfo.alpha * sampleVal2;
        }
      }

      fSampleVal = (float)sampleVal;
    }
    else if (Alembic::AbcGeom::ILight::matches(
                 iObj.getMetaData())) {  // ILight material properties

      ESS_PROFILE_SCOPE(
          "AlembicFloatController::GetValueLocalTime - read ILight shader "
          "parameter");

      Alembic::AbcGeom::ILight objLight =
          Alembic::AbcGeom::ILight(iObj, Alembic::Abc::kWrapExisting);

      SampleInfo sampleInfo =
          getSampleInfo(sampleTime, objLight.getSchema().getTimeSampling(),
                        objLight.getSchema().getNumSamples());

      AbcM::IMaterialSchema matSchema = getMatSchema(objLight);

      std::string strProp = szProperty;

      std::vector<std::string> parts;
      boost::split(parts, strProp, boost::is_any_of("."));

      if (parts.size() == 3) {
        const std::string& target = parts[0];
        const std::string& type = parts[1];
        const std::string& prop = parts[2];

        Abc::IFloatProperty fProp = readShaderScalerProp<Abc::IFloatProperty>(
            matSchema, target, type, prop);
        if (fProp.valid()) {
          fProp.get(fSampleVal, sampleInfo.floorIndex);
        }
        else {
          ESS_LOG_WARNING("Float Controller Error: could find shader parameter "
                          << strProp);
        }
      }
      else if (parts.size() == 5) {
        const std::string& target = parts[0];
        const std::string& type = parts[1];
        const std::string& prop = parts[2];
        const std::string& propInterp = parts[3];
        const std::string& propComp = parts[4];

        // ESS_LOG_WARNING("propInterp: "<<propInterp);

        if (propInterp == "rgb") {
          Abc::IC3fProperty fProp = readShaderScalerProp<Abc::IC3fProperty>(
              matSchema, target, type, prop);
          if (fProp.valid()) {
            Abc::C3f v3f;
            fProp.get(v3f, sampleInfo.floorIndex);
            if (propComp == "x") {
              fSampleVal = v3f.x;
            }
            else if (propComp == "y") {
              fSampleVal = v3f.y;
            }
            else if (propComp == "z") {
              fSampleVal = v3f.z;
            }
            else {
              ESS_LOG_WARNING(
                  "Float Controller Error: invalid component: " << propComp);
            }
          }
          else {
            ESS_LOG_WARNING(
                "Float Controller Error: could find shader parameter "
                << strProp);
          }
        }
        else {
          ESS_LOG_WARNING(
              "Float Controller Error: unrecognized parameter interpretation: "
              << propInterp);
        }
      }
      else {
        ESS_LOG_WARNING(
            "Float Controller Error: could not parse property field: "
            << strProperty);
      }
    }
  }
  else if (boost::iequals(szCategory, "userProperties")) {
    // AbcA::TimeSamplingPtr timeSampling = obj.getSchema().getTimeSampling();
    // int nSamples = (int)obj.getSchema().getNumSamples();

    AbcA::TimeSamplingPtr timeSampling;
    int nSamples = 0;
    Abc::ICompoundProperty propk =
        AbcNodeUtils::getUserProperties(iObj, timeSampling, nSamples);

    if (propk.valid()) {
      SampleInfo sampleInfo = getSampleInfo(sampleTime, timeSampling, nSamples);

      std::vector<std::string> parts;
      boost::split(parts, szProperty, boost::is_any_of("."));

      if (parts.size() == 1) {
        Abc::IFloatProperty fProp =
            readScalarProperty<Abc::IFloatProperty>(propk, szProperty);
        if (fProp.valid()) {
          fProp.get(fSampleVal, sampleInfo.floorIndex);
        }
        else {
          Abc::IInt32Property intProp =
              readScalarProperty<Abc::IInt32Property>(propk, szProperty);
          if (intProp.valid()) {
            int intVal;
            intProp.get(intVal, sampleInfo.floorIndex);
            fSampleVal = (float)intVal;
          }
          else {
            ESS_LOG_WARNING(
                "Float Controller Error: could not read user property "
                << szProperty);
          }
        }
      }
      else if (parts.size() == 3) {
        const std::string& prop = parts[0];
        const std::string& propInterp = parts[1];
        const std::string& propComp = parts[2];

        // ESS_LOG_WARNING("interpretation: "<<propInterp);

        if (propInterp == "rgb") {
          fSampleVal = readScalarPropertyExt3<Abc::IC3fProperty, Abc::C3f>(
              propk, sampleInfo, prop, propComp);
        }
        else if (propInterp == "vector") {
          fSampleVal = readScalarPropertyExt3<Abc::IV3fProperty, Abc::V3f>(
              propk, sampleInfo, prop, propComp);
        }
        else {
          ESS_LOG_WARNING(
              "Float Controller Error: unrecognized parameter interpretation: "
              << propInterp);
        }
      }
    }
  }
  // else if( boost::iequals(szCategory, "arbGeomParams") ){

  //}

  return setController("6", szProperty, valid, interval, method, ptr,
                       fSampleVal);

  ESS_CPP_EXCEPTION_REPORTING_END
}