# How can I make a dialog window make changes in real time?

Watching a tutorial from youtube I managed to setup an addon with a tab into VIEW_3D > UI, which contains a panel with some buttons (operators) where if you press any of them, you get a different dialog window with some properties, labels etc.

What I want to do is to have the ability to see changes in real time and not when I press OK. Something like this...

Is that possible? And if yes, how can I do that? Because I tried to execute my action through draw method but I get this error AttributeError: Writing to ID classes in this context is not allowed: Scene, Scene datablock, error setting LayerCollection.hide_viewport.

Here is an example of my code...

class fu3dm_WM_OT_Model_Prefs_Operator(bpy.types.Operator):
bl_idname = "wm.fu3dm_model_prefs"
bl_label = "Model Preferences"
bl_description = "Blah blah blah"

fu3dm_model_gender : bpy.props.EnumProperty(name="Gender", description="Choose model's gender", items= [('OP1', "Male", ""), ('OP2', "Female", "")], default='OP1')
fu3dm_model_eyes_color : bpy.props.IntProperty(name="Eyes Color", description="Choose model's eyes color", min=1, max=10, default=1)
fu3dm_model_skin_color: bpy.props.IntProperty(name="Skin Color", description="Choose model's skin color", min=1, max=10, default=1)
fu3dm_model_upper_body : bpy.props.EnumProperty(name="Upper Body", description="Choose model's upper body mesh", items= [('OP1', "Arms for Long Sleeves", ""), ('OP2', "Arms for Short Sleeves", ""), ('OP3', "Full Upper Body", "")], default='OP2')
fu3dm_model_lower_body : bpy.props.EnumProperty(name="Lower Body", description="Choose model's lower body mesh", items= [('OP1', "Legs without Socks", ""), ('OP2', "Legs with Low Socks", ""), ('OP3', "Legs with Short Socks", ""), ('OP4', "Legs with Medium Socks", ""), ('OP5', "Legs with Long Socks", ""), ('OP6', "Legs with Medium Socks but without Shinpads", ""), ('OP7', "Full Lower Body", "")], default='OP4')

def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self)
bpy.ops.wm.fu3dm_model_prefs('INVOKE_DEFAULT')

def draw(self, context):
layout = self.layout
box = layout.box()
col = box.column()

row = col.split()
row.label(text="Gender:")
row.prop(self, "fu3dm_model_gender", text="")

if self.fu3dm_model_gender == 'OP1':
row = col.split()
self.do_it(self=self, context=context)
else:
row = col.split()
self.do_it(self=self, context=context)

row = col.split()
row.label(text="Eyes Color:")
row.prop(self, "fu3dm_model_eyes_color", text="")

row = col.split()
row.label(text="Skin Color:")
row.prop(self, "fu3dm_model_skin_color", text="")

row = col.split()
row.label(text="Upper Body:")
row.prop(self, "fu3dm_model_upper_body", text="")

row = col.split()
row.label(text="Lower Body:")
row.prop(self, "fu3dm_model_lower_body", text="")

def execute(self, context):
pass
return {"FINISHED"}

@staticmethod
def do_it(self, context):
vlayer = bpy.context.scene.view_layers['View Layer']
if self.fu3dm_model_gender == 'OP1':
vlayer.layer_collection.children['MALE'].hide_viewport = False
vlayer.layer_collection.children['FEMALE'].hide_viewport = True
else:
vlayer.layer_collection.children['MALE'].hide_viewport = True
vlayer.layer_collection.children['FEMALE'].hide_viewport = False


Please keep in mind that I am totally new to blender and python!!!

• – batFINGER Oct 6 '20 at 8:58
• As a side note, your do_it method shouldn't be a static method and the second line of your invoke method is never executed since it is written after a return statement – Gorgious Oct 6 '20 at 9:01
• First of all, most likely just copied from a bad tutorial (link would be helpful), replace bpy.context.* by context.* Why do_it() method has a decorator? Recommend split up your question into multiple ones and always provide a minimal working example to make your question useful to others too. – brockmann Oct 6 '20 at 9:02
• IMO doit should instead be the execute method. Changing props fires the execute method. pasteall.org/VSiA – batFINGER Oct 6 '20 at 9:34
• Can call any other method from execute. The execute method gets fired when props change. To throw a spanner in the works: defining a property group with update methods on properties, and layout in a sub-panel may be a more robust approach to setting preferences. – batFINGER Oct 6 '20 at 9:48

You need to set a Redo Panel.

In this tutorial Sybren shows how to create an operator with a redo panel (at 8:17 he starts talking about it)

At 13:38 he talks exactly about what you need. Basicly you need to add:

bl_options = {'REGISTER','UNDO'}


after your bl_description.

• I did not know that is called Redo Panel. Thank you very much for your answer. Solved my problem. One more question. Do I have to keep this def invoke(self, context, event): ...etc anyway? Because I removed it and I added bl_options = {'REGISTER','UNDO'}and works fine!!! – Simonetos The Greek Oct 6 '20 at 9:45
• @SimonetosTheGreek use invoke to have a popup at location of mouse event (eg link posted in q comment with invoke props popup) Without defaults to the bottom LH corner in 3D view. – batFINGER Oct 6 '20 at 9:52