Community
Fusion API and Scripts
Got a new add-in to share? Need something specialized to be scripted? Ask questions or share what you’ve discovered with the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

If selector is present then validator won't be called until a selection is made

4 REPLIES 4
Reply
Message 1 of 5
adonno
246 Views, 4 Replies

If selector is present then validator won't be called until a selection is made

I have a simple piece of code (listed below) that has a SelectionCommandInput (filtered to require a single sketch line) and an input box where I expect an integer >= 3 to be entered. Following the example in SpurGear, to ensure that I actually get an integer, I created a ValidateInputsEventHandler class, in which I check the input. The thing that is bothering me is that validator only gets called if (and only if) I have already selected a line. If I remove the line selector then the validator gets called as expected.

 

Is this expected or am I doing something wrong.

 

Thanks

Tony 

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

app = adsk.core.Application.cast(None)
ui = adsk.core.UserInterface.cast(None)
handlers = []

# Global variables
ID = 'TV'
MIN_VALUE = 3

# Command inputs
_selected_line = adsk.core.SelectionCommandInput.cast(None)
_number = adsk.core.StringValueCommandInput.cast(None)
_err_message = adsk.core.StringValueCommandInput.cast(None)

def run(context):
    try:
        global app, ui, handlers
        
        app = adsk.core.Application.get()
        ui  = app.userInterface

        # Get the existing command definition or create it if it doesn't already exist.
        cmd_def = ui.commandDefinitions.itemById('TestValidation')
        if not cmd_def:
            cmd_def = ui.commandDefinitions.addButtonDefinition('TestValidation', 
                                                                'Test Validation', 
                                                                'Sample to demonstrate validaiton')
        
        # Create a command handler
        on_command = TVCommandCreatedHandler()
        cmd_def.commandCreated.add(on_command)
        handlers.append(on_command)
        
        # Execute the command
        cmd_def.execute()
        
        # Prevent this module from being terminated when the script returns, because we are waiting for event handlers to fire.
        adsk.autoTerminate(False)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


class TVCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
        
    def notify(self, args):
        try:
            global handlers, _selected_line, _number, _err_message
            
            # Get the command that was created.
            cmd = adsk.core.Command.cast(args.command)
            cmd.isExecutedWhenPreEmpted = False
            inputs = cmd.commandInputs
    
            # Add a selector to get a sketch line
            _selected_line = inputs.addSelectionInput(ID + '_selected_line', 'BaseLine', 'Select a sketch line')
            _selected_line.setSelectionLimits(1, 1)
            _selected_line.selectionFilters = ['SketchLines']        

            # Add a text box to get a number (>=3)
            _number = inputs.addStringValueInput(ID + '_number', 'Number', str(MIN_VALUE))

            
            # Add an error message box for feedback
            _err_message = inputs.addTextBoxCommandInput(ID + '_err_message', '', '', 2, True)
            _err_message.isFullWidth = True

            # Add a input validator
            on_validate_inputs = TVCommandValidateInputsHandler()
            cmd.validateInputs.add(on_validate_inputs)
            handlers.append(on_validate_inputs)
            
            # Connect to the command destroyed event.
            on_destroy = TVCommandDestroyHandler()
            cmd.destroy.add(on_destroy)
            handlers.append(on_destroy)
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
            
    
class TVCommandValidateInputsHandler(adsk.core.ValidateInputsEventHandler):
    def __init__(self):
        super().__init__()
        
    def notify(self, args):
        try:
            global _err_message
            event_args = adsk.core.ValidateInputsEventArgs.cast(args)
            
            _err_message.text = ''
 
            if not _number.value.isdigit():
                _err_message.text = 'Number must be a whole number'
                event_args.areInputsValid = False
                return
            else:
                segment_count = int(_number.value)

            if segment_count < 3:
                _err_message.text = 'Number must be 3 or more'
                event_args.areInputsValid = False
                return           
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
        
        
# Event handler that reacts to when the command is destroyed. This terminates the script.            
class TVCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
        
    def notify(self, args):
        try:
            # When the command is done, terminate the script
            # This will release all globals which will remove all event handlers
            adsk.terminate()
        except:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
4 REPLIES 4
Message 2 of 5
rory2WEHA
in reply to: adonno

I'm a few years behind this one but I have the same issue, did you ever resolve it?

Message 3 of 5
j.han97
in reply to: adonno

Just guessing: Since selection limits are specified Fusion 360 will wait till the selection input is satisfied (in this case 1 selection has been made) before it goes on to validate the inputs.

 

Try disabling the selection limits and see if the issue exists. 

Message 4 of 5
kandennti
in reply to: rory2WEHA

Hi @rory2WEHA .

 

Why not use the InputChanged event to send a message to warn?

https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-1c8998bd-c4b1-4b91-881d-0b57cf468a5f 

 

I modified the above example.

・・・
class TVCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
        
    def notify(self, args):
        try:
            global handlers, _selected_line, _number, _err_message
            
            # Get the command that was created.
            cmd = adsk.core.Command.cast(args.command)
            cmd.isExecutedWhenPreEmpted = False
            inputs = cmd.commandInputs
    
            # Add a selector to get a sketch line
            _selected_line = inputs.addSelectionInput(ID + '_selected_line', 'BaseLine', 'Select a sketch line')
            _selected_line.setSelectionLimits(1, 1)
            _selected_line.selectionFilters = ['SketchLines']        

            # Add a text box to get a number (>=3)
            _number = inputs.addStringValueInput(ID + '_number', 'Number', str(MIN_VALUE))

            
            # Add an error message box for feedback
            _err_message = inputs.addTextBoxCommandInput(ID + '_err_message', '', '', 2, True)
            _err_message.isFullWidth = True

            # Add a input validator
            on_validate_inputs = TVCommandValidateInputsHandler()
            cmd.validateInputs.add(on_validate_inputs)
            handlers.append(on_validate_inputs)
            
            # Connect to the command destroyed event.
            on_destroy = TVCommandDestroyHandler()
            cmd.destroy.add(on_destroy)
            handlers.append(on_destroy)

            # ***addition***
            onInputChanged = MyInputChangedHandler()
            cmd.inputChanged.add(onInputChanged)
            handlers.append(onInputChanged)

        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
・・・
class TVCommandValidateInputsHandler(adsk.core.ValidateInputsEventHandler):
    def __init__(self):
        super().__init__()
        
    def notify(self, args):
        adsk.core.Application.get().log(args.firingEvent.name)
        try:
            global _err_message
            event_args = adsk.core.ValidateInputsEventArgs.cast(args)
 
            if not _number.value.isdigit():
                event_args.areInputsValid = False
                return
            else:
                segment_count = int(_number.value)

            if segment_count < 3:
                event_args.areInputsValid = False
                return           
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
・・・
class MyInputChangedHandler(adsk.core.InputChangedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: adsk.core.InputChangedEventArgs):
        global _err_message
        _err_message.text = ''

        if not _number.value.isdigit():
            _err_message.text = 'Number must be a whole number'
            return
        else:
            segment_count = int(_number.value)

        if segment_count < 3:
            _err_message.text = 'Number must be 3 or more'
            return     

 

Message 5 of 5
adonno
in reply to: rory2WEHA

To be honest I don't even remember what piece of code I was working on at the time when I found this. I'm fairly certain that I did not find a solution but the suggestion from kandennti in the thread might be a good solution. I just do not have the time right now to dig back into this but would be interested to know if that suggestion solves your issue.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report