예제 #1
0
static int node_animation_properties(bNodeTree *ntree, bNode *node)
{
	bNodeSocket *sock;
	const ListBase *lb;
	Link *link;
	PointerRNA ptr;
	PropertyRNA *prop;

	/* check to see if any of the node's properties have fcurves */
	RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
	lb = RNA_struct_type_properties(ptr.type);

	for (link = lb->first; link; link = link->next) {
		int driven, len = 1, index;
		prop = (PropertyRNA *)link;

		if (RNA_property_array_check(prop))
			len = RNA_property_array_length(&ptr, prop);

		for (index = 0; index < len; index++) {
			if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
				nodeUpdate(ntree, node);
				return 1;
			}
		}
	}

	/* now check node sockets */
	for (sock = node->inputs.first; sock; sock = sock->next) {
		int driven, len = 1, index;

		RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
		prop = RNA_struct_find_property(&ptr, "default_value");
		if (prop) {
			if (RNA_property_array_check(prop))
				len = RNA_property_array_length(&ptr, prop);

			for (index = 0; index < len; index++) {
				if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
					nodeUpdate(ntree, node);
					return 1;
				}
			}
		}
	}

	return 0;
}
예제 #2
0
static bool depthdropper_poll(bContext *C)
{
  PointerRNA ptr;
  PropertyRNA *prop;
  int index_dummy;
  uiBut *but;

  /* check if there's an active button taking depth value */
  if ((CTX_wm_window(C) != NULL) &&
      (but = UI_context_active_but_prop_get(C, &ptr, &prop, &index_dummy)) &&
      (but->type == UI_BTYPE_NUM) && (prop != NULL)) {
    if ((RNA_property_type(prop) == PROP_FLOAT) &&
        (RNA_property_subtype(prop) & PROP_UNIT_LENGTH) &&
        (RNA_property_array_check(prop) == false)) {
      return 1;
    }
  }
  else {
    RegionView3D *rv3d = CTX_wm_region_view3d(C);
    if (rv3d && rv3d->persp == RV3D_CAMOB) {
      View3D *v3d = CTX_wm_view3d(C);
      if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) {
        return 1;
      }
    }
  }

  return 0;
}
예제 #3
0
/* create new expression for button (i.e. a "scripted driver"), if it can be created... */
bool ui_but_anim_expression_create(uiBut *but, const char *str)
{
	bContext *C = but->block->evil_C;
	ID *id;
	FCurve *fcu;
	char *path;
	bool ok = false;
	
	/* button must have RNA-pointer to a numeric-capable property */
	if (ELEM(NULL, but->rnapoin.data, but->rnaprop)) {
		if (G.debug & G_DEBUG)
			printf("ERROR: create expression failed - button has no RNA info attached\n");
		return false;
	}
	
	if (RNA_property_array_check(but->rnaprop) != 0) {
		if (but->rnaindex == -1) {
			if (G.debug & G_DEBUG)
				printf("ERROR: create expression failed - can't create expression for entire array\n");
			return false;
		}
	}
	
	/* make sure we have animdata for this */
	/* FIXME: until materials can be handled by depsgraph, don't allow drivers to be created for them */
	id = (ID *)but->rnapoin.id.data;
	if ((id == NULL) || (GS(id->name) == ID_MA) || (GS(id->name) == ID_TE)) {
		if (G.debug & G_DEBUG)
			printf("ERROR: create expression failed - invalid id-datablock for adding drivers (%p)\n", id);
		return false;
	}
	
	/* get path */
	path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
	
	/* create driver */
	fcu = verify_driver_fcurve(id, path, but->rnaindex, 1);
	if (fcu) {
		ChannelDriver *driver = fcu->driver;
		
		if (driver) {
			/* set type of driver */
			driver->type = DRIVER_TYPE_PYTHON;

			/* set the expression */
			/* TODO: need some way of identifying variables used */
			BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression));

			/* updates */
			driver->flag |= DRIVER_FLAG_RECOMPILE;
			WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL);
			ok = true;
		}
	}
	
	MEM_freeN(path);
	
	return ok;
}
예제 #4
0
/* get reference value from F-Curve using RNA */
static bool pose_propagate_get_refVal(Object *ob, FCurve *fcu, float *value)
{
	PointerRNA id_ptr, ptr;
	PropertyRNA *prop;
	bool found = false;
	
	/* base pointer is always the object -> id_ptr */
	RNA_id_pointer_create(&ob->id, &id_ptr);
	
	/* resolve the property... */
	if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
		if (RNA_property_array_check(prop)) {
			/* array */
			if (fcu->array_index < RNA_property_array_length(&ptr, prop)) {
				found = true;
				switch (RNA_property_type(prop)) {
					case PROP_BOOLEAN:
						*value = (float)RNA_property_boolean_get_index(&ptr, prop, fcu->array_index);
						break;
					case PROP_INT:
						*value = (float)RNA_property_int_get_index(&ptr, prop, fcu->array_index);
						break;
					case PROP_FLOAT:
						*value = RNA_property_float_get_index(&ptr, prop, fcu->array_index);
						break;
					default:
						found = false;
						break;
				}
			}
		}
		else {
			/* not an array */
			found = true;
			switch (RNA_property_type(prop)) {
				case PROP_BOOLEAN:
					*value = (float)RNA_property_boolean_get(&ptr, prop);
					break;
				case PROP_INT:
					*value = (float)RNA_property_int_get(&ptr, prop);
					break;
				case PROP_ENUM:
					*value = (float)RNA_property_enum_get(&ptr, prop);
					break;
				case PROP_FLOAT:
					*value = RNA_property_float_get(&ptr, prop);
					break;
				default:
					found = false;
					break;
			}
		}
	}
	
	return found;
}
예제 #5
0
/**
 * \a check_prop callback filters functions to avoid drawing certain properties,
 * in cases where PROP_HIDDEN flag can't be used for a property.
 */
int uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr,
                     int (*check_prop)(PointerRNA *, PropertyRNA *),
                     const char label_align)
{
	uiLayout *split, *col;
	int flag;
	const char *name;
	int tot = 0;

	assert(ELEM3(label_align, '\0', 'H', 'V'));

	RNA_STRUCT_BEGIN (ptr, prop)
	{
		flag = RNA_property_flag(prop);
		if (flag & PROP_HIDDEN || (check_prop && check_prop(ptr, prop) == FALSE))
			continue;

		if (label_align != '\0') {
			PropertyType type = RNA_property_type(prop);
			int is_boolean = (type == PROP_BOOLEAN && !RNA_property_array_check(prop));

			name = RNA_property_ui_name(prop);

			if (label_align == 'V') {
				col = uiLayoutColumn(layout, TRUE);

				if (!is_boolean)
					uiItemL(col, name, ICON_NONE);
			}
			else if (label_align == 'H') {
				split = uiLayoutSplit(layout, 0.5f, FALSE);

				col = uiLayoutColumn(split, FALSE);
				uiItemL(col, (is_boolean) ? "" : name, ICON_NONE);
				col = uiLayoutColumn(split, FALSE);
			}
			else {
				col = NULL;
			}

			/* may meed to add more cases here.
			 * don't override enum flag names */

			/* name is shown above, empty name for button below */
			name = (flag & PROP_ENUM_FLAG || is_boolean) ? NULL : "";
		}
		else {
			col = layout;
			name = NULL; /* no smart label alignment, show default name with button */
		}

		uiItemFullR(col, ptr, prop, -1, 0, 0, name, ICON_NONE);
		tot++;
	}
예제 #6
0
static bool assign_default_button_poll(bContext *C)
{
  PointerRNA ptr;
  PropertyRNA *prop;
  int index;

  UI_context_active_but_prop_get(C, &ptr, &prop, &index);

  if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
    PropertyType type = RNA_property_type(prop);

    return RNA_property_is_idprop(prop) && !RNA_property_array_check(prop) &&
           ELEM(type, PROP_INT, PROP_FLOAT);
  }

  return false;
}
예제 #7
0
파일: drivers.c 프로젝트: dfelinto/blender
/* Filtering callback for driver mapping types enum */
static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C,
                                                          PointerRNA *UNUSED(owner_ptr),
                                                          PropertyRNA *UNUSED(owner_prop),
                                                          bool *r_free)
{
  EnumPropertyItem *input = prop_driver_create_mapping_types;
  EnumPropertyItem *item = NULL;

  PointerRNA ptr = {{NULL}};
  PropertyRNA *prop = NULL;
  int index;

  int totitem = 0;

  if (!C) { /* needed for docs */
    return prop_driver_create_mapping_types;
  }

  UI_context_active_but_prop_get(C, &ptr, &prop, &index);

  if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
    const bool is_array = RNA_property_array_check(prop);

    while (input->identifier) {
      if (ELEM(input->value, CREATEDRIVER_MAPPING_1_1, CREATEDRIVER_MAPPING_NONE) || (is_array)) {
        RNA_enum_item_add(&item, &totitem, input);
      }
      input++;
    }
  }
  else {
    /* We need at least this one! */
    RNA_enum_items_add_value(&item, &totitem, input, CREATEDRIVER_MAPPING_NONE);
  }

  RNA_enum_item_end(&item, &totitem);

  *r_free = true;
  return item;
}
예제 #8
0
static int depthdropper_poll(bContext *C)
{
	PointerRNA ptr;
	PropertyRNA *prop;
	int index_dummy;
	uiBut *but;

	/* check if there's an active button taking depth value */
	if ((CTX_wm_window(C) != NULL) &&
	    (but = UI_context_active_but_prop_get(C, &ptr, &prop, &index_dummy)) &&
	    (but->type == UI_BTYPE_NUM) &&
	    (prop != NULL))
	{
		if ((RNA_property_type(prop) == PROP_FLOAT) &&
		    (RNA_property_subtype(prop) & PROP_UNIT_LENGTH) &&
		    (RNA_property_array_check(prop) == false))
		{
			return 1;
		}
	}

	return 0;
}
/* Write into "name" buffer, the name of the property (retrieved using RNA from the curve's settings),
 * and return the icon used for the struct that this property refers to 
 * WARNING: name buffer we're writing to cannot exceed 256 chars (check anim_channels_defines.c for details)
 */
