void buttons_context_draw(const bContext *C, uiLayout *layout)
{
	SpaceButs *sbuts = CTX_wm_space_buts(C);
	ButsContextPath *path = sbuts->path;
	uiLayout *row;
	uiBlock *block;
	uiBut *but;
	PointerRNA *ptr;
	char namebuf[128], *name;
	int a, icon;

	if (!path)
		return;

	row = uiLayoutRow(layout, true);
	uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);

	block = uiLayoutGetBlock(row);
	UI_block_emboss_set(block, UI_EMBOSS_NONE);
	but = uiDefIconButBitC(block, UI_BTYPE_ICON_TOGGLE, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag,
	                       0, 0, 0, 0, TIP_("Follow context or keep fixed datablock displayed"));
	UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
	UI_but_func_set(but, pin_cb, NULL, NULL);

	for (a = 0; a < path->len; a++) {
		ptr = &path->ptr[a];

		if (a != 0)
			uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC);

		if (ptr->data) {
			icon = RNA_struct_ui_icon(ptr->type);
			name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);

			if (name) {
				if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene)
					uiItemLDrag(row, ptr, "", icon);  /* save some space */
				else
					uiItemLDrag(row, ptr, name, icon);

				if (name != namebuf)
					MEM_freeN(name);
			}
			else
				uiItemL(row, "", icon);
		}
	}
}
예제 #2
0
/* Helper func to extract an RNA path from selected tree element 
 * NOTE: the caller must zero-out all values of the pointers that it passes here first, as
 * this function does not do that yet 
 */
static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, 
							ID **id, char **path, int *array_index, short *flag, short *UNUSED(groupmode))
{
	ListBase hierarchy = {NULL, NULL};
	LinkData *ld;
	TreeElement *tem, *temnext, *temsub;
	TreeStoreElem *tse, *tsenext;
	PointerRNA *ptr, *nextptr;
	PropertyRNA *prop;
	char *newpath=NULL;
	
	/* optimise tricks:
	 *	- Don't do anything if the selected item is a 'struct', but arrays are allowed
	 */
	if (tselem->type == TSE_RNA_STRUCT)
		return;
	
	/* Overview of Algorithm:
	 * 	1. Go up the chain of parents until we find the 'root', taking note of the 
	 *	   levels encountered in reverse-order (i.e. items are added to the start of the list
	 *      for more convenient looping later)
	 * 	2. Walk down the chain, adding from the first ID encountered 
	 *	   (which will become the 'ID' for the KeyingSet Path), and build a  
	 * 		path as we step through the chain
	 */
	 
	/* step 1: flatten out hierarchy of parents into a flat chain */
	for (tem= te->parent; tem; tem= tem->parent) {
		ld= MEM_callocN(sizeof(LinkData), "LinkData for tree_element_to_path()");
		ld->data= tem;
		BLI_addhead(&hierarchy, ld);
	}
	
	/* step 2: step down hierarchy building the path (NOTE: addhead in previous loop was needed so that we can loop like this) */
	for (ld= hierarchy.first; ld; ld= ld->next) {
		/* get data */
		tem= (TreeElement *)ld->data;
		tse= TREESTORE(tem);
		ptr= &tem->rnaptr;
		prop= tem->directdata;
		
		/* check if we're looking for first ID, or appending to path */
		if (*id) {
			/* just 'append' property to path 
			 *	- to prevent memory leaks, we must write to newpath not path, then free old path + swap them
			 */
			if(tse->type == TSE_RNA_PROPERTY) {
				if(RNA_property_type(prop) == PROP_POINTER) {
					/* for pointer we just append property name */
					newpath= RNA_path_append(*path, ptr, prop, 0, NULL);
				}
				else if(RNA_property_type(prop) == PROP_COLLECTION) {
					char buf[128], *name;
					
					temnext= (TreeElement*)(ld->next->data);
					tsenext= TREESTORE(temnext);
					
					nextptr= &temnext->rnaptr;
					name= RNA_struct_name_get_alloc(nextptr, buf, sizeof(buf));
					
					if(name) {
						/* if possible, use name as a key in the path */
						newpath= RNA_path_append(*path, NULL, prop, 0, name);
						
						if(name != buf)
							MEM_freeN(name);
					}
					else {
						/* otherwise use index */
						int index= 0;
						
						for(temsub=tem->subtree.first; temsub; temsub=temsub->next, index++)
							if(temsub == temnext)
								break;
						
						newpath= RNA_path_append(*path, NULL, prop, index, NULL);
					}
					
					ld= ld->next;
				}
			}
			
			if(newpath) {
				if (*path) MEM_freeN(*path);
				*path= newpath;
				newpath= NULL;
			}
		}
		else {
			/* no ID, so check if entry is RNA-struct, and if that RNA-struct is an ID datablock to extract info from */
			if (tse->type == TSE_RNA_STRUCT) {
				/* ptr->data not ptr->id.data seems to be the one we want, since ptr->data is sometimes the owner of this ID? */
				if(RNA_struct_is_ID(ptr->type)) {
					*id= (ID *)ptr->data;
					
					/* clear path */
					if(*path) {
						MEM_freeN(*path);
						path= NULL;
					}
				}
			}
		}
	}

	/* step 3: if we've got an ID, add the current item to the path */
	if (*id) {
		/* add the active property to the path */
		ptr= &te->rnaptr;
		prop= te->directdata;
		
		/* array checks */
		if (tselem->type == TSE_RNA_ARRAY_ELEM) {
			/* item is part of an array, so must set the array_index */
			*array_index= te->index;
		}
		else if (RNA_property_array_length(ptr, prop)) {
			/* entire array was selected, so keyframe all */
			*flag |= KSP_FLAG_WHOLE_ARRAY;
		}
		
		/* path */
		newpath= RNA_path_append(*path, NULL, prop, 0, NULL);
		if (*path) MEM_freeN(*path);
		*path= newpath;
	}

	/* free temp data */
	BLI_freelistN(&hierarchy);
}