コード例 #1
0
ファイル: drivers.c プロジェクト: Walid-Shouman/Blender
static int paste_driver_button_exec(bContext *C, wmOperator *op)
{
	PointerRNA ptr = {{NULL}};
	PropertyRNA *prop = NULL;
	short success = 0;
	int index;
	
	/* try to create driver using property retrieved from UI */
	uiContextActiveProperty(C, &ptr, &prop, &index);
	
	if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
		char *path = get_driver_path_hack(C, &ptr, prop);
		
		if (path) {
			/* only copy the driver for the button that this was involved for */
			success = ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0);
			
			uiContextAnimUpdate(C);
			
			MEM_freeN(path);
		}
	}
	
	/* since we're just copying, we don't really need to do anything else...*/
	return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
コード例 #2
0
ファイル: drivers.c プロジェクト: dfelinto/blender
/* Wrapper for creating a driver without knowing what the targets will be yet
 * (i.e. "manual/add later"). */
static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_type)
{
  PointerRNA ptr = {{NULL}};
  PropertyRNA *prop = NULL;
  int index;
  int success = 0;

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

  if (mapping_type == CREATEDRIVER_MAPPING_NONE_ALL) {
    index = -1;
  }

  if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
    char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
    short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;

    if (path) {
      success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
      MEM_freeN(path);
    }
  }

  if (success) {
    /* send updates */
    UI_context_update_anim_flag(C);
    DEG_relations_tag_update(CTX_data_main(C));
    WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL);  // XXX

    return OPERATOR_FINISHED;
  }
  else {
    return OPERATOR_CANCELLED;
  }
}
コード例 #3
0
ファイル: drivers.c プロジェクト: Walid-Shouman/Blender
static int add_driver_button_exec(bContext *C, wmOperator *op)
{
	PointerRNA ptr = {{NULL}};
	PropertyRNA *prop = NULL;
	int success = 0;
	int index;
	const bool all = RNA_boolean_get(op->ptr, "all");
	
	/* try to create driver using property retrieved from UI */
	uiContextActiveProperty(C, &ptr, &prop, &index);
	
	if (all)
		index = -1;
	
	if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
		char *path = get_driver_path_hack(C, &ptr, prop);
		short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
		
		if (path) {
			success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
			
			MEM_freeN(path);
		}
	}
	
	if (success) {
		/* send updates */
		uiContextAnimUpdate(C);
		
		WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
	}
	
	return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
コード例 #4
0
ファイル: drivers.c プロジェクト: dfelinto/blender
static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
  PointerRNA ptr = {{NULL}};
  PropertyRNA *prop = NULL;
  int index;

  /* try to find driver using property retrieved from UI */
  UI_context_active_but_prop_get(C, &ptr, &prop, &index);

  if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
    /* 1) Create a new "empty" driver for this property */
    char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
    short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
    short success = 0;

    if (path) {
      success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
      MEM_freeN(path);
    }

    if (success) {
      /* send updates */
      UI_context_update_anim_flag(C);
      DEG_id_tag_update(ptr.id.data, ID_RECALC_COPY_ON_WRITE);
      DEG_relations_tag_update(CTX_data_main(C));
      WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL);
    }

    /* 2) Show editing panel for setting up this driver */
    /* TODO: Use a different one from the editing popever, so we can have the single/all toggle? */
    UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports);
  }

  return OPERATOR_INTERFACE;
}
コード例 #5
0
ファイル: drivers.c プロジェクト: dfelinto/blender
static int paste_driver_button_exec(bContext *C, wmOperator *op)
{
  PointerRNA ptr = {{NULL}};
  PropertyRNA *prop = NULL;
  short success = 0;
  int index;

  /* try to create driver using property retrieved from UI */
  UI_context_active_but_prop_get(C, &ptr, &prop, &index);

  if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
    char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);

    if (path) {
      /* only copy the driver for the button that this was involved for */
      success = ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0);

      UI_context_update_anim_flag(C);

      DEG_relations_tag_update(CTX_data_main(C));

      DEG_id_tag_update(ptr.id.data, ID_RECALC_ANIMATION);

      WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);  // XXX

      MEM_freeN(path);
    }
  }

  /* since we're just copying, we don't really need to do anything else...*/
  return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
