From 87eaf79b6a561a0e4440f4dde5dda1c8babbf815 Mon Sep 17 00:00:00 2001 From: Johan Andruejol Date: Tue, 20 Nov 2012 15:00:02 -0500 Subject: [PATCH] Refactor initialization of the display bone node Since the display node is the last to be added to the scene, it must be properly initialized with the widget values before fullfilling its destiny. For that we relied on the event DisplayModifiedEvent that is suppose to fire an event with empty calldata upon creation of the display node. This led to 2 issues: - The first DisplayModifiedEvent fired isn't with empty data. This is a bug and steered us toward the previous ugly hack. - It does not work ! Indeed with multiple bones, all the display node can be changed and and pass through that function. That means that only the first of them would not update the widget from its values. Instead, we simply create a ShouldBeInitialized flag for each display node that can be checked and changed once the node has been initialized. See Issue #13693 --- .../MRML/Core/vtkMRMLBoneDisplayNode.cxx | 1 + .../MRML/Core/vtkMRMLBoneDisplayNode.h | 5 ++ .../vtkMRMLArmatureDisplayableManager.cxx | 50 +++++++------------ 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/Modules/Loadable/Armatures/MRML/Core/vtkMRMLBoneDisplayNode.cxx b/Modules/Loadable/Armatures/MRML/Core/vtkMRMLBoneDisplayNode.cxx index 5ffe9a9..e986d53 100644 --- a/Modules/Loadable/Armatures/MRML/Core/vtkMRMLBoneDisplayNode.cxx +++ b/Modules/Loadable/Armatures/MRML/Core/vtkMRMLBoneDisplayNode.cxx @@ -38,6 +38,7 @@ vtkMRMLNodeNewMacro(vtkMRMLBoneDisplayNode); vtkMRMLBoneDisplayNode::vtkMRMLBoneDisplayNode() { this->SetVisibility(1); + this->ShouldBeInitialized = true; } //---------------------------------------------------------------------------- diff --git a/Modules/Loadable/Armatures/MRML/Core/vtkMRMLBoneDisplayNode.h b/Modules/Loadable/Armatures/MRML/Core/vtkMRMLBoneDisplayNode.h index 0d32b64..01bb8e6 100644 --- a/Modules/Loadable/Armatures/MRML/Core/vtkMRMLBoneDisplayNode.h +++ b/Modules/Loadable/Armatures/MRML/Core/vtkMRMLBoneDisplayNode.h @@ -78,6 +78,10 @@ class VTK_BENDER_ARMATURES_MRML_CORE_EXPORT vtkMRMLBoneDisplayNode vtkSetVector3Macro(WidgetInteractionColor, double); vtkGetVector3Macro(WidgetInteractionColor, double); + /// Set/Get if the widget should be initialized or not. + vtkSetMacro(ShouldBeInitialized, bool); + vtkGetMacro(ShouldBeInitialized, bool); + //-------------------------------------------------------------------------- // Bone methods //-------------------------------------------------------------------------- @@ -95,6 +99,7 @@ class VTK_BENDER_ARMATURES_MRML_CORE_EXPORT vtkMRMLBoneDisplayNode ~vtkMRMLBoneDisplayNode(); double WidgetInteractionColor[3]; + bool ShouldBeInitialized; vtkMRMLBoneDisplayNode(const vtkMRMLBoneDisplayNode&); /// not implemented void operator=(const vtkMRMLBoneDisplayNode&); /// not implemented diff --git a/Modules/Loadable/Armatures/MRML/DisplayableManagers/vtkMRMLArmatureDisplayableManager.cxx b/Modules/Loadable/Armatures/MRML/DisplayableManagers/vtkMRMLArmatureDisplayableManager.cxx index a019e81..47334dd 100644 --- a/Modules/Loadable/Armatures/MRML/DisplayableManagers/vtkMRMLArmatureDisplayableManager.cxx +++ b/Modules/Loadable/Armatures/MRML/DisplayableManagers/vtkMRMLArmatureDisplayableManager.cxx @@ -120,7 +120,6 @@ class vtkMRMLArmatureDisplayableManager::vtkInternal ArmatureNodesLink ArmatureNodes; BoneNodesLink BoneNodes; vtkMRMLArmatureDisplayableManager* External; - bool IgnoreFirstBuggyEvent; }; //--------------------------------------------------------------------------- @@ -131,7 +130,6 @@ vtkMRMLArmatureDisplayableManager::vtkInternal ::vtkInternal(vtkMRMLArmatureDisplayableManager* external) { this->External = external; - this->IgnoreFirstBuggyEvent = true; } //--------------------------------------------------------------------------- @@ -601,6 +599,22 @@ ::UpdateBoneWidgetFromNode(vtkMRMLBoneNode* boneNode, boneNode->PasteBoneNodeProperties(boneWidget); if (boneDisplayNode) { + if (boneDisplayNode->GetShouldBeInitialized()) + { + // This hackish code is here to prevent the update of the widget + // by the display node before the display node was initialized. + int wasModifying = boneDisplayNode->StartModify(); + double normalColor[3]; + boneWidget->GetBoneRepresentation()->GetLineProperty() + ->GetColor(normalColor); + boneDisplayNode->SetColor(normalColor); + + boneDisplayNode->CopyBoneWidgetDisplayProperties(boneWidget); + boneDisplayNode->SetSelected(true); + boneDisplayNode->SetShouldBeInitialized(false); + boneDisplayNode->EndModify(wasModifying); + } + boneDisplayNode->PasteBoneDisplayNodeProperties(boneWidget); } boneWidget->AddObserver(vtkCommand::ModifiedEvent, @@ -825,37 +839,7 @@ ::ProcessMRMLNodesEvents(vtkObject *caller, vtkMRMLBoneNode* boneNode = vtkMRMLBoneNode::SafeDownCast(caller); vtkBoneWidget* boneWidget = this->Internal->GetBoneWidget(boneNode); - if (!callData) - { - vtkMRMLBoneDisplayNode* displayBoneNode = - boneNode->GetBoneDisplayNode(); - if (displayBoneNode && boneWidget) - { - int wasModifying = displayBoneNode->StartModify(); - double normalColor[3]; - boneWidget->GetBoneRepresentation()->GetLineProperty()->GetColor(normalColor); - displayBoneNode->SetColor(normalColor); - displayBoneNode->CopyBoneWidgetDisplayProperties(boneWidget); - displayBoneNode->SetSelected(true); - displayBoneNode->EndModify(wasModifying); - } - } - else - { - // This hackish code is here to prevent the update of the widget - // by the display node before the display node was initialized. - // Normally, an event with empty calldata is fired as the first event - // when the display node is created. However an undesired "normal" - // event is fired before. We just ignore it. - if (this->Internal->IgnoreFirstBuggyEvent) - { - this->Internal->IgnoreFirstBuggyEvent = false; - return; - } - // Normal event, the display node was changed, so update the widget. - this->Internal->UpdateBoneWidgetFromNode(boneNode, boneWidget); - } - + this->Internal->UpdateBoneWidgetFromNode(boneNode, boneWidget); this->RequestRender(); }