- 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:
2009-11-19 18:22:21 +00:00
parent e61c90e416
commit 512c06afdb
4 changed files with 70 additions and 90 deletions

View File

@@ -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)

View File

@@ -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'

View File

@@ -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)

View File

@@ -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
{ {