#include "TGLAutoRotator.h"
#include "TGLViewer.h"
#include "TGLCamera.h"
#include "TMath.h"
#include "TTimer.h"
#include "TStopwatch.h"
ClassImp(TGLAutoRotator);
TGLAutoRotator::TGLAutoRotator(TGLViewer* v) :
fViewer(v), fCamera(0),
fTimer(new TTimer), fWatch(new TStopwatch),
fDt (0.01),
fWPhi (0.40),
fWTheta(0.15), fATheta(0.5),
fWDolly(0.30), fADolly(0.4),
fTimerRunning(kFALSE),
fImageCount(0), fImageAutoSave(kFALSE),
fImageGUIBaseName("animation"), fImageGUIOutMode(1)
{
fTimer->Connect("Timeout()", "TGLAutoRotator", this, "Timeout()");
}
TGLAutoRotator::~TGLAutoRotator()
{
delete fWatch;
delete fTimer;
}
void TGLAutoRotator::SetDt(Double_t dt)
{
fDt = TMath::Range(0.01, 1.0, dt);
if (fTimerRunning)
{
fTimer->SetTime(TMath::Nint(1000*fDt));
fTimer->Reset();
}
}
void TGLAutoRotator::SetATheta(Double_t a)
{
a = TMath::Range(0.01, 1.0, a);
if (fTimerRunning)
{
fThetaA0 = fThetaA0 * a / fATheta;
}
fATheta = a;
}
void TGLAutoRotator::SetADolly(Double_t a)
{
a = TMath::Range(0.01, 1.0, a);
if (fTimerRunning)
{
fDollyA0 = fDollyA0 * a / fADolly;
}
fADolly = a;
}
void TGLAutoRotator::Start()
{
if (fTimerRunning)
{
Stop();
}
fCamera = & fViewer->CurrentCamera();
fThetaA0 = fATheta * TMath::PiOver2();
fDollyA0 = fADolly * fCamera->GetCamTrans().GetBaseVec(4).Mag();
fTimerRunning = kTRUE;
fTimer->SetTime(TMath::Nint(1000*fDt));
fTimer->Reset();
fTimer->TurnOn();
fWatch->Start();
}
void TGLAutoRotator::Stop()
{
if (fTimerRunning)
{
fWatch->Stop();
fTimer->TurnOff();
fTimerRunning = kFALSE;
}
}
void TGLAutoRotator::Timeout()
{
if (!fTimerRunning || gTQSender != fTimer)
{
Error("Timeout", "Not running or not called via timer.");
return;
}
using namespace TMath;
fWatch->Stop();
Double_t time = fWatch->RealTime();
fWatch->Continue();
Double_t delta_p = fWPhi*fDt;
Double_t delta_t = fThetaA0*fWTheta*Cos(fWTheta*time)*fDt;
Double_t delta_d = fDollyA0*fWDolly*Cos(fWDolly*time)*fDt;
Double_t th = fCamera->GetTheta();
if (th + delta_t > 3.0 || th + delta_t < 0.1416)
delta_t = 0;
fCamera->RotateRad(delta_t, delta_p);
fCamera->RefCamTrans().MoveLF(1, -delta_d);
fViewer->RequestDraw(TGLRnrCtx::kLODHigh);
if (fImageAutoSave)
{
TString filename;
if (fImageName.Contains("%"))
{
filename.Form(fImageName, fImageCount);
}
else
{
filename = fImageName;
}
fViewer->SavePicture(filename);
++fImageCount;
}
}
void TGLAutoRotator::StartImageAutoSaveAnimatedGif(const TString& filename)
{
if ( ! filename.Contains(".gif+"))
{
Error("StartImageAutoSaveAnimatedGif", "Name should end with '.gif+'. Not starting.");
return;
}
fImageName = filename;
fImageCount = 0;
fImageAutoSave = kTRUE;
}
void TGLAutoRotator::StartImageAutoSave(const TString& filename)
{
if ( ! filename.Contains("%"))
{
Error("StartImageAutoSave", "Name should include a '%%' character, like 'image-%%05d.png'. Not starting.");
return;
}
fImageName = filename;
fImageCount = 0;
fImageAutoSave = kTRUE;
}
void TGLAutoRotator::StopImageAutoSave()
{
fImageAutoSave = kFALSE;
}
void TGLAutoRotator::SetImageGUIOutMode(Int_t m)
{
if (m < 1 || m > 2)
{
Warning("SetImageGUIOutMode", "Invalid value, ignoring");
return;
}
fImageGUIOutMode = m;
}
void TGLAutoRotator::StartImageAutoSaveWithGUISettings()
{
if (fImageGUIOutMode == 1)
{
TString name = fImageGUIBaseName + ".gif+";
StartImageAutoSaveAnimatedGif(name);
}
else if (fImageGUIOutMode == 2)
{
TString name = fImageGUIBaseName + "-%05d.png";
StartImageAutoSave(name);
}
else
{
Warning("StartImageAutoSaveWithGUISettings", "Unsupported mode '%d'.", fImageGUIOutMode);
}
}