From e17fdd00780879d53c1e19c6ad5791a5dfa6cdc2 Mon Sep 17 00:00:00 2001 From: Youen Toupin Date: Sun, 12 Dec 2021 23:43:55 +0100 Subject: [PATCH] - added tools to visualize stages (hide parts that are in subsequent stages) - added animation tool --- InitGui.py | 8 ++++ ahb_cmd_animate.py | 21 +++++++++ ahb_cmd_switch_visibility_mode.py | 21 +++++++++ ahb_context.py | 73 ++++++++++++++++++++++++++++++- 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 ahb_cmd_animate.py create mode 100644 ahb_cmd_switch_visibility_mode.py diff --git a/InitGui.py b/InitGui.py index adc7d13..e762958 100644 --- a/InitGui.py +++ b/InitGui.py @@ -59,6 +59,12 @@ class AssemblyHandbookWorkbench(Gui.Workbench): self.importModule('ahb_cmd_set_part_stage') toolbox.append("AHB_setPartStage") + self.importModule('ahb_cmd_switch_visibility_mode') + toolbox.append("AHB_switchVisibilityMode") + + self.importModule('ahb_cmd_animate') + toolbox.append("AHB_animate") + if self.dev: self.importModule('ahb_cmd_reload') toolbox.append("AHB_reload") @@ -71,6 +77,8 @@ class AssemblyHandbookWorkbench(Gui.Workbench): self.removeToolbar("Assembly Handbook") self.removeMenu("Assembly Handbook") + self.context.setAnimationActive(False) + import importlib import ahb_context importlib.reload(ahb_context) diff --git a/ahb_cmd_animate.py b/ahb_cmd_animate.py new file mode 100644 index 0000000..769366c --- /dev/null +++ b/ahb_cmd_animate.py @@ -0,0 +1,21 @@ +from typing import Optional + +import FreeCADGui as Gui +import FreeCAD as App + +class AHB_Animate: + def GetResources(self): + return {"MenuText": "Animate", + "ToolTip": "Animate active stage to show all build stages", + "Pixmap": "" + } + + def IsActive(self): + return True + + def Activated(self, stageId: Optional[int] = None): + workbench = Gui.getWorkbench("AssemblyHandbookWorkbench") + workbench.context.setAnimationActive(not workbench.context.getAnimationActive()) + +from ahb_command import AHB_CommandWrapper +AHB_CommandWrapper.addGuiCommand('AHB_animate', AHB_Animate()) diff --git a/ahb_cmd_switch_visibility_mode.py b/ahb_cmd_switch_visibility_mode.py new file mode 100644 index 0000000..c9cba25 --- /dev/null +++ b/ahb_cmd_switch_visibility_mode.py @@ -0,0 +1,21 @@ +from typing import Optional + +import FreeCADGui as Gui +import FreeCAD as App + +class AHB_SwitchVisibilityMode: + def GetResources(self): + return {"MenuText": "Switch visibility", + "ToolTip": "Switch visibility mode", + "Pixmap": "" + } + + def IsActive(self): + return True + + def Activated(self, stageId: Optional[int] = None): + workbench = Gui.getWorkbench("AssemblyHandbookWorkbench") + workbench.context.setAllStagesVisible(not workbench.context.getAllStagesVisible()) + +from ahb_command import AHB_CommandWrapper +AHB_CommandWrapper.addGuiCommand('AHB_switchVisibilityMode', AHB_SwitchVisibilityMode()) diff --git a/ahb_context.py b/ahb_context.py index bca0daa..db30415 100644 --- a/ahb_context.py +++ b/ahb_context.py @@ -1,5 +1,6 @@ import FreeCADGui as Gui import FreeCAD as App +from PySide.QtCore import QTimer import random def _rgb(r, g, b): @@ -20,14 +21,18 @@ _colors = [ 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 onPartStageChanged(self, part: App.DocumentObject): + def getAllStages(self): allStages = set() doc = App.ActiveDocument @@ -38,6 +43,12 @@ class AHB_Context: allStages = list(allStages) allStages.sort() + return allStages + + def onPartStageChanged(self, part: App.DocumentObject): + allStages = self.getAllStages() + + doc = App.ActiveDocument if not 'AssemblyHandbook_Stage' in part.PropertiesList: part.ViewObject.ShapeColor = (0.8,0.8,0.8,0.0) @@ -47,3 +58,63 @@ class AHB_Context: if 'AssemblyHandbook_Stage' in obj.PropertiesList: stageIndex = allStages.index(obj.AssemblyHandbook_Stage) obj.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': + 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)