I studied a lot of examples but with no success. The script I'm working on is calculating the area of the selected object faces (or the whole area), and then I would like to call the operator to store the area. The area should be stored in a list of simple floats, which then I would like to save by another operator. However, I can't force python to create a list of values. I analyzed UIList "simple" example for materials list, but is was not too simple at all. Also, I analyzed solutions found here: http://blenderartists.org/forum/showthread.php?343863-List-of-strings-as-scene-variable&highlight=UI+list+from+python http://blenderartists.org/forum/showthread.php?349417-How-to-add-custom-list-property&highlight=UI+list+from+python http://blenderartists.org/forum/showthread.php?376910-UI-list-for-actions&highlight=UI+list+from+python How can I store and retrieve a custom list in a blend file? What ui would work for choosing from a long, long list? and few more. No solution works for me. Obviously I miss something. The question is: how to do a list of float values added to it by pressing a button. The list should expand to for example at most 10 values and then a scrollbar should appear, similar to other lists in Blender UI. I don't need any searching, no clicking on the list, no selecting items, nothing. The list of values should act as a history of measurements, that's it. And I would like to have data in memory in a list form, to save it on demand to a text file (but this is not important here).
So far I created script like this:
import bpy, bmesh
from bpy.types import ( Operator, Panel, UIList )
from bpy.props import ( IntProperty, CollectionProperty )
# returns -1 if object has no area property
def calcArea(self,obj):
area = 0.0
#.... calculating the area, unimportant
return(area)
# this was supposed to be a list, but it is not working
class AreaItemList(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(item, "name", text="", emboss=False, icon_value=icon)
elif self.layout_type in {'GRID'}:
pass
# this class should actually store area in the list
# but right now I stored only one area in custom data
# I should get rid of this when I manage to store data in a list
class AreaStorage(Operator):
bl_idname = "area.storage"
bl_label = "Area Storage"
def execute(self,context):
ob = context.active_object
area = calcArea(self,ob)
ob['area'] = area
return {'FINISHED'}
class AreaCalculator(Panel):
"""Some text"""
bl_idname = "area.calculator"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_category = "aaa"
bl_label = "bbb"
# I've put calculating area code also in draw panel class
# because then simple selecting the object is showing a result
# in the panel. Dunno how to make this better.
def draw(self, context):
ob = context.active_object
if ob is not None and ob.type == 'MESH' and (ob.mode == 'OBJECT' or ob.mode == 'EDIT'):
area = calcArea(self,ob)
layout = self.layout
if area >= 0.0:
r = layout.row(align=True)
b = r.box()
b.label(str(context.active_object.name)+":")
b.label(str(round(area,6))+'m²')
if ob.scale[0] != 1.000 or ob.scale[1] != 1.000 or ob.scale[2] != 1.000:
b.label('Set scale to 1.0!!!',icon='ERROR')
else:
if area < 0.0:
r = layout.row(align=True)
b = r.box()
b.label(str(context.active_object.name))
b.label("has no polygons!")
r = layout.row(align=False)
r.operator("area.storage",text="Store Area",icon='FACESEL')
# and here is the list, which DOES NOT WORK
# simply I have no idea how to generate proper data for it
s = context.scene
layout.template_list("AreaItemList", "", s, "areas", s, "area_index")
else:
layout = self.layout
r = layout.row(align=False)
r.label("Select a mesh.")
# this was written as one of the examples from network, did not
# work either.
class Area(bpy.types.PropertyGroup):
id = IntProperty()
def register():
# here is a mess
bpy.utils.register_class(Area)
bpy.types.Scene.areas = CollectionProperty(type=Area)
bpy.types.Scene.area_index = IntProperty()
# those two classess are ok so far
bpy.utils.register_class(AreaStorage)
bpy.utils.register_class(AreaCalculator)
def unregister():
bpy.utils.unregister_class(AreaStorage)
bpy.utils.unregister_class(AreaCalculator)
del bpy.types.Scene.area_index
del bpy.types.Scene.areas
bpy.utils.unregister_class(Area)
if __name__ == "__main__":
register()
So it seems that I did not understand how to create lists. I do not need any custom listing, nothing fancy, and I did not found working example of this very simple case. Please help.