diff options
-rw-r--r-- | release/scripts/modules/nodeitems_utils.py | 6 | ||||
-rw-r--r-- | release/scripts/templates_py/custom_nodes.py | 81 | ||||
-rw-r--r-- | source/blender/editors/object/object_vgroup.c | 101 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_node_types.h | 9 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_nodetree.c | 14 |
5 files changed, 127 insertions, 84 deletions
diff --git a/release/scripts/modules/nodeitems_utils.py b/release/scripts/modules/nodeitems_utils.py index 904062c36cd..4be6e340760 100644 --- a/release/scripts/modules/nodeitems_utils.py +++ b/release/scripts/modules/nodeitems_utils.py @@ -59,7 +59,8 @@ class NodeItem: return self._label else: # if no custom label is defined, fall back to the node type UI name - return getattr(bpy.types, self.nodetype).bl_rna.name + cls = next(cls for cls in bpy.types.Node.__subclasses__() if cls.bl_rna.identifier == self.nodetype) + return cls.bl_rna.name @property def translation_context(self): @@ -67,7 +68,8 @@ class NodeItem: return bpy.app.translations.contexts.default else: # if no custom label is defined, fall back to the node type UI name - return getattr(bpy.types, self.nodetype).bl_rna.translation_context + cls = next(cls for cls in bpy.types.Node.__subclasses__() if cls.bl_rna.identifier == self.nodetype) + return cls.bl_rna.translation_context # NB: is a staticmethod because called with an explicit self argument # NodeItemCustom sets this as a variable attribute in __init__ diff --git a/release/scripts/templates_py/custom_nodes.py b/release/scripts/templates_py/custom_nodes.py index 32c61abace7..8ca748c1d66 100644 --- a/release/scripts/templates_py/custom_nodes.py +++ b/release/scripts/templates_py/custom_nodes.py @@ -11,7 +11,7 @@ class MyCustomTree(NodeTree): # Optional identifier string. If not explicitly defined, the python class name is used. bl_idname = 'CustomTreeType' # Label for nice name display - bl_label = 'Custom Node Tree' + bl_label = "Custom Node Tree" # Icon identifier bl_icon = 'NODETREE' @@ -23,24 +23,24 @@ class MyCustomSocket(NodeSocket): # Optional identifier string. If not explicitly defined, the python class name is used. bl_idname = 'CustomSocketType' # Label for nice name display - bl_label = 'Custom Node Socket' + bl_label = "Custom Node Socket" # Enum items list - my_items = [ - ("DOWN", "Down", "Where your feet are"), - ("UP", "Up", "Where your head should be"), - ("LEFT", "Left", "Not right"), - ("RIGHT", "Right", "Not left") - ] + my_items = ( + ('DOWN', "Down", "Where your feet are"), + ('UP', "Up", "Where your head should be"), + ('LEFT', "Left", "Not right"), + ('RIGHT', "Right", "Not left") + ) - myEnumProperty = bpy.props.EnumProperty(name="Direction", description="Just an example", items=my_items, default='UP') + my_enum_prop = bpy.props.EnumProperty(name="Direction", description="Just an example", items=my_items, default='UP') # Optional function for drawing the socket input value def draw(self, context, layout, node, text): if self.is_output or self.is_linked: layout.label(text) else: - layout.prop(self, "myEnumProperty", text=text) + layout.prop(self, "my_enum_prop", text=text) # Socket color def draw_color(self, context, node): @@ -63,7 +63,7 @@ class MyCustomNode(Node, MyCustomTreeNode): # Optional identifier string. If not explicitly defined, the python class name is used. bl_idname = 'CustomNodeType' # Label for nice name display - bl_label = 'Custom Node' + bl_label = "Custom Node" # Icon identifier bl_icon = 'SOUND' @@ -71,8 +71,8 @@ class MyCustomNode(Node, MyCustomTreeNode): # These work just like custom properties in ID data blocks # Extensive information can be found under # http://wiki.blender.org/index.php/Doc:2.6/Manual/Extensions/Python/Properties - myStringProperty = bpy.props.StringProperty() - myFloatProperty = bpy.props.FloatProperty(default=3.1415926) + my_string_prop = bpy.props.StringProperty() + my_float_prop = bpy.props.FloatProperty(default=3.1415926) # === Optional Functions === # Initialization function, called when a new node is created. @@ -99,14 +99,14 @@ class MyCustomNode(Node, MyCustomTreeNode): # Additional buttons displayed on the node. def draw_buttons(self, context, layout): layout.label("Node settings") - layout.prop(self, "myFloatProperty") + layout.prop(self, "my_float_prop") # Detail buttons in the sidebar. # If this function is not defined, the draw_buttons function is used instead def draw_buttons_ext(self, context, layout): - layout.prop(self, "myFloatProperty") - # myStringProperty button will only be visible in the sidebar - layout.prop(self, "myStringProperty") + layout.prop(self, "my_float_prop") + # my_string_prop button will only be visible in the sidebar + layout.prop(self, "my_string_prop") # Optional: custom label # Explicit user label overrides this, but here we can define a label dynamically @@ -122,7 +122,6 @@ class MyCustomNode(Node, MyCustomTreeNode): import nodeitems_utils from nodeitems_utils import NodeCategory, NodeItem - # our own base class with an appropriate poll function, # so the categories only show up in our own tree type class MyNodeCategory(NodeCategory): @@ -130,44 +129,50 @@ class MyNodeCategory(NodeCategory): def poll(cls, context): return context.space_data.tree_type == 'CustomTreeType' + # all categories in a list node_categories = [ # identifier, label, items list - MyNodeCategory("SOMENODES", "Some Nodes", items=[ + MyNodeCategory('SOMENODES', "Some Nodes", items=[ # our basic node NodeItem("CustomNodeType"), - ]), - MyNodeCategory("OTHERNODES", "Other Nodes", items=[ + ]), + MyNodeCategory('OTHERNODES', "Other Nodes", items=[ # the node item can have additional settings, # which are applied to new nodes # NB: settings values are stored as string expressions, # for this reason they should be converted to strings using repr() NodeItem("CustomNodeType", label="Node A", settings={ - "myStringProperty": repr("Lorem ipsum dolor sit amet"), - "myFloatProperty": repr(1.0), - }), + "my_string_prop": repr("Lorem ipsum dolor sit amet"), + "my_float_prop": repr(1.0), + }), NodeItem("CustomNodeType", label="Node B", settings={ - "myStringProperty": repr("consectetur adipisicing elit"), - "myFloatProperty": repr(2.0), - }), - ]), - ] - + "my_string_prop": repr("consectetur adipisicing elit"), + "my_float_prop": repr(2.0), + }), + ]), +] + +classes = ( + MyCustomTree, + MyCustomSocket, + MyCustomNode, +) def register(): - bpy.utils.register_class(MyCustomTree) - bpy.utils.register_class(MyCustomSocket) - bpy.utils.register_class(MyCustomNode) + from bpy.utils import register_class + for cls in classes: + register_class(cls) - nodeitems_utils.register_node_categories("CUSTOM_NODES", node_categories) + nodeitems_utils.register_node_categories('CUSTOM_NODES', node_categories) def unregister(): - nodeitems_utils.unregister_node_categories("CUSTOM_NODES") + nodeitems_utils.unregister_node_categories('CUSTOM_NODES') - bpy.utils.unregister_class(MyCustomTree) - bpy.utils.unregister_class(MyCustomSocket) - bpy.utils.unregister_class(MyCustomNode) + from bpy.utils import unregister_class + for cls in reversed(classes): + unregister_class(cls) if __name__ == "__main__": diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 58d93e46bde..4c13c03d9b2 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -1720,17 +1720,11 @@ static void vgroup_invert_subset(Object *ob, } } -enum { - WEIGHT_SMOOTH_ALL = -1, - WEIGHT_SMOOTH_DESELECT = false, - WEIGHT_SMOOTH_SELECT = true, -}; - static void vgroup_smooth_subset( Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int subset_count, const float fac, const int repeat, - const float fac_expand, const int source) + const float fac_expand) { const float ifac = 1.0f - fac; MDeformVert **dvert_array = NULL; @@ -1738,6 +1732,8 @@ static void vgroup_smooth_subset( int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count); float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count); const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false; + const bool use_select = vertex_group_use_vert_sel(ob); + const bool use_hide = use_select; const int expand_sign = signum_i(fac_expand); const float expand = fabsf(fac_expand); @@ -1781,19 +1777,26 @@ static void vgroup_smooth_subset( verts_used = MEM_mallocN(sizeof(*verts_used) * dvert_tot, __func__); STACK_INIT(verts_used, dvert_tot); +#define IS_BM_VERT_READ(v) \ + (use_hide ? (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == 0) : true) +#define IS_BM_VERT_WRITE(v) \ + (use_select ? (BM_elem_flag_test(v, BM_ELEM_SELECT) != 0) : true) + +#define IS_ME_VERT_READ(v) \ + (use_hide ? (((v)->flag & ME_HIDE) == 0) : true) +#define IS_ME_VERT_WRITE(v) \ + (use_select ? (((v)->flag & SELECT) != 0) : true) /* initialize used verts */ if (bm) { for (int i = 0; i < dvert_tot; i++) { BMVert *v = BM_vert_at_index(bm, i); - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + if (IS_BM_VERT_WRITE(v)) { BMIter eiter; BMEdge *e; BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { BMVert *v_other = BM_edge_other_vert(e, v); - if ((source == WEIGHT_SMOOTH_ALL) || - (source == (BM_elem_flag_test(v_other, BM_ELEM_SELECT) != 0))) - { + if (IS_BM_VERT_READ(v_other)) { STACK_PUSH(verts_used, i); break; } @@ -1803,13 +1806,12 @@ static void vgroup_smooth_subset( } else { for (int i = 0; i < dvert_tot; i++) { - MVert *v = &me->mvert[i]; - if (v->flag & SELECT) { + const MVert *v = &me->mvert[i]; + if (IS_ME_VERT_WRITE(v)) { for (int j = 0; j < emap[i].count; j++) { - MVert *v_other = &me->mvert[emap[i].indices[j]]; - if ((source == WEIGHT_SMOOTH_ALL) || - (source == ((v_other->flag & SELECT) != 0))) - { + const MEdge *e = &me->medge[emap[i].indices[j]]; + const MVert *v_other = &me->mvert[(e->v1 == i) ? e->v2 : e->v1]; + if (IS_ME_VERT_READ(v_other)) { STACK_PUSH(verts_used, i); break; } @@ -1862,13 +1864,11 @@ static void vgroup_smooth_subset( BMEdge *e; /* checked already */ - BLI_assert(BM_elem_flag_test(v, BM_ELEM_SELECT)); + BLI_assert(IS_BM_VERT_WRITE(v)); BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { BMVert *v_other = BM_edge_other_vert(e, v); - if ((source == WEIGHT_SMOOTH_ALL) || - (source == (BM_elem_flag_test(v_other, BM_ELEM_SELECT) != 0))) - { + if (IS_BM_VERT_READ(v_other)) { const int i_other = BM_elem_index_get(v_other); WEIGHT_ACCUMULATE; @@ -1879,16 +1879,14 @@ static void vgroup_smooth_subset( int j; /* checked already */ - BLI_assert(me->mvert[i].flag & SELECT); + BLI_assert(IS_ME_VERT_WRITE(&me->mvert[i])); for (j = 0; j < emap[i].count; j++) { MEdge *e = &me->medge[emap[i].indices[j]]; const int i_other = (e->v1 == i ? e->v2 : e->v1); MVert *v_other = &me->mvert[i_other]; - if ((source == WEIGHT_SMOOTH_ALL) || - (source == ((v_other->flag & SELECT) != 0))) - { + if (IS_ME_VERT_READ(v_other)) { WEIGHT_ACCUMULATE; } } @@ -1912,6 +1910,11 @@ static void vgroup_smooth_subset( ED_vgroup_parray_from_weight_array(dvert_array, dvert_tot, weight_accum_prev, def_nr, true); } +#undef IS_BM_VERT_READ +#undef IS_BM_VERT_WRITE +#undef IS_ME_VERT_READ +#undef IS_ME_VERT_WRITE + MEM_freeN(weight_accum_curr); MEM_freeN(weight_accum_prev); MEM_freeN(verts_used); @@ -2505,7 +2508,7 @@ static int UNUSED_FUNCTION(vertex_group_poll_edit) (bContext *C) } /* editmode _or_ weight paint vertex sel */ -static int vertex_group_vert_select_poll_ex(bContext *C, const short ob_type_flag) +static int vertex_group_vert_poll_ex(bContext *C, const bool needs_select, const short ob_type_flag) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; @@ -2521,12 +2524,17 @@ static int vertex_group_vert_select_poll_ex(bContext *C, const short ob_type_fla return true; } else if (ob->mode & OB_MODE_WEIGHT_PAINT) { - if (BKE_object_is_in_wpaint_select_vert(ob)) { - return true; + if (needs_select) { + if (BKE_object_is_in_wpaint_select_vert(ob)) { + return true; + } + else { + CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode"); + return false; + } } else { - CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode"); - return false; + return true; } } else { @@ -2534,15 +2542,31 @@ static int vertex_group_vert_select_poll_ex(bContext *C, const short ob_type_fla } } +#if 0 +static int vertex_group_vert_poll(bContext *C) +{ + return vertex_group_vert_poll_ex(C, false, 0); +} +#endif + + +static int vertex_group_mesh_vert_poll(bContext *C) +{ + return vertex_group_vert_poll_ex(C, false, (1 << OB_MESH)); +} + static int vertex_group_vert_select_poll(bContext *C) { - return vertex_group_vert_select_poll_ex(C, 0); + return vertex_group_vert_poll_ex(C, true, 0); } +#if 0 static int vertex_group_mesh_vert_select_poll(bContext *C) { - return vertex_group_vert_select_poll_ex(C, (1 << OB_MESH)); + return vertex_group_vert_poll_ex(C, true, (1 << OB_MESH)); } +#endif + /* editmode _or_ weight paint vertex sel and active group unlocked */ static int vertex_group_vert_select_unlocked_poll(bContext *C) @@ -3089,13 +3113,12 @@ static int vertex_group_smooth_exec(bContext *C, wmOperator *op) const float fac = RNA_float_get(op->ptr, "factor"); const int repeat = RNA_int_get(op->ptr, "repeat"); eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); - const int source = RNA_enum_get(op->ptr, "source"); const float fac_expand = RNA_float_get(op->ptr, "expand"); int subset_count, vgroup_tot; const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count); - vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand, source); + vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand); MEM_freeN((void *)vgroup_validmap); DEG_id_tag_update(&ob->id, OB_RECALC_DATA); @@ -3107,20 +3130,13 @@ static int vertex_group_smooth_exec(bContext *C, wmOperator *op) void OBJECT_OT_vertex_group_smooth(wmOperatorType *ot) { - static EnumPropertyItem smooth_source_item[] = { - {WEIGHT_SMOOTH_ALL, "ALL", 0, "All", ""}, - {WEIGHT_SMOOTH_SELECT, "SELECT", 0, "Only Selected", ""}, - {WEIGHT_SMOOTH_DESELECT, "DESELECT", 0, "Only Deselected", ""}, - {0, NULL, 0, NULL, NULL} - }; - /* identifiers */ ot->name = "Smooth Vertex Weights"; ot->idname = "OBJECT_OT_vertex_group_smooth"; ot->description = "Smooth weights for selected vertices"; /* api callbacks */ - ot->poll = vertex_group_mesh_vert_select_poll; + ot->poll = vertex_group_mesh_vert_poll; ot->exec = vertex_group_smooth_exec; /* flags */ @@ -3131,7 +3147,6 @@ void OBJECT_OT_vertex_group_smooth(wmOperatorType *ot) RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200); RNA_def_float(ot->srna, "expand", 0.0f, -1.0f, 1.0, "Expand/Contract", "Expand/contract weights", -1.0f, 1.0f); - RNA_def_enum(ot->srna, "source", smooth_source_item, -1, "Source", "Vertices to mix with"); } static int vertex_group_clean_exec(bContext *C, wmOperator *op) diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index de1214e9b3d..016de0f1cc9 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -111,7 +111,7 @@ typedef struct bNodeSocket { short stack_index; /* local stack index */ /* XXX deprecated, kept for forward compatibility */ short stack_type DNA_DEPRECATED; - int pad; + char draw_shape, pad[3]; void *cache; /* cached data from execution */ @@ -143,6 +143,13 @@ typedef enum eNodeSocketDatatype { SOCK_STRING = 7 } eNodeSocketDatatype; +/* socket shape */ +typedef enum eNodeSocketDrawShape { + SOCK_DRAW_SHAPE_CIRCLE = 0, + SOCK_DRAW_SHAPE_SQUARE = 1, + SOCK_DRAW_SHAPE_DIAMOND = 2 +} eNodeSocketDrawShape; + /* socket side (input/output) */ typedef enum eNodeSocketInOut { SOCK_IN = 1, diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 99ec0c00ac6..55ac8a32d80 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -75,6 +75,13 @@ EnumPropertyItem rna_enum_node_socket_in_out_items[] = { }; #ifndef RNA_RUNTIME +static EnumPropertyItem rna_enum_node_socket_draw_shape_items[] = { + {SOCK_DRAW_SHAPE_CIRCLE, "CIRCLE", 0, "Circle", ""}, + {SOCK_DRAW_SHAPE_SQUARE, "SQUARE", 0, "Square", ""}, + {SOCK_DRAW_SHAPE_DIAMOND, "DIAMOND", 0, "Diamond", ""}, + {0, NULL, 0, NULL, NULL } +}; + static EnumPropertyItem node_socket_type_items[] = { {SOCK_CUSTOM, "CUSTOM", 0, "Custom", ""}, {SOCK_FLOAT, "VALUE", 0, "Value", ""}, @@ -7009,6 +7016,13 @@ static void rna_def_node_socket(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Type", "Data type"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update"); + prop = RNA_def_property(srna, "draw_shape", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "draw_shape"); + RNA_def_property_enum_items(prop, rna_enum_node_socket_draw_shape_items); + RNA_def_property_enum_default(prop, SOCK_DRAW_SHAPE_CIRCLE); + RNA_def_property_ui_text(prop, "Shape", "Socket shape"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update"); + /* registration */ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname"); |