Fix #141387: Light Probes not integrated into Animation Editors

You could basically not interact with the animation (except for
keyframes in the main region), channels region was totally empty, NLA
could not be used, ...

It is not something users will animate a lot, but we should still have
animation editors in mind when adding a new object type.

Just missing from cc31d7bb49

Pull Request: https://projects.blender.org/blender/blender/pulls/141449
This commit is contained in:
Philipp Oeser
2025-07-04 15:01:15 +02:00
committed by Philipp Oeser
parent 859d271528
commit eb82ff6166
13 changed files with 149 additions and 2 deletions

View File

@@ -125,6 +125,8 @@ class DopesheetFilterPopoverBase:
flow.prop(dopesheet, "show_pointclouds", text="Point Clouds")
if bpy.data.volumes:
flow.prop(dopesheet, "show_volumes", text="Volumes")
if bpy.data.lightprobes:
flow.prop(dopesheet, "show_lightprobes", text="Light Probes")
# data types
flow.prop(dopesheet, "show_worlds", text="Worlds")

View File

@@ -33,6 +33,7 @@
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_light_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_mask_types.h"
#include "DNA_material_types.h"
@@ -3367,6 +3368,103 @@ static bAnimChannelType ACF_DSVOLUME = {
/*setting_post_update*/ nullptr,
};
/* LightProbe Expander ------------------------------------------- */
/* TODO: just get this from RNA? */
static int acf_dslightprobe_icon(bAnimListElem *ale)
{
const LightProbe *probe = static_cast<LightProbe *>(ale->data);
switch (probe->type) {
case LIGHTPROBE_TYPE_SPHERE:
return ICON_LIGHTPROBE_SPHERE;
case LIGHTPROBE_TYPE_PLANE:
return ICON_LIGHTPROBE_PLANE;
case LIGHTPROBE_TYPE_VOLUME:
return ICON_LIGHTPROBE_VOLUME;
default:
return ICON_LIGHTPROBE_SPHERE;
}
}
/* Get the appropriate flag(s) for the setting when it is valid. */
static int acf_dslightprobe_setting_flag(bAnimContext * /*ac*/,
eAnimChannel_Settings setting,
bool *r_neg)
{
/* Clear extra return data first. */
*r_neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
return LIGHTPROBE_DS_EXPAND;
case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
*r_neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
case ACHANNEL_SETTING_ALWAYS_VISIBLE: /* pin */
return ADT_CURVES_ALWAYS_VISIBLE;
default: /* unsupported */
return 0;
}
}
/* get pointer to the setting */
static void *acf_dslightprobe_setting_ptr(bAnimListElem *ale,
eAnimChannel_Settings setting,
short *r_type)
{
LightProbe *probe = static_cast<LightProbe *>(ale->data);
/* Clear extra return data first. */
*r_type = 0;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
return GET_ACF_FLAG_PTR(probe->flag, r_type);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
case ACHANNEL_SETTING_ALWAYS_VISIBLE: /* pin */
if (probe->adt) {
return GET_ACF_FLAG_PTR(probe->adt->flag, r_type);
}
return nullptr;
default: /* unsupported */
return nullptr;
}
}
/** Light Probe expander type define. */
static bAnimChannelType ACF_DSLIGHTPROBE = {
/*channel_type_name*/ "LightProbe Expander",
/*channel_role*/ ACHANNEL_ROLE_EXPANDER,
/*get_backdrop_color*/ acf_generic_dataexpand_color,
/*get_channel_color*/ nullptr,
/*draw_backdrop*/ acf_generic_dataexpand_backdrop,
/*get_indent_level*/ acf_generic_indentation_1,
/*get_offset*/ acf_generic_basic_offset,
/*name*/ acf_generic_idblock_name,
/*name_prop*/ acf_generic_idblock_name_prop,
/*icon*/ acf_dslightprobe_icon,
/*has_setting*/ acf_generic_dataexpand_setting_valid,
/*setting_flag*/ acf_dslightprobe_setting_flag,
/*setting_ptr*/ acf_dslightprobe_setting_ptr,
/*setting_post_update*/ nullptr,
};
/* GPencil Expander ------------------------------------------- */
/* TODO: just get this from RNA? */
@@ -4633,6 +4731,7 @@ static void ANIM_init_channel_typeinfo_data()
animchannelTypeInfo[type++] = &ACF_DSCURVES; /* Curves Channel */
animchannelTypeInfo[type++] = &ACF_DSPOINTCLOUD; /* PointCloud Channel */
animchannelTypeInfo[type++] = &ACF_DSVOLUME; /* Volume Channel */
animchannelTypeInfo[type++] = &ACF_DSLIGHTPROBE; /* Light Probe */
animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */

