#include "TGLViewer.h"
#include "TGLIncludes.h"
#include "TGLStopwatch.h"
#include "TGLRnrCtx.h"
#include "TGLSelectBuffer.h"
#include "TGLLightSet.h"
#include "TGLManipSet.h"
#include "TGLCameraOverlay.h"
#include "TGLAutoRotator.h"
#include "TGLScenePad.h"
#include "TGLLogicalShape.h"
#include "TGLPhysicalShape.h"
#include "TGLObject.h"
#include "TGLStopwatch.h"
#include "TBuffer3D.h"
#include "TBuffer3DTypes.h"
#include "TGLOutput.h"
#include "TVirtualPad.h"
#include "TVirtualX.h"
#include "TMath.h"
#include "TColor.h"
#include "TError.h"
#include "TClass.h"
#include "TROOT.h"
#include "TEnv.h"
#include "Buttons.h"
#include "GuiTypes.h"
#include "TVirtualGL.h"
#include "TGLWidget.h"
#include "TGLFBO.h"
#include "TGLViewerEditor.h"
#include "TGedEditor.h"
#include "TGLPShapeObj.h"
#include "KeySymbols.h"
#include "TContextMenu.h"
#include "TImage.h"
#include <stdexcept>
#ifndef GL_BGRA
#define GL_BGRA GL_BGRA_EXT
#endif
ClassImp(TGLViewer);
TGLColorSet TGLViewer::fgDefaultColorSet;
Bool_t TGLViewer::fgUseDefaultColorSetForNewViewers = kFALSE;
TGLViewer::TGLViewer(TVirtualPad * pad, Int_t x, Int_t y,
Int_t width, Int_t height) :
fPad(pad),
fContextMenu(0),
fPerspectiveCameraXOZ(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)),
fPerspectiveCameraYOZ(TGLVector3( 0.0,-1.0, 0.0), TGLVector3(1.0, 0.0, 0.0)),
fPerspectiveCameraXOY(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 0.0, 1.0)),
fOrthoXOYCamera (TGLOrthoCamera::kXOY, TGLVector3( 0.0, 0.0, 1.0), TGLVector3(0.0, 1.0, 0.0)),
fOrthoXOZCamera (TGLOrthoCamera::kXOZ, TGLVector3( 0.0,-1.0, 0.0), TGLVector3(0.0, 0.0, 1.0)),
fOrthoZOYCamera (TGLOrthoCamera::kZOY, TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)),
fOrthoXnOYCamera(TGLOrthoCamera::kXnOY, TGLVector3( 0.0, 0.0,-1.0), TGLVector3(0.0, 1.0, 0.0)),
fOrthoXnOZCamera(TGLOrthoCamera::kXnOZ, TGLVector3( 0.0, 1.0, 0.0), TGLVector3(0.0, 0.0, 1.0)),
fOrthoZnOYCamera(TGLOrthoCamera::kZnOY, TGLVector3( 1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)),
fCurrentCamera(&fPerspectiveCameraXOZ),
fAutoRotator(0),
fStereo (kFALSE),
fStereoZeroParallax (0.03f),
fStereoEyeOffsetFac (1.0f),
fStereoFrustumAsymFac (1.0f),
fLightSet (0),
fClipSet (0),
fSelectedPShapeRef (0),
fCurrentOvlElm (0),
fEventHandler(0),
fGedEditor(0),
fPShapeWrap(0),
fPushAction(kPushStd), fDragAction(kDragNone),
fRedrawTimer(0),
fMaxSceneDrawTimeHQ(5000),
fMaxSceneDrawTimeLQ(100),
fPointScale (1), fLineScale(1), fSmoothPoints(kFALSE), fSmoothLines(kFALSE),
fAxesType(TGLUtil::kAxesNone),
fAxesDepthTest(kTRUE),
fReferenceOn(kFALSE),
fReferencePos(0.0, 0.0, 0.0),
fDrawCameraCenter(kFALSE),
fCameraOverlay(0),
fSmartRefresh(kFALSE),
fDebugMode(kFALSE),
fIsPrinting(kFALSE),
fPictureFileName("viewer.jpg"),
fFader(0),
fGLWidget(0),
fGLDevice(-1),
fGLCtxId(0),
fIgnoreSizesOnUpdate(kFALSE),
fResetCamerasOnUpdate(kTRUE),
fResetCamerasOnNextUpdate(kFALSE)
{
InitSecondaryObjects();
SetViewport(x, y, width, height);
}
TGLViewer::TGLViewer(TVirtualPad * pad) :
fPad(pad),
fContextMenu(0),
fPerspectiveCameraXOZ(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)),
fPerspectiveCameraYOZ(TGLVector3( 0.0,-1.0, 0.0), TGLVector3(1.0, 0.0, 0.0)),
fPerspectiveCameraXOY(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 0.0, 1.0)),
fOrthoXOYCamera (TGLOrthoCamera::kXOY, TGLVector3( 0.0, 0.0, 1.0), TGLVector3(0.0, 1.0, 0.0)),
fOrthoXOZCamera (TGLOrthoCamera::kXOZ, TGLVector3( 0.0,-1.0, 0.0), TGLVector3(0.0, 0.0, 1.0)),
fOrthoZOYCamera (TGLOrthoCamera::kZOY, TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)),
fOrthoXnOYCamera(TGLOrthoCamera::kXnOY, TGLVector3( 0.0, 0.0,-1.0), TGLVector3(0.0, 1.0, 0.0)),
fOrthoXnOZCamera(TGLOrthoCamera::kXnOZ, TGLVector3( 0.0, 1.0, 0.0), TGLVector3(0.0, 0.0, 1.0)),
fOrthoZnOYCamera(TGLOrthoCamera::kZnOY, TGLVector3( 1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)),
fCurrentCamera(&fPerspectiveCameraXOZ),
fAutoRotator(0),
fStereo (kFALSE),
fStereoZeroParallax (0.03f),
fStereoEyeOffsetFac (1.0f),
fStereoFrustumAsymFac (1.0f),
fLightSet (0),
fClipSet (0),
fSelectedPShapeRef (0),
fCurrentOvlElm (0),
fEventHandler(0),
fGedEditor(0),
fPShapeWrap(0),
fPushAction(kPushStd), fDragAction(kDragNone),
fRedrawTimer(0),
fMaxSceneDrawTimeHQ(5000),
fMaxSceneDrawTimeLQ(100),
fPointScale (1), fLineScale(1), fSmoothPoints(kFALSE), fSmoothLines(kFALSE),
fAxesType(TGLUtil::kAxesNone),
fAxesDepthTest(kTRUE),
fReferenceOn(kFALSE),
fReferencePos(0.0, 0.0, 0.0),
fDrawCameraCenter(kFALSE),
fCameraOverlay(0),
fSmartRefresh(kFALSE),
fDebugMode(kFALSE),
fIsPrinting(kFALSE),
fPictureFileName("viewer.jpg"),
fFader(0),
fGLWidget(0),
fGLDevice(fPad->GetGLDevice()),
fGLCtxId(0),
fIgnoreSizesOnUpdate(kFALSE),
fResetCamerasOnUpdate(kTRUE),
fResetCamerasOnNextUpdate(kFALSE)
{
InitSecondaryObjects();
if (fGLDevice != -1) {
fGLCtxId = new TGLContextIdentity;
fGLCtxId->AddRef(0);
Int_t viewport[4] = {0};
gGLManager->ExtractViewport(fGLDevice, viewport);
SetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
}
void TGLViewer::InitSecondaryObjects()
{
fLightSet = new TGLLightSet;
fClipSet = new TGLClipSet;
AddOverlayElement(fClipSet);
fSelectedPShapeRef = new TGLManipSet;
fSelectedPShapeRef->SetDrawBBox(kTRUE);
AddOverlayElement(fSelectedPShapeRef);
fPShapeWrap = new TGLPShapeObj(0, this);
fLightColorSet.StdLightBackground();
if (fgUseDefaultColorSetForNewViewers) {
fRnrCtx->ChangeBaseColorSet(&fgDefaultColorSet);
} else {
if (fPad) {
fRnrCtx->ChangeBaseColorSet(&fLightColorSet);
fLightColorSet.Background().SetColor(fPad->GetFillColor());
fLightColorSet.Foreground().SetColor(fPad->GetLineColor());
} else {
fRnrCtx->ChangeBaseColorSet(&fDarkColorSet);
}
}
fCameraOverlay = new TGLCameraOverlay(kFALSE, kFALSE);
AddOverlayElement(fCameraOverlay);
fRedrawTimer = new TGLRedrawTimer(*this);
}
TGLViewer::~TGLViewer()
{
delete fAutoRotator;
delete fLightSet;
delete fContextMenu;
delete fRedrawTimer;
if (fEventHandler) {
if (fGLWidget)
fGLWidget->SetEventHandler(0);
delete fEventHandler;
}
if (fPad)
fPad->ReleaseViewer3D();
if (fGLDevice != -1)
fGLCtxId->Release(0);
}
void TGLViewer::PadPaint(TVirtualPad* pad)
{
TGLScenePad* scenepad = 0;
for (SceneInfoList_i si = fScenes.begin(); si != fScenes.end(); ++si)
{
scenepad = dynamic_cast<TGLScenePad*>((*si)->GetScene());
if (scenepad && scenepad->GetPad() == pad)
break;
scenepad = 0;
}
if (scenepad == 0)
{
scenepad = new TGLScenePad(pad);
AddScene(scenepad);
}
scenepad->PadPaintFromViewer(this);
PostSceneBuildSetup(fResetCamerasOnNextUpdate || fResetCamerasOnUpdate);
fResetCamerasOnNextUpdate = kFALSE;
RequestDraw();
}
void TGLViewer::UpdateScene(Bool_t redraw)
{
fRedrawTimer->Stop();
for (SceneInfoList_i si = fScenes.begin(); si != fScenes.end(); ++si)
{
TGLScenePad* scenepad = dynamic_cast<TGLScenePad*>((*si)->GetScene());
if (scenepad)
scenepad->PadPaintFromViewer(this);
}
PostSceneBuildSetup(fResetCamerasOnNextUpdate || fResetCamerasOnUpdate);
fResetCamerasOnNextUpdate = kFALSE;
if (redraw)
RequestDraw();
}
void TGLViewer::ResetCurrentCamera()
{
MergeSceneBBoxes(fOverallBoundingBox);
CurrentCamera().Setup(fOverallBoundingBox, kTRUE);
}
void TGLViewer::SetupCameras(Bool_t reset)
{
if (IsLocked()) {
Error("TGLViewer::SetupCameras", "expected kUnlocked, found %s", LockName(CurrentLock()));
return;
}
const TGLBoundingBox & box = fOverallBoundingBox;
if (!box.IsEmpty()) {
fPerspectiveCameraYOZ.Setup(box, reset);
fPerspectiveCameraXOZ.Setup(box, reset);
fPerspectiveCameraXOY.Setup(box, reset);
fOrthoXOYCamera.Setup(box, reset);
fOrthoXOZCamera.Setup(box, reset);
fOrthoZOYCamera.Setup(box, reset);
fOrthoXnOYCamera.Setup(box, reset);
fOrthoXnOZCamera.Setup(box, reset);
fOrthoZnOYCamera.Setup(box, reset);
}
}
void TGLViewer::PostSceneBuildSetup(Bool_t resetCameras)
{
MergeSceneBBoxes(fOverallBoundingBox);
SetupCameras(resetCameras);
fReferencePos.Set(fOverallBoundingBox.Center());
RefreshPadEditor(this);
}
void TGLViewer::InitGL()
{
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glClearColor(0.f, 0.f, 0.f, 0.f);
glClearDepth(1.0);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glMaterialf(GL_BACK, GL_SHININESS, 0.0);
glPolygonMode(GL_FRONT, GL_FILL);
glDisable(GL_BLEND);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
Float_t lmodelAmb[] = {0.5f, 0.5f, 1.f, 1.f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodelAmb);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
TGLUtil::CheckError("TGLViewer::InitGL");
}
void TGLViewer::RequestDraw(Short_t LODInput)
{
fRedrawTimer->Stop();
if ((!fGLWidget && fGLDevice == -1) || (fGLWidget && !fGLWidget->IsMapped()))
{
return;
}
if ( ! TakeLock(kDrawLock)) {
if (gDebug>3) {
Info("TGLViewer::RequestDraw", "viewer locked - requesting another draw.");
}
fRedrawTimer->RequestDraw(100, LODInput);
return;
}
fLOD = LODInput;
if (!gVirtualX->IsCmdThread())
gROOT->ProcessLineFast(Form("((TGLViewer *)0x%lx)->DoDraw()", (ULong_t)this));
else
DoDraw();
}
void TGLViewer::SetupClipObject()
{
if (GetClipAutoUpdate())
{
fClipSet->SetupCurrentClip(fOverallBoundingBox);
}
else
{
fClipSet->SetupCurrentClipIfInvalid(fOverallBoundingBox);
}
}
void TGLViewer::PreRender()
{
fCamera = fCurrentCamera;
fClip = fClipSet->GetCurrentClip();
if (fGLDevice != -1)
{
fRnrCtx->SetGLCtxIdentity(fGLCtxId);
fGLCtxId->DeleteGLResources();
}
TGLUtil::SetPointSizeScale(fPointScale * fRnrCtx->GetRenderScale());
TGLUtil::SetLineWidthScale(fLineScale * fRnrCtx->GetRenderScale());
if (fSmoothPoints) glEnable(GL_POINT_SMOOTH); else glDisable(GL_POINT_SMOOTH);
if (fSmoothLines) glEnable(GL_LINE_SMOOTH); else glDisable(GL_LINE_SMOOTH);
if (fSmoothPoints || fSmoothLines)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
}
else
{
glDisable(GL_BLEND);
}
TGLViewerBase::PreRender();
fLightSet->StdSetupLights(fOverallBoundingBox, *fCamera, fDebugMode);
}
void TGLViewer::Render()
{
TGLViewerBase::Render();
DrawGuides();
RenderOverlay(TGLOverlayElement::kAllVisible, kFALSE);
if ( ! fRnrCtx->Selection())
{
RenderSelectedForHighlight();
}
glClear(GL_DEPTH_BUFFER_BIT);
DrawDebugInfo();
}
void TGLViewer::PostRender()
{
TGLViewerBase::PostRender();
TGLUtil::SetPointSizeScale(1);
TGLUtil::SetLineWidthScale(1);
}
void TGLViewer::DoDraw(Bool_t swap_buffers)
{
fRedrawTimer->Stop();
if (CurrentLock() != kDrawLock) {
if ( ! TakeLock(kDrawLock)) {
Error("TGLViewer::DoDraw", "viewer is %s", LockName(CurrentLock()));
return;
}
}
TUnlocker ulck(this);
if (fGLDevice == -1 && (fViewport.Width() <= 1 || fViewport.Height() <= 1)) {
if (gDebug > 2) {
Info("TGLViewer::DoDraw()", "zero surface area, draw skipped.");
}
return;
}
if (fGLDevice != -1) {
Int_t viewport[4] = {};
gGLManager->ExtractViewport(fGLDevice, viewport);
SetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
TGLStopwatch timer;
if (gDebug>2) {
timer.Start();
}
fRnrCtx->SetRenderTimeOut(fLOD == TGLRnrCtx::kLODHigh ?
fMaxSceneDrawTimeHQ :
fMaxSceneDrawTimeLQ);
if (fStereo && fCurrentCamera->IsPerspective() && !fRnrCtx->GetGrabImage() &&
!fIsPrinting)
{
DoDrawStereo(swap_buffers);
}
else
{
DoDrawMono(swap_buffers);
}
ReleaseLock(kDrawLock);
if (gDebug>2) {
Info("TGLViewer::DoDraw()", "Took %f msec", timer.End());
}
if (CurrentCamera().UpdateInterest(kFALSE)) {
ResetSceneInfos();
fRedrawTimer->RequestDraw(0, fLOD);
}
if (fLOD != TGLRnrCtx::kLODHigh &&
(fDragAction < kDragCameraRotate || fDragAction > kDragCameraDolly))
{
fRedrawTimer->RequestDraw(100, TGLRnrCtx::kLODHigh);
}
}
void TGLViewer::DoDrawMono(Bool_t swap_buffers)
{
MakeCurrent();
if (!fIsPrinting) PreDraw();
PreRender();
fRnrCtx->StartStopwatch();
if (fFader < 1)
{
Render();
}
fRnrCtx->StopStopwatch();
PostRender();
if (fFader > 0)
{
FadeView(fFader);
}
PostDraw();
if (swap_buffers)
{
SwapBuffers();
}
}
void TGLViewer::DoDrawStereo(Bool_t swap_buffers)
{
TGLPerspectiveCamera &c = *dynamic_cast<TGLPerspectiveCamera*>(fCurrentCamera);
Float_t gl_near, gl_far, zero_p_dist;
Float_t h_half, w_half;
Float_t x_len_at_zero_parallax;
Float_t stereo_offset;
Float_t frustum_asym;
MakeCurrent();
glDrawBuffer(GL_BACK_LEFT);
PreDraw();
PreRender();
gl_near = c.GetNearClip();
gl_far = c.GetFarClip();
zero_p_dist = gl_near + fStereoZeroParallax*(gl_far-gl_near);
h_half = TMath::Tan(0.5*TMath::DegToRad()*c.GetFOV()) * gl_near;
w_half = h_half * fViewport.Aspect();
x_len_at_zero_parallax = 2.0f * w_half * zero_p_dist / gl_near;
stereo_offset = 0.035f * x_len_at_zero_parallax * fStereoEyeOffsetFac;
frustum_asym = stereo_offset * gl_near / zero_p_dist * fStereoFrustumAsymFac;
TGLMatrix abs_trans(c.RefCamBase());
abs_trans *= c.RefCamTrans();
TGLVector3 left_vec = abs_trans.GetBaseVec(2);
glTranslatef(stereo_offset*left_vec[0], stereo_offset*left_vec[1], stereo_offset*left_vec[2]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-w_half + frustum_asym, w_half + frustum_asym,
-h_half, h_half, gl_near, gl_far);
glMatrixMode(GL_MODELVIEW);
fRnrCtx->StartStopwatch();
if (fFader < 1)
{
Render();
}
fRnrCtx->StopStopwatch();
PostRender();
if (fFader > 0)
{
FadeView(fFader);
}
PostDraw();
glDrawBuffer(GL_BACK_RIGHT);
PreDraw();
PreRender();
glTranslatef(-stereo_offset*left_vec[0], -stereo_offset*left_vec[1], -stereo_offset*left_vec[2]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-w_half - frustum_asym, w_half - frustum_asym,
-h_half, h_half, gl_near, gl_far);
glMatrixMode(GL_MODELVIEW);
fRnrCtx->StartStopwatch();
if (fFader < 1)
{
Render();
}
fRnrCtx->StopStopwatch();
PostRender();
if (fFader > 0)
{
FadeView(fFader);
}
PostDraw();
if (swap_buffers)
{
SwapBuffers();
}
glDrawBuffer(GL_BACK);
}
Bool_t TGLViewer::SavePicture()
{
return SavePicture(fPictureFileName);
}
Bool_t TGLViewer::SavePicture(const TString &fileName)
{
if (fileName.EndsWith(".eps"))
{
return TGLOutput::Capture(*this, TGLOutput::kEPS_BSP, fileName.Data());
}
else if (fileName.EndsWith(".pdf"))
{
return TGLOutput::Capture(*this, TGLOutput::kPDF_BSP, fileName.Data());
}
else
{
if (GLEW_EXT_framebuffer_object && gEnv->GetValue("OpenGL.SavePicturesViaFBO", 1))
{
return SavePictureUsingFBO(fileName, fViewport.Width(), fViewport.Height(), kFALSE);
}
else
{
return SavePictureUsingBB(fileName);
}
}
}
Bool_t TGLViewer::SavePictureUsingBB(const TString &fileName)
{
static const TString eh("TGLViewer::SavePictureUsingBB");
if (! fileName.EndsWith(".gif") && ! fileName.Contains(".gif+") &&
! fileName.EndsWith(".jpg") && ! fileName.EndsWith(".png"))
{
Warning(eh, "file %s cannot be saved with this extension.", fileName.Data());
return kFALSE;
}
if ( ! TakeLock(kDrawLock)) {
Error(eh, "viewer locked - try later.");
return kFALSE;
}
TUnlocker ulck(this);
fLOD = TGLRnrCtx::kLODHigh;
fRnrCtx->SetGrabImage(kTRUE);
if (!gVirtualX->IsCmdThread())
gROOT->ProcessLineFast(Form("((TGLViewer *)0x%lx)->DoDraw(kFALSE)", (ULong_t)this));
else
DoDraw(kFALSE);
fRnrCtx->SetGrabImage(kFALSE);
glReadBuffer(GL_BACK);
UChar_t* xx = new UChar_t[4 * fViewport.Width() * fViewport.Height()];
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, fViewport.Width(), fViewport.Height(),
GL_BGRA, GL_UNSIGNED_BYTE, xx);
std::auto_ptr<TImage> image(TImage::Create());
image->FromGLBuffer(xx, fViewport.Width(), fViewport.Height());
image->WriteImage(fileName);
delete [] xx;
return kTRUE;
}
Bool_t TGLViewer::SavePictureUsingFBO(const TString &fileName, Int_t w, Int_t h,
Float_t pixel_object_scale)
{
static const TString eh("TGLViewer::SavePictureUsingFBO");
if (! fileName.EndsWith(".gif") && ! fileName.Contains(".gif+") &&
! fileName.EndsWith(".jpg") && ! fileName.EndsWith(".png"))
{
Warning(eh, "file %s cannot be saved with this extension.", fileName.Data());
return kFALSE;
}
if ( ! TakeLock(kDrawLock)) {
Error(eh, "viewer locked - try later.");
return kFALSE;
}
TUnlocker ulck(this);
MakeCurrent();
TGLFBO *fbo = new TGLFBO();
try
{
fbo->Init(w, h, fGLWidget->GetPixelFormat()->GetSamples());
}
catch (std::runtime_error& exc)
{
Error(eh, "%s",exc.what());
if (gEnv->GetValue("OpenGL.SavePictureFallbackToBB", 1)) {
Info(eh, "Falling back to saving image via back-buffer. Window must be fully visible.");
if (w != fViewport.Width() || h != fViewport.Height())
Warning(eh, "Back-buffer does not support image scaling, window size will be used.");
return SavePictureUsingBB(fileName);
} else {
return kFALSE;
}
}
TGLRect old_vp(fViewport);
SetViewport(0, 0, w, h);
Float_t old_scale = 1;
if (pixel_object_scale != 0)
{
old_scale = fRnrCtx->GetRenderScale();
fRnrCtx->SetRenderScale(old_scale * pixel_object_scale);
}
fbo->Bind();
fLOD = TGLRnrCtx::kLODHigh;
fRnrCtx->SetGrabImage(kTRUE);
if (!gVirtualX->IsCmdThread())
gROOT->ProcessLineFast(Form("((TGLViewer *)0x%lx)->DoDraw(kFALSE)", (ULong_t)this));
else
DoDraw(kFALSE);
fRnrCtx->SetGrabImage(kFALSE);
fbo->Unbind();
fbo->SetAsReadBuffer();
UChar_t* xx = new UChar_t[4 * fViewport.Width() * fViewport.Height()];
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, fViewport.Width(), fViewport.Height(),
GL_BGRA, GL_UNSIGNED_BYTE, xx);
std::auto_ptr<TImage> image(TImage::Create());
image->FromGLBuffer(xx, fViewport.Width(), fViewport.Height());
image->WriteImage(fileName);
delete [] xx;
delete fbo;
if (pixel_object_scale != 0)
{
fRnrCtx->SetRenderScale(old_scale);
}
SetViewport(old_vp);
return kTRUE;
}
Bool_t TGLViewer::SavePictureWidth(const TString &fileName, Int_t width,
Bool_t pixel_object_scale)
{
Float_t scale = Float_t(width) / fViewport.Width();
Int_t height = TMath::Nint(scale*fViewport.Height());
return SavePictureUsingFBO(fileName, width, height, pixel_object_scale ? scale : 0);
}
Bool_t TGLViewer::SavePictureHeight(const TString &fileName, Int_t height,
Bool_t pixel_object_scale)
{
Float_t scale = Float_t(height) / fViewport.Height();
Int_t width = TMath::Nint(scale*fViewport.Width());
return SavePictureUsingFBO(fileName, width, height, pixel_object_scale ? scale : 0);
}
Bool_t TGLViewer::SavePictureScale (const TString &fileName, Float_t scale,
Bool_t pixel_object_scale)
{
Int_t w = TMath::Nint(scale*fViewport.Width());
Int_t h = TMath::Nint(scale*fViewport.Height());
return SavePictureUsingFBO(fileName, w, h, pixel_object_scale ? scale : 0);
}
void TGLViewer::DrawGuides()
{
Bool_t disabled = kFALSE;
if (fReferenceOn)
{
glDisable(GL_DEPTH_TEST);
TGLUtil::DrawReferenceMarker(*fCamera, fReferencePos);
disabled = kTRUE;
}
if (fDrawCameraCenter)
{
glDisable(GL_DEPTH_TEST);
Float_t radius = fCamera->ViewportDeltaToWorld(TGLVertex3(fCamera->GetCenterVec()), 3, 3).Mag();
const UChar_t rgba[4] = { 0, 255, 255, 255 };
TGLUtil::DrawSphere(fCamera->GetCenterVec(), radius, rgba);
disabled = kTRUE;
}
if (fAxesDepthTest && disabled)
{
glEnable(GL_DEPTH_TEST);
disabled = kFALSE;
}
else if (fAxesDepthTest == kFALSE && disabled == kFALSE)
{
glDisable(GL_DEPTH_TEST);
disabled = kTRUE;
}
TGLUtil::DrawSimpleAxes(*fCamera, fOverallBoundingBox, fAxesType);
if (disabled)
glEnable(GL_DEPTH_TEST);
}
void TGLViewer::DrawDebugInfo()
{
if (fDebugMode)
{
glDisable(GL_LIGHTING);
CurrentCamera().DrawDebugAids();
glColor3d(0.0, 1.0, 0.0);
fOverallBoundingBox.Draw();
glDisable(GL_DEPTH_TEST);
Double_t size = fOverallBoundingBox.Extents().Mag() / 200.0;
TGLUtil::DrawSphere(TGLVertex3(0.0, 0.0, 0.0), size, TGLUtil::fgWhite);
const TGLVertex3 & center = fOverallBoundingBox.Center();
TGLUtil::DrawSphere(center, size, TGLUtil::fgGreen);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
}
}
void TGLViewer::PreDraw()
{
InitGL();
{
Color_t ci = (fGLDevice != -1) ? gPad->GetFillColor() : fRnrCtx->ColorSet().Background().GetColorIndex();
TColor *color = gROOT->GetColor(ci);
Float_t rgb[3];
if (color)
color->GetRGB(rgb[0], rgb[1], rgb[2]);
else
rgb[0] = rgb[1] = rgb[2] = 0.0f;
glClearColor(rgb[0], rgb[1], rgb[2], 0.0f);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
TGLUtil::CheckError("TGLViewer::PreDraw");
}
void TGLViewer::PostDraw()
{
glFlush();
TGLUtil::CheckError("TGLViewer::PostDraw");
}
void TGLViewer::FadeView(Float_t alpha)
{
static const Float_t z = -1.0f;
glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity();
glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity();
{
TGLCapabilitySwitch blend(GL_BLEND, kTRUE);
TGLCapabilitySwitch light(GL_LIGHTING, kFALSE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
TGLUtil::ColorAlpha(fRnrCtx->ColorSet().Background(), alpha);
glBegin(GL_QUADS);
glVertex3f(-1, -1, z); glVertex3f( 1, -1, z);
glVertex3f( 1, 1, z); glVertex3f(-1, 1, z);
glEnd();
}
glMatrixMode(GL_PROJECTION); glPopMatrix();
glMatrixMode(GL_MODELVIEW); glPopMatrix();
}
void TGLViewer::MakeCurrent() const
{
if (fGLDevice == -1)
fGLWidget->MakeCurrent();
else
gGLManager->MakeCurrent(fGLDevice);
}
void TGLViewer::SwapBuffers() const
{
if ( ! IsDrawOrSelectLock()) {
Error("TGLViewer::SwapBuffers", "viewer is %s", LockName(CurrentLock()));
}
if (fGLDevice == -1)
fGLWidget->SwapBuffers();
else {
gGLManager->ReadGLBuffer(fGLDevice);
gGLManager->Flush(fGLDevice);
gGLManager->MarkForDirectCopy(fGLDevice, kFALSE);
}
}
Bool_t TGLViewer::RequestSelect(Int_t x, Int_t y)
{
if ( ! TakeLock(kSelectLock)) {
return kFALSE;
}
if (!gVirtualX->IsCmdThread())
return Bool_t(gROOT->ProcessLineFast(Form("((TGLViewer *)0x%lx)->DoSelect(%d, %d)", (ULong_t)this, x, y)));
else
return DoSelect(x, y);
}
Bool_t TGLViewer::DoSelect(Int_t x, Int_t y)
{
if (CurrentLock() != kSelectLock) {
Error("TGLViewer::DoSelect", "expected kSelectLock, found %s", LockName(CurrentLock()));
return kFALSE;
}
TGLUtil::PointToViewport(x, y);
TUnlocker ulck(this);
MakeCurrent();
fRnrCtx->BeginSelection(x, y, TGLUtil::GetPickingRadius());
glRenderMode(GL_SELECT);
PreRender();
TGLViewerBase::Render();
PostRender();
Int_t nHits = glRenderMode(GL_RENDER);
fRnrCtx->EndSelection(nHits);
if (gDebug > 0) Info("TGLViewer::DoSelect", "Primary select nHits=%d.", nHits);
if (nHits > 0)
{
Int_t idx = 0;
if (FindClosestRecord(fSelRec, idx))
{
if (fSelRec.GetTransparent() && fRnrCtx->SelectTransparents() != TGLRnrCtx::kIfClosest)
{
TGLSelectRecord opaque;
if (FindClosestOpaqueRecord(opaque, ++idx))
fSelRec = opaque;
else if (fRnrCtx->SelectTransparents() == TGLRnrCtx::kNever)
fSelRec.Reset();
}
if (gDebug > 1) fSelRec.Print();
}
} else {
fSelRec.Reset();
}
ReleaseLock(kSelectLock);
return ! TGLSelectRecord::AreSameSelectionWise(fSelRec, fCurrentSelRec);
}
Bool_t TGLViewer::RequestSecondarySelect(Int_t x, Int_t y)
{
if ( ! TakeLock(kSelectLock)) {
return kFALSE;
}
if (!gVirtualX->IsCmdThread())
return Bool_t(gROOT->ProcessLineFast(Form("((TGLViewer *)0x%lx)->DoSecondarySelect(%d, %d)", (ULong_t)this, x, y)));
else
return DoSecondarySelect(x, y);
}
Bool_t TGLViewer::DoSecondarySelect(Int_t x, Int_t y)
{
if (CurrentLock() != kSelectLock) {
Error("TGLViewer::DoSecondarySelect", "expected kSelectLock, found %s", LockName(CurrentLock()));
return kFALSE;
}
TGLUtil::PointToViewport(x, y);
TUnlocker ulck(this);
if (! fSelRec.GetSceneInfo() || ! fSelRec.GetPhysShape() ||
! fSelRec.GetLogShape()->SupportsSecondarySelect())
{
if (gDebug > 0)
Info("TGLViewer::SecondarySelect", "Skipping secondary selection "
"(sinfo=0x%lx, pshape=0x%lx).\n",
(Long_t)fSelRec.GetSceneInfo(), (Long_t)fSelRec.GetPhysShape());
fSecSelRec.Reset();
return kFALSE;
}
MakeCurrent();
TGLSceneInfo* sinfo = fSelRec.GetSceneInfo();
TGLSceneBase* scene = sinfo->GetScene();
TGLPhysicalShape* pshp = fSelRec.GetPhysShape();
SceneInfoList_t foo;
foo.push_back(sinfo);
fScenes.swap(foo);
fRnrCtx->BeginSelection(x, y, TGLUtil::GetPickingRadius());
fRnrCtx->SetSecSelection(kTRUE);
glRenderMode(GL_SELECT);
PreRender();
fRnrCtx->SetSceneInfo(sinfo);
scene->PreRender(*fRnrCtx);
fRnrCtx->SetDrawPass(TGLRnrCtx::kPassFill);
fRnrCtx->SetShapeLOD(TGLRnrCtx::kLODHigh);
glPushName(pshp->ID());
pshp->Draw(*fRnrCtx);
glPopName();
scene->PostRender(*fRnrCtx);
fRnrCtx->SetSceneInfo(0);
PostRender();
Int_t nSecHits = glRenderMode(GL_RENDER);
fRnrCtx->EndSelection(nSecHits);
fScenes.swap(foo);
if (gDebug > 0) Info("TGLViewer::DoSelect", "Secondary select nSecHits=%d.", nSecHits);
ReleaseLock(kSelectLock);
if (nSecHits > 0)
{
fSecSelRec = fSelRec;
fSecSelRec.SetRawOnly(fRnrCtx->GetSelectBuffer()->RawRecord(0));
if (gDebug > 1) fSecSelRec.Print();
return kTRUE;
} else {
fSecSelRec.Reset();
return kFALSE;
}
}
void TGLViewer::ApplySelection()
{
fCurrentSelRec = fSelRec;
TGLPhysicalShape *selPhys = fSelRec.GetPhysShape();
fSelectedPShapeRef->SetPShape(selPhys);
SelectionChanged();
RequestDraw(TGLRnrCtx::kLODHigh);
}
Bool_t TGLViewer::RequestOverlaySelect(Int_t x, Int_t y)
{
if ( ! TakeLock(kSelectLock)) {
return kFALSE;
}
if (!gVirtualX->IsCmdThread())
return Bool_t(gROOT->ProcessLineFast(Form("((TGLViewer *)0x%lx)->DoOverlaySelect(%d, %d)", (ULong_t)this, x, y)));
else
return DoOverlaySelect(x, y);
}
Bool_t TGLViewer::DoOverlaySelect(Int_t x, Int_t y)
{
if (CurrentLock() != kSelectLock) {
Error("TGLViewer::DoOverlaySelect", "expected kSelectLock, found %s", LockName(CurrentLock()));
return kFALSE;
}
TGLUtil::PointToViewport(x, y);
TUnlocker ulck(this);
MakeCurrent();
fRnrCtx->BeginSelection(x, y, TGLUtil::GetPickingRadius());
glRenderMode(GL_SELECT);
PreRenderOverlaySelection();
RenderOverlay(TGLOverlayElement::kActive, kTRUE);
PostRenderOverlaySelection();
Int_t nHits = glRenderMode(GL_RENDER);
fRnrCtx->EndSelection(nHits);
TGLOverlayElement * selElm = 0;
if (nHits > 0)
{
Int_t idx = 0;
while (idx < nHits && FindClosestOverlayRecord(fOvlSelRec, idx))
{
TGLOverlayElement* el = fOvlSelRec.GetOvlElement();
if (el == fCurrentOvlElm)
{
if (el->MouseStillInside(fOvlSelRec))
{
selElm = el;
break;
}
}
else if (el->MouseEnter(fOvlSelRec))
{
selElm = el;
break;
}
++idx;
}
}
else
{
fOvlSelRec.Reset();
}
ReleaseLock(kSelectLock);
if (fCurrentOvlElm != selElm)
{
if (fCurrentOvlElm) fCurrentOvlElm->MouseLeave();
fCurrentOvlElm = selElm;
return kTRUE;
}
else
{
return kFALSE;
}
}
void TGLFaderHelper::MakeFadeStep()
{
Float_t fade = fViewer->GetFader();
if (fade == fFadeTarget) {
delete this; return;
}
if (TMath::Abs(fFadeTarget - fade) < 1e-3) {
fViewer->SetFader(fFadeTarget);
fViewer->RequestDraw(TGLRnrCtx::kLODHigh);
delete this;
return;
}
Float_t dt = fTime/fNSteps;
Float_t df = (fFadeTarget - fade)/fNSteps;
fViewer->SetFader(fade + df);
fViewer->RequestDraw(TGLRnrCtx::kLODHigh);
fTime -= dt; --fNSteps;
TTimer::SingleShot(TMath::CeilNint(1000*dt),
"TGLFaderHelper", this, "MakeFadeStep()");
}
void TGLViewer::AutoFade(Float_t fade, Float_t time, Int_t steps)
{
TGLFaderHelper* fh = new TGLFaderHelper(this, fade, time, steps);
fh->MakeFadeStep();
}
void TGLViewer::UseDarkColorSet()
{
fRnrCtx->ChangeBaseColorSet(&fDarkColorSet);
RefreshPadEditor(this);
}
void TGLViewer::UseLightColorSet()
{
fRnrCtx->ChangeBaseColorSet(&fLightColorSet);
RefreshPadEditor(this);
}
void TGLViewer::SwitchColorSet()
{
if (IsUsingDefaultColorSet())
{
Info("SwitchColorSet()", "Global color-set is in use, switch not supported.");
return;
}
if (fRnrCtx->GetBaseColorSet() == &fLightColorSet)
UseDarkColorSet();
else
UseLightColorSet();
}
void TGLViewer::UseDefaultColorSet(Bool_t x)
{
if (x)
fRnrCtx->ChangeBaseColorSet(&fgDefaultColorSet);
else
fRnrCtx->ChangeBaseColorSet(&fDarkColorSet);
RefreshPadEditor(this);
}
Bool_t TGLViewer::IsUsingDefaultColorSet() const
{
return fRnrCtx->GetBaseColorSet() == &fgDefaultColorSet;
}
void TGLViewer::SetClearColor(Color_t col)
{
fRnrCtx->GetBaseColorSet()->Background().SetColor(col);
}
TGLColorSet& TGLViewer::GetDefaultColorSet()
{
return fgDefaultColorSet;
}
void TGLViewer::UseDefaultColorSetForNewViewers(Bool_t x)
{
fgUseDefaultColorSetForNewViewers = x;
}
Bool_t TGLViewer::IsUsingDefaultColorSetForNewViewers()
{
return fgUseDefaultColorSetForNewViewers;
}
Bool_t TGLViewer::IsColorSetDark() const
{
return fRnrCtx->GetBaseColorSet() == &fDarkColorSet;
}
void TGLViewer::SetViewport(Int_t x, Int_t y, Int_t width, Int_t height)
{
if (fViewport.X() == x && fViewport.Y() == y &&
fViewport.Width() == width && fViewport.Height() == height) {
return;
}
fViewport.Set(x, y, width, height);
fCurrentCamera->SetViewport(fViewport);
if (gDebug > 2) {
Info("TGLViewer::SetViewport", "updated - corner %d,%d dimensions %d,%d", x, y, width, height);
}
}
void TGLViewer::SetViewport(const TGLRect& vp)
{
SetViewport(vp.X(), vp.Y(), vp.Width(), vp.Height());
}
TGLCamera& TGLViewer::RefCamera(ECameraType cameraType)
{
switch(cameraType) {
case kCameraPerspXOZ:
return fPerspectiveCameraXOZ;
case kCameraPerspYOZ:
return fPerspectiveCameraYOZ;
case kCameraPerspXOY:
return fPerspectiveCameraXOY;
case kCameraOrthoXOY:
return fOrthoXOYCamera;
case kCameraOrthoXOZ:
return fOrthoXOZCamera;
case kCameraOrthoZOY:
return fOrthoZOYCamera;
case kCameraOrthoXnOY:
return fOrthoXnOYCamera;
case kCameraOrthoXnOZ:
return fOrthoXnOZCamera;
case kCameraOrthoZnOY:
return fOrthoZnOYCamera;
default:
Error("TGLViewer::SetCurrentCamera", "invalid camera type");
return *fCurrentCamera;
}
}
void TGLViewer::SetCurrentCamera(ECameraType cameraType)
{
if (IsLocked()) {
Error("TGLViewer::SetCurrentCamera", "expected kUnlocked, found %s", LockName(CurrentLock()));
return;
}
TGLCamera *prev = fCurrentCamera;
switch (cameraType)
{
case kCameraPerspXOZ: {
fCurrentCamera = &fPerspectiveCameraXOZ;
break;
}
case kCameraPerspYOZ: {
fCurrentCamera = &fPerspectiveCameraYOZ;
break;
}
case kCameraPerspXOY: {
fCurrentCamera = &fPerspectiveCameraXOY;
break;
}
case kCameraOrthoXOY: {
fCurrentCamera = &fOrthoXOYCamera;
break;
}
case kCameraOrthoXOZ: {
fCurrentCamera = &fOrthoXOZCamera;
break;
}
case kCameraOrthoZOY: {
fCurrentCamera = &fOrthoZOYCamera;
break;
}
case kCameraOrthoXnOY: {
fCurrentCamera = &fOrthoXnOYCamera;
break;
}
case kCameraOrthoXnOZ: {
fCurrentCamera = &fOrthoXnOZCamera;
break;
}
case kCameraOrthoZnOY: {
fCurrentCamera = &fOrthoZnOYCamera;
break;
}
default: {
Error("TGLViewer::SetCurrentCamera", "invalid camera type");
break;
}
}
if (fCurrentCamera != prev)
{
fCurrentCamera->SetViewport(fViewport);
RefreshPadEditor(this);
if (fAutoRotator)
{
if (fAutoRotator->IsRunning())
{
fAutoRotator->Stop();
}
else
{
if (fAutoRotator->GetCamera() == fCurrentCamera)
{
fAutoRotator->Start();
}
}
}
RequestDraw(TGLRnrCtx::kLODHigh);
}
}
void TGLViewer::SetOrthoCamera(ECameraType camera,
Double_t zoom, Double_t dolly,
Double_t center[3],
Double_t hRotate, Double_t vRotate)
{
switch(camera) {
case kCameraOrthoXOY: {
fOrthoXOYCamera.Configure(zoom, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fOrthoXOYCamera) {
RequestDraw(TGLRnrCtx::kLODHigh);
}
break;
}
case kCameraOrthoXOZ: {
fOrthoXOZCamera.Configure(zoom, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fOrthoXOZCamera) {
RequestDraw(TGLRnrCtx::kLODHigh);
}
break;
}
case kCameraOrthoZOY: {
fOrthoZOYCamera.Configure(zoom, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fOrthoZOYCamera) {
RequestDraw(TGLRnrCtx::kLODHigh);
}
break;
}
default: {
Error("TGLViewer::SetOrthoCamera", "invalid camera type");
break;
}
}
}
void TGLViewer::SetPerspectiveCamera(ECameraType camera,
Double_t fov, Double_t dolly,
Double_t center[3],
Double_t hRotate, Double_t vRotate)
{
switch(camera) {
case kCameraPerspXOZ: {
fPerspectiveCameraXOZ.Configure(fov, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fPerspectiveCameraXOZ) {
RequestDraw(TGLRnrCtx::kLODHigh);
}
break;
}
case kCameraPerspYOZ: {
fPerspectiveCameraYOZ.Configure(fov, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fPerspectiveCameraYOZ) {
RequestDraw(TGLRnrCtx::kLODHigh);
}
break;
}
case kCameraPerspXOY: {
fPerspectiveCameraXOY.Configure(fov, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fPerspectiveCameraXOY) {
RequestDraw(TGLRnrCtx::kLODHigh);
}
break;
}
default: {
Error("TGLViewer::SetPerspectiveCamera", "invalid camera type");
break;
}
}
}
void TGLViewer::ReinitializeCurrentCamera(const TGLVector3& hAxis, const TGLVector3& vAxis, Bool_t redraw)
{
TGLMatrix& cb = fCurrentCamera->RefCamBase();
cb.Set(cb.GetTranslation(), vAxis, hAxis);
fCurrentCamera->Setup(fOverallBoundingBox, kTRUE);
if (redraw)
RequestDraw();
}
TGLAutoRotator* TGLViewer::GetAutoRotator()
{
if (fAutoRotator == 0)
fAutoRotator = new TGLAutoRotator(this);
return fAutoRotator;
}
void TGLViewer::SetAutoRotator(TGLAutoRotator* ar)
{
delete fAutoRotator;
fAutoRotator = ar;
}
void TGLViewer::GetGuideState(Int_t & axesType, Bool_t & axesDepthTest, Bool_t & referenceOn, Double_t referencePos[3]) const
{
axesType = fAxesType;
axesDepthTest = fAxesDepthTest;
referenceOn = fReferenceOn;
referencePos[0] = fReferencePos.X();
referencePos[1] = fReferencePos.Y();
referencePos[2] = fReferencePos.Z();
}
void TGLViewer::SetGuideState(Int_t axesType, Bool_t axesDepthTest, Bool_t referenceOn, const Double_t referencePos[3])
{
fAxesType = axesType;
fAxesDepthTest = axesDepthTest;
fReferenceOn = referenceOn;
if (referencePos)
fReferencePos.Set(referencePos[0], referencePos[1], referencePos[2]);
if (fGLDevice != -1)
gGLManager->MarkForDirectCopy(fGLDevice, kTRUE);
RequestDraw();
}
void TGLViewer::SetDrawCameraCenter(Bool_t x)
{
fDrawCameraCenter = x;
RequestDraw();
}
const TGLPhysicalShape * TGLViewer::GetSelected() const
{
return fSelectedPShapeRef->GetPShape();
}
void TGLViewer::MouseOver(TGLPhysicalShape *shape)
{
Emit("MouseOver(TGLPhysicalShape*)", (Long_t)shape);
}
void TGLViewer::MouseOver(TGLPhysicalShape *shape, UInt_t state)
{
Long_t args[2];
args[0] = (Long_t)shape;
args[1] = state;
Emit("MouseOver(TGLPhysicalShape*,UInt_t)", args);
}
void TGLViewer::MouseOver(TObject *obj, UInt_t state)
{
Long_t args[2];
args[0] = (Long_t)obj;
args[1] = state;
Emit("MouseOver(TObject*,UInt_t)", args);
}
void TGLViewer::ReMouseOver(TObject *obj, UInt_t state)
{
Long_t args[2];
args[0] = (Long_t)obj;
args[1] = state;
Emit("ReMouseOver(TObject*,UInt_t)", args);
}
void TGLViewer::UnMouseOver(TObject *obj, UInt_t state)
{
Long_t args[2];
args[0] = (Long_t)obj;
args[1] = state;
Emit("UnMouseOver(TObject*,UInt_t)", args);
}
void TGLViewer::Clicked(TObject *obj)
{
Emit("Clicked(TObject*)", (Long_t)obj);
}
void TGLViewer::Clicked(TObject *obj, UInt_t button, UInt_t state)
{
Long_t args[3];
args[0] = (Long_t)obj;
args[1] = button;
args[2] = state;
Emit("Clicked(TObject*,UInt_t,UInt_t)", args);
}
void TGLViewer::ReClicked(TObject *obj, UInt_t button, UInt_t state)
{
Long_t args[3];
args[0] = (Long_t)obj;
args[1] = button;
args[2] = state;
Emit("ReClicked(TObject*,UInt_t,UInt_t)", args);
}
void TGLViewer::UnClicked(TObject *obj, UInt_t button, UInt_t state)
{
Long_t args[3];
args[0] = (Long_t)obj;
args[1] = button;
args[2] = state;
Emit("UnClicked(TObject*,UInt_t,UInt_t)", args);
}
void TGLViewer::MouseIdle(TGLPhysicalShape *shape, UInt_t posx, UInt_t posy)
{
Long_t args[3];
static UInt_t oldx = 0, oldy = 0;
if (oldx != posx || oldy != posy) {
args[0] = (Long_t)shape;
args[1] = posx;
args[2] = posy;
Emit("MouseIdle(TGLPhysicalShape*,UInt_t,UInt_t)", args);
oldx = posx;
oldy = posy;
}
}
Int_t TGLViewer::DistancetoPrimitive(Int_t , Int_t )
{
gPad->SetSelected(this);
return 0;
}
void TGLViewer::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
if (fEventHandler)
return fEventHandler->ExecuteEvent(event, px, py);
}
void TGLViewer::PrintObjects()
{
TGLOutput::Capture(*this);
}
void TGLViewer::SelectionChanged()
{
if (!fGedEditor)
return;
TGLPhysicalShape *selected = const_cast<TGLPhysicalShape*>(GetSelected());
if (selected) {
fPShapeWrap->fPShape = selected;
fGedEditor->SetModel(fPad, fPShapeWrap, kButton1Down);
} else {
fPShapeWrap->fPShape = 0;
fGedEditor->SetModel(fPad, this, kButton1Down);
}
}
void TGLViewer::OverlayDragFinished()
{
if (fGedEditor)
{
fGedEditor->SetModel(fPad, fGedEditor->GetModel(), kButton1Down);
}
}
void TGLViewer::RefreshPadEditor(TObject* obj)
{
if (fGedEditor && (obj == 0 || fGedEditor->GetModel() == obj))
{
fGedEditor->SetModel(fPad, fGedEditor->GetModel(), kButton1Down);
}
}
void TGLViewer::SetEventHandler(TGEventHandler *handler)
{
if (fEventHandler)
delete fEventHandler;
fEventHandler = handler;
if (fGLWidget)
fGLWidget->SetEventHandler(fEventHandler);
}
void TGLViewer::RemoveOverlayElement(TGLOverlayElement* el)
{
if (el == fCurrentOvlElm)
{
fCurrentOvlElm = 0;
}
TGLViewerBase::RemoveOverlayElement(el);
}
void TGLViewer::ClearCurrentOvlElm()
{
if (fCurrentOvlElm)
{
fCurrentOvlElm->MouseLeave();
fCurrentOvlElm = 0;
RequestDraw();
}
}