Message 1 of 2
Custom graphics following mouse cursor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
what I do: I have written this code that creates a custom graphics line on each point the mouse cursor reports back while hoovering over a face.
it draws a new line for every change in position. The lines are drawn normal to the face.
what I want to do: make the custom graphics line follow the mouse pointer, updating the line for every position. Not showing the last line.
what should I do? I have tried the deleteMe() way but then fusion crashes. Can someone help me?
this is the code from the entry.py file. The rest should be as the blueprint when you create a new addin.
import adsk.core
import os
import adsk.fusion
from ...lib import fusionAddInUtils as futil
from ... import config
app = adsk.core.Application.get()
ui = app.userInterface
product = app.activeProduct
design = adsk.fusion.Design.cast(product)
custom_graphics_group = design.rootComponent.customGraphicsGroups.add()
# TODO *** Specify the command identity information. ***
CMD_ID = f'{config.COMPANY_NAME}_{config.ADDIN_NAME}_cmdDialog'
CMD_NAME = 'Command Dialog Sample'
CMD_Description = 'A Fusion Add-in Command with a dialog'
# Specify that the command will be promoted to the panel.
IS_PROMOTED = True
# TODO *** Define the location where the command button will be created. ***
# This is done by specifying the workspace, the tab, and the panel, and the
# command it will be inserted beside. Not providing the command to position it
# will insert it at the end.
WORKSPACE_ID = 'FusionSolidEnvironment'
PANEL_ID = 'SolidScriptsAddinsPanel'
COMMAND_BESIDE_ID = 'ScriptsManagerCommand'
# Resource location for command icons, here we assume a sub folder in this directory named "resources".
ICON_FOLDER = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'resources', '')
# Local list of event handlers used to maintain a reference so
# they are not released and garbage collected.
local_handlers = []
# Executed when add-in is run.
def start():
# Create a command Definition.
cmd_def = ui.commandDefinitions.addButtonDefinition(CMD_ID, CMD_NAME, CMD_Description, ICON_FOLDER)
# Define an event handler for the command created event. It will be called when the button is clicked.
futil.add_handler(cmd_def.commandCreated, command_created)
# ******** Add a button into the UI so the user can run the command. ********
# Get the target workspace the button will be created in.
workspace = ui.workspaces.itemById(WORKSPACE_ID)
# Get the panel the button will be created in.
panel = workspace.toolbarPanels.itemById(PANEL_ID)
# Create the button command control in the UI after the specified existing command.
control = panel.controls.addCommand(cmd_def, COMMAND_BESIDE_ID, False)
# Specify if the command is promoted to the main toolbar.
control.isPromoted = IS_PROMOTED
# Executed when add-in is stopped.
def stop():
# Get the various UI elements for this command
workspace = ui.workspaces.itemById(WORKSPACE_ID)
panel = workspace.toolbarPanels.itemById(PANEL_ID)
command_control = panel.controls.itemById(CMD_ID)
command_definition = ui.commandDefinitions.itemById(CMD_ID)
# Delete the button command control
if command_control:
command_control.deleteMe()
# Delete the command definition
if command_definition:
command_definition.deleteMe()
# Function that is called when a user clicks the corresponding button in the UI.
# This defines the contents of the command dialog and connects to the command related events.
def command_created(args: adsk.core.CommandCreatedEventArgs):
# General logging for debug.
futil.log(f'{CMD_NAME} Command Created Event')
# https://help.autodesk.com/view/fusion360/ENU/?contextId=CommandInputs
inputs = args.command.commandInputs
# TODO Define the dialog for your command by adding different inputs to the command.
# Create a simple text box input.
inputs.addTextBoxCommandInput('text_box', 'Some Text', 'Enter some text.', 1, False)
# Create a value input field and set the default using 1 unit of the default length unit.
defaultLengthUnits = app.activeProduct.unitsManager.defaultLengthUnits
default_value = adsk.core.ValueInput.createByString('1')
inputs.addValueInput('value_input', 'Some Value', defaultLengthUnits, default_value)
# Create a selection input
inputs.addSelectionInput('selection_input', 'Selection Input', 'select anything')
# TODO Connect to the events that are needed by this command.
futil.add_handler(args.command.execute, command_execute, local_handlers=local_handlers)
futil.add_handler(args.command.inputChanged, command_input_changed, local_handlers=local_handlers)
futil.add_handler(args.command.executePreview, command_preview, local_handlers=local_handlers)
futil.add_handler(args.command.validateInputs, command_validate_input, local_handlers=local_handlers)
futil.add_handler(args.command.destroy, command_destroy, local_handlers=local_handlers)
futil.add_handler(args.command.preSelect, command_preSelect, local_handlers=local_handlers)
futil.add_handler(args.command.select, command_Select, local_handlers=local_handlers)
# This event handler is called when the user clicks the OK button in the command dialog or
# is immediately called after the created event not command inputs were created for the dialog.
def command_execute(args: adsk.core.CommandEventArgs):
# General logging for debug.
futil.log(f'{CMD_NAME} Command Execute Event')
# TODO ******************************** Your code here ********************************
# Get a reference to your command's inputs.
inputs = args.command.commandInputs
text_box: adsk.core.TextBoxCommandInput = inputs.itemById('text_box')
value_input: adsk.core.ValueCommandInput = inputs.itemById('value_input')
# Do something interesting
text = text_box.text
expression = value_input.expression
msg = f'Your text: {text}<br>Your value: {expression}'
ui.messageBox(msg)
def command_Select(args: adsk.core.SelectionEventArgs):
futil.log(f'{CMD_NAME} Command Select Event')
global custom_graphics_group
selection = args.selection
selected_entity = selection.entity
#print(selected_entity)
input_point = args.selection.point
#print(input_point.asVector())
if isinstance (selected_entity, adsk.fusion.BRepFace):
# Get a specific vertice of selected face
areaSurface = adsk.core.SurfaceEvaluator.area
vertices = selected_entity.vertices.item(0)
#print(vertices.geometry.asArray())
# Get normal a selected point
normalAtPoint = selected_entity.evaluator.getNormalAtPoint(input_point)
print("normalAtPoint:", normalAtPoint)
normalVector = normalAtPoint[1]
# Scale normal vector
scaleVector = 10.0
normalVector.scaleBy(scaleVector)
print("lenght", normalVector.asArray())
endPoint = adsk.core.Point3D.create(
input_point.x + normalVector.x,
input_point.y + normalVector.y,
input_point.z + normalVector.z)
# Create and draw line based on vector
line = adsk.core.Line3D.create(input_point,endPoint)
lineGraphics = custom_graphics_group.addCurve(line)
# Modifications of line
lineGraphics.weight = 5
redColor = adsk.core.Color.create(255,0,0,255)
solidColor = adsk.fusion.CustomGraphicsSolidColorEffect.create(redColor)
lineGraphics.color = solidColor
print(endPoint)
else:
print("Not a BRep face")
app.activeViewport.refresh()
def command_preSelect(args: adsk.core.SelectionEventArgs):
global custom_graphics_group
print("preSelect")
selection = args.selection
selected_entity = selection.entity
#print(selected_entity)
input_point = args.selection.point
#print(input_point.asVector())
if isinstance (selected_entity, adsk.fusion.BRepFace):
# Get a specific vertice of selected face
areaSurface = adsk.core.SurfaceEvaluator.area
vertices = selected_entity.vertices.item(0)
#print(vertices.geometry.asArray())
# Get normal a selected point
normalAtPoint = selected_entity.evaluator.getNormalAtPoint(input_point)
print("normalAtPoint:", normalAtPoint)
normalVector = normalAtPoint[1]
# Scale normal vector
scaleVector = 10.0
normalVector.scaleBy(scaleVector)
print("lenght", normalVector.asArray())
endPoint = adsk.core.Point3D.create(
input_point.x + normalVector.x,
input_point.y + normalVector.y,
input_point.z + normalVector.z)
# Create and draw line based on vector
line = adsk.core.Line3D.create(input_point,endPoint)
lineGraphics = custom_graphics_group.addCurve(line)
# Modifications of line
lineGraphics.weight = 5
redColor = adsk.core.Color.create(255,0,0,255)
solidColor = adsk.fusion.CustomGraphicsSolidColorEffect.create(redColor)
lineGraphics.color = solidColor
print(endPoint)
def command_preview(args: adsk.core.CommandEventArgs):
# General logging for debug.
futil.log(f'{CMD_NAME} Command Preview Event')
inputs = args.command.commandInputs
# This event handler is called when the user changes anything in the command dialog
# allowing you to modify values of other inputs based on that change.
def command_input_changed(args: adsk.core.InputChangedEventArgs):
changed_input = args.input
inputs = args.inputs
# General logging for debug.
futil.log(f'{CMD_NAME} Input Changed Event fired from a change to {changed_input.id}')
# This event handler is called when the user interacts with any of the inputs in the dialog
# which allows you to verify that all of the inputs are valid and enables the OK button.
def command_validate_input(args: adsk.core.ValidateInputsEventArgs):
# General logging for debug.
futil.log(f'{CMD_NAME} Validate Input Event')
inputs = args.inputs
# Verify the validity of the input values. This controls if the OK button is enabled or not.
valueInput = inputs.itemById('value_input')
if valueInput.value >= 0:
args.areInputsValid = True
else:
args.areInputsValid = False
# This event handler is called when the command terminates.
def command_destroy(args: adsk.core.CommandEventArgs):
# General logging for debug.
futil.log(f'{CMD_NAME} Command Destroy Event')
global local_handlers
local_handlers = []