This commit is contained in:
lovebird 2021-10-31 19:12:13 +01:00
parent 001cc1111e
commit c84f4acf63
3775 changed files with 778592 additions and 0 deletions

View File

@ -0,0 +1,17 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Attach",
"type": "python",
"request": "attach",
"pathMappings": [ {
"localRoot": "${workspaceRoot}",
"remoteRoot": "${workspaceRoot}"}],
"osx": {"filePath":"${file}"},
"windows": {"filePath":"${file}"},
"port": 9000,
"host": "localhost"
}
]
}

View File

@ -0,0 +1,14 @@
{
"autodeskProduct":"Fusion360",
"type":"addin",
"id":"319679C5-AF6D-4A46-862D-93414F1AE117",
"author":"Autodesk Inc.",
"description":{
"": "This is sample addin.",
"1033": "This is sample addin.",
"2052": "这是一个附加模块的例子。"
},
"version":"0.0.1",
"runOnStartup":false,
"supportedOS":"windows|mac"
}

View File

@ -0,0 +1,314 @@
#Author-Autodesk Inc.
#Description-This is sample addin.
import adsk.core, adsk.fusion, traceback, os, gettext
btnCmdIdOnQAT = 'demoButtonCommandOnQAT'
listCmdIdOnQAT = 'demoListCommandOnQAT'
commandIdOnPanel = 'demoCommandOnPanel'
selectionInputId = 'selectionInput'
distanceInputId = 'distanceValueCommandInput'
panelId = 'SolidCreatePanel'
# global set of event handlers to keep them referenced for the duration of the command
handlers = []
# Support localization
_ = None
def getUserLanguage():
app = adsk.core.Application.get()
return {
adsk.core.UserLanguages.ChinesePRCLanguage: "zh-CN",
adsk.core.UserLanguages.ChineseTaiwanLanguage: "zh-TW",
adsk.core.UserLanguages.CzechLanguage: "cs-CZ",
adsk.core.UserLanguages.EnglishLanguage: "en-US",
adsk.core.UserLanguages.FrenchLanguage: "fr-FR",
adsk.core.UserLanguages.GermanLanguage: "de-DE",
adsk.core.UserLanguages.HungarianLanguage: "hu-HU",
adsk.core.UserLanguages.ItalianLanguage: "it-IT",
adsk.core.UserLanguages.JapaneseLanguage: "ja-JP",
adsk.core.UserLanguages.KoreanLanguage: "ko-KR",
adsk.core.UserLanguages.PolishLanguage: "pl-PL",
adsk.core.UserLanguages.PortugueseBrazilianLanguage: "pt-BR",
adsk.core.UserLanguages.RussianLanguage: "ru-RU",
adsk.core.UserLanguages.SpanishLanguage: "es-ES"
}[app.preferences.generalPreferences.userLanguage]
# Get loc string by language
def getLocStrings():
currentDir = os.path.dirname(os.path.realpath(__file__))
return gettext.translation('resource', currentDir, [getUserLanguage(), "en-US"]).gettext
def commandDefinitionById(id):
app = adsk.core.Application.get()
ui = app.userInterface
if not id:
ui.messageBox(_('commandDefinition id is not specified'))
return None
commandDefinitions_ = ui.commandDefinitions
commandDefinition_ = commandDefinitions_.itemById(id)
return commandDefinition_
def commandControlByIdForQAT(id):
app = adsk.core.Application.get()
ui = app.userInterface
if not id:
ui.messageBox(_('commandControl id is not specified'))
return None
toolbars_ = ui.toolbars
toolbarQAT_ = toolbars_.itemById('QAT')
toolbarControls_ = toolbarQAT_.controls
toolbarControl_ = toolbarControls_.itemById(id)
return toolbarControl_
def commandControlByIdForPanel(id):
app = adsk.core.Application.get()
ui = app.userInterface
if not id:
ui.messageBox(_('commandControl id is not specified'))
return None
workspaces_ = ui.workspaces
modelingWorkspace_ = workspaces_.itemById('FusionSolidEnvironment')
toolbarPanels_ = modelingWorkspace_.toolbarPanels
toolbarPanel_ = toolbarPanels_.itemById(panelId)
toolbarControls_ = toolbarPanel_.controls
toolbarControl_ = toolbarControls_.itemById(id)
return toolbarControl_
def destroyObject(uiObj, tobeDeleteObj):
if uiObj and tobeDeleteObj:
if tobeDeleteObj.isValid:
tobeDeleteObj.deleteMe()
else:
uiObj.messageBox(_('tobeDeleteObj is not a valid object'))
def run(context):
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
global _
_ = getLocStrings()
commandName = _('Demo')
commandDescription = _('Demo Command')
commandResources = './resources'
iconResources = './resources'
class InputChangedHandler(adsk.core.InputChangedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
command = args.firingEvent.sender
cmdInput = args.input
if cmdInput.id != distanceInputId:
ui.messageBox(_('Input: {} changed event triggered').format(command.parentCommandDefinition.id))
if cmdInput.id == selectionInputId:
inputs = cmdInput.commandInputs
distanceInput = inputs.itemById(distanceInputId)
if cmdInput.selectionCount > 0:
sel = cmdInput.selection(0)
selPt = sel.point
ent = sel.entity
plane = ent.geometry
distanceInput.setManipulator(selPt, plane.normal)
distanceInput.expression = "10mm * 2"
distanceInput.isEnabled = True
distanceInput.isVisible = True
else:
distanceInput.isEnabled = False
distanceInput.isVisible = False
except:
if ui:
ui.messageBox(_('Input changed event failed: {}').format(traceback.format_exc()))
class CommandExecuteHandler(adsk.core.CommandEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
command = args.firingEvent.sender
ui.messageBox(_('command: {} executed successfully').format(command.parentCommandDefinition.id))
except:
if ui:
ui.messageBox(_('command executed failed: {}').format(traceback.format_exc()))
class CommandCreatedEventHandlerPanel(adsk.core.CommandCreatedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
cmd = args.command
cmd.helpFile = 'help.html'
onExecute = CommandExecuteHandler()
cmd.execute.add(onExecute)
onInputChanged = InputChangedHandler()
cmd.inputChanged.add(onInputChanged)
# keep the handler referenced beyond this function
handlers.append(onExecute)
handlers.append(onInputChanged)
commandInputs_ = cmd.commandInputs
commandInputs_.addValueInput('valueInput_', _('Value'), 'cm', adsk.core.ValueInput.createByString('0.0 cm'))
commandInputs_.addBoolValueInput('boolvalueInput_', _('Bool'), True)
commandInputs_.addStringValueInput('stringValueInput_', _('String Value'), _('Default value'))
selInput = commandInputs_.addSelectionInput(selectionInputId, _('Selection'), _('Select one'))
selInput.addSelectionFilter('PlanarFaces')
selInput.addSelectionFilter('ConstructionPlanes')
dropDownCommandInput_ = commandInputs_.addDropDownCommandInput('dropdownCommandInput', _('Drop Down'), adsk.core.DropDownStyles.LabeledIconDropDownStyle)
dropDownItems_ = dropDownCommandInput_.listItems
dropDownItems_.add(_('ListItem 1'), True)
dropDownItems_.add(_('ListItem 2'), False)
dropDownItems_.add(_('ListItem 3'), False)
dropDownCommandInput2_ = commandInputs_.addDropDownCommandInput('dropDownCommandInput2', _('Drop Down2'), adsk.core.DropDownStyles.CheckBoxDropDownStyle)
dropDownCommandInputListItems_ = dropDownCommandInput2_.listItems
dropDownCommandInputListItems_.add(_('ListItem 1'), True)
dropDownCommandInputListItems_.add(_('ListItem 2'), True)
dropDownCommandInputListItems_.add(_('ListItem 3'), False)
commandInputs_.addFloatSliderCommandInput('floatSliderCommandInput', _('Slider'), 'cm', 0.0, 10.0, True)
buttonRowCommandInput_ = commandInputs_.addButtonRowCommandInput('buttonRowCommandInput', _('Button Row'), False)
buttonRowCommandInputListItems_ = buttonRowCommandInput_.listItems
buttonRowCommandInputListItems_.add(_('ListItem 1'), False, iconResources)
buttonRowCommandInputListItems_.add(_('ListItem 2'), True, iconResources)
buttonRowCommandInputListItems_.add(_('ListItem 3'), False, iconResources)
distanceInput = commandInputs_.addDistanceValueCommandInput(distanceInputId, _('Distance'), adsk.core.ValueInput.createByReal(0.0))
distanceInput.isEnabled = False
distanceInput.isVisible = False
distanceInput.minimumValue = 1.0
distanceInput.maximumValue = 10.0
directionInput = commandInputs_.addDirectionCommandInput('directionInput', _('Direction'))
directionInput.setManipulator(adsk.core.Point3D.create(0,0,0), adsk.core.Vector3D.create(1,0,0))
directionInput2 = commandInputs_.addDirectionCommandInput('directionInput2', _('Direction2'), iconResources)
directionInput2.setManipulator(adsk.core.Point3D.create(0,0,0), adsk.core.Vector3D.create(0,1,0))
ui.messageBox(_('Panel command created successfully'))
except:
if ui:
ui.messageBox(_('Panel command created failed: {}').format(traceback.format_exc()))
class CommandCreatedEventHandlerQAT(adsk.core.CommandCreatedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
command = args.command
onExecute = CommandExecuteHandler()
command.execute.add(onExecute)
# keep the handler referenced beyond this function
handlers.append(onExecute)
ui.messageBox(_('QAT command created successfully'))
except:
ui.messageBox(_('QAT command created failed: {}').format(traceback.format_exc()))
commandDefinitions_ = ui.commandDefinitions
# add a button command on Quick Access Toolbar
toolbars_ = ui.toolbars
toolbarQAT_ = toolbars_.itemById('QAT')
toolbarControlsQAT_ = toolbarQAT_.controls
btnCmdToolbarCtlQAT_ = toolbarControlsQAT_.itemById(btnCmdIdOnQAT)
if not btnCmdToolbarCtlQAT_:
btnCmdDefinitionQAT_ = commandDefinitions_.itemById(btnCmdIdOnQAT)
if not btnCmdDefinitionQAT_:
btnCmdDefinitionQAT_ = commandDefinitions_.addButtonDefinition(btnCmdIdOnQAT, commandName, commandDescription, commandResources)
onButtonCommandCreated = CommandCreatedEventHandlerQAT()
btnCmdDefinitionQAT_.commandCreated.add(onButtonCommandCreated)
# keep the handler referenced beyond this function
handlers.append(onButtonCommandCreated)
btnCmdToolbarCtlQAT_ = toolbarControlsQAT_.addCommand(btnCmdDefinitionQAT_)
btnCmdToolbarCtlQAT_.isVisible = True
ui.messageBox(_('A demo button command is successfully added to the Quick Access Toolbar'))
# add a list command on Quick Access Toolbar
listCmdToolbarCtlQAT_ = toolbarControlsQAT_.itemById(listCmdIdOnQAT)
if not listCmdToolbarCtlQAT_:
listCmdDefinitionQAT_ = commandDefinitions_.itemById(listCmdIdOnQAT)
if not listCmdDefinitionQAT_:
listCmdDefinitionQAT_ = commandDefinitions_.addListDefinition(listCmdIdOnQAT, commandName, adsk.core.ListControlDisplayTypes.CheckBoxListType, commandResources)
listItems_ = adsk.core.ListControlDefinition.cast(listCmdDefinitionQAT_.controlDefinition).listItems
listItems_.add('Demo item 1', True)
listItems_.add('Demo item 2', False)
listItems_.add('Demo item 3', False)
onListCommandCreated = CommandCreatedEventHandlerQAT()
listCmdDefinitionQAT_.commandCreated.add(onListCommandCreated)
# keep the handler referenced beyond this function
handlers.append(onListCommandCreated)
listCmdToolbarCtlQAT_ = toolbarControlsQAT_.addCommand(listCmdDefinitionQAT_)
listCmdToolbarCtlQAT_.isVisible = True
ui.messageBox(_('A demo list command is successfully added to the Quick Access Toolbar'))
# add a command on create panel in modeling workspace
workspaces_ = ui.workspaces
modelingWorkspace_ = workspaces_.itemById('FusionSolidEnvironment')
toolbarPanels_ = modelingWorkspace_.toolbarPanels
toolbarPanel_ = toolbarPanels_.itemById(panelId) # add the new command under the CREATE panel
toolbarControlsPanel_ = toolbarPanel_.controls
toolbarControlPanel_ = toolbarControlsPanel_.itemById(commandIdOnPanel)
if not toolbarControlPanel_:
commandDefinitionPanel_ = commandDefinitions_.itemById(commandIdOnPanel)
if not commandDefinitionPanel_:
commandDefinitionPanel_ = commandDefinitions_.addButtonDefinition(commandIdOnPanel, commandName, commandDescription, commandResources)
onCommandCreated = CommandCreatedEventHandlerPanel()
commandDefinitionPanel_.commandCreated.add(onCommandCreated)
# keep the handler referenced beyond this function
handlers.append(onCommandCreated)
toolbarControlPanel_ = toolbarControlsPanel_.addCommand(commandDefinitionPanel_)
toolbarControlPanel_.isVisible = True
ui.messageBox(_('A demo command is successfully added to the create panel in modeling workspace'))
except:
if ui:
ui.messageBox(_('AddIn Start Failed: {}').format(traceback.format_exc()))
def stop(context):
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
objArrayQAT = []
objArrayPanel = []
btnCmdToolbarCtlQAT_ = commandControlByIdForQAT(btnCmdIdOnQAT)
if btnCmdToolbarCtlQAT_:
objArrayQAT.append(btnCmdToolbarCtlQAT_)
btnCmdDefinitionQAT_ = commandDefinitionById(btnCmdIdOnQAT)
if btnCmdDefinitionQAT_:
objArrayQAT.append(btnCmdDefinitionQAT_)
listCmdToolbarCtlQAT_ = commandControlByIdForQAT(listCmdIdOnQAT)
if listCmdToolbarCtlQAT_:
objArrayQAT.append(listCmdToolbarCtlQAT_)
listCmdDefinitionQAT_ = commandDefinitionById(listCmdIdOnQAT)
if listCmdDefinitionQAT_:
objArrayQAT.append(listCmdDefinitionQAT_)
commandControlPanel_ = commandControlByIdForPanel(commandIdOnPanel)
if commandControlPanel_:
objArrayPanel.append(commandControlPanel_)
commandDefinitionPanel_ = commandDefinitionById(commandIdOnPanel)
if commandDefinitionPanel_:
objArrayPanel.append(commandDefinitionPanel_)
for obj in objArrayQAT:
destroyObject(ui, obj)
for obj in objArrayPanel:
destroyObject(ui, obj)
except:
if ui:
ui.messageBox(_('AddIn Stop Failed: {}').format(traceback.format_exc()))

View File

@ -0,0 +1,136 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2015-08-03 15:59+China Standard Time\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
#:
msgid "commandDefinition id is not specified"
msgstr "commandDefinition id is not specified"
#:
msgid "commandControl id is not specified"
msgstr "commandControl id is not specified"
#:
msgid "tobeDeleteObj is not a valid object"
msgstr "tobeDeleteObj is not a valid object"
#:
msgid "Demo"
msgstr "Demo"
#:
msgid "Demo Command"
msgstr "Demo Command"
#:
msgid "Input: {} changed event triggered"
msgstr "Input: {} changed event triggered"
#:
msgid "Input changed event failed: {}"
msgstr "Input changed event failed: {}"
#:
msgid "command: {} executed successfully"
msgstr "command: {} executed successfully"
#:
msgid "command executed failed: {}"
msgstr "command executed failed: {}"
#:
msgid "Value"
msgstr "Value"
#:
msgid "Checked"
msgstr "Checked"
#:
msgid "Default value"
msgstr "Default value"
#:
msgid "String Value"
msgstr "String Value"
#:
msgid "Select one"
msgstr "Select one"
#:
msgid "Selection"
msgstr "Selection"
#:
msgid "Drop Down"
msgstr "Drop Down"
#:
msgid "Drop Down2"
msgstr "Drop Down2"
#:
msgid "ListItem 1"
msgstr "ListItem 1"
#:
msgid "ListItem 2"
msgstr "ListItem 2"
#:
msgid "ListItem 3"
msgstr "ListItem 3"
#:
msgid "Slider"
msgstr "Slider"
#:
msgid "Button Row"
msgstr "Button Row"
#:
msgid "Panel command created successfully"
msgstr "Panel command created successfully"
#:
msgid "Panel command created failed: {}"
msgstr "Panel command created failed: {}"
#:
msgid "QAT command created successfully"
msgstr "QAT command created successfully"
#:
msgid "QAT command created failed: {}"
msgstr "QAT command created failed: {}"
#:
msgid "A demo command button is successfully added to the Quick Access Toolbar"
msgstr "A demo command button is successfully added to the Quick Access Toolbar"
#:
msgid "A demo command is successfully added to the create panel in modeling workspace"
msgstr "A demo command is successfully added to the create panel in modeling workspace"
#:
msgid "AddIn Start Failed: {}"
msgstr "AddIn Start Failed: {}"
#:
msgid "AddIn Stop Failed: {}"
msgstr "AddIn Stop Failed: {}"

View File

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
This is help file of this addin.
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,136 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2015-08-04 12:47+China Standard Time\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
#:
msgid "commandDefinition id is not specified"
msgstr "没有指定commandDefinition id"
#:
msgid "commandControl id is not specified"
msgstr "没有指定commandControl id"
#:
msgid "tobeDeleteObj is not a valid object"
msgstr "tobeDeleteObj不是一个有效的对象"
#:
msgid "Demo"
msgstr "演示"
#:
msgid "Demo Command"
msgstr "演示命令"
#:
msgid "Input: {} changed event triggered"
msgstr "触发事件Input: {} changed"
#:
msgid "Input changed event failed: {}"
msgstr "输入变化事件失败: {}"
#:
msgid "command: {} executed successfully"
msgstr "命令: {} 执行成功"
#:
msgid "命令执行失败: {}"
msgstr "命令执行失败: {}"
#:
msgid "Value"
msgstr "值"
#:
msgid "Checked"
msgstr "选中"
#:
msgid "Default value"
msgstr "默认值"
#:
msgid "String Value"
msgstr "字符串"
#:
msgid "Select one"
msgstr "选一个"
#:
msgid "Selection"
msgstr "选择"
#:
msgid "Drop Down"
msgstr "下拉框"
#:
msgid "Drop Down2"
msgstr "下拉框2"
#:
msgid "ListItem 1"
msgstr "列表项 1"
#:
msgid "ListItem 2"
msgstr "列表项 2"
#:
msgid "ListItem 3"
msgstr "列表项 3"
#:
msgid "Slider"
msgstr "滚动条"
#:
msgid "Button Row"
msgstr "按钮行"
#:
msgid "Panel command created successfully"
msgstr "面板命令创建成功"
#:
msgid "Panel command created failed: {}"
msgstr "面板命令创建失败: {}"
#:
msgid "QAT command created successfully"
msgstr "QAT命令创建成功"
#:
msgid "QAT command created failed: {}"
msgstr "QAT命令创建失败: {}"
#:
msgid "A demo command button is successfully added to the Quick Access Toolbar"
msgstr "一个演示命令被成功的添加到QAT"
#:
msgid "A demo command is successfully added to the create panel in modeling workspace"
msgstr "一个演示命令被成功的添加到创建面板"
#:
msgid "AddIn Start Failed: {}"
msgstr "附加模块启动失败: {}"
#:
msgid "AddIn Stop Failed: {}"
msgstr "附加模块启动成功: {}"

View File

@ -0,0 +1,17 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Attach",
"type": "python",
"request": "attach",
"pathMappings": [ {
"localRoot": "${workspaceRoot}",
"remoteRoot": "${workspaceRoot}"}],
"osx": {"filePath":"${file}"},
"windows": {"filePath":"${file}"},
"port": 9000,
"host": "localhost"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 965 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1,13 @@
{
"autodeskProduct": "Fusion360",
"type": "addin",
"id": "6b509eec-34ca-4044-875d-cfb30563b658",
"author": "",
"description": {
"": "Creates a spur gear component."
},
"version": "",
"runOnStartup": false,
"supportedOS": "windows|mac",
"editEnabled": true
}

View File

@ -0,0 +1,772 @@
#Author-Brian Ekins
#Description-Creates a spur gear component.
# AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. AUTODESK SPECIFICALLY
# DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
# AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
# UNINTERRUPTED OR ERROR FREE.
import adsk.core, adsk.fusion, adsk.cam, traceback
import math
# Globals
_app = adsk.core.Application.cast(None)
_ui = adsk.core.UserInterface.cast(None)
_units = ''
# Command inputs
_imgInputEnglish = adsk.core.ImageCommandInput.cast(None)
_imgInputMetric = adsk.core.ImageCommandInput.cast(None)
_standard = adsk.core.DropDownCommandInput.cast(None)
_pressureAngle = adsk.core.DropDownCommandInput.cast(None)
_pressureAngleCustom = adsk.core.ValueCommandInput.cast(None)
_backlash = adsk.core.ValueCommandInput.cast(None)
_diaPitch = adsk.core.ValueCommandInput.cast(None)
_module = adsk.core.ValueCommandInput.cast(None)
_numTeeth = adsk.core.StringValueCommandInput.cast(None)
_rootFilletRad = adsk.core.ValueCommandInput.cast(None)
_thickness = adsk.core.ValueCommandInput.cast(None)
_holeDiam = adsk.core.ValueCommandInput.cast(None)
_pitchDiam = adsk.core.TextBoxCommandInput.cast(None)
_errMessage = adsk.core.TextBoxCommandInput.cast(None)
_handlers = []
def run(context):
try:
global _app, _ui
_app = adsk.core.Application.get()
_ui = _app.userInterface
# Create a command definition and add a button to the CREATE panel.
cmdDef = _ui.commandDefinitions.addButtonDefinition('adskSpurGearPythonAddIn', 'Spur Gear', 'Creates a spur gear component', 'Resources/SpurGear')
createPanel = _ui.allToolbarPanels.itemById('SolidCreatePanel')
gearButton = createPanel.controls.addCommand(cmdDef)
# Connect to the command created event.
onCommandCreated = GearCommandCreatedHandler()
cmdDef.commandCreated.add(onCommandCreated)
_handlers.append(onCommandCreated)
if context['IsApplicationStartup'] == False:
_ui.messageBox('The "Spur Gear" command has been added\nto the CREATE panel of the MODEL workspace.')
except:
if _ui:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
def stop(context):
try:
createPanel = _ui.allToolbarPanels.itemById('SolidCreatePanel')
gearButton = createPanel.controls.itemById('adskSpurGearPythonAddIn')
if gearButton:
gearButton.deleteMe()
cmdDef = _ui.commandDefinitions.itemById('adskSpurGearPythonAddIn')
if cmdDef:
cmdDef.deleteMe()
except:
if _ui:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
# Verfies that a value command input has a valid expression and returns the
# value if it does. Otherwise it returns False. This works around a
# problem where when you get the value from a ValueCommandInput it causes the
# current expression to be evaluated and updates the display. Some new functionality
# is being added in the future to the ValueCommandInput object that will make
# this easier and should make this function obsolete.
def getCommandInputValue(commandInput, unitType):
try:
valCommandInput = adsk.core.ValueCommandInput.cast(commandInput)
if not valCommandInput:
return (False, 0)
# Verify that the expression is valid.
des = adsk.fusion.Design.cast(_app.activeProduct)
unitsMgr = des.unitsManager
if unitsMgr.isValidExpression(valCommandInput.expression, unitType):
value = unitsMgr.evaluateExpression(valCommandInput.expression, unitType)
return (True, value)
else:
return (False, 0)
except:
if _ui:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
# Event handler for the commandCreated event.
class GearCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
eventArgs = adsk.core.CommandCreatedEventArgs.cast(args)
# Verify that a Fusion design is active.
des = adsk.fusion.Design.cast(_app.activeProduct)
if not des:
_ui.messageBox('A Fusion design must be active when invoking this command.')
return()
defaultUnits = des.unitsManager.defaultLengthUnits
# Determine whether to use inches or millimeters as the intial default.
global _units
if defaultUnits == 'in' or defaultUnits == 'ft':
_units = 'in'
else:
_units = 'mm'
# Define the default values and get the previous values from the attributes.
if _units == 'in':
standard = 'English'
else:
standard = 'Metric'
standardAttrib = des.attributes.itemByName('SpurGear', 'standard')
if standardAttrib:
standard = standardAttrib.value
if standard == 'English':
_units = 'in'
else:
_units = 'mm'
pressureAngle = '20 deg'
pressureAngleAttrib = des.attributes.itemByName('SpurGear', 'pressureAngle')
if pressureAngleAttrib:
pressureAngle = pressureAngleAttrib.value
pressureAngleCustom = 20 * (math.pi/180.0)
pressureAngleCustomAttrib = des.attributes.itemByName('SpurGear', 'pressureAngleCustom')
if pressureAngleCustomAttrib:
pressureAngleCustom = float(pressureAngleCustomAttrib.value)
diaPitch = '2'
diaPitchAttrib = des.attributes.itemByName('SpurGear', 'diaPitch')
if diaPitchAttrib:
diaPitch = diaPitchAttrib.value
metricModule = 25.4 / float(diaPitch)
backlash = '0'
backlashAttrib = des.attributes.itemByName('SpurGear', 'backlash')
if backlashAttrib:
backlash = backlashAttrib.value
numTeeth = '24'
numTeethAttrib = des.attributes.itemByName('SpurGear', 'numTeeth')
if numTeethAttrib:
numTeeth = numTeethAttrib.value
rootFilletRad = str(.0625 * 2.54)
rootFilletRadAttrib = des.attributes.itemByName('SpurGear', 'rootFilletRad')
if rootFilletRadAttrib:
rootFilletRad = rootFilletRadAttrib.value
thickness = str(0.5 * 2.54)
thicknessAttrib = des.attributes.itemByName('SpurGear', 'thickness')
if thicknessAttrib:
thickness = thicknessAttrib.value
holeDiam = str(0.5 * 2.54)
holeDiamAttrib = des.attributes.itemByName('SpurGear', 'holeDiam')
if holeDiamAttrib:
holeDiam = holeDiamAttrib.value
cmd = eventArgs.command
cmd.isExecutedWhenPreEmpted = False
inputs = cmd.commandInputs
global _standard, _pressureAngle, _pressureAngleCustom, _diaPitch, _pitch, _module, _numTeeth, _rootFilletRad, _thickness, _holeDiam, _pitchDiam, _backlash, _imgInputEnglish, _imgInputMetric, _errMessage
# Define the command dialog.
_imgInputEnglish = inputs.addImageCommandInput('gearImageEnglish', '', 'Resources/GearEnglish.png')
_imgInputEnglish.isFullWidth = True
_imgInputMetric = inputs.addImageCommandInput('gearImageMetric', '', 'Resources/GearMetric.png')
_imgInputMetric.isFullWidth = True
_standard = inputs.addDropDownCommandInput('standard', 'Standard', adsk.core.DropDownStyles.TextListDropDownStyle)
if standard == "English":
_standard.listItems.add('English', True)
_standard.listItems.add('Metric', False)
_imgInputMetric.isVisible = False
else:
_standard.listItems.add('English', False)
_standard.listItems.add('Metric', True)
_imgInputEnglish.isVisible = False
_pressureAngle = inputs.addDropDownCommandInput('pressureAngle', 'Pressure Angle', adsk.core.DropDownStyles.TextListDropDownStyle)
if pressureAngle == '14.5 deg':
_pressureAngle.listItems.add('14.5 deg', True)
else:
_pressureAngle.listItems.add('14.5 deg', False)
if pressureAngle == '20 deg':
_pressureAngle.listItems.add('20 deg', True)
else:
_pressureAngle.listItems.add('20 deg', False)
if pressureAngle == '25 deg':
_pressureAngle.listItems.add('25 deg', True)
else:
_pressureAngle.listItems.add('25 deg', False)
if pressureAngle == 'Custom':
_pressureAngle.listItems.add('Custom', True)
else:
_pressureAngle.listItems.add('Custom', False)
_pressureAngleCustom = inputs.addValueInput('pressureAngleCustom', 'Custom Angle', 'deg', adsk.core.ValueInput.createByReal(pressureAngleCustom))
if pressureAngle != 'Custom':
_pressureAngleCustom.isVisible = False
_diaPitch = inputs.addValueInput('diaPitch', 'Diametral Pitch', '', adsk.core.ValueInput.createByString(diaPitch))
_module = inputs.addValueInput('module', 'Module', '', adsk.core.ValueInput.createByReal(metricModule))
if standard == 'English':
_module.isVisible = False
elif standard == 'Metric':
_diaPitch.isVisible = False
_numTeeth = inputs.addStringValueInput('numTeeth', 'Number of Teeth', numTeeth)
_backlash = inputs.addValueInput('backlash', 'Backlash', _units, adsk.core.ValueInput.createByReal(float(backlash)))
_rootFilletRad = inputs.addValueInput('rootFilletRad', 'Root Fillet Radius', _units, adsk.core.ValueInput.createByReal(float(rootFilletRad)))
_thickness = inputs.addValueInput('thickness', 'Gear Thickness', _units, adsk.core.ValueInput.createByReal(float(thickness)))
_holeDiam = inputs.addValueInput('holeDiam', 'Hole Diameter', _units, adsk.core.ValueInput.createByReal(float(holeDiam)))
_pitchDiam = inputs.addTextBoxCommandInput('pitchDiam', 'Pitch Diameter', '', 1, True)
_errMessage = inputs.addTextBoxCommandInput('errMessage', '', '', 2, True)
_errMessage.isFullWidth = True
# Connect to the command related events.
onExecute = GearCommandExecuteHandler()
cmd.execute.add(onExecute)
_handlers.append(onExecute)
onInputChanged = GearCommandInputChangedHandler()
cmd.inputChanged.add(onInputChanged)
_handlers.append(onInputChanged)
onValidateInputs = GearCommandValidateInputsHandler()
cmd.validateInputs.add(onValidateInputs)
_handlers.append(onValidateInputs)
except:
if _ui:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
# Event handler for the execute event.
class GearCommandExecuteHandler(adsk.core.CommandEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
eventArgs = adsk.core.CommandEventArgs.cast(args)
if _standard.selectedItem.name == 'English':
diaPitch = _diaPitch.value
elif _standard.selectedItem.name == 'Metric':
diaPitch = 25.4 / _module.value
# Save the current values as attributes.
des = adsk.fusion.Design.cast(_app.activeProduct)
attribs = des.attributes
attribs.add('SpurGear', 'standard', _standard.selectedItem.name)
attribs.add('SpurGear', 'pressureAngle', _pressureAngle.selectedItem.name)
attribs.add('SpurGear', 'pressureAngleCustom', str(_pressureAngleCustom.value))
attribs.add('SpurGear', 'diaPitch', str(diaPitch))
attribs.add('SpurGear', 'numTeeth', str(_numTeeth.value))
attribs.add('SpurGear', 'rootFilletRad', str(_rootFilletRad.value))
attribs.add('SpurGear', 'thickness', str(_thickness.value))
attribs.add('SpurGear', 'holeDiam', str(_holeDiam.value))
attribs.add('SpurGear', 'backlash', str(_backlash.value))
# Get the current values.
if _pressureAngle.selectedItem.name == 'Custom':
pressureAngle = _pressureAngleCustom.value
else:
if _pressureAngle.selectedItem.name == '14.5 deg':
pressureAngle = 14.5 * (math.pi/180)
elif _pressureAngle.selectedItem.name == '20 deg':
pressureAngle = 20.0 * (math.pi/180)
elif _pressureAngle.selectedItem.name == '25 deg':
pressureAngle = 25.0 * (math.pi/180)
numTeeth = int(_numTeeth.value)
rootFilletRad = _rootFilletRad.value
thickness = _thickness.value
holeDiam = _holeDiam.value
backlash = _backlash.value
# Create the gear.
gearComp = drawGear(des, diaPitch, numTeeth, thickness, rootFilletRad, pressureAngle, backlash, holeDiam)
if gearComp:
if _standard.selectedItem.name == 'English':
desc = 'Spur Gear; Diametrial Pitch: ' + str(diaPitch) + '; '
elif _standard.selectedItem.name == 'Metric':
desc = 'Spur Gear; Module: ' + str(25.4 / diaPitch) + '; '
desc += 'Num Teeth: ' + str(numTeeth) + '; '
desc += 'Pressure Angle: ' + str(pressureAngle * (180/math.pi)) + '; '
desc += 'Backlash: ' + des.unitsManager.formatInternalValue(backlash, _units, True)
gearComp.description = desc
except:
if _ui:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
# Event handler for the inputChanged event.
class GearCommandInputChangedHandler(adsk.core.InputChangedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
eventArgs = adsk.core.InputChangedEventArgs.cast(args)
changedInput = eventArgs.input
global _units
if changedInput.id == 'standard':
if _standard.selectedItem.name == 'English':
_imgInputMetric.isVisible = False
_imgInputEnglish.isVisible = True
_diaPitch.isVisible = True
_module.isVisible = False
_diaPitch.value = 25.4 / _module.value
_units = 'in'
elif _standard.selectedItem.name == 'Metric':
_imgInputMetric.isVisible = True
_imgInputEnglish.isVisible = False
_diaPitch.isVisible = False
_module.isVisible = True
_module.value = 25.4 / _diaPitch.value
_units = 'mm'
# Set each one to it's current value because otherwised if the user
# has edited it, the value won't update in the dialog because
# apparently it remembers the units when the value was edited.
# Setting the value using the API resets this.
_backlash.value = _backlash.value
_backlash.unitType = _units
_rootFilletRad.value = _rootFilletRad.value
_rootFilletRad.unitType = _units
_thickness.value = _thickness.value
_thickness.unitType = _units
_holeDiam.value = _holeDiam.value
_holeDiam.unitType = _units
# Update the pitch diameter value.
diaPitch = None
if _standard.selectedItem.name == 'English':
result = getCommandInputValue(_diaPitch, '')
if result[0]:
diaPitch = result[1]
elif _standard.selectedItem.name == 'Metric':
result = getCommandInputValue(_module, '')
if result[0]:
diaPitch = 25.4 / result[1]
if not diaPitch == None:
if _numTeeth.value.isdigit():
numTeeth = int(_numTeeth.value)
pitchDia = numTeeth/diaPitch
# The pitch dia has been calculated in inches, but this expects cm as the input units.
des = adsk.fusion.Design.cast(_app.activeProduct)
pitchDiaText = des.unitsManager.formatInternalValue(pitchDia * 2.54, _units, True)
_pitchDiam.text = pitchDiaText
else:
_pitchDiam.text = ''
else:
_pitchDiam.text = ''
if changedInput.id == 'pressureAngle':
if _pressureAngle.selectedItem.name == 'Custom':
_pressureAngleCustom.isVisible = True
else:
_pressureAngleCustom.isVisible = False
except:
if _ui:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
# Event handler for the validateInputs event.
class GearCommandValidateInputsHandler(adsk.core.ValidateInputsEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
eventArgs = adsk.core.ValidateInputsEventArgs.cast(args)
_errMessage.text = ''
# Verify that at lesat 4 teath are specified.
if not _numTeeth.value.isdigit():
_errMessage.text = 'The number of teeth must be a whole number.'
eventArgs.areInputsValid = False
return
else:
numTeeth = int(_numTeeth.value)
if numTeeth < 4:
_errMessage.text = 'The number of teeth must be 4 or more.'
eventArgs.areInputsValid = False
return
# Calculate some of the gear sizes to use in validation.
if _standard.selectedItem.name == 'English':
result = getCommandInputValue(_diaPitch, '')
if result[0] == False:
eventArgs.areInputsValid = False
return
else:
diaPitch = result[1]
elif _standard.selectedItem.name == 'Metric':
result = getCommandInputValue(_module, '')
if result[0] == False:
eventArgs.areInputsValid = False
return
else:
diaPitch = 25.4 / result[1]
diametralPitch = diaPitch / 2.54
pitchDia = numTeeth / diametralPitch
if (diametralPitch < (20 *(math.pi/180))-0.000001):
dedendum = 1.157 / diametralPitch
else:
circularPitch = math.pi / diametralPitch
if circularPitch >= 20:
dedendum = 1.25 / diametralPitch
else:
dedendum = (1.2 / diametralPitch) + (.002 * 2.54)
rootDia = pitchDia - (2 * dedendum)
if _pressureAngle.selectedItem.name == 'Custom':
pressureAngle = _pressureAngleCustom.value
else:
if _pressureAngle.selectedItem.name == '14.5 deg':
pressureAngle = 14.5 * (math.pi/180)
elif _pressureAngle.selectedItem.name == '20 deg':
pressureAngle = 20.0 * (math.pi/180)
elif _pressureAngle.selectedItem.name == '25 deg':
pressureAngle = 25.0 * (math.pi/180)
baseCircleDia = pitchDia * math.cos(pressureAngle)
baseCircleCircumference = 2 * math.pi * (baseCircleDia / 2)
des = adsk.fusion.Design.cast(_app.activeProduct)
result = getCommandInputValue(_holeDiam, _units)
if result[0] == False:
eventArgs.areInputsValid = False
return
else:
holeDiam = result[1]
if holeDiam >= (rootDia - 0.01):
_errMessage.text = 'The center hole diameter is too large. It must be less than ' + des.unitsManager.formatInternalValue(rootDia - 0.01, _units, True)
eventArgs.areInputsValid = False
return
toothThickness = baseCircleCircumference / (numTeeth * 2)
if _rootFilletRad.value > toothThickness * .4:
_errMessage.text = 'The root fillet radius is too large. It must be less than ' + des.unitsManager.formatInternalValue(toothThickness * .4, _units, True)
eventArgs.areInputsValid = False
return
except:
if _ui:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
# Calculate points along an involute curve.
def involutePoint(baseCircleRadius, distFromCenterToInvolutePoint):
try:
# Calculate the other side of the right-angle triangle defined by the base circle and the current distance radius.
# This is also the length of the involute chord as it comes off of the base circle.
triangleSide = math.sqrt(math.pow(distFromCenterToInvolutePoint,2) - math.pow(baseCircleRadius,2))
# Calculate the angle of the involute.
alpha = triangleSide / baseCircleRadius
# Calculate the angle where the current involute point is.
theta = alpha - math.acos(baseCircleRadius / distFromCenterToInvolutePoint)
# Calculate the coordinates of the involute point.
x = distFromCenterToInvolutePoint * math.cos(theta)
y = distFromCenterToInvolutePoint * math.sin(theta)
# Create a point to return.
return adsk.core.Point3D.create(x, y, 0)
except:
if _ui:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
# Builds a spur gear.
def drawGear(design, diametralPitch, numTeeth, thickness, rootFilletRad, pressureAngle, backlash, holeDiam):
try:
# The diametral pitch is specified in inches but everthing
# here expects all distances to be in centimeters, so convert
# for the gear creation.
diametralPitch = diametralPitch / 2.54
# Compute the various values for a gear.
pitchDia = numTeeth / diametralPitch
#addendum = 1.0 / diametralPitch
if (diametralPitch < (20 *(math.pi/180))-0.000001):
dedendum = 1.157 / diametralPitch
else:
circularPitch = math.pi / diametralPitch
if circularPitch >= 20:
dedendum = 1.25 / diametralPitch
else:
dedendum = (1.2 / diametralPitch) + (.002 * 2.54)
rootDia = pitchDia - (2 * dedendum)
baseCircleDia = pitchDia * math.cos(pressureAngle)
outsideDia = (numTeeth + 2) / diametralPitch
# Create a new component by creating an occurrence.
occs = design.rootComponent.occurrences
mat = adsk.core.Matrix3D.create()
newOcc = occs.addNewComponent(mat)
newComp = adsk.fusion.Component.cast(newOcc.component)
# Create a new sketch.
sketches = newComp.sketches
xyPlane = newComp.xYConstructionPlane
baseSketch = sketches.add(xyPlane)
# Draw a circle for the base.
baseSketch.sketchCurves.sketchCircles.addByCenterRadius(adsk.core.Point3D.create(0,0,0), rootDia/2.0)
# Draw a circle for the center hole, if the value is greater than 0.
prof = adsk.fusion.Profile.cast(None)
if holeDiam - (_app.pointTolerance * 2) > 0:
baseSketch.sketchCurves.sketchCircles.addByCenterRadius(adsk.core.Point3D.create(0,0,0), holeDiam/2.0)
# Find the profile that uses both circles.
for prof in baseSketch.profiles:
if prof.profileLoops.count == 2:
break
else:
# Use the single profile.
prof = baseSketch.profiles.item(0)
#### Extrude the circle to create the base of the gear.
# Create an extrusion input to be able to define the input needed for an extrusion
# while specifying the profile and that a new component is to be created
extrudes = newComp.features.extrudeFeatures
extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
# Define that the extent is a distance extent of 5 cm.
distance = adsk.core.ValueInput.createByReal(thickness)
extInput.setDistanceExtent(False, distance)
# Create the extrusion.
baseExtrude = extrudes.add(extInput)
# Create a second sketch for the tooth.
toothSketch = sketches.add(xyPlane)
# Calculate points along the involute curve.
involutePointCount = 15;
involuteIntersectionRadius = baseCircleDia / 2.0
involutePoints = []
involuteSize = (outsideDia - baseCircleDia) / 2.0
for i in range(0, involutePointCount):
involuteIntersectionRadius = (baseCircleDia / 2.0) + ((involuteSize / (involutePointCount - 1)) * i)
newPoint = involutePoint(baseCircleDia / 2.0, involuteIntersectionRadius)
involutePoints.append(newPoint)
# Get the point along the tooth that's at the pictch diameter and then
# calculate the angle to that point.
pitchInvolutePoint = involutePoint(baseCircleDia / 2.0, pitchDia / 2.0)
pitchPointAngle = math.atan(pitchInvolutePoint.y / pitchInvolutePoint.x)
# Determine the angle defined by the tooth thickness as measured at
# the pitch diameter circle.
toothThicknessAngle = (2 * math.pi) / (2 * numTeeth)
# Determine the angle needed for the specified backlash.
backlashAngle = (backlash / (pitchDia / 2.0)) * .25
# Determine the angle to rotate the curve.
rotateAngle = -((toothThicknessAngle/2) + pitchPointAngle - backlashAngle)
# Rotate the involute so the middle of the tooth lies on the x axis.
cosAngle = math.cos(rotateAngle)
sinAngle = math.sin(rotateAngle)
for i in range(0, involutePointCount):
newX = involutePoints[i].x * cosAngle - involutePoints[i].y * sinAngle
newY = involutePoints[i].x * sinAngle + involutePoints[i].y * cosAngle
involutePoints[i] = adsk.core.Point3D.create(newX, newY, 0)
# Create a new set of points with a negated y. This effectively mirrors the original
# points about the X axis.
involute2Points = []
for i in range(0, involutePointCount):
involute2Points.append(adsk.core.Point3D.create(involutePoints[i].x, -involutePoints[i].y, 0))
curve1Dist = []
curve1Angle = []
for i in range(0, involutePointCount):
curve1Dist.append(math.sqrt(involutePoints[i].x * involutePoints[i].x + involutePoints[i].y * involutePoints[i].y))
curve1Angle.append(math.atan(involutePoints[i].y / involutePoints[i].x))
curve2Dist = []
curve2Angle = []
for i in range(0, involutePointCount):
curve2Dist.append(math.sqrt(involute2Points[i].x * involute2Points[i].x + involute2Points[i].y * involute2Points[i].y))
curve2Angle.append(math.atan(involute2Points[i].y / involute2Points[i].x))
toothSketch.isComputeDeferred = True
# Create and load an object collection with the points.
pointSet = adsk.core.ObjectCollection.create()
for i in range(0, involutePointCount):
pointSet.add(involutePoints[i])
# Create the first spline.
spline1 = toothSketch.sketchCurves.sketchFittedSplines.add(pointSet)
# Add the involute points for the second spline to an ObjectCollection.
pointSet = adsk.core.ObjectCollection.create()
for i in range(0, involutePointCount):
pointSet.add(involute2Points[i])
# Create the second spline.
spline2 = toothSketch.sketchCurves.sketchFittedSplines.add(pointSet)
# Draw the arc for the top of the tooth.
midPoint = adsk.core.Point3D.create((outsideDia / 2), 0, 0)
toothSketch.sketchCurves.sketchArcs.addByThreePoints(spline1.endSketchPoint, midPoint, spline2.endSketchPoint)
# Check to see if involute goes down to the root or not. If not, then
# create lines to connect the involute to the root.
if( baseCircleDia < rootDia ):
toothSketch.sketchCurves.sketchLines.addByTwoPoints(spline2.startSketchPoint, spline1.startSketchPoint)
else:
rootPoint1 = adsk.core.Point3D.create((rootDia / 2 - 0.001) * math.cos(curve1Angle[0] ), (rootDia / 2) * math.sin(curve1Angle[0]), 0)
line1 = toothSketch.sketchCurves.sketchLines.addByTwoPoints(rootPoint1, spline1.startSketchPoint)
rootPoint2 = adsk.core.Point3D.create((rootDia / 2 - 0.001) * math.cos(curve2Angle[0]), (rootDia / 2) * math.sin(curve2Angle[0]), 0)
line2 = toothSketch.sketchCurves.sketchLines.addByTwoPoints(rootPoint2, spline2.startSketchPoint)
baseLine = toothSketch.sketchCurves.sketchLines.addByTwoPoints(line1.startSketchPoint, line2.startSketchPoint)
# Make the lines tangent to the spline so the root fillet will behave correctly.
line1.isFixed = True
line2.isFixed = True
toothSketch.geometricConstraints.addTangent(spline1, line1)
toothSketch.geometricConstraints.addTangent(spline2, line2)
toothSketch.isComputeDeferred = False
### Extrude the tooth.
# Get the profile defined by the tooth.
prof = toothSketch.profiles.item(0)
# Create an extrusion input to be able to define the input needed for an extrusion
# while specifying the profile and that a new component is to be created
extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.JoinFeatureOperation)
# Define that the extent is a distance extent of 5 cm.
distance = adsk.core.ValueInput.createByReal(thickness)
extInput.setDistanceExtent(False, distance)
# Create the extrusion.
toothExtrude = extrudes.add(extInput)
baseFillet = None
if rootFilletRad > 0:
### Find the edges between the base cylinder and the tooth.
# Get the outer cylindrical face from the base extrusion by checking the number
# of edges and if it's 2 get the other one.
cylFace = baseExtrude.sideFaces.item(0)
if cylFace.edges.count == 2:
cylFace = baseExtrude.sideFaces.item(1)
# Get the two linear edges, which are the connection between the cylinder and tooth.
edges = adsk.core.ObjectCollection.create()
for edge in cylFace.edges:
if isinstance(edge.geometry, adsk.core.Line3D):
edges.add(edge)
# Create a fillet input to be able to define the input needed for a fillet.
fillets = newComp.features.filletFeatures;
filletInput = fillets.createInput()
# Define that the extent is a distance extent of 5 cm.
radius = adsk.core.ValueInput.createByReal(rootFilletRad)
filletInput.addConstantRadiusEdgeSet(edges, radius, False)
# Create the extrusion.
baseFillet = fillets.add(filletInput)
# Create a pattern of the tooth extrude and the base fillet.
circularPatterns = newComp.features.circularPatternFeatures
entities = adsk.core.ObjectCollection.create()
entities.add(toothExtrude)
if baseFillet:
entities.add(baseFillet)
cylFace = baseExtrude.sideFaces.item(0)
patternInput = circularPatterns.createInput(entities, cylFace)
numTeethInput = adsk.core.ValueInput.createByString(str(numTeeth))
patternInput.quantity = numTeethInput
patternInput.patternComputeOption = adsk.fusion.PatternComputeOptions.IdenticalPatternCompute
pattern = circularPatterns.add(patternInput)
# Create an extra sketch that contains a circle of the diametral pitch.
diametralPitchSketch = sketches.add(xyPlane)
diametralPitchCircle = diametralPitchSketch.sketchCurves.sketchCircles.addByCenterRadius(adsk.core.Point3D.create(0,0,0), pitchDia/2.0)
diametralPitchCircle.isConstruction = True
diametralPitchCircle.isFixed = True
# Group everything used to create the gear in the timeline.
timelineGroups = design.timeline.timelineGroups
newOccIndex = newOcc.timelineObject.index
pitchSketchIndex = diametralPitchSketch.timelineObject.index
# ui.messageBox("Indices: " + str(newOccIndex) + ", " + str(pitchSketchIndex))
timelineGroup = timelineGroups.add(newOccIndex, pitchSketchIndex)
timelineGroup.name = 'Spur Gear'
# Add an attribute to the component with all of the input values. This might
# be used in the future to be able to edit the gear.
gearValues = {}
gearValues['diametralPitch'] = str(diametralPitch * 2.54)
gearValues['numTeeth'] = str(numTeeth)
gearValues['thickness'] = str(thickness)
gearValues['rootFilletRad'] = str(rootFilletRad)
gearValues['pressureAngle'] = str(pressureAngle)
gearValues['holeDiam'] = str(holeDiam)
gearValues['backlash'] = str(backlash)
attrib = newComp.attributes.add('SpurGear', 'Values',str(gearValues))
newComp.name = 'Spur Gear (' + str(numTeeth) + ' teeth)'
return newComp
except Exception as error:
_ui.messageBox("drawGear Failed : " + str(error))
return None

BIN
python/DLLs/_asyncio.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_asyncio_d.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_bz2.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_bz2_d.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_ctypes.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_ctypes_d.pyd Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
python/DLLs/_decimal.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_decimal_d.pyd Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
python/DLLs/_hashlib.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_hashlib_d.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_lzma.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_lzma_d.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_msi.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_msi_d.pyd Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
python/DLLs/_overlapped.pyd Normal file

Binary file not shown.

Binary file not shown.

BIN
python/DLLs/_queue.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_queue_d.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_socket.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_socket_d.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_sqlite3.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_sqlite3_d.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_ssl.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_ssl_d.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_testbuffer.pyd Normal file

Binary file not shown.

Binary file not shown.

BIN
python/DLLs/_testcapi.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_testcapi_d.pyd Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
python/DLLs/_tkinter.pyd Normal file

Binary file not shown.

BIN
python/DLLs/_tkinter_d.pyd Normal file

Binary file not shown.

Binary file not shown.

BIN
python/DLLs/libssl-1_1.dll Normal file

Binary file not shown.

BIN
python/DLLs/py.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
python/DLLs/pyc.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
python/DLLs/pyd.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
python/DLLs/pyexpat.pyd Normal file

Binary file not shown.

BIN
python/DLLs/pyexpat_d.pyd Normal file

Binary file not shown.

BIN
python/DLLs/python_lib.cat Normal file

Binary file not shown.

Binary file not shown.

BIN
python/DLLs/select.pyd Normal file

Binary file not shown.

BIN
python/DLLs/select_d.pyd Normal file

Binary file not shown.

BIN
python/DLLs/sqlite3.dll Normal file

Binary file not shown.

BIN
python/DLLs/sqlite3_d.dll Normal file

Binary file not shown.

BIN
python/DLLs/tcl86t.dll Normal file

Binary file not shown.

BIN
python/DLLs/tk86t.dll Normal file

Binary file not shown.

BIN
python/DLLs/unicodedata.pyd Normal file

Binary file not shown.

Binary file not shown.

BIN
python/DLLs/winsound.pyd Normal file

Binary file not shown.

BIN
python/DLLs/winsound_d.pyd Normal file

Binary file not shown.

View File

@ -0,0 +1,10 @@
{
"autodeskProduct":"Fusion360",
"type":"script",
"author":"Autodesk Inc.",
"description":{
"":"This is sample script."
},
"supportedOS":"windows|mac",
"editEnabled": true
}

15
python/Default/default.py Normal file
View File

@ -0,0 +1,15 @@
#Author-
#Description-
import adsk.core, adsk.fusion, adsk.cam, traceback
def run(context):
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
ui.messageBox('Hello script')
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

View File

@ -0,0 +1,17 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Attach",
"type": "python",
"request": "attach",
"pathMappings": [ {
"localRoot": "${workspaceRoot}",
"remoteRoot": "${workspaceRoot}"}],
"osx": {"filePath":"${file}"},
"windows": {"filePath":"${file}"},
"port": 9000,
"host": "localhost"
}
]
}

View File

@ -0,0 +1,13 @@
{
"autodeskProduct":"Fusion360",
"type":"addin",
"id":"319679C5-AF6D-4A46-862D-93414F1AE117",
"author":"Autodesk Inc.",
"description":{
"":"This is sample addin."
},
"version":"0.0.1",
"runOnStartup":false,
"supportedOS":"windows|mac",
"editEnabled": true
}

View File

@ -0,0 +1,26 @@
#Author-
#Description-
import adsk.core, adsk.fusion, adsk.cam, traceback
def run(context):
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
ui.messageBox('Hello addin')
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
ui.messageBox('Stop addin')
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

146
python/Lib/__future__.py Normal file
View File

@ -0,0 +1,146 @@
"""Record of phased-in incompatible language changes.
Each line is of the form:
FeatureName = "_Feature(" OptionalRelease "," MandatoryRelease ","
CompilerFlag ")"
where, normally, OptionalRelease < MandatoryRelease, and both are 5-tuples
of the same form as sys.version_info:
(PY_MAJOR_VERSION, # the 2 in 2.1.0a3; an int
PY_MINOR_VERSION, # the 1; an int
PY_MICRO_VERSION, # the 0; an int
PY_RELEASE_LEVEL, # "alpha", "beta", "candidate" or "final"; string
PY_RELEASE_SERIAL # the 3; an int
)
OptionalRelease records the first release in which
from __future__ import FeatureName
was accepted.
In the case of MandatoryReleases that have not yet occurred,
MandatoryRelease predicts the release in which the feature will become part
of the language.
Else MandatoryRelease records when the feature became part of the language;
in releases at or after that, modules no longer need
from __future__ import FeatureName
to use the feature in question, but may continue to use such imports.
MandatoryRelease may also be None, meaning that a planned feature got
dropped.
Instances of class _Feature have two corresponding methods,
.getOptionalRelease() and .getMandatoryRelease().
CompilerFlag is the (bitfield) flag that should be passed in the fourth
argument to the builtin function compile() to enable the feature in
dynamically compiled code. This flag is stored in the .compiler_flag
attribute on _Future instances. These values must match the appropriate
#defines of CO_xxx flags in Include/compile.h.
No feature line is ever to be deleted from this file.
"""
all_feature_names = [
"nested_scopes",
"generators",
"division",
"absolute_import",
"with_statement",
"print_function",
"unicode_literals",
"barry_as_FLUFL",
"generator_stop",
"annotations",
]
__all__ = ["all_feature_names"] + all_feature_names
# The CO_xxx symbols are defined here under the same names defined in
# code.h and used by compile.h, so that an editor search will find them here.
# However, they're not exported in __all__, because they don't really belong to
# this module.
CO_NESTED = 0x0010 # nested_scopes
CO_GENERATOR_ALLOWED = 0 # generators (obsolete, was 0x1000)
CO_FUTURE_DIVISION = 0x2000 # division
CO_FUTURE_ABSOLUTE_IMPORT = 0x4000 # perform absolute imports by default
CO_FUTURE_WITH_STATEMENT = 0x8000 # with statement
CO_FUTURE_PRINT_FUNCTION = 0x10000 # print function
CO_FUTURE_UNICODE_LITERALS = 0x20000 # unicode string literals
CO_FUTURE_BARRY_AS_BDFL = 0x40000
CO_FUTURE_GENERATOR_STOP = 0x80000 # StopIteration becomes RuntimeError in generators
CO_FUTURE_ANNOTATIONS = 0x100000 # annotations become strings at runtime
class _Feature:
def __init__(self, optionalRelease, mandatoryRelease, compiler_flag):
self.optional = optionalRelease
self.mandatory = mandatoryRelease
self.compiler_flag = compiler_flag
def getOptionalRelease(self):
"""Return first release in which this feature was recognized.
This is a 5-tuple, of the same form as sys.version_info.
"""
return self.optional
def getMandatoryRelease(self):
"""Return release in which this feature will become mandatory.
This is a 5-tuple, of the same form as sys.version_info, or, if
the feature was dropped, is None.
"""
return self.mandatory
def __repr__(self):
return "_Feature" + repr((self.optional,
self.mandatory,
self.compiler_flag))
nested_scopes = _Feature((2, 1, 0, "beta", 1),
(2, 2, 0, "alpha", 0),
CO_NESTED)
generators = _Feature((2, 2, 0, "alpha", 1),
(2, 3, 0, "final", 0),
CO_GENERATOR_ALLOWED)
division = _Feature((2, 2, 0, "alpha", 2),
(3, 0, 0, "alpha", 0),
CO_FUTURE_DIVISION)
absolute_import = _Feature((2, 5, 0, "alpha", 1),
(3, 0, 0, "alpha", 0),
CO_FUTURE_ABSOLUTE_IMPORT)
with_statement = _Feature((2, 5, 0, "alpha", 1),
(2, 6, 0, "alpha", 0),
CO_FUTURE_WITH_STATEMENT)
print_function = _Feature((2, 6, 0, "alpha", 2),
(3, 0, 0, "alpha", 0),
CO_FUTURE_PRINT_FUNCTION)
unicode_literals = _Feature((2, 6, 0, "alpha", 2),
(3, 0, 0, "alpha", 0),
CO_FUTURE_UNICODE_LITERALS)
barry_as_FLUFL = _Feature((3, 1, 0, "alpha", 2),
(3, 9, 0, "alpha", 0),
CO_FUTURE_BARRY_AS_BDFL)
generator_stop = _Feature((3, 5, 0, "beta", 1),
(3, 7, 0, "alpha", 0),
CO_FUTURE_GENERATOR_STOP)
annotations = _Feature((3, 7, 0, "beta", 1),
(4, 0, 0, "alpha", 0),
CO_FUTURE_ANNOTATIONS)

View File

@ -0,0 +1 @@
# This file exists as a helper for the test.test_frozen module.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More