/*************************************************************************
 * Copyright (C) 1995-2007, 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 "TEveLegoEventHandler.h"
#include "TEveCaloLegoGL.h"

#include "TGLViewer.h"
#include "TGLWidget.h"
#include "TGLOverlay.h"
#include "TGLLogicalShape.h"
#include "TGLPhysicalShape.h"
#include "TGLCamera.h"
#include "TGLPerspectiveCamera.h"
#include "TGLOrthoCamera.h"
#include "KeySymbols.h"

#include "TMath.h"
#include "TGLUtil.h"
#include "TEveTrans.h"

#include "TEveCalo.h"


//==============================================================================
//==============================================================================
// TEveLegoEventHandler
//==============================================================================

ClassImp(TEveLegoEventHandler);

//______________________________________________________________________________
//
// A base class of TGLEventHandler. Switches current camera from perspective
// to orthographic bird-view, if camera theta is less than given threshold. It sets back
// perspective camera when accumulated angle is more than transition theta.
//

//______________________________________________________________________________
TEveLegoEventHandler::TEveLegoEventHandler(TGWindow *w, TObject *obj, TEveCaloLego *lego):
   TGLEventHandler(w, obj),

   fMode(kFree),
   fTransTheta(0.5f),
   fTheta(0.f),

   fLego(lego)
{
   // Constructor.
}

//______________________________________________________________________________
Bool_t TEveLegoEventHandler::HandleKey(Event_t *event)
{
   // Virtual from TGLEventHandler.
   // Free the camera when home is pressed.

   if (event->fCode == kKey_Home)
      fMode = kFree;

   return TGLEventHandler::HandleKey(event);
}

//______________________________________________________________________________
Bool_t TEveLegoEventHandler::Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
{
   // Method to handle action TGLViewer::kDragCameraRotate. It switches from standard perspective
   // view to bird-view bellow angle fTransTheta and restores view when accumulated theta is larger
   // than transition angle.

   if ( !fLego ) return TGLEventHandler::Rotate(xDelta, yDelta, mod1, mod2);

   TGLCamera &cam =  fGLViewer->GetRnrCtx()->RefCamera();
   Double_t hRotate = cam.AdjustDelta(-yDelta, TMath::Pi()/cam.RefViewport().Height(), mod1, mod2);

   // get lego bounding box
   Float_t *bb = fLego->AssertBBox();
   TGLBoundingBox box;
   box.SetAligned(TGLVertex3(bb[0], bb[2], bb[4]), TGLVertex3(bb[1], bb[3], bb[5]));
   box.Transform(fLego->RefMainTrans().Array());

   Bool_t camChanged = kFALSE;

   if (cam.IsOrthographic())
   {
      fTheta += hRotate;
      if (fTheta < 0) fTheta = 0;
      if (fTheta > fTransTheta)
      {
         TGLCamera* ortho = &cam;
         Double_t l = -ortho->FrustumPlane(TGLCamera::kLeft).D();
         Double_t r =  ortho->FrustumPlane(TGLCamera::kRight).D();
         Double_t t =  ortho->FrustumPlane(TGLCamera::kTop).D();
         Double_t b = -ortho->FrustumPlane(TGLCamera::kBottom).D();

         fGLViewer->SetCurrentCamera(TGLViewer::kCameraPerspXOY);
         TGLPerspectiveCamera* persp = dynamic_cast<TGLPerspectiveCamera*>(&fGLViewer->GetRnrCtx()->RefCamera());
         persp->Setup(box, kTRUE);

         TGLVector3 extents = box.Extents();
         Int_t sortInd[3];
         TMath::Sort(3, extents.CArr(), sortInd);
         Double_t size = TMath::Hypot(extents[sortInd[0]], extents[sortInd[1]]);
         Double_t dolly  = size / (2.0*TMath::Tan(30*TMath::Pi()/360));
         Double_t fov = TMath::ATan(TMath::Hypot(t-b, r-l)/(2*dolly));

         persp->SetCenterVecWarp(0.5*(l+r), 0.5*(t+b), 0);

         Double_t vR =  -0.5 * TMath::Pi(); // switch XY
         Double_t hR =  -0.5 * TMath::Pi() + fTransTheta; // fix top view angle
         persp->Configure(fov*TMath::RadToDeg(), 0, 0, hR, vR);

         fMode = kFree;
         camChanged = kTRUE;
      }
   }
   else
   {
      Double_t theta  = cam.GetTheta();
      Double_t thetaN = theta + hRotate;
      if (thetaN > TMath::Pi() - cam.GetVAxisMinAngle()) thetaN = TMath::Pi() - cam.GetVAxisMinAngle();
      else if (thetaN < cam.GetVAxisMinAngle())   thetaN = cam.GetVAxisMinAngle();

      fTheta = thetaN;

      if (thetaN < fTransTheta)
      {
         TGLPerspectiveCamera* persp =  (TGLPerspectiveCamera*)(&cam);
         fGLViewer->SetCurrentCamera(TGLViewer::kCameraOrthoXOY);
         TGLOrthoCamera* ortho = dynamic_cast<TGLOrthoCamera*>(& fGLViewer->GetRnrCtx()->RefCamera());
         ortho->Setup(box,  kTRUE);

         // translation to the plane intersect
         const TGLMatrix& mx =  cam.GetCamBase() * cam.GetCamTrans();
         TGLVertex3 d   = mx.GetTranslation();
         TGLVertex3 p = d + mx.GetBaseVec(1);
         TGLLine3  line(d, p);
         const TGLPlane rp = TGLPlane(cam.GetCamBase().GetBaseVec(3), TGLVertex3());
         std::pair<Bool_t, TGLVertex3> intersection;
         intersection = Intersection(rp, line, kTRUE);
         TGLVertex3 v = intersection.second;
         ortho->Truck( v.X() - box.Center().X(), v.Y() - box.Center().Y());

         // zoom
         Double_t t =  persp->FrustumPlane(TGLCamera::kTop).D();
         Double_t b = -persp->FrustumPlane(TGLCamera::kBottom).D();
         Double_t zoom = box.Extents().Y()/(t-b);
         ortho->Configure(zoom, 0, 0, 0, 0);

         fMode = kLocked;
         camChanged = kTRUE;
      }
      else
      {
         camChanged = fGLViewer->CurrentCamera().Rotate(xDelta, -yDelta, mod1, mod2);
      }
   }
   return camChanged;
}
 TEveLegoEventHandler.cxx:1
 TEveLegoEventHandler.cxx:2
 TEveLegoEventHandler.cxx:3
 TEveLegoEventHandler.cxx:4
 TEveLegoEventHandler.cxx:5
 TEveLegoEventHandler.cxx:6
 TEveLegoEventHandler.cxx:7
 TEveLegoEventHandler.cxx:8
 TEveLegoEventHandler.cxx:9
 TEveLegoEventHandler.cxx:10
 TEveLegoEventHandler.cxx:11
 TEveLegoEventHandler.cxx:12
 TEveLegoEventHandler.cxx:13
 TEveLegoEventHandler.cxx:14
 TEveLegoEventHandler.cxx:15
 TEveLegoEventHandler.cxx:16
 TEveLegoEventHandler.cxx:17
 TEveLegoEventHandler.cxx:18
 TEveLegoEventHandler.cxx:19
 TEveLegoEventHandler.cxx:20
 TEveLegoEventHandler.cxx:21
 TEveLegoEventHandler.cxx:22
 TEveLegoEventHandler.cxx:23
 TEveLegoEventHandler.cxx:24
 TEveLegoEventHandler.cxx:25
 TEveLegoEventHandler.cxx:26
 TEveLegoEventHandler.cxx:27
 TEveLegoEventHandler.cxx:28
 TEveLegoEventHandler.cxx:29
 TEveLegoEventHandler.cxx:30
 TEveLegoEventHandler.cxx:31
 TEveLegoEventHandler.cxx:32
 TEveLegoEventHandler.cxx:33
 TEveLegoEventHandler.cxx:34
 TEveLegoEventHandler.cxx:35
 TEveLegoEventHandler.cxx:36
 TEveLegoEventHandler.cxx:37
 TEveLegoEventHandler.cxx:38
 TEveLegoEventHandler.cxx:39
 TEveLegoEventHandler.cxx:40
 TEveLegoEventHandler.cxx:41
 TEveLegoEventHandler.cxx:42
 TEveLegoEventHandler.cxx:43
 TEveLegoEventHandler.cxx:44
 TEveLegoEventHandler.cxx:45
 TEveLegoEventHandler.cxx:46
 TEveLegoEventHandler.cxx:47
 TEveLegoEventHandler.cxx:48
 TEveLegoEventHandler.cxx:49
 TEveLegoEventHandler.cxx:50
 TEveLegoEventHandler.cxx:51
 TEveLegoEventHandler.cxx:52
 TEveLegoEventHandler.cxx:53
 TEveLegoEventHandler.cxx:54
 TEveLegoEventHandler.cxx:55
 TEveLegoEventHandler.cxx:56
 TEveLegoEventHandler.cxx:57
 TEveLegoEventHandler.cxx:58
 TEveLegoEventHandler.cxx:59
 TEveLegoEventHandler.cxx:60
 TEveLegoEventHandler.cxx:61
 TEveLegoEventHandler.cxx:62
 TEveLegoEventHandler.cxx:63
 TEveLegoEventHandler.cxx:64
 TEveLegoEventHandler.cxx:65
 TEveLegoEventHandler.cxx:66
 TEveLegoEventHandler.cxx:67
 TEveLegoEventHandler.cxx:68
 TEveLegoEventHandler.cxx:69
 TEveLegoEventHandler.cxx:70
 TEveLegoEventHandler.cxx:71
 TEveLegoEventHandler.cxx:72
 TEveLegoEventHandler.cxx:73
 TEveLegoEventHandler.cxx:74
 TEveLegoEventHandler.cxx:75
 TEveLegoEventHandler.cxx:76
 TEveLegoEventHandler.cxx:77
 TEveLegoEventHandler.cxx:78
 TEveLegoEventHandler.cxx:79
 TEveLegoEventHandler.cxx:80
 TEveLegoEventHandler.cxx:81
 TEveLegoEventHandler.cxx:82
 TEveLegoEventHandler.cxx:83
 TEveLegoEventHandler.cxx:84
 TEveLegoEventHandler.cxx:85
 TEveLegoEventHandler.cxx:86
 TEveLegoEventHandler.cxx:87
 TEveLegoEventHandler.cxx:88
 TEveLegoEventHandler.cxx:89
 TEveLegoEventHandler.cxx:90
 TEveLegoEventHandler.cxx:91
 TEveLegoEventHandler.cxx:92
 TEveLegoEventHandler.cxx:93
 TEveLegoEventHandler.cxx:94
 TEveLegoEventHandler.cxx:95
 TEveLegoEventHandler.cxx:96
 TEveLegoEventHandler.cxx:97
 TEveLegoEventHandler.cxx:98
 TEveLegoEventHandler.cxx:99
 TEveLegoEventHandler.cxx:100
 TEveLegoEventHandler.cxx:101
 TEveLegoEventHandler.cxx:102
 TEveLegoEventHandler.cxx:103
 TEveLegoEventHandler.cxx:104
 TEveLegoEventHandler.cxx:105
 TEveLegoEventHandler.cxx:106
 TEveLegoEventHandler.cxx:107
 TEveLegoEventHandler.cxx:108
 TEveLegoEventHandler.cxx:109
 TEveLegoEventHandler.cxx:110
 TEveLegoEventHandler.cxx:111
 TEveLegoEventHandler.cxx:112
 TEveLegoEventHandler.cxx:113
 TEveLegoEventHandler.cxx:114
 TEveLegoEventHandler.cxx:115
 TEveLegoEventHandler.cxx:116
 TEveLegoEventHandler.cxx:117
 TEveLegoEventHandler.cxx:118
 TEveLegoEventHandler.cxx:119
 TEveLegoEventHandler.cxx:120
 TEveLegoEventHandler.cxx:121
 TEveLegoEventHandler.cxx:122
 TEveLegoEventHandler.cxx:123
 TEveLegoEventHandler.cxx:124
 TEveLegoEventHandler.cxx:125
 TEveLegoEventHandler.cxx:126
 TEveLegoEventHandler.cxx:127
 TEveLegoEventHandler.cxx:128
 TEveLegoEventHandler.cxx:129
 TEveLegoEventHandler.cxx:130
 TEveLegoEventHandler.cxx:131
 TEveLegoEventHandler.cxx:132
 TEveLegoEventHandler.cxx:133
 TEveLegoEventHandler.cxx:134
 TEveLegoEventHandler.cxx:135
 TEveLegoEventHandler.cxx:136
 TEveLegoEventHandler.cxx:137
 TEveLegoEventHandler.cxx:138
 TEveLegoEventHandler.cxx:139
 TEveLegoEventHandler.cxx:140
 TEveLegoEventHandler.cxx:141
 TEveLegoEventHandler.cxx:142
 TEveLegoEventHandler.cxx:143
 TEveLegoEventHandler.cxx:144
 TEveLegoEventHandler.cxx:145
 TEveLegoEventHandler.cxx:146
 TEveLegoEventHandler.cxx:147
 TEveLegoEventHandler.cxx:148
 TEveLegoEventHandler.cxx:149
 TEveLegoEventHandler.cxx:150
 TEveLegoEventHandler.cxx:151
 TEveLegoEventHandler.cxx:152
 TEveLegoEventHandler.cxx:153
 TEveLegoEventHandler.cxx:154
 TEveLegoEventHandler.cxx:155
 TEveLegoEventHandler.cxx:156
 TEveLegoEventHandler.cxx:157
 TEveLegoEventHandler.cxx:158
 TEveLegoEventHandler.cxx:159
 TEveLegoEventHandler.cxx:160
 TEveLegoEventHandler.cxx:161
 TEveLegoEventHandler.cxx:162
 TEveLegoEventHandler.cxx:163
 TEveLegoEventHandler.cxx:164