ROOT logo
// @(#)root/gl:$Id: TGLScaleManip.cxx 20882 2007-11-19 11:31:26Z rdm $
// Author:  Richard Maunder  16/09/2005

/*************************************************************************
 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TGLScaleManip.h"
#include "TGLPhysicalShape.h"
#include "TGLCamera.h"
#include "TGLIncludes.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGLScaleManip                                                        //
//                                                                      //
// Scale manipulator - attaches to physical shape and draws local axes  //
// widgets with box heads. User can mouse over (turns yellow) and L     //
// click/drag to scale along this axis.                                 //
// Widgets use standard 3D package axes colours: X red, Y green, Z blue.//
//////////////////////////////////////////////////////////////////////////

ClassImp(TGLScaleManip)

//______________________________________________________________________________
TGLScaleManip::TGLScaleManip()
{
   // Construct scale manipulator not bound to any physical shape.
}

//______________________________________________________________________________
TGLScaleManip::TGLScaleManip(TGLPhysicalShape * shape) :
   TGLManip(shape)
{
   // Construct scale manipulator bound to TGLPhysicalShape 'shape'.
}

//______________________________________________________________________________
TGLScaleManip::~TGLScaleManip()
{
   // Destory the scale manipulator
}

//______________________________________________________________________________
void TGLScaleManip::Draw(const TGLCamera & camera) const
{
   // Draw scale manipulator - tubes with box heads, in local axes of
   // attached shape, in red(X), green(Y) and blue(Z), with white center sphere.
   // If selected widget (mouse over) this is drawn in active colour (yellow).

   if (!fShape) {
      return;
   }

   // Get draw scales
   const TGLBoundingBox & box = fShape->BoundingBox();
   Double_t baseScale;
   TGLVector3 axisScale[3];
   CalcDrawScale(box, camera, baseScale, axisScale);

   // Get permitted manipulations on shape
   TGLPhysicalShape::EManip manip = fShape->GetManip();

   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glDisable(GL_CULL_FACE);

   // Draw three axis widgets out of bounding box where permitted
   // Not drawing will prevent interaction
   // GL name loading for hit testing - 0 reserved for no selection
   if (manip & TGLPhysicalShape::kScaleX) {
      glPushName(1);
      TGLUtil::DrawLine(box.Center(), axisScale[0], TGLUtil::kLineHeadBox,
                        baseScale, fSelectedWidget == 1 ? fgYellow : fgRed);
      glPopName();
   } else {
      TGLUtil::DrawLine(box.Center(), axisScale[0], TGLUtil::kLineHeadBox,
                        baseScale, fgGrey);
   }
   if (manip & TGLPhysicalShape::kScaleY) {
      glPushName(2);
      TGLUtil::DrawLine(box.Center(), axisScale[1], TGLUtil::kLineHeadBox,
                        baseScale, fSelectedWidget == 2 ? fgYellow : fgGreen);
      glPopName();
   } else {
      TGLUtil::DrawLine(box.Center(), axisScale[1], TGLUtil::kLineHeadBox,
                        baseScale, fgGrey);
   }
   if (manip & TGLPhysicalShape::kScaleZ) {
      glPushName(3);
      TGLUtil::DrawLine(box.Center(), axisScale[2], TGLUtil::kLineHeadBox,
                        baseScale, fSelectedWidget == 3 ? fgYellow : fgBlue);
      glPopName();
   } else {
      TGLUtil::DrawLine(box.Center(), axisScale[2], TGLUtil::kLineHeadBox,
                        baseScale, fgGrey);
   }
   // Draw white center sphere
   TGLUtil::DrawSphere(box.Center(), baseScale/2.0, fgWhite);

   glEnable(GL_CULL_FACE);
   glDisable(GL_BLEND);
}

//______________________________________________________________________________
Bool_t TGLScaleManip::HandleButton(const Event_t   & event,
                                   const TGLCamera & camera)
{
   // Handle mouse button event over manipulator - returns kTRUE if
   // redraw required kFALSE otherwise.

   if (event.fType == kButtonPress && fSelectedWidget != 0) {
      fStartScale = fShape->GetScale();
   }

   return TGLManip::HandleButton(event, camera);
}

//______________________________________________________________________________
Bool_t TGLScaleManip::HandleMotion(const Event_t & event,
                                   const TGLCamera & camera)
{
   // Handle mouse motion over manipulator - if active (selected
   // widget) scale physical along selected widget (axis) of the
   // manipulator, so it tracks mouse action. Returns kTRUE if redraw
   // required kFALSE otherwise.

   if (fActive) {
      // Find mouse delta projected into world at attached object center
      TGLVector3 shift = camera.ViewportDeltaToWorld(fShape->BoundingBox().Center(),
                                                     event.fX - fFirstMouse.GetX(),
                                                     -event.fY + fFirstMouse.GetY()); // Y inverted

      UInt_t axisIndex = fSelectedWidget - 1; // Ugg sort out axis / widget id mapping
      TGLVector3 widgetAxis = fShape->BoundingBox().Axis(axisIndex, kTRUE);

      // Scale by projected screen factor
      TGLVector3 screenScale = camera.ViewportDeltaToWorld(fShape->BoundingBox().Center(), 500, 500);
      Double_t factor = -5.0*Dot(shift, widgetAxis) / screenScale.Mag();

      TGLVector3 newScale = fStartScale;
      newScale[axisIndex] += factor;
      LimitScale(newScale[axisIndex]);
      fShape->Scale(newScale);

      fLastMouse.SetX(event.fX);
      fLastMouse.SetY(event.fY);

      return kTRUE;
   }
   return kFALSE;
}

//______________________________________________________________________________
void TGLScaleManip::LimitScale(Double_t & factor) const
{
   // Clamp scale to sizable values: 1000 - 1/1000
   // Guards against div by zero problems.
   if (factor < 1e-4) {
      factor = 1e-4;
   }
   if (factor > 1e+4) {
      factor = 1e+4;
   }
}
 TGLScaleManip.cxx:1
 TGLScaleManip.cxx:2
 TGLScaleManip.cxx:3
 TGLScaleManip.cxx:4
 TGLScaleManip.cxx:5
 TGLScaleManip.cxx:6
 TGLScaleManip.cxx:7
 TGLScaleManip.cxx:8
 TGLScaleManip.cxx:9
 TGLScaleManip.cxx:10
 TGLScaleManip.cxx:11
 TGLScaleManip.cxx:12
 TGLScaleManip.cxx:13
 TGLScaleManip.cxx:14
 TGLScaleManip.cxx:15
 TGLScaleManip.cxx:16
 TGLScaleManip.cxx:17
 TGLScaleManip.cxx:18
 TGLScaleManip.cxx:19
 TGLScaleManip.cxx:20
 TGLScaleManip.cxx:21
 TGLScaleManip.cxx:22
 TGLScaleManip.cxx:23
 TGLScaleManip.cxx:24
 TGLScaleManip.cxx:25
 TGLScaleManip.cxx:26
 TGLScaleManip.cxx:27
 TGLScaleManip.cxx:28
 TGLScaleManip.cxx:29
 TGLScaleManip.cxx:30
 TGLScaleManip.cxx:31
 TGLScaleManip.cxx:32
 TGLScaleManip.cxx:33
 TGLScaleManip.cxx:34
 TGLScaleManip.cxx:35
 TGLScaleManip.cxx:36
 TGLScaleManip.cxx:37
 TGLScaleManip.cxx:38
 TGLScaleManip.cxx:39
 TGLScaleManip.cxx:40
 TGLScaleManip.cxx:41
 TGLScaleManip.cxx:42
 TGLScaleManip.cxx:43
 TGLScaleManip.cxx:44
 TGLScaleManip.cxx:45
 TGLScaleManip.cxx:46
 TGLScaleManip.cxx:47
 TGLScaleManip.cxx:48
 TGLScaleManip.cxx:49
 TGLScaleManip.cxx:50
 TGLScaleManip.cxx:51
 TGLScaleManip.cxx:52
 TGLScaleManip.cxx:53
 TGLScaleManip.cxx:54
 TGLScaleManip.cxx:55
 TGLScaleManip.cxx:56
 TGLScaleManip.cxx:57
 TGLScaleManip.cxx:58
 TGLScaleManip.cxx:59
 TGLScaleManip.cxx:60
 TGLScaleManip.cxx:61
 TGLScaleManip.cxx:62
 TGLScaleManip.cxx:63
 TGLScaleManip.cxx:64
 TGLScaleManip.cxx:65
 TGLScaleManip.cxx:66
 TGLScaleManip.cxx:67
 TGLScaleManip.cxx:68
 TGLScaleManip.cxx:69
 TGLScaleManip.cxx:70
 TGLScaleManip.cxx:71
 TGLScaleManip.cxx:72
 TGLScaleManip.cxx:73
 TGLScaleManip.cxx:74
 TGLScaleManip.cxx:75
 TGLScaleManip.cxx:76
 TGLScaleManip.cxx:77
 TGLScaleManip.cxx:78
 TGLScaleManip.cxx:79
 TGLScaleManip.cxx:80
 TGLScaleManip.cxx:81
 TGLScaleManip.cxx:82
 TGLScaleManip.cxx:83
 TGLScaleManip.cxx:84
 TGLScaleManip.cxx:85
 TGLScaleManip.cxx:86
 TGLScaleManip.cxx:87
 TGLScaleManip.cxx:88
 TGLScaleManip.cxx:89
 TGLScaleManip.cxx:90
 TGLScaleManip.cxx:91
 TGLScaleManip.cxx:92
 TGLScaleManip.cxx:93
 TGLScaleManip.cxx:94
 TGLScaleManip.cxx:95
 TGLScaleManip.cxx:96
 TGLScaleManip.cxx:97
 TGLScaleManip.cxx:98
 TGLScaleManip.cxx:99
 TGLScaleManip.cxx:100
 TGLScaleManip.cxx:101
 TGLScaleManip.cxx:102
 TGLScaleManip.cxx:103
 TGLScaleManip.cxx:104
 TGLScaleManip.cxx:105
 TGLScaleManip.cxx:106
 TGLScaleManip.cxx:107
 TGLScaleManip.cxx:108
 TGLScaleManip.cxx:109
 TGLScaleManip.cxx:110
 TGLScaleManip.cxx:111
 TGLScaleManip.cxx:112
 TGLScaleManip.cxx:113
 TGLScaleManip.cxx:114
 TGLScaleManip.cxx:115
 TGLScaleManip.cxx:116
 TGLScaleManip.cxx:117
 TGLScaleManip.cxx:118
 TGLScaleManip.cxx:119
 TGLScaleManip.cxx:120
 TGLScaleManip.cxx:121
 TGLScaleManip.cxx:122
 TGLScaleManip.cxx:123
 TGLScaleManip.cxx:124
 TGLScaleManip.cxx:125
 TGLScaleManip.cxx:126
 TGLScaleManip.cxx:127
 TGLScaleManip.cxx:128
 TGLScaleManip.cxx:129
 TGLScaleManip.cxx:130
 TGLScaleManip.cxx:131
 TGLScaleManip.cxx:132
 TGLScaleManip.cxx:133
 TGLScaleManip.cxx:134
 TGLScaleManip.cxx:135
 TGLScaleManip.cxx:136
 TGLScaleManip.cxx:137
 TGLScaleManip.cxx:138
 TGLScaleManip.cxx:139
 TGLScaleManip.cxx:140
 TGLScaleManip.cxx:141
 TGLScaleManip.cxx:142
 TGLScaleManip.cxx:143
 TGLScaleManip.cxx:144
 TGLScaleManip.cxx:145
 TGLScaleManip.cxx:146
 TGLScaleManip.cxx:147
 TGLScaleManip.cxx:148
 TGLScaleManip.cxx:149
 TGLScaleManip.cxx:150
 TGLScaleManip.cxx:151
 TGLScaleManip.cxx:152
 TGLScaleManip.cxx:153
 TGLScaleManip.cxx:154
 TGLScaleManip.cxx:155
 TGLScaleManip.cxx:156
 TGLScaleManip.cxx:157
 TGLScaleManip.cxx:158
 TGLScaleManip.cxx:159
 TGLScaleManip.cxx:160
 TGLScaleManip.cxx:161
 TGLScaleManip.cxx:162
 TGLScaleManip.cxx:163
 TGLScaleManip.cxx:164
 TGLScaleManip.cxx:165
 TGLScaleManip.cxx:166
 TGLScaleManip.cxx:167
 TGLScaleManip.cxx:168
 TGLScaleManip.cxx:169