1

I have two properties set in my Class:

o_color: FloatVectorProperty(name="Obj Color",subtype='COLOR',default=[0.0,0.0,0.0],set=set_o,update=set_o_color)
mode_o: EnumProperty(name="Mode", items=[("O1", "Randomize", ""),("O2", "Set", "")], default="O1",update=change_mode_o)

I want to set the color of o_color to a specific value when mode_o is switched to O2. In my head it was simple: when mode_o updates, I run the set function of o_color:

# update of EnumProperty
def change_mode_o(self, context):
    if self['mode_o'] == 1: # if switched to O2
        set_o(self, tuple(1, 0.5, 0)) # set o_color to (1, 0.5, 0)

# set of FloatVectorProperty
def set_o(self, value):
    self["o_color"] = value

in reality:

  • my color doesn't update. No errors, just nothing happens.
  • when I try to select color it only allows me to change Saturation. This seems to happen if FloatVectorProperty has set or get function passed:

enter image description here

What am I doing wrong?

Sergey Kritskiy
  • 895
  • 5
  • 15
  • Does it work if the color property is part of a panel? If so try add a def check(self, context): return True method to the operator. – brockmann Mar 26 '20 at 11:47
  • Perhaps you need to copy those attribute and assign them separately? Since the code you did is actually changing the pointer of the List (And you gave him a tuple... not sure it can work) – HikariTW Mar 26 '20 at 11:50
  • @brockmann haven't tried as a panel (never made them, seems like a lot of things to change... so maybe later) but adding the check function didn't do anything – Sergey Kritskiy Mar 26 '20 at 11:57
  • @HikariTW yes I've tried that, same result – Sergey Kritskiy Mar 26 '20 at 11:57
  • different self problem? Can you open up the system console to see whether there is any error? – HikariTW Mar 26 '20 at 12:01
  • @HikariTW there were no errors. If I assign an int instead of a list, update of the FloatVectorProperty prints this integer – Sergey Kritskiy Mar 26 '20 at 12:05
  • @brockmann tried to convert to a panel, they probably work somehow differently? none of my props were registered (getting rna_uiItemR: property not found: view3d.copy_paste_viewport_sk.o_color) – Sergey Kritskiy Mar 26 '20 at 12:06
  • Is there any workaround to avoid using getter and setter? I don't feel you need to use them in your scenario. I mean: self["o_color"] = (.0,.5,1.0)? – HikariTW Mar 26 '20 at 12:17
  • @HikariTW this won't work until I manually change a color of o_color. Not sure exactly how it works, but o_color doesn't seem to exist in self until I change it at least ones – Sergey Kritskiy Mar 26 '20 at 12:52
  • Yeah, you probably need to call redraw after that operation since no any event occur and panel won't notice the change. BTW did you just type: tuple(1, 0.5, 0) in your code? Did it work? – HikariTW Mar 26 '20 at 12:56
  • @HikariTW I did, it didn't :( – Sergey Kritskiy Mar 26 '20 at 13:01
  • Oh if you didn't change them from default value, those value won't be exist since we don't need to store a duplicated default thing in system. See this post Blender Setter – HikariTW Mar 26 '20 at 13:10
  • 1
    oh! setting it via self.o_color in update function of EnumProperty worked! (self['o_color'] didn't) – Sergey Kritskiy Mar 26 '20 at 13:17
  • Changed my mind, adding min and max seems required, although I would expect that changing the subtype should be enough to make it work. Added as example to HikariTW's answer. – brockmann Mar 26 '20 at 13:41

1 Answers1

2

Elaborate From brockmann comment and Blender API:

bpy.props.FloatVectorProperty(
min=sys.float_info.min, 
max=sys.float_info.max, 
soft_min=sys.float_info.min, 
soft_max=sys.float_info.max)
  • min (float) – Hard minimum, trying to assign a value below will silently assign this minimum instead.
  • max (float) – Hard maximum, trying to assign a value above will silently assign this maximum instead.
  • soft_min (float) – Soft minimum (>= min), user won’t be able to drag the widget below this value in the UI.
  • soft_max (float) – Soft maximum (<= max), user won’t be able to drag the widget above this value in the UI.

You need to set min = 0.0 and max=1.0 (or soft min/max) for the color subtype property. So it will look like this:

a_color : bpy.props.FloatVectorProperty(name='Color',subtype='COLOR_GAMMA',size=4,default=(0.5,0.5,0.9,1.0),min = 0.0, max = 1.0)

b_color : bpy.props.FloatVectorProperty(name='Color',subtype='COLOR',min = 0.0, max = 1.0)

It seems like color also support by light system. So the min max wasn't set by default, causing the silder getting a ridiculous range and break the panel


Operator based on this answer:

import bpy


class SimplePropConfirmOperator(bpy.types.Operator):
    """Really?"""
    bl_idname = "my_category.custom_confirm_dialog"
    bl_label = "Do you really want to do that?"
    bl_options = {'REGISTER', 'INTERNAL'}

    def update_func(self, context):
        #print("my test function", self)
        self.my_color = (0.5,0.5,0.9, 1.0) # Alpha

    my_enum : bpy.props.EnumProperty(
        items = (("RND", "Randomize", ""),("SET", "Set", "")),
        update = update_func)

    my_color : bpy.props.FloatVectorProperty(
        subtype='COLOR', 
        min=0.0, 
        max=1.0,
        size=4) # Alpha

    @classmethod
    def poll(cls, context):
        return True

    def execute(self, context):
        self.report({'INFO'}, "YES!")
        return {'FINISHED'}

    '''
    def check(self, context): 
        return True
    '''

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

    def draw(self, context):
        row = self.layout
        row.prop(self, "my_enum", text="Property A")
        if self.my_enum == "SET":
            row.prop(self, "my_color", text="Property B")


class OBJECT_PT_CustomPanel(bpy.types.Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        layout.operator(SimplePropConfirmOperator.bl_idname)

def register():
    bpy.utils.register_class(OBJECT_PT_CustomPanel)
    bpy.utils.register_class(SimplePropConfirmOperator)

def unregister():
    bpy.utils.unregister_class(SimplePropConfirmOperator)
    bpy.utils.unregister_class(OBJECT_PT_CustomPanel)

if __name__ == "__main__":
    register()
brockmann
  • 12,613
  • 4
  • 50
  • 93
HikariTW
  • 7,821
  • 2
  • 18
  • 37