GPv3: Attribute panel to configure layer attributes on original data

This follows the same pattern as attribute panels for Mesh, Curves, and
Point Cloud. Only the layer domain is supported. The _add_ operator now
has to validate the domain setting on invoke, because layer attributes
don't support the default `Point` domain.

Pull Request: https://projects.blender.org/blender/blender/pulls/128471
This commit is contained in:
Lukas Tönne
2024-10-02 13:58:13 +02:00
committed by Falk David
parent a25456eaf1
commit dfc8a782f5
3 changed files with 85 additions and 1 deletions

View File

@@ -403,6 +403,73 @@ class DATA_PT_grease_pencil_custom_props(DataButtonsPanel, PropertyPanel, Panel)
_property_type = bpy.types.GreasePencilv3
class GREASE_PENCIL_UL_attributes(UIList):
def filter_items(self, _context, data, property):
attributes = getattr(data, property)
flags = []
indices = [i for i in range(len(attributes))]
# Filtering by name
if self.filter_name:
flags = bpy.types.UI_UL_list.filter_items_by_name(
self.filter_name, self.bitflag_filter_item, attributes, "name", reverse=self.use_filter_invert)
if not flags:
flags = [self.bitflag_filter_item] * len(attributes)
# Filtering internal attributes
for idx, item in enumerate(attributes):
flags[idx] = 0 if item.is_internal else flags[idx]
# Reorder by name.
if self.use_filter_sort_alpha:
indices = bpy.types.UI_UL_list.sort_items_by_name(attributes, "name")
return flags, indices
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
data_type = attribute.bl_rna.properties["data_type"].enum_items[attribute.data_type]
split = layout.split(factor=0.50)
split.emboss = 'NONE'
split.prop(attribute, "name", text="")
sub = split.row()
sub.alignment = 'RIGHT'
sub.active = False
sub.label(text=data_type.name)
class DATA_PT_grease_pencil_attributes(DataButtonsPanel, Panel):
bl_label = "Attributes"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {
'BLENDER_RENDER',
'BLENDER_EEVEE',
'BLENDER_EEVEE_NEXT',
'BLENDER_WORKBENCH',
}
def draw(self, context):
grease_pencil = context.grease_pencil
layout = self.layout
row = layout.row()
col = row.column()
col.template_list(
"GREASE_PENCIL_UL_attributes",
"attributes",
grease_pencil,
"attributes",
grease_pencil.attributes,
"active_index",
rows=3,
)
col = row.column(align=True)
col.operator("geometry.attribute_add", icon='ADD', text="")
col.operator("geometry.attribute_remove", icon='REMOVE', text="")
classes = (
GREASE_PENCIL_UL_masks,
GREASE_PENCIL_MT_layer_mask_add,
@@ -420,6 +487,8 @@ classes = (
GREASE_PENCIL_MT_grease_pencil_add_layer_extra,
GREASE_PENCIL_MT_group_context_menu,
DATA_PT_grease_pencil_animation,
GREASE_PENCIL_UL_attributes,
DATA_PT_grease_pencil_attributes,
)

View File

@@ -289,6 +289,21 @@ static int geometry_attribute_add_invoke(bContext *C, wmOperator *op, const wmEv
if (!RNA_property_is_set(op->ptr, prop)) {
RNA_property_string_set(op->ptr, prop, DATA_("Attribute"));
}
/* Set a valid default domain, in case Point domain is not supported. */
prop = RNA_struct_find_property(op->ptr, "domain");
if (!RNA_property_is_set(op->ptr, prop)) {
EnumPropertyItem *items;
int totitems;
bool free;
RNA_property_enum_items(
C, op->ptr, prop, const_cast<const EnumPropertyItem **>(&items), &totitems, &free);
if (totitems > 0) {
RNA_property_enum_set(op->ptr, prop, items[0].value);
}
if (free) {
MEM_freeN(items);
}
}
return WM_operator_props_popup_confirm_ex(
C, op, event, IFACE_("Add Attribute"), CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add"));
}

View File

@@ -332,7 +332,7 @@ const EnumPropertyItem *rna_enum_attribute_domain_itemf(const AttributeOwner &ow
continue;
}
if (owner.type() == AttributeOwnerType::GreasePencil &&
ELEM(domain_item->value, int(AttrDomain::Layer)))
!ELEM(domain_item->value, int(AttrDomain::Layer)))
{
continue;
}