forked from blender/blender
Node panels: Enable new node group interfaces #1
@ -80,6 +80,7 @@ def rna_idprop_ui_create(
|
|||||||
description=None,
|
description=None,
|
||||||
overridable=False,
|
overridable=False,
|
||||||
subtype=None,
|
subtype=None,
|
||||||
|
id_type='OBJECT',
|
||||||
):
|
):
|
||||||
"""Create and initialize a custom property with limits, defaults and other settings."""
|
"""Create and initialize a custom property with limits, defaults and other settings."""
|
||||||
|
|
||||||
@ -91,11 +92,16 @@ def rna_idprop_ui_create(
|
|||||||
proptype, _ = rna_idprop_value_item_type(default)
|
proptype, _ = rna_idprop_value_item_type(default)
|
||||||
|
|
||||||
if (proptype is bool) or (proptype is str):
|
if (proptype is bool) or (proptype is str):
|
||||||
ui_data = item.id_properties_ui(prop)
|
|
||||||
ui_data.update(
|
ui_data.update(
|
||||||
description=description,
|
description=description,
|
||||||
default=default,
|
default=default,
|
||||||
)
|
)
|
||||||
|
elif proptype is type(None) or issubclass(proptype, bpy.types.ID):
|
||||||
|
ui_data.update(
|
||||||
|
description=description,
|
||||||
|
default=default,
|
||||||
|
id_type=id_type,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if soft_min is None:
|
if soft_min is None:
|
||||||
soft_min = min
|
soft_min = min
|
||||||
@ -156,6 +162,7 @@ def draw(layout, context, context_member, property_type, *, use_edit=True):
|
|||||||
|
|
||||||
to_dict = getattr(value, "to_dict", None)
|
to_dict = getattr(value, "to_dict", None)
|
||||||
to_list = getattr(value, "to_list", None)
|
to_list = getattr(value, "to_list", None)
|
||||||
|
is_datablock = value is None or isinstance(value, bpy.types.ID)
|
||||||
|
|
||||||
if to_dict:
|
if to_dict:
|
||||||
value = to_dict()
|
value = to_dict()
|
||||||
@ -178,6 +185,8 @@ def draw(layout, context, context_member, property_type, *, use_edit=True):
|
|||||||
props = value_column.operator("wm.properties_edit_value", text="Edit Value")
|
props = value_column.operator("wm.properties_edit_value", text="Edit Value")
|
||||||
props.data_path = context_member
|
props.data_path = context_member
|
||||||
props.property_name = key
|
props.property_name = key
|
||||||
|
elif is_datablock:
|
||||||
|
value_column.template_ID(rna_item, '["%s"]' % escape_identifier(key), text="")
|
||||||
else:
|
else:
|
||||||
value_column.prop(rna_item, '["%s"]' % escape_identifier(key), text="")
|
value_column.prop(rna_item, '["%s"]' % escape_identifier(key), text="")
|
||||||
|
|
||||||
|
@ -1387,6 +1387,7 @@ rna_custom_property_type_items = (
|
|||||||
('BOOL', "Boolean", "A true or false value"),
|
('BOOL', "Boolean", "A true or false value"),
|
||||||
('BOOL_ARRAY', "Boolean Array", "An array of true or false values"),
|
('BOOL_ARRAY', "Boolean Array", "An array of true or false values"),
|
||||||
('STRING', "String", "A string value"),
|
('STRING', "String", "A string value"),
|
||||||
|
('DATA_BLOCK', "Data-Block", "A data-block value"),
|
||||||
('PYTHON', "Python", "Edit a Python value directly, for unsupported property types"),
|
('PYTHON', "Python", "Edit a Python value directly, for unsupported property types"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1412,6 +1413,8 @@ rna_custom_property_subtype_vector_items = (
|
|||||||
('QUATERNION', "Quaternion Rotation", "Quaternion rotation (affects NLA blending)"),
|
('QUATERNION', "Quaternion Rotation", "Quaternion rotation (affects NLA blending)"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rna_id_type_items = tuple((item.identifier, item.name, item.description, item.icon, item.value)
|
||||||
|
for item in bpy.types.Action.bl_rna.properties['id_root'].enum_items)
|
||||||
|
|
||||||
class WM_OT_properties_edit(Operator):
|
class WM_OT_properties_edit(Operator):
|
||||||
"""Change a custom property's type, or adjust how it is displayed in the interface"""
|
"""Change a custom property's type, or adjust how it is displayed in the interface"""
|
||||||
@ -1554,6 +1557,14 @@ class WM_OT_properties_edit(Operator):
|
|||||||
maxlen=1024,
|
maxlen=1024,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Data-block properties.
|
||||||
|
|
||||||
|
id_type: EnumProperty(
|
||||||
|
name="ID Type",
|
||||||
|
items=rna_id_type_items,
|
||||||
|
default='OBJECT',
|
||||||
|
)
|
||||||
|
|
||||||
# Store the value converted to a string as a fallback for otherwise unsupported types.
|
# Store the value converted to a string as a fallback for otherwise unsupported types.
|
||||||
eval_string: StringProperty(
|
eval_string: StringProperty(
|
||||||
name="Value",
|
name="Value",
|
||||||
@ -1623,9 +1634,21 @@ class WM_OT_properties_edit(Operator):
|
|||||||
if is_array:
|
if is_array:
|
||||||
return 'PYTHON'
|
return 'PYTHON'
|
||||||
return 'STRING'
|
return 'STRING'
|
||||||
|
elif prop_type == type(None) or issubclass(prop_type, bpy.types.ID):
|
||||||
|
if is_array:
|
||||||
|
return 'PYTHON'
|
||||||
|
return 'DATA_BLOCK'
|
||||||
|
|
||||||
return 'PYTHON'
|
return 'PYTHON'
|
||||||
|
|
||||||
|
# For `DATA_BLOCK` types, return the `id_type` or an empty string for non data-block types.
|
||||||
|
@staticmethod
|
||||||
|
def get_property_id_type(item, property_name):
|
||||||
|
ui_data = item.id_properties_ui(property_name)
|
||||||
|
rna_data = ui_data.as_dict()
|
||||||
|
# For non `DATA_BLOCK` types, the `id_type` wont exist.
|
||||||
|
return rna_data.get("id_type", "")
|
||||||
|
|
||||||
def _init_subtype(self, subtype):
|
def _init_subtype(self, subtype):
|
||||||
self.subtype = subtype or 'NONE'
|
self.subtype = subtype or 'NONE'
|
||||||
|
|
||||||
@ -1664,6 +1687,8 @@ class WM_OT_properties_edit(Operator):
|
|||||||
self.default_string = rna_data["default"]
|
self.default_string = rna_data["default"]
|
||||||
elif self.property_type in {'BOOL', 'BOOL_ARRAY'}:
|
elif self.property_type in {'BOOL', 'BOOL_ARRAY'}:
|
||||||
self.default_bool = self._convert_new_value_array(rna_data["default"], bool, 32)
|
self.default_bool = self._convert_new_value_array(rna_data["default"], bool, 32)
|
||||||
|
elif self.property_type == 'DATA_BLOCK':
|
||||||
|
self.id_type = rna_data["id_type"]
|
||||||
|
|
||||||
if self.property_type in {'FLOAT_ARRAY', 'INT_ARRAY', 'BOOL_ARRAY'}:
|
if self.property_type in {'FLOAT_ARRAY', 'INT_ARRAY', 'BOOL_ARRAY'}:
|
||||||
self.array_length = len(item[name])
|
self.array_length = len(item[name])
|
||||||
@ -1677,7 +1702,7 @@ class WM_OT_properties_edit(Operator):
|
|||||||
|
|
||||||
# When the operator chooses a different type than the original property,
|
# When the operator chooses a different type than the original property,
|
||||||
# attempt to convert the old value to the new type for continuity and speed.
|
# attempt to convert the old value to the new type for continuity and speed.
|
||||||
def _get_converted_value(self, item, name_old, prop_type_new):
|
def _get_converted_value(self, item, name_old, prop_type_new, id_type_old, id_type_new):
|
||||||
if prop_type_new == 'INT':
|
if prop_type_new == 'INT':
|
||||||
return self._convert_new_value_single(item[name_old], int)
|
return self._convert_new_value_single(item[name_old], int)
|
||||||
elif prop_type_new == 'FLOAT':
|
elif prop_type_new == 'FLOAT':
|
||||||
@ -1700,6 +1725,14 @@ class WM_OT_properties_edit(Operator):
|
|||||||
return [False] * self.array_length
|
return [False] * self.array_length
|
||||||
elif prop_type_new == 'STRING':
|
elif prop_type_new == 'STRING':
|
||||||
return self.convert_custom_property_to_string(item, name_old)
|
return self.convert_custom_property_to_string(item, name_old)
|
||||||
|
elif prop_type_new == 'DATA_BLOCK':
|
||||||
|
if id_type_old != id_type_new:
|
||||||
|
return None
|
||||||
|
old_value = item[name_old]
|
||||||
|
if not isinstance(old_value, bpy.types.ID):
|
||||||
|
return None
|
||||||
|
return old_value
|
||||||
|
|
||||||
# If all else fails, create an empty string property. That should avoid errors later on anyway.
|
# If all else fails, create an empty string property. That should avoid errors later on anyway.
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@ -1761,6 +1794,12 @@ class WM_OT_properties_edit(Operator):
|
|||||||
default=self.default_string,
|
default=self.default_string,
|
||||||
description=self.description,
|
description=self.description,
|
||||||
)
|
)
|
||||||
|
elif prop_type_new == 'DATA_BLOCK':
|
||||||
|
ui_data = item.id_properties_ui(name)
|
||||||
|
ui_data.update(
|
||||||
|
description=self.description,
|
||||||
|
id_type=self.id_type,
|
||||||
|
)
|
||||||
|
|
||||||
escaped_name = bpy.utils.escape_identifier(name)
|
escaped_name = bpy.utils.escape_identifier(name)
|
||||||
item.property_overridable_library_set('["%s"]' % escaped_name, self.is_overridable_library)
|
item.property_overridable_library_set('["%s"]' % escaped_name, self.is_overridable_library)
|
||||||
@ -1824,6 +1863,9 @@ class WM_OT_properties_edit(Operator):
|
|||||||
prop_type_new = self.property_type
|
prop_type_new = self.property_type
|
||||||
self._old_prop_name[:] = [name]
|
self._old_prop_name[:] = [name]
|
||||||
|
|
||||||
|
id_type_old = self.get_property_id_type(item, name_old)
|
||||||
|
id_type_new = self.id_type
|
||||||
|
|
||||||
if prop_type_new == 'PYTHON':
|
if prop_type_new == 'PYTHON':
|
||||||
try:
|
try:
|
||||||
new_value = eval(self.eval_string)
|
new_value = eval(self.eval_string)
|
||||||
@ -1838,7 +1880,7 @@ class WM_OT_properties_edit(Operator):
|
|||||||
if name_old != name:
|
if name_old != name:
|
||||||
del item[name_old]
|
del item[name_old]
|
||||||
else:
|
else:
|
||||||
new_value = self._get_converted_value(item, name_old, prop_type_new)
|
new_value = self._get_converted_value(item, name_old, prop_type_new, id_type_old, id_type_new)
|
||||||
del item[name_old]
|
del item[name_old]
|
||||||
item[name] = new_value
|
item[name] = new_value
|
||||||
|
|
||||||
@ -1991,6 +2033,8 @@ class WM_OT_properties_edit(Operator):
|
|||||||
layout.prop(self, "default_bool", index=0)
|
layout.prop(self, "default_bool", index=0)
|
||||||
elif self.property_type == 'STRING':
|
elif self.property_type == 'STRING':
|
||||||
layout.prop(self, "default_string")
|
layout.prop(self, "default_string")
|
||||||
|
elif self.property_type == 'DATA_BLOCK':
|
||||||
|
layout.prop(self, "id_type")
|
||||||
|
|
||||||
if self.property_type == 'PYTHON':
|
if self.property_type == 'PYTHON':
|
||||||
layout.prop(self, "eval_string")
|
layout.prop(self, "eval_string")
|
||||||
|
@ -439,9 +439,10 @@ static bool idprop_ui_data_update_id(IDProperty *idprop, PyObject *args, PyObjec
|
|||||||
{
|
{
|
||||||
const char *rna_subtype = nullptr;
|
const char *rna_subtype = nullptr;
|
||||||
const char *description = nullptr;
|
const char *description = nullptr;
|
||||||
const char *kwlist[] = {"subtype", "description", nullptr};
|
const char *id_type = nullptr;
|
||||||
|
const char *kwlist[] = {"subtype", "description", "id_type", nullptr};
|
||||||
if (!PyArg_ParseTupleAndKeywords(
|
if (!PyArg_ParseTupleAndKeywords(
|
||||||
args, kwargs, "|$zz:update", (char **)kwlist, &rna_subtype, &description))
|
args, kwargs, "|$zzz:update", (char **)kwlist, &rna_subtype, &description, &id_type))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -455,6 +456,15 @@ static bool idprop_ui_data_update_id(IDProperty *idprop, PyObject *args, PyObjec
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int id_type_tmp;
|
||||||
|
if (pyrna_enum_value_from_id(
|
||||||
|
rna_enum_id_type_items, id_type, &id_type_tmp, "IDPropertyUIManager.update") == -1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_data.id_type = short(id_type_tmp);
|
||||||
|
|
||||||
/* Write back to the property's UI data. */
|
/* Write back to the property's UI data. */
|
||||||
IDP_ui_data_free_unique_contents(&ui_data_orig->base, IDP_ui_data_type(idprop), &ui_data.base);
|
IDP_ui_data_free_unique_contents(&ui_data_orig->base, IDP_ui_data_type(idprop), &ui_data.base);
|
||||||
*ui_data_orig = ui_data;
|
*ui_data_orig = ui_data;
|
||||||
@ -471,6 +481,7 @@ PyDoc_STRVAR(BPy_IDPropertyUIManager_update_doc,
|
|||||||
"precision=None, "
|
"precision=None, "
|
||||||
"step=None, "
|
"step=None, "
|
||||||
"default=None, "
|
"default=None, "
|
||||||
|
"id_type=None, "
|
||||||
"description=None)\n"
|
"description=None)\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Update the RNA information of the IDProperty used for interaction and\n"
|
" Update the RNA information of the IDProperty used for interaction and\n"
|
||||||
@ -619,6 +630,17 @@ static void idprop_ui_data_to_dict_string(IDProperty *property, PyObject *dict)
|
|||||||
Py_DECREF(item);
|
Py_DECREF(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void idprop_ui_data_to_dict_id(IDProperty *property, PyObject *dict)
|
||||||
|
{
|
||||||
|
IDPropertyUIDataID *ui_data = (IDPropertyUIDataID *)property->ui_data;
|
||||||
|
|
||||||
|
const char *id_type = nullptr;
|
||||||
|
RNA_enum_identifier(rna_enum_id_type_items, ui_data->id_type, &id_type);
|
||||||
|
PyObject *item = PyUnicode_FromString(id_type);
|
||||||
|
PyDict_SetItemString(dict, "id_type", item);
|
||||||
|
Py_DECREF(item);
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(BPy_IDPropertyUIManager_as_dict_doc,
|
PyDoc_STRVAR(BPy_IDPropertyUIManager_as_dict_doc,
|
||||||
".. method:: as_dict()\n"
|
".. method:: as_dict()\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -655,6 +677,7 @@ static PyObject *BPy_IDIDPropertyUIManager_as_dict(BPy_IDPropertyUIManager *self
|
|||||||
idprop_ui_data_to_dict_string(property, dict);
|
idprop_ui_data_to_dict_string(property, dict);
|
||||||
break;
|
break;
|
||||||
case IDP_UI_DATA_TYPE_ID:
|
case IDP_UI_DATA_TYPE_ID:
|
||||||
|
idprop_ui_data_to_dict_id(property, dict);
|
||||||
break;
|
break;
|
||||||
case IDP_UI_DATA_TYPE_INT:
|
case IDP_UI_DATA_TYPE_INT:
|
||||||
idprop_ui_data_to_dict_int(property, dict);
|
idprop_ui_data_to_dict_int(property, dict);
|
||||||
|
Loading…
Reference in New Issue
Block a user