Fix: View in Graph Editor not working when object is unselected #118658

Merged
Christoph Lendenfeld merged 5 commits from ChrisLend/blender:fix_view_in_ge into blender-v4.1-release 2024-03-07 17:15:13 +01:00

View File

@ -4532,13 +4532,70 @@ static void deselect_all_fcurves(bAnimContext *ac, const bool hide)
ANIM_animdata_freelist(&anim_data);
}
static rctf calculate_selection_fcurve_bounds_and_unhide(
bContext *C,
ListBase /* CollectionPointerLink */ *selection,
PropertyRNA *prop,
const blender::StringRefNull id_to_prop_path,
const int index,
const bool whole_array)
static int count_fcurves_hidden_by_filter(bAnimContext *ac, const blender::Span<FCurve *> fcurves)
{
ListBase anim_data = {nullptr, nullptr};
if (ac->sl->spacetype != SPACE_GRAPH) {
return 0;
}
SpaceGraph *sipo = (SpaceGraph *)ac->sl;
const eAnimFilter_Flags filter = eAnimFilter_Flags(sipo->ads->filterflag);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, eAnimCont_Types(ac->datatype));
/* Adding FCurves to a map for quicker lookup times. */
blender::Map<FCurve *, bool> filtered_fcurves;
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
FCurve *fcu = (FCurve *)ale->key_data;
filtered_fcurves.add(fcu, true);
}
int hidden_fcurve_count = fcurves.size();
for (FCurve *fcu : fcurves) {
if (filtered_fcurves.contains(fcu)) {
hidden_fcurve_count--;
}
}
ANIM_animdata_freelist(&anim_data);
return hidden_fcurve_count;
}
static blender::Vector<FCurve *> get_fcurves_of_property(
ID *id, PointerRNA *ptr, PropertyRNA *prop, const bool whole_array, const int index)
{
using namespace blender;
AnimData *anim_data = BKE_animdata_from_id(id);
if (anim_data == nullptr) {
return Vector<FCurve *>();
}
const std::optional<std::string> path = RNA_path_from_ID_to_property(ptr, prop);
blender::Vector<FCurve *> fcurves;
if (RNA_property_array_check(prop) && whole_array) {
const int length = RNA_property_array_length(ptr, prop);
for (int i = 0; i < length; i++) {
FCurve *fcurve = BKE_animadata_fcurve_find_by_rna_path(
anim_data, path->c_str(), i, nullptr, nullptr);
if (fcurve != nullptr) {
fcurves.append(fcurve);
}
}
}
else {
FCurve *fcurve = BKE_animadata_fcurve_find_by_rna_path(
anim_data, path->c_str(), index, nullptr, nullptr);
if (fcurve != nullptr) {
fcurves.append(fcurve);
}
}
return fcurves;
}
static rctf calculate_fcurve_bounds_and_unhide(SpaceLink *space_link,
Scene *scene,
ID *id,
const blender::Span<FCurve *> fcurves)
{
rctf bounds;
bounds.xmin = INFINITY;
@ -4546,16 +4603,59 @@ static rctf calculate_selection_fcurve_bounds_and_unhide(
bounds.ymin = INFINITY;
bounds.ymax = -INFINITY;
SpaceLink *ge_space_link = CTX_wm_space_data(C);
if (ge_space_link->spacetype != SPACE_GRAPH) {
if (space_link->spacetype != SPACE_GRAPH) {
return bounds;
}
AnimData *anim_data = BKE_animdata_from_id(id);
if (anim_data == nullptr) {
return bounds;
}
Scene *scene = CTX_data_scene(C);
float frame_range[2];
get_view_range(scene, true, frame_range);
float mapped_frame_range[2];
mapped_frame_range[0] = BKE_nla_tweakedit_remap(
anim_data, frame_range[0], NLATIME_CONVERT_UNMAP);
mapped_frame_range[1] = BKE_nla_tweakedit_remap(
anim_data, frame_range[1], NLATIME_CONVERT_UNMAP);
const bool include_handles = false;
for (FCurve *fcurve : fcurves) {
fcurve->flag |= (FCURVE_SELECTED | FCURVE_VISIBLE);
rctf fcu_bounds;
get_normalized_fcurve_bounds(fcurve,
anim_data,
space_link,
scene,
id,
include_handles,
mapped_frame_range,
&fcu_bounds);
if (BLI_rctf_is_valid(&fcu_bounds)) {
BLI_rctf_union(&bounds, &fcu_bounds);
}
}
return bounds;
}
static rctf calculate_selection_fcurve_bounds(bAnimContext *ac,
ListBase /* CollectionPointerLink */ *selection,
PropertyRNA *prop,
const blender::StringRefNull id_to_prop_path,
const int index,
const bool whole_array,
int *r_filtered_fcurve_count)
{
rctf bounds;
bounds.xmin = INFINITY;
bounds.xmax = -INFINITY;
bounds.ymin = INFINITY;
bounds.ymax = -INFINITY;
LISTBASE_FOREACH (CollectionPointerLink *, selected, selection) {
ID *selected_id = selected->ptr.owner_id;
if (!BKE_animdata_id_is_animated(selected_id)) {
@ -4574,45 +4674,11 @@ static rctf calculate_selection_fcurve_bounds_and_unhide(
resolved_ptr = selected->ptr;
resolved_prop = prop;
}
const std::optional<std::string> path = RNA_path_from_ID_to_property(&resolved_ptr,
resolved_prop);
AnimData *anim_data = BKE_animdata_from_id(selected_id);
blender::Vector<FCurve *> fcurves;
if (RNA_property_array_check(prop) && whole_array) {
const int length = RNA_property_array_length(&selected->ptr, prop);
for (int i = 0; i < length; i++) {
FCurve *fcurve = BKE_animadata_fcurve_find_by_rna_path(
anim_data, path->c_str(), i, nullptr, nullptr);
if (fcurve != nullptr) {
fcurves.append(fcurve);
}
}
}
else {
FCurve *fcurve = BKE_animadata_fcurve_find_by_rna_path(
anim_data, path->c_str(), index, nullptr, nullptr);
if (fcurve != nullptr) {
fcurves.append(fcurve);
}
}
for (FCurve *fcurve : fcurves) {
fcurve->flag |= (FCURVE_SELECTED | FCURVE_VISIBLE);
rctf fcu_bounds;
float mapped_frame_range[2];
mapped_frame_range[0] = BKE_nla_tweakedit_remap(
anim_data, frame_range[0], NLATIME_CONVERT_UNMAP);
mapped_frame_range[1] = BKE_nla_tweakedit_remap(
anim_data, frame_range[1], NLATIME_CONVERT_UNMAP);
get_normalized_fcurve_bounds(fcurve,
anim_data,
ge_space_link,
scene,
selected_id,
include_handles,
mapped_frame_range,
&fcu_bounds);
blender::Vector<FCurve *> fcurves = get_fcurves_of_property(
selected_id, &resolved_ptr, resolved_prop, whole_array, index);
*r_filtered_fcurve_count += count_fcurves_hidden_by_filter(ac, fcurves);
rctf fcu_bounds = calculate_fcurve_bounds_and_unhide(ac->sl, ac->scene, selected_id, fcurves);
if (BLI_rctf_is_valid(&fcu_bounds)) {
BLI_rctf_union(&bounds, &fcu_bounds);
}
}
@ -4622,12 +4688,12 @@ static rctf calculate_selection_fcurve_bounds_and_unhide(
static int view_curve_in_graph_editor_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr = {nullptr};
PropertyRNA *prop = nullptr;
PointerRNA button_ptr = {nullptr};
PropertyRNA *button_prop = nullptr;
uiBut *but;
int index;
if (!(but = UI_context_active_but_prop_get(C, &ptr, &prop, &index))) {
if (!(but = UI_context_active_but_prop_get(C, &button_ptr, &button_prop, &index))) {
/* Pass event on if no active button found. */
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
@ -4645,14 +4711,10 @@ static int view_curve_in_graph_editor_exec(bContext *C, wmOperator *op)
bool path_from_id;
std::optional<std::string> id_to_prop_path;
const bool selected_list_success = UI_context_copy_to_selected_list(
C, &ptr, prop, &selection, &path_from_id, &id_to_prop_path);
C, &button_ptr, button_prop, &selection, &path_from_id, &id_to_prop_path);
if (BLI_listbase_is_empty(&selection) || !selected_list_success) {
WM_report(RPT_ERROR, "Nothing selected");
retval = OPERATOR_CANCELLED;
}
else if (!context_find_graph_editor(
C, &wm_context_temp.win, &wm_context_temp.area, &wm_context_temp.region))
if (!context_find_graph_editor(
C, &wm_context_temp.win, &wm_context_temp.area, &wm_context_temp.region))
{
WM_report(RPT_WARNING, "No open Graph Editor window found");
retval = OPERATOR_CANCELLED;
@ -4674,12 +4736,43 @@ static int view_curve_in_graph_editor_exec(bContext *C, wmOperator *op)
}
else {
const bool isolate = RNA_boolean_get(op->ptr, "isolate");
/* The index can be less than 0 e.g. on color properties. */
const bool whole_array = RNA_boolean_get(op->ptr, "all") || index < 0;
deselect_all_fcurves(&ac, isolate);
const bool whole_array = RNA_boolean_get(op->ptr, "all");
rctf bounds;
bounds.xmin = INFINITY;
bounds.xmax = -INFINITY;
bounds.ymin = INFINITY;
bounds.ymax = -INFINITY;
int filtered_fcurve_count = 0;
if (selected_list_success && !BLI_listbase_is_empty(&selection)) {
rctf selection_bounds = calculate_selection_fcurve_bounds(&ac,
&selection,
button_prop,
id_to_prop_path.value_or(""),
index,
whole_array,
&filtered_fcurve_count);
if (BLI_rctf_is_valid(&selection_bounds)) {
BLI_rctf_union(&bounds, &selection_bounds);
}
}
rctf bounds = calculate_selection_fcurve_bounds_and_unhide(
C, &selection, prop, id_to_prop_path.value_or(""), index, whole_array);
/* The object to which the button belongs might not be selected, or selectable. */
blender::Vector<FCurve *> button_fcurves = get_fcurves_of_property(
button_ptr.owner_id, &button_ptr, button_prop, whole_array, index);
filtered_fcurve_count += count_fcurves_hidden_by_filter(&ac, button_fcurves);
rctf button_bounds = calculate_fcurve_bounds_and_unhide(
ac.sl, ac.scene, button_ptr.owner_id, button_fcurves);
if (BLI_rctf_is_valid(&button_bounds)) {
BLI_rctf_union(&bounds, &button_bounds);
}
if (filtered_fcurve_count > 0) {
WM_report(RPT_WARNING, "One or more F-Curves are not visible due to filter settings");
}
if (!BLI_rctf_is_valid(&bounds)) {
WM_report(RPT_ERROR, "F-Curves have no valid size");