-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathFPSimRotaryEncoder.py
More file actions
executable file
·160 lines (142 loc) · 8.31 KB
/
FPSimRotaryEncoder.py
File metadata and controls
executable file
·160 lines (142 loc) · 8.31 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
import FreeCAD
import FPEventDispatcher
from FPInitialPlacement import InitialPlacements
import FPSimServer
import generated.python.FPSimulation_pb2 as Proto
lastRotationIncrementsAtAquire = dict()
buttonState = dict()
class FPSimRotaryEncoder(InitialPlacements):
def __init__(self, obj):
InitialPlacements.__init__(self, obj)
buttonState[obj.Name] = Proto.BUTTON_RELEASED
obj.addProperty('App::PropertyPythonObject', 'PressEventLocationXY').PressEventLocationXY = []
obj.addProperty('App::PropertyPythonObject', 'RotationAngleAtPress').RotationAngleAtPress = 0
obj.addProperty('App::PropertyPythonObject', 'RotationAngle').RotationAngle = 0
obj.addProperty('App::PropertyInteger', 'IncrementsPerRev').IncrementsPerRev = 64
obj.addProperty('App::PropertyFloat', 'MouseSensitivity').MouseSensitivity = 1.0
obj.addProperty('App::PropertyBool', 'PushButton').PushButton = False
obj.addProperty('App::PropertyBool', 'TouchSensitive').TouchSensitive = False
obj.addProperty('App::PropertyFloat', 'PushButtonDepth').PushButtonDepth = 1.0
obj.addProperty('App::PropertyVector', 'RotationAxis').RotationAxis = (0,0,0)
obj.addProperty('App::PropertyVector', 'RotationCenter').RotationCenter = (0,0,0)
obj.addProperty('App::PropertyInteger', 'NumSnapInPositions').NumSnapInPositions = 0 #TODO: implement
obj.Proxy = self
def _registerEventCallbacks(self, objName):
FPEventDispatcher.eventDispatcher.registerForButtonEvent(objName, self.onButtonEvent)
def _unregisterEventCallbacks(self, objName):
FPEventDispatcher.eventDispatcher.unregisterForButtonEvent(objName)
def onChanged(self, obj, prop):
#FreeCAD.Console.PrintMessage("in onChanged obj.Name: " + str(obj.Name) + " obj.Label: " + str(obj.Label) + " prop: " + str(prop) + "\n")
if prop == 'Proxy':
# Called at loading existing object on first place(Placement is not valid yet )
# Called at creation on first place(ToCheck: I think Placement is not valid here yet)
self._registerEventCallbacks(obj.Name)
buttonState[obj.Name] = Proto.BUTTON_RELEASED
elif prop == 'Group':
# Always called when the group changes(new group member inserted or removed)
# or gets created :
# - called after 'proxy'-cb
# - Placement is valid
# - strange thing is at this point there is no child object inside
if not obj.Group:
# Called when Removing all objects from group or when group-obj gets deleted
#FreeCAD.Console.PrintMessage(str(obj.Label) + " Obj has no Group attribute\n")
self._unregisterEventCallbacks(obj.Name)
elif self.hasNoChilds(obj):
# Called at object creation
#FreeCAD.Console.PrintMessage(str(obj.Label) + " Obj has Group attribute but no childs\n")
self._registerEventCallbacks(obj.Name)
else:
# Called When object gets added to a group that already has at least one child
#FreeCAD.Console.PrintMessage(str(obj.Label) + " Obj has Group attribute and childs\n")
pass
self.saveInitialPlacements(obj)
elif prop == 'ExpressionEngine':
# Called at loading existing object at last cb(Placement is valid now)
try:
obj.RotationAngle = 0
self.moveToInitialPlacement(obj)
except KeyError:
self.saveInitialPlacements(obj)
elif prop == 'PushButton':
if obj.PushButton == True:
FPEventDispatcher.eventDispatcher.registerForHoverKeyPress(obj.Name, FPEventDispatcher.FPEventDispatcher.CTRL_KEYCODE,self.onKeyEvent)
FPSimServer.dataAquisitionCBHolder.setButtonCB(obj.Name, self.getButtonState)
else:
FPEventDispatcher.eventDispatcher.unregisterHoverKeyPress(obj.Name, FPEventDispatcher.FPEventDispatcher.CTRL_KEYCODE)
# Called on parameter change (followed by execute-cb when it gets applied)
def execute(self, fp):
#FreeCAD.Console.PrintMessage("in execute fp: " + str(fp.Label) + "\n")
# Called when group-obj parameter change or child-objects parameter change gets applied
pass
def onButtonEvent(self, objName, state, pointerPos):
if state == FPEventDispatcher.FPEventDispatcher.PRESSED:
obj = FreeCAD.ActiveDocument.getObject(objName)
obj.PressEventLocationXY = pointerPos
obj.RotationAngleAtPress = obj.RotationAngle
FPEventDispatcher.eventDispatcher.registerForLocation(objName, self.onDragged)
else:
FPEventDispatcher.eventDispatcher.unregisterForLocation(objName, self.onDragged)
def onDragged(self, objName, pointerPos):
obj = FreeCAD.ActiveDocument.getObject(objName)
obj.RotationAngle = obj.RotationAngleAtPress + (pointerPos[1] - obj.PressEventLocationXY[1]) * obj.MouseSensitivity
rot = FreeCAD.Rotation(obj.RotationAxis, obj.RotationAngle)
for child in obj.Group:
initPlc = self.getInitialPlacement(obj, child.Name)
initBase = initPlc.Base
if objName in buttonState:
if buttonState[objName] == Proto.BUTTON_PRESSED:
deltaVec = FreeCAD.Vector(obj.RotationAxis[0], obj.RotationAxis[1], obj.RotationAxis[2]) * obj.PushButtonDepth
initBase = initBase - deltaVec
rotPlacement = FreeCAD.Placement(initBase, rot, obj.RotationCenter - initBase)
newRot = rotPlacement.Rotation.multiply( initPlc.Rotation )
newBase = rotPlacement.Base
#FreeCAD.Console.PrintMessage("OrigBase: " + str(initPlc.Base) + "\n" + "newBase: " + str(newBase) + "\n")
child.Placement.Base = newBase
child.Placement.Rotation = newRot
FPSimServer.dataAquisitionCBHolder.setEncoderCB(objName, self.getIncrements)
def onKeyEvent(self, objName, keyCode, state):
#FreeCAD.Console.PrintMessage("onKeyEvent " + str(objName) + " " + str(keyCode) + " " + str(state) + "\n")
FPSimServer.dataAquisitionCBHolder.setButtonCB(objName, self.getButtonState)
obj = FreeCAD.ActiveDocument.getObject(objName)
deltaVec = FreeCAD.Vector(obj.RotationAxis[0], obj.RotationAxis[1], obj.RotationAxis[2]) * obj.PushButtonDepth
if state == FPEventDispatcher.FPEventDispatcher.PRESSED:
buttonState[objName] = Proto.BUTTON_PRESSED
for child in obj.Group:
initPlc = self.getInitialPlacement(obj, child.Name)
base = child.Placement.Base - deltaVec
child.Placement.Base = base
else:
buttonState[objName] = Proto.BUTTON_RELEASED
for child in obj.Group:
base = child.Placement.Base + deltaVec
child.Placement.Base = base
def getIncrements(self, objName):
obj = FreeCAD.ActiveDocument.getObject(objName)
# take a sample of rot angle because of thread concurrency
actRotIncr = int( (float(obj.RotationAngle) / 360.0) * float(obj.IncrementsPerRev) )
if not lastRotationIncrementsAtAquire.get(objName):
lastRotationIncrementsAtAquire[objName] = actRotIncr
ret = actRotIncr - lastRotationIncrementsAtAquire[objName]
lastRotationIncrementsAtAquire[objName] = actRotIncr
return ret
def getButtonState(self, objName):
return buttonState[objName]
class FPSimRotaryEncoderViewProvider:
def __init__(self, obj):
obj.Proxy = self
def getIcon(self):
import FPSimDir
return FPSimDir.__dir__ + '/icons/RotEncoder.svg'
def createFPSimRotaryEncoder():
obj = FreeCAD.ActiveDocument.addObject('App::DocumentObjectGroupPython', 'FPSimRotaryEncoder')
FPSimRotaryEncoder(obj)
FPSimRotaryEncoderViewProvider(obj.ViewObject)
selection = FreeCAD.Gui.Selection.getSelectionEx()
try:
obj.RotationAxis = selection[-1].SubObjects[-1].normalAt(0,0)
obj.RotationCenter = selection[-1].SubObjects[-1].CenterOfMass
for sel_obj in selection:
obj.addObject(sel_obj.Object)
except IndexError:
FreeCAD.Console.PrintError("Usage Error, select objects and a rotation surface\n")