int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
{
	int icon = 0;
	
	/* sanity checks */
	if (name == NULL)
		return icon;
	else if (ELEM(NULL, id, fcu, fcu->rna_path)) {
		if (fcu == NULL)
			strcpy(name, IFACE_("<invalid>"));
		else if (fcu->rna_path == NULL)
			strcpy(name, IFACE_("<no path>"));
		else /* id == NULL */
			BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
	}
	else {
		PointerRNA id_ptr, ptr;
		PropertyRNA *prop;
		
		/* get RNA pointer, and resolve the path */
		RNA_id_pointer_create(id, &id_ptr);
		
		/* try to resolve the path */
		if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
			const char *structname = NULL, *propname = NULL;
			char arrayindbuf[16];
			const char *arrayname = NULL;
			short free_structname = 0;
			
			/* For now, name will consist of 3 parts: struct-name, property name, array index
			 * There are several options possible:
			 *	1) <struct-name>.<property-name>.<array-index>
			 *		i.e. Bone1.Location.X, or Object.Location.X
			 *	2) <array-index> <property-name> (<struct name>)
			 *		i.e. X Location (Bone1), or X Location (Object)
			 *
			 * Currently, option 2 is in use, to try and make it easier to quickly identify F-Curves (it does have
			 * problems with looking rather odd though). Option 1 is better in terms of revealing a consistent sense of 
			 * hierarchy though, which isn't so clear with option 2.
			 */
			
			/* for structname
			 *	- as base, we use a custom name from the structs if one is available 
			 *	- however, if we're showing subdata of bones (probably there will be other exceptions later)
			 *	  need to include that info too since it gets confusing otherwise
			 *	- if a pointer just refers to the ID-block, then don't repeat this info
			 *	  since this just introduces clutter
			 */
			if (strstr(fcu->rna_path, "bones") && strstr(fcu->rna_path, "constraints")) {
				/* perform string 'chopping' to get "Bone Name : Constraint Name" */
				char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
				char *constName = BLI_str_quoted_substrN(fcu->rna_path, "constraints[");
				
				/* assemble the string to display in the UI... */
				structname = BLI_sprintfN("%s : %s", pchanName, constName);
				free_structname = 1;
				
				/* free the temp names */
				if (pchanName) MEM_freeN(pchanName);
				if (constName) MEM_freeN(constName);
			}
			else if (ptr.data != ptr.id.data) {
				PropertyRNA *nameprop = RNA_struct_name_property(ptr.type);
				if (nameprop) {
					/* this gets a string which will need to be freed */
					structname = RNA_property_string_get_alloc(&ptr, nameprop, NULL, 0, NULL);
					free_structname = 1;
				}
				else
					structname = RNA_struct_ui_name(ptr.type);
			}
			
			/* Property Name is straightforward */
			propname = RNA_property_ui_name(prop);
			
			/* Array Index - only if applicable */
			if (RNA_property_array_check(prop)) {
				char c = RNA_property_array_item_char(prop, fcu->array_index);
				
				/* we need to write the index to a temp buffer (in py syntax) */
				if (c) BLI_snprintf(arrayindbuf, sizeof(arrayindbuf), "%c ", c);
				else BLI_snprintf(arrayindbuf, sizeof(arrayindbuf), "[%d]", fcu->array_index);
				
				arrayname = &arrayindbuf[0];
			}
			else {
				/* no array index */
				arrayname = "";
			}
			
			/* putting this all together into the buffer */
			/* XXX we need to check for invalid names...
			 * XXX the name length limit needs to be passed in or as some define */
			if (structname)
				BLI_snprintf(name, 256, "%s%s (%s)", arrayname, propname, structname);
			else
				BLI_snprintf(name, 256, "%s%s", arrayname, propname);
			
			/* free temp name if nameprop is set */
			if (free_structname)
				MEM_freeN((void *)structname);
			
			
			/* Icon for this property's owner:
			 *	use the struct's icon if it is set
			 */
			icon = RNA_struct_ui_icon(ptr.type);
			
			/* valid path - remove the invalid tag since we now know how to use it saving
			 * users manual effort to reenable using "Revive Disabled FCurves" [#29629]
			 */
			fcu->flag &= ~FCURVE_DISABLED;
		}
		else {
			/* invalid path */
			BLI_snprintf(name, 256, "\"%s[%d]\"", fcu->rna_path, fcu->array_index);
			
			/* icon for this should be the icon for the base ID */
			/* TODO: or should we just use the error icon? */
			icon = RNA_struct_ui_icon(id_ptr.type);
			
			/* tag F-Curve as disabled - as not usable path */
			fcu->flag |= FCURVE_DISABLED;
		}
	}
	
	/* return the icon that the active data had */
	return icon;
}
예제 #10
0
파일: drivers.c 프로젝트: dfelinto/blender
/* Main Driver Management API calls:
 * Add a new driver for the specified property on the given ID block,
 * and make it be driven by the specified target.
 *
 * This is intended to be used in conjunction with a modal "eyedropper"
 * for picking the variable that is going to be used to drive this one.
 *
 * - flag: eCreateDriverFlags
 * - driver_type: eDriver_Types
 * - mapping_type: eCreateDriver_MappingTypes
 */