コード例 #6
0
/* Recursively iterate over tree, finding and working on selected items */
static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBase *tree, short mode)
{
	TreeElement *te;
	TreeStoreElem *tselem;
	
	for (te= tree->first; te; te=te->next) {
		tselem= TREESTORE(te);
		
		/* if item is selected, perform operation */
		if (tselem->flag & TSE_SELECTED) {
			ID *id= NULL;
			char *path= NULL;
			int array_index= 0;
			short flag= 0;
			short groupmode= KSP_GROUP_KSNAME;
			
			/* check if RNA-property described by this selected element is an animateable prop */
			if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) && RNA_property_animateable(&te->rnaptr, te->directdata)) {
				/* get id + path + index info from the selected element */
				tree_element_to_path(soops, te, tselem, 
						&id, &path, &array_index, &flag, &groupmode);
			}
			
			/* only if ID and path were set, should we perform any actions */
			if (id && path) {
				/* action depends on mode */
				switch (mode) {
					case KEYINGSET_EDITMODE_ADD:
					{
						/* add a new path with the information obtained (only if valid) */
						// TODO: what do we do with group name? for now, we don't supply one, and just let this use the KeyingSet name
						BKE_keyingset_add_path(ks, id, NULL, path, array_index, flag, groupmode);
						ks->active_path= BLI_countlist(&ks->paths);
					}
						break;
					case KEYINGSET_EDITMODE_REMOVE:
					{
						/* find the relevant path, then remove it from the KeyingSet */
						KS_Path *ksp= BKE_keyingset_find_path(ks, id, NULL, path, array_index, groupmode);
						
						if (ksp) {
							/* free path's data */
							BKE_keyingset_free_path(ks, ksp);

							ks->active_path= 0;
						}
					}
						break;
				}
				
				/* free path, since it had to be generated */
				MEM_freeN(path);
			}
		}
		
		/* go over sub-tree */
		if ((tselem->flag & TSE_CLOSED)==0)
			do_outliner_keyingset_editop(soops, ks, &te->subtree, mode);
	}
}
コード例 #7
0
static int add_driver_button_poll(bContext *C)
{
	PointerRNA ptr = {{NULL}};
	PropertyRNA *prop = NULL;
	int index;
	
	/* this operator can only run if there's a property button active, and it can be animated */
	UI_context_active_but_prop_get(C, &ptr, &prop, &index);
	return (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop));
}
コード例 #8
0
ファイル: interface_anim.c プロジェクト: jinjoh/NOOR
static FCurve *ui_but_get_fcurve(uiBut *but, bAction **action, int *driven)
{
	FCurve *fcu= NULL;

	*driven= 0;

	/* there must be some RNA-pointer + property combo for this button */
	if(but->rnaprop && but->rnapoin.id.data && 
		RNA_property_animateable(&but->rnapoin, but->rnaprop)) 
	{
		AnimData *adt= BKE_animdata_from_id(but->rnapoin.id.data);
		char *path;
		
		if(adt) {
			if((adt->action && adt->action->curves.first) || (adt->drivers.first)) {
				/* XXX this function call can become a performance bottleneck */
				path= RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);

				if(path) {
					/* animation takes priority over drivers */
					if(adt->action && adt->action->curves.first)
						fcu= list_find_fcurve(&adt->action->curves, path, but->rnaindex);
					
					/* if not animated, check if driven */
					if(!fcu && (adt->drivers.first)) {
						fcu= list_find_fcurve(&adt->drivers, path, but->rnaindex);
						
						if(fcu)
							*driven= 1;
					}

					if(fcu && action)
						*action= adt->action;

					MEM_freeN(path);
				}
			}
		}
	}

	return fcu;
}
コード例 #9
0
ファイル: interface_eyedropper.c プロジェクト: diekev/blender
static bool driverdropper_init(bContext *C, wmOperator *op)
{
	DriverDropper *ddr;
	uiBut *but;

	op->customdata = ddr = MEM_callocN(sizeof(DriverDropper), "DriverDropper");

	but = UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &ddr->index);

	if ((ddr->ptr.data == NULL) ||
	    (ddr->prop == NULL) ||
	    (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
	    (RNA_property_animateable(&ddr->ptr, ddr->prop) == false) ||
	    (but->flag & UI_BUT_DRIVEN))
	{
		return false;
	}
	
	return true;
}
コード例 #10
0
ファイル: drivers.c プロジェクト: dfelinto/blender
static bool add_driver_button_poll(bContext *C)
{
  PointerRNA ptr = {{NULL}};
  PropertyRNA *prop = NULL;
  int index;
  bool driven, special;

  /* this operator can only run if there's a property button active, and it can be animated */
  UI_context_active_but_prop_get(C, &ptr, &prop, &index);

  if (!(ptr.id.data && ptr.data && prop)) {
    return false;
  }
  if (!RNA_property_animateable(&ptr, prop)) {
    return false;
  }

  /* Don't do anything if there is an fcurve for animation without a driver. */
  FCurve *fcu = rna_get_fcurve_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
  return (fcu == NULL || fcu->driver);
}
コード例 #11
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;
}
コード例 #12
0
ファイル: keyingsets.c プロジェクト: castlelore/blender-git
static int add_keyingset_button_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	KeyingSet *ks = NULL;
	PropertyRNA *prop = NULL;
	PointerRNA ptr = {{NULL}};
	char *path = NULL;
	short success = 0;
	int index = 0, pflag = 0;
	const bool all = RNA_boolean_get(op->ptr, "all");
	
	/* verify the Keying Set to use:
	 *	- use the active one for now (more control over this can be added later)
	 *	- add a new one if it doesn't exist 
	 */
	if (scene->active_keyingset == 0) {
		short flag = 0, keyingflag = 0;
		
		/* validate flags 
		 *	- absolute KeyingSets should be created by default
		 */
		flag |= KEYINGSET_ABSOLUTE;
		
		keyingflag |= ANIM_get_keyframing_flags(scene, 0);
		
		if (IS_AUTOKEY_FLAG(scene, XYZ2RGB)) 
			keyingflag |= INSERTKEY_XYZ2RGB;
			
		/* call the API func, and set the active keyingset index */
		ks = BKE_keyingset_add(&scene->keyingsets, "ButtonKeyingSet", "Button Keying Set", flag, keyingflag);
		
		scene->active_keyingset = BLI_countlist(&scene->keyingsets);
	}
	else if (scene->active_keyingset < 0) {
		BKE_report(op->reports, RPT_ERROR, "Cannot add property to built in keying set");
		return OPERATOR_CANCELLED;
	}
	else {
		ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
	}
	
	/* try to add to keyingset using property retrieved from UI */
	uiContextActiveProperty(C, &ptr, &prop, &index);
	
	/* check if property is able to be added */
	if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
		path = RNA_path_from_ID_to_property(&ptr, prop);
		
		if (path) {
			/* set flags */
			if (all) {
				pflag |= KSP_FLAG_WHOLE_ARRAY;
				
				/* we need to set the index for this to 0, even though it may break in some cases, this is 
				 * necessary if we want the entire array for most cases to get included without the user
				 * having to worry about where they clicked
				 */
				index = 0;
			}
				
			/* add path to this setting */
			BKE_keyingset_add_path(ks, ptr.id.data, NULL, path, index, pflag, KSP_GROUP_KSNAME);
			ks->active_path = BLI_countlist(&ks->paths);
			success = 1;
			
			/* free the temp path created */
			MEM_freeN(path);
		}
	}
	
	if (success) {
		/* send updates */
		WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
		
		/* show notification/report header, so that users notice that something changed */
		BKE_reportf(op->reports, RPT_INFO, "Property added to Keying Set: '%s'", ks->name);
	}
	
	return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
