# Assuming you have not changed the general structure of the template no modification is needed in this file. # from . import commands from ast import arg from glob import glob from ...lib import fusion360utils as futil import threading import adsk.core import adsk.fusion import adsk.cam import traceback import json CMD_NAME = 'View Controller backend' app = adsk.core.Application.get() ui = app.userInterface stopFlag = None cameraViewEvent = 'CameraViewEventId' updateConstantsEvent = "UpdateConstantsEventId" customEvents = [] local_handlers = [] X_ROTATION = 0 Y_ROTATION = 0 Z_ROTATION = 0 X_PAN = 0 Y_PAN = 0 Z_PAN = 0 class UpdateConstantsEventHandler(adsk.core.CustomEventHandler): def __init__(self): super().__init__() def notify(self, args: adsk.core.CustomEventArgs) -> None: futil.log(f'{CMD_NAME} UpdateConstants notity...') eventArgs = json.loads(args.additionalInfo) global X_ROTATION, Y_ROTATION, Z_ROTATION global X_PAN, Y_PAN, Z_PAN X_ROTATION = float(eventArgs["X_rotation"]) Y_ROTATION = float(eventArgs["Y_rotation"]) Z_ROTATION = float(eventArgs["Z_rotation"]) X_PAN = float(eventArgs["X_pan"]) Y_PAN = float(eventArgs["Y_pan"]) Z_PAN = float(eventArgs["Z_pan"]) # The event handler that responds to the custom event being fired. class CameraViewEventHandler(adsk.core.CustomEventHandler): def __init__(self): super().__init__() self.viewport = app.activeViewport def notify(self, args: adsk.core.CustomEventArgs): global app try: # Make sure a command isn't running before changes are made. activeCmd = ui.activeCommand if activeCmd != 'SelectCommand': ui.commandDefinitions.itemById('SelectCommand').execute() camera = self.viewport.camera eye = camera.eye target = camera.target up = camera.upVector zoom = camera.viewExtents front = eye.vectorTo(target) right = up.crossProduct(front) rotate_matrix = adsk.core.Matrix3D.create() rotate_matrix.setWithCoordinateSystem(target, right, front, up) mat = rotate_matrix.asArray() # Get the value from the JSON data passed through the event. eventArgs: dict = json.loads(args.additionalInfo) X_radians = float(eventArgs.get('X_rotation', 0)) * X_ROTATION if X_radians: rotate_matrix.setToRotation(X_radians, front, target) eye.transformBy(rotate_matrix) up.transformBy(rotate_matrix) Y_radians = float(eventArgs.get('Y_rotation', 0)) * Y_ROTATION if Y_radians: rotate_matrix.setToRotation(Y_radians, right, target) eye.transformBy(rotate_matrix) up.transformBy(rotate_matrix) Z_radians = float(eventArgs.get('Z_rotation', 0)) * Z_ROTATION if Z_radians: rotate_matrix.setToRotation(Z_radians, up, target) eye.transformBy(rotate_matrix) up.transformBy(rotate_matrix) X_pan = float(eventArgs.get('X_pan', 0)) * X_pan Y_pan = float(eventArgs.get('Y_pan', 0)) * Y_pan Z_pan = float(eventArgs.get('Z_pan', 0)) * Z_pan if any([X_pan, Z_pan]): move_vector = adsk.core.Vector3D.create(X_pan, 0, Z_pan) move_vector.transformBy(rotate_matrix) eye.translateBy(move_vector) target.translateBy(move_vector) if Y_pan: zoom = zoom + Y_pan * 10 camera.isSmoothTransition = True camera.eye = eye camera.upVector = up camera.target = target camera.viewExtents = zoom app.activeViewport.camera = camera app.activeViewport.refresh() except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def rotate(self, X_radians: float, Y_radians: float, Z_radians: float): pass # The class for the new thread. class ControllerThread(threading.Thread): def __init__(self, event): threading.Thread.__init__(self) self.stopped = event def run(self): # Every five seconds fire a custom event, passing a random number. while not self.stopped.wait(2): futil.log(f'{CMD_NAME} Thread start sending data') args = {'X_rotation': 0.0, 'Y_rotation': 0.0, 'Z_rotation': 0.0, 'X_pan': 0.0, 'Y_pan': 0.0, 'Z_pan': 0.0} app.fireCustomEvent(cameraViewEvent, json.dumps(args)) def start(): futil.log(f'{CMD_NAME} Start...') # Register the custom event and connect the handler. global customEvents customEvents.append(app.registerCustomEvent(cameraViewEvent)) onCameraViewEvent = CameraViewEventHandler() customEvents[0].add(onCameraViewEvent) local_handlers.append(onCameraViewEvent) futil.log(f'{CMD_NAME} CameraViewEvent register') customEvents.append(app.registerCustomEvent(updateConstantsEvent)) onUpadateConstantEvent = UpdateConstantsEventHandler() customEvents[1].add(onUpadateConstantEvent) local_handlers.append(onUpadateConstantEvent) futil.log(f'{CMD_NAME} UpdateConstantsEvent register') # Create a new thread for the other processing. global stopFlag stopFlag = threading.Event() myThread = ControllerThread(stopFlag) # myThread.start() futil.log(f'{CMD_NAME} ControllerThread started') def stop(): try: for event, handler in zip(customEvents, local_handlers): event.remove(handler) # if local_handlers.count: # customEvent.remove(local_handlers[0]) stopFlag.set() app.unregisterCustomEvent(cameraViewEvent) app.unregisterCustomEvent(updateConstantsEvent) ui.messageBox('Stop addin') except: futil.handle_error('stop') # if ui: # ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))