# FloatProperty Slider Pairs That Sum to 1, Dynamically Changing

This might just not be possible but I thought I'd ask. Is it possible to have two sliders min=0.0, max=1.0. Where their contents always sum to 1 but the user can still move them.

For example a slider A and slider B. When A is increased, B decreases by some linearly proportional amount.

I tried a couple different approaches, first by just setting the value in draw:

total = myPropGroup.probA + myPropGroup.probB
if total > 1.0:
myPropGroup.probA = myPropGroup.probA / total
myPropGroup.probB = myPropGroup.probB / total
layoutBox.prop(myPropGroup, "probA", text="Probability A", slider=True)
layoutBox.prop(myPropGroup, "probB", text="Probability B", slider=True)


I also tried using the set and update functions of the properties but caused some infinite loops.

• You'll want to use an update function on your properties. a similar instance of comparing one property to another is here.
– Ratt
Jan 24, 2023 at 20:00

Rough example.

Honestly a single variable could be used as a property and just subtract the value from 1 for any comparison.

import bpy

def upd_left(self, context):
if not self.my_prop_right + self.my_prop_left == 1:
self.my_prop_right = 1 - self.my_prop_left

def upd_right(self, context):
if not self.my_prop_right + self.my_prop_left == 1:
self.my_prop_left = 1 - self.my_prop_right

class TEST_PG_props(bpy.types.PropertyGroup):
my_prop_left: bpy.props.FloatProperty(
name="my_prop_left",
default=0,
min=0,
max=1,
update=upd_left,
)

my_prop_right: bpy.props.FloatProperty(
name="my_prop_right",
default=0,
min=0,
max=1,
update=upd_right,
)

class TEST_PT_test_panel(bpy.types.Panel):
bl_idname = "TEST_PT_test_panel"
bl_label = "Test Panel"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "Test Tab"

def draw(self, context):
my_props = context.scene.my_props
layout = self.layout
row = layout.row()
row.prop(my_props, "my_prop_left", text="left")
row.prop(my_props, "my_prop_right", text="right")

classes = [
TEST_PG_props,
TEST_PT_test_panel,
]

def register():
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.Scene.my_props = bpy.props.PointerProperty(
type=TEST_PG_props)

def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)
del bpy.types.Scene.my_props

if __name__ == "__main__":
register()
$$$$

• This is better than diving by the sum because the property you're editing is set exactly and won't jump around. But instead of the if to avoid infinite recursion, you can set the underlying custom prop which won't invoke update again: self["my_prop_right"] = 1 - self.my_prop_left. Jan 24, 2023 at 20:29
• @scurest thanks for the info on using self["my_prop_right"]` to avoid recursion. I was unaware of that functionality and while it Likely would be a better implementation I think I will leave the answer as is for clarity of avoiding recursion. Hopefuly anyone that finds this post in the future will read your comment and make their own decision on best implementation for their needs.
– Ratt
Jan 24, 2023 at 21:20