Custom Properties: Add boolean type

A proper boolean custom property type is commonly requested. This
commit simply adds a new `IDP_BOOLEAN` type that can be used for
boolean and boolean array custom properties. This can also be used
for exposing boolean node sockets in the geometry nodes modifier.

I've just extended the places existing IDProperty types are used, and
tested with the custom property edit operator and the python console.
Adding another IDProperty type is a straightforward extension of the
existing design.

Differential Revision: https://developer.blender.org/D12815
This commit is contained in:
2023-01-13 12:31:27 -06:00
parent 4961e5f91d
commit ef68a37e5d
16 changed files with 457 additions and 39 deletions

View File

@@ -14,6 +14,7 @@ from bpy.props import (
FloatProperty,
IntProperty,
StringProperty,
BoolVectorProperty,
IntVectorProperty,
FloatVectorProperty,
)
@@ -1325,6 +1326,8 @@ rna_custom_property_type_items = (
('FLOAT_ARRAY', "Float Array", "An array of floating-point values"),
('INT', "Integer", "A single integer"),
('INT_ARRAY', "Integer Array", "An array of integers"),
('BOOL', "Boolean", "A true or false value"),
('BOOL_ARRAY', "Boolean Array", "An array of true or false values"),
('STRING', "String", "A string value"),
('PYTHON', "Python", "Edit a python value directly, for unsupported property types"),
)
@@ -1410,6 +1413,14 @@ class WM_OT_properties_edit(Operator):
default=1,
)
# Boolean properties.
# This property stores values for both array and non-array properties.
default_bool: BoolVectorProperty(
name="Default Value",
size=32,
)
# Float properties.
# This property stores values for both array and non-array properties.
@@ -1520,6 +1531,10 @@ class WM_OT_properties_edit(Operator):
if is_array:
return 'FLOAT_ARRAY'
return 'FLOAT'
elif prop_type == bool:
if is_array:
return 'BOOL_ARRAY'
return 'BOOL'
elif prop_type == str:
if is_array:
return 'PYTHON'
@@ -1571,8 +1586,10 @@ class WM_OT_properties_edit(Operator):
self.default_int = self._convert_new_value_array(rna_data["default"], int, 32)
elif self.property_type == 'STRING':
self.default_string = rna_data["default"]
elif self.property_type in {'BOOL', 'BOOL_ARRAY'}:
self.default_int = self._convert_new_value_array(rna_data["default"], bool, 32)
if self.property_type in {'FLOAT_ARRAY', 'INT_ARRAY'}:
if self.property_type in {'FLOAT_ARRAY', 'INT_ARRAY', 'BOOL_ARRAY'}:
self.array_length = len(item[name])
# The dictionary does not contain the description if it was empty.
@@ -1591,16 +1608,26 @@ class WM_OT_properties_edit(Operator):
if prop_type_new == 'FLOAT':
return self._convert_new_value_single(item[name_old], float)
if prop_type_new == 'BOOL':
return self._convert_new_value_single(item[name_old], bool)
if prop_type_new == 'INT_ARRAY':
prop_type_old = self.get_property_type(item, name_old)
if prop_type_old in {'INT', 'FLOAT', 'INT_ARRAY', 'FLOAT_ARRAY'}:
if prop_type_old in {'INT', 'FLOAT', 'INT_ARRAY', 'FLOAT_ARRAY', 'BOOL_ARRAY'}:
return self._convert_new_value_array(item[name_old], int, self.array_length)
if prop_type_new == 'FLOAT_ARRAY':
prop_type_old = self.get_property_type(item, name_old)
if prop_type_old in {'INT', 'FLOAT', 'FLOAT_ARRAY', 'INT_ARRAY'}:
if prop_type_old in {'INT', 'FLOAT', 'FLOAT_ARRAY', 'INT_ARRAY', 'BOOL_ARRAY'}:
return self._convert_new_value_array(item[name_old], float, self.array_length)
if prop_type_new == 'BOOL_ARRAY':
prop_type_old = self.get_property_type(item, name_old)
if prop_type_old in {'INT', 'FLOAT', 'FLOAT_ARRAY', 'INT_ARRAY'}:
return self._convert_new_value_array(item[name_old], bool, self.array_length)
else:
return [False] * self.array_length
if prop_type_new == 'STRING':
return self.convert_custom_property_to_string(item, name_old)
@@ -1622,6 +1649,9 @@ class WM_OT_properties_edit(Operator):
self.soft_min_float = float(self.soft_min_int)
self.soft_max_float = float(self.soft_max_int)
self.default_float = self._convert_new_value_array(self.default_int, float, 32)
elif prop_type_new in {'BOOL', 'BOOL_ARRAY'} and prop_type_old in {'INT', 'INT_ARRAY'}:
self.default_bool = self._convert_new_value_array(self.default_int, bool, 32)
# Don't convert between string and float/int defaults here, it's not expected like the other conversions.
# Fill the property's UI data with the values chosen in the operator.
@@ -1637,6 +1667,12 @@ class WM_OT_properties_edit(Operator):
default=self.default_int[0] if prop_type_new == 'INT' else self.default_int[:self.array_length],
description=self.description,
)
if prop_type_new in {'BOOL', 'BOOL_ARRAY'}:
ui_data = item.id_properties_ui(name)
ui_data.update(
default=self.default_bool[0] if prop_type_new == 'BOOL' else self.default_bool[:self.array_length],
description=self.description,
)
elif prop_type_new in {'FLOAT', 'FLOAT_ARRAY'}:
ui_data = item.id_properties_ui(name)
ui_data.update(
@@ -1879,6 +1915,15 @@ class WM_OT_properties_edit(Operator):
col.prop(self, "soft_max_int", text="Max")
layout.prop(self, "step_int")
elif self.property_type in {'BOOL', 'BOOL_ARRAY'}:
if self.property_type == 'BOOL_ARRAY':
layout.prop(self, "array_length")
col = layout.column(align=True)
col.prop(self, "default_bool", index=0, text="Default")
for i in range(1, self.array_length):
col.prop(self, "default_bool", index=i, text=" ")
else:
layout.prop(self, "default_bool", index=0)
elif self.property_type == 'STRING':
layout.prop(self, "default_string")