Outliner: Display respective data-block icon in library overrides mode

Just showing the library override icon for every item doesn't add much
information, it's just redundant. Displaying the data-block type icon on
the other hand can be useful.

Differential Revision: https://developer.blender.org/D14208
This commit is contained in:
Julian Eisel 2022-03-03 13:18:23 +01:00
parent 9b12889a1a
commit 76879e3702
3 changed files with 193 additions and 240 deletions

View File

@ -66,6 +66,7 @@
#include "outliner_intern.hh"
#include "tree/tree_display.hh"
#include "tree/tree_element.hh"
#include "tree/tree_element_overrides.hh"
#include "tree/tree_element_rna.hh"
using namespace blender::ed::outliner;
@ -2222,6 +2223,185 @@ static void outliner_draw_warning_column(const bContext *C,
/* ****************************************************** */
/* Normal Drawing... */
static BIFIconID tree_element_get_icon_from_id(const ID *id)
{
if (GS(id->name) == ID_OB) {
const Object *ob = (Object *)id;
switch (ob->type) {
case OB_LAMP:
return ICON_OUTLINER_OB_LIGHT;
case OB_MESH:
return ICON_OUTLINER_OB_MESH;
case OB_CAMERA:
return ICON_OUTLINER_OB_CAMERA;
case OB_CURVES_LEGACY:
return ICON_OUTLINER_OB_CURVE;
case OB_MBALL:
return ICON_OUTLINER_OB_META;
case OB_LATTICE:
return ICON_OUTLINER_OB_LATTICE;
case OB_ARMATURE:
return ICON_OUTLINER_OB_ARMATURE;
case OB_FONT:
return ICON_OUTLINER_OB_FONT;
case OB_SURF:
return ICON_OUTLINER_OB_SURFACE;
case OB_SPEAKER:
return ICON_OUTLINER_OB_SPEAKER;
case OB_LIGHTPROBE:
return ICON_OUTLINER_OB_LIGHTPROBE;
case OB_CURVES:
return ICON_OUTLINER_OB_CURVES;
case OB_POINTCLOUD:
return ICON_OUTLINER_OB_POINTCLOUD;
case OB_VOLUME:
return ICON_OUTLINER_OB_VOLUME;
case OB_EMPTY:
if (ob->instance_collection && (ob->transflag & OB_DUPLICOLLECTION)) {
return ICON_OUTLINER_OB_GROUP_INSTANCE;
}
else if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
return ICON_OUTLINER_OB_IMAGE;
}
else if (ob->pd && ob->pd->forcefield) {
return ICON_OUTLINER_OB_FORCE_FIELD;
}
else {
return ICON_OUTLINER_OB_EMPTY;
}
case OB_GPENCIL:
return ICON_OUTLINER_OB_GREASEPENCIL;
}
return ICON_NONE;
}
/* TODO(sergey): Casting to short here just to handle ID_NLA which is
* NOT inside of IDType enum.
*/
switch ((short)GS(id->name)) {
case ID_SCE:
return ICON_SCENE_DATA;
case ID_ME:
return ICON_OUTLINER_DATA_MESH;
case ID_CU_LEGACY: {
const Curve *cu = (Curve *)id;
const short obtype = BKE_curve_type_get(cu);
switch (obtype) {
case OB_FONT:
return ICON_OUTLINER_DATA_FONT;
case OB_SURF:
return ICON_OUTLINER_DATA_SURFACE;
default:
return ICON_OUTLINER_DATA_CURVE;
}
break;
}
case ID_MB:
return ICON_OUTLINER_DATA_META;
case ID_LT:
return ICON_OUTLINER_DATA_LATTICE;
case ID_LA: {
const Light *la = (Light *)id;
switch (la->type) {
case LA_LOCAL:
return ICON_LIGHT_POINT;
case LA_SUN:
return ICON_LIGHT_SUN;
case LA_SPOT:
return ICON_LIGHT_SPOT;
case LA_AREA:
return ICON_LIGHT_AREA;
default:
return ICON_OUTLINER_DATA_LIGHT;
}
}
case ID_MA:
return ICON_MATERIAL_DATA;
case ID_TE:
return ICON_TEXTURE_DATA;
case ID_IM:
return ICON_IMAGE_DATA;
case ID_SPK:
case ID_SO:
return ICON_OUTLINER_DATA_SPEAKER;
case ID_AR:
return ICON_OUTLINER_DATA_ARMATURE;
case ID_CA:
return ICON_OUTLINER_DATA_CAMERA;
case ID_KE:
return ICON_SHAPEKEY_DATA;
case ID_WO:
return ICON_WORLD_DATA;
case ID_AC:
return ICON_ACTION;
case ID_NLA:
return ICON_NLA;
case ID_TXT: {
const Text *text = (Text *)id;
if (text->filepath == nullptr || (text->flags & TXT_ISMEM)) {
return ICON_FILE_TEXT;
}
else {
/* Helps distinguish text-based formats like the file-browser does. */
return (BIFIconID)ED_file_extension_icon(text->filepath);
}
}
case ID_GR:
return ICON_OUTLINER_COLLECTION;
case ID_CV:
return ICON_OUTLINER_DATA_CURVES;
case ID_PT:
return ICON_OUTLINER_DATA_POINTCLOUD;
case ID_VO:
return ICON_OUTLINER_DATA_VOLUME;
case ID_LI:
if (id->tag & LIB_TAG_MISSING) {
return ICON_LIBRARY_DATA_BROKEN;
}
else if (((Library *)id)->parent) {
return ICON_LIBRARY_DATA_INDIRECT;
}
else {
return ICON_LIBRARY_DATA_DIRECT;
}
case ID_LS:
return ICON_LINE_DATA;
case ID_GD:
return ICON_OUTLINER_DATA_GREASEPENCIL;
case ID_LP: {
const LightProbe *lp = (LightProbe *)id;
switch (lp->type) {
case LIGHTPROBE_TYPE_CUBE:
return ICON_LIGHTPROBE_CUBEMAP;
case LIGHTPROBE_TYPE_PLANAR:
return ICON_LIGHTPROBE_PLANAR;
case LIGHTPROBE_TYPE_GRID:
return ICON_LIGHTPROBE_GRID;
default:
return ICON_LIGHTPROBE_CUBEMAP;
}
}
case ID_BR:
return ICON_BRUSH_DATA;
case ID_SCR:
case ID_WS:
return ICON_WORKSPACE;
case ID_MSK:
return ICON_MOD_MASK;
case ID_MC:
return ICON_SEQUENCE;
case ID_PC:
return ICON_CURVE_BEZCURVE;
case ID_SIM:
/* TODO: Use correct icon. */
return ICON_PHYSICS;
default:
return ICON_NONE;
}
}
TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
{
TreeElementIcon data = {nullptr};
@ -2356,7 +2536,11 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
data.icon = ICON_MODIFIER_DATA;
data.drag_id = tselem->id;
break;
case TSE_LIBRARY_OVERRIDE_BASE:
case TSE_LIBRARY_OVERRIDE_BASE: {
TreeElementOverridesBase *base_te = tree_element_cast<TreeElementOverridesBase>(te);
data.icon = tree_element_get_icon_from_id(&base_te->id);
break;
}
case TSE_LIBRARY_OVERRIDE:
data.icon = ICON_LIBRARY_DATA_OVERRIDE;
break;
@ -2580,239 +2764,7 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
else if (tselem->id) {
data.drag_id = tselem->id;
data.drag_parent = (data.drag_id && te->parent) ? TREESTORE(te->parent)->id : nullptr;
if (GS(tselem->id->name) == ID_OB) {
Object *ob = (Object *)tselem->id;
switch (ob->type) {
case OB_LAMP:
data.icon = ICON_OUTLINER_OB_LIGHT;
break;
case OB_MESH:
data.icon = ICON_OUTLINER_OB_MESH;
break;
case OB_CAMERA:
data.icon = ICON_OUTLINER_OB_CAMERA;
break;
case OB_CURVES_LEGACY:
data.icon = ICON_OUTLINER_OB_CURVE;
break;
case OB_MBALL:
data.icon = ICON_OUTLINER_OB_META;
break;
case OB_LATTICE:
data.icon = ICON_OUTLINER_OB_LATTICE;
break;
case OB_ARMATURE:
data.icon = ICON_OUTLINER_OB_ARMATURE;
break;
case OB_FONT:
data.icon = ICON_OUTLINER_OB_FONT;
break;
case OB_SURF:
data.icon = ICON_OUTLINER_OB_SURFACE;
break;
case OB_SPEAKER:
data.icon = ICON_OUTLINER_OB_SPEAKER;
break;
case OB_LIGHTPROBE:
data.icon = ICON_OUTLINER_OB_LIGHTPROBE;
break;
case OB_CURVES:
data.icon = ICON_OUTLINER_OB_CURVES;
break;
case OB_POINTCLOUD:
data.icon = ICON_OUTLINER_OB_POINTCLOUD;
break;
case OB_VOLUME:
data.icon = ICON_OUTLINER_OB_VOLUME;
break;
case OB_EMPTY:
if (ob->instance_collection && (ob->transflag & OB_DUPLICOLLECTION)) {
data.icon = ICON_OUTLINER_OB_GROUP_INSTANCE;
}
else if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
data.icon = ICON_OUTLINER_OB_IMAGE;
}
else if (ob->pd && ob->pd->forcefield) {
data.icon = ICON_OUTLINER_OB_FORCE_FIELD;
}
else {
data.icon = ICON_OUTLINER_OB_EMPTY;
}
break;
case OB_GPENCIL:
data.icon = ICON_OUTLINER_OB_GREASEPENCIL;
break;
}
}
else {
/* TODO(sergey): Casting to short here just to handle ID_NLA which is
* NOT inside of IDType enum.
*/
switch ((short)GS(tselem->id->name)) {
case ID_SCE:
data.icon = ICON_SCENE_DATA;
break;
case ID_ME:
data.icon = ICON_OUTLINER_DATA_MESH;
break;
case ID_CU_LEGACY: {
const Curve *cu = (Curve *)tselem->id;
const short obtype = BKE_curve_type_get(cu);
switch (obtype) {
case OB_FONT:
data.icon = ICON_OUTLINER_DATA_FONT;
break;
case OB_SURF:
data.icon = ICON_OUTLINER_DATA_SURFACE;
break;
default:
data.icon = ICON_OUTLINER_DATA_CURVE;
break;
}
break;
}
case ID_MB:
data.icon = ICON_OUTLINER_DATA_META;
break;
case ID_LT:
data.icon = ICON_OUTLINER_DATA_LATTICE;
break;
case ID_LA: {
Light *la = (Light *)tselem->id;
switch (la->type) {
case LA_LOCAL:
data.icon = ICON_LIGHT_POINT;
break;
case LA_SUN:
data.icon = ICON_LIGHT_SUN;
break;
case LA_SPOT:
data.icon = ICON_LIGHT_SPOT;
break;
case LA_AREA:
data.icon = ICON_LIGHT_AREA;
break;
default:
data.icon = ICON_OUTLINER_DATA_LIGHT;
break;
}
break;
}
case ID_MA:
data.icon = ICON_MATERIAL_DATA;
break;
case ID_TE:
data.icon = ICON_TEXTURE_DATA;
break;
case ID_IM:
data.icon = ICON_IMAGE_DATA;
break;
case ID_SPK:
case ID_SO:
data.icon = ICON_OUTLINER_DATA_SPEAKER;
break;
case ID_AR:
data.icon = ICON_OUTLINER_DATA_ARMATURE;
break;
case ID_CA:
data.icon = ICON_OUTLINER_DATA_CAMERA;
break;
case ID_KE:
data.icon = ICON_SHAPEKEY_DATA;
break;
case ID_WO:
data.icon = ICON_WORLD_DATA;
break;
case ID_AC:
data.icon = ICON_ACTION;
break;
case ID_NLA:
data.icon = ICON_NLA;
break;
case ID_TXT: {
Text *text = (Text *)tselem->id;
if (text->filepath == nullptr || (text->flags & TXT_ISMEM)) {
data.icon = ICON_FILE_TEXT;
}
else {
/* Helps distinguish text-based formats like the file-browser does. */
data.icon = ED_file_extension_icon(text->filepath);
}
break;
}
case ID_GR:
data.icon = ICON_OUTLINER_COLLECTION;
break;
case ID_CV:
data.icon = ICON_OUTLINER_DATA_CURVES;
break;
case ID_PT:
data.icon = ICON_OUTLINER_DATA_POINTCLOUD;
break;
case ID_VO:
data.icon = ICON_OUTLINER_DATA_VOLUME;
break;
case ID_LI:
if (tselem->id->tag & LIB_TAG_MISSING) {
data.icon = ICON_LIBRARY_DATA_BROKEN;
}
else if (((Library *)tselem->id)->parent) {
data.icon = ICON_LIBRARY_DATA_INDIRECT;
}
else {
data.icon = ICON_LIBRARY_DATA_DIRECT;
}
break;
case ID_LS:
data.icon = ICON_LINE_DATA;
break;
case ID_GD:
data.icon = ICON_OUTLINER_DATA_GREASEPENCIL;
break;
case ID_LP: {
LightProbe *lp = (LightProbe *)tselem->id;
switch (lp->type) {
case LIGHTPROBE_TYPE_CUBE:
data.icon = ICON_LIGHTPROBE_CUBEMAP;
break;
case LIGHTPROBE_TYPE_PLANAR:
data.icon = ICON_LIGHTPROBE_PLANAR;
break;
case LIGHTPROBE_TYPE_GRID:
data.icon = ICON_LIGHTPROBE_GRID;
break;
default:
data.icon = ICON_LIGHTPROBE_CUBEMAP;
break;
}
break;
}
case ID_BR:
data.icon = ICON_BRUSH_DATA;
break;
case ID_SCR:
case ID_WS:
data.icon = ICON_WORKSPACE;
break;
case ID_MSK:
data.icon = ICON_MOD_MASK;
break;
case ID_MC:
data.icon = ICON_SEQUENCE;
break;
case ID_PC:
data.icon = ICON_CURVE_BEZCURVE;
break;
case ID_SIM:
/* TODO: Use correct icon. */
data.icon = ICON_PHYSICS;
break;
default:
break;
}
}
data.icon = tree_element_get_icon_from_id(tselem->id);
}
return data;

