# Passing variables in IntProperty constructors ignores changes in the variable when creating more instances using CollectionProperty.add()?

Sorry if the title is unclear.

I'm working on an addon which involves a UI with a list of IntProperties. I need to be able to add and remove elements from that list on the fly, and I want the min/max values of these elements to vary. See comments in the code snippet below for further explanation, and feel free to copy/paste this straight into blender to test it for yourself. Just have an armature as your active object, in Blender 2.8, run the script and check the new category created on the N panel.

import bpy

my_armature = bpy.context.object
my_min = 2
my_max = 7
# So first in order to be able to add and remove properties on the fly at all,
# I need to put them in a CollectionProperty,
# which I can only do by extending bpy.types.PropertyGroup.
# (Correct me if I'm wrong about anything this far)
class IntPropContainer(bpy.types.PropertyGroup):
# While declaring the property, I pass in the my_min and my_max from outside the class scope.
# As of 2.8 I have to use ':' instead of '=' for creating properties, for reasons that are unclear to me.
value: bpy.props.IntProperty(name="Int Property", min=my_min, max=my_max)

bpy.utils.register_class(IntPropContainer)
bpy.types.Armature.my_ints = bpy.props.CollectionProperty(type=IntPropContainer)

# Adding a property to the collection
my_min = 5
my_max = 10
# I would expect my_new_int.value to have its min and max set to 5 and 10.

class MyUI(bpy.types.Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_idname = "OBJECT_PT_my_ui"
bl_label = "My Label"
bl_category = "My Category"

def draw(self, context):
layout = self.layout
layout.row().prop(my_armature.data.my_ints[0], 'value')
# The min/max of the property are the original 2/7 instead of the new 5/10.

bpy.utils.register_class(MyUI)


The problem: I expected the value I added to the UI to have its min/max set to 5/10, but instead it's 2/7 - the original values of my_min and my_max. This means any properties I create within this colelction property will have the same min and max values, which is not what I want.

I can of course add my_min and my_max variables to within my IntPropContainer class, and then set an update callback function to clamp the value to within those bounds BUT this is not ideal because it allows the user to move the slider out of the min/max bounds, and only after they let go of left mouse will it snap back, which makes this solution very clunky from the user's POV.

# Reason I want to use IntProperty over ID Properties

This is simply because I want to use the update callback of IntProperty, ie. I want to run a function whenever a value is changed. Finding a way to do this for ID Properties could very well be an alternate solution to my specific problem.

• The property will have the arguments that are assigned when registered. AFAIK they do not keep the reference to some global variable my_min for example, rather its value 2. Can have adjustable args with id prop set via eg ob['_RNA_UI']["my_prop"]["soft_min"] = 5 but as mentioned cannot then have an update method, Jan 24, 2019 at 17:48
• ... or put another way each item added to your collection is an instance of the registered class .. say bpy.types.OBJECT_PT_my_ui not of MyUI. Jan 24, 2019 at 17:59

I append a function to bpy.app.handlers.depsgraph_update_post, in which I grab all the properties I'm interested in and compare them to a previously saved copy of them that's stored in a list ID property. If they match, I do nothing, if they differ, I save the current properties to the list and run my update().