FreeCAD workbench to create assembly handbooks
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
4.5 KiB

from typing import Optional
import FreeCADGui as Gui
import FreeCAD as App
from PySide.QtCore import QTimer
import random
def _rgb(r, g, b):
return r/255.0, g/255.0, b/255.0, 0.0
_colors = [
_rgb(94, 224, 174),
_rgb(223, 234, 70),
_rgb(35, 120, 200),
_rgb(188, 80, 33),
_rgb(26, 242, 69),
_rgb(13, 41, 107),
_rgb(153, 9, 52),
_rgb(211, 119, 0),
_rgb(34, 130, 7),
_rgb(221, 79, 249)
]
class AHB_Context:
_activeStageId: int = None
_allStagesVisible: bool = True
_animationActive: bool = False
_timeSinceLastStageUpdate: int = 0
def setActiveStage(self, stageId):
self._activeStageId = stageId
self._updateVisibility()
def getActiveStage(self):
return self._activeStageId
def getAllStages(self):
allStages = set()
doc = App.ActiveDocument
for obj in doc.Objects:
if obj.TypeId in ['Part::Feature', 'App::Part']:
if 'AssemblyHandbook_Stage' in obj.PropertiesList:
allStages.add(obj.AssemblyHandbook_Stage)
allStages = list(allStages)
allStages.sort()
return allStages
def onPartStageChanged(self, part: Optional[App.DocumentObject]):
allStages = self.getAllStages()
doc = App.ActiveDocument
if part is not None and not 'AssemblyHandbook_Stage' in part.PropertiesList:
part.ViewObject.ShapeColor = (0.8,0.8,0.8,0.0)
for obj in doc.Objects:
if obj.TypeId in ['Part::Feature', 'App::Part']:
if 'AssemblyHandbook_Stage' in obj.PropertiesList:
stageIndex = allStages.index(obj.AssemblyHandbook_Stage)
if obj.TypeId == 'Part::Feature':
obj.ViewObject.ShapeColor = _colors[stageIndex % len(_colors)]
elif obj.TypeId == 'App::Part':
for feature in obj.Group:
if feature.TypeId == 'Part::Feature':
feature.ViewObject.ShapeColor = _colors[stageIndex % len(_colors)]
self._updateVisibility()
def setAllStagesVisible(self, allStagesVisible):
self._allStagesVisible = allStagesVisible
self._updateVisibility()
def getAllStagesVisible(self):
return self._allStagesVisible
def _updateVisibility(self):
activeStageId = self.getActiveStage()
doc = App.ActiveDocument
for obj in doc.Objects:
if obj.TypeId == 'Part::Feature' in ['Part::Feature', 'App::Part']:
if 'AssemblyHandbook_Stage' in obj.PropertiesList:
obj.ViewObject.Visibility = self._allStagesVisible or activeStageId is None or obj.AssemblyHandbook_Stage <= activeStageId
def setAnimationActive(self, animationActive):
if self._animationActive == animationActive: return
self._animationActive = animationActive
self._updateAnimation()
def getAnimationActive(self):
return self._animationActive
def _updateAnimation(self):
if not self._animationActive: return
allStages = self.getAllStages()
if len(allStages) > 1 and self._timeSinceLastStageUpdate >= 1000:
self._timeSinceLastStageUpdate = 0
activeStageId = self.getActiveStage() or 0
stageIndex = allStages.index(activeStageId) if activeStageId in allStages else 0
stageIndex = (stageIndex + 1) % len(allStages)
self.setActiveStage(allStages[stageIndex])
tickResolution = 33
import math
from pivy import coin
cam = Gui.ActiveDocument.ActiveView.getCameraNode()
"""rot = coin.SbRotation()
rot.setValue(coin.SbVec3f(0, 0, 1), math.pi * tickResolution / 1000.0)
nrot = cam.orientation.getValue() * rot
cam.orientation = nrot"""
center = coin.SbVec3f(1000,0,750)
v = cam.position.getValue() - center
v[2] = 0
dist = v.length()
height = cam.position.getValue()[2]
angle = math.atan2(v[1], v[0])
angle = angle + 0.3 * tickResolution / 1000.0
cam.position = coin.SbVec3f(center[0] + math.cos(angle)*dist, center[1] + math.sin(angle)*dist, height)
cam.pointAt(center, coin.SbVec3f(0,0,1))
self._timeSinceLastStageUpdate = self._timeSinceLastStageUpdate + tickResolution
QTimer.singleShot(tickResolution, self._updateAnimation)