Skip to content

Commit

Permalink
Refactor initialization of the display bone node
Browse files Browse the repository at this point in the history
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
  • Loading branch information
vovythevov committed Nov 20, 2012
1 parent 848b809 commit 87eaf79
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 33 deletions.
Expand Up @@ -38,6 +38,7 @@ vtkMRMLNodeNewMacro(vtkMRMLBoneDisplayNode);
vtkMRMLBoneDisplayNode::vtkMRMLBoneDisplayNode()
{
this->SetVisibility(1);
this->ShouldBeInitialized = true;
}

//----------------------------------------------------------------------------
Expand Down
5 changes: 5 additions & 0 deletions Modules/Loadable/Armatures/MRML/Core/vtkMRMLBoneDisplayNode.h
Expand Up @@ -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
//--------------------------------------------------------------------------
Expand All @@ -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
Expand Down
Expand Up @@ -120,7 +120,6 @@ class vtkMRMLArmatureDisplayableManager::vtkInternal
ArmatureNodesLink ArmatureNodes;
BoneNodesLink BoneNodes;
vtkMRMLArmatureDisplayableManager* External;
bool IgnoreFirstBuggyEvent;
};

//---------------------------------------------------------------------------
Expand All @@ -131,7 +130,6 @@ vtkMRMLArmatureDisplayableManager::vtkInternal
::vtkInternal(vtkMRMLArmatureDisplayableManager* external)
{
this->External = external;
this->IgnoreFirstBuggyEvent = true;
}

//---------------------------------------------------------------------------
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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();
}

Expand Down

0 comments on commit 87eaf79

Please sign in to comment.