validateInputs Command Event doesn't seem to fire

validateInputs Command Event doesn't seem to fire

pragungoyal
Explorer Explorer
604 Views
2 Replies
Message 1 of 3

validateInputs Command Event doesn't seem to fire

pragungoyal
Explorer
Explorer

Hello, I'm beginning writing scripts for Fusion 360, so far it seems like quite an awesome framework. I was hoping that someone could help me with the following two questions.

1. I am however trouble understanding if there's something I'm missing here to get the ValidateInputs event to fire at all. 

2. I seem to get stuck with my VSCode responding to actions happening on Fusion 360 side (for example it just doesn't seem to activate breakpoints). I'm running Fusion 360 2.0.9642, and VSCode 1.52.1. 

 

I've attached the code here, as far as I can understand I am plumbing up the ValidateInput event handler correctly, but I'm not sure. Thank you!

 

#Author-Pragun Goyal 
#Description-This add-in contains several useful tools to design Mechanical Keyboards

import adsk.core, adsk.fusion, adsk.cam, traceback
import json, re 

handlers = []

tbPanel = None

number_of_key_style_identifiers = 20
default_key_style_identifiers = ['1u', '1.25u', '1.5u', '1.75u', '2u', '2.25u', '2.5u', '2.75u', '3u']

attribute_group_name = 'mechKbrdTools'
key_styles_attrib_name = 'key_styles'

identifier_text_ids = ['identifier_text_%d'%(i,) for i in range(number_of_key_style_identifiers)]
component_selection_ids = ['selected_component_%d'%(i,) for i in range(number_of_key_style_identifiers)]


def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        workSpace = ui.workspaces.itemById('FusionSolidEnvironment')
        tbPanels = workSpace.toolbarPanels
        
        global tbPanel
        tbPanel = tbPanels.itemById('mechKbrdTools')
        if tbPanel:
            tbPanel.deleteMe()
        tbPanel = tbPanels.add('mechKbrdTools', 'MechKbrd Tools', 'Mechanical Keyboard', False)
        
        # Empty panel can't be displayed. Add a command to the panel
        cmdDef = ui.commandDefinitions.itemById('select_single_key_components')
        if cmdDef:
            cmdDef.deleteMe()
        
        cmdDef = ui.commandDefinitions.addButtonDefinition('select_single_key_components', 'Select Components for Single Key', 'Demo for new command')

        # Connect to the command created event.
        sampleCommandCreated = SelectSingleKeyComponentsCreatedEventHandler()
        cmdDef.commandCreated.add(sampleCommandCreated)
        handlers.append(sampleCommandCreated)
        
        tbPanel.controls.addCommand(cmdDef)

        ui.messageBox('Mechanical Keyboard Design Tools Add-In Started')

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

def stop(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        if tbPanel:
            tbPanel.deleteMe()
        
        ui.messageBox('Stop addin')

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

class SelectSingleKeyComponentsValidateInputsHandler(adsk.core.ValidateInputsEventHandler):
    def __init__(self):
        super().__init__()

    def validate_key_identifier_list(txt):
        txt_list = txt.split(',')
        txt_list = [i.strip() for i in txt_list]
        valid = True
        for txt_fragment in txt_list:
            valid &= validate_key_identifier(txt_fragment)
        return valid

    def validate_key_identifier(txt):
        if(re.search('[^\w.]',txt) == None):
            return True
        else:
            return False

    def notify(self, args):
        print("Validate Handler\n")
        app = adsk.core.Application.get()
        ui  = app.userInterface
        ui.messageBox('In command validate event handler.')

        eventArgs = adsk.core.ValidateInputsEventArgs.cast(args)
        inputs = eventArgs.firingEvent.sender.commandInputs
    
        inputs_valid = True 

        for i in range(number_of_key_style_identifiers):
            key_style_identifier_text = inputs.itemById(identifier_text_ids[i])
            key_style_selected_component = inputs.itemById(component_selection_ids[i])
            inputs_valid &= validate_key_identifier_list(key_style_identifier_text)
            if key_style_selected_component.selection(0) is not None:
                pass    
        
        eventArgs.areInputsValid = inputs_valid

# Event handler for the commandCreated event.
class SelectSingleKeyComponentsCreatedEventHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args):
        app = adsk.core.Application.get()
        design = adsk.fusion.Design.cast(app.activeProduct)

        eventArgs = adsk.core.CommandCreatedEventArgs.cast(args)
        cmd = eventArgs.command
        
        ui  = app.userInterface
        ui.messageBox('In command create event handler.')
        print("Create Event Handler\n")

         # Get the CommandInputs collection to create new command inputs.            
        inputs = cmd.commandInputs

        list_key_style_identifier_texts = []
        list_key_style_component_selection = []

        attribs = design.findAttributes(attribute_group_name, key_styles_attrib_name)
        associated_key_styles = []
        associated_key_style_names = []
        if len(attribs) > 0:
            for attrib_lst_json in attribs:
                attrib_lst = json.loads(attrib_lst_json)
                for attrib in attrib_lst:
                    if attrib.name in associated_key_style_names:
                        raise NameError("Duplicate Attribute found %s"%(attrib.name,))
                    associated_key_styles.append(attrib)
                    associated_key_style_names.append(attrib.name)

        unassociated_attrib_names = set(default_key_style_identifiers) - set(associated_key_style_names)

        key_style_identifier_suggestion_list = list(unassociated_attrib_names)
        for i in range(number_of_key_style_identifiers):
            txt = ''
            if i < len(key_style_identifier_suggestion_list):
                txt = key_style_identifier_suggestion_list[i]

            key_style_identifier_text = inputs.addStringValueInput(identifier_text_ids[i],'Key Identifier', txt)
            component_selection = inputs.addSelectionInput(component_selection_ids[i],'Component for Keys with above identifier','Select a component to be inserted for the keys identified with this identifier')
            component_selection.addSelectionFilter('Occurrences')
            list_key_style_identifier_texts.append(key_style_identifier_text)
            list_key_style_component_selection.append(component_selection)

        # Connect to the execute event.
        onValidateInputs = SelectSingleKeyComponentsValidateInputsHandler()
        cmd.validateInputs.add(onValidateInputs)
        handlers.append(onValidateInputs)

        onExecute = SelectSingleKeyComponentsExecuteHandler()    
        cmd.execute.add(onExecute)
        handlers.append(onExecute)
        


# Event handler for the execute event.
class SelectSingleKeyComponentsExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        print("Execute Handler\n")
        eventArgs = adsk.core.CommandEventArgs.cast(args)

        # Code to react to the event.
        app = adsk.core.Application.get()
        ui  = app.userInterface
        ui.messageBox('In command execute event handler.')
0 Likes
Accepted solutions (1)
605 Views
2 Replies
Replies (2)
Message 2 of 3

kandennti
Mentor
Mentor
Accepted solution

Hi @pragungoyal .

 

It seems to be called correctly when I setSelectionLimits(0).

・・・
            component_selection = inputs.addSelectionInput(
                component_selection_ids[i],
                'Component for Keys with above identifier',
                'Select a component to be inserted for the keys identified with this identifier')
            component_selection.addSelectionFilter('Occurrences')
            component_selection.setSelectionLimits(0) # this
            list_key_style_component_selection.append(component_selection)
・・・

 

I don't know why, but it didn't work the way I thought it would if there were multiple SelectionCommandInputs in the dialog.
I also learned this from this forum.

Message 3 of 3

pragungoyal
Explorer
Explorer

Thanks a lot that helps a lot! I think maybe the SelectionCommandInput object is not fully defined/{ready to use} til min/max selections are set for it and it prevents the generation of ValidateInput Events. Anyhow, your solution took care of it.

As for item 2, I'll post again when I can accurately describe my debugging woes.

0 Likes