Fix #119384: Outliner mode column crash with shared object data #119745

Closed
Hans Goudey wants to merge 3 commits from HooglyBoogly:fix-outliner-mode-switch-crash into blender-v4.1-release

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
3 changed files with 20 additions and 7 deletions

View File

@ -2158,10 +2158,11 @@ static void outliner_mode_toggle_fn(bContext *C, void *tselem_poin, void * /*arg
BLI_assert(tselem->id != nullptr && GS(tselem->id->name) == ID_OB);
Object *ob = (Object *)tselem->id;
const bool object_data_shared = (ob->data == tvc.obact->data);
const bool object_data_in_mode = tvc.object_data_in_mode.contains(
static_cast<const ID *>(ob->data));
wmWindow *win = CTX_wm_window(C);
const bool do_extend = (win->eventstate->modifier & KM_CTRL) && !object_data_shared;
const bool do_extend = (win->eventstate->modifier & KM_CTRL) && !object_data_in_mode;
outliner_item_mode_toggle(C, &tvc, te, do_extend);
}
@ -2199,15 +2200,16 @@ static void outliner_draw_mode_column_toggle(uiBlock *block,
draw_active_icon = false;
}
const bool object_data_shared = (ob->data == ob_active->data);
draw_active_icon = draw_active_icon || object_data_shared;
const bool object_data_in_mode = tvc->object_data_in_mode.contains(
static_cast<const ID *>(ob->data));
draw_active_icon = draw_active_icon || object_data_in_mode;
int icon;
const char *tip;
if (draw_active_icon) {
icon = UI_icon_from_object_mode(ob_active->mode);
tip = object_data_shared ? TIP_("Change the object in the current mode") :
TIP_("Remove from the current mode");
tip = object_data_in_mode ? TIP_("Change the object in the current mode") :
TIP_("Remove from the current mode");
}
else {
icon = ICON_DOT;

View File

@ -10,6 +10,8 @@
#include <memory>
#include "BLI_set.hh"
#include "RNA_types.hh"
/* Needed for `tree_element_cast()`. */
@ -253,6 +255,8 @@ struct TreeViewContext {
* The pose object may not be the active object (when in weight paint mode).
* Checking this in draw loops isn't efficient, so set only once. */
Object *ob_pose;
Set<const ID *> object_data_in_mode;
};
enum TreeItemSelectAction {

View File

@ -40,7 +40,7 @@ namespace blender::ed::outliner {
void outliner_viewcontext_init(const bContext *C, TreeViewContext *tvc)
{
memset(tvc, 0, sizeof(*tvc));
*tvc = {};
/* Scene level. */
tvc->scene = CTX_data_scene(C);
@ -59,6 +59,13 @@ void outliner_viewcontext_init(const bContext *C, TreeViewContext *tvc)
tvc->ob_pose = BKE_object_pose_armature_get(tvc->obact);
}
}
if (tvc->obact && tvc->obact->mode != OB_MODE_OBJECT) {
for (const Object *object : BKE_view_layer_array_from_objects_in_mode_unique_data(
tvc->scene, tvc->view_layer, nullptr, eObjectMode(tvc->obact->mode)))
{
tvc->object_data_in_mode.add_new(static_cast<const ID *>(object->data));
}
}
}
/** \} */