/**
 * called from both exec & poll
 *
 * \note: normally we wouldn't call a loop from within a poll function,
 * However this is a special case, and for regular poll calls, getting
 * the context from the button will fail early.
 */
static bool copy_to_selected_button(bContext *C, bool all, bool poll)
{
	PointerRNA ptr, lptr, idptr;
	PropertyRNA *prop, *lprop;
	bool success = false;
	int index;

	/* try to reset the nominated setting to its default value */
	uiContextActiveProperty(C, &ptr, &prop, &index);

	/* if there is a valid property that is editable... */
	if (ptr.data && prop) {
		char *path = NULL;
		bool use_path;
		CollectionPointerLink *link;
		ListBase lb;

		if (!copy_to_selected_list(C, &ptr, &lb, &use_path))
			return success;

		if (!use_path || (path = RNA_path_from_ID_to_property(&ptr, prop))) {
			for (link = lb.first; link; link = link->next) {
				if (link->ptr.data != ptr.data) {
					if (use_path) {
						lprop = NULL;
						RNA_id_pointer_create(link->ptr.id.data, &idptr);
						RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
					}
					else {
						lptr = link->ptr;
						lprop = prop;
					}

					if (lprop == prop) {
						if (RNA_property_editable(&lptr, lprop)) {
							if (poll) {
								success = true;
								break;
							}
							else {
								if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
									RNA_property_update(C, &lptr, prop);
									success = true;
								}
							}
						}
					}
				}
			}

			if (path)
				MEM_freeN(path);
		}

		BLI_freelistN(&lb);
	}

	return success;
}
Example #2
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;
}
Example #3
0
static int remove_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;
	
	/* verify the Keying Set to use:
	 *	- use the active one for now (more control over this can be added later)
	 *	- return error if it doesn't exist
	 */
	if (scene->active_keyingset == 0) {
		BKE_report(op->reports, RPT_ERROR, "No active keying set to remove property from");
		return OPERATOR_CANCELLED;
	}
	else if (scene->active_keyingset < 0) {
		BKE_report(op->reports, RPT_ERROR, "Cannot remove property from 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);

	if (ptr.id.data && ptr.data && prop) {
		path = RNA_path_from_ID_to_property(&ptr, prop);
		
		if (path) {
			KS_Path *ksp;
			
			/* try to find a path matching this description */
			ksp = BKE_keyingset_find_path(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME);
			
			if (ksp) {
				BKE_keyingset_free_path(ks, ksp);
				success = 1;
			}
			
			/* free temp path used */
			MEM_freeN(path);
		}
	}
	
	
	if (success) {
		/* send updates */
		WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
		
		/* show warning */
		BKE_report(op->reports, RPT_INFO, "Property removed from Keying Set");
	}
	
	return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
Example #4
0
static int remove_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;
	
	/* verify the Keying Set to use:
	 *	- use the active one for now (more control over this can be added later)
	 *	- return error if it doesn't exist
	 */
	if (scene->active_keyingset == 0) {
		BKE_report(op->reports, RPT_ERROR, "No active Keying Set to remove property from");
		return OPERATOR_CANCELLED;
	}
	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);

	if (ptr.data && prop) {
		path= RNA_path_from_ID_to_property(&ptr, prop);
		
		if (path) {
			KS_Path *ksp;
			
			/* try to find a path matching this description */
			ksp= BKE_keyingset_find_destination(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME);
			
			if (ksp) {
				/* just free it... */
				MEM_freeN(ksp->rna_path);
				BLI_freelinkN(&ks->paths, ksp);
				
				success= 1;
			}
			
			/* free temp path used */
			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;
}
Example #5
0
/* Temporary wrapper for driver operators for buttons to make it easier to create
 * such drivers by rerouting all paths through the active object instead so that
 * they will get picked up by the dependency system.
 *
 * < C: context pointer - for getting active data 
 * <> ptr: RNA pointer for property's datablock. May be modified as result of path remapping.
 * < prop: RNA definition of property to add for
 *
 * > returns: MEM_alloc'd string representing the path to the property from the given PointerRNA
 */
static char *get_driver_path_hack(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
{
	ID *id = (ID *)ptr->id.data;
	ScrArea *sa = CTX_wm_area(C);
	
	/* get standard path which may be extended */
	char *basepath = RNA_path_from_ID_to_property(ptr, prop);
	char *path = basepath; /* in case no remapping is needed */
	
	
	/* Remapping will only be performed in the Properties Editor, as only this 
	 * restricts the subspace of options to the 'active' data (a manageable state)
	 */
	// TODO: watch out for pinned context?
	if ((sa) && (sa->spacetype == SPACE_BUTS)) {
		Object *ob = CTX_data_active_object(C);
		
		if (ob && id) {
			/* only id-types which can be remapped to go through objects should be considered */
			switch (GS(id->name)) {
				case ID_TE: /* textures */
				{
					Material *ma = give_current_material(ob, ob->actcol);
					Tex *tex = give_current_material_texture(ma);
					
					/* assumes: texture will only be shown if it is active material's active texture it's ok */
					if ((ID *)tex == id) {
						char name_esc_ma[(sizeof(ma->id.name) - 2) * 2];
						char name_esc_tex[(sizeof(tex->id.name) - 2) * 2];

						BLI_strescape(name_esc_ma, ma->id.name + 2, sizeof(name_esc_ma));
						BLI_strescape(name_esc_tex, tex->id.name + 2, sizeof(name_esc_tex));

						/* create new path */
						// TODO: use RNA path functions to construct step by step instead?
						// FIXME: maybe this isn't even needed anymore...
						path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s", 
						                    name_esc_ma, name_esc_tex, basepath);
							
						/* free old one */
						MEM_freeN(basepath);
					}
					break;
				}
			}
			
			/* fix RNA pointer, as we've now changed the ID root by changing the paths */
			if (basepath != path) {
				/* rebase provided pointer so that it starts from object... */
				RNA_pointer_create(&ob->id, ptr->type, ptr->data, ptr);
			}
		}
	}
	
	/* the path should now have been corrected for use */
	return path;
}
Example #6
0
static int copy_to_selected_button_exec(bContext *C, wmOperator *op)
{
	PointerRNA ptr, lptr, idptr;
	PropertyRNA *prop, *lprop;
	int success = 0;
	int index, all = RNA_boolean_get(op->ptr, "all");

	/* try to reset the nominated setting to its default value */
	uiContextActiveProperty(C, &ptr, &prop, &index);
	
	/* if there is a valid property that is editable... */
	if (ptr.data && prop) {
		char *path = NULL;
		int use_path;
		CollectionPointerLink *link;
		ListBase lb;

		if (!copy_to_selected_list(C, &ptr, &lb, &use_path))
			return success;

		if (!use_path || (path = RNA_path_from_ID_to_property(&ptr, prop))) {
			for (link = lb.first; link; link = link->next) {
				if (link->ptr.data != ptr.data) {
					if (use_path) {
						lprop = NULL;
						RNA_id_pointer_create(link->ptr.id.data, &idptr);
						RNA_path_resolve(&idptr, path, &lptr, &lprop);
					}
					else {
						lptr = link->ptr;
						lprop = prop;
					}

					if (lprop == prop) {
						if (RNA_property_editable(&lptr, lprop)) {
							if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
								RNA_property_update(C, &lptr, prop);
								success = 1;
							}
						}
					}
				}
			}

			if (path)
				MEM_freeN(path);
		}

		BLI_freelistN(&lb);
	}
	
	return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
Example #7
0
static int copy_to_selected_button_poll(bContext *C)
{
	PointerRNA ptr, lptr, idptr;
	PropertyRNA *prop, *lprop;
	int index, success = 0;

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

	if (ptr.data && prop) {
		char *path = NULL;
		int use_path;
		CollectionPointerLink *link;
		ListBase lb;

		if (!copy_to_selected_list(C, &ptr, &lb, &use_path))
			return success;

		if (!use_path || (path = RNA_path_from_ID_to_property(&ptr, prop))) {
			for (link = lb.first; link; link = link->next) {
				if (link->ptr.data != ptr.data) {
					if (use_path) {
						lprop = NULL;
						RNA_id_pointer_create(link->ptr.id.data, &idptr);
						RNA_path_resolve(&idptr, path, &lptr, &lprop);
					}
					else {
						lptr = link->ptr;
						lprop = prop;
					}

					if (lprop == prop) {
						if (RNA_property_editable(&lptr, prop))
							success = 1;
					}
				}
			}

			if (path)
				MEM_freeN(path);
		}

		BLI_freelistN(&lb);
	}

	return success;
}
Example #8
0
static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *event)
{
	DriverDropper *ddr = (DriverDropper *)op->customdata;
	uiBut *but = eyedropper_get_property_button_under_mouse(C, event);
	
	short mapping_type = RNA_enum_get(op->ptr, "mapping_type");
	short flag = 0;
	
	/* we can only add a driver if we know what RNA property it corresponds to */
	if (but == NULL) {
		return;
	}
	else {
		/* Get paths for src... */
		PointerRNA *target_ptr = &but->rnapoin;
		PropertyRNA *target_prop = but->rnaprop;
		int target_index = but->rnaindex;
		
		char *target_path = RNA_path_from_ID_to_property(target_ptr, target_prop);
		
		/* ... and destination */
		char *dst_path    = BKE_animdata_driver_path_hack(C, &ddr->ptr, ddr->prop, NULL);
		
		/* Now create driver(s) */
		if (target_path && dst_path) {
			int success = ANIM_add_driver_with_target(op->reports,
			                                          ddr->ptr.id.data, dst_path, ddr->index,
			                                          target_ptr->id.data, target_path, target_index,
			                                          flag, DRIVER_TYPE_PYTHON, mapping_type);
			
			if (success) {
				/* send updates */
				UI_context_update_anim_flag(C);
				DAG_relations_tag_update(CTX_data_main(C));
				DAG_id_tag_update(ddr->ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA);
				WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL);  // XXX
			}
		}
		
		/* cleanup */
		if (target_path)
			MEM_freeN(target_path);
		if (dst_path)
			MEM_freeN(dst_path);
	}
}
Example #9
0
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;
}
static int copy_data_path_button_poll(bContext *C)
{
	PointerRNA ptr;
	PropertyRNA *prop;
	char *path;
	int index;

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

	if (ptr.id.data && ptr.data && prop) {
		path = RNA_path_from_ID_to_property(&ptr, prop);
		
		if (path) {
			MEM_freeN(path);
			return 1;
		}
	}

	return 0;
}
Example #11
0
static bool copy_to_selected_list(
        bContext *C, PointerRNA *ptr, PropertyRNA *prop,
        ListBase *r_lb, bool *r_use_path_from_id, char **r_path)
{
	*r_use_path_from_id = false;
	*r_path = NULL;

	if (RNA_struct_is_a(ptr->type, &RNA_EditBone)) {
		*r_lb = CTX_data_collection_get(C, "selected_editable_bones");
	}
	else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
		*r_lb = CTX_data_collection_get(C, "selected_pose_bones");
	}
	else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
		*r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
	}
	else if (ptr->id.data) {
		ID *id = ptr->id.data;

		if (GS(id->name) == ID_OB) {
			*r_lb = CTX_data_collection_get(C, "selected_editable_objects");
			*r_use_path_from_id = true;
			*r_path = RNA_path_from_ID_to_property(ptr, prop);
		}
		else if (GS(id->name) == ID_SCE) {
			/* Sequencer's ID is scene :/ */
			/* Try to recursively find an RNA_Sequence ancestor, to handle situations like T41062... */
			if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence)) != NULL) {
				*r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
			}
		}
		return (*r_path != NULL);
	}
	else {
		return false;
	}

	return true;
}
static int copy_data_path_button_exec(bContext *C, wmOperator *UNUSED(op))
{
	PointerRNA ptr;
	PropertyRNA *prop;
	char *path;
	int index;

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

	if (ptr.id.data && ptr.data && prop) {
		path = RNA_path_from_ID_to_property(&ptr, prop);
		
		if (path) {
			WM_clipboard_text_set(path, false);
			MEM_freeN(path);
			return OPERATOR_FINISHED;
		}
	}

	return OPERATOR_CANCELLED;
}
Example #13
0
static int copy_data_path_button_exec(bContext *C, wmOperator *UNUSED(op))
{
	PointerRNA ptr;
	PropertyRNA *prop;
	char *path;
	int 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) {
		path= RNA_path_from_ID_to_property(&ptr, prop);
		
		if (path) {
			WM_clipboard_text_set(path, FALSE);
			MEM_freeN(path);
		}
	}

	/* since we're just copying, we don't really need to do anything else...*/
	return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
}
Example #14
0
static int copy_data_path_button_exec(bContext *C, wmOperator *op)
{
  PointerRNA ptr;
  PropertyRNA *prop;
  char *path;
  int index;

  const bool full_path = RNA_boolean_get(op->ptr, "full_path");

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

  if (ptr.id.data != NULL) {

    if (full_path) {

      if (prop) {
        path = RNA_path_full_property_py_ex(&ptr, prop, index, true);
      }
      else {
        path = RNA_path_full_struct_py(&ptr);
      }
    }
    else {
      path = RNA_path_from_ID_to_property(&ptr, prop);
    }

    if (path) {
      WM_clipboard_text_set(path, false);
      MEM_freeN(path);
      return OPERATOR_FINISHED;
    }
  }

  return OPERATOR_CANCELLED;
}
Example #15
0
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;
}
Example #16
0
/* create new expression for button (i.e. a "scripted driver"), if it can be created... */
int ui_but_anim_expression_create(uiBut *but, const char *str)
{
	bContext *C = but->block->evil_C;
	ID *id;
	FCurve *fcu;
	char *path;
	short ok=0;
	
	/* button must have RNA-pointer to a numeric-capable property */
	if (ELEM(NULL, but->rnapoin.data, but->rnaprop)) {
		if (G.f & G_DEBUG) 
			printf("ERROR: create expression failed - button has no RNA info attached\n");
		return 0;
	}
	
	/* 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.f & G_DEBUG)
			printf("ERROR: create expression failed - invalid id-datablock for adding drivers (%p)\n", id);
		return 0;
	}
	
	/* 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(driver->expression, str, sizeof(driver->expression));
			
			/* FIXME: for now, assume that 
			 * 	- for expressions, users are likely to be using "frame" -> current frame" as a variable
			 *	- driver_add_new_variable() adds a single-prop variable by default
			 */
			{
				DriverVar *dvar;
				DriverTarget *dtar;
				
				dvar = driver_add_new_variable(driver);
				BLI_strncpy(dvar->name, "frame", sizeof(dvar->name));
				
				dtar = &dvar->targets[0];
				dtar->id = (ID *)CTX_data_scene(C); // XXX: should we check that C is valid first?
				dtar->rna_path = BLI_sprintfN("frame_current");
			}
			
			/* updates */
			driver->flag |= DRIVER_FLAG_RECOMPILE;
			WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME, NULL);
		}
	}
	
	MEM_freeN(path);
	
	return ok;
}
Example #17
0
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;
}
Example #18
0
bool UI_context_copy_to_selected_list(bContext *C,
                                      PointerRNA *ptr,
                                      PropertyRNA *prop,
                                      ListBase *r_lb,
                                      bool *r_use_path_from_id,
                                      char **r_path)
{
  *r_use_path_from_id = false;
  *r_path = NULL;

  if (RNA_struct_is_a(ptr->type, &RNA_EditBone)) {
    *r_lb = CTX_data_collection_get(C, "selected_editable_bones");
  }
  else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
    *r_lb = CTX_data_collection_get(C, "selected_pose_bones");
  }
  else if (RNA_struct_is_a(ptr->type, &RNA_Bone)) {
    ListBase lb;
    lb = CTX_data_collection_get(C, "selected_pose_bones");

    if (!BLI_listbase_is_empty(&lb)) {
      CollectionPointerLink *link;
      for (link = lb.first; link; link = link->next) {
        bPoseChannel *pchan = link->ptr.data;
        RNA_pointer_create(link->ptr.id.data, &RNA_Bone, pchan->bone, &link->ptr);
      }
    }

    *r_lb = lb;
  }
  else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
    *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
  }
  else if (RNA_struct_is_a(ptr->type, &RNA_FCurve)) {
    *r_lb = CTX_data_collection_get(C, "selected_editable_fcurves");
  }
  else if (RNA_struct_is_a(ptr->type, &RNA_Node) || RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
    ListBase lb = {NULL, NULL};
    char *path = NULL;
    bNode *node = NULL;

    /* Get the node we're editing */
    if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
      bNodeTree *ntree = ptr->id.data;
      bNodeSocket *sock = ptr->data;
      if (nodeFindNode(ntree, sock, &node, NULL)) {
        if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != NULL) {
          /* we're good! */
        }
        else {
          node = NULL;
        }
      }
    }
    else {
      node = ptr->data;
    }

    /* Now filter by type */
    if (node) {
      CollectionPointerLink *link, *link_next;
      lb = CTX_data_collection_get(C, "selected_nodes");

      for (link = lb.first; link; link = link_next) {
        bNode *node_data = link->ptr.data;
        link_next = link->next;

        if (node_data->type != node->type) {
          BLI_remlink(&lb, link);
          MEM_freeN(link);
        }
      }
    }

    *r_lb = lb;
    *r_path = path;
  }
  else if (ptr->id.data) {
    ID *id = ptr->id.data;

    if (GS(id->name) == ID_OB) {
      *r_lb = CTX_data_collection_get(C, "selected_editable_objects");
      *r_use_path_from_id = true;
      *r_path = RNA_path_from_ID_to_property(ptr, prop);
    }
    else if (OB_DATA_SUPPORT_ID(GS(id->name))) {
      /* check we're using the active object */
      const short id_code = GS(id->name);
      ListBase lb = CTX_data_collection_get(C, "selected_editable_objects");
      char *path = RNA_path_from_ID_to_property(ptr, prop);

      /* de-duplicate obdata */
      if (!BLI_listbase_is_empty(&lb)) {
        CollectionPointerLink *link, *link_next;

        for (link = lb.first; link; link = link->next) {
          Object *ob = link->ptr.id.data;
          if (ob->data) {
            ID *id_data = ob->data;
            id_data->tag |= LIB_TAG_DOIT;
          }
        }

        for (link = lb.first; link; link = link_next) {
          Object *ob = link->ptr.id.data;
          ID *id_data = ob->data;
          link_next = link->next;

          if ((id_data == NULL) || (id_data->tag & LIB_TAG_DOIT) == 0 || ID_IS_LINKED(id_data) ||
              (GS(id_data->name) != id_code)) {
            BLI_remlink(&lb, link);
            MEM_freeN(link);
          }
          else {
            /* avoid prepending 'data' to the path */
            RNA_id_pointer_create(id_data, &link->ptr);
          }

          if (id_data) {
            id_data->tag &= ~LIB_TAG_DOIT;
          }
        }
      }

      *r_lb = lb;
      *r_path = path;
    }
    else if (GS(id->name) == ID_SCE) {
      /* Sequencer's ID is scene :/ */
      /* Try to recursively find an RNA_Sequence ancestor,
       * to handle situations like T41062... */
      if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence)) != NULL) {
        *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
      }
    }
    return (*r_path != NULL);
  }
  else {
    return false;
  }

  return true;
}
Example #19
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;
}