3

I'm trying to call a method from within the same class. I've found that if I have no args apart from self and context, I can simply call it using 'UpdateObjectProperties' and it works perfectly. However I want to add other arguments to it and when I do that I have to add in self and context too. I don't know what values to add there to get it to work. I've included an exert of my script here. Not the whole thing as it is several hundred lines long but that should include all necessary info. There will be more enum properties calling the method than just AIInput. Any ideas?

#Input field information can be found here
class PanelProperties(bpy.types.PropertyGroup):
    """Input field information"""
#Create a tuple containing the objects shape keys            
def GetVisemeList(self, context):
    curIndex = 0
    ListForTuple = []
    for shapekey in bpy.context.active_object.data.shape_keys.key_blocks.keys():
        currentKeyIdentifier = shapekey
        currentKeyName = shapekey
        currentKeyInfo = ""
        newTuple = (currentKeyIdentifier, currentKeyName, currentKeyInfo)
        ListForTuple.append(newTuple)
        curIndex = curIndex + 1                    
    FinalTuple = tuple(ListForTuple)
    return FinalTuple  

#This method is called when the property is updated. It is the one I'm having trouble with.
def UpdateObjectProperties(self, context, stringName, value):
    scene = bpy.context.scene
    if 'TextToSpeech_toolprops2' in scene:           
        obj = bpy.context.active_object
        rna_ui = obj.get('_RNA_UI')
        if rna_ui is None:
            obj['_RNA_UI'] = {}
            rna_ui = obj['_RNA_UI']

        obj[stringName] = value

        rna_ui[stringName] = {"description":stringName,
                "default": "",
                "min":0,
                "max":1,
                "soft_min":0,
                "soft_max":1}

#Info for the inputs is found here

AIInput : bpy.props.EnumProperty(
    name= "AI",
    description = "Viseme Shape",        
    items = GetVisemeList,
    update = UpdateObjectProperties('self = ??????', 'context = ??????', "AI", bpy.types.scene.TextToSpeech_tool.AIInput)

class TEXTTOSPEECHANIM_PT_main_panel(bpy.types.Panel): """Creates a panel in the main window for the Text to Speech Animation Tool""" bl_label = "Text To Speech Animation" bl_idname = "TEXTTOSPEECHANIM_PT_main_panel" bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_category = "Text To Anim"

def draw(self,context):
    layout = self.layout
    scene = context.scene
    mytool = scene.TextToSpeech_tool
    mytool2 = scene.TextToSpeech_toolprops2        

    row = layout.row()
    row.label(text = ".wav directory")
    layout.operator(OT_IdentifierFileSelector.bl_idname, icon="FILE_FOLDER", text="Select .wav file")
    layout.label(text = bpy.context.scene.TextToSpeech_toolprops2.AudioDirectory)
    layout.operator(SimpleOperator.bl_idname, text="Get Sentence Data")
    layout.prop(mytool2, "StartFrame")
    layout.prop(mytool2, "FramesPerSecond")
    layout.operator(SimpleOperator2.bl_idname, text="Animate")   

classes = [PanelProperties, TEXTTOSPEECHANIM_PT_main_panel]

def register(): SimpleOperator for cls in classes: bpy.utils.register_class(cls)

bpy.types.Scene.TextToSpeech_tool = bpy.props.PointerProperty(type= PanelProperties) 

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

if name == "main": register()
```

2 Answers2

2

It is an update callback.

Started as a long comment, will throw it together as an answer Will hunt down some links that explain this (probable dupes).

This is what I think you are after

Using a single worker method for properties

Centralizing properties updates in one function?

Firstly going to suggest that if context is passed as an argument use it, not bpy.context Possibly only semantics atm, but if it changes such that the context passed doesn't match global context will cause all sorts of issues...

In the API docs style guide it is recommended to use CamelCase for class names, hence for clarity have changed method & property names to snake_case to coincide with the rest of blender.

The value assigned to update, get, set and items (if items is to be dynamically built via callback) are methods. Consult the bpy.props docs. update and items are expected to have arguments (self, context) a getter (self) and a setter (self, value) where value is the value being set.

def get_viseme_list(self, context):
    ...
    # return the enum items as a list

def update_viseme_list(self, context): # self is in this case scene.tts_tool # self.id_data is scene # the value being updated is self.ai_input

print(self, self.id_data, self.ai_input)

ai_input : bpy.props.EnumProperty( name= "AI", description = "Viseme Shape",
items = get_viseme_list, update = update_viseme_list )

at issue here somewhat is you have defined a scene property that both populates from & updates the context object, that's Ok I suppose if that is the intention, albeit somewhat confusing. Especially in the case of

scene = bpy.data.scenes["Some other not context scene"]
scene.tts_tool.ai_input = 'P'

in which case context.object may or may not be an object of the scene.

Consider instead using

bpy.types.Object.tts_tool = bpy.props.PointerProperty(type= PanelProperties) 

(or Mesh or even Key)

Go Cats.

batFINGER
  • 84,216
  • 10
  • 108
  • 233
  • I think that first link you posted is spot on in terms of what I'm after. I apologize for any confusing naming conventions and code. I am very new at this. Thank you for taking the time to answer :). I'll use your suggestions. – Jess Fittock Jun 22 '21 at 06:19
  • Cheers, happy to help, & abs no apologies necessary. Will close as dupe of first link. – batFINGER Jun 22 '21 at 06:29
0

But why do you want constant values as parameters? You could just use the normal use case you know with the two parameters and "read"/use your values inside the function.

Chris
  • 59,454
  • 6
  • 30
  • 84
  • 1
    Because the AIInput EnumProperty values aren't the only ones I'm going to be using. There are about ten and to keep things neat I don't want to have to repeat the method that many times. – Jess Fittock Jun 22 '21 at 04:44