Javascript add-in to modify user parameters

Javascript add-in to modify user parameters

Anonymous
Not applicable
2,588 Views
4 Replies
Message 1 of 5

Javascript add-in to modify user parameters

Anonymous
Not applicable

Hi

 

I've been testing out writing a Javascript Add-in which would manipulate user params. Since it's a new environment I've started with the AddInSample javascript code which is bundled with Autodesk Fusion 360 and created new addIn with nearly identical sources to make the UI initialization work. The major modifications I've made are in the onInputChanged function. The current version of the source looks the following way:

 

        var onInputChanged = function(args) {
            console.log('onInputChanged', args, args.input, args.input.name, '=', args.input.value);
        
            var name = args.input.name;
            var expr = args.input.value;
            try
            {
                var app = adsk.core.Application.get();
                var design = app.activeProduct;
		var userParams = design.userParameters
                var p = design.userParameters.itemByName(name);
		p.expression = ''+expr;
            } catch (e) {
                ui.messageBox(locStrings.FailedInInputChangedEvent + errorDescription(e));
            }
        };

What I've been struggling with is the runtime behaviour of the code above. To begin with I've defined 2 user parameters and used them to dimension a rectangle in a sketch. When I edit a parameter in the UI of the add in what is happening is the following sequence of events which I've caught with the debugger breakpoint: 

 

  1. onInputChanged function is called with the value from UI inputs
  2. The new value of parameter expression is being applied
  3. After onInputChanged function finishes previous user parameters values are being restored

All of these are illustrated in images I've attached: 

  • step1.png - before applying the new value the dimension in the upper edge of the screenshot is 10mm
  • step2.png - after updating the parameter's expression new value is applied and the value of the dimension in the upper edge applies and is 20mm
  • step3.png - after the function exits the dimension returns to 10mm

 

What I'm suspecting is that handling of the userParams manipulation is done in a temporary context/thread and thus it doesn't apply to the activeDocument/design context so it could be persisted. Does somebody maybe know how to persist the new expression value to the design?

0 Likes
2,589 Views
4 Replies
Replies (4)
Message 2 of 5

marshaltu
Autodesk
Autodesk

Hello,

 

I would like to recommend you do that in onExecute event instead of onInputChanged. The following Python sample would demostrade what you want. You can translate it to Javascript if you prefer to Javascript language.

 

In a command, generally we only commit the changes which made in onExecute. For those changes in other events, we will treat it as command preview and abort them right away before onExecute event is executed.

 

Thanks,

Marshal

 

#Author-
#Description-

import adsk.core, adsk.fusion, traceback
import os

# global set of event handlers to keep them referenced for the duration of the command
handlers = []

app = adsk.core.Application.get()
if app:
    ui = app.userInterface

class MyCommandExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            command = args.firingEvent.sender
            inputs = command.commandInputs

            # We need access to the inputs within a command during the execute.
            nameInput = inputs.itemById('Name')
            valInput = inputs.itemById('Value')

            name = nameInput.value
            expr = valInput.value
            design = app.activeProduct
            p = design.userParameters.itemByName(name)
            p.expression = '' + expr           

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

class MyCommandDestroyHandler(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:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):    
    def __init__(self):
        super().__init__()        
    def notify(self, args):
        try:
            cmd = args.command
            onExecute = MyCommandExecuteHandler()
            cmd.execute.add(onExecute)
            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            
            # keep the handler referenced beyond this function
            handlers.append(onExecute)
            handlers.append(onDestroy)

            # Define the inputs.
            inputs = cmd.commandInputs

            inputs.addStringValueInput('Name', 'Number of Parameter', 'A')
            inputs.addStringValueInput('Value', 'Value of Parameter', '1 in')

        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
                
def run(context):
    try:
        commandId = 'ModifyParameter'
        commandName = 'Modify parameter'
        commandDescription = 'Modify parameter'
        cmdDef = ui.commandDefinitions.itemById(commandId)
        if not cmdDef:
            resourceDir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'resources') # absolute resource file path is specified
            cmdDef = ui.commandDefinitions.addButtonDefinition(commandId, commandName, commandDescription, resourceDir)

        onCommandCreated = MyCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        # keep the handler referenced beyond this function
        handlers.append(onCommandCreated)

        inputs = adsk.core.NamedValues.create()
        cmdDef.execute(inputs)

        # prevent this module from being terminate 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()))


Marshal Tu
Fusion Developer
>
0 Likes
Message 3 of 5

prainsberry
Autodesk
Autodesk

Hey check this example out.  I actually use both methods.  It is kind of nice to see the parameters update live when you are changing them, then you commit the values in on execute.

 

hope this helps:

https://github.com/tapnair/ParamEdit

 

Sorry it is also in Python.  BTW if you are going to be doing anythign that involves a lot of actions like updating parameters you will find it significantly faster in python vs. Javascript.   JS runs out of process and is orders of magnatude slower to compute.  If it is possible for your application.

 



Patrick Rainsberry
Developer Advocate, Fusion 360
0 Likes
Message 4 of 5

Anonymous
Not applicable

Thank you 

 

0 Likes
Message 5 of 5

prainsberry
Autodesk
Autodesk
Thanks man, glad to help out. Feel free to use this code as needed.

Regards,
Patrick Rainsberry


Patrick Rainsberry
Developer Advocate, Fusion 360
0 Likes