View File

@ -24,7 +24,7 @@
namespace blender::ed::outliner {
TreeElementOverridesBase::TreeElementOverridesBase(TreeElement &legacy_te, ID &id)
: AbstractTreeElement(legacy_te), id_(id)
: AbstractTreeElement(legacy_te), id(id)
{
BLI_assert(legacy_te.store_elem->type == TSE_LIBRARY_OVERRIDE_BASE);
if (legacy_te.parent != nullptr &&
@ -40,20 +40,20 @@ TreeElementOverridesBase::TreeElementOverridesBase(TreeElement &legacy_te, ID &i
void TreeElementOverridesBase::expand(SpaceOutliner &space_outliner) const
{
BLI_assert(id_.override_library != nullptr);
BLI_assert(id.override_library != nullptr);
const bool show_system_overrides = (SUPPORT_FILTER_OUTLINER(&space_outliner) &&
(space_outliner.filter & SO_FILTER_SHOW_SYSTEM_OVERRIDES) !=
0);
PointerRNA idpoin;
RNA_id_pointer_create(&id_, &idpoin);
RNA_id_pointer_create(&id, &idpoin);
PointerRNA override_rna_ptr;
PropertyRNA *override_rna_prop;
short index = 0;
for (auto *override_prop :
ListBaseWrapper<IDOverrideLibraryProperty>(id_.override_library->properties)) {
ListBaseWrapper<IDOverrideLibraryProperty>(id.override_library->properties)) {
const bool is_rna_path_valid = BKE_lib_override_rna_property_find(
&idpoin, override_prop, &override_rna_ptr, &override_rna_prop);
if (is_rna_path_valid && !show_system_overrides &&
@ -73,7 +73,7 @@ void TreeElementOverridesBase::expand(SpaceOutliner &space_outliner) const
}
}
TreeElementOverridesData data = {id_, *override_prop, is_rna_path_valid};
TreeElementOverridesData data = {id, *override_prop, is_rna_path_valid};
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &data, &legacy_te_, TSE_LIBRARY_OVERRIDE, index++);
}

View File

@ -17,7 +17,8 @@ struct TreeElementOverridesData {
};
class TreeElementOverridesBase final : public AbstractTreeElement {
ID &id_;
public:
ID &id;
public:
TreeElementOverridesBase(TreeElement &legacy_te, ID &id);