From 015bc7ca4d3527728b4d5e036709ba40e7338bac Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 22 Sep 2023 17:44:25 +0200 Subject: [PATCH] Light linking: Make list interface look more similar to other places This change makes it so the list interface in the properties panels looks closer to things like shape keys, vertex groups and so on: there are two buttons to add selected objects to the collection and remove active item from the collection, as well as the "extra" drop down menu. The add operator adds selected objects to the light linking collection using the Include policy. For the light linking it means that the objects are added as receivers that receive the light, and for the shadow linking it means that objects are added as blockers which cast shadow from the light. The communication of the active list element is done via context property similar to how it was done before. The difference is that these properties are set on a parent of the list layout, which makes it so they are inherited by the layout hierarchy needed to place the Remove button. Pull Request: https://projects.blender.org/blender/blender/pulls/112713 --- intern/cycles/blender/addon/ui.py | 12 ++++- .../blender/editors/include/UI_interface_c.hh | 5 +- .../interface_template_light_linking.cc | 48 +++++++++++-------- source/blender/makesrna/intern/rna_ui_api.cc | 6 +++ 4 files changed, 49 insertions(+), 22 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 175b70c9b7c..3f971eee048 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1367,10 +1367,14 @@ class CYCLES_OBJECT_PT_light_linking(CyclesButtonsPanel, Panel): row = layout.row() col = row.column() - col.template_light_linking_collection(light_linking, "receiver_collection") + col.template_light_linking_collection(row, light_linking, "receiver_collection") col = row.column() sub = col.column(align=True) + prop = sub.operator("object.light_linking_receivers_link", icon='ADD', text="") + prop.link_state = 'INCLUDE' + sub.operator("object.light_linking_unlink_from_collection", icon='REMOVE', text="") + sub = col.column() sub.menu("CYCLES_OBJECT_MT_light_linking_context_menu", icon='DOWNARROW_HLT', text="") @@ -1399,10 +1403,14 @@ class CYCLES_OBJECT_PT_shadow_linking(CyclesButtonsPanel, Panel): row = layout.row() col = row.column() - col.template_light_linking_collection(light_linking, "blocker_collection") + col.template_light_linking_collection(row, light_linking, "blocker_collection") col = row.column() sub = col.column(align=True) + prop = sub.operator("object.light_linking_blockers_link", icon='ADD', text="") + prop.link_state = 'INCLUDE' + sub.operator("object.light_linking_unlink_from_collection", icon='REMOVE', text="") + sub = col.column() sub.menu("CYCLES_OBJECT_MT_shadow_linking_context_menu", icon='DOWNARROW_HLT', text="") diff --git a/source/blender/editors/include/UI_interface_c.hh b/source/blender/editors/include/UI_interface_c.hh index 940b1ba1a46..fe15f8e5384 100644 --- a/source/blender/editors/include/UI_interface_c.hh +++ b/source/blender/editors/include/UI_interface_c.hh @@ -2638,7 +2638,10 @@ void uiTemplateAssetView(uiLayout *layout, const char *drag_opname, PointerRNA *r_drag_op_properties); -void uiTemplateLightLinkingCollection(uiLayout *layout, PointerRNA *ptr, const char *propname); +void uiTemplateLightLinkingCollection(uiLayout *layout, + uiLayout *context_layout, + PointerRNA *ptr, + const char *propname); void uiTemplateGreasePencilLayerTree(uiLayout *layout, bContext *C); diff --git a/source/blender/editors/interface/interface_template_light_linking.cc b/source/blender/editors/interface/interface_template_light_linking.cc index 02baf800202..c4a2a4c49c7 100644 --- a/source/blender/editors/interface/interface_template_light_linking.cc +++ b/source/blender/editors/interface/interface_template_light_linking.cc @@ -89,17 +89,20 @@ class CollectionDropTarget : public DropTargetInterface { }; class CollectionViewItem : public BasicTreeViewItem { + uiLayout &context_layout_; Collection &collection_; ID *id_ = nullptr; CollectionLightLinking &collection_light_linking_; public: - CollectionViewItem(Collection &collection, + CollectionViewItem(uiLayout &context_layout, + Collection &collection, ID &id, CollectionLightLinking &collection_light_linking, const BIFIconID icon) : BasicTreeViewItem(id.name + 2, icon), + context_layout_(context_layout), collection_(collection), id_(&id), collection_light_linking_(collection_light_linking) @@ -108,13 +111,20 @@ class CollectionViewItem : public BasicTreeViewItem { void build_row(uiLayout &row) override { + if (is_active()) { + PointerRNA id_ptr = RNA_id_pointer_create(id_); + PointerRNA collection_ptr = RNA_id_pointer_create(&collection_.id); + + uiLayoutSetContextPointer(&context_layout_, "id", &id_ptr); + uiLayoutSetContextPointer(&context_layout_, "collection", &collection_ptr); + } + add_label(row); uiLayout *sub = uiLayoutRow(&row, true); uiLayoutSetPropDecorate(sub, false); build_state_button(*sub); - build_remove_button(*sub); } private: @@ -174,30 +184,24 @@ class CollectionViewItem : public BasicTreeViewItem { link_state_toggle(collection_light_linking); }); } - - void build_remove_button(uiLayout &row) - { - PointerRNA id_ptr = RNA_id_pointer_create(id_); - PointerRNA collection_ptr = RNA_id_pointer_create(&collection_.id); - - uiLayoutSetContextPointer(&row, "id", &id_ptr); - uiLayoutSetContextPointer(&row, "collection", &collection_ptr); - - uiItemO(&row, "", ICON_X, "OBJECT_OT_light_linking_unlink_from_collection"); - } }; class CollectionView : public AbstractTreeView { + uiLayout &context_layout_; Collection &collection_; public: - explicit CollectionView(Collection &collection) : collection_(collection) {} + CollectionView(uiLayout &context_layout, Collection &collection) + : context_layout_(context_layout), collection_(collection) + { + } void build_tree() override { LISTBASE_FOREACH (CollectionChild *, collection_child, &collection_.children) { Collection *child_collection = collection_child->collection; - add_tree_item(collection_, + add_tree_item(context_layout_, + collection_, child_collection->id, collection_child->light_linking, ICON_OUTLINER_COLLECTION); @@ -205,8 +209,11 @@ class CollectionView : public AbstractTreeView { LISTBASE_FOREACH (CollectionObject *, collection_object, &collection_.gobject) { Object *child_object = collection_object->ob; - add_tree_item( - collection_, child_object->id, collection_object->light_linking, ICON_OBJECT_DATA); + add_tree_item(context_layout_, + collection_, + child_object->id, + collection_object->light_linking, + ICON_OBJECT_DATA); } } @@ -220,7 +227,10 @@ class CollectionView : public AbstractTreeView { } // namespace blender::ui::light_linking -void uiTemplateLightLinkingCollection(uiLayout *layout, PointerRNA *ptr, const char *propname) +void uiTemplateLightLinkingCollection(uiLayout *layout, + uiLayout *context_layout, + PointerRNA *ptr, + const char *propname) { if (!ptr->data) { return; @@ -260,7 +270,7 @@ void uiTemplateLightLinkingCollection(uiLayout *layout, PointerRNA *ptr, const c blender::ui::AbstractTreeView *tree_view = UI_block_add_view( *block, "Light Linking Collection Tree View", - std::make_unique(*collection)); + std::make_unique(*context_layout, *collection)); tree_view->set_min_rows(3); blender::ui::TreeViewBuilder::build_tree_view(*tree_view, *layout); diff --git a/source/blender/makesrna/intern/rna_ui_api.cc b/source/blender/makesrna/intern/rna_ui_api.cc index 6784e723c3e..0f73e8f1c76 100644 --- a/source/blender/makesrna/intern/rna_ui_api.cc +++ b/source/blender/makesrna/intern/rna_ui_api.cc @@ -2096,6 +2096,12 @@ void RNA_api_ui_layout(StructRNA *srna) srna, "template_light_linking_collection", "uiTemplateLightLinkingCollection"); RNA_def_function_ui_description(func, "Visualization of a content of a light linking collection"); + parm = RNA_def_pointer(func, + "context_layout", + "UILayout", + "", + "Layout to set active list element as context properties"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); api_ui_item_rna_common(func); func = RNA_def_function(