From eb82ff616686e74c441563805e3b9180fc7ab2d0 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Fri, 4 Jul 2025 15:01:15 +0200 Subject: [PATCH] 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 cc31d7bb4909 Pull Request: https://projects.blender.org/blender/blender/pulls/141449 --- scripts/startup/bl_ui/space_dopesheet.py | 2 + .../animation/anim_channels_defines.cc | 99 +++++++++++++++++++ .../editors/animation/anim_channels_edit.cc | 9 ++ source/blender/editors/animation/anim_deps.cc | 1 + .../blender/editors/animation/anim_filter.cc | 19 ++++ source/blender/editors/include/ED_anim_api.hh | 3 + .../blender/editors/space_nla/nla_buttons.cc | 3 +- source/blender/editors/space_nla/nla_draw.cc | 1 + .../blender/editors/space_nla/nla_tracks.cc | 3 +- .../transform/transform_convert_action.cc | 1 + source/blender/makesdna/DNA_action_types.h | 2 + .../blender/makesdna/DNA_lightprobe_types.h | 1 + source/blender/makesrna/intern/rna_action.cc | 7 ++ 13 files changed, 149 insertions(+), 2 deletions(-) diff --git a/scripts/startup/bl_ui/space_dopesheet.py b/scripts/startup/bl_ui/space_dopesheet.py index 77027621fac..47313e174c3 100644 --- a/scripts/startup/bl_ui/space_dopesheet.py +++ b/scripts/startup/bl_ui/space_dopesheet.py @@ -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") diff --git a/source/blender/editors/animation/anim_channels_defines.cc b/source/blender/editors/animation/anim_channels_defines.cc index 481b5ce0784..43dd9fda888 100644 --- a/source/blender/editors/animation/anim_channels_defines.cc +++ b/source/blender/editors/animation/anim_channels_defines.cc @@ -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(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(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 */ diff --git a/source/blender/editors/animation/anim_channels_edit.cc b/source/blender/editors/animation/anim_channels_edit.cc index d3de3d24ce0..ed817928e2b 100644 --- a/source/blender/editors/animation/anim_channels_edit.cc +++ b/source/blender/editors/animation/anim_channels_edit.cc @@ -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: diff --git a/source/blender/editors/animation/anim_deps.cc b/source/blender/editors/animation/anim_deps.cc index fcb4b9cceeb..7d2733c78d7 100644 --- a/source/blender/editors/animation/anim_deps.cc +++ b/source/blender/editors/animation/anim_deps.cc @@ -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: diff --git a/source/blender/editors/animation/anim_filter.cc b/source/blender/editors/animation/anim_filter.cc index 5e8916af9e3..614952e2b32 100644 --- a/source/blender/editors/animation/anim_filter.cc +++ b/source/blender/editors/animation/anim_filter.cc @@ -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(data); + ale->flag = FILTER_LIGHTPROBE_OBJD(probe); + key_data_from_adt(*ale, probe->adt); + break; + } case ANIMTYPE_DSSKEY: { Key *key = static_cast(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(ob->data); + + if (ads_filterflag2 & ADS_FILTER_NOLIGHTPROBE) { + return 0; + } + + type = ANIMTYPE_DSLIGHTPROBE; + expanded = FILTER_LIGHTPROBE_OBJD(probe); + break; + } } /* add object data animation channels */ diff --git a/source/blender/editors/include/ED_anim_api.hh b/source/blender/editors/include/ED_anim_api.hh index 0db5f32904d..ae5e67be437 100644 --- a/source/blender/editors/include/ED_anim_api.hh +++ b/source/blender/editors/include/ED_anim_api.hh @@ -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))) diff --git a/source/blender/editors/space_nla/nla_buttons.cc b/source/blender/editors/space_nla/nla_buttons.cc index 1a06c93a242..e98b0d92fe8 100644 --- a/source/blender/editors/space_nla/nla_buttons.cc +++ b/source/blender/editors/space_nla/nla_buttons.cc @@ -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; diff --git a/source/blender/editors/space_nla/nla_draw.cc b/source/blender/editors/space_nla/nla_draw.cc index 3378b760c1f..c4cf312bb58 100644 --- a/source/blender/editors/space_nla/nla_draw.cc +++ b/source/blender/editors/space_nla/nla_draw.cc @@ -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: diff --git a/source/blender/editors/space_nla/nla_tracks.cc b/source/blender/editors/space_nla/nla_tracks.cc index 2024f5b71c6..77330e18f9d 100644 --- a/source/blender/editors/space_nla/nla_tracks.cc +++ b/source/blender/editors/space_nla/nla_tracks.cc @@ -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 */ diff --git a/source/blender/editors/transform/transform_convert_action.cc b/source/blender/editors/transform/transform_convert_action.cc index b02db9784cd..7b5ca190bc4 100644 --- a/source/blender/editors/transform/transform_convert_action.cc +++ b/source/blender/editors/transform/transform_convert_action.cc @@ -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: diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 9b1a5b558ed..6bfc3e99297 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -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 */ diff --git a/source/blender/makesdna/DNA_lightprobe_types.h b/source/blender/makesdna/DNA_lightprobe_types.h index 334efbe5150..6a5697ba860 100644 --- a/source/blender/makesdna/DNA_lightprobe_types.h +++ b/source/blender/makesdna/DNA_lightprobe_types.h @@ -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 */ diff --git a/source/blender/makesrna/intern/rna_action.cc b/source/blender/makesrna/intern/rna_action.cc index f56f3367f24..b3343624ec1 100644 --- a/source/blender/makesrna/intern/rna_action.cc +++ b/source/blender/makesrna/intern/rna_action.cc @@ -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(