Merge branch 'master' into blender2.8
This discards node drawing changes which need to be written as shaders.
This commit is contained in:
@@ -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__
|
||||
|
||||
@@ -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__":
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
static int vertex_group_vert_select_poll(bContext *C)
|
||||
#if 0
|
||||
static int vertex_group_vert_poll(bContext *C)
|
||||
{
|
||||
return vertex_group_vert_select_poll_ex(C, 0);
|
||||
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_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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user