From 51a78d58d2188a0ca752dd251da10e988da926f1 Mon Sep 17 00:00:00 2001 From: Durman Date: Wed, 27 Jul 2022 14:13:06 +0400 Subject: [PATCH] add named attribute node --- docs/nodes/object_nodes/named_attribute.rst | 34 ++++++++ .../nodes/object_nodes/object_nodes_index.rst | 1 + index.md | 1 + nodes/object_nodes/named_attribute.py | 84 +++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 docs/nodes/object_nodes/named_attribute.rst create mode 100644 nodes/object_nodes/named_attribute.py diff --git a/docs/nodes/object_nodes/named_attribute.rst b/docs/nodes/object_nodes/named_attribute.rst new file mode 100644 index 0000000000..b8a2c55a7f --- /dev/null +++ b/docs/nodes/object_nodes/named_attribute.rst @@ -0,0 +1,34 @@ +Named attribute +=============== + +Functionality +------------- + +The node takes a blender object and an attribute name and tries to find +attribute with such name if it fails it rises an error. The size and type +of attributes remains unchanged by the node. + +Category +-------- + +BPY Data -> Set mesh attribute + +Inputs +------ + +- **Object** - Blender data blocks +- **Name** - name of attribute to read + +Outputs +------- + +- **Object** - Blender data blocks +- **Attribute** - Values of the attriubte + +Usage +----- + +Setting and reading some attribute on a mesh + +.. image:: https://user-images.githubusercontent.com/28003269/181222478-42302284-b72f-460d-9df2-6fed2b49f625.png + :width: 800px \ No newline at end of file diff --git a/docs/nodes/object_nodes/object_nodes_index.rst b/docs/nodes/object_nodes/object_nodes_index.rst index 5e17ac79b5..89e9e4f4e2 100644 --- a/docs/nodes/object_nodes/object_nodes_index.rst +++ b/docs/nodes/object_nodes/object_nodes_index.rst @@ -20,3 +20,4 @@ Objects set_mesh_attribute set_collection copy_modifiers + named_attribute diff --git a/index.md b/index.md index 7d73171f8c..04e52bcf68 100644 --- a/index.md +++ b/index.md @@ -642,6 +642,7 @@ SvSortObjsNode SvFilterObjsNode SvSetMeshAttributeNode + SvNamedMeshAttributeNode SvPointOnMeshNodeMK2 SvOBJRayCastNodeMK2 SvSCNRayCastNodeMK2 diff --git a/nodes/object_nodes/named_attribute.py b/nodes/object_nodes/named_attribute.py new file mode 100644 index 0000000000..eb9f5af9b4 --- /dev/null +++ b/nodes/object_nodes/named_attribute.py @@ -0,0 +1,84 @@ +# This file is part of project Sverchok. It's copyrighted by the contributors +# recorded in the version control history of the file, available from +# its original location https://github.com/nortikin/sverchok/commit/master +# +# SPDX-License-Identifier: GPL3 +# License-Filename: LICENSE + +import numpy as np + +import bpy +from sverchok.data_structure import fixed_iter +from sverchok.node_tree import SverchCustomTreeNode + + +def read_mesh_attribute(obj, name): + attr = obj.data.attributes[name] + + if attr.data_type == 'FLOAT': + out = np.zeros(len(attr.data), dtype=np.float32) + attr.data.foreach_get('value', out) + elif attr.data_type == 'INT': + out = np.zeros(len(attr.data), dtype=int) + attr.data.foreach_get('value', out) + elif attr.data_type == 'BOOLEAN': + out = np.zeros(len(attr.data), dtype=bool) + attr.data.foreach_get('value', out) + elif attr.data_type == 'FLOAT_VECTOR': + out = np.zeros(len(attr.data) * 3, dtype=np.float32) + attr.data.foreach_get('vector', out) + out.shape = (-1, 3) + elif attr.data_type == 'FLOAT2': + out = np.zeros(len(attr.data) * 2, dtype=np.float32) + attr.data.foreach_get('vector', out) + out.shape = (-1, 2) + elif attr.data_type == 'FLOAT_COLOR': + out = np.zeros(len(attr.data) * 4, dtype=np.float32) + attr.data.foreach_get('color', out) + out.shape = (-1, 4) + elif attr.data_type == 'BYTE_COLOR': + # it seems blender keeps the values as floats internally + out = np.zeros(len(attr.data) * 4) + attr.data.foreach_get('color', out) + out *= 255 + out = out.astype(np.uint8) + out.shape = (-1, 4) + else: + raise TypeError(f"Unknown {attr.data_type=}") + return out + + +class SvNamedMeshAttributeNode(SverchCustomTreeNode, bpy.types.Node): + """ + Triggers: object mesh + Tooltip: Reading mesh attribute + """ + bl_idname = 'SvNamedMeshAttributeNode' + bl_label = 'Named Attribute' + bl_icon = 'SORTALPHA' + + def sv_init(self, context): + self.inputs.new('SvObjectSocket', 'Object') + self.inputs.new('SvTextSocket', 'Name').use_prop = True + self.outputs.new('SvObjectSocket', "Object") + self.outputs.new('SvStringsSocket', "Attribute") + + def process(self): + objs = self.inputs['Object'].sv_get(deepcopy=False, default=[]) + names = self.inputs['Name'].sv_get(deepcopy=False) + + attrs = [] + names = fixed_iter(names, len(objs)) + for obj, name in zip(objs, names): + name = name[0] + if name: + attrs.append(read_mesh_attribute(obj, name)) + else: + attrs.append([]) + + self.outputs['Object'].sv_set(objs) + self.outputs['Attribute'].sv_set(attrs) + + +register, unregister = bpy.utils.register_classes_factory( + [SvNamedMeshAttributeNode])