Files
fusion360/ControllByPs4/commands/backend/backend.py
2022-09-21 23:25:38 +02:00

200 lines
6.6 KiB
Python

# 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
from ...lib import hid
CMD_NAME = 'View Controller backend'
app = adsk.core.Application.get()
ui = app.userInterface
myThread = None
stopFlag = None
cameraViewEvent = 'CameraViewEventId'
updateConstantsEvent = "UpdateConstantsEventId"
customEvents = []
l_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"])
myThread.start()
# 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 = False
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):
futil.log(f'{CMD_NAME} ControllerThread started')
gamepad = hid.Device(vid=1356, pid=1476)
gamepad.nonblocking = True
# Every five seconds fire a custom event, passing a random number.
while not self.stopped.wait(0.01):
# futil.log(f'{CMD_NAME} Thread start sending data')
report = list(gamepad.read(128))
args = {
'X_rotation': 0.0,
'Y_rotation': self.convert(report[4], 10),
'Z_rotation': self.convert(report[3], 10),
'X_pan': self.convert(report[1], 10),
'Y_pan': self.convert(report[2], 10),
'Z_pan': 0.0
}
app.fireCustomEvent(cameraViewEvent, json.dumps(args))
def convert(self, input, dedzone) -> float:
normal: float = input - 127
if abs(normal) < dedzone:
return 0.0
normal = normal / 128
return normal
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)
l_handlers.append(onCameraViewEvent)
futil.log(f'{CMD_NAME} CameraViewEvent register')
customEvents.append(app.registerCustomEvent(updateConstantsEvent))
onUpadateConstantEvent = UpdateConstantsEventHandler()
customEvents[1].add(onUpadateConstantEvent)
l_handlers.append(onUpadateConstantEvent)
futil.log(f'{CMD_NAME} UpdateConstantsEvent register')
# Create a new thread for the other processing.
global stopFlag, myThread
stopFlag = threading.Event()
myThread = ControllerThread(stopFlag)
# myThread.start()
def stop():
try:
for event, handler in zip(customEvents, l_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()))