コード例 #13
0
ファイル: bpy_rna_anim.c プロジェクト: DrangPo/blender
/* 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;
}
コード例 #14
0
/* Recursively iterate over tree, finding and working on selected items */
static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, ReportList *reports, short mode)
{
	TreeElement *te;
	TreeStoreElem *tselem;
	
	for (te= tree->first; te; te=te->next) {
		tselem= TREESTORE(te);
		
		/* if item is selected, perform operation */
		if (tselem->flag & TSE_SELECTED) {
			ID *id= NULL;
			char *path= NULL;
			int array_index= 0;
			short flag= 0;
			short groupmode= KSP_GROUP_KSNAME;
			
			/* check if RNA-property described by this selected element is an animateable prop */
			if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) && RNA_property_animateable(&te->rnaptr, te->directdata)) {
				/* get id + path + index info from the selected element */
				tree_element_to_path(soops, te, tselem, 
						&id, &path, &array_index, &flag, &groupmode);
			}
			
			/* only if ID and path were set, should we perform any actions */
			if (id && path) {
				short dflags = CREATEDRIVER_WITH_DEFAULT_DVAR;
				int arraylen = 1;
				
				/* array checks */
				if (flag & KSP_FLAG_WHOLE_ARRAY) {
					/* entire array was selected, so add drivers for all */
					arraylen= RNA_property_array_length(&te->rnaptr, te->directdata);
				}
				else
					arraylen= array_index;
				
				/* we should do at least one step */
				if (arraylen == array_index)
					arraylen++;
				
				/* for each array element we should affect, add driver */
				for (; array_index < arraylen; array_index++) {
					/* action depends on mode */
					switch (mode) {
						case DRIVERS_EDITMODE_ADD:
						{
							/* add a new driver with the information obtained (only if valid) */
							ANIM_add_driver(reports, id, path, array_index, dflags, DRIVER_TYPE_PYTHON);
						}
							break;
						case DRIVERS_EDITMODE_REMOVE:
						{
							/* remove driver matching the information obtained (only if valid) */
							ANIM_remove_driver(reports, id, path, array_index, dflags);
						}
							break;
					}
				}
				
				/* free path, since it had to be generated */
				MEM_freeN(path);
			}
			
			
		}
		
		/* go over sub-tree */
		if ((tselem->flag & TSE_CLOSED)==0)
			do_outliner_drivers_editop(soops, &te->subtree, reports, mode);
	}
}
コード例 #15
0
ファイル: keyingsets.c プロジェクト: jinjoh/NOOR
static int add_keyingset_button_exec (bContext *C, wmOperator *op)
{
	Scene *scene= CTX_data_scene(C);
	KeyingSet *ks = NULL;
	PropertyRNA *prop= NULL;
	PointerRNA ptr;
	char *path = NULL;
	short success= 0;
	int index=0, pflag=0;
	int all= RNA_boolean_get(op->ptr, "all");
	
	/* verify the Keying Set to use:
	 *	- use the active one for now (more control over this can be added later)
	 *	- add a new one if it doesn't exist 
	 */
	if (scene->active_keyingset == 0) {
		short flag=0, keyingflag=0;
		
		/* validate flags 
		 *	- absolute KeyingSets should be created by default
		 */
		flag |= KEYINGSET_ABSOLUTE;
		
		if (IS_AUTOKEY_FLAG(AUTOMATKEY)) 
			keyingflag |= INSERTKEY_MATRIX;
		if (IS_AUTOKEY_FLAG(INSERTNEEDED)) 
			keyingflag |= INSERTKEY_NEEDED;
			
		/* call the API func, and set the active keyingset index */
		ks= BKE_keyingset_add(&scene->keyingsets, "ButtonKeyingSet", flag, keyingflag);
		
		scene->active_keyingset= BLI_countlist(&scene->keyingsets);
	}
	else
		ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
	
	/* try to add to keyingset using property retrieved from UI */
	memset(&ptr, 0, sizeof(PointerRNA));
	uiAnimContextProperty(C, &ptr, &prop, &index);
	
	/* check if property is able to be added */
	if (ptr.data && prop && RNA_property_animateable(ptr.data, prop)) {
		path= RNA_path_from_ID_to_property(&ptr, prop);
		
		if (path) {
			/* set flags */
			if (all) {
				pflag |= KSP_FLAG_WHOLE_ARRAY;
				
				/* we need to set the index for this to 0, even though it may break in some cases, this is 
				 * necessary if we want the entire array for most cases to get included without the user
				 * having to worry about where they clicked
				 */
				index= 0;
			}
				
			/* add path to this setting */
			BKE_keyingset_add_destination(ks, ptr.id.data, NULL, path, index, pflag, KSP_GROUP_KSNAME);
			ks->active_path= BLI_countlist(&ks->paths);
			success= 1;
			
			/* free the temp path created */
			MEM_freeN(path);
		}
	}
	
	if (success) {
		/* send updates */
		ED_anim_dag_flush_update(C);	
		
		/* for now, only send ND_KEYS for KeyingSets */
		WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL);
	}
	
	return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
}