Outliner: add ID type filter option for Blender File and Orphaned Data.
This commit is contained in:
@@ -37,13 +37,18 @@ class OUTLINER_HT_header(Header):
|
|||||||
|
|
||||||
layout.prop(space, "display_mode", text="")
|
layout.prop(space, "display_mode", text="")
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row(align=True)
|
||||||
if display_mode == 'COLLECTIONS':
|
if display_mode == 'COLLECTIONS':
|
||||||
row.popover(space_type='OUTLINER',
|
row.popover(space_type='OUTLINER',
|
||||||
region_type='HEADER',
|
region_type='HEADER',
|
||||||
panel_type="OUTLINER_PT_filter",
|
panel_type="OUTLINER_PT_filter",
|
||||||
text="",
|
text="",
|
||||||
icon='FILTER')
|
icon='FILTER')
|
||||||
|
elif display_mode in {'LIBRARIES', 'ORPHAN_DATA'}:
|
||||||
|
row.prop(space, "use_filter_id_type", text="", icon='FILTER')
|
||||||
|
sub = row.row(align=True)
|
||||||
|
sub.active = space.use_filter_id_type
|
||||||
|
sub.prop(space, "filter_id_type", text="", icon_only=True)
|
||||||
|
|
||||||
OUTLINER_MT_editor_menus.draw_collapsible(context, layout)
|
OUTLINER_MT_editor_menus.draw_collapsible(context, layout)
|
||||||
|
|
||||||
|
|||||||
@@ -1301,5 +1301,18 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
|
|||||||
scene->display.matcap_ssao_samples = 16;
|
scene->display.matcap_ssao_samples = 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!DNA_struct_elem_find(fd->filesdna, "SpaceOops", "short", "filter_id_type")) {
|
||||||
|
for (bScreen *screen = main->screen.first; screen; screen = screen->id.next) {
|
||||||
|
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
|
||||||
|
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
|
||||||
|
if (sl->spacetype == SPACE_OUTLINER) {
|
||||||
|
SpaceOops *soops = (SpaceOops *)sl;
|
||||||
|
soops->filter_id_type = ID_GR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1260,7 +1260,7 @@ static const char *outliner_idcode_to_plural(short idcode)
|
|||||||
{
|
{
|
||||||
const char *propname = BKE_idcode_to_name_plural(idcode);
|
const char *propname = BKE_idcode_to_name_plural(idcode);
|
||||||
PropertyRNA *prop = RNA_struct_type_find_property(&RNA_BlendData, propname);
|
PropertyRNA *prop = RNA_struct_type_find_property(&RNA_BlendData, propname);
|
||||||
return RNA_property_ui_name(prop);
|
return (prop) ? RNA_property_ui_name(prop) : "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeElement *te, Library *lib)
|
static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeElement *te, Library *lib)
|
||||||
@@ -1268,10 +1268,18 @@ static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeE
|
|||||||
TreeElement *ten;
|
TreeElement *ten;
|
||||||
ListBase *lbarray[MAX_LIBARRAY];
|
ListBase *lbarray[MAX_LIBARRAY];
|
||||||
int a, tot;
|
int a, tot;
|
||||||
|
short filter_id_type = (soops->filter & SO_FILTER_ID_TYPE) ? soops->filter_id_type : 0;
|
||||||
|
|
||||||
tot = set_listbasepointers(mainvar, lbarray);
|
if (filter_id_type) {
|
||||||
|
lbarray[0] = which_libbase(mainvar, soops->filter_id_type);
|
||||||
|
tot = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tot = set_listbasepointers(mainvar, lbarray);
|
||||||
|
}
|
||||||
|
|
||||||
for (a = 0; a < tot; a++) {
|
for (a = 0; a < tot; a++) {
|
||||||
if (lbarray[a]->first) {
|
if (lbarray[a] && lbarray[a]->first) {
|
||||||
ID *id = lbarray[a]->first;
|
ID *id = lbarray[a]->first;
|
||||||
|
|
||||||
/* check if there's data in current lib */
|
/* check if there's data in current lib */
|
||||||
@@ -1280,12 +1288,14 @@ static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeE
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (id) {
|
if (id) {
|
||||||
ten = outliner_add_element(soops, &te->subtree, lbarray[a], NULL, TSE_ID_BASE, 0);
|
if (filter_id_type) {
|
||||||
ten->directdata = lbarray[a];
|
ten = te;
|
||||||
|
}
|
||||||
ten->name = outliner_idcode_to_plural(GS(id->name));
|
else {
|
||||||
if (ten->name == NULL)
|
ten = outliner_add_element(soops, &te->subtree, lbarray[a], NULL, TSE_ID_BASE, 0);
|
||||||
ten->name = "UNKNOWN";
|
ten->directdata = lbarray[a];
|
||||||
|
ten->name = outliner_idcode_to_plural(GS(id->name));
|
||||||
|
}
|
||||||
|
|
||||||
for (id = lbarray[a]->first; id; id = id->next) {
|
for (id = lbarray[a]->first; id; id = id->next) {
|
||||||
if (id->lib == lib)
|
if (id->lib == lib)
|
||||||
@@ -1302,10 +1312,18 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
|
|||||||
TreeElement *ten;
|
TreeElement *ten;
|
||||||
ListBase *lbarray[MAX_LIBARRAY];
|
ListBase *lbarray[MAX_LIBARRAY];
|
||||||
int a, tot;
|
int a, tot;
|
||||||
|
short filter_id_type = (soops->filter & SO_FILTER_ID_TYPE) ? soops->filter_id_type : 0;
|
||||||
|
|
||||||
tot = set_listbasepointers(mainvar, lbarray);
|
if (filter_id_type) {
|
||||||
|
lbarray[0] = which_libbase(mainvar, soops->filter_id_type);
|
||||||
|
tot = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tot = set_listbasepointers(mainvar, lbarray);
|
||||||
|
}
|
||||||
|
|
||||||
for (a = 0; a < tot; a++) {
|
for (a = 0; a < tot; a++) {
|
||||||
if (lbarray[a]->first) {
|
if (lbarray[a] && lbarray[a]->first) {
|
||||||
ID *id = lbarray[a]->first;
|
ID *id = lbarray[a]->first;
|
||||||
|
|
||||||
/* check if there are any datablocks of this type which are orphans */
|
/* check if there are any datablocks of this type which are orphans */
|
||||||
@@ -1316,21 +1334,19 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
|
|||||||
|
|
||||||
if (id) {
|
if (id) {
|
||||||
/* header for this type of datablock */
|
/* header for this type of datablock */
|
||||||
/* TODO's:
|
if (filter_id_type) {
|
||||||
* - Add a parameter to BKE_idcode_to_name_plural to get a sane "user-visible" name instead?
|
ten = NULL;
|
||||||
* - Ensure that this uses nice icons for the datablock type involved instead of the dot?
|
}
|
||||||
*/
|
else {
|
||||||
ten = outliner_add_element(soops, &soops->tree, lbarray[a], NULL, TSE_ID_BASE, 0);
|
ten = outliner_add_element(soops, &soops->tree, lbarray[a], NULL, TSE_ID_BASE, 0);
|
||||||
ten->directdata = lbarray[a];
|
ten->directdata = lbarray[a];
|
||||||
|
ten->name = outliner_idcode_to_plural(GS(id->name));
|
||||||
ten->name = outliner_idcode_to_plural(GS(id->name));
|
}
|
||||||
if (ten->name == NULL)
|
|
||||||
ten->name = "UNKNOWN";
|
|
||||||
|
|
||||||
/* add the orphaned datablocks - these will not be added with any subtrees attached */
|
/* add the orphaned datablocks - these will not be added with any subtrees attached */
|
||||||
for (id = lbarray[a]->first; id; id = id->next) {
|
for (id = lbarray[a]->first; id; id = id->next) {
|
||||||
if (ID_REAL_USERS(id) <= 0)
|
if (ID_REAL_USERS(id) <= 0)
|
||||||
outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
|
outliner_add_element(soops, (ten) ? &ten->subtree : &soops->tree, id, ten, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -487,6 +487,7 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(
|
|||||||
|
|
||||||
soutliner = MEM_callocN(sizeof(SpaceOops), "initoutliner");
|
soutliner = MEM_callocN(sizeof(SpaceOops), "initoutliner");
|
||||||
soutliner->spacetype = SPACE_OUTLINER;
|
soutliner->spacetype = SPACE_OUTLINER;
|
||||||
|
soutliner->filter_id_type = ID_GR;
|
||||||
|
|
||||||
/* header */
|
/* header */
|
||||||
ar = MEM_callocN(sizeof(ARegion), "header for outliner");
|
ar = MEM_callocN(sizeof(ARegion), "header for outliner");
|
||||||
|
|||||||
@@ -260,7 +260,8 @@ typedef struct SpaceOops {
|
|||||||
short flag, outlinevis, storeflag, search_flags;
|
short flag, outlinevis, storeflag, search_flags;
|
||||||
int filter;
|
int filter;
|
||||||
char filter_state;
|
char filter_state;
|
||||||
char pad[3];
|
char pad;
|
||||||
|
short filter_id_type;
|
||||||
|
|
||||||
/* pointers to treestore elements, grouped by (id, type, nr) in hashtable for faster searching */
|
/* pointers to treestore elements, grouped by (id, type, nr) in hashtable for faster searching */
|
||||||
void *treehash;
|
void *treehash;
|
||||||
@@ -297,6 +298,8 @@ typedef enum eSpaceOutliner_Filter {
|
|||||||
SO_FILTER_OB_STATE_SELECTED = (1 << 14), /* Not set via DNA. */
|
SO_FILTER_OB_STATE_SELECTED = (1 << 14), /* Not set via DNA. */
|
||||||
SO_FILTER_OB_STATE_ACTIVE = (1 << 15), /* Not set via DNA. */
|
SO_FILTER_OB_STATE_ACTIVE = (1 << 15), /* Not set via DNA. */
|
||||||
SO_FILTER_NO_COLLECTION = (1 << 16),
|
SO_FILTER_NO_COLLECTION = (1 << 16),
|
||||||
|
|
||||||
|
SO_FILTER_ID_TYPE = (1 << 17),
|
||||||
} eSpaceOutliner_Filter;
|
} eSpaceOutliner_Filter;
|
||||||
|
|
||||||
#define SO_FILTER_OB_TYPE (SO_FILTER_NO_OB_MESH | \
|
#define SO_FILTER_OB_TYPE (SO_FILTER_NO_OB_MESH | \
|
||||||
|
|||||||
@@ -75,16 +75,15 @@ const EnumPropertyItem rna_enum_id_type_items[] = {
|
|||||||
{ID_PC, "PAINTCURVE", ICON_CURVE_BEZCURVE, "Paint Curve", ""},
|
{ID_PC, "PAINTCURVE", ICON_CURVE_BEZCURVE, "Paint Curve", ""},
|
||||||
{ID_PAL, "PALETTE", ICON_COLOR, "Palette", ""},
|
{ID_PAL, "PALETTE", ICON_COLOR, "Palette", ""},
|
||||||
{ID_PA, "PARTICLE", ICON_PARTICLE_DATA, "Particle", ""},
|
{ID_PA, "PARTICLE", ICON_PARTICLE_DATA, "Particle", ""},
|
||||||
{ID_LT, "LIGHT_PROBE", ICON_LIGHTPROBE_CUBEMAP, "Light Probe", ""},
|
{ID_LP, "LIGHT_PROBE", ICON_LIGHTPROBE_CUBEMAP, "Light Probe", ""},
|
||||||
{ID_SCE, "SCENE", ICON_SCENE_DATA, "Scene", ""},
|
{ID_SCE, "SCENE", ICON_SCENE_DATA, "Scene", ""},
|
||||||
{ID_SCR, "SCREEN", ICON_SPLITSCREEN, "Screen", ""},
|
{ID_SO, "SOUND", ICON_SOUND, "Sound", ""},
|
||||||
{ID_SO, "SOUND", ICON_PLAY_AUDIO, "Sound", ""},
|
|
||||||
{ID_SPK, "SPEAKER", ICON_SPEAKER, "Speaker", ""},
|
{ID_SPK, "SPEAKER", ICON_SPEAKER, "Speaker", ""},
|
||||||
{ID_TXT, "TEXT", ICON_TEXT, "Text", ""},
|
{ID_TXT, "TEXT", ICON_TEXT, "Text", ""},
|
||||||
{ID_TE, "TEXTURE", ICON_TEXTURE_DATA, "Texture", ""},
|
{ID_TE, "TEXTURE", ICON_TEXTURE_DATA, "Texture", ""},
|
||||||
{ID_WM, "WINDOWMANAGER", ICON_FULLSCREEN, "Window Manager", ""},
|
{ID_WM, "WINDOWMANAGER", ICON_FULLSCREEN, "Window Manager", ""},
|
||||||
{ID_WO, "WORLD", ICON_WORLD_DATA, "World", ""},
|
{ID_WO, "WORLD", ICON_WORLD_DATA, "World", ""},
|
||||||
{ID_WS, "WORKSPACE", ICON_NONE, "Workspace", ""},
|
{ID_WS, "WORKSPACE", ICON_SPLITSCREEN, "Workspace", ""},
|
||||||
{0, NULL, 0, NULL, NULL}
|
{0, NULL, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2189,6 +2189,17 @@ static void rna_def_space_outliner(BlenderRNA *brna)
|
|||||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "filter", SO_FILTER_NO_OB_OTHERS);
|
RNA_def_property_boolean_negative_sdna(prop, NULL, "filter", SO_FILTER_NO_OB_OTHERS);
|
||||||
RNA_def_property_ui_text(prop, "Show Other Objects", "Show curves, lattices, light probes, fonts, ...");
|
RNA_def_property_ui_text(prop, "Show Other Objects", "Show curves, lattices, light probes, fonts, ...");
|
||||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
|
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
|
||||||
|
|
||||||
|
/* Libraries filter. */
|
||||||
|
prop = RNA_def_property(srna, "use_filter_id_type", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "filter", SO_FILTER_ID_TYPE);
|
||||||
|
RNA_def_property_ui_text(prop, "Filter By Type", "Show only data-blocks of one type");
|
||||||
|
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "filter_id_type", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_sdna(prop, NULL, "filter_id_type");
|
||||||
|
RNA_def_property_enum_items(prop, rna_enum_id_type_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Filter ID Type", "Data-block type to show");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||||
|
|||||||
Reference in New Issue
Block a user