-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathNoComponentDrag.py
More file actions
192 lines (160 loc) · 8.86 KB
/
NoComponentDrag.py
File metadata and controls
192 lines (160 loc) · 8.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#Author-Thomas Axelsson, ZXYNINE
#Description-Blocks Component Dragging in parametric mode
# This file is part of NoComponentDrag, a Fusion 360 add-in for blocking
# component drags.
#
# Copyright (c) 2020 Thomas Axelsson
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import adsk.core, adsk.fusion, adsk.cam, traceback
import math, os, operator, time
from collections import deque
NAME = 'NoComponentDrag'
FILE_DIR = os.path.dirname(os.path.realpath(__file__))
# Import relative path to avoid namespace pollution
from .thomasa88lib import utils, events, manifest, error
# Force modules to be fresh during development
import importlib
importlib.reload(thomasa88lib.utils)
importlib.reload(thomasa88lib.events)
importlib.reload(thomasa88lib.manifest)
importlib.reload(thomasa88lib.error)
ENABLE_CMD_ID = 'thomasa88_NoComponentDrag_Enable'
DIRECT_EDIT_DRAG_CMD_ID = 'FusionDragCompControlsCmd'
app_ = None
ui_ = None
error_catcher_ = thomasa88lib.error.ErrorCatcher()
events_manager_ = thomasa88lib.events.EventsManager(error_catcher_)
manifest_ = thomasa88lib.manifest.read()
select_panel_ = None
enable_cmd_def_ = None
parametric_environment_ = True
addin_updating_checkbox_ = False
fusion_drag_controls_cmd_def_ = None
def command_starting_handler(args: adsk.core.ApplicationCommandEventArgs):
# Should we block?
if parametric_environment_ and args.commandId == 'FusionDragComponentsCommand' and not get_direct_edit_drag_enabled():
args.isCanceled = True
def command_terminated_handler(args: adsk.core.ApplicationCommandEventArgs):
# Detect if user toggles Direct Edit or enters/leaves a Base Feature
# Undo/Redo triggers the ActivateEnvironmentCommand instead.
# PLM360OpenAttachmentCommand, CurrentlyOpenDocumentsCommand are workarounds for DocumentActivated with Drawings bug.
# https://forums.autodesk.com/t5/fusion-360-api-and-scripts/api-bug-application-documentactivated-event-do-not-raise/m-p/9020750
if (args.commandId in ('ActivateEnvironmentCommand', 'PLM360OpenAttachmentCommand', 'CurrentlyOpenDocumentsCommand') or
(args.terminationReason == adsk.core.CommandTerminationReason.CompletedTerminationReason and
args.commandId in ('Undo', 'Redo','ConvertToPMDesignCommand', 'ConvertToDMDesignCommand',
'BaseFeatureActivate', 'BaseFeatureStop', 'BaseFeatureCreationCommand'))):
check_environment()
# This handler is called three times per window switch and only two times when first
# starting and only once when trying to insert a derive.
def document_activated_handler(args: adsk.core.WorkspaceEventArgs):
check_environment()
def enable_cmd_created_handler(args: adsk.core.CommandCreatedEventArgs):
global addin_updating_checkbox_
# Check if we are updating the checkbox programmatically, to avoid infinite event recursion
if addin_updating_checkbox_:
return
checkbox_def: adsk.core.CheckBoxControlDefinition = args.command.parentCommandDefinition.controlDefinition
set_direct_edit_drag_enabled(checkbox_def.isChecked)
def set_direct_edit_drag_enabled(value):
'''Sets the Fusion's "Component Drag" checkbox to the given value'''
fusion_drag_controls_cmd_def_.controlDefinition.isChecked = value
def get_direct_edit_drag_enabled():
'''Gets the value of Fusion's "Component Drag" checkbox'''
return fusion_drag_controls_cmd_def_.controlDefinition.isChecked
def check_environment():
global enable_cmd_def_, parametric_environment_
is_parametric = is_parametric_mode()
if parametric_environment_ == is_parametric:
# Environment did not change
return
parametric_environment_ = is_parametric
# Hide/show our menu command to avoid showing to Component Drag menu items
# in direct edit mode (Our command + Fusion's command).
enable_cmd_def_.controlDefinition.isVisible = is_parametric
# We only need to update checkbox in parametric mode, as it will not be
# seen in direct edit mode.
if is_parametric and enable_cmd_def_.controlDefinition.isChecked != get_direct_edit_drag_enabled():
# Fusion crashes if we change isChecked from (one of?) the event handlers,
# so we put the update at the end of the event queue.
events_manager_.delay(update_checkbox)
def update_checkbox():
global addin_updating_checkbox_
# Only set the checkbox value (triggering a command creation), if the
# direct edit value has actually changed
direct_edit_drag_ = get_direct_edit_drag_enabled()
if enable_cmd_def_.controlDefinition.isChecked != direct_edit_drag_:
addin_updating_checkbox_ = True
enable_cmd_def_.controlDefinition.isChecked = direct_edit_drag_
addin_updating_checkbox_ = False
def is_parametric_mode():
try:
# UserInterface.ActiveWorkspace throws when it is called from DocumentActivatedHandler
# during Fusion 360 start-up(?). Checking for app_.isStartupComplete does not help.
if ui_.activeWorkspace.id == 'FusionSolidEnvironment':
design = adsk.fusion.Design.cast(app_.activeProduct)
if design and design.designType == adsk.fusion.DesignTypes.ParametricDesignType:
return True
except:
pass
return False
def clear_ui_item(item):
if item:
item.deleteMe()
def run(context):
#Expose global variables inside of function
global app_, ui_, enable_cmd_def_, select_panel_, fusion_drag_controls_cmd_def_
with error_catcher_:
app_ = adsk.core.Application.get()
ui_ = app_.userInterface
fusion_drag_controls_cmd_def_ = ui_.commandDefinitions.itemById('FusionDragCompControlsCmd')
# Clearing any previous enable_cmd_def
clear_ui_item(ui_.commandDefinitions.itemById(ENABLE_CMD_ID))
# There are multiple select panels. Pick the right one
select_panel_ = ui_.toolbarPanelsByProductType('DesignProductType').itemById('SelectPanel')
enabled = get_direct_edit_drag_enabled()
# Use a Command to get a transaction when renaming
enable_cmd_def_ = ui_.commandDefinitions.addCheckBoxDefinition(ENABLE_CMD_ID,
f'Component Drag',
'Enables or disables the movement of components by dragging '
'in the canvas.\n\n'
f'({NAME} v {manifest_["version"]})\n',
enabled)
events_manager_.add_handler(enable_cmd_def_.commandCreated,
callback=enable_cmd_created_handler)
# Removing the old control
clear_ui_item(select_panel_.controls.itemById(ENABLE_CMD_ID))
select_panel_.controls.addCommand(enable_cmd_def_, DIRECT_EDIT_DRAG_CMD_ID, False)
events_manager_.add_handler(ui_.commandStarting, callback=command_starting_handler)
events_manager_.add_handler(ui_.commandTerminated, callback=command_terminated_handler)
# Fusion bug: DocumentActivated is not called when switching to/from Drawing.
# https://forums.autodesk.com/t5/fusion-360-api-and-scripts/api-bug-application-documentactivated-event-do-not-raise/m-p/9020750
events_manager_.add_handler(app_.documentActivated,
callback=document_activated_handler)
# Workspace is not ready when starting (?)
if app_.isStartupComplete:
check_environment()
# Checking workspace type in DocumentActivated handler fails since Fusion 360 v2.0.10032
# Put a check at the end of the event queue instead.
events_manager_.delay(check_environment)
def stop(context):
with error_catcher_:
events_manager_.clean_up()
# Removing the old control
clear_ui_item(select_panel_.controls.itemById(ENABLE_CMD_ID))