bind method

  1. @override
void bind()
override

Implementation

@override
void bind() {
  dynamic targetObject = node;
  final parsedPath = this.parsedPath;

  final objectName = parsedPath["objectName"];
  final propertyName = parsedPath["propertyName"];
  String? propertyIndex = parsedPath["propertyIndex"];

  if (targetObject == null) {
    targetObject = PropertyBinding.findNode(rootNode, parsedPath["nodeName"]) ?? rootNode;
    node = targetObject;
  }

  // set fail state so we can just 'return' on error
  getValue = _getValueUnavailable;
  setValue = _setValueUnavailable;

  // ensure there is a value node
  if (targetObject == null) {
    console.warning('PropertyBinding: Trying to update node for track: $path but it wasn\'t found.');
    return;
  }

  if (objectName != null) {
    int? objectIndex = parsedPath["objectIndex"];

    // special cases were we need to reach deeper into the hierarchy to get the face materials....
    switch (objectName) {
      case 'materials':
        if (!targetObject.material) {
          console.warning('PropertyBinding: Can not bind to material as node does not have a material. $this');
          return;
        }

        if (!targetObject.material.materials) {
          console.warning('PropertyBinding: Can not bind to material.materials as node.material does not have a materials array. $this');
          return;
        }
        targetObject = targetObject.material.materials;
        break;
      case 'bones':
        if (targetObject.skeleton != null) {
          console.warning('PropertyBinding: Can not bind to bones as node does not have a skeleton. $this');
          return;
        }
        // potential future optimization: skip this if propertyIndex is already an integer
        // and convert the integer string to a true integer.
        targetObject.children = targetObject.skeleton!.bones;

        // support resolving morphTarget names into indices.
        for (int i = 0; i < targetObject.children.length; i++) {
          if (targetObject.children[i].name == objectIndex.toString()) {
            objectIndex = i;
            break;
          }
        }
        break;
      default:
        if (targetObject.getProperty(objectName) == null) {
          console.warning('PropertyBinding: Can not bind to objectName of node null. $this');
          return;
        }

        // targetObject = targetObject[ objectName ];
        targetObject = targetObject.getProperty(objectName);
    }

    if (objectIndex != null) {
      if (targetObject?.children[objectIndex] == null) {
        console.warning('PropertyBinding: Trying to bind to objectIndex of objectName, but is null.$this $targetObject');
        return;
      }

      targetObject = targetObject?.children[objectIndex];
    }
  }

  // resolve property
  final nodeProperty = targetObject?.getProperty(propertyName);

  if (nodeProperty == null) {
    final nodeName = parsedPath["nodeName"];

    console.warning('PropertyBinding: Trying to update property for track: $nodeName $propertyName  but it wasn\'t found. $targetObject');
    return;
  }

  // determine versioning scheme
  Versioning versioning = Versioning.none;

  this.targetObject = targetObject;

  // if ( targetObject.needsUpdate != null ) { // material
  if (targetObject.runtimeType.toString().endsWith("Material")) {
    versioning = Versioning.needsUpdate;
  }
  else if (targetObject?.matrixWorldNeedsUpdate != null) {
    // node transform
    versioning = Versioning.matrixWorldNeedsUpdate;
  }

  // determine how the property gets bound
  BindingType bindingType = BindingType.direct;

  if (propertyIndex != null) {
    // access a sub element of the property array (only primitives are supported right now)

    if (propertyName == 'morphTargetInfluences') {
      // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.

      // support resolving morphTarget names into indices.
      if (targetObject?.geometry != null) {
        console.warning('PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry. $this');
        return;
      }

      if (targetObject?.geometry is BufferGeometry) {
        if (targetObject?.geometry?.morphAttributes != null) {
          console.warning('PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes. $this');
          return;
        }

        if (targetObject?.morphTargetDictionary?[propertyIndex] != null) {
          propertyIndex = targetObject!.morphTargetDictionary![propertyIndex];
        }
      }
      else {
        console.warning('PropertyBinding: Can not bind to morphTargetInfluences on Geometry. Use BufferGeometry instead. $this');
        return;
      }
    }

    bindingType = BindingType.arrayElement;

    resolvedProperty = nodeProperty;
    this.propertyIndex = propertyIndex;

    // } else if ( nodeProperty.fromArray != null && nodeProperty.toArray != null ) {
  }
  else if (["Color", "Vector3", "Quaternion"].contains(nodeProperty.runtimeType.toString())) {
    // must use copy for Object3D.Euler/Quaternion

    bindingType = BindingType.hasFromToArray;

    resolvedProperty = nodeProperty;
  } else if (nodeProperty is List) {
    bindingType = BindingType.entireArray;

    resolvedProperty = nodeProperty;
  } else {
    this.propertyName = propertyName;
  }

  // select getter / setter
  getValue = getterByBindingType(bindingType.index,0);
  setValue = setterByBindingTypeAndVersioning(bindingType.index, versioning.index)!;
}