1 /**
2 * UGENE - Integrated Bioinformatics Tools.
3 * Copyright (C) 2008-2021 UniPro <ugene@unipro.ru>
4 * http://ugene.net
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #include <math.h>
23 #include <time.h>
24
25 #include <QColorDialog>
26 #include <QImageWriter>
27 #include <QMessageBox>
28 #include <QMouseEvent>
29 #include <QOffscreenSurface>
30 #include <QOpenGLContext>
31 #include <QOpenGLShaderProgram>
32 #include <QTime>
33
34 #include <U2Algorithm/MolecularSurfaceFactoryRegistry.h>
35 #include <U2Algorithm/StructuralAlignmentAlgorithm.h>
36
37 #include <U2Core/AnnotationSelection.h>
38 #include <U2Core/AnnotationSettings.h>
39 #include <U2Core/AnnotationTableObject.h>
40 #include <U2Core/AppContext.h>
41 #include <U2Core/BioStruct3D.h>
42 #include <U2Core/BioStruct3DObject.h>
43 #include <U2Core/Counter.h>
44 #include <U2Core/DNASequenceObject.h>
45 #include <U2Core/DNASequenceSelection.h>
46 #include <U2Core/DocumentModel.h>
47 #include <U2Core/GObjectRelationRoles.h>
48 #include <U2Core/GUrlUtils.h>
49 #include <U2Core/Log.h>
50 #include <U2Core/ProjectModel.h>
51 #include <U2Core/QObjectScopedPointer.h>
52 #include <U2Core/TaskSignalMapper.h>
53 #include <U2Core/U2SafePoints.h>
54
55 #include <U2Gui/ExportImageDialog.h>
56
57 #include <U2View/ADVSequenceObjectContext.h>
58 #include <U2View/AnnotatedDNAView.h>
59
60 #include "BioStruct3DColorScheme.h"
61 #include "BioStruct3DGLImageExportTask.h"
62 #include "BioStruct3DGLRender.h"
63 #include "BioStruct3DGLWidget.h"
64 #include "GLFrameManager.h"
65 #include "SelectModelsDialog.h"
66 #include "SettingsDialog.h"
67 #include "StructuralAlignmentDialog.h"
68 #include "gl2ps/gl2ps.h"
69
70 // disable "unsafe functions" deprecation warnings on MS VS
71 #ifdef Q_OS_WIN
72 # pragma warning(disable : 4996)
73 #endif
74
75 namespace U2 {
76
77 int BioStruct3DGLWidget::widgetCount = 0;
78
checkShaderPrograms()79 bool BioStruct3DGLWidget::checkShaderPrograms() {
80 QOffscreenSurface surf;
81 surf.create();
82
83 QOpenGLContext ctx;
84 ctx.create();
85 ctx.makeCurrent(&surf);
86
87 bool opgl = QOpenGLShaderProgram::hasOpenGLShaderPrograms(&ctx);
88 if (!opgl) {
89 coreLog.error(tr("The \"3D Structure Viewer\" was disabled, because shader programs written in the OpenGL Shading Language (GLSL) are not supported on this system. "
90 "Please try to update drivers and reset the UGENE settings to default in the \"Application Settings\" dialog."));
91 }
92
93 return opgl;
94 }
95
tryGL()96 void BioStruct3DGLWidget::tryGL() {
97 volatile QOpenGLWidget wgt;
98 Q_UNUSED(wgt);
99 }
100
101 const double BioStruct3DGLWidget::MINIMUM_ACCEPTABLE_VERSION = 2.0f;
102
103 static QColor DEFAULT_BACKGROUND_COLOR = Qt::black;
104 static QColor DEFAULT_SELECTION_COLOR = Qt::yellow;
105
106 static float DEFAULT_RENDER_DETAIL_LEVEL = 1.0;
107 static int DEFAULT_SHADING_LEVEL = 50;
108
109 const QString BioStruct3DGLWidget::BACKGROUND_COLOR_NAME("BackgroundColor");
110 const QString BioStruct3DGLWidget::PRODUCT_NAME("Unipro Ugene");
111 const QString BioStruct3DGLWidget::PLUGIN_NAME("BioStruct3D Viewer Plugin");
112 const QString BioStruct3DGLWidget::COLOR_SCHEME_NAME("ColorScheme");
113 const QString BioStruct3DGLWidget::RENDERER_NAME("GLRenderer");
114 const QString BioStruct3DGLWidget::OBJECT_ID_NAME("OBJECT_ID");
115
116 const QString BioStruct3DGLWidget::SELECTION_COLOR_NAME("SelectionColor");
117 const QString BioStruct3DGLWidget::SHADING_LEVEL_NAME("Shading Unselected Regions Level");
118 const QString BioStruct3DGLWidget::RENDER_DETAIL_LEVEL_NAME("RenderDetailLevel");
119 const QString BioStruct3DGLWidget::ANAGLYPH_STATUS_NAME("AnaglyphStatus");
120
BioStruct3DGLWidget(BioStruct3DObject * obj,const AnnotatedDNAView * _dnaView,GLFrameManager * manager,QWidget * parent)121 BioStruct3DGLWidget::BioStruct3DGLWidget(BioStruct3DObject *obj, const AnnotatedDNAView *_dnaView, GLFrameManager *manager, QWidget *parent /* = 0*/)
122 : QOpenGLWidget(parent),
123 dnaView(_dnaView), contexts(),
124 rendererSettings(DEFAULT_RENDER_DETAIL_LEVEL),
125 frameManager(manager), glFrame(new GLFrame(this)),
126 molSurface(0), surfaceRenderer(), surfaceCalcTask(0),
127 anaglyphStatus(DISABLED),
128 anaglyph(new AnaglyphRenderer(this, AnaglyphSettings::defaultSettings())),
129
130 defaultsSettings(), currentColorSchemeName(), currentGLRendererName(),
131 rotAngle(0), spinAngle(0), rotAxis(), lastPos(),
132 backgroundColor(DEFAULT_BACKGROUND_COLOR),
133 selectionColor(DEFAULT_SELECTION_COLOR), animationTimer(0),
134 unselectedShadingLevel(DEFAULT_SHADING_LEVEL), imageRenderingMode(false),
135
136 spinAction(0), settingsAction(0), closeAction(0), exportImageAction(0), selectModelsAction(0), alignWithAction(0),
137 resetAlignmentAction(0), colorSchemeActions(0), rendererActions(0), molSurfaceRenderActions(0),
138 molSurfaceTypeActions(0), selectColorSchemeMenu(0), selectRendererMenu(0), displayMenu(0), lblGlError(nullptr) {
139 lightPosition[0] = lightPosition[1] = lightPosition[2] = lightPosition[3] = 0;
140 GCOUNTER(cvar, "BioStruct3DGLWidget");
141
142 QString currentModelID = obj->getBioStruct3D().pdbId;
143 setObjectName(QString("%1-%2").arg(++widgetCount).arg(currentModelID));
144
145 setWindowIcon(GObjectTypes::getTypeInfo(GObjectTypes::BIOSTRUCTURE_3D).icon);
146
147 connectExternalSignals();
148
149 currentColorSchemeName = BioStruct3DColorSchemeRegistry::defaultFactoryName();
150 currentGLRendererName = BioStruct3DGLRendererRegistry::defaultFactoryName();
151
152 QList<QString> availableRenders = BioStruct3DGLRendererRegistry::getRenderersAvailableFor(obj->getBioStruct3D());
153 if (!availableRenders.contains(currentGLRendererName)) {
154 currentGLRendererName = availableRenders.first();
155 }
156
157 addBiostruct(obj);
158
159 checkRenderingAndCreateLblError();
160
161 createActions();
162 createMenus();
163
164 loadColorSchemes();
165 loadGLRenderers(availableRenders);
166
167 frameManager->addGLFrame(glFrame.data());
168 saveDefaultSettings();
169 }
170
~BioStruct3DGLWidget()171 BioStruct3DGLWidget::~BioStruct3DGLWidget() {
172 uiLog.trace("Biostruct3DGLWdiget " + objectName() + " deleted");
173 }
174
setupFrame()175 void BioStruct3DGLWidget::setupFrame() {
176 const float scaleFactor = 2.5;
177 float radius = getSceneRadius();
178 float camZ = scaleFactor * radius;
179
180 float cameraClipNear = (camZ - radius) * 0.66f;
181 float cameraClipFar = (camZ + radius) * 1.2f;
182
183 glFrame->setCameraClip(cameraClipNear, cameraClipFar);
184
185 Vector3D pos = glFrame->getCameraPosition();
186 pos.z = camZ;
187 glFrame->setCameraPosition(pos);
188 }
189
getSceneRadius() const190 float BioStruct3DGLWidget::getSceneRadius() const {
191 // good idea: ask renderer for radius instead of asking biostruct
192 float maxRadius = 0;
193 const Vector3D sceneCenter = getSceneCenter();
194
195 foreach (const BioStruct3DRendererContext &ctx, contexts) {
196 Vector3D center = ctx.biostruct->getCenter();
197 float radius = (center - sceneCenter).length() + ctx.biostruct->getRadius();
198 if (maxRadius < radius) {
199 maxRadius = radius;
200 }
201 }
202
203 return maxRadius;
204 }
205
getSceneCenter() const206 Vector3D BioStruct3DGLWidget::getSceneCenter() const {
207 // good idea: ask renderer for center instead of asking biostruct
208 Vector3D c;
209 foreach (const BioStruct3DRendererContext &ctx, contexts) {
210 // TODO: transform should be applied in BioStruct
211 Vector3D tmp = ctx.biostruct->getCenter();
212 c += tmp.dot(ctx.biostruct->getTransform());
213 }
214
215 return c / float(contexts.length());
216 }
217
getBioStruct3D() const218 const BioStruct3D &BioStruct3DGLWidget::getBioStruct3D() const {
219 return *(contexts.first().biostruct);
220 }
221
getPDBId() const222 const QString BioStruct3DGLWidget::getPDBId() const {
223 return contexts.first().biostruct->pdbId;
224 }
225
getBioStruct3DObjectName() const226 const QString BioStruct3DGLWidget::getBioStruct3DObjectName() const {
227 return contexts.first().obj->getGObjectName();
228 }
229
setImageRenderingMode(bool status)230 void BioStruct3DGLWidget::setImageRenderingMode(bool status) {
231 imageRenderingMode = status;
232 }
233
getGLFrame()234 GLFrame *BioStruct3DGLWidget::getGLFrame() {
235 return glFrame.data();
236 }
237
initializeGL()238 void BioStruct3DGLWidget::initializeGL() {
239 setLightPosition(Vector3D(0, 0.0, 1.0));
240 GLfloat light_diffuse[] = {0.8f, 0.8f, 0.8f, 1.0};
241 GLfloat light_specular[] = {0.6f, 0.6f, 0.6f, 1.0};
242 GLfloat mat_specular[] = {0.6f, 0.6f, 0.6f, 1.0};
243 GLfloat mat_shininess[] = {90.0};
244
245 glClearColor(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF(), backgroundColor.alphaF());
246 glShadeModel(GL_SMOOTH);
247 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
248 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
249 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
250 glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
251 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
252 glEnable(GL_BLEND); // Enable Blending
253 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
254
255 updateAllRenderers();
256
257 QString videoAdapterString(QLatin1String(reinterpret_cast<const char *>(glGetString(GL_VENDOR))));
258 if (videoAdapterString.contains("intel", Qt::CaseInsensitive)) {
259 anaglyphStatus = NOT_AVAILABLE;
260 } else if (!imageRenderingMode) {
261 anaglyph->init();
262 if (!anaglyph->isAvailable()) {
263 anaglyphStatus = NOT_AVAILABLE;
264 }
265 }
266 }
267
resizeGL(int width,int height)268 void BioStruct3DGLWidget::resizeGL(int width, int height) {
269 glFrame->updateViewPort(width, height);
270 if (lblGlError != nullptr) {
271 lblGlError->resize(size());
272 }
273 if (anaglyphStatus == ENABLED) {
274 anaglyph->resize(width, height);
275 }
276 }
277
paintGL()278 void BioStruct3DGLWidget::paintGL() {
279 if (!isVisible()) {
280 return;
281 }
282
283 clock_t frameStart = clock();
284
285 // Clear buffers, setup modelview matrix
286 // Scene render unable to do this since it used by anaglyph renderer
287 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
288
289 glMatrixMode(GL_MODELVIEW);
290 glLoadIdentity();
291
292 gluLookAt(0.0, 0.0, glFrame->getCameraPosition().z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
293
294 if (anaglyphStatus == ENABLED && !imageRenderingMode) {
295 // draw using anaglyph renderer
296 anaglyph->draw();
297 } else {
298 // draw using default scene renderer (this)
299 draw();
300 }
301
302 clock_t frameEnd = clock();
303 double frameTime = (frameEnd - frameStart) / (double)CLOCKS_PER_SEC;
304 perfLog.trace(QString("BioStruct3DView frame rendering time %1 s").arg(frameTime));
305 }
306
draw()307 void BioStruct3DGLWidget::draw() {
308 glEnable(GL_DEPTH_TEST);
309 glEnable(GL_LIGHTING);
310 glEnable(GL_LIGHT0);
311
312 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
313
314 Vector3D rotCenter = getSceneCenter();
315
316 glTranslatef(glFrame->getCameraPosition().x, glFrame->getCameraPosition().y, 0);
317
318 glMultMatrixf(glFrame->getRotationMatrix());
319 glTranslatef(-rotCenter.x, -rotCenter.y, -rotCenter.z);
320
321 foreach (const BioStruct3DRendererContext &ctx, contexts) {
322 glPushMatrix();
323
324 Matrix44 colmt = ctx.biostruct->getTransform();
325 colmt.transpose();
326 glMultMatrixf(colmt.data());
327
328 ctx.renderer->drawBioStruct3D();
329 glPopMatrix();
330 }
331
332 if (!molSurface.isNull()) {
333 glEnable(GL_CULL_FACE);
334
335 glCullFace(GL_FRONT);
336 surfaceRenderer->drawSurface(*molSurface);
337
338 glCullFace(GL_BACK);
339 surfaceRenderer->drawSurface(*molSurface);
340
341 glDisable(GL_CULL_FACE);
342 CHECK_GL_ERROR;
343 }
344
345 glDisable(GL_LIGHTING);
346 glDisable(GL_LIGHT0);
347 glDisable(GL_DEPTH_TEST);
348 }
349
getTrackballMapping(int x,int y)350 Vector3D BioStruct3DGLWidget::getTrackballMapping(int x, int y) {
351 Vector3D pos;
352 /* project x,y onto a hemisphere centered within width, height */
353 pos.x = (2.0f * x - width()) / width();
354 pos.y = (height() - 2.0f * y) / height();
355 pos.z = 0;
356 float d = pos.length();
357 d = (d < 1.0) ? d : 1.0;
358 pos.z = sqrtf(1.0f - d * d);
359 pos.normalize();
360
361 return pos;
362 }
363
contextMenuEvent(QContextMenuEvent * event)364 void BioStruct3DGLWidget::contextMenuEvent(QContextMenuEvent *event) {
365 QMenu menu;
366 foreach (QAction *action, getDisplayMenu()->actions()) {
367 menu.addAction(action);
368 }
369
370 menu.addAction(closeAction);
371
372 menu.exec(event->globalPos());
373 }
374
setLightPosition(const Vector3D & pos)375 void BioStruct3DGLWidget::setLightPosition(const Vector3D &pos) {
376 lightPosition[0] = pos.x;
377 lightPosition[1] = pos.y;
378 lightPosition[2] = pos.z;
379 lightPosition[3] = 1.0;
380 }
381
getSequenceChainId(const U2SequenceObject * seqObj)382 static int getSequenceChainId(const U2SequenceObject *seqObj) {
383 bool isFound = false;
384 qint64 result = seqObj->getSequenceInfo().value(DNAInfo::CHAIN_ID).toInt(&isFound);
385 SAFE_POINT(isFound, "Sequence does not have the CHAIN_ID attribute", -1);
386 return (int)result;
387 }
388
sl_onSequenceSelectionChanged(LRegionsSelection * s,const QVector<U2Region> & added,const QVector<U2Region> & removed)389 void BioStruct3DGLWidget::sl_onSequenceSelectionChanged(LRegionsSelection *s, const QVector<U2Region> &added, const QVector<U2Region> &removed) {
390 if (!isVisible())
391 return;
392
393 DNASequenceSelection *selection = qobject_cast<DNASequenceSelection *>(s);
394 const U2SequenceObject *seqObj = selection->getSequenceObject();
395 assert(seqObj);
396
397 const BioStruct3DRendererContext &ctx = contexts.first();
398
399 // check that biostruct and sequence objects are from the same document
400 // appropriate relation check must be here
401 if (seqObj->getDocument() == ctx.obj->getDocument()) {
402 int chainId = getSequenceChainId(seqObj);
403 assert(ctx.biostruct->moleculeMap.contains(chainId));
404
405 ctx.colorScheme->updateSelectionRegion(chainId, added, removed);
406
407 updateAllColorSchemes();
408 update();
409 }
410 }
411
getState()412 QVariantMap BioStruct3DGLWidget::getState() {
413 QVariantMap state;
414 glFrame->writeStateToMap(state);
415 anaglyph->getSettings().toMap(state);
416
417 state[ANAGLYPH_STATUS_NAME] = qVariantFromValue((int)anaglyphStatus);
418
419 state[COLOR_SCHEME_NAME] = QVariant::fromValue(currentColorSchemeName);
420 state[RENDERER_NAME] = QVariant::fromValue(currentGLRendererName);
421 state[OBJECT_ID_NAME] = QVariant::fromValue(getBioStruct3DObjectName());
422
423 state[BACKGROUND_COLOR_NAME] = QVariant::fromValue(backgroundColor);
424 state[SELECTION_COLOR_NAME] = QVariant::fromValue(selectionColor);
425
426 state[RENDER_DETAIL_LEVEL_NAME] = QVariant::fromValue(rendererSettings.detailLevel);
427 state[SHADING_LEVEL_NAME] = QVariant::fromValue(unselectedShadingLevel);
428
429 return state;
430 }
431
setState(const QVariantMap & state)432 void BioStruct3DGLWidget::setState(const QVariantMap &state) {
433 // bug-2859: correct save/restore current selection.
434 if (state.isEmpty()) {
435 return;
436 }
437 glFrame->makeCurrent();
438 glFrame->setState(state);
439
440 anaglyphStatus = (AnaglyphStatus)state.value(ANAGLYPH_STATUS_NAME).value<int>();
441 anaglyph->setSettings(AnaglyphSettings::fromMap(state));
442
443 backgroundColor = state.value(BACKGROUND_COLOR_NAME, DEFAULT_BACKGROUND_COLOR).value<QColor>();
444 setBackgroundColor(backgroundColor);
445
446 selectionColor = state.value(SELECTION_COLOR_NAME, DEFAULT_SELECTION_COLOR).value<QColor>();
447
448 rendererSettings.detailLevel = state.value(RENDER_DETAIL_LEVEL_NAME, DEFAULT_RENDER_DETAIL_LEVEL).value<float>();
449
450 QString previousColorSchemeName = currentColorSchemeName;
451 QString previousGLRendererName = currentGLRendererName;
452
453 currentColorSchemeName = state.value(COLOR_SCHEME_NAME, BioStruct3DColorSchemeRegistry::defaultFactoryName()).value<QString>();
454 currentGLRendererName = state.value(RENDERER_NAME, BioStruct3DGLRendererRegistry::defaultFactoryName()).value<QString>();
455
456 if (previousColorSchemeName != currentColorSchemeName) {
457 setupColorScheme(currentColorSchemeName);
458 }
459
460 unselectedShadingLevel = state.value(SHADING_LEVEL_NAME, DEFAULT_SHADING_LEVEL).value<int>();
461 setUnselectedShadingLevel(unselectedShadingLevel);
462
463 if (previousGLRendererName != currentGLRendererName) {
464 setupRenderer(currentGLRendererName);
465 }
466
467 resizeGL(width(), height());
468 update();
469 }
470
setupColorScheme(const QString & name)471 void BioStruct3DGLWidget::setupColorScheme(const QString &name) {
472 QList<BioStruct3DRendererContext>::iterator i = contexts.begin();
473 for (; i != contexts.end(); ++i) {
474 BioStruct3DRendererContext &ctx = *(i);
475
476 // TODO: this situation may be potentialy dangerous
477 // if renderer starts draw right now, maybe SharedPointer will be good solution
478 BioStruct3DColorScheme *scheme = BioStruct3DColorSchemeRegistry::createColorScheme(name, ctx.obj);
479 assert(scheme);
480
481 scheme->setSelectionColor(selectionColor);
482 scheme->setUnselectedShadingLevel((double)unselectedShadingLevel / 100.0);
483
484 ctx.colorScheme = QSharedPointer<BioStruct3DColorScheme>(scheme);
485 ctx.renderer->setColorScheme(scheme);
486 }
487 }
488
setupRenderer(const QString & name)489 void BioStruct3DGLWidget::setupRenderer(const QString &name) {
490 QList<BioStruct3DRendererContext>::iterator i = contexts.begin();
491 for (; i != contexts.end(); ++i) {
492 BioStruct3DRendererContext &ctx = *(i);
493
494 // TODO: this situation may be potentialy dangerous
495 // if renderer starts draw right now, maybe SharedPointer will be good solution
496 const QList<int> &shownModelsIndexes = ctx.renderer->getShownModelsIndexes();
497 BioStruct3DGLRenderer *rend = BioStruct3DGLRendererRegistry::createRenderer(name, *ctx.biostruct, ctx.colorScheme.data(), shownModelsIndexes, &rendererSettings);
498 assert(rend);
499 ctx.renderer = QSharedPointer<BioStruct3DGLRenderer>(rend);
500 }
501 }
502
updateAllColorSchemes()503 void BioStruct3DGLWidget::updateAllColorSchemes() {
504 foreach (const BioStruct3DRendererContext &ctx, contexts) {
505 ctx.renderer->updateColorScheme();
506 }
507 }
508
updateAllRenderers()509 void BioStruct3DGLWidget::updateAllRenderers() {
510 foreach (const BioStruct3DRendererContext &ctx, contexts) {
511 ctx.renderer->update();
512 }
513 }
514
setBackgroundColor(QColor backgroundColor)515 void BioStruct3DGLWidget::setBackgroundColor(QColor backgroundColor) {
516 this->backgroundColor = backgroundColor;
517 glClearColor(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF(), backgroundColor.alphaF());
518 }
519
zoom(float delta)520 void BioStruct3DGLWidget::zoom(float delta) {
521 bool syncLock = isSyncModeOn();
522 QList<GLFrame *> frames = frameManager->getActiveGLFrameList(glFrame.data(), syncLock);
523 foreach (GLFrame *frame, frames) {
524 frame->makeCurrent();
525 frame->performZoom(delta);
526 frame->updateViewPort();
527 frame->updateGL();
528 }
529 }
530
shift(float deltaX,float deltaY)531 void BioStruct3DGLWidget::shift(float deltaX, float deltaY) {
532 bool syncLock = isSyncModeOn();
533 QList<GLFrame *> frames = frameManager->getActiveGLFrameList(glFrame.data(), syncLock);
534 foreach (GLFrame *frame, frames) {
535 frame->makeCurrent();
536 frame->performShift(deltaX, deltaY);
537 frame->updateViewPort();
538 frame->updateGL();
539 }
540 }
541
saveDefaultSettings()542 void BioStruct3DGLWidget::saveDefaultSettings() {
543 glFrame->writeStateToMap(defaultsSettings);
544 defaultsSettings[COLOR_SCHEME_NAME] = QVariant::fromValue(currentColorSchemeName);
545 defaultsSettings[RENDERER_NAME] = QVariant::fromValue(currentGLRendererName);
546 }
547
restoreDefaultSettigns()548 void BioStruct3DGLWidget::restoreDefaultSettigns() {
549 assert(!defaultsSettings.isEmpty());
550 bool syncLock = isSyncModeOn();
551 QList<GLFrame *> frames = frameManager->getActiveGLFrameList(glFrame.data(), syncLock);
552 foreach (GLFrame *frame, frames) {
553 frame->makeCurrent();
554 frame->setState(defaultsSettings);
555 frame->updateViewPort();
556 frame->updateGL();
557 }
558 }
559
showModel(int modelId,bool show)560 void BioStruct3DGLWidget::showModel(int modelId, bool show) {
561 BioStruct3DRendererContext &ctx = contexts.first();
562
563 // this function uses modelId - key from BioStruct3D::modelMap
564 int idx = ctx.biostruct->modelMap.keys().indexOf(modelId);
565 assert(idx != -1);
566
567 QList<int> shownModelsIndexes = ctx.renderer->getShownModelsIndexes();
568
569 if (show && !shownModelsIndexes.contains(idx)) {
570 shownModelsIndexes.append(idx);
571 } else if (!show) {
572 shownModelsIndexes.removeAll(idx);
573 }
574 ctx.renderer->setShownModelsIndexes(shownModelsIndexes);
575 }
576
showAllModels(bool show)577 void BioStruct3DGLWidget::showAllModels(bool show) {
578 BioStruct3DRendererContext &ctx = contexts.first();
579
580 QList<int> shownModelsIndexes;
581 if (show) {
582 int numModels = ctx.biostruct->modelMap.size();
583 for (int i = 0; i < numModels; ++i) {
584 shownModelsIndexes.append(i);
585 }
586 }
587 ctx.renderer->setShownModelsIndexes(shownModelsIndexes);
588 }
589
sl_selectModels()590 void BioStruct3DGLWidget::sl_selectModels() {
591 BioStruct3DRendererContext &ctx = contexts.first();
592 QObjectScopedPointer<SelectModelsDialog> dlg = new SelectModelsDialog(ctx.biostruct->getModelsNames(), ctx.renderer->getShownModelsIndexes(), this);
593 dlg->exec();
594 CHECK(!dlg.isNull(), );
595
596 if (dlg->result() == QDialog::Accepted) {
597 ctx.renderer->setShownModelsIndexes(dlg->getSelectedModelsIndexes());
598
599 contexts.first().renderer->updateShownModels();
600 update();
601 }
602 }
603
writeImage2DToFile(int format,int options,int nbcol,const char * fileName)604 void BioStruct3DGLWidget::writeImage2DToFile(int format, int options, int nbcol, const char *fileName) {
605 FILE *fp = nullptr;
606 const char *FOPEN_ARGS = "wb";
607 const QByteArray title(fileName);
608 int state = GL2PS_OVERFLOW, buffsize = 0;
609 GLint viewport[4];
610 int sort = GL2PS_SIMPLE_SORT;
611
612 fp = fopen(fileName, FOPEN_ARGS);
613
614 if (!fp) {
615 QMessageBox::warning(this, tr("Error"), tr("Unable to open file %1 for writing").arg(fileName));
616 return;
617 }
618
619 glGetIntegerv(GL_VIEWPORT, viewport);
620
621 if (format == GL2PS_EPS) {
622 // hack -> make widget aspect ratio 1:1
623 if (width() > height()) {
624 int size = height();
625 resize(size, size);
626 }
627 }
628
629 while (state == GL2PS_OVERFLOW) {
630 buffsize += 2048 * 2048;
631 gl2psBeginPage(title.constData(), "Unipro UGENE BioStruct3D Viewer plugin", viewport, format, sort, options, GL_RGBA, 0, nullptr, nbcol, nbcol, nbcol, buffsize, fp, fileName);
632 paintGL();
633 state = gl2psEndPage();
634 }
635
636 fclose(fp);
637
638 if (format == GL2PS_EPS) {
639 // restore sizes
640 updateGeometry();
641 }
642 }
643
loadColorSchemes()644 void BioStruct3DGLWidget::loadColorSchemes() {
645 currentColorSchemeName = BioStruct3DColorSchemeRegistry::defaultFactoryName();
646
647 // highlight default color scheme in menu
648 QList<QAction *>::iterator iter;
649 QList<QAction *> schemeActions = colorSchemeActions->actions();
650 for (iter = schemeActions.begin(); iter != schemeActions.end(); ++iter) {
651 if ((*iter)->text() == currentColorSchemeName) {
652 (*iter)->setChecked(true);
653 break;
654 }
655 }
656 assert(iter != schemeActions.end());
657 }
658
loadGLRenderers(const QList<QString> & availableRenderers)659 void BioStruct3DGLWidget::loadGLRenderers(const QList<QString> &availableRenderers) {
660 // highlight current renderer in menu
661
662 foreach (QAction *ac, rendererActions->actions()) {
663 // disable all unavailable renderers in menu
664 if (!availableRenderers.contains(ac->text())) {
665 ac->setDisabled(true);
666 }
667
668 if (ac->text() == currentGLRendererName) {
669 ac->setChecked(true);
670 }
671 }
672
673 QString surfaceRendererName = ConvexMapRenderer::ID;
674 surfaceRenderer.reset(MolecularSurfaceRendererRegistry::createMSRenderer(surfaceRendererName));
675 }
676
isSyncModeOn()677 bool BioStruct3DGLWidget::isSyncModeOn() {
678 Qt::KeyboardModifiers km = QApplication::keyboardModifiers();
679 bool synchronizationMode = km.testFlag(Qt::ShiftModifier) || frameManager->getSyncLock();
680 synchronizationMode &= frameManager->getGLFrames().count() > 1;
681 return synchronizationMode;
682 }
683
checkRenderingAndCreateLblError()684 void BioStruct3DGLWidget::checkRenderingAndCreateLblError() {
685 QOffscreenSurface surf;
686 QOpenGLContext ctx;
687 surf.create();
688 ctx.create();
689 ctx.makeCurrent(&surf);
690
691 GLenum error = glGetError();
692 bool canRender = error == GL_NO_ERROR;
693 if (!canRender) {
694 coreLog.info(tr("The \"3D Structure Viewer\" was disabled, because OpenGL has error ") +
695 QString("(%1): %2").arg(error).arg(reinterpret_cast<const char *>(gluErrorString(error))));
696 lblGlError = new QLabel("Failed to initialize OpenGL", this);
697 lblGlError->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
698 lblGlError->setStyleSheet("QLabel { background-color : black; color : white; }");
699 }
700 }
701
setUnselectedShadingLevel(int shading)702 void BioStruct3DGLWidget::setUnselectedShadingLevel(int shading) {
703 foreach (const BioStruct3DRendererContext &ctx, contexts) {
704 ctx.colorScheme->setUnselectedShadingLevel((double)shading / 100.0);
705 }
706 updateAllColorSchemes();
707 }
708
getDisplayMenu()709 QMenu *BioStruct3DGLWidget::getDisplayMenu() {
710 assert(displayMenu != nullptr);
711 return displayMenu;
712 }
713
mousePressEvent(QMouseEvent * event)714 void BioStruct3DGLWidget::mousePressEvent(QMouseEvent *event) {
715 lastPos = getTrackballMapping(event->x(), event->y());
716 }
717
mouseMoveEvent(QMouseEvent * event)718 void BioStruct3DGLWidget::mouseMoveEvent(QMouseEvent *event) {
719 if (event->buttons() & Qt::LeftButton) {
720 Vector3D curPos = getTrackballMapping(event->x(), event->y());
721 Vector3D delta = curPos - lastPos;
722
723 if (delta.x || delta.y || delta.z) {
724 rotAngle = 90.0f * delta.length();
725 rotAxis = vector_cross(lastPos, curPos);
726
727 bool syncLock = isSyncModeOn();
728 QList<GLFrame *> frames = frameManager->getActiveGLFrameList(glFrame.data(), syncLock);
729 foreach (GLFrame *frame, frames) {
730 frame->makeCurrent();
731
732 if (event->modifiers() & Qt::CTRL)
733 frame->performShift(delta.x, delta.y);
734 else
735 frame->rotateCamera(rotAxis, rotAngle);
736
737 frame->updateGL();
738 }
739 }
740
741 lastPos = curPos;
742 }
743 }
744
wheelEvent(QWheelEvent * event)745 void BioStruct3DGLWidget::wheelEvent(QWheelEvent *event) {
746 float numDegrees = event->delta() / 8;
747 zoom(numDegrees / 10);
748 }
749
createActions()750 void BioStruct3DGLWidget::createActions() {
751 QAction *action = nullptr;
752
753 animationTimer = new QTimer(this);
754 animationTimer->setInterval(20); // fixed interval
755 connect(animationTimer, SIGNAL(timeout()), this, SLOT(sl_updateAnnimation()));
756
757 rendererActions = new QActionGroup(this);
758 connect(rendererActions, SIGNAL(triggered(QAction *)), this, SLOT(sl_selectGLRenderer(QAction *)));
759
760 foreach (const QString &key, BioStruct3DGLRendererRegistry::factoriesNames()) {
761 action = new QAction(key, rendererActions);
762 action->setCheckable(true);
763 action->setObjectName(action->text());
764 }
765
766 colorSchemeActions = new QActionGroup(this);
767 connect(colorSchemeActions, SIGNAL(triggered(QAction *)), this, SLOT(sl_selectColorScheme(QAction *)));
768 foreach (const QString &key, BioStruct3DColorSchemeRegistry::factoriesNames()) {
769 action = new QAction(key, colorSchemeActions);
770 action->setCheckable(true);
771 action->setObjectName(key);
772 }
773
774 molSurfaceRenderActions = new QActionGroup(this);
775 connect(molSurfaceRenderActions, SIGNAL(triggered(QAction *)), this, SLOT(sl_selectSurfaceRenderer(QAction *)));
776 foreach (const QString &key, MolecularSurfaceRendererRegistry::factoriesNames()) {
777 action = new QAction(key, molSurfaceRenderActions);
778 action->setCheckable(true);
779 if (key == ConvexMapRenderer::ID) {
780 action->setChecked(true);
781 }
782 }
783
784 molSurfaceTypeActions = new QActionGroup(this);
785 foreach (QString key, AppContext::getMolecularSurfaceFactoryRegistry()->getSurfNameList()) {
786 action = new QAction(key, molSurfaceTypeActions);
787 action->setObjectName(key);
788 connect(action, SIGNAL(triggered()), this, SLOT(sl_showSurface()));
789 action->setCheckable(true);
790 bool hasConstraints = AppContext::getMolecularSurfaceFactoryRegistry()->getSurfaceFactory(key)->hasConstraints(*contexts.first().biostruct);
791 action->setEnabled(!hasConstraints);
792 }
793 action = new QAction(tr("Off"), molSurfaceTypeActions);
794 connect(action, SIGNAL(triggered()), this, SLOT(sl_hideSurface()));
795 action->setCheckable(true);
796 action->setChecked(true);
797
798 selectModelsAction = 0;
799 if (!contexts.isEmpty() && contexts.first().biostruct->getModelsNames().size() > 1) {
800 selectModelsAction = new QAction(tr("Models.."), this);
801 connect(selectModelsAction, SIGNAL(triggered()), this, SLOT(sl_selectModels()));
802 }
803
804 spinAction = new QAction(tr("Spin"), this);
805 spinAction->setCheckable(true);
806 connect(spinAction, SIGNAL(triggered()), this, SLOT(sl_acitvateSpin()));
807
808 settingsAction = new QAction(tr("Settings..."), this);
809 connect(settingsAction, SIGNAL(triggered()), this, SLOT(sl_settings()));
810
811 closeAction = new QAction(tr("Close"), this);
812 connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
813
814 exportImageAction = new QAction(tr("Export Image..."), this);
815 connect(exportImageAction, SIGNAL(triggered()), this, SLOT(sl_exportImage()));
816
817 createStrucluralAlignmentActions();
818
819 connect(AppContext::getTaskScheduler(), SIGNAL(si_stateChanged(Task *)), SLOT(sl_onTaskFinished(Task *)));
820 }
821
createStrucluralAlignmentActions()822 void BioStruct3DGLWidget::createStrucluralAlignmentActions() {
823 alignWithAction = new QAction(tr("Align With..."), this);
824 alignWithAction->setObjectName("align_with");
825 connect(alignWithAction, SIGNAL(triggered()), this, SLOT(sl_alignWith()));
826
827 resetAlignmentAction = new QAction(tr("Reset"), this);
828 connect(resetAlignmentAction, SIGNAL(triggered()), this, SLOT(sl_resetAlignment()));
829 }
830
createMenus()831 void BioStruct3DGLWidget::createMenus() {
832 // Renderer selection
833 selectRendererMenu = new QMenu(tr("Render Style"));
834 selectRendererMenu->addActions(rendererActions->actions());
835 selectRendererMenu->menuAction()->setObjectName("Render Style");
836
837 // Color scheme selection
838 selectColorSchemeMenu = new QMenu(tr("Coloring Scheme"));
839 selectColorSchemeMenu->addActions(colorSchemeActions->actions());
840 selectColorSchemeMenu->menuAction()->setObjectName("Coloring Scheme");
841
842 // Molecular surface
843 QMenu *surfaceMenu = new QMenu(tr("Molecular Surface Render Style"));
844 surfaceMenu->addActions(molSurfaceRenderActions->actions());
845 surfaceMenu->menuAction()->setObjectName("Molecular Surface Render Style");
846
847 QMenu *surfaceTypeMenu = new QMenu(tr("Molecular Surface"));
848 surfaceTypeMenu->addActions(molSurfaceTypeActions->actions());
849 surfaceTypeMenu->menuAction()->setObjectName("Molecular Surface");
850
851 // Display (context) menu
852 displayMenu = new QMenu(this);
853 displayMenu->addMenu(selectRendererMenu);
854 displayMenu->addMenu(selectColorSchemeMenu);
855
856 displayMenu->addMenu(surfaceMenu);
857 displayMenu->addMenu(surfaceTypeMenu);
858
859 if (selectModelsAction) {
860 displayMenu->addAction(selectModelsAction);
861 }
862
863 displayMenu->addAction(spinAction);
864 displayMenu->addAction(settingsAction);
865 displayMenu->addAction(exportImageAction);
866
867 QMenu *saMenu = createStructuralAlignmentMenu();
868 displayMenu->addMenu(saMenu);
869 }
870
createStructuralAlignmentMenu()871 QMenu *BioStruct3DGLWidget::createStructuralAlignmentMenu() {
872 QMenu *saMenu = new QMenu(tr("Structural Alignment"));
873 saMenu->menuAction()->setObjectName("Structural Alignment");
874
875 saMenu->addAction(alignWithAction);
876 saMenu->addAction(resetAlignmentAction);
877
878 return saMenu;
879 }
880
connectExternalSignals()881 void BioStruct3DGLWidget::connectExternalSignals() {
882 AnnotationSettingsRegistry *asr = AppContext::getAnnotationsSettingsRegistry();
883 connect(asr, SIGNAL(si_annotationSettingsChanged(const QStringList &)), this, SLOT(sl_updateRenderSettings(const QStringList &)));
884
885 const QList<ADVSequenceObjectContext *> seqContexts = dnaView->getSequenceContexts();
886
887 foreach (ADVSequenceObjectContext *ctx, seqContexts) {
888 connect(ctx->getSequenceSelection(),
889 SIGNAL(si_selectionChanged(LRegionsSelection *, const QVector<U2Region> &, const QVector<U2Region> &)),
890 SLOT(sl_onSequenceSelectionChanged(LRegionsSelection *, const QVector<U2Region> &, const QVector<U2Region> &)));
891 }
892
893 connect(dnaView,
894 SIGNAL(si_sequenceAdded(ADVSequenceObjectContext *)),
895 SLOT(sl_onSequenceAddedToADV(ADVSequenceObjectContext *)));
896
897 connect(dnaView,
898 SIGNAL(si_sequenceRemoved(ADVSequenceObjectContext *)),
899 SLOT(sl_onSequenceRemovedFromADV(ADVSequenceObjectContext *)));
900 }
901
sl_onSequenceAddedToADV(ADVSequenceObjectContext * ctx)902 void BioStruct3DGLWidget::sl_onSequenceAddedToADV(ADVSequenceObjectContext *ctx) {
903 connect(ctx->getSequenceSelection(),
904 SIGNAL(si_selectionChanged(LRegionsSelection *, const QVector<U2Region> &, const QVector<U2Region> &)),
905 SLOT(sl_onSequenceSelectionChanged(LRegionsSelection *, const QVector<U2Region> &, const QVector<U2Region> &)));
906 }
907
sl_onSequenceRemovedFromADV(ADVSequenceObjectContext * ctx)908 void BioStruct3DGLWidget::sl_onSequenceRemovedFromADV(ADVSequenceObjectContext *ctx) {
909 disconnect(ctx->getSequenceSelection(), SIGNAL(si_selectionChanged(LRegionsSelection *, const QVector<U2Region> &, const QVector<U2Region> &)), this, SLOT(sl_onSequenceSelectionChanged(LRegionsSelection *, const QVector<U2Region> &, const QVector<U2Region> &)));
910 }
911
sl_selectColorScheme(QAction * action)912 void BioStruct3DGLWidget::sl_selectColorScheme(QAction *action) {
913 QString schemeName = action->text();
914
915 currentColorSchemeName = schemeName;
916 setupColorScheme(schemeName);
917
918 GLFrame *frame = frameManager->getGLWidgetFrame(this);
919 frame->makeCurrent();
920 frame->updateGL();
921 }
922
sl_updateRenderSettings(const QStringList & list)923 void BioStruct3DGLWidget::sl_updateRenderSettings(const QStringList &list) {
924 Q_UNUSED(list);
925 sl_selectColorScheme(colorSchemeActions->checkedAction());
926 }
927
sl_acitvateSpin()928 void BioStruct3DGLWidget::sl_acitvateSpin() {
929 if (spinAction->isChecked()) {
930 animationTimer->start();
931 } else {
932 animationTimer->stop();
933 }
934
935 update();
936 }
937
sl_updateAnnimation()938 void BioStruct3DGLWidget::sl_updateAnnimation() {
939 static float velocity = 0.05f;
940 spinAngle = velocity * animationTimer->interval();
941 Vector3D rotAxis(0, 1, 0);
942 bool syncLock = isSyncModeOn();
943 QList<GLFrame *> frames = frameManager->getActiveGLFrameList(glFrame.data(), syncLock);
944
945 foreach (GLFrame *frame, frames) {
946 frame->makeCurrent();
947 frame->rotateCamera(rotAxis, spinAngle);
948 frame->updateGL();
949 }
950 update();
951 }
952
sl_selectGLRenderer(QAction * action)953 void BioStruct3DGLWidget::sl_selectGLRenderer(QAction *action) {
954 QString rendererName = action->text();
955 currentGLRendererName = rendererName;
956 setupRenderer(currentGLRendererName);
957
958 GLFrame *frame = frameManager->getGLWidgetFrame(this);
959 frame->makeCurrent();
960 frame->updateGL();
961 }
962
sl_settings()963 void BioStruct3DGLWidget::sl_settings() {
964 QObjectScopedPointer<BioStruct3DSettingsDialog> dialog = new BioStruct3DSettingsDialog();
965
966 dialog->setWidget(this);
967
968 dialog->setBackgroundColor(backgroundColor);
969 dialog->setSelectionColor(selectionColor);
970 dialog->setRenderDetailLevel(rendererSettings.detailLevel);
971 dialog->setShadingLevel(unselectedShadingLevel);
972
973 dialog->setAnaglyphStatus(anaglyphStatus);
974 dialog->setAnaglyphSettings(anaglyph->getSettings());
975
976 QVariantMap previousState = getState();
977
978 dialog->exec();
979 CHECK(!dialog.isNull(), );
980
981 if (QDialog::Accepted == dialog->result()) {
982 backgroundColor = dialog->getBackgroundColor();
983 selectionColor = dialog->getSelectionColor();
984 unselectedShadingLevel = dialog->getShadingLevel();
985
986 foreach (const BioStruct3DRendererContext &ctx, contexts) {
987 ctx.colorScheme->setSelectionColor(selectionColor);
988 }
989 setUnselectedShadingLevel(unselectedShadingLevel);
990
991 rendererSettings.detailLevel = dialog->getRenderDetailLevel();
992
993 anaglyphStatus = dialog->getAnaglyphStatus();
994 anaglyph->setSettings(dialog->getAnaglyphSettings());
995
996 this->makeCurrent();
997 setBackgroundColor(backgroundColor);
998
999 update();
1000 } else {
1001 setState(previousState);
1002 }
1003 }
1004
sl_exportImage()1005 void BioStruct3DGLWidget::sl_exportImage() {
1006 BioStruct3DImageExportController factory(this);
1007 QString fileName = GUrlUtils::fixFileName(getBioStruct3DObjectName());
1008 QObjectScopedPointer<ExportImageDialog> dialog = new ExportImageDialog(&factory, ExportImageDialog::MolView, fileName, ExportImageDialog::SupportScaling, this);
1009 dialog->exec();
1010 }
1011
sl_showSurface()1012 void BioStruct3DGLWidget::sl_showSurface() {
1013 QList<SharedAtom> atoms;
1014 BioStruct3DRendererContext ctx = contexts.first();
1015 atoms = ctx.biostruct->getAllAtoms();
1016
1017 QString surfaceType = qobject_cast<QAction *>(sender())->text();
1018 surfaceCalcTask = new MolecularSurfaceCalcTask(surfaceType, atoms);
1019 AppContext::getTaskScheduler()->registerTopLevelTask(surfaceCalcTask);
1020 }
1021
sl_hideSurface()1022 void BioStruct3DGLWidget::sl_hideSurface() {
1023 molSurface.reset();
1024
1025 makeCurrent();
1026 update();
1027 }
1028
sl_selectSurfaceRenderer(QAction * action)1029 void BioStruct3DGLWidget::sl_selectSurfaceRenderer(QAction *action) {
1030 QString msRendererName = action->text();
1031 surfaceRenderer.reset(MolecularSurfaceRendererRegistry::createMSRenderer(msRendererName));
1032
1033 makeCurrent();
1034 update();
1035 }
1036
sl_onTaskFinished(Task * task)1037 void BioStruct3DGLWidget::sl_onTaskFinished(Task *task) {
1038 if (surfaceCalcTask != task || surfaceCalcTask->getState() != Task::State_Finished) {
1039 return;
1040 }
1041
1042 molSurface.reset(surfaceCalcTask->getCalculatedSurface());
1043
1044 makeCurrent();
1045 update();
1046 }
1047
1048 /** Convert modelId's list to modelIndexes list */
modelIdsToModelIdx(const BioStruct3D & bs,const QList<int> & modelsIds)1049 static QList<int> modelIdsToModelIdx(const BioStruct3D &bs, const QList<int> &modelsIds) {
1050 QList<int> modelsIdx;
1051 foreach (int modelId, modelsIds) {
1052 int idx = bs.getModelsNames().indexOf(modelId);
1053 assert(idx != -1 && "No such modelId in biostruct");
1054 modelsIdx << idx;
1055 }
1056
1057 return modelsIdx;
1058 }
1059
addBiostruct(const BioStruct3DObject * obj,const QList<int> & shownModels)1060 void BioStruct3DGLWidget::addBiostruct(const BioStruct3DObject *obj, const QList<int> &shownModels /* = QList<int>()*/) {
1061 assert(contexts.size() < 2 && "Multiple models in one view is unsupported now");
1062 BioStruct3DRendererContext ctx(obj);
1063
1064 QList<int> shownModelsIdx = modelIdsToModelIdx(*ctx.biostruct, shownModels);
1065
1066 // show only first model if model list is empty
1067 if (shownModelsIdx.isEmpty()) {
1068 shownModelsIdx << 0;
1069 }
1070
1071 BioStruct3DColorScheme *colorScheme = BioStruct3DColorSchemeRegistry::createColorScheme(currentColorSchemeName, ctx.obj);
1072 assert(colorScheme);
1073 ctx.colorScheme = QSharedPointer<BioStruct3DColorScheme>(colorScheme);
1074 ctx.colorScheme->setSelectionColor(selectionColor);
1075 ctx.colorScheme->setUnselectedShadingLevel((double)unselectedShadingLevel / 100.0);
1076
1077 BioStruct3DGLRenderer *renderer = BioStruct3DGLRendererRegistry::createRenderer(currentGLRendererName, *ctx.biostruct, ctx.colorScheme.data(), shownModelsIdx, &rendererSettings);
1078 assert(renderer);
1079 ctx.renderer = QSharedPointer<BioStruct3DGLRenderer>(renderer);
1080
1081 contexts.append(ctx);
1082 setupRenderer(currentGLRendererName);
1083
1084 setupFrame();
1085 }
1086
sl_alignWith()1087 void BioStruct3DGLWidget::sl_alignWith() {
1088 const BioStruct3DRendererContext &ctx = contexts.first();
1089 int currentModelId = ctx.biostruct->getModelsNames().at(ctx.renderer->getShownModelsIndexes().first());
1090
1091 QObjectScopedPointer<StructuralAlignmentDialog> dlg = new StructuralAlignmentDialog(contexts.first().obj, currentModelId);
1092 const int dialogResult = dlg->execIfAlgorithmAvailable();
1093 CHECK(!dlg.isNull(), );
1094
1095 if (QDialog::Accepted == dialogResult) {
1096 sl_resetAlignment();
1097
1098 Task *task = dlg->getTask();
1099 assert(task && "If dialog accepded it must return valid task");
1100
1101 TaskSignalMapper *taskMapper = new TaskSignalMapper(task);
1102 connect(taskMapper, SIGNAL(si_taskFinished(Task *)), this, SLOT(sl_onAlignmentDone(Task *)));
1103
1104 AppContext::getTaskScheduler()->registerTopLevelTask(task);
1105 }
1106 }
1107
sl_resetAlignment()1108 void BioStruct3DGLWidget::sl_resetAlignment() {
1109 assert(contexts.size() < 3 && "Multiple models in one view is unsupported now");
1110 if (contexts.size() == 2) {
1111 contexts.removeLast();
1112 setupFrame();
1113
1114 glFrame->makeCurrent();
1115 update();
1116 }
1117 }
1118
sl_onAlignmentDone(Task * task)1119 void BioStruct3DGLWidget::sl_onAlignmentDone(Task *task) {
1120 if (!task->hasError()) {
1121 StructuralAlignmentTask *saTask = qobject_cast<StructuralAlignmentTask *>(task);
1122 assert(saTask && "Task should have type StructuralAlignmentTask");
1123
1124 StructuralAlignment result = saTask->getResult();
1125 StructuralAlignmentTaskSettings settings = saTask->getSettings();
1126
1127 const Matrix44 &mt = result.transform;
1128 const_cast<BioStruct3D *>(&settings.alt.obj->getBioStruct3D())->setTransform(mt);
1129
1130 addBiostruct(settings.alt.obj, QList<int>() << settings.alt.modelId);
1131
1132 glFrame->makeCurrent();
1133 update();
1134 }
1135 }
1136
1137 } // namespace U2
1138