/*========================================================================= Program: Visualization Toolkit Module: vtkTexturedButtonRepresentation.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkTexturedButtonRepresentation.h" #include "vtkActor.h" #include "vtkAssemblyPath.h" #include "vtkCamera.h" #include "vtkCellPicker.h" #include "vtkCoordinate.h" #include "vtkFollower.h" #include "vtkImageData.h" #include "vtkInteractorObserver.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkPickingManager.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkProperty.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkSmartPointer.h" #include "vtkTexture.h" #include vtkStandardNewMacro(vtkTexturedButtonRepresentation); vtkCxxSetObjectMacro(vtkTexturedButtonRepresentation, Property, vtkProperty); vtkCxxSetObjectMacro(vtkTexturedButtonRepresentation, HoveringProperty, vtkProperty); vtkCxxSetObjectMacro(vtkTexturedButtonRepresentation, SelectingProperty, vtkProperty); // Map of textures class vtkTextureArray : public std::map> { }; typedef std::map>::iterator vtkTextureArrayIterator; //------------------------------------------------------------------------------ vtkTexturedButtonRepresentation::vtkTexturedButtonRepresentation() { this->Mapper = vtkPolyDataMapper::New(); this->Texture = vtkTexture::New(); this->Texture->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_ADD); this->Actor = vtkActor::New(); this->Actor->SetMapper(this->Mapper); this->Actor->SetTexture(this->Texture); this->Follower = vtkFollower::New(); this->Follower->SetMapper(this->Mapper); this->Follower->SetTexture(this->Texture); // Following this->FollowCamera = 0; // Set up the initial properties this->CreateDefaultProperties(); // List of textures this->TextureArray = new vtkTextureArray; this->Picker = vtkCellPicker::New(); this->Picker->AddPickList(this->Actor); this->Picker->AddPickList(this->Follower); this->Picker->PickFromListOn(); } //------------------------------------------------------------------------------ vtkTexturedButtonRepresentation::~vtkTexturedButtonRepresentation() { this->Actor->Delete(); this->Follower->Delete(); this->Mapper->Delete(); this->Texture->Delete(); if (this->Property) { this->Property->Delete(); this->Property = nullptr; } if (this->HoveringProperty) { this->HoveringProperty->Delete(); this->HoveringProperty = nullptr; } if (this->SelectingProperty) { this->SelectingProperty->Delete(); this->SelectingProperty = nullptr; } delete this->TextureArray; this->Picker->Delete(); } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::SetButtonGeometry(vtkPolyData* pd) { this->Mapper->SetInputData(pd); } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::SetButtonGeometryConnection(vtkAlgorithmOutput* algOutput) { this->Mapper->SetInputConnection(algOutput); } //------------------------------------------------------------------------------ vtkPolyData* vtkTexturedButtonRepresentation::GetButtonGeometry() { return this->Mapper->GetInput(); } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::SetButtonTexture(int i, vtkImageData* image) { if (i < 0) { i = 0; } if (i >= this->NumberOfStates) { i = this->NumberOfStates - 1; } (*this->TextureArray)[i] = image; } //------------------------------------------------------------------------------ vtkImageData* vtkTexturedButtonRepresentation::GetButtonTexture(int i) { if (i < 0) { i = 0; } if (i >= this->NumberOfStates) { i = this->NumberOfStates - 1; } vtkTextureArrayIterator iter = this->TextureArray->find(i); if (iter != this->TextureArray->end()) { return (*iter).second; } else { return nullptr; } } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::RegisterPickers() { vtkPickingManager* pm = this->GetPickingManager(); if (!pm) { return; } pm->AddPicker(this->Picker, this); } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::PlaceWidget(double scale, double xyz[3], double normal[3]) { // Translate the center double bds[6], center[3]; this->Actor->GetBounds(bds); center[0] = (bds[0] + bds[1]) / 2.0; center[1] = (bds[2] + bds[3]) / 2.0; center[2] = (bds[4] + bds[5]) / 2.0; this->Actor->AddPosition(xyz[0] - center[0], xyz[1] - center[1], xyz[2] - center[2]); this->Follower->AddPosition(xyz[0] - center[0], xyz[1] - center[1], xyz[2] - center[2]); // Scale the button this->Actor->SetScale(scale, scale, scale); this->Follower->SetScale(scale, scale, scale); // Rotate the button to align with the normal Cross the z axis with the // normal to get a rotation vector. Then rotate around it. double zAxis[3]; zAxis[0] = zAxis[1] = 0.0; zAxis[2] = 1.0; double rotAxis[3], angle; vtkMath::Normalize(normal); vtkMath::Cross(zAxis, normal, rotAxis); angle = acos(vtkMath::Dot(zAxis, normal)); this->Actor->RotateWXYZ(vtkMath::DegreesFromRadians(angle), rotAxis[0], rotAxis[1], rotAxis[2]); this->Follower->RotateWXYZ( vtkMath::DegreesFromRadians(angle), rotAxis[0], rotAxis[1], rotAxis[2]); } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::PlaceWidget(double bds[6]) { double bounds[6], center[3], aBds[6], aCenter[3]; this->AdjustBounds(bds, bounds, center); for (int i = 0; i < 6; i++) { this->InitialBounds[i] = bounds[i]; } this->InitialLength = sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) + (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) + (bounds[5] - bounds[4]) * (bounds[5] - bounds[4])); // Get the bounds of the actor this->Actor->GetBounds(aBds); aCenter[0] = (aBds[0] + aBds[1]) / 2.0; aCenter[1] = (aBds[2] + aBds[3]) / 2.0; aCenter[2] = (aBds[4] + aBds[5]) / 2.0; // Now fit the actor bounds in the place bounds by tampering with its // transform. this->Actor->AddPosition(center[0] - aCenter[0], center[1] - aCenter[1], center[2] - aCenter[2]); this->Follower->AddPosition( center[0] - aCenter[0], center[1] - aCenter[1], center[2] - aCenter[2]); double s[3], sMin; for (int i = 0; i < 3; ++i) { if ((bounds[2 * i + 1] - bounds[2 * i]) <= 0.0 || (aBds[2 * i + 1] - aBds[2 * i]) <= 0.0) { s[i] = VTK_FLOAT_MAX; } else { s[i] = (bounds[2 * i + 1] - bounds[2 * i]) / (aBds[2 * i + 1] - aBds[2 * i]); } } sMin = (s[0] < s[1] ? (s[0] < s[2] ? s[0] : s[2]) : (s[1] < s[2] ? s[1] : s[2])); this->Actor->SetScale(sMin, sMin, sMin); this->Follower->SetScale(sMin, sMin, sMin); } //------------------------------------------------------------------------------ int vtkTexturedButtonRepresentation ::ComputeInteractionState(int X, int Y, int vtkNotUsed(modify)) { this->VisibilityOn(); // actor must be on to be picked vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->Picker); if (path != nullptr) { this->InteractionState = vtkButtonRepresentation::Inside; } else { this->InteractionState = vtkButtonRepresentation::Outside; } return this->InteractionState; } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::Highlight(int highlight) { this->Superclass::Highlight(highlight); vtkProperty* initialProperty = this->Actor->GetProperty(); vtkProperty* selectedProperty; if (highlight == vtkButtonRepresentation::HighlightHovering) { this->Actor->SetProperty(this->HoveringProperty); this->Follower->SetProperty(this->HoveringProperty); selectedProperty = this->HoveringProperty; } else if (highlight == vtkButtonRepresentation::HighlightSelecting) { this->Actor->SetProperty(this->SelectingProperty); this->Follower->SetProperty(this->SelectingProperty); selectedProperty = this->SelectingProperty; } else // if ( highlight == vtkButtonRepresentation::HighlightNormal ) { this->Actor->SetProperty(this->Property); this->Follower->SetProperty(this->Property); selectedProperty = this->Property; } if (selectedProperty != initialProperty) { this->Modified(); } } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::CreateDefaultProperties() { this->Property = vtkProperty::New(); this->Property->SetColor(1, 1, 1); this->HoveringProperty = vtkProperty::New(); this->HoveringProperty->SetAmbient(1.0); this->SelectingProperty = vtkProperty::New(); this->SelectingProperty->SetAmbient(0.2); this->SelectingProperty->SetAmbientColor(0.2, 0.2, 0.2); } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::BuildRepresentation() { // The net effect is to resize the handle if (this->GetMTime() > this->BuildTime || (this->Renderer && this->Renderer->GetVTKWindow() && this->Renderer->GetVTKWindow()->GetMTime() > this->BuildTime)) { // In case follower is being used if (this->FollowCamera) { this->Follower->VisibilityOn(); this->Actor->VisibilityOff(); this->Follower->SetCamera(this->Renderer->GetActiveCamera()); } else { this->Follower->VisibilityOff(); this->Actor->VisibilityOn(); } vtkTextureArrayIterator iter = this->TextureArray->find(this->State); if (iter != this->TextureArray->end()) { this->Texture->SetInputData((*iter).second); } else { this->Texture->SetInputData(nullptr); } this->BuildTime.Modified(); } } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::ShallowCopy(vtkProp* prop) { vtkTexturedButtonRepresentation* rep = vtkTexturedButtonRepresentation::SafeDownCast(prop); if (rep) { this->Mapper->ShallowCopy(rep->Mapper); this->Property->DeepCopy(rep->Property); this->HoveringProperty->DeepCopy(rep->HoveringProperty); this->SelectingProperty->DeepCopy(rep->SelectingProperty); vtkTextureArrayIterator iter; for (iter = rep->TextureArray->begin(); iter != rep->TextureArray->end(); ++iter) { (*this->TextureArray)[(*iter).first] = (*iter).second; } this->FollowCamera = rep->FollowCamera; } this->Superclass::ShallowCopy(prop); } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::ReleaseGraphicsResources(vtkWindow* win) { this->Actor->ReleaseGraphicsResources(win); this->Follower->ReleaseGraphicsResources(win); } //------------------------------------------------------------------------------ int vtkTexturedButtonRepresentation::RenderOpaqueGeometry(vtkViewport* viewport) { this->BuildRepresentation(); if (this->FollowCamera) { return this->Follower->RenderOpaqueGeometry(viewport); } else { return this->Actor->RenderOpaqueGeometry(viewport); } } //------------------------------------------------------------------------------ int vtkTexturedButtonRepresentation::RenderTranslucentPolygonalGeometry(vtkViewport* viewport) { this->BuildRepresentation(); if (this->FollowCamera) { return this->Follower->RenderTranslucentPolygonalGeometry(viewport); } else { return this->Actor->RenderTranslucentPolygonalGeometry(viewport); } } //------------------------------------------------------------------------------ vtkTypeBool vtkTexturedButtonRepresentation::HasTranslucentPolygonalGeometry() { this->BuildRepresentation(); if (this->FollowCamera) { return this->Follower->HasTranslucentPolygonalGeometry(); } else { return this->Actor->HasTranslucentPolygonalGeometry(); } } //------------------------------------------------------------------------------ double* vtkTexturedButtonRepresentation::GetBounds() { return this->Actor->GetBounds(); } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::GetActors(vtkPropCollection* pc) { if (this->FollowCamera) { this->Follower->GetActors(pc); } else { this->Actor->GetActors(pc); } } //------------------------------------------------------------------------------ void vtkTexturedButtonRepresentation::PrintSelf(ostream& os, vtkIndent indent) { // Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h this->Superclass::PrintSelf(os, indent); os << indent << "Button Geometry: " << this->GetButtonGeometry() << "\n"; os << indent << "Follow Camera: " << (this->FollowCamera ? "On\n" : "Off\n"); if (this->Property) { os << indent << "Property: " << this->Property << "\n"; } else { os << indent << "Property: (none)\n"; } if (this->HoveringProperty) { os << indent << "Hovering Property: " << this->HoveringProperty << "\n"; } else { os << indent << "Hovering Property: (none)\n"; } if (this->SelectingProperty) { os << indent << "Selecting Property: " << this->SelectingProperty << "\n"; } else { os << indent << "Selecting Property: (none)\n"; } }