Esempio n. 1
0
void outliner_do_object_operation(bContext *C, Scene *scene_act, SpaceOops *soops, ListBase *lb, 
                                  void (*operation_cb)(bContext *C, Scene *scene, TreeElement *,
                                                       TreeStoreElem *, TreeStoreElem *))
{
	TreeElement *te;
	TreeStoreElem *tselem;
	
	for (te = lb->first; te; te = te->next) {
		tselem = TREESTORE(te);
		if (tselem->flag & TSE_SELECTED) {
			if (tselem->type == 0 && te->idcode == ID_OB) {
				// when objects selected in other scenes... dunno if that should be allowed
				Scene *scene_owner = (Scene *)outliner_search_back(soops, te, ID_SCE);
				if (scene_owner && scene_act != scene_owner) {
					ED_screen_set_scene(C, CTX_wm_screen(C), scene_owner);
				}
				/* important to use 'scene_owner' not scene_act else deleting objects can crash.
				 * only use 'scene_act' when 'scene_owner' is NULL, which can happen when the
				 * outliner isn't showing scenes: Visible Layer draw mode for eg. */
				operation_cb(C, scene_owner ? scene_owner : scene_act, te, NULL, tselem);
			}
		}
		if (TSELEM_OPEN(tselem, soops)) {
			outliner_do_object_operation(C, scene_act, soops, &te->subtree, operation_cb);
		}
	}
}
Esempio n. 2
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 animatable 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_OPEN(tselem, soops))
			do_outliner_keyingset_editop(soops, ks, &te->subtree, mode);
	}
}
Esempio n. 3
0
static int outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *selecting)
{
	TreeElement *te;
	TreeStoreElem *tselem;
	int change= 0;
	
	for (te= lb->first; te && *index >= 0; te=te->next, (*index)--) {
		tselem= TREESTORE(te);
		
		/* if we've encountered the right item, set its 'Outliner' selection status */
		if (*index == 0) {
			/* this should be the last one, so no need to do anything with index */
			if ((te->flag & TE_ICONROW)==0) {
				/* -1 value means toggle testing for now... */
				if (*selecting == -1) {
					if (tselem->flag & TSE_SELECTED) 
						*selecting= 0;
					else 
						*selecting= 1;
				}
				
				/* set selection */
				if (*selecting) 
					tselem->flag |= TSE_SELECTED;
				else 
					tselem->flag &= ~TSE_SELECTED;

				change |= 1;
			}
		}
		else if (TSELEM_OPEN(tselem,soops)) {
			/* Only try selecting sub-elements if we haven't hit the right element yet
			 *
			 * Hack warning:
			 * 	Index must be reduced before supplying it to the sub-tree to try to do
			 * 	selection, however, we need to increment it again for the next loop to 
			 * 	function correctly
			 */
			(*index)--;
			change |= outliner_select(soops, &te->subtree, index, selecting);
			(*index)++;
		}
	}

	return change;
}
Esempio n. 4
0
/* recursive helper for function below */
static void outliner_set_coordinates_element(SpaceOops *soops, TreeElement *te, int startx, int *starty)
{
	TreeStoreElem *tselem = TREESTORE(te);
	
	/* store coord and continue, we need coordinates for elements outside view too */
	te->xs = (float)startx;
	te->ys = (float)(*starty);
	*starty -= UI_UNIT_Y;
	
	if (TSELEM_OPEN(tselem, soops)) {
		TreeElement *ten;
		for (ten = te->subtree.first; ten; ten = ten->next) {
			outliner_set_coordinates_element(soops, ten, startx + UI_UNIT_X, starty);
		}
	}
	
}
Esempio n. 5
0
static void set_operation_types(SpaceOops *soops, ListBase *lb,
                                int *scenelevel,
                                int *objectlevel,
                                int *idlevel,
                                int *datalevel)
{
	TreeElement *te;
	TreeStoreElem *tselem;
	
	for (te = lb->first; te; te = te->next) {
		tselem = TREESTORE(te);
		if (tselem->flag & TSE_SELECTED) {
			if (tselem->type) {
				if (*datalevel == 0)
					*datalevel = tselem->type;
				else if (*datalevel != tselem->type)
					*datalevel = -1;
			}
			else {
				int idcode = GS(tselem->id->name);
				switch (idcode) {
					case ID_SCE:
						*scenelevel = 1;
						break;
					case ID_OB:
						*objectlevel = 1;
						break;
						
					case ID_ME: case ID_CU: case ID_MB: case ID_LT:
					case ID_LA: case ID_AR: case ID_CA: case ID_SPK:
					case ID_MA: case ID_TE: case ID_IP: case ID_IM:
					case ID_SO: case ID_KE: case ID_WO: case ID_AC:
					case ID_NLA: case ID_TXT: case ID_GR:
						if (*idlevel == 0) *idlevel = idcode;
						else if (*idlevel != idcode) *idlevel = -1;
						break;
				}
			}
		}
		if (TSELEM_OPEN(tselem, soops)) {
			set_operation_types(soops, &te->subtree,
			                    scenelevel, objectlevel, idlevel, datalevel);
		}
	}
}
Esempio n. 6
0
static void outliner_do_data_operation(SpaceOops *soops, int type, int event, ListBase *lb, 
										 void (*operation_cb)(int, TreeElement *, TreeStoreElem *))
{
	TreeElement *te;
	TreeStoreElem *tselem;
	
	for (te=lb->first; te; te= te->next) {
		tselem= TREESTORE(te);
		if (tselem->flag & TSE_SELECTED) {
			if (tselem->type==type) {
				operation_cb(event, te, tselem);
			}
		}
		if (TSELEM_OPEN(tselem,soops)) {
			outliner_do_data_operation(soops, type, event, &te->subtree, operation_cb);
		}
	}
}
Esempio n. 7
0
static void outliner_do_id_set_operation(SpaceOops *soops, int type, ListBase *lb, ID *newid,
                                         void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *, ID *))
{
	TreeElement *te;
	TreeStoreElem *tselem;
	
	for (te = lb->first; te; te = te->next) {
		tselem = TREESTORE(te);
		if (tselem->flag & TSE_SELECTED) {
			if (tselem->type == type) {
				TreeStoreElem *tsep = te->parent ? TREESTORE(te->parent) : NULL;
				operation_cb(te, tselem, tsep, newid);
			}
		}
		if (TSELEM_OPEN(tselem, soops)) {
			outliner_do_id_set_operation(soops, type, &te->subtree, newid, operation_cb);
		}
	}
}
Esempio n. 8
0
static void outliner_do_libdata_operation(bContext *C, Scene *scene, SpaceOops *soops, ListBase *lb, 
										 void (*operation_cb)(bContext *C, Scene *scene, TreeElement *, TreeStoreElem *, TreeStoreElem *))
{
	TreeElement *te;
	TreeStoreElem *tselem;
	
	for (te=lb->first; te; te= te->next) {
		tselem= TREESTORE(te);
		if (tselem->flag & TSE_SELECTED) {
			if (tselem->type==0) {
				TreeStoreElem *tsep= TREESTORE(te->parent);
				operation_cb(C, scene, te, tsep, tselem);
			}
		}
		if (TSELEM_OPEN(tselem,soops)) {
			outliner_do_libdata_operation(C, scene, soops, &te->subtree, operation_cb);
		}
	}
}
Esempio n. 9
0
/* recursive helper function for Show Hierarchy operator */
static void tree_element_show_hierarchy(Scene *scene, SpaceOops *soops, ListBase *lb)
{
	TreeElement *te;
	TreeStoreElem *tselem;

	/* open all object elems, close others */
	for (te = lb->first; te; te = te->next) {
		tselem = TREESTORE(te);
		
		if (tselem->type == 0) {
			if (te->idcode == ID_SCE) {
				if (tselem->id != (ID *)scene) tselem->flag |= TSE_CLOSED;
				else tselem->flag &= ~TSE_CLOSED;
			}
			else if (te->idcode == ID_OB) {
				if (subtree_has_objects(soops, &te->subtree)) tselem->flag &= ~TSE_CLOSED;
				else tselem->flag |= TSE_CLOSED;
			}
		}
		else tselem->flag |= TSE_CLOSED;
		
		if (TSELEM_OPEN(tselem, soops)) tree_element_show_hierarchy(scene, soops, &te->subtree);
	}
}
Esempio n. 10
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 animatable 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_OPEN(tselem, soops))
			do_outliner_drivers_editop(soops, &te->subtree, reports, mode);
	}
}