View File

@@ -300,6 +300,7 @@ void ANIM_set_active_channel(bAnimContext *ac,
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE:
case ANIMTYPE_NLAACTION: {
/* need to verify that this data is valid for now */
if (ale->adt) {
@@ -382,6 +383,7 @@ void ANIM_set_active_channel(bAnimContext *ac,
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE:
case ANIMTYPE_NLAACTION: {
/* need to verify that this data is valid for now */
if (ale && ale->adt) {
@@ -438,6 +440,7 @@ bool ANIM_is_active_channel(bAnimListElem *ale)
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE:
case ANIMTYPE_NLAACTION: {
return ale->adt && (ale->adt->flag & ADT_UI_ACTIVE);
}
@@ -599,6 +602,7 @@ static eAnimChannels_SetFlag anim_channels_selection_flag_for_toggle(const ListB
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE:
case ANIMTYPE_NLAACTION: {
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) {
return ACHANNEL_SETFLAG_CLEAR;
@@ -771,6 +775,7 @@ static void anim_channels_select_set(bAnimContext *ac,
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE:
case ANIMTYPE_NLAACTION: {
/* need to verify that this data is valid for now */
if (ale->adt) {
@@ -2878,6 +2883,7 @@ static bool animchannels_delete_containers(const bContext *C, bAnimContext *ac)
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE:
case ANIMTYPE_SHAPEKEY:
case ANIMTYPE_GPLAYER:
case ANIMTYPE_GREASE_PENCIL_DATABLOCK:
@@ -3053,6 +3059,7 @@ static wmOperatorStatus animchannels_delete_exec(bContext *C, wmOperator * /*op*
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE:
case ANIMTYPE_SHAPEKEY:
case ANIMTYPE_GREASE_PENCIL_DATABLOCK:
case ANIMTYPE_GREASE_PENCIL_LAYER_GROUP:
@@ -3882,6 +3889,7 @@ static void box_select_anim_channels(bAnimContext *ac, const rcti &rect, short s
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE:
case ANIMTYPE_SHAPEKEY:
case ANIMTYPE_GPLAYER:
case ANIMTYPE_GREASE_PENCIL_DATABLOCK:
@@ -4749,6 +4757,7 @@ static int mouse_anim_channels(bContext *C,
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE:
notifierFlags |= click_select_channel_dummy(ac, ale, selectmode);
break;
case ANIMTYPE_GROUP:

View File

@@ -336,6 +336,7 @@ void ANIM_sync_animchannels_to_data(const bContext *C)
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE:
case ANIMTYPE_SHAPEKEY:
case ANIMTYPE_GREASE_PENCIL_DATABLOCK:
case ANIMTYPE_GREASE_PENCIL_LAYER_GROUP:

View File

@@ -38,6 +38,7 @@
#include "DNA_lattice_types.h"
#include "DNA_layer_types.h"
#include "DNA_light_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_mask_types.h"
#include "DNA_material_types.h"
@@ -771,6 +772,12 @@ static bAnimListElem *make_new_animlistelem(
key_data_from_adt(*ale, volume->adt);
break;
}
case ANIMTYPE_DSLIGHTPROBE: {
LightProbe *probe = static_cast<LightProbe *>(data);
ale->flag = FILTER_LIGHTPROBE_OBJD(probe);
key_data_from_adt(*ale, probe->adt);
break;
}
case ANIMTYPE_DSSKEY: {
Key *key = static_cast<Key *>(data);
ale->flag = FILTER_SKE_OBJD(key);
@@ -3060,6 +3067,18 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac,
expanded = FILTER_VOLUME_OBJD(volume);
break;
}
case OB_LIGHTPROBE: /* ---------- LightProbe ----------- */
{
LightProbe *probe = static_cast<LightProbe *>(ob->data);
if (ads_filterflag2 & ADS_FILTER_NOLIGHTPROBE) {
return 0;
}
type = ANIMTYPE_DSLIGHTPROBE;
expanded = FILTER_LIGHTPROBE_OBJD(probe);
break;
}
}
/* add object data animation channels */

View File

@@ -194,6 +194,7 @@ enum eAnim_ChannelType {
ANIMTYPE_DSHAIR,
ANIMTYPE_DSPOINTCLOUD,
ANIMTYPE_DSVOLUME,
ANIMTYPE_DSLIGHTPROBE,
ANIMTYPE_SHAPEKEY,
@@ -440,6 +441,8 @@ ENUM_OPERATORS(eAnimFilter_Flags, ANIMFILTER_TMP_IGNORE_ONLYSEL);
#define FILTER_CURVES_OBJD(ha) (CHECK_TYPE_INLINE(ha, Curves *), ((ha->flag & HA_DS_EXPAND)))
#define FILTER_POINTS_OBJD(pt) (CHECK_TYPE_INLINE(pt, PointCloud *), ((pt->flag & PT_DS_EXPAND)))
#define FILTER_VOLUME_OBJD(vo) (CHECK_TYPE_INLINE(vo, Volume *), ((vo->flag & VO_DS_EXPAND)))
#define FILTER_LIGHTPROBE_OBJD(probe) \
(CHECK_TYPE_INLINE(probe, LightProbe *), ((probe->flag & LIGHTPROBE_DS_EXPAND)))
/* Variable use expanders */
#define FILTER_NTREE_DATA(ntree) \
(CHECK_TYPE_INLINE(ntree, bNodeTree *), (((ntree)->flag & NTREE_DS_EXPAND)))

View File

@@ -131,7 +131,8 @@ bool nla_panel_context(const bContext *C,
case ANIMTYPE_PALETTE:
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME: {
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE: {
/* for these channels, we only do AnimData */
if (ale->adt && adt_ptr) {
ID *id;

View File

@@ -946,6 +946,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region)
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE:
case ANIMTYPE_SHAPEKEY:
case ANIMTYPE_GPLAYER:
case ANIMTYPE_GREASE_PENCIL_DATABLOCK:

View File

@@ -172,7 +172,8 @@ static int mouse_nla_tracks(bContext *C, bAnimContext *ac, int track_index, shor
case ANIMTYPE_PALETTE:
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME: {
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE: {
/* sanity checking... */
if (ale->adt) {
/* select/deselect */

View File

@@ -750,6 +750,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
case ANIMTYPE_DSVOLUME:
case ANIMTYPE_DSLIGHTPROBE:
case ANIMTYPE_SHAPEKEY:
case ANIMTYPE_GREASE_PENCIL_DATABLOCK:
case ANIMTYPE_GREASE_PENCIL_LAYER_GROUP:

View File

@@ -958,6 +958,8 @@ typedef enum eDopeSheet_FilterFlag2 {
/** Include working drivers with variables using their fallback values into Only Show Errors. */
ADS_FILTER_DRIVER_FALLBACK_AS_ERROR = (1 << 6),
ADS_FILTER_NOLIGHTPROBE = (1 << 7),
} eDopeSheet_FilterFlag2;
/* DopeSheet general flags */

View File

@@ -103,6 +103,7 @@ enum {
LIGHTPROBE_FLAG_SHOW_CLIP_DIST = (1 << 3),
LIGHTPROBE_FLAG_SHOW_DATA = (1 << 4),
LIGHTPROBE_FLAG_INVERT_GROUP = (1 << 5),
LIGHTPROBE_DS_EXPAND = (1 << 6),
};
/* Probe->grid_flag */

View File

@@ -1986,6 +1986,13 @@ static void rna_def_dopesheet(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_VOLUME, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, nullptr);
prop = RNA_def_property(srna, "show_lightprobes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag2", ADS_FILTER_NOLIGHTPROBE);
RNA_def_property_ui_text(
prop, "Display Light Probe", "Include visualization of lightprobe related animation data");
RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_LIGHTPROBE, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, nullptr);
prop = RNA_def_property(srna, "show_gpencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOGPENCIL);
RNA_def_property_ui_text(