-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathSketchChecker_Python.py
executable file
·277 lines (233 loc) · 9.96 KB
/
SketchChecker_Python.py
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# Author - Adam Nagy
# Description - Tests the currently selected sketch for open ended skecth curves
import adsk.core, adsk.fusion, traceback
# Adds the items of coll2 to coll1
def addCollections(coll1, coll2):
for item in coll2:
if not coll1.contains(item):
coll1.add(item)
# Go through each curve's endpoints and check if they are connected to another
# curve's endpoint. If not then we'll make a note of it. Once we found two of those
# we return
def getLoopEndPoints(loop):
# Collect all sketch points that is used just once
one = adsk.core.ObjectCollection.create()
more = adsk.core.ObjectCollection.create()
for curve in loop:
# skipping construction entities
if curve.isConstruction:
continue
# If it has issues, e.g. circles and ellipses don't
# have sketch end points then we get an expection that
# we can ignore since those entities are closed anyway
try:
if one.contains(curve.startSketchPoint):
more.add(curve.startSketchPoint)
one.removeByItem(curve.startSketchPoint)
elif not more.contains(curve.startSketchPoint):
one.add(curve.startSketchPoint)
if one.contains(curve.endSketchPoint):
more.add(curve.endSketchPoint)
one.removeByItem(curve.endSketchPoint)
elif not more.contains(curve.endSketchPoint):
one.add(curve.endSketchPoint)
except:
None
# look for values '1' because those are
# not connecting curves, i.e. they are open
return one
# By default we'll get the sketch points in context of the
# component that the sketch resides in. In order to select them in the UI
# we'll need the get their proxy in the root context through the
# active component occurrence
def selectInRootContext(pts):
app = adsk.core.Application.get()
design = app.activeProduct
root = design.rootComponent
comp = design.activeComponent
ui = app.userInterface
actSel = ui.activeSelections
# If the root component is active we have nothing to do
# than select them
#if comp == root:
for pt in pts:
actSel.add(pt)
return None
# Unfortunately component does not have an activeOccurrence property :(
# that's why we have to do the following workaround:
# we have to check all instances of the component to see
# in whose context we can get the selection to work
occs = root.allOccurrencesByComponent(comp)
for occ in occs:
try:
# If we get an exception when trying to select
# the sketch point in context of the given
# occurrence then we are using the wrong
# occurrence so we just move on to the next one
for pt in pts:
proxy = pt.createForAssemblyContext(occ)
actSel.add(proxy)
# We're done
return None
except:
# Nothing to do apart from moving on
# to the next possible occurrence
None
show(ui, "Could not select sketch points")
def show(ui, msg):
ui.messageBox(msg, "Sketch Tester")
# Global set of event handlers to keep them referenced for the duration of the command
handlers = []
isSavingSnapshot = True
commandId = 'SketchCheckerCmd'
workspaceToUse = 'FusionSolidEnvironment'
panelToUse = 'InspectPanel'
# Some utility functions
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 commandControlByIdForPanel(id):
global workspaceToUse
global panelToUse
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(workspaceToUse)
toolbarPanels_ = modelingWorkspace_.toolbarPanels
toolbarPanel_ = toolbarPanels_.itemById(panelToUse)
toolbarControls_ = toolbarPanel_.controls
toolbarControl_ = toolbarControls_.itemById(id)
return toolbarControl_
def destroyObject(uiObj, objToDelete):
if uiObj and objToDelete:
if objToDelete.isValid:
objToDelete.deleteMe()
else:
uiObj.messageBox('objToDelete is not a valid object')
def addCommandToPanel(panel, commandId, commandName, commandDescription, commandResources, onCommandCreated):
app = adsk.core.Application.get()
ui = app.userInterface
commandDefinitions_ = ui.commandDefinitions
toolbarControlsPanel_ = panel.controls
toolbarControlPanel_ = toolbarControlsPanel_.itemById(commandId)
if not toolbarControlPanel_:
commandDefinitionPanel_ = commandDefinitions_.itemById(commandId)
if not commandDefinitionPanel_:
commandDefinitionPanel_ = commandDefinitions_.addButtonDefinition(commandId, commandName, commandDescription, commandResources)
commandDefinitionPanel_.commandCreated.add(onCommandCreated)
# Keep the handler referenced beyond this function
handlers.append(onCommandCreated)
toolbarControlPanel_ = toolbarControlsPanel_.addCommand(commandDefinitionPanel_, '')
toolbarControlPanel_.isVisible = True
def getControlAndDefinition(commandId, objects):
commandControl_ = commandControlByIdForPanel(commandId)
if commandControl_:
objects.append(commandControl_)
commandDefinition_ = commandDefinitionById(commandId)
if commandDefinition_:
objects.append(commandDefinition_)
def checkSketch():
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
# Collect sketch entities which are
# already found as part of a loop
processed = adsk.core.ObjectCollection.create()
# No problems found so far
problemFound = False
# Sketch that the user is currently editing
sketch = app.activeEditObject
if not type(sketch) is adsk.fusion.Sketch:
show(ui, "A sketch needs to be active to run this command")
return None
for curve in sketch.sketchCurves:
# If we did not check this curve yet
if not processed.contains(curve):
# Check if other curves are connected to it
#curves = sketch.findConnectedCurves(curve)
curves = sketch.sketchCurves
pts = getLoopEndPoints(curves)
# If there are open end points
if pts:
# Highlight the open end sketch points
#pts = getLoopEndPoints(curves)
selectInRootContext(pts)
# We're done
problemFound = True
break
# If the loop is closed
else:
addCollections(processed, curves)
if not problemFound:
show(ui, "No open loops found in sketch")
except:
if ui:
show(ui, 'Failed:\n{}'.format(traceback.format_exc()))
# the main function that is called when our addin is loaded
def run(context):
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
# command properties
commandName = 'Check Sketch'
commandDescription = 'Checks the curves in the currently active sketch for ' \
'any open ends which do not connect to other curves and highlights those\n'
commandResources = './resources/command'
# our command
class CommandExecuteHandler(adsk.core.CommandEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
checkSketch()
except:
if ui:
ui.messageBox('command executed failed:\n{}'.format(traceback.format_exc()))
class CommandCreatedEventHandler(adsk.core.CommandCreatedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
cmd = args.command
onExecute = CommandExecuteHandler()
cmd.execute.add(onExecute)
# keep the handler referenced beyond this function
handlers.append(onExecute)
except:
if ui:
ui.messageBox('Panel command created failed:\n{}'.format(traceback.format_exc()))
# add our command on "Inspect" panel in "Modeling" workspace
global workspaceToUse
global panelToUse
workspaces_ = ui.workspaces
modelingWorkspace_ = workspaces_.itemById(workspaceToUse)
toolbarPanels_ = modelingWorkspace_.toolbarPanels
# add the new command under the fifth panel / "Inspect"
toolbarPanel_ = toolbarPanels_.itemById(panelToUse)
addCommandToPanel(toolbarPanel_, commandId, commandName, commandDescription, commandResources, CommandCreatedEventHandler())
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
objArray = []
getControlAndDefinition(commandId, objArray)
for obj in objArray:
destroyObject(ui, obj)
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))