int ANIM_add_driver_with_target(ReportList *reports,
                                ID *dst_id,
                                const char dst_path[],
                                int dst_index,
                                ID *src_id,
                                const char src_path[],
                                int src_index,
                                short flag,
                                int driver_type,
                                short mapping_type)
{
  PointerRNA id_ptr, ptr;
  PropertyRNA *prop;

  PointerRNA id_ptr2, ptr2;
  PropertyRNA *prop2;
  int done_tot = 0;

  /* validate pointers first - exit if failure */
  RNA_id_pointer_create(dst_id, &id_ptr);
  if (RNA_path_resolve_property(&id_ptr, dst_path, &ptr, &prop) == false) {
    BKE_reportf(
        reports,
        RPT_ERROR,
        "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
        dst_id->name,
        dst_path);
    return 0;
  }

  RNA_id_pointer_create(src_id, &id_ptr2);
  if ((RNA_path_resolve_property(&id_ptr2, src_path, &ptr2, &prop2) == false) ||
      (mapping_type == CREATEDRIVER_MAPPING_NONE)) {
    /* No target - So, fall back to default method for adding a "simple" driver normally */
    return ANIM_add_driver(
        reports, dst_id, dst_path, dst_index, flag | CREATEDRIVER_WITH_DEFAULT_DVAR, driver_type);
  }

  /* handle curve-property mappings based on mapping_type */
  switch (mapping_type) {
    case CREATEDRIVER_MAPPING_N_N: /* N-N - Try to match as much as possible,
                                    * then use the first one */
    {
      /* Use the shorter of the two (to avoid out of bounds access) */
      int dst_len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr, prop) : 1;
      int src_len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr2, prop2) : 1;

      int len = MIN2(dst_len, src_len);
      int i;

      for (i = 0; i < len; i++) {
        done_tot += add_driver_with_target(reports,
                                           dst_id,
                                           dst_path,
                                           i,
                                           src_id,
                                           src_path,
                                           i,
                                           &ptr,
                                           prop,
                                           &ptr2,
                                           prop2,
                                           flag,
                                           driver_type);
      }
      break;
    }

    case CREATEDRIVER_MAPPING_1_N: /* 1-N - Specified target index for all */
    default: {
      int len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr, prop) : 1;
      int i;

      for (i = 0; i < len; i++) {
        done_tot += add_driver_with_target(reports,
                                           dst_id,
                                           dst_path,
                                           i,
                                           src_id,
                                           src_path,
                                           src_index,
                                           &ptr,
                                           prop,
                                           &ptr2,
                                           prop2,
                                           flag,
                                           driver_type);
      }
      break;
    }

    case CREATEDRIVER_MAPPING_1_1: /* 1-1 - Use the specified index (unless -1) */
    {
      done_tot = add_driver_with_target(reports,
                                        dst_id,
                                        dst_path,
                                        dst_index,
                                        src_id,
                                        src_path,
                                        src_index,
                                        &ptr,
                                        prop,
                                        &ptr2,
                                        prop2,
                                        flag,
                                        driver_type);
      break;
    }
  }

  /* done */
  return done_tot;
}
예제 #11
0
파일: drivers.c 프로젝트: dfelinto/blender
/* Helper for ANIM_add_driver_with_target - Adds the actual driver */
static int add_driver_with_target(ReportList *UNUSED(reports),
                                  ID *dst_id,
                                  const char dst_path[],
                                  int dst_index,
                                  ID *src_id,
                                  const char src_path[],
                                  int src_index,
                                  PointerRNA *dst_ptr,
                                  PropertyRNA *dst_prop,
                                  PointerRNA *src_ptr,
                                  PropertyRNA *src_prop,
                                  short flag,
                                  int driver_type)
{
  FCurve *fcu;
  short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1;
  const char *prop_name = RNA_property_identifier(src_prop);

  /* Create F-Curve with Driver */
  fcu = verify_driver_fcurve(dst_id, dst_path, dst_index, add_mode);

  if (fcu && fcu->driver) {
    ChannelDriver *driver = fcu->driver;
    DriverVar *dvar;

    /* Set the type of the driver */
    driver->type = driver_type;

    /* Set driver expression, so that the driver works out of the box
     *
     * The following checks define a bit of "autodetection magic" we use
     * to ensure that the drivers will behave as expected out of the box
     * when faced with properties with different units.
     */
    /* XXX: if we have N-1 mapping, should we include all those in the expression? */
    if ((RNA_property_unit(dst_prop) == PROP_UNIT_ROTATION) &&
        (RNA_property_unit(src_prop) != PROP_UNIT_ROTATION)) {
      /* Rotation Destination:  normal -> radians,  so convert src to radians
       * (However, if both input and output is a rotation, don't apply such corrections)
       */
      BLI_strncpy(driver->expression, "radians(var)", sizeof(driver->expression));
    }
    else if ((RNA_property_unit(src_prop) == PROP_UNIT_ROTATION) &&
             (RNA_property_unit(dst_prop) != PROP_UNIT_ROTATION)) {
      /* Rotation Source:  radians -> normal,  so convert src to degrees
       * (However, if both input and output is a rotation, don't apply such corrections)
       */
      BLI_strncpy(driver->expression, "degrees(var)", sizeof(driver->expression));
    }
    else {
      /* Just a normal property without any unit problems */
      BLI_strncpy(driver->expression, "var", sizeof(driver->expression));
    }

    /* Create a driver variable for the target
     *   - For transform properties, we want to automatically use "transform channel" instead
     *     (The only issue is with quat rotations vs euler channels...)
     *   - To avoid problems with transform properties depending on the final transform that they
     *     control (thus creating pseudo-cycles - see T48734), we don't use transform channels
     *     when both the source and destinations are in same places.
     */
    dvar = driver_add_new_variable(driver);

    if (ELEM(src_ptr->type, &RNA_Object, &RNA_PoseBone) &&
        (STREQ(prop_name, "location") || STREQ(prop_name, "scale") ||
         STRPREFIX(prop_name, "rotation_")) &&
        (src_ptr->data != dst_ptr->data)) {
      /* Transform Channel */
      DriverTarget *dtar;

      driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
      dtar = &dvar->targets[0];

      /* Bone or Object target? */
      dtar->id = src_id;
      dtar->idtype = GS(src_id->name);

      if (src_ptr->type == &RNA_PoseBone) {
        RNA_string_get(src_ptr, "name", dtar->pchan_name);
      }

      /* Transform channel depends on type */
      if (STREQ(prop_name, "location")) {
        if (src_index == 2) {
          dtar->transChan = DTAR_TRANSCHAN_LOCZ;
        }
        else if (src_index == 1) {
          dtar->transChan = DTAR_TRANSCHAN_LOCY;
        }
        else {
          dtar->transChan = DTAR_TRANSCHAN_LOCX;
        }
      }
      else if (STREQ(prop_name, "scale")) {
        if (src_index == 2) {
          dtar->transChan = DTAR_TRANSCHAN_SCALEZ;
        }
        else if (src_index == 1) {
          dtar->transChan = DTAR_TRANSCHAN_SCALEY;
        }
        else {
          dtar->transChan = DTAR_TRANSCHAN_SCALEX;
        }
      }
      else {
        /* XXX: With quaternions and axis-angle, this mapping might not be correct...
         *      But since those have 4 elements instead, there's not much we can do
         */
        if (src_index == 2) {
          dtar->transChan = DTAR_TRANSCHAN_ROTZ;
        }
        else if (src_index == 1) {
          dtar->transChan = DTAR_TRANSCHAN_ROTY;
        }
        else {
          dtar->transChan = DTAR_TRANSCHAN_ROTX;
        }
      }
    }
    else {
      /* Single RNA Property */
      DriverTarget *dtar = &dvar->targets[0];

      /* ID is as-is */
      dtar->id = src_id;
      dtar->idtype = GS(src_id->name);

      /* Need to make a copy of the path (or build one with array index built in) */
      if (RNA_property_array_check(src_prop)) {
        dtar->rna_path = BLI_sprintfN("%s[%d]", src_path, src_index);
      }
      else {
        dtar->rna_path = BLI_strdup(src_path);
      }
    }
  }

  /* set the done status */
  return (fcu != NULL);
}
예제 #12
0
/* for keyframes and drivers */
static int pyrna_struct_anim_args_parse(
        PointerRNA *ptr, const char *error_prefix, const char *path,
        const char **path_full, int *index)
{
	const bool is_idbase = RNA_struct_is_ID(ptr->type);
	PropertyRNA *prop;
	PointerRNA r_ptr;

	if (ptr->data == NULL) {
		PyErr_Format(PyExc_TypeError,
		             "%.200s this struct has no data, can't be animated",
		             error_prefix);
		return -1;
	}

	/* full paths can only be given from ID base */
	if (is_idbase) {
		int r_index = -1;
		if (RNA_path_resolve_property_full(ptr, path, &r_ptr, &prop, &r_index) == false) {
			prop = NULL;
		}
		else if (r_index != -1) {
			PyErr_Format(PyExc_ValueError,
			             "%.200s path includes index, must be a separate argument",
			             error_prefix, path);
			return -1;
		}
		else if (ptr->id.data != r_ptr.id.data) {
			PyErr_Format(PyExc_ValueError,
			             "%.200s path spans ID blocks",
			             error_prefix, path);
			return -1;
		}
	}
	else {
		prop = RNA_struct_find_property(ptr, path);
		r_ptr = *ptr;
	}

	if (prop == NULL) {
		PyErr_Format(PyExc_TypeError,
		             "%.200s property \"%s\" not found",
		             error_prefix, path);
		return -1;
	}

	if (!RNA_property_animateable(&r_ptr, prop)) {
		PyErr_Format(PyExc_TypeError,
		             "%.200s property \"%s\" not animatable",
		             error_prefix, path);
		return -1;
	}

	if (RNA_property_array_check(prop) == 0) {
		if ((*index) == -1) {
			*index = 0;
		}
		else {
			PyErr_Format(PyExc_TypeError,
			             "%.200s index %d was given while property \"%s\" is not an array",
			             error_prefix, *index, path);
			return -1;
		}
	}
	else {
		int array_len = RNA_property_array_length(&r_ptr, prop);
		if ((*index) < -1 || (*index) >= array_len) {
			PyErr_Format(PyExc_TypeError,
			             "%.200s index out of range \"%s\", given %d, array length is %d",
			             error_prefix, path, *index, array_len);
			return -1;
		}
	}

	if (is_idbase) {
		*path_full = BLI_strdup(path);
	}
	else {
		*path_full = RNA_path_from_ID_to_property(&r_ptr, prop);

		if (*path_full == NULL) {
			PyErr_Format(PyExc_TypeError,
			             "%.200s could not make path to \"%s\"",
			             error_prefix, path);
			return -1;
		}
	}

	return 0;
}