- StructRNA's __dir__ was missing members from its classes __dict__
- property editor can now set button min/max values and edit the tooltip - custom props tooltips were not displayed - cleanup the property UI - remove hacks that were used for editing (edit is now a popup operator) - object.children was broken
This commit is contained in:
@@ -15,7 +15,6 @@
|
|||||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#
|
#
|
||||||
# ##### END GPL LICENSE BLOCK #####
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
from _bpy import types as bpy_types
|
from _bpy import types as bpy_types
|
||||||
|
|
||||||
StructRNA = bpy_types.Struct.__bases__[0]
|
StructRNA = bpy_types.Struct.__bases__[0]
|
||||||
@@ -37,6 +36,7 @@ class Context(StructRNA):
|
|||||||
class Object(bpy_types.ID):
|
class Object(bpy_types.ID):
|
||||||
|
|
||||||
def _get_children(self):
|
def _get_children(self):
|
||||||
|
import bpy
|
||||||
return [child for child in bpy.data.objects if child.parent == self]
|
return [child for child in bpy.data.objects if child.parent == self]
|
||||||
|
|
||||||
children = property(_get_children)
|
children = property(_get_children)
|
||||||
|
|||||||
@@ -20,22 +20,6 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
EVIL_PROP = "act_property"
|
|
||||||
EVIL_PROP_PATH = EVIL_PROP + '_path'
|
|
||||||
EVIL_PROP_VALUE = EVIL_PROP + '_value'
|
|
||||||
EVIL_PROP_PROP = EVIL_PROP + '_prop'
|
|
||||||
EVIL_PROP_PROP_ORIG = EVIL_PROP + '_prop_orig'
|
|
||||||
|
|
||||||
|
|
||||||
# nasty!, use a scene property to store the active edit item
|
|
||||||
def evil_prop_init():
|
|
||||||
Scene = bpy.types.Scene
|
|
||||||
if EVIL_PROP_PROP_ORIG not in Scene.bl_rna.properties:
|
|
||||||
Scene.StringProperty(attr=EVIL_PROP_PATH)
|
|
||||||
Scene.StringProperty(attr=EVIL_PROP_VALUE)
|
|
||||||
Scene.StringProperty(attr=EVIL_PROP_PROP)
|
|
||||||
Scene.StringProperty(attr=EVIL_PROP_PROP_ORIG)
|
|
||||||
|
|
||||||
def rna_idprop_ui_get(item, create=True):
|
def rna_idprop_ui_get(item, create=True):
|
||||||
try:
|
try:
|
||||||
return item['_RNA_UI']
|
return item['_RNA_UI']
|
||||||
@@ -85,17 +69,6 @@ def draw(layout, context, context_member, use_edit = True):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
rna_item = eval("context." + context_member)
|
rna_item = eval("context." + context_member)
|
||||||
|
|
||||||
evil_prop_init()
|
|
||||||
|
|
||||||
scene = context.scene
|
|
||||||
|
|
||||||
global_path = getattr(scene, EVIL_PROP_PATH)
|
|
||||||
global_value = getattr(scene, EVIL_PROP_VALUE)
|
|
||||||
global_prop = getattr(scene, EVIL_PROP_PROP)
|
|
||||||
global_prop_orig = getattr(scene, EVIL_PROP_PROP_ORIG)
|
|
||||||
|
|
||||||
# print((global_path, global_value, global_prop, global_prop_orig))
|
|
||||||
|
|
||||||
items = rna_item.items()
|
items = rna_item.items()
|
||||||
items.sort()
|
items.sort()
|
||||||
@@ -107,7 +80,7 @@ def draw(layout, context, context_member, use_edit = True):
|
|||||||
del row
|
del row
|
||||||
|
|
||||||
for key, val in items:
|
for key, val in items:
|
||||||
print("KEY - " + key)
|
|
||||||
if key == '_RNA_UI':
|
if key == '_RNA_UI':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -122,43 +95,28 @@ def draw(layout, context, context_member, use_edit = True):
|
|||||||
val_draw = val
|
val_draw = val
|
||||||
|
|
||||||
box = row.box()
|
box = row.box()
|
||||||
|
|
||||||
'''
|
if use_edit:
|
||||||
if use_edit and key == global_prop_orig and context_member == global_path:
|
|
||||||
split = box.split(percentage=0.75)
|
split = box.split(percentage=0.75)
|
||||||
|
|
||||||
row = split.row()
|
row = split.row()
|
||||||
row.itemR(scene, EVIL_PROP_PROP)
|
else:
|
||||||
row.itemR(scene, EVIL_PROP_VALUE)
|
row = box.row()
|
||||||
|
|
||||||
|
row.itemL(text=key)
|
||||||
|
|
||||||
|
# explicit exception for arrays
|
||||||
|
if convert_to_pyobject and not hasattr(val_orig, "len"):
|
||||||
|
row.itemL(text=val_draw)
|
||||||
|
else:
|
||||||
|
row.itemR(rna_item, '["%s"]' % key, text="")
|
||||||
|
|
||||||
row = split.column()
|
if use_edit:
|
||||||
prop = row.itemO("wm.properties_edit", properties=True, text="done")
|
row = split.row(align=True)
|
||||||
|
prop = row.itemO("wm.properties_edit", properties=True, text="edit")
|
||||||
assign_props(prop, val_draw, key)
|
assign_props(prop, val_draw, key)
|
||||||
|
|
||||||
else:
|
prop = row.itemO("wm.properties_remove", properties=True, text="", icon='ICON_ZOOMOUT')
|
||||||
'''
|
assign_props(prop, val_draw, key)
|
||||||
if 1:
|
|
||||||
if use_edit:
|
|
||||||
split = box.split(percentage=0.75)
|
|
||||||
row = split.row()
|
|
||||||
else:
|
|
||||||
row = box.row()
|
|
||||||
|
|
||||||
row.itemL(text=key)
|
|
||||||
|
|
||||||
# explicit exception for arrays
|
|
||||||
if convert_to_pyobject and not hasattr(val_orig, "len"):
|
|
||||||
row.itemL(text=val_draw)
|
|
||||||
else:
|
|
||||||
row.itemR(rna_item, '["%s"]' % key, text="")
|
|
||||||
|
|
||||||
if use_edit:
|
|
||||||
row = split.row(align=True)
|
|
||||||
prop = row.itemO("wm.properties_edit", properties=True, text="edit")
|
|
||||||
assign_props(prop, val_draw, key)
|
|
||||||
|
|
||||||
prop = row.itemO("wm.properties_remove", properties=True, text="", icon='ICON_ZOOMOUT')
|
|
||||||
assign_props(prop, val_draw, key)
|
|
||||||
|
|
||||||
|
|
||||||
from bpy.props import *
|
from bpy.props import *
|
||||||
@@ -173,62 +131,64 @@ rna_value = StringProperty(name="Property Value",
|
|||||||
rna_property = StringProperty(name="Property Name",
|
rna_property = StringProperty(name="Property Name",
|
||||||
description="Property name edit", maxlen=1024, default="")
|
description="Property name edit", maxlen=1024, default="")
|
||||||
|
|
||||||
rna_min = FloatProperty(name="Min", default=0.0)
|
rna_min = FloatProperty(name="Min", default=0.0, precision=3)
|
||||||
rna_min = FloatProperty(name="Max", default=1.0)
|
rna_max = FloatProperty(name="Max", default=1.0, precision=3)
|
||||||
|
|
||||||
class WM_OT_properties_edit(bpy.types.Operator):
|
class WM_OT_properties_edit(bpy.types.Operator):
|
||||||
'''Internal use (edit a property path)'''
|
'''Internal use (edit a property path)'''
|
||||||
bl_idname = "wm.properties_edit"
|
bl_idname = "wm.properties_edit"
|
||||||
bl_label = "Edit Property!"
|
bl_label = "Edit Property!"
|
||||||
|
|
||||||
|
description = StringProperty(name="Tip", default="")
|
||||||
path = rna_path
|
path = rna_path
|
||||||
value = rna_value
|
value = rna_value
|
||||||
property = rna_property
|
property = rna_property
|
||||||
|
|
||||||
min = FloatProperty(name="Min", default=0.0)
|
min = rna_min
|
||||||
max = FloatProperty(name="Max", default=1.0)
|
max = rna_max
|
||||||
description = StringProperty(name="Tip", default="")
|
|
||||||
|
|
||||||
# the class instance is not persistant, need to store in the class
|
# the class instance is not persistant, need to store in the class
|
||||||
# not ideal but changes as the op runs.
|
# not ideal but changes as the op runs.
|
||||||
_last_prop = ['']
|
_last_prop = ['']
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
global_path = self.properties.path
|
path = self.properties.path
|
||||||
global_value = self.properties.value
|
value = self.properties.value
|
||||||
global_prop = self.properties.property
|
prop = self.properties.property
|
||||||
global_prop_old = self._last_prop[0]
|
prop_old = self._last_prop[0]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = eval(global_value)
|
value_eval = eval(value)
|
||||||
except:
|
except:
|
||||||
value = global_value
|
value_eval = value
|
||||||
|
|
||||||
if type(value) == str:
|
if type(value_eval) == str:
|
||||||
value = '"' + value + '"'
|
value_eval = '"' + value_eval + '"'
|
||||||
|
|
||||||
# First remove
|
# First remove
|
||||||
item = eval("context.%s" % global_path)
|
item = eval("context.%s" % path)
|
||||||
|
|
||||||
rna_idprop_ui_prop_clear(item, global_prop_old)
|
rna_idprop_ui_prop_clear(item, prop_old)
|
||||||
exec_str = "del item['%s']" % global_prop_old
|
exec_str = "del item['%s']" % prop_old
|
||||||
# print(exec_str)
|
# print(exec_str)
|
||||||
exec(exec_str)
|
exec(exec_str)
|
||||||
|
|
||||||
|
|
||||||
# Reassign
|
# Reassign
|
||||||
exec_str = "item['%s'] = %s" % (global_prop, value)
|
exec_str = "item['%s'] = %s" % (prop, value_eval)
|
||||||
# print(exec_str)
|
# print(exec_str)
|
||||||
exec(exec_str)
|
exec(exec_str)
|
||||||
|
|
||||||
prop_type = type(item[global_prop])
|
prop_type = type(item[prop])
|
||||||
|
|
||||||
prop_ui = rna_idprop_ui_prop_get(item, global_prop)
|
prop_ui = rna_idprop_ui_prop_get(item, prop)
|
||||||
|
|
||||||
if prop_type in (float, int):
|
if prop_type in (float, int):
|
||||||
|
|
||||||
prop_ui['soft_min'] = prop_ui['min'] = prop_type(self.properties.min)
|
prop_ui['soft_min'] = prop_ui['min'] = prop_type(self.properties.min)
|
||||||
prop_ui['soft_max'] = prop_ui['max'] = prop_type(self.properties.max)
|
prop_ui['soft_max'] = prop_ui['max'] = prop_type(self.properties.max)
|
||||||
|
|
||||||
|
prop_ui['description'] = self.properties.description
|
||||||
|
|
||||||
return ('FINISHED',)
|
return ('FINISHED',)
|
||||||
|
|
||||||
@@ -242,7 +202,7 @@ class WM_OT_properties_edit(bpy.types.Operator):
|
|||||||
prop_ui = rna_idprop_ui_prop_get(item, self.properties.property, False) # dont create
|
prop_ui = rna_idprop_ui_prop_get(item, self.properties.property, False) # dont create
|
||||||
if prop_ui:
|
if prop_ui:
|
||||||
self.properties.min = prop_ui.get("min", -1000000000)
|
self.properties.min = prop_ui.get("min", -1000000000)
|
||||||
self.properties.min = prop_ui.get("max", 1000000000)
|
self.properties.max = prop_ui.get("max", 1000000000)
|
||||||
self.properties.description = prop_ui.get("description", "")
|
self.properties.description = prop_ui.get("description", "")
|
||||||
|
|
||||||
if 0:
|
if 0:
|
||||||
@@ -280,7 +240,7 @@ class WM_OT_properties_add(bpy.types.Operator):
|
|||||||
path = rna_path
|
path = rna_path
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
item = eval("context.%s" % self.path)
|
item = eval("context.%s" % self.properties.path)
|
||||||
|
|
||||||
def unique_name(names):
|
def unique_name(names):
|
||||||
prop = 'prop'
|
prop = 'prop'
|
||||||
|
|||||||
@@ -424,8 +424,10 @@ static const char *rna_ensure_property_description(PropertyRNA *prop)
|
|||||||
IDProperty *idp_ui= rna_idproperty_ui(prop);
|
IDProperty *idp_ui= rna_idproperty_ui(prop);
|
||||||
|
|
||||||
if(idp_ui) { /* TODO, type checking on ID props */
|
if(idp_ui) { /* TODO, type checking on ID props */
|
||||||
|
|
||||||
IDProperty *item= IDP_GetPropertyFromGroup(idp_ui, "description");
|
IDProperty *item= IDP_GetPropertyFromGroup(idp_ui, "description");
|
||||||
return item ? ((IDProperty*)prop)->name : item->data.pointer;
|
if(item)
|
||||||
|
return (char *)item->data.pointer ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ((IDProperty*)prop)->name; /* XXX - not correct */
|
return ((IDProperty*)prop)->name; /* XXX - not correct */
|
||||||
@@ -955,7 +957,7 @@ const char *RNA_property_ui_name(PropertyRNA *prop)
|
|||||||
|
|
||||||
const char *RNA_property_ui_description(PropertyRNA *prop)
|
const char *RNA_property_ui_description(PropertyRNA *prop)
|
||||||
{
|
{
|
||||||
return rna_ensure_property(prop)->description;
|
return rna_ensure_property_description(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
int RNA_property_ui_icon(PropertyRNA *prop)
|
int RNA_property_ui_icon(PropertyRNA *prop)
|
||||||
|
|||||||
@@ -1443,18 +1443,22 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA *self)
|
|||||||
if (BPy_StructRNA_CheckExact(self)) {
|
if (BPy_StructRNA_CheckExact(self)) {
|
||||||
ret = PyList_New(0);
|
ret = PyList_New(0);
|
||||||
} else {
|
} else {
|
||||||
pystring = PyUnicode_FromString("__dict__");
|
PyObject *list;
|
||||||
dict = PyObject_GenericGetAttr((PyObject *)self, pystring);
|
/* class instances */
|
||||||
Py_DECREF(pystring);
|
dict = *_PyObject_GetDictPtr((PyObject *)self);
|
||||||
|
|
||||||
if (dict==NULL) {
|
if (dict==NULL) {
|
||||||
PyErr_Clear();
|
|
||||||
ret = PyList_New(0);
|
ret = PyList_New(0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ret = PyDict_Keys(dict);
|
ret = PyDict_Keys(dict);
|
||||||
Py_DECREF(dict);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* classes dict */
|
||||||
|
dict= ((PyTypeObject *)Py_TYPE(self))->tp_dict;
|
||||||
|
list = PyDict_Keys(dict);
|
||||||
|
PyList_SetSlice(ret, INT_MAX, INT_MAX, list);
|
||||||
|
Py_DECREF(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Collect RNA items*/
|
/* Collect RNA items*/
|
||||||
@@ -1617,6 +1621,17 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA *self, PyObject *pyname )
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static int pyrna_struct_pydict_contains(PyObject *self, PyObject *pyname)
|
||||||
|
{
|
||||||
|
PyObject *dict= *(_PyObject_GetDictPtr((PyObject *)self));
|
||||||
|
if (dict==NULL) /* unlikely */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return PyDict_Contains(dict, pyname);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//--------------- setattr-------------------------------------------
|
//--------------- setattr-------------------------------------------
|
||||||
static int pyrna_struct_setattro( BPy_StructRNA *self, PyObject *pyname, PyObject *value )
|
static int pyrna_struct_setattro( BPy_StructRNA *self, PyObject *pyname, PyObject *value )
|
||||||
{
|
{
|
||||||
@@ -1627,7 +1642,10 @@ static int pyrna_struct_setattro( BPy_StructRNA *self, PyObject *pyname, PyObjec
|
|||||||
// XXX - This currently allows anything to be assigned to an rna prop, need to see how this should be used
|
// XXX - This currently allows anything to be assigned to an rna prop, need to see how this should be used
|
||||||
// but for now it makes porting scripts confusing since it fails silently.
|
// but for now it makes porting scripts confusing since it fails silently.
|
||||||
// edit: allowing this for setting classes internal attributes.
|
// edit: allowing this for setting classes internal attributes.
|
||||||
if (name[0]=='_' && !BPy_StructRNA_CheckExact(self) && PyObject_GenericSetAttr((PyObject *)self, pyname, value) >= 0) {
|
// edit: allow this for any attribute that alredy exists as a python attr
|
||||||
|
if ( (name[0]=='_' /* || pyrna_struct_pydict_contains(self, pyname) */ ) &&
|
||||||
|
!BPy_StructRNA_CheckExact(self) &&
|
||||||
|
PyObject_GenericSetAttr((PyObject *)self, pyname, value) >= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user