"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "layer1/Scene.cpp" between
pymol-open-source-2.2.0.tar.gz and pymol-open-source-2.3.0.tar.gz

About: PyMOL is a Python-enhanced molecular graphics tool. It excels at 3D visualization of proteins, small molecules, density, surfaces, and trajectories. It also includes molecular editing, ray tracing, and movies. Open Source version.

Scene.cpp  (pymol-open-source-2.2.0):Scene.cpp  (pymol-open-source-2.3.0)
skipping to change at line 23 skipping to change at line 23
-* -*
Z* ------------------------------------------------------------------- Z* -------------------------------------------------------------------
*/ */
#include"os_std.h" #include"os_std.h"
#include"os_gl.h" #include"os_gl.h"
#include"os_python.h" #include"os_python.h"
#include"os_numpy.h" #include"os_numpy.h"
#include"Util.h" #include"Util.h"
#include"LangUtil.h"
#include"Word.h" #include"Word.h"
#include"main.h" #include"main.h"
#include"Base.h" #include"Base.h"
#include"MemoryDebug.h" #include"MemoryDebug.h"
#include"Err.h" #include"Err.h"
#include"Matrix.h" #include"Matrix.h"
#include"ListMacros.h" #include"ListMacros.h"
#include"PyMOLObject.h" #include"PyMOLObject.h"
#include"Scene.h" #include"Scene.h"
skipping to change at line 65 skipping to change at line 66
#include"PyMOL.h" #include"PyMOL.h"
#include"PConv.h" #include"PConv.h"
#include"ScrollBar.h" #include"ScrollBar.h"
#include "ShaderMgr.h" #include "ShaderMgr.h"
#include "PopUp.h" #include "PopUp.h"
#include "MacPyMOL.h" #include "MacPyMOL.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#ifdef _PYMOL_IP_EXTRAS
#include "IncentiveCopyToClipboard.h"
#endif
#include <algorithm>
#include <iostream>
using namespace std;
static void glReadBufferError(PyMOLGlobals *G, GLenum b, GLenum e){ static void glReadBufferError(PyMOLGlobals *G, GLenum b, GLenum e){
PRINTFB(G, FB_OpenGL, FB_Warnings) PRINTFB(G, FB_OpenGL, FB_Warnings)
" WARNING: glReadBuffer caused GL error 0x%04x\n", e ENDFB(G); " WARNING: glReadBuffer caused GL error 0x%04x\n", e ENDFB(G);
} }
// TH 2013-11-01: glReadBuffer fails in JyMOL when picking, OSX 10.9, Intel Grap hics // TH 2013-11-01: glReadBuffer fails in JyMOL when picking, OSX 10.9, Intel Grap hics
// for minor cases (i.e., png is called) this might get called outside of the ma in // for minor cases (i.e., png is called) this might get called outside of the ma in
// thread (from ExecutiveDrawNow()) in this case, just don't call glReadBuffer f or // thread (from ExecutiveDrawNow()) in this case, just don't call glReadBuffer f or
// now, it should be ok because i believe it is used to figure out the size of t he // now, it should be ok because i believe it is used to figure out the size of t he
// 3D window (using SceneImagePrepareImpl) in situations where the size gets cha nged. // 3D window (using SceneImagePrepareImpl) in situations where the size gets cha nged.
#define glReadBuffer(b) { int e; if (PIsGlutThread()) glReadBuffer(b); \ #define glReadBuffer(b) { int e; if (PIsGlutThread()) glReadBuffer(b); \
skipping to change at line 283 skipping to change at line 275
} }
break; break;
case 2: case 2:
case 3: case 3:
if(I->SlotVLA) { if(I->SlotVLA) {
VLAFreeP(I->SlotVLA); VLAFreeP(I->SlotVLA);
I->SlotVLA = NULL; I->SlotVLA = NULL;
} }
{ {
int max_slot = 0; int max_slot = 0;
for ( auto it = I->Obj.begin(); it != I->Obj.end(); ++it) { for (auto& obj : I->Obj) {
if((*it)->fGetNFrame) { if(obj->fGetNFrame) {
slot = (*it)->fGetNFrame(*it); slot = obj->fGetNFrame(obj);
if(grid_mode == 3) { if(grid_mode == 3) {
(*it)->grid_slot = max_slot; // slot offset for 1st state obj->grid_slot = max_slot; // slot offset for 1st state
max_slot += slot; max_slot += slot;
} else if(max_slot < slot) { } else if(max_slot < slot) {
max_slot = slot; max_slot = slot;
} }
} }
} }
size = max_slot; size = max_slot;
} }
break; break;
} }
skipping to change at line 310 skipping to change at line 302
if(grid_max >= 0) if(grid_max >= 0)
if(size > grid_max) if(size > grid_max)
size = grid_max; size = grid_max;
} }
return size; return size;
} }
int SceneHasImage(PyMOLGlobals * G) int SceneHasImage(PyMOLGlobals * G)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
return (I->Image && I->Image->data); return (I->Image && !I->Image->empty());
} }
int SceneMustDrawBoth(PyMOLGlobals * G) int SceneMustDrawBoth(PyMOLGlobals * G)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
return (G->StereoCapable && return (G->StereoCapable &&
((I->StereoMode == 1) || ((I->StereoMode == 1) ||
SettingGetGlobal_b(G, cSetting_stereo_double_pump_mono))); SettingGetGlobal_b(G, cSetting_stereo_double_pump_mono)));
} }
skipping to change at line 370 skipping to change at line 362
if(click_side) if(click_side)
*click_side = 1; /* right */ *click_side = 1; /* right */
} else { } else {
if(click_side) if(click_side)
*click_side = -1; /* left */ *click_side = -1; /* left */
} }
} }
return x; return x;
} }
int SceneLoopDrag(Block * block, int x, int y, int mod);
int SceneLoopRelease(Block * block, int button, int x, int y, int mod);
int SceneLoopClick(Block * block, int button, int x, int y, int mod);
void SceneAbortAnimation(PyMOLGlobals * G) void SceneAbortAnimation(PyMOLGlobals * G)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
if(I->cur_ani_elem < I->n_ani_elem) { /* allow user to override animation */ if(I->cur_ani_elem < I->n_ani_elem) { /* allow user to override animation */
I->cur_ani_elem = I->n_ani_elem; I->cur_ani_elem = I->n_ani_elem;
} }
} }
void ScenePrimeAnimation(PyMOLGlobals * G) void ScenePrimeAnimation(PyMOLGlobals * G)
{ {
skipping to change at line 411 skipping to change at line 398
else /* 0 fps means use movie_delay instead */ else /* 0 fps means use movie_delay instead */
minTime = SettingGetGlobal_f(G, cSetting_movie_delay) / 1000.0; minTime = SettingGetGlobal_f(G, cSetting_movie_delay) / 1000.0;
if(minTime >= 0.0F) if(minTime >= 0.0F)
fps = 1.0F / minTime; fps = 1.0F / minTime;
else else
fps = 1000.0F; fps = 1000.0F;
} }
return fps; return fps;
} }
void ScenePurgeImageImpl(PyMOLGlobals * G, int noinvalid); /**
* Release `G->Scene->Image` and clear related flags (`CopyType`).
*
* Invalidates the Ortho CGO and requests a redisplay. It's not entirely clear
* why this is done, a code comment says "need to invalidate since text could be
* shown".
*/
static void ScenePurgeImage(PyMOLGlobals * G) static void ScenePurgeImage(PyMOLGlobals * G)
{ {
ScenePurgeImageImpl(G, 0);
}
void ScenePurgeImageImpl(PyMOLGlobals * G, int noinvalid)
{
CScene *I = G->Scene; CScene *I = G->Scene;
if(I->MovieOwnsImageFlag) {
I->MovieOwnsImageFlag = false;
I->Image = NULL;
} else {
if(I->Image) {
FreeP(I->Image->data);
}
FreeP(I->Image);
}
I->CopyType = false; I->CopyType = false;
if (!noinvalid) I->Image = nullptr;
// TODO does this belong here?
if (true /* !noinvalid */)
OrthoInvalidateDoDraw(G); // right now, need to invalidate since text could be shown OrthoInvalidateDoDraw(G); // right now, need to invalidate since text could be shown
} }
void SceneInvalidateCopy(PyMOLGlobals * G, int free_buffer) void SceneInvalidateCopy(PyMOLGlobals * G, int free_buffer)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
if(I) { if(I) {
if(I->MovieOwnsImageFlag) { if(free_buffer){
I->MovieOwnsImageFlag = false;
I->Image = NULL;
} else if(free_buffer) {
ScenePurgeImage(G); ScenePurgeImage(G);
} }
else{
I->Image = nullptr;
}
if (I->CopyType) if (I->CopyType)
OrthoInvalidateDoDraw(G); // right now, need to invalidate since text coul d be shown OrthoInvalidateDoDraw(G); // right now, need to invalidate since text coul d be shown
I->CopyType = false; I->CopyType = false;
} }
} }
void SceneInvalidate(PyMOLGlobals * G) void SceneInvalidate(PyMOLGlobals * G)
{ {
SceneInvalidateCopy(G, false); SceneInvalidateCopy(G, false);
SceneDirty(G); SceneDirty(G);
skipping to change at line 488 skipping to change at line 469
SceneFromViewElem(G, I->ani_elem, true); SceneFromViewElem(G, I->ani_elem, true);
I->cur_ani_elem = 0; I->cur_ani_elem = 0;
I->n_ani_elem = target; I->n_ani_elem = target;
I->AnimationStartTime = UtilGetSeconds(G); I->AnimationStartTime = UtilGetSeconds(G);
I->AnimationStartFlag = true; I->AnimationStartFlag = true;
I->AnimationStartFrame = SceneGetFrame(G); I->AnimationStartFrame = SceneGetFrame(G);
I->AnimationLagTime = 0.0; I->AnimationLagTime = 0.0;
} }
} }
static
int SceneLoopClick(Block * block, int button, int x, int y, int mod) int SceneLoopClick(Block * block, int button, int x, int y, int mod)
{ {
PyMOLGlobals *G = block->G; PyMOLGlobals *G = block->m_G;
CScene *I = G->Scene; CScene *I = G->Scene;
I->LoopRect.left = x; I->LoopRect.left = x;
I->LoopRect.top = y; I->LoopRect.top = y;
I->LoopRect.right = x; I->LoopRect.right = x;
I->LoopRect.bottom = y; I->LoopRect.bottom = y;
I->LoopFlag = true; I->LoopFlag = true;
I->LoopMod = mod; I->LoopMod = mod;
OrthoSetLoopRect(G, true, &I->LoopRect); OrthoSetLoopRect(G, true, &I->LoopRect);
OrthoGrab(G, block); OrthoGrab(G, block);
return 1; return 1;
} }
static
int SceneLoopDrag(Block * block, int x, int y, int mod) int SceneLoopDrag(Block * block, int x, int y, int mod)
{ {
PyMOLGlobals *G = block->G; PyMOLGlobals *G = block->m_G;
CScene *I = G->Scene; CScene *I = G->Scene;
I->LoopRect.right = x; I->LoopRect.right = x;
I->LoopRect.bottom = y; I->LoopRect.bottom = y;
OrthoSetLoopRect(G, true, &I->LoopRect); OrthoSetLoopRect(G, true, &I->LoopRect);
return 1; return 1;
} }
static
int SceneLoopRelease(Block * block, int button, int x, int y, int mod) int SceneLoopRelease(Block * block, int button, int x, int y, int mod)
{ {
PyMOLGlobals *G = block->G; PyMOLGlobals *G = block->m_G;
CScene *I = G->Scene; CScene *I = G->Scene;
int tmp; int tmp;
int mode; int mode;
mode = ButModeTranslate(G, button, I->LoopMod); mode = ButModeTranslate(G, button, I->LoopMod);
if(I->LoopRect.top < I->LoopRect.bottom) { if(I->LoopRect.top < I->LoopRect.bottom) {
tmp = I->LoopRect.top; tmp = I->LoopRect.top;
I->LoopRect.top = I->LoopRect.bottom; I->LoopRect.top = I->LoopRect.bottom;
I->LoopRect.bottom = tmp; I->LoopRect.bottom = tmp;
} }
skipping to change at line 539 skipping to change at line 523
I->LoopRect.left = tmp; I->LoopRect.left = tmp;
} }
OrthoSetLoopRect(G, false, &I->LoopRect); OrthoSetLoopRect(G, false, &I->LoopRect);
ExecutiveSelectRect(G, &I->LoopRect, mode); ExecutiveSelectRect(G, &I->LoopRect, mode);
I->LoopFlag = false; I->LoopFlag = false;
OrthoUngrab(G); OrthoUngrab(G);
OrthoDirty(G); OrthoDirty(G);
return 1; return 1;
} }
/* /**
* Set FrontSafe and BackSafe * Set FrontSafe and BackSafe
*/ */
static void UpdateFrontBackSafe(CScene *I) static void UpdateFrontBackSafe(CScene *I)
{ {
float front = I->Front; float front = I->Front;
float back = I->Back; float back = I->Back;
// minimum slab // minimum slab
if(back - front < cSliceMin) { if(back - front < cSliceMin) {
float avg = (back + front) / 2.0; float avg = (back + front) / 2.0;
skipping to change at line 608 skipping to change at line 592
im[14] = 0.0F; im[14] = 0.0F;
im[15] = 1.0F; im[15] = 1.0F;
} }
void SceneUpdateStereo(PyMOLGlobals * G) void SceneUpdateStereo(PyMOLGlobals * G)
{ {
SceneSetStereo(G, SettingGetGlobal_b(G, cSetting_stereo)); SceneSetStereo(G, SettingGetGlobal_b(G, cSetting_stereo));
PyMOL_NeedRedisplay(G->PyMOL); PyMOL_NeedRedisplay(G->PyMOL);
} }
char *SceneGetSeleModeKeyword(PyMOLGlobals * G) /**
* Get the selection operator for the `mouse_selection_mode` setting.
* Example: `mouse_selection_mode=2` -> "bychain"
*/
const char *SceneGetSeleModeKeyword(PyMOLGlobals * G)
{ {
int sel_mode = SettingGetGlobal_i(G, cSetting_mouse_selection_mode); int sel_mode = SettingGetGlobal_i(G, cSetting_mouse_selection_mode);
if((sel_mode >= 0) && (sel_mode < SELE_MODE_MAX)) if((sel_mode >= 0) && (sel_mode < SELE_MODE_MAX))
return (char *) SelModeKW[sel_mode]; return (char *) SelModeKW[sel_mode];
return (char *) SelModeKW[0]; return (char *) SelModeKW[0];
} }
void SceneDraw(Block * block ORTHOCGOARG);
void SceneToViewElem(PyMOLGlobals * G, CViewElem * elem, const char *scene_name) void SceneToViewElem(PyMOLGlobals * G, CViewElem * elem, const char *scene_name)
{ {
float *fp; float *fp;
double *dp; double *dp;
CScene *I = G->Scene; CScene *I = G->Scene;
/* copy rotation matrix */ /* copy rotation matrix */
elem->matrix_flag = true; elem->matrix_flag = true;
dp = elem->matrix; dp = elem->matrix;
fp = I->RotMatrix; fp = I->RotMatrix;
skipping to change at line 770 skipping to change at line 756
if(elem->state_flag&&!MovieDefined(G)) { if(elem->state_flag&&!MovieDefined(G)) {
SettingSetGlobal_i(G, cSetting_state, (elem->state)+1); SettingSetGlobal_i(G, cSetting_state, (elem->state)+1);
} }
if(changed_flag) { if(changed_flag) {
SceneRestartSweepTimer(G); SceneRestartSweepTimer(G);
I->RockFrame = 0; I->RockFrame = 0;
SceneRovingDirty(G); SceneRovingDirty(G);
} }
} }
void SceneCleanupStereo(PyMOLGlobals * G)
{
#ifndef _PYMOL_NOPY
CScene *I = G->Scene;
if(I->StereoMode == 1)
PSGIStereo(G, 0);
#endif
}
void ScenePrepareUnitContext(SceneUnitContext * context, int width, int height) void ScenePrepareUnitContext(SceneUnitContext * context, int width, int height)
{ {
float tw = 1.0F; float tw = 1.0F;
float th = 1.0F; float th = 1.0F;
float aspRat; float aspRat;
if(height) { if(height) {
aspRat = width / (float) height; aspRat = width / (float) height;
} else { } else {
aspRat = 1.0F; aspRat = 1.0F;
skipping to change at line 815 skipping to change at line 792
"ScenePrepareUnitContext:%8.3f %8.3f %8.3f %8.3f %8.3f %8.3f\n", "ScenePrepareUnitContext:%8.3f %8.3f %8.3f %8.3f %8.3f %8.3f\n",
context->unit_left, context->unit_left,
context->unit_right, context->unit_right,
context->unit_top, context->unit_top,
context->unit_bottom, context->unit_bottom,
context->unit_front, context->unit_front,
context->unit_back); context->unit_back);
*/ */
} }
/* /**
* cmd.get_viewport() * cmd.get_viewport()
*/ */
void SceneGetWidthHeight(PyMOLGlobals * G, int *width, int *height) void SceneGetWidthHeight(PyMOLGlobals * G, int *width, int *height)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
*width = I->Width; *width = I->Width;
*height = I->Height; *height = I->Height;
} }
/* /**
* Get the actual current (sub-)viewport size, considering grid mode and * Get the actual current (sub-)viewport size, considering grid mode and
* side-by-side stereo * side-by-side stereo
*/ */
void SceneGetWidthHeightStereo(PyMOLGlobals * G, int *width, int *height) void SceneGetWidthHeightStereo(PyMOLGlobals * G, int *width, int *height)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
if (I->grid.active) { if (I->grid.active) {
// TODO: this considers "draw W, H" (PYMOL-2775) // TODO: this considers "draw W, H" (PYMOL-2775)
*width = I->grid.cur_viewport_size[0]; *width = I->grid.cur_viewport_size[0];
skipping to change at line 881 skipping to change at line 858
(*renderer) = I->renderer; (*renderer) = I->renderer;
(*version) = I->version; (*version) = I->version;
} }
void SceneSuppressMovieFrame(PyMOLGlobals * G) void SceneSuppressMovieFrame(PyMOLGlobals * G)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
I->MovieFrameFlag = false; I->MovieFrameFlag = false;
} }
/* /**
* Get center of screen in world coordinates * Get center of screen in world coordinates
*
* @param[out] pos 3f output vector
*/ */
void SceneGetCenter(PyMOLGlobals * G, float *pos) void SceneGetCenter(PyMOLGlobals * G, float *pos)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
MatrixTransformC44fAs33f3f(I->RotMatrix, I->Origin, pos); MatrixTransformC44fAs33f3f(I->RotMatrix, I->Origin, pos);
pos[0] -= I->Pos[0]; pos[0] -= I->Pos[0];
pos[1] -= I->Pos[1]; pos[1] -= I->Pos[1];
skipping to change at line 906 skipping to change at line 885
/*========================================================================*/ /*========================================================================*/
int SceneGetNFrame(PyMOLGlobals * G, int *has_movie) int SceneGetNFrame(PyMOLGlobals * G, int *has_movie)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
if(has_movie) if(has_movie)
*has_movie = I->HasMovie; *has_movie = I->HasMovie;
return (I->NFrame); return (I->NFrame);
} }
/*========================================================================*/ /*========================================================================*/
/* SceneGetView: all information required to define the geometry /**
Get information required to define the geometry
of a particular view, for shipping to and from python of a particular view, for shipping to and from python
as a list of floats as a list of floats
@verbatim
0-15 = 4x4 rotation matrix 0-15 = 4x4 rotation matrix
16-18 = position 16-18 = position
19-21 = origin 19-21 = origin
22 = front plane 22 = front plane
23 = rear plane 23 = rear plane
24 = orthoscopic flag 24 = orthoscopic flag
@endverbatim
@param[out] view buffer to fill
*/ */
void SceneGetView(PyMOLGlobals * G, SceneViewType view) void SceneGetView(PyMOLGlobals * G, SceneViewType view)
{ {
float *p; float *p;
int a; int a;
CScene *I = G->Scene; CScene *I = G->Scene;
p = view; p = view;
for(a = 0; a < 16; a++) for(a = 0; a < 16; a++)
*(p++) = I->RotMatrix[a]; *(p++) = I->RotMatrix[a];
*(p++) = I->Pos[0]; *(p++) = I->Pos[0];
skipping to change at line 1388 skipping to change at line 1371
} else { } else {
SceneCopy(G, GL_BACK, true, true); SceneCopy(G, GL_BACK, true, true);
} }
if(!I->Image) if(!I->Image)
ok = false; ok = false;
if(ok && I->Image) { if(ok && I->Image) {
I->DirtyFlag = false; I->DirtyFlag = false;
I->CopyType = 2; /* suppresses display of copied image */ I->CopyType = 2; /* suppresses display of copied image */
if(SettingGetGlobal_b(G, cSetting_opaque_background)) if(SettingGetGlobal_b(G, cSetting_opaque_background))
I->Image->needs_alpha_reset = true; I->Image->m_needs_alpha_reset = true;
I->MovieOwnsImageFlag = false;
} }
} else { } else {
ok = false; ok = false;
} }
return ok; return ok;
} }
static int SceneMakeSizedImage(PyMOLGlobals * G, int width, int height, int anti alias) static int SceneMakeSizedImage(PyMOLGlobals * G, int width, int height, int anti alias)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
skipping to change at line 1488 skipping to change at line 1470
"Scene-Warning: Maximum OpenGL viewport exceeded. Antialiasing disab led." "Scene-Warning: Maximum OpenGL viewport exceeded. Antialiasing disab led."
ENDFB(G); ENDFB(G);
break; break;
} }
} }
} }
if(factor < 2) if(factor < 2)
factor = 0; factor = 0;
{ {
unsigned int final_buffer_size = width * height;
unsigned int *final_image = NULL;
int nXStep = (width / (I->Width + 1)) + 1; int nXStep = (width / (I->Width + 1)) + 1;
int nYStep = (height / (I->Height + 1)) + 1; int nYStep = (height / (I->Height + 1)) + 1;
int x, y; int x, y;
int draw_both = SceneMustDrawBoth(G); int draw_both = SceneMustDrawBoth(G);
/* note here we're treating the buffer as 32-bit unsigned ints, not chars */ /* note here we're treating the buffer as 32-bit unsigned ints, not chars */
final_image = Alloc(unsigned int, final_buffer_size); auto final_image = pymol::Image(width, height);
if(!final_image) {
ok = false;
}
ScenePurgeImage(G); ScenePurgeImage(G);
if(draw_both) { if(draw_both) {
SceneCopy(G, GL_BACK_LEFT, true, false); SceneCopy(G, GL_BACK_LEFT, true, false);
} else { } else {
SceneCopy(G, GL_BACK, true, false); SceneCopy(G, GL_BACK, true, false);
} }
if(!I->Image) if(!I->Image)
ok = false; ok = false;
skipping to change at line 1546 skipping to change at line 1523
SceneRender(G, NULL, x_offset, y_offset, NULL, width, height, 0, 0); SceneRender(G, NULL, x_offset, y_offset, NULL, width, height, 0, 0);
SceneGLClearColor(0.0, 0.0, 0.0, 1.0); SceneGLClearColor(0.0, 0.0, 0.0, 1.0);
if(draw_both) { if(draw_both) {
SceneCopy(G, GL_BACK_LEFT, true, false); SceneCopy(G, GL_BACK_LEFT, true, false);
} else { } else {
SceneCopy(G, GL_BACK, true, false); SceneCopy(G, GL_BACK, true, false);
} }
if(I->Image) { /* the image into place */ if(I->Image) { /* the image into place */
p = (unsigned int *) I->Image->data; p = I->Image->pixels();
q = final_image + (x * I->Width) + (y * I->Height) * width; q = final_image.pixels() + (x * I->Width) + (y * I->Height) * widt
h;
{ {
int y_limit; int y_limit;
int x_limit; int x_limit;
if(((y + 1) * I->Height) > height) if(((y + 1) * I->Height) > height)
y_limit = height - (y * I->Height); y_limit = height - (y * I->Height);
else else
y_limit = I->Height; y_limit = I->Height;
if(((x + 1) * I->Width) > width) if(((x + 1) * I->Width) > width)
x_limit = width - (x * I->Width); x_limit = width - (x * I->Width);
skipping to change at line 1591 skipping to change at line 1568
SceneInvalidateCopy(G, true); SceneInvalidateCopy(G, true);
if(factor) { /* are we oversampling? */ if(factor) { /* are we oversampling? */
unsigned int src_row_bytes = width * 4; unsigned int src_row_bytes = width * 4;
width = width / factor; width = width / factor;
height = height / factor; height = height / factor;
{ {
unsigned char *p = (unsigned char *) final_image; unsigned char *p = final_image.bits();
unsigned char *buffer = Alloc(unsigned char, 4 * width * height); auto buffer = pymol::Image(width, height);
unsigned char *q = buffer; unsigned char *q = buffer.bits();
unsigned char *pp, *ppp, *pppp; unsigned char *pp, *ppp, *pppp;
int a, b, c, d; int a, b, c, d;
unsigned int c1, c2, c3, c4, alpha; unsigned int c1, c2, c3, c4, alpha;
unsigned int factor_col_bytes = factor * 4; unsigned int factor_col_bytes = factor * 4;
unsigned int factor_row_bytes = factor * src_row_bytes; unsigned int factor_row_bytes = factor * src_row_bytes;
for(b = 0; b < height; b++) { /* rows */ for(b = 0; b < height; b++) { /* rows */
pp = p; pp = p;
for(a = 0; a < width; a++) { /* cols */ for(a = 0; a < width; a++) { /* cols */
c1 = c2 = c3 = c4 = 0; c1 = c2 = c3 = c4 = 0;
skipping to change at line 1646 skipping to change at line 1623
} }
*(q++) = c1; *(q++) = c1;
*(q++) = c2; *(q++) = c2;
*(q++) = c3; *(q++) = c3;
*(q++) = c4 >> shift; *(q++) = c4 >> shift;
pp += factor_col_bytes; pp += factor_col_bytes;
} }
p += factor_row_bytes; p += factor_row_bytes;
} }
FreeP(final_image); final_image = std::move(buffer);
final_image = (unsigned int *) buffer;
} }
} }
ScenePurgeImage(G); ScenePurgeImage(G);
I->Image = Calloc(ImageType, 1); I->Image = std::make_shared<pymol::Image>(std::move(final_image));
I->Image->data = (unsigned char *) final_image;
final_image = NULL;
I->Image->size = final_buffer_size * 4; /* in bytes, not 32-bit words */
I->Image->width = width;
I->Image->height = height;
I->Image->stereo = false;
I->DirtyFlag = false; I->DirtyFlag = false;
I->CopyType = true; I->CopyType = true;
I->CopyForced = true; I->CopyForced = true;
if(SettingGetGlobal_b(G, cSetting_opaque_background)) if(SettingGetGlobal_b(G, cSetting_opaque_background))
I->Image->needs_alpha_reset = true; I->Image->m_needs_alpha_reset = true;
I->MovieOwnsImageFlag = false;
} }
FreeP(final_image);
} }
} else { } else {
ok = false; ok = false;
} }
if(save_flag) { if(save_flag) {
I->Width = save_width; I->Width = save_width;
I->Height = save_height; I->Height = save_height;
} }
return ok; return ok;
} }
#define SceneImagePrepareImpl SceneImagePrepare /**
* Prepares the scene image for PNG export.
unsigned char *SceneImagePrepareImpl(PyMOLGlobals * G, int prior_only, int noinv *
alid) * If there is no rendered image (`G->Scene->CopyType` is false) then read the
* current image from the OpenGL back buffer.
*
* Sets the alpha channel to opaque if the `opaque_background` setting is on.
*
* Modifies `G->Scene->Image`.
*
* @param prior_only Return NULL if there is no prior image (`G->Scene->Image` i
s NULL)
* @return The scene image
*/
pymol::Image* SceneImagePrepare(PyMOLGlobals* G, bool prior_only)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
unsigned char *image = NULL; pymol::Image* image = nullptr;
int save_stereo = (I->StereoMode == 1); int save_stereo = (I->StereoMode == 1);
int ok = true; int ok = true;
if(!noinvalid && !(I->CopyType || prior_only)) { if (!(I->CopyType || prior_only)) {
if(G->HaveGUI && G->ValidContext) { if(G->HaveGUI && G->ValidContext) {
unsigned int buffer_size; ScenePurgeImage(G);
I->Image = std::make_shared<pymol::Image>(I->Width, I->Height, save_stereo
);
image = I->Image.get();
buffer_size = 4 * I->Width * I->Height; #ifndef PURE_OPENGL_ES_2
if(save_stereo)
image = Alloc(unsigned char, buffer_size * 2);
else
image = Alloc(unsigned char, buffer_size);
CHECKOK(ok, image);
if (!ok)
return NULL;
if(SceneMustDrawBoth(G) || save_stereo) { if(SceneMustDrawBoth(G) || save_stereo) {
glReadBuffer(GL_BACK_LEFT); glReadBuffer(GL_BACK_LEFT);
} else { } else {
glReadBuffer(GL_BACK); glReadBuffer(GL_BACK);
} }
PyMOLReadPixels(I->Block->rect.left, I->Block->rect.bottom, I->Width, I->H #endif
eight, PyMOLReadPixels(I->rect.left, I->rect.bottom, I->Width, I->Height,
GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *) (image)); GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *) (image->bits()));
#ifndef PURE_OPENGL_ES_2
if(save_stereo) { if(save_stereo) {
glReadBuffer(GL_BACK_RIGHT); glReadBuffer(GL_BACK_RIGHT);
PyMOLReadPixels(I->Block->rect.left, I->Block->rect.bottom, I->Width, I- PyMOLReadPixels(I->rect.left, I->rect.bottom, I->Width, I->Height,
>Height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *) (image->bits() + i
GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *) (image + buffer_si mage->getSizeInBytes()));
ze));
} }
ScenePurgeImageImpl(G, noinvalid); #endif
I->Image = Calloc(ImageType, 1); I->Image->m_needs_alpha_reset = true;
I->Image->needs_alpha_reset = true;
I->Image->data = image;
I->Image->height = I->Height;
I->Image->width = I->Width;
I->Image->size = buffer_size;
if(save_stereo)
I->Image->stereo = 1;
} }
} else if(I->Image) { } else if(I->Image) {
image = I->Image->data; image = I->Image.get();
} }
if(image) { if(image) {
int opaque_back = SettingGetGlobal_b(G, cSetting_opaque_background); int opaque_back = SettingGetGlobal_b(G, cSetting_opaque_background);
if(opaque_back && I->Image->needs_alpha_reset) { if(opaque_back && I->Image->m_needs_alpha_reset) {
int i, s = 4 * I->Image->width * I->Image->height; int i, s = image->getSizeInBytes() * (image->isStereo() ? 2 : 1);
for(i = 3; i < s; i += 4) for (i = pymol::Image::Channel::ALPHA; i < s;
image[i] = 0xFF; i += pymol::Image::getPixelSize())
I->Image->needs_alpha_reset = false; image->bits()[i] = 0xFF;
I->Image->m_needs_alpha_reset = false;
} }
} }
return (unsigned char *) image; return image;
} }
void SceneImageFinish(PyMOLGlobals * G, GLvoid *image) /**
{
CScene *I = G->Scene;
if(I->Image) {
if(I->Image->data != (unsigned char *) image) /* purge the image if th
is isn't the active copy */
FreeP(image);
} else {
FreeP(image);
}
}
/*
* Get the size of the rendered image. This is either identical to * Get the size of the rendered image. This is either identical to
* cmd.get_viewport(), or the dimensions which were last passed to * cmd.get_viewport(), or the dimensions which were last passed to
* cmd.draw(), cmd.ray() or cmd.png(). * cmd.draw(), cmd.ray() or cmd.png().
*/ */
void SceneGetImageSize(PyMOLGlobals * G, int *width, int *height) std::pair<int, int> SceneGetImageSize(PyMOLGlobals * G)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
// TODO: calling ImagePrepare looks like a heavy side effect. Need to if (I->CopyType && I->Image) {
// clarify if checking (CopyType && Image && Image->data) here would return I->Image->getSize();
// be sufficient.
GLvoid *image = SceneImagePrepareImpl(G, false, false);
if(image && I->Image) {
*width = I->Image->width;
*height = I->Image->height;
} else { } else {
*width = I->Width; return std::make_pair(I->Width, I->Height);
*height = I->Height;
} }
SceneImageFinish(G, image); /* don't leak if(image != I->Image) */
} }
float SceneGetGridAspectRatio(PyMOLGlobals * G){ float SceneGetGridAspectRatio(PyMOLGlobals * G){
CScene *I = G->Scene; CScene *I = G->Scene;
return (I->Width / (float)I->Height) / return (I->Width / (float)I->Height) /
(float)(I->grid.cur_viewport_size[0] / (float)I->grid.cur_viewport_size[1]); (float)(I->grid.cur_viewport_size[0] / (float)I->grid.cur_viewport_size[1]);
} }
int SceneCopyExternal(PyMOLGlobals * G, int width, int height, int SceneCopyExternal(PyMOLGlobals * G, int width, int height,
int rowbytes, unsigned char *dest, int mode) int rowbytes, unsigned char *dest, int mode)
{ {
GLvoid *image = SceneImagePrepare(G, false); auto image = SceneImagePrepare(G, false);
CScene *I = G->Scene; CScene *I = G->Scene;
int result = false; int result = false;
int i, j; int i, j;
int premultiply_alpha = true; int premultiply_alpha = true;
int red_index = 0, blue_index = 1, green_index = 2, alpha_index = 3; int red_index = 0, blue_index = 1, green_index = 2, alpha_index = 3;
int no_alpha = (SettingGetGlobal_b(G, cSetting_opaque_background) && int no_alpha = (SettingGetGlobal_b(G, cSetting_opaque_background) &&
SettingGetGlobal_b(G, cSetting_ray_opaque_background)); SettingGetGlobal_b(G, cSetting_ray_opaque_background));
if(mode & 0x1) { if(mode & 0x1) {
int index = 0; int index = 0;
skipping to change at line 1815 skipping to change at line 1766
} }
if(mode & 0x2) { if(mode & 0x2) {
premultiply_alpha = false; premultiply_alpha = false;
} }
/* /*
printf("image %p I->image %p\n"); printf("image %p I->image %p\n");
if(I->Image) { if(I->Image) {
printf("%d %d %d %d\n",I->Image->width,width,I->Image->height,height); printf("%d %d %d %d\n",I->Image->width,width,I->Image->height,height);
} */ } */
if(image && I->Image && (I->Image->width == width) && (I->Image->height == hei ght)) { if(image && I->Image && (I->Image->getWidth() == width) && (I->Image->getHeigh t() == height)) {
for(i = 0; i < height; i++) { for(i = 0; i < height; i++) {
unsigned char *src = ((unsigned char *) image) + ((height - 1) - i) * widt h * 4; unsigned char *src = image->bits() + ((height - 1) - i) * width * 4;
unsigned char *dst; unsigned char *dst;
if(mode & 0x4) { if(mode & 0x4) {
dst = dest + (height - (i + 1)) * (rowbytes); dst = dest + (height - (i + 1)) * (rowbytes);
} else { } else {
dst = dest + i * (rowbytes); dst = dest + i * (rowbytes);
} }
for(j = 0; j < width; j++) { for(j = 0; j < width; j++) {
if(no_alpha) { if(no_alpha) {
dst[red_index] = src[0]; /* no alpha */ dst[red_index] = src[0]; /* no alpha */
dst[green_index] = src[1]; dst[green_index] = src[1];
skipping to change at line 1858 skipping to change at line 1809
} */ } */
} }
dst += 4; dst += 4;
src += 4; src += 4;
} }
} }
result = true; result = true;
} else { } else {
printf("image or size mismatch\n"); printf("image or size mismatch\n");
} }
SceneImageFinish(G, image);
return (result); return (result);
} }
static void interlace(unsigned int *dst, unsigned int *src, int width, int heigh bool ScenePNG(PyMOLGlobals * G, const char *png, float dpi, int quiet,
t)
{
int a, b;
unsigned int *p0 = src, *p1 = src + (height * width);
unsigned int *q = dst;
for(a = 0; a < height; a++) {
for(b = 0; b < width; b++) {
*(q++) = *(p0++);
}
for(b = 0; b < width; b++) {
*(q++) = *(p1++);
}
}
}
static void deinterlace(unsigned int *dst, unsigned int *src,
int width, int height, int swap)
{
int a, b;
unsigned int *p = src;
unsigned int *q0 = dst, *q1 = dst + (height * width);
if(swap) {
q0 = dst + (height * width);
q1 = dst;
}
for(a = 0; a < height; a++) {
for(b = 0; b < width; b++) {
*(q0++) = *(p++);
}
for(b = 0; b < width; b++) {
*(q1++) = *(p++);
}
}
}
int ScenePNG(PyMOLGlobals * G, char *png, float dpi, int quiet,
int prior_only, int format) int prior_only, int format)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
GLvoid *image = SceneImagePrepare(G, prior_only); SceneImagePrepare(G, prior_only);
if(image && I->Image) { if(I->Image) {
int width = I->Image->width; int width, height;
int height = I->Image->height; std::tie(width, height) = I->Image->getSize();
unsigned char *save_image = (unsigned char*) image; auto saveImage = I->Image;
if(I->Image->isStereo()) {
if((image == I->Image->data) && I->Image->stereo) { saveImage = std::make_shared<pymol::Image>();
width = I->Image->width; *(saveImage) = I->Image->interlace();
save_image = Alloc(unsigned char, I->Image->size * 2);
interlace((unsigned int *) save_image, (unsigned int *) I->Image->data, wi
dth,
height);
width *= 2;
} }
if(dpi < 0.0F) if(dpi < 0.0F)
dpi = SettingGetGlobal_f(G, cSetting_image_dots_per_inch); dpi = SettingGetGlobal_f(G, cSetting_image_dots_per_inch);
if(MyPNGWrite(G, png, save_image, width, height, dpi, format, quiet)) { auto screen_gamma = SettingGetGlobal_f(G, cSetting_png_screen_gamma);
auto file_gamma = SettingGetGlobal_f(G, cSetting_png_file_gamma);
if(MyPNGWrite(png, *saveImage, dpi, format, quiet, screen_gamma, file_gamma)
) {
if(!quiet) { if(!quiet) {
PRINTFB(G, FB_Scene, FB_Actions) PRINTFB(G, FB_Scene, FB_Actions)
" ScenePNG: wrote %dx%d pixel image to file \"%s\".\n", " ScenePNG: wrote %dx%d pixel image to file \"%s\".\n",
width, I->Image->height, png ENDFB(G); width, I->Image->getHeight(), png ENDFB(G);
} }
} else { } else {
PRINTFB(G, FB_Scene, FB_Errors) PRINTFB(G, FB_Scene, FB_Errors)
" ScenePNG-Error: error writing \"%s\"! Please check directory...\n", " ScenePNG-Error: error writing \"%s\"! Please check directory...\n",
png ENDFB(G); png ENDFB(G);
} }
if(save_image && (save_image != image))
FreeP(save_image);
} }
SceneImageFinish(G, image); return I->Image.get() != nullptr;
return (image != NULL);
} }
/*========================================================================*/ /*========================================================================*/
int SceneGetFrame(PyMOLGlobals * G) int SceneGetFrame(PyMOLGlobals * G)
{ {
if(MovieDefined(G)) if(MovieDefined(G))
return (SettingGetGlobal_i(G, cSetting_frame) - 1); return (SettingGetGlobal_i(G, cSetting_frame) - 1);
else else
return (SettingGetGlobal_i(G, cSetting_state) - 1); return (SettingGetGlobal_i(G, cSetting_state) - 1);
} }
/*========================================================================*/ /*========================================================================*/
/* GM: /**
* Returns the number of movie frames, or the number of states if no movie * Returns the number of movie frames, or the number of states if no movie
* is defined. * is defined.
*/ */
int SceneCountFrames(PyMOLGlobals * G) int SceneCountFrames(PyMOLGlobals * G)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
int n; int mov_len = MovieGetLength(G);
int mov_len;
I->NFrame = 0;
for ( auto it = I->Obj.begin(); it != I->Obj.end(); ++it) {
n = (*it)->getNFrame();
if(n > I->NFrame)
I->NFrame = n;
}
mov_len = MovieGetLength(G);
I->HasMovie = (mov_len != 0); I->HasMovie = (mov_len != 0);
if(mov_len > 0) { if(mov_len > 0) {
I->NFrame = mov_len; I->NFrame = mov_len;
} else if(mov_len < 0) { } else {
mov_len = -mov_len; if (mov_len < 0) {
if(I->NFrame < mov_len) /* allows you to see cached movie even w/o objec // allows you to see cached movie even w/o object
t */ I->NFrame = -mov_len;
I->NFrame = mov_len; } else {
I->NFrame = 0;
}
for (const auto& obj : I->Obj) {
int n = obj->getNFrame();
if (n > I->NFrame)
I->NFrame = n;
}
} }
PRINTFD(G, FB_Scene)" SceneCountFrames: leaving... I->NFrame %d\n", I->NFrame ENDFD PRINTFD(G, FB_Scene)" SceneCountFrames: leaving... I->NFrame %d\n", I->NFrame ENDFD
return I->NFrame; return I->NFrame;
} }
/*========================================================================*/ /*========================================================================*/
void SceneSetFrame(PyMOLGlobals * G, int mode, int frame) void SceneSetFrame(PyMOLGlobals * G, int mode, int frame)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
int newFrame; int newFrame;
skipping to change at line 2145 skipping to change at line 2055
SceneInvalidateCopy(G, false); SceneInvalidateCopy(G, false);
SceneDirty(G); SceneDirty(G);
SeqChanged(G); SeqChanged(G);
PyMOL_NeedRedisplay(G->PyMOL); PyMOL_NeedRedisplay(G->PyMOL);
} }
/*========================================================================*/ /*========================================================================*/
Block *SceneGetBlock(PyMOLGlobals * G) Block *SceneGetBlock(PyMOLGlobals * G)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
return (I->Block); return (I);
} }
/*========================================================================*/ /*========================================================================*/
int SceneValidateImageMode(PyMOLGlobals * G, int mode, bool defaultdraw) { int SceneValidateImageMode(PyMOLGlobals * G, int mode, bool defaultdraw) {
switch (mode) { switch (mode) {
case cSceneImage_Normal: case cSceneImage_Normal:
case cSceneImage_Draw: case cSceneImage_Draw:
case cSceneImage_Ray: case cSceneImage_Ray:
return mode; return mode;
} }
skipping to change at line 2221 skipping to change at line 2131
if(draw_both) { if(draw_both) {
SceneCopy(G, GL_BACK_LEFT, true, false); SceneCopy(G, GL_BACK_LEFT, true, false);
} else { } else {
SceneCopy(G, GL_BACK, true, false); SceneCopy(G, GL_BACK, true, false);
} }
/* insert OpenGL context validation code here? */ /* insert OpenGL context validation code here? */
} }
} }
break; break;
} }
if(I->Image) { MovieSetImage(G,
MovieSetImage(G, MovieFrameToImage(G, SettingGetGlobal_i(G, cSetting_frame) - 1),
MovieFrameToImage(G, SettingGetGlobal_i(G, cSetting_frame) - 1 I->Image);
),
I->Image);
I->MovieOwnsImageFlag = true;
} else {
I->MovieOwnsImageFlag = false;
}
if(I->Image) if(I->Image)
I->CopyType = true; I->CopyType = true;
return valid; return valid;
} }
/*========================================================================*/ /*========================================================================*/
static void SceneUpdateCameraRock(PyMOLGlobals * G, int dirty) static void SceneUpdateCameraRock(PyMOLGlobals * G, int dirty)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
skipping to change at line 2306 skipping to change at line 2211
double renderTime; double renderTime;
double minTime; double minTime;
int frameFlag = false; int frameFlag = false;
if(I->PossibleSingleClick == 2) { if(I->PossibleSingleClick == 2) {
double now = UtilGetSeconds(G); double now = UtilGetSeconds(G);
double single_click_delay = I->SingleClickDelay; double single_click_delay = I->SingleClickDelay;
double diff = now - I->LastReleaseTime; double diff = now - I->LastReleaseTime;
if(diff > single_click_delay) { if(diff > single_click_delay) {
/* post a single click processing event */ /* post a single click processing event */
SceneDeferClickWhen(I->Block, I->LastButton + P_GLUT_SINGLE_LEFT, I->LastW inX, I->LastWinY, I->LastClickTime, I->LastMod); /* push a click onto the queue */ SceneDeferClickWhen(I, I->LastButton + P_GLUT_SINGLE_LEFT, I->LastWinX, I- >LastWinY, I->LastClickTime, I->LastMod); /* push a click onto the queue */
I->PossibleSingleClick = 0; I->PossibleSingleClick = 0;
OrthoDirty(G); /* force an update */ OrthoDirty(G); /* force an update */
} }
} }
if(!OrthoDeferredWaiting(G)) { if(!OrthoDeferredWaiting(G)) {
if(MoviePlaying(G)) { if(MoviePlaying(G)) {
renderTime = UtilGetSeconds(G) - I->LastFrameTime; renderTime = UtilGetSeconds(G) - I->LastFrameTime;
{ {
float fps = SettingGetGlobal_f(G, cSetting_movie_fps); float fps = SettingGetGlobal_f(G, cSetting_movie_fps);
skipping to change at line 2365 skipping to change at line 2270
MoviePlay(G, cMovieStop); MoviePlay(G, cMovieStop);
} else { } else {
SceneSetFrame(G, 5, 1); SceneSetFrame(G, 5, 1);
} }
PyMOL_NeedRedisplay(G->PyMOL); PyMOL_NeedRedisplay(G->PyMOL);
} }
} }
} }
/*========================================================================*/ /*========================================================================*/
/* /**
* Zoom to location and radius * Zoom to location and radius
*/ */
void SceneWindowSphere(PyMOLGlobals * G, float *location, float radius) void SceneWindowSphere(PyMOLGlobals * G, const float *location, float radius)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
float v0[3]; float v0[3];
float dist = 2.f * radius / GetFovWidth(G); float dist = 2.f * radius / GetFovWidth(G);
/* find where this point is in relationship to the origin */ /* find where this point is in relationship to the origin */
subtract3f(I->Origin, location, v0); subtract3f(I->Origin, location, v0);
MatrixTransformC44fAs33f3f(I->RotMatrix, v0, I->Pos); /* convert to view-space */ MatrixTransformC44fAs33f3f(I->RotMatrix, v0, I->Pos); /* convert to view-space */
skipping to change at line 2390 skipping to change at line 2295
dist *= I->Height / I->Width; dist *= I->Height / I->Width;
I->Pos[2] -= dist; I->Pos[2] -= dist;
I->Front = (-I->Pos[2] - radius * 1.2F); I->Front = (-I->Pos[2] - radius * 1.2F);
I->Back = (-I->Pos[2] + radius * 1.2F); I->Back = (-I->Pos[2] + radius * 1.2F);
UpdateFrontBackSafe(I); UpdateFrontBackSafe(I);
SceneRovingDirty(G); SceneRovingDirty(G);
} }
/*========================================================================*/ /*========================================================================*/
void SceneRelocate(PyMOLGlobals * G, float *location) void SceneRelocate(PyMOLGlobals * G, const float *location)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
float v0[3]; float v0[3];
float slab_width; float slab_width;
float dist; float dist;
slab_width = I->Back - I->Front; slab_width = I->Back - I->Front;
/* find out how far camera was from previous origin */ /* find out how far camera was from previous origin */
dist = I->Pos[2]; dist = I->Pos[2];
skipping to change at line 2422 skipping to change at line 2327
I->Pos[2] = dist; I->Pos[2] = dist;
I->Front = (-I->Pos[2] - (slab_width * 0.50F)); I->Front = (-I->Pos[2] - (slab_width * 0.50F));
I->Back = (-I->Pos[2] + (slab_width * 0.50F)); I->Back = (-I->Pos[2] + (slab_width * 0.50F));
UpdateFrontBackSafe(I); UpdateFrontBackSafe(I);
SceneRovingDirty(G); SceneRovingDirty(G);
} }
/*========================================================================*/ /*========================================================================*/
/* /**
* Get the origin of rotation in model space * Get the origin of rotation in model space
* cmd.get_view()[12:15] * cmd.get_view()[12:15]
*
* @param[out] origin
*/ */
void SceneOriginGet(PyMOLGlobals * G, float *origin) void SceneOriginGet(PyMOLGlobals * G, float *origin)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
copy3f(I->Origin, origin); copy3f(I->Origin, origin);
} }
/*========================================================================*/ /*========================================================================*/
void SceneOriginSet(PyMOLGlobals * G, float *origin, int preserve) /**
* Set the origin of rotation in model space
* (`cmd.get_view()[12:15]`)
*
* @param origin New origin
* @param preserve preserve current viewing location
*/
void SceneOriginSet(PyMOLGlobals * G, const float *origin, int preserve)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
float v0[3], v1[3]; float v0[3], v1[3];
if(preserve) { /* preserve current viewing location */ if(preserve) { /* preserve current viewing location */
subtract3f(origin, I->Origin, v0); /* model-space translation */ subtract3f(origin, I->Origin, v0); /* model-space translation */
MatrixTransformC44fAs33f3f(I->RotMatrix, v0, v1); /* convert to view-space */ MatrixTransformC44fAs33f3f(I->RotMatrix, v0, v1); /* convert to view-space */
add3f(I->Pos, v1, I->Pos); /* offset view to compensate */ add3f(I->Pos, v1, I->Pos); /* offset view to compensate */
} }
I->Origin[0] = origin[0]; /* move origin */ I->Origin[0] = origin[0]; /* move origin */
skipping to change at line 2483 skipping to change at line 2397
return result; return result;
} }
int SceneObjectDel(PyMOLGlobals * G, CObject * obj, int allow_purge) int SceneObjectDel(PyMOLGlobals * G, CObject * obj, int allow_purge)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
int defer_builds_mode = SettingGetGlobal_i(G, cSetting_defer_builds_mode); int defer_builds_mode = SettingGetGlobal_i(G, cSetting_defer_builds_mode);
if(!obj) { /* deletes all members */ if(!obj) { /* deletes all members */
if(allow_purge && (defer_builds_mode >= 3)) { if(allow_purge && (defer_builds_mode >= 3)) {
for ( auto it = I->Obj.begin(); it != I->Obj.end(); ++it) { for (auto& obj : I->Obj) {
/* purge graphics representation when no longer used */ /* purge graphics representation when no longer used */
(*it)->invalidate(cRepAll, cRepInvPurge, -1); obj->invalidate(cRepAll, cRepInvPurge, -1);
} }
} }
I->Obj.clear(); I->Obj.clear();
I->GadgetObjs.clear(); I->GadgetObjs.clear();
I->NonGadgetObjs.clear(); I->NonGadgetObjs.clear();
} else { } else {
auto &obj_list = (obj->type == cObjectGadget) ? I->GadgetObjs : I->NonGadget Objs; auto &obj_list = (obj->type == cObjectGadget) ? I->GadgetObjs : I->NonGadget Objs;
auto itg = find(obj_list.begin(), obj_list.end(), obj); auto itg = find(obj_list.begin(), obj_list.end(), obj);
if (itg != obj_list.end()) if (itg != obj_list.end())
obj_list.erase(itg); obj_list.erase(itg);
skipping to change at line 2518 skipping to change at line 2432
SceneInvalidate(G); SceneInvalidate(G);
return 0; return 0;
} }
/*========================================================================*/ /*========================================================================*/
int SceneLoadPNG(PyMOLGlobals * G, const char *fname, int movie_flag, int stereo , int quiet) int SceneLoadPNG(PyMOLGlobals * G, const char *fname, int movie_flag, int stereo , int quiet)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
int ok = false; int ok = false;
if(I->Image) { if(I->Image) {
if(I->MovieOwnsImageFlag) { ScenePurgeImage(G);
I->MovieOwnsImageFlag = false;
I->Image = NULL;
} else {
ScenePurgeImage(G);
}
I->CopyType = false; I->CopyType = false;
OrthoInvalidateDoDraw(G); // right now, need to invalidate since text could be shown OrthoInvalidateDoDraw(G); // right now, need to invalidate since text could be shown
} }
I->Image = Calloc(ImageType, 1); I->Image = MyPNGRead(fname);
if(MyPNGRead(fname, if(I->Image) {
(unsigned char **) &I->Image->data,
(unsigned int *) &I->Image->width, (unsigned int *) &I->Image->he
ight)) {
I->Image->size = I->Image->width * I->Image->height * 4;
if(!quiet) { if(!quiet) {
PRINTFB(G, FB_Scene, FB_Details) PRINTFB(G, FB_Scene, FB_Details)
" Scene: loaded image from '%s'.\n", fname ENDFB(G); " Scene: loaded image from '%s'.\n", fname ENDFB(G);
} }
if((stereo > 0) || ((stereo < 0) && if((stereo > 0) || ((stereo < 0) &&
(I->Image->width == 2 * I->Width) && (I->Image->getWidth() == 2 * I->Width) &&
(I->Image->height == I->Height))) { (I->Image->getHeight() == I->Height))) {
unsigned char *tmp = Alloc(unsigned char, I->Image->size); *(I->Image) = I->Image->deinterlace(stereo == 2);
if(tmp) {
I->Image->width /= 2;
I->Image->stereo = true;
I->Image->size /= 2;
deinterlace((unsigned int *) tmp,
(unsigned int *) I->Image->data,
I->Image->width, I->Image->height, (stereo == 2));
FreeP(I->Image->data);
I->Image->data = tmp;
}
} }
I->CopyType = true; I->CopyType = true;
I->CopyForced = true; I->CopyForced = true;
OrthoRemoveSplash(G); OrthoRemoveSplash(G);
SettingSetGlobal_b(G, cSetting_text, 0); SettingSetGlobal_b(G, cSetting_text, 0);
if(movie_flag && if(movie_flag &&
I->Image && I->Image->data && I->Image && !I->Image->empty()) {
(I->Image->height == I->Height) && (I->Image->width == I->Width)) {
MovieSetImage(G, MovieFrameToImage(G, SettingGetGlobal_i(G, cSetting_frame ) - 1) MovieSetImage(G, MovieFrameToImage(G, SettingGetGlobal_i(G, cSetting_frame ) - 1)
, I->Image); , I->Image);
I->MovieOwnsImageFlag = true;
I->MovieFrameFlag = true; I->MovieFrameFlag = true;
} else { } else {
I->MovieOwnsImageFlag = false;
I->DirtyFlag = false; /* make sure we don't overwrite image */ I->DirtyFlag = false; /* make sure we don't overwrite image */
} }
OrthoDirty(G); OrthoDirty(G);
ok = true; ok = true;
} else { } else {
if(!quiet) { if(!quiet) {
PRINTFB(G, FB_Scene, FB_Errors) PRINTFB(G, FB_Scene, FB_Errors)
" Scene: unable to load image from '%s'.\n", fname ENDFB(G); " Scene: unable to load image from '%s'.\n", fname ENDFB(G);
} }
} }
skipping to change at line 2680 skipping to change at line 2573
glColor3f(1.0F, 1.0F, 0.1F); glColor3f(1.0F, 1.0F, 0.1F);
glVertex3i(x2 + w - 1, y2 + h - 1, z); glVertex3i(x2 + w - 1, y2 + h - 1, z);
glColor3f(0.1F, 0.1F, 1.0F); glColor3f(0.1F, 0.1F, 1.0F);
glVertex3i(x2 + w - 1, y2 + 1, z); glVertex3i(x2 + w - 1, y2 + 1, z);
glEnd(); glEnd();
} }
} }
} }
#endif #endif
/* /**
* Update the G->Scene->SceneVLA names array which is used for scene buttons * Update the G->Scene->SceneVLA names array which is used for scene buttons
*
* @param list List of scene names
*/ */
void SceneSetNames(PyMOLGlobals * G, const std::vector<std::string> &list) void SceneSetNames(PyMOLGlobals * G, const std::vector<std::string> &list)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
I->NScene = (int)list.size(); I->NScene = (int)list.size();
VLACheck(I->SceneVLA, SceneElem, I->NScene); VLACheck(I->SceneVLA, SceneElem, I->NScene);
SceneElem *elem = I->SceneVLA; SceneElem *elem = I->SceneVLA;
for(int a = 0; a < I->NScene; ++a) { for(int a = 0; a < I->NScene; ++a) {
elem->name = (char*) list[a].c_str(); elem->name = (char*) list[a].c_str();
skipping to change at line 2704 skipping to change at line 2599
elem++; elem++;
} }
OrthoDirty(G); OrthoDirty(G);
} }
/*========================================================================*/ /*========================================================================*/
static void SceneDrawButtons(Block * block, int draw_for_real ORTHOCGOARG) static void SceneDrawButtons(Block * block, int draw_for_real ORTHOCGOARG)
{ {
#ifndef _PYMOL_NOPY #ifndef _PYMOL_NOPY
PyMOLGlobals *G = block->G; PyMOLGlobals *G = block->m_G;
CScene *I = G->Scene; CScene *I = G->Scene;
int x, y, xx, x2; int x, y, xx, x2;
const char *c = NULL; const char *c = NULL;
float enabledColor[3] = { 0.5F, 0.5F, 0.5F }; float enabledColor[3] = { 0.5F, 0.5F, 0.5F };
float pressedColor[3] = { 0.7F, 0.7F, 0.7F }; float pressedColor[3] = { 0.7F, 0.7F, 0.7F };
float disabledColor[3] = { 0.25F, 0.25F, 0.25F }; float disabledColor[3] = { 0.25F, 0.25F, 0.25F };
float lightEdge[3] = { 0.6F, 0.6F, 0.6F }; float lightEdge[3] = { 0.6F, 0.6F, 0.6F };
float darkEdge[3] = { 0.35F, 0.35F, 0.35F }; float darkEdge[3] = { 0.35F, 0.35F, 0.35F };
int charWidth = DIP2PIXEL(8); int charWidth = DIP2PIXEL(8);
int n_ent; int n_ent;
skipping to change at line 2732 skipping to change at line 2627
if(((G->HaveGUI && G->ValidContext) || (!draw_for_real)) && if(((G->HaveGUI && G->ValidContext) || (!draw_for_real)) &&
((block->rect.right - block->rect.left) > 6) && (I->NScene)) { ((block->rect.right - block->rect.left) > 6) && (I->NScene)) {
int max_char; int max_char;
int nChar; int nChar;
I->ButtonsShown = true; I->ButtonsShown = true;
/* do we have enough structures to warrant a scroll bar? */ /* do we have enough structures to warrant a scroll bar? */
n_ent = I->NScene; n_ent = I->NScene;
n_disp = n_disp =
(((I->Block->rect.top - I->Block->rect.bottom) - (SceneTopMargin)) / lineH eight) - (((I->rect.top - I->rect.bottom) - (SceneTopMargin)) / lineHeight) -
1; 1;
if(n_disp < 1) if(n_disp < 1)
n_disp = 1; n_disp = 1;
{ {
int i; int i;
for(i = 0; i < I->NScene; i++) for(i = 0; i < I->NScene; i++)
I->SceneVLA[i].drawn = false; I->SceneVLA[i].drawn = false;
} }
if(n_ent > n_disp) { if(n_ent > n_disp) {
int bar_maxed = ScrollBarIsMaxed(I->ScrollBar); int bar_maxed = I->m_ScrollBar.isMaxed();
if(!I->ScrollBarActive) { if(!I->ScrollBarActive) {
ScrollBarSetLimits(I->ScrollBar, n_ent, n_disp); I->m_ScrollBar.setLimits(n_ent, n_disp);
if(bar_maxed) { if(bar_maxed) {
ScrollBarMaxOut(I->ScrollBar); I->m_ScrollBar.maxOut();
I->NSkip = (int) ScrollBarGetValue(I->ScrollBar); I->NSkip = static_cast<int>(I->m_ScrollBar.getValue());
} else { } else {
ScrollBarSetValue(I->ScrollBar, 0); I->m_ScrollBar.setValue(0);
I->NSkip = 0; I->NSkip = 0;
} }
} else { } else {
ScrollBarSetLimits(I->ScrollBar, n_ent, n_disp); I->m_ScrollBar.setLimits(n_ent, n_disp);
if(bar_maxed) if(bar_maxed)
ScrollBarMaxOut(I->ScrollBar); I->m_ScrollBar.maxOut();
I->NSkip = (int) ScrollBarGetValue(I->ScrollBar); I->NSkip = static_cast<int>(I->m_ScrollBar.getValue());
} }
I->ScrollBarActive = 1; I->ScrollBarActive = 1;
} else { } else {
I->ScrollBarActive = 0; I->ScrollBarActive = 0;
I->NSkip = 0; I->NSkip = 0;
} }
max_char = (((I->Block->rect.right - I->Block->rect.left) - max_char = (((I->rect.right - I->rect.left) -
(SceneTextLeftMargin + SceneRightMargin + 4)) - (SceneTextLeftMargin + SceneRightMargin + 4)) -
(op_cnt * SceneToggleWidth)); (op_cnt * SceneToggleWidth));
if(I->ScrollBarActive) { if(I->ScrollBarActive) {
max_char -= (SceneScrollBarMargin + SceneScrollBarWidth); max_char -= (SceneScrollBarMargin + SceneScrollBarWidth);
} }
max_char /= charWidth; max_char /= charWidth;
if(I->ScrollBarActive) { if(I->ScrollBarActive) {
ScrollBarSetBox(I->ScrollBar, I->Block->rect.top - SceneScrollBarMargin, I->m_ScrollBar.setBox(I->rect.top - SceneScrollBarMargin,
I->Block->rect.left + SceneScrollBarMargin, I->rect.left + SceneScrollBarMargin,
I->Block->rect.bottom + 2, I->rect.bottom + 2,
I->Block->rect.left + SceneScrollBarMargin + SceneScrollBa I->rect.left + SceneScrollBarMargin + SceneScrollBar
rWidth); Width);
if(draw_for_real) if(draw_for_real)
ScrollBarDoDraw(I->ScrollBar ORTHOCGOARGVAR); I->m_ScrollBar.draw(orthoCGO);
} }
skip = I->NSkip; skip = I->NSkip;
x = I->Block->rect.left + SceneTextLeftMargin; x = I->rect.left + SceneTextLeftMargin;
/* y = ((I->Block->rect.top-lineHeight)-SceneTopMargin)-lineHeight; */ /* y = ((I->rect.top-lineHeight)-SceneTopMargin)-lineHeight; */
{ {
int n_vis = n_disp; int n_vis = n_disp;
if(n_ent < n_vis) if(n_ent < n_vis)
n_vis = n_ent; n_vis = n_ent;
y = (I->Block->rect.bottom + SceneBottomMargin) + (n_vis - 1) * lineHeight ; y = (I->rect.bottom + SceneBottomMargin) + (n_vis - 1) * lineHeight;
} }
/* xx = I->Block->rect.right-SceneRightMargin-SceneToggleWidth*(cRepCnt+o /* xx = I->rect.right-SceneRightMargin-SceneToggleWidth*(cRepCnt+op_cnt);
p_cnt); */ */
xx = I->Block->rect.right - SceneRightMargin - SceneToggleWidth * (op_cnt); xx = I->rect.right - SceneRightMargin - SceneToggleWidth * (op_cnt);
if(I->ScrollBarActive) { if(I->ScrollBarActive) {
x += SceneScrollBarWidth + SceneScrollBarMargin; x += SceneScrollBarWidth + SceneScrollBarMargin;
} }
{ {
int i; int i;
for(i = 0; i < n_ent; i++) { for(i = 0; i < n_ent; i++) {
if(skip) { if(skip) {
skip--; skip--;
skipping to change at line 2821 skipping to change at line 2716
if((x - SceneToggleMargin) - (xx - SceneToggleMargin) > -10) { if((x - SceneToggleMargin) - (xx - SceneToggleMargin) > -10) {
x2 = x + 10; x2 = x + 10;
} }
{ {
float toggleColor[3] = { 0.5F, 0.5F, 1.0F }; float toggleColor[3] = { 0.5F, 0.5F, 1.0F };
if(draw_for_real) { if(draw_for_real) {
glColor3fv(toggleColor); glColor3fv(toggleColor);
TextSetColor(G, I->Block->TextColor); TextSetColor(G, I->TextColor);
TextSetPos2i(G, x + DIP2PIXEL(2), y + text_lift); TextSetPos2i(G, x + DIP2PIXEL(2), y + text_lift);
} }
{ {
int len; int len;
const char *cur_name = SettingGetGlobal_s(G, cSetting_scene_curren t_name); const char *cur_name = SettingGetGlobal_s(G, cSetting_scene_curren t_name);
SceneElem *elem = I->SceneVLA + i; SceneElem *elem = I->SceneVLA + i;
int item = I->NSkip + row; int item = I->NSkip + row;
c = elem->name; c = elem->name;
len = elem->len; len = elem->len;
skipping to change at line 2862 skipping to change at line 2757
draw_button(x, y, 0, (x2 - x) - 1, (lineHeight - 1), lightEdge , draw_button(x, y, 0, (x2 - x) - 1, (lineHeight - 1), lightEdge ,
darkEdge, pressedColor ORTHOCGOARGVAR); darkEdge, pressedColor ORTHOCGOARGVAR);
} else if(cur_name && elem->name && (!strcmp(elem->name, cur_nam e))) { } else if(cur_name && elem->name && (!strcmp(elem->name, cur_nam e))) {
draw_button(x, y, 0, (x2 - x) - 1, (lineHeight - 1), lightEdge , draw_button(x, y, 0, (x2 - x) - 1, (lineHeight - 1), lightEdge ,
darkEdge, enabledColor ORTHOCGOARGVAR); darkEdge, enabledColor ORTHOCGOARGVAR);
} else { } else {
draw_button(x, y, 0, (x2 - x) - 1, (lineHeight - 1), lightEdge , draw_button(x, y, 0, (x2 - x) - 1, (lineHeight - 1), lightEdge ,
darkEdge, disabledColor ORTHOCGOARGVAR); darkEdge, disabledColor ORTHOCGOARGVAR);
} }
TextSetColor(G, I->Block->TextColor); TextSetColor(G, I->TextColor);
if(c) { if(c) {
while(*c) { while(*c) {
if((nChar--) > 0) if((nChar--) > 0)
TextDrawChar(G, *(c++) ORTHOCGOARGVAR); TextDrawChar(G, *(c++) ORTHOCGOARGVAR);
else else
break; break;
} }
} }
} }
} }
} }
y -= lineHeight; y -= lineHeight;
if(y < (I->Block->rect.bottom)) if(y < (I->rect.bottom))
break; break;
} }
} }
} }
I->HowFarDown = y; I->HowFarDown = y;
I->ButtonsValid = true; I->ButtonsValid = true;
} }
#endif #endif
} }
int SceneDrawImageOverlay(PyMOLGlobals * G, int override ORTHOCGOARG){ int SceneDrawImageOverlay(PyMOLGlobals * G, int override ORTHOCGOARG){
CScene *I = G->Scene; CScene *I = G->Scene;
int drawn = false; int drawn = false;
int text = SettingGetGlobal_b(G, cSetting_text); int text = SettingGetGlobal_b(G, cSetting_text);
/* is the text/overlay (ESC) on? */ /* is the text/overlay (ESC) on? */
int overlay = OrthoGetOverlayStatus(G); int overlay = OrthoGetOverlayStatus(G);
if(((!text) || overlay) && (override || I->CopyType == true) && I->Image && I- >Image->data) { if(((!text) || overlay) && (override || I->CopyType == true) && I->Image && !I ->Image->empty()) {
/* show transparent bg as checkboard? */ /* show transparent bg as checkboard? */
int show_alpha = SettingGetGlobal_b(G, cSetting_show_alpha_checker); int show_alpha = SettingGetGlobal_b(G, cSetting_show_alpha_checker);
const float *bg_color = ColorGet(G, SettingGet_color(G, NULL, NULL, cSetting _bg_rgb)); const float *bg_color = ColorGet(G, SettingGet_color(G, NULL, NULL, cSetting _bg_rgb));
unsigned int bg_rr, bg_r = (unsigned int) (255 * bg_color[0]); unsigned int bg_rr, bg_r = (unsigned int) (255 * bg_color[0]);
unsigned int bg_gg, bg_g = (unsigned int) (255 * bg_color[1]); unsigned int bg_gg, bg_g = (unsigned int) (255 * bg_color[1]);
unsigned int bg_bb, bg_b = (unsigned int) (255 * bg_color[2]); unsigned int bg_bb, bg_b = (unsigned int) (255 * bg_color[2]);
int width = I->Image->width; int width = I->Image->getWidth();
int height = I->Image->height; int height = I->Image->getHeight();
unsigned char *data = I->Image->data; unsigned char *data = I->Image->bits();
if(I->Image->stereo) { if(I->Image->isStereo()) {
int buffer; int buffer;
glGetIntegerv(GL_DRAW_BUFFER, (GLint *) & buffer); glGetIntegerv(GL_DRAW_BUFFER, (GLint *) & buffer);
if(buffer == GL_BACK_RIGHT) /* hardware stereo */ if(buffer == GL_BACK_RIGHT) /* hardware stereo */
data += I->Image->size; data += I->Image->getSizeInBytes();
else { else {
int stereo = SettingGetGlobal_i(G, cSetting_stereo); int stereo = SettingGetGlobal_i(G, cSetting_stereo);
if (stereo){ if (stereo){
switch (OrthoGetRenderMode(G)) { switch (OrthoGetRenderMode(G)) {
case cStereo_geowall: case cStereo_geowall:
data += I->Image->size; data += I->Image->getSizeInBytes();
break; break;
} }
} }
} }
/* if drawing the right buffer, then draw the right image */ /* if drawing the right buffer, then draw the right image */
} }
if((height > I->Height) || (width > I->Width)) { /* image is oversize */ if((height > I->Height) || (width > I->Width)) { /* image is oversize */
{ {
int factor = 1; int factor = 1;
int shift = 0; int shift = 0;
int tmp_height = I->Image->height; int tmp_height = I->Image->getHeight();
int tmp_width = I->Image->width; int tmp_width = I->Image->getWidth();
int src_row_bytes = I->Image->width * 4; int src_row_bytes = I->Image->getWidth() * pymol::Image::getPixelSize();
unsigned int color_word; unsigned int color_word;
float rgba[4] = { 0.0F, 0.0F, 0.0F, 1.0F }; float rgba[4] = { 0.0F, 0.0F, 0.0F, 1.0F };
ColorGetBkrdContColor(G, rgba, false); ColorGetBkrdContColor(G, rgba, false);
color_word = ColorGet32BitWord(G, rgba); color_word = ColorGet32BitWord(G, rgba);
while(tmp_height && tmp_width && while(tmp_height && tmp_width &&
((tmp_height > (I->Height - 3)) || (tmp_width > (I->Width - 3)))) { ((tmp_height > (I->Height - 3)) || (tmp_width > (I->Width - 3)))) {
tmp_height = (tmp_height >> 1); tmp_height = (tmp_height >> 1);
tmp_width = (tmp_width >> 1); tmp_width = (tmp_width >> 1);
skipping to change at line 3020 skipping to change at line 2915
} }
*((unsigned int *) (q)) = color_word; /* border */ *((unsigned int *) (q)) = color_word; /* border */
q += 4; q += 4;
p += factor_row_bytes; p += factor_row_bytes;
} }
for(a = 0; a < tmp_width; a++) { /* border, last row */ for(a = 0; a < tmp_width; a++) { /* border, last row */
*((unsigned int *) (q)) = color_word; *((unsigned int *) (q)) = color_word;
q += 4; q += 4;
} }
glRasterPos3i((int) ((I->Width - tmp_width) / 2 + I->Block->rect.left #ifndef PURE_OPENGL_ES_2
), glRasterPos3i((int) ((I->Width - tmp_width) / 2 + I->rect.left),
(int) ((I->Height - tmp_height) / 2 + I->Block->rect.bo (int) ((I->Height - tmp_height) / 2 + I->rect.bottom),
ttom),
-10); -10);
#endif
PyMOLDrawPixels(tmp_width, tmp_height, GL_RGBA, GL_UNSIGNED_BYTE, buf fer); PyMOLDrawPixels(tmp_width, tmp_height, GL_RGBA, GL_UNSIGNED_BYTE, buf fer);
drawn = true; drawn = true;
} }
FreeP(buffer); FreeP(buffer);
} }
{ {
char buffer[255]; char buffer[255];
int text_pos = (I->Height - tmp_height) / 2 - 15; int text_pos = (I->Height - tmp_height) / 2 - 15;
int x_pos, y_pos; int x_pos, y_pos;
if(text_pos < 0) { if(text_pos < 0) {
text_pos = (I->Height - tmp_height) / 2 + 3; text_pos = (I->Height - tmp_height) / 2 + 3;
x_pos = (I->Width - tmp_width) / 2 + 3; x_pos = (I->Width - tmp_width) / 2 + 3;
y_pos = text_pos; y_pos = text_pos;
} else { } else {
x_pos = (I->Width - tmp_width) / 2; x_pos = (I->Width - tmp_width) / 2;
y_pos = text_pos; y_pos = text_pos;
} }
sprintf(buffer, "Image size = %d x %d", I->Image->width, I->Image->heig ht); sprintf(buffer, "Image size = %d x %d", I->Image->getWidth(), I->Image- >getHeight());
TextSetColor3f(G, rgba[0], rgba[1], rgba[2]); TextSetColor3f(G, rgba[0], rgba[1], rgba[2]);
TextDrawStrAt(G, buffer, TextDrawStrAt(G, buffer,
x_pos + I->Block->rect.left, y_pos + I->Block->rect.botto m ORTHOCGOARGVAR); x_pos + I->rect.left, y_pos + I->rect.bottom ORTHOCGOARGVAR);
} }
} }
} else if(((width < I->Width) || (height < I->Height)) && ((I->Width - width ) > 2) && ((I->Height - height) > 2)) { } else if(((width < I->Width) || (height < I->Height)) && ((I->Width - width ) > 2) && ((I->Height - height) > 2)) {
/* but a border around image */ /* but a border around image */
unsigned int color_word; unsigned int color_word;
float rgba[4] = { 0.0F, 0.0F, 0.0F, 1.0F }; float rgba[4] = { 0.0F, 0.0F, 0.0F, 1.0F };
unsigned int tmp_height = height + 2; unsigned int tmp_height = height + 2;
unsigned int tmp_width = width + 2; unsigned int tmp_width = width + 2;
unsigned int border = 1; unsigned int border = 1;
skipping to change at line 3137 skipping to change at line 3034
*(q++) = color_word; *(q++) = color_word;
} }
} }
// bottom border // bottom border
for(a = 0; a < border; ++a) { for(a = 0; a < border; ++a) {
for(b = 0; b < tmp_width; b++) for(b = 0; b < tmp_width; b++)
*(q++) = color_word; *(q++) = color_word;
} }
glRasterPos3i((int) ((I->Width - tmp_width) / 2 + I->Block->rect.left), #ifndef PURE_OPENGL_ES_2
(int) ((I->Height - tmp_height) / 2 + I->Block->rect.bottom glRasterPos3i((int) ((I->Width - tmp_width) / 2 + I->rect.left),
), (int) ((I->Height - tmp_height) / 2 + I->rect.bottom),
-10); -10);
#endif
PyMOLDrawPixels(tmp_width, tmp_height, GL_RGBA, GL_UNSIGNED_BYTE, tmp_buf fer); PyMOLDrawPixels(tmp_width, tmp_height, GL_RGBA, GL_UNSIGNED_BYTE, tmp_buf fer);
drawn = true; drawn = true;
} }
FreeP(tmp_buffer); FreeP(tmp_buffer);
} else if(I->CopyForced) { /* near-exact fit */ } else if(I->CopyForced) { /* near-exact fit */
float rgba[4] = { 0.0F, 0.0F, 0.0F, 1.0F }; float rgba[4] = { 0.0F, 0.0F, 0.0F, 1.0F };
unsigned int n_word = height * width; unsigned int n_word = height * width;
unsigned int *tmp_buffer = Alloc(unsigned int, n_word); unsigned int *tmp_buffer = Alloc(unsigned int, n_word);
ColorGetBkrdContColor(G, rgba, false); ColorGetBkrdContColor(G, rgba, false);
skipping to change at line 3185 skipping to change at line 3084
*(qq++) = bg_rr; *(qq++) = bg_rr;
*(qq++) = bg_gg; *(qq++) = bg_gg;
*(qq++) = bg_bb; *(qq++) = bg_bb;
*(qq++) = 0xFF; *(qq++) = 0xFF;
} }
q++; q++;
p++; p++;
} }
} }
} }
glRasterPos3i((int) ((I->Width - width) / 2 + I->Block->rect.left), #ifndef PURE_OPENGL_ES_2
(int) ((I->Height - height) / 2 + I->Block->rect.bottom), -10 glRasterPos3i((int) ((I->Width - width) / 2 + I->rect.left),
); (int) ((I->Height - height) / 2 + I->rect.bottom), -10);
#endif
PyMOLDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, tmp_buffer); PyMOLDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, tmp_buffer);
drawn = true; drawn = true;
FreeP(tmp_buffer); FreeP(tmp_buffer);
} else { /* not a forced copy, so don't show/blend alpha */ } else { /* not a forced copy, so don't show/blend alpha */
glRasterPos3i((int) ((I->Width - width) / 2 + I->Block->rect.left), #ifndef PURE_OPENGL_ES_2
(int) ((I->Height - height) / 2 + I->Block->rect.bottom), -10 glRasterPos3i((int) ((I->Width - width) / 2 + I->rect.left),
); (int) ((I->Height - height) / 2 + I->rect.bottom), -10);
#endif
PyMOLDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); PyMOLDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
drawn = true; drawn = true;
} }
I->LastRender = UtilGetSeconds(G); I->LastRender = UtilGetSeconds(G);
} }
return drawn; return drawn;
} }
void SceneDraw(Block * block ORTHOCGOARG) /* returns true if scene was drawn (us ing a cached image) */ void CScene::draw(CGO* orthoCGO) /* returns true if scene was drawn (using a cac hed image) */
{ {
PyMOLGlobals *G = block->G; PyMOLGlobals *G = m_G;
CScene *I = G->Scene; CScene *I = G->Scene;
int drawn = false; int drawn = false;
if(G->HaveGUI && G->ValidContext) { if(G->HaveGUI && G->ValidContext) {
I->ButtonsShown = false; I->ButtonsShown = false;
drawn = SceneDrawImageOverlay(G, 0 ORTHOCGOARGVAR); drawn = SceneDrawImageOverlay(G, 0 ORTHOCGOARGVAR);
if(SettingGetGlobal_b(G, cSetting_scene_buttons)) { if(SettingGetGlobal_b(G, cSetting_scene_buttons)) {
SceneDrawButtons(block, true ORTHOCGOARGVAR); SceneDrawButtons(this, true ORTHOCGOARGVAR);
} else { } else {
I->ButtonMargin = 0; I->ButtonMargin = 0;
} }
} }
if(drawn) if(drawn)
OrthoDrawWizardPrompt(G ORTHOCGOARGVAR); /* ugly hack necessitated because w izard OrthoDrawWizardPrompt(G ORTHOCGOARGVAR); /* ugly hack necessitated because w izard
prompt is overwritten when image is drawn */ prompt is overwritten when image is drawn */
} }
int SceneGetButtonMargin(PyMOLGlobals * G) int SceneGetButtonMargin(PyMOLGlobals * G)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
return I->ButtonMargin; return I->ButtonMargin;
} }
/*========================================================================*/ /*========================================================================*/
static int SceneRelease(Block * block, int button, int x, int y, int mod, double when) static int SceneRelease(Block * block, int button, int x, int y, int mod, double when)
{ {
PyMOLGlobals *G = block->G; PyMOLGlobals *G = block->m_G;
CScene *I = G->Scene; CScene *I = G->Scene;
int release_handled = false; int release_handled = false;
if(I->ButtonsShown && I->PressMode) { if(I->ButtonsShown && I->PressMode) {
if(I->ScrollBarActive) { if(I->ScrollBarActive) {
if((x - I->Block->rect.left) < (SceneScrollBarWidth + SceneScrollBarMargin if((x - I->rect.left) < (SceneScrollBarWidth + SceneScrollBarMargin)) {
)) { I->m_ScrollBar.release(button, x, y, mod);
ScrollBarDoRelease(I->ScrollBar, button, x, y, mod);
release_handled = true; release_handled = true;
} }
} }
if(!release_handled) { if(!release_handled) {
int ungrab = true; int ungrab = true;
if(I->PressMode) { if(I->PressMode) {
int i; int i;
SceneElem *elem = I->SceneVLA; SceneElem *elem = I->SceneVLA;
I->Over = -1; I->Over = -1;
for(i = 0; i < I->NScene; i++) { for(i = 0; i < I->NScene; i++) {
skipping to change at line 3288 skipping to change at line 3191
PFlush(G); PFlush(G);
PLog(G, buffer, cPLog_pym); PLog(G, buffer, cPLog_pym);
} }
} }
break; break;
case 3: case 3:
if(I->Pressed == I->Over) { if(I->Pressed == I->Over) {
Block *block = MenuActivate1Arg(G, I->LastWinX, I->LastWinY + 20, /* scene menu */ Block *block = MenuActivate1Arg(G, I->LastWinX, I->LastWinY + 20, /* scene menu */
I->LastWinX, I->LastWinY, true, "sc ene_menu", elem->name); I->LastWinX, I->LastWinY, true, "sc ene_menu", elem->name);
if (block) if (block)
PopUpDrag(block, x, y, mod); block->drag(x, y, mod);
ungrab = false; ungrab = false;
} }
break; break;
} }
} }
} }
I->LastPickVertexFlag = false; I->LastPickVertexFlag = false;
I->Pressed = -1; I->Pressed = -1;
I->Over = -1; I->Over = -1;
I->PressMode = 0; I->PressMode = 0;
skipping to change at line 3473 skipping to change at line 3376
{ {
SceneAbortAnimation(G); SceneAbortAnimation(G);
if(SettingGet_b(G, NULL, NULL, cSetting_mouse_restart_movie_delay)) { if(SettingGet_b(G, NULL, NULL, cSetting_mouse_restart_movie_delay)) {
SceneRestartFrameTimer(G); SceneRestartFrameTimer(G);
} }
} }
/*========================================================================*/ /*========================================================================*/
static int SceneClick(Block * block, int button, int x, int y, int mod, double w hen) static int SceneClick(Block * block, int button, int x, int y, int mod, double w hen)
{ {
PyMOLGlobals *G = block->G; PyMOLGlobals *G = block->m_G;
CScene *I = G->Scene; CScene *I = G->Scene;
CObject *obj; CObject *obj;
ObjectMolecule *objMol; ObjectMolecule *objMol;
OrthoLineType buffer, buf1, buf2; OrthoLineType buffer, buf1, buf2;
WordType selName = ""; WordType selName = "";
int mode = 0; /* trying to work around something... */ int mode = 0; /* trying to work around something... */
int atIndex; int atIndex;
char empty_string[1] = ""; const char *sel_mode_kw = "";
char *sel_mode_kw = empty_string;
int is_single_click = ((button == P_GLUT_SINGLE_LEFT) || int is_single_click = ((button == P_GLUT_SINGLE_LEFT) ||
(button == P_GLUT_SINGLE_MIDDLE) || (button == P_GLUT_SINGLE_MIDDLE) ||
(button == P_GLUT_SINGLE_RIGHT)); (button == P_GLUT_SINGLE_RIGHT));
int click_handled = false; int click_handled = false;
int click_side = 0; int click_side = 0;
if(!is_single_click) { if(!is_single_click) {
int click_handled = false; int click_handled = false;
if(I->ButtonsShown) { if(I->ButtonsShown) {
int i; int i;
SceneElem *elem = I->SceneVLA; SceneElem *elem = I->SceneVLA;
/* check & handle a click on the scrollbar */ /* check & handle a click on the scrollbar */
if(I->ScrollBarActive) { if(I->ScrollBarActive) {
if((x - I->Block->rect.left) < (SceneScrollBarWidth + SceneScrollBarMarg in)) { if((x - I->rect.left) < (SceneScrollBarWidth + SceneScrollBarMargin)) {
click_handled = true; click_handled = true;
ScrollBarDoClick(I->ScrollBar, button, x, y, mod); I->m_ScrollBar.click(button, x, y, mod);
} }
} }
if(!click_handled) { if(!click_handled) {
for(i = 0; i < I->NScene; i++) { for(i = 0; i < I->NScene; i++) {
if(elem->drawn && if(elem->drawn &&
(x >= elem->x1) && (y >= elem->y1) && (x < elem->x2) && (y < elem-> y2)) { (x >= elem->x1) && (y >= elem->y1) && (x < elem->x2) && (y < elem-> y2)) {
click_handled = true; click_handled = true;
break; break;
} }
elem++; elem++;
skipping to change at line 3562 skipping to change at line 3464
I->LastWinY = y; I->LastWinY = y;
I->LastClickTime = when; I->LastClickTime = when;
I->LastButton = button; I->LastButton = button;
I->LastMod = mod; I->LastMod = mod;
I->Threshold = 0; I->Threshold = 0;
SceneGetCenter(G, I->LastClickVertex); SceneGetCenter(G, I->LastClickVertex);
{ {
float vScale = SceneGetExactScreenVertexScale(G, I->LastClickVertex); float vScale = SceneGetExactScreenVertexScale(G, I->LastClickVertex);
float v[3]; float v[3];
v[0] = -(I->Width / 2 - (x - I->Block->rect.left)) * vScale; v[0] = -(I->Width / 2 - (x - I->rect.left)) * vScale;
v[1] = -(I->Height / 2 - (y - I->Block->rect.bottom)) * vScale; v[1] = -(I->Height / 2 - (y - I->rect.bottom)) * vScale;
v[2] = 0; v[2] = 0;
MatrixInvTransformC44fAs33f3f(I->RotMatrix, v, v); MatrixInvTransformC44fAs33f3f(I->RotMatrix, v, v);
add3f(v, I->LastClickVertex, I->LastClickVertex); add3f(v, I->LastClickVertex, I->LastClickVertex);
} }
if(I->ButtonsShown) { if(I->ButtonsShown) {
int i; int i;
SceneElem *elem = I->SceneVLA; SceneElem *elem = I->SceneVLA;
if(I->ScrollBarActive) { if(I->ScrollBarActive) {
if((x - I->Block->rect.left) < (SceneScrollBarWidth + SceneScrollBarMargin )) { if((x - I->rect.left) < (SceneScrollBarWidth + SceneScrollBarMargin)) {
click_handled = true; click_handled = true;
ScrollBarDoClick(I->ScrollBar, button, x, y, mod); I->m_ScrollBar.click(button, x, y, mod);
} }
} }
if(!click_handled) { if(!click_handled) {
for(i = 0; i < I->NScene; i++) { for(i = 0; i < I->NScene; i++) {
if(elem->drawn && if(elem->drawn &&
(x >= elem->x1) && (y >= elem->y1) && (x < elem->x2) && (y < elem->y2 )) { (x >= elem->x1) && (y >= elem->y1) && (x < elem->x2) && (y < elem->y2 )) {
switch (button) { switch (button) {
case P_GLUT_LEFT_BUTTON: /* normal activate (with interpolation) * / case P_GLUT_LEFT_BUTTON: /* normal activate (with interpolation) * /
I->Pressed = i; I->Pressed = i;
I->Over = i; I->Over = i;
skipping to change at line 3725 skipping to change at line 3627
case cButModeSeleSetBox: case cButModeSeleSetBox:
case cButModeSeleSubBox: case cButModeSeleSubBox:
return SceneLoopClick(block, button, x, y, mod); return SceneLoopClick(block, button, x, y, mod);
break; break;
case cButModeRotDrag: case cButModeRotDrag:
case cButModeMovDrag: case cButModeMovDrag:
case cButModeMovDragZ: case cButModeMovDragZ:
SceneNoteMouseInteraction(G); SceneNoteMouseInteraction(G);
SceneDontCopyNext(G); SceneDontCopyNext(G);
y = y - I->Block->margin.bottom; y = y - I->margin.bottom;
x = x - I->Block->margin.left; x = x - I->margin.left;
if(stereo_via_adjacent_array(I->StereoMode)) if(stereo_via_adjacent_array(I->StereoMode))
x = get_stereo_x(x, NULL, I->Width, NULL); x = get_stereo_x(x, NULL, I->Width, NULL);
I->LastX = x; I->LastX = x;
I->LastY = y; I->LastY = y;
EditorReadyDrag(G, SettingGetGlobal_i(G, cSetting_state) - 1); EditorReadyDrag(G, SettingGetGlobal_i(G, cSetting_state) - 1);
if(EditorDraggingObjectMatrix(G)) { if(EditorDraggingObjectMatrix(G)) {
obj = EditorDragObject(G); obj = EditorDragObject(G);
skipping to change at line 3766 skipping to change at line 3668
case cButModeClipN: case cButModeClipN:
case cButModeClipF: case cButModeClipF:
case cButModeRotZ: case cButModeRotZ:
case cButModeInvRotZ: case cButModeInvRotZ:
case cButModeRotL: case cButModeRotL:
case cButModeMovL: case cButModeMovL:
case cButModeMvzL: case cButModeMvzL:
SceneNoteMouseInteraction(G); SceneNoteMouseInteraction(G);
SceneDontCopyNext(G); SceneDontCopyNext(G);
y = y - I->Block->margin.bottom; y = y - I->margin.bottom;
x = x - I->Block->margin.left; x = x - I->margin.left;
if(stereo_via_adjacent_array(I->StereoMode)) if(stereo_via_adjacent_array(I->StereoMode))
x = get_stereo_x(x, NULL, I->Width, NULL); x = get_stereo_x(x, NULL, I->Width, NULL);
I->LastX = x; I->LastX = x;
I->LastY = y; I->LastY = y;
break; break;
case cButModePickAtom1: case cButModePickAtom1:
case cButModePickAtom: case cButModePickAtom:
case cButModeMenu: case cButModeMenu:
if(stereo_via_adjacent_array(I->StereoMode)) if(stereo_via_adjacent_array(I->StereoMode))
x = get_stereo_x(x, NULL, I->Width, NULL); x = get_stereo_x(x, NULL, I->Width, NULL);
if(SceneDoXYPick(G, x, y, click_side)) { if(SceneDoXYPick(G, x, y, click_side)) {
obj = (CObject *) I->LastPicked.context.object; obj = (CObject *) I->LastPicked.context.object;
y = y - I->Block->margin.bottom; y = y - I->margin.bottom;
x = x - I->Block->margin.left; x = x - I->margin.left;
I->LastX = x; I->LastX = x;
I->LastY = y; I->LastY = y;
switch (obj->type) { switch (obj->type) {
case cObjectMolecule: case cObjectMolecule:
switch (mode) { switch (mode) {
case cButModeMenu: case cButModeMenu:
{ {
ObjectMolecule *objMol = (ObjectMolecule *) obj; ObjectMolecule *objMol = (ObjectMolecule *) obj;
int active_sele = ExecutiveGetActiveSele(G); int active_sele = ExecutiveGetActiveSele(G);
if(active_sele if(active_sele
skipping to change at line 3917 skipping to change at line 3819
} }
SceneDirty(G); SceneDirty(G);
break; break;
case cButModePickBond: case cButModePickBond:
case cButModePkTorBnd: case cButModePkTorBnd:
if(stereo_via_adjacent_array(I->StereoMode)) if(stereo_via_adjacent_array(I->StereoMode))
x = get_stereo_x(x, NULL, I->Width, &click_side); x = get_stereo_x(x, NULL, I->Width, &click_side);
if(SceneDoXYPick(G, x, y, click_side)) { if(SceneDoXYPick(G, x, y, click_side)) {
obj = (CObject *) I->LastPicked.context.object; obj = (CObject *) I->LastPicked.context.object;
y = y - I->Block->margin.bottom; y = y - I->margin.bottom;
x = x - I->Block->margin.left; x = x - I->margin.left;
I->LastX = x; I->LastX = x;
I->LastY = y; I->LastY = y;
if(mode == cButModePkTorBnd) { if(mode == cButModePkTorBnd) {
I->Threshold = 3; I->Threshold = 3;
I->ThresholdX = x; I->ThresholdX = x;
I->ThresholdY = y; I->ThresholdY = y;
} }
switch (obj->type) { switch (obj->type) {
skipping to change at line 4017 skipping to change at line 3919
case cButModeMovFrag: case cButModeMovFrag:
case cButModeMovFragZ: case cButModeMovFragZ:
case cButModeTorFrag: case cButModeTorFrag:
case cButModeMoveAtom: case cButModeMoveAtom:
case cButModeMoveAtomZ: case cButModeMoveAtomZ:
if(stereo_via_adjacent_array(I->StereoMode)) if(stereo_via_adjacent_array(I->StereoMode))
x = get_stereo_x(x, NULL, I->Width, &click_side); x = get_stereo_x(x, NULL, I->Width, &click_side);
if(SceneDoXYPick(G, x, y, click_side)) { if(SceneDoXYPick(G, x, y, click_side)) {
obj = (CObject *) I->LastPicked.context.object; obj = (CObject *) I->LastPicked.context.object;
y = y - I->Block->margin.bottom; y = y - I->margin.bottom;
x = x - I->Block->margin.left; x = x - I->margin.left;
I->LastX = x; I->LastX = x;
I->LastY = y; I->LastY = y;
switch (obj->type) { switch (obj->type) {
case cObjectMolecule: case cObjectMolecule:
if(I->LastPicked.src.bond == cPickableLabel) { if(I->LastPicked.src.bond == cPickableLabel) {
/* if user picks a label with move object/move fragment, /* if user picks a label with move object/move fragment,
then move the object/fragment, not the label */ then move the object/fragment, not the label */
switch (mode) { switch (mode) {
skipping to change at line 4371 skipping to change at line 4273
glScalef(scale, scale, scale); glScalef(scale, scale, scale);
return scale; return scale;
} }
void ScenePopRasterMatrix(PyMOLGlobals * G) void ScenePopRasterMatrix(PyMOLGlobals * G)
{ {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPopMatrix(); glPopMatrix();
} }
/* /**
* Compose the ModelViewMatrix from Pos, RotMatrix and Origin * Compose the ModelViewMatrix from Pos, RotMatrix and Origin
* See also: CScene.ModMatrix (queried from OpenGL) * See also: CScene.ModMatrix (queried from OpenGL)
*
* @param[out] modelView 4x4 matrix
*/ */
static void SceneComposeModelViewMatrix(CScene * I, float * modelView) { static void SceneComposeModelViewMatrix(CScene * I, float * modelView) {
identity44f(modelView); identity44f(modelView);
MatrixTranslateC44f(modelView, I->Pos[0], I->Pos[1], I->Pos[2]); MatrixTranslateC44f(modelView, I->Pos[0], I->Pos[1], I->Pos[2]);
MatrixMultiplyC44f(I->RotMatrix, modelView); MatrixMultiplyC44f(I->RotMatrix, modelView);
MatrixTranslateC44f(modelView, -I->Origin[0], -I->Origin[1], -I->Origin[2]); MatrixTranslateC44f(modelView, -I->Origin[0], -I->Origin[1], -I->Origin[2]);
} }
/*========================================================================*/ /*========================================================================*/
void SceneGetEyeNormal(PyMOLGlobals * G, float *v1, float *normal) void SceneGetEyeNormal(PyMOLGlobals * G, float *v1, float *normal)
skipping to change at line 4400 skipping to change at line 4304
copy3f(v1, p1); copy3f(v1, p1);
p1[3] = 1.0; p1[3] = 1.0;
MatrixTransformC44f4f(modelView, p1, p2); /* modelview transformation */ MatrixTransformC44f4f(modelView, p1, p2); /* modelview transformation */
copy3f(p2, p1); copy3f(p2, p1);
normalize3f(p1); normalize3f(p1);
MatrixInvTransformC44fAs33f3f(I->RotMatrix, p1, p2); MatrixInvTransformC44fAs33f3f(I->RotMatrix, p1, p2);
invert3f3f(p2, normal); invert3f3f(p2, normal);
} }
/* /**
* Return true if the v1 is within the safe clipping planes * Return true if the v1 is within the safe clipping planes
*/ */
short SceneGetVisible(PyMOLGlobals * G, float *v1) bool SceneGetVisible(PyMOLGlobals * G, const float *v1)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
float depth = SceneGetRawDepth(G, v1); float depth = SceneGetRawDepth(G, v1);
return (I->BackSafe >= depth && depth >= I->FrontSafe); return (I->BackSafe >= depth && depth >= I->FrontSafe);
} }
/* /**
* Get the depth (camera space Z) of v1 * Get the depth (camera space Z) of v1
* *
* v1: point (3f) in world space or NULL (= origin) * @param v1 point (3f) in world space or NULL (= origin)
*/ */
float SceneGetRawDepth(PyMOLGlobals * G, float *v1) float SceneGetRawDepth(PyMOLGlobals * G, const float *v1)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
float vt[3]; float vt[3];
float modelView[16]; float modelView[16];
if(!v1 || SettingGetGlobal_i(G, cSetting_ortho)) if(!v1 || SettingGetGlobal_i(G, cSetting_ortho))
return -I->Pos[2]; return -I->Pos[2];
SceneComposeModelViewMatrix(I, modelView); SceneComposeModelViewMatrix(I, modelView);
MatrixTransformC44f3f(modelView, v1, vt); MatrixTransformC44f3f(modelView, v1, vt);
return -vt[2]; return -vt[2];
} }
/* /**
* Get the depth (camera space Z) of v1 in normalized clip space * Get the depth (camera space Z) of v1 in normalized clip space
* from 0.0 (near) to 1.0 (far) * from 0.0 (near) to 1.0 (far)
* *
* v1: point (3f) in world space or NULL (= origin) * @param v1 point (3f) in world space or NULL (= origin)
*/ */
float SceneGetDepth(PyMOLGlobals * G, float *v1) float SceneGetDepth(PyMOLGlobals * G, const float *v1)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
float rawDepth = SceneGetRawDepth(G, v1); float rawDepth = SceneGetRawDepth(G, v1);
return ((rawDepth - I->FrontSafe)/(I->BackSafe-I->FrontSafe)); return ((rawDepth - I->FrontSafe)/(I->BackSafe-I->FrontSafe));
} }
/*========================================================================*/ /*========================================================================*/
/* /**
* Get the angstrom per pixel factor at v1. If v1 is NULL, return the * Get the angstrom per pixel factor at v1. If v1 is NULL, return the
* factor at the origin, but clamped to an empirical positive value. * factor at the origin, but clamped to an empirical positive value.
* *
* v1: point (3f) in world space or NULL (= origin) * @param v1 point (3f) in world space or NULL (= origin)
*/ */
float SceneGetScreenVertexScale(PyMOLGlobals * G, float *v1) float SceneGetScreenVertexScale(PyMOLGlobals * G, const float *v1)
/* does not require OpenGL-provided matrices */ /* does not require OpenGL-provided matrices */
{ {
float depth = SceneGetRawDepth(G, v1); float depth = SceneGetRawDepth(G, v1);
float ratio = depth * GetFovWidth(G) / G->Scene->Height; float ratio = depth * GetFovWidth(G) / G->Scene->Height;
if(!v1 && ratio < R_SMALL4) if(!v1 && ratio < R_SMALL4)
// origin depth, return a safe clipped value (origin must not be // origin depth, return a safe clipped value (origin must not be
// behind or very close in front of the camera) // behind or very close in front of the camera)
ratio = R_SMALL4; ratio = R_SMALL4;
skipping to change at line 4800 skipping to change at line 4704
} }
I->RovingLastUpdate = UtilGetSeconds(G); I->RovingLastUpdate = UtilGetSeconds(G);
I->RovingDirtyFlag = false; I->RovingDirtyFlag = false;
} }
} }
/*========================================================================*/ /*========================================================================*/
static int SceneDrag(Block * block, int x, int y, int mod, double when) static int SceneDrag(Block * block, int x, int y, int mod, double when)
{ {
PyMOLGlobals *G = block->G; PyMOLGlobals *G = block->m_G;
CScene *I = G->Scene; CScene *I = G->Scene;
float scale, vScale; float scale, vScale;
float v1[3], v2[3], n1[3], n2[3], r1, r2, cp[3], v3[3]; float v1[3], v2[3], n1[3], n2[3], r1, r2, cp[3], v3[3];
float dx, dy, dt; float dx, dy, dt;
float axis[3], axis2[3], theta, omega; float axis[3], axis2[3], theta, omega;
float old_front, old_back, old_origin; float old_front, old_back, old_origin;
int mode; int mode;
int eff_width; int eff_width;
int moved_flag; int moved_flag;
int adjust_flag; int adjust_flag;
skipping to change at line 4900 skipping to change at line 4804
} }
} }
} }
} }
} }
if(!drag_handled) { if(!drag_handled) {
mode = ButModeTranslate(G, I->Button, mod); mode = ButModeTranslate(G, I->Button, mod);
y = y - I->Block->margin.bottom; y = y - I->margin.bottom;
scale = (float) I->Height; scale = (float) I->Height;
if(scale > I->Width) if(scale > I->Width)
scale = (float) I->Width; scale = (float) I->Width;
scale = 0.45F * scale; scale = 0.45F * scale;
SceneInvalidateCopy(G, false); SceneInvalidateCopy(G, false);
SceneDontCopyNext(G); SceneDontCopyNext(G);
switch (mode) { switch (mode) {
case cButModePickAtom: case cButModePickAtom:
obj = (CObject *) I->LastPicked.context.object; obj = (CObject *) I->LastPicked.context.object;
skipping to change at line 5635 skipping to change at line 5539
return (1); return (1);
} }
static int SceneDeferredClick(DeferredMouse * dm) static int SceneDeferredClick(DeferredMouse * dm)
{ {
if(!SceneClick(dm->block, dm->button, dm->x, dm->y, dm->mod, dm->when)) { if(!SceneClick(dm->block, dm->button, dm->x, dm->y, dm->mod, dm->when)) {
} }
return 1; return 1;
} }
/* /**
* Will call cmd.raw_image_callback(img) with the current RGBA image, copied * Will call cmd.raw_image_callback(img) with the current RGBA image, copied
* to a WxHx4 numpy array. Return false if no callback is defined * to a WxHx4 numpy array. Return false if no callback is defined
* (cmd.raw_image_callback == None). * (cmd.raw_image_callback == None).
*/ */
static static
bool call_raw_image_callback(PyMOLGlobals * G) { bool call_raw_image_callback(PyMOLGlobals * G) {
bool done = false; bool done = false;
#ifndef _PYMOL_NOPY #ifndef _PYMOL_NOPY
int blocked = PAutoBlock(G); int blocked = PAutoBlock(G);
auto raw_image_callback = auto raw_image_callback =
PyObject_GetAttrString(G->P_inst->cmd, "raw_image_callback"); PyObject_GetAttrString(G->P_inst->cmd, "raw_image_callback");
if (raw_image_callback != Py_None) { if (raw_image_callback != Py_None) {
#ifdef _PYMOL_NUMPY #ifdef _PYMOL_NUMPY
auto& image = G->Scene->Image; auto& image = G->Scene->Image;
// RGBA image as uint8 numpy array // RGBA image as uint8 numpy array
import_array1(0); import_array1(0);
npy_intp dims[3] = {image->width, image->height, 4}; npy_intp dims[3] = {image->getWidth(), image->getHeight(), 4};
auto py = PyArray_SimpleNew(3, dims, NPY_UINT8); auto py = PyArray_SimpleNew(3, dims, NPY_UINT8);
memcpy(PyArray_DATA((PyArrayObject *)py), image->data, dims[0] * dims[1] * 4 ); memcpy(PyArray_DATA((PyArrayObject *)py), image->bits(), dims[0] * dims[1] * 4);
PYOBJECT_CALLFUNCTION(raw_image_callback, "O", py); PYOBJECT_CALLFUNCTION(raw_image_callback, "O", py);
Py_DECREF(py); Py_DECREF(py);
done = true; done = true;
#else #else
PRINTFB(G, FB_Scene, FB_Errors) PRINTFB(G, FB_Scene, FB_Errors)
" raw_image_callback-Error: no numpy support\n" ENDFB(G); " raw_image_callback-Error: no numpy support\n" ENDFB(G);
#endif #endif
} }
Py_XDECREF(raw_image_callback); Py_XDECREF(raw_image_callback);
PAutoUnblock(G, blocked); PAutoUnblock(G, blocked);
#endif #endif
return done; return done;
} }
static int SceneDeferredImage(DeferredImage * di) static int SceneDeferredImage(DeferredImage * di)
{ {
PyMOLGlobals *G = di->G; PyMOLGlobals *G = di->m_G;
SceneMakeSizedImage(G, di->width, di->height, di->antialias); SceneMakeSizedImage(G, di->width, di->height, di->antialias);
if(di->filename) { if(!di->filename.empty()) {
ScenePNG(G, di->filename, di->dpi, di->quiet, false, di->format); ScenePNG(G, di->filename.c_str(), di->dpi, di->quiet, false, di->format);
FreeP(di->filename);
} else if(call_raw_image_callback(G)) { } else if(call_raw_image_callback(G)) {
} else if(G->HaveGUI && SettingGetGlobal_b(G, cSetting_auto_copy_images)) { } else if(G->HaveGUI && SettingGetGlobal_b(G, cSetting_auto_copy_images)) {
#ifdef _PYMOL_IP_EXTRAS #ifdef _PYMOL_IP_EXTRAS
if(IncentiveCopyToClipboard(G, di->quiet)) { if(IncentiveCopyToClipboard(G, di->quiet)) {
} }
#else #else
#ifdef PYMOL_EVAL #ifdef PYMOL_EVAL
PRINTFB(G, FB_Scene, FB_Warnings) PRINTFB(G, FB_Scene, FB_Warnings)
" Warning: Clipboard image transfers disabled in Evaluation builds.\n" END FB(G); " Warning: Clipboard image transfers disabled in Evaluation builds.\n" END FB(G);
#endif #endif
#endif #endif
} }
return 1; return 1;
} }
int SceneDeferImage(PyMOLGlobals * G, int width, int height, int SceneDeferImage(PyMOLGlobals * G, int width, int height,
const char *filename, int antialias, float dpi, int format, int quiet) const char *filename, int antialias, float dpi, int format, int quiet)
{ {
DeferredImage *di = Calloc(DeferredImage, 1); auto di = pymol::make_unique<DeferredImage>(G);
if(di) { if(di) {
DeferredInit(G, &di->deferred);
di->G = G;
di->width = width; di->width = width;
di->height = height; di->height = height;
di->antialias = antialias; di->antialias = antialias;
di->deferred.fn = (DeferredFn *) SceneDeferredImage; di->fn = (DeferredFn *) SceneDeferredImage;
di->dpi = dpi; di->dpi = dpi;
di->format = format; di->format = format;
di->quiet = quiet; di->quiet = quiet;
if(filename) { if(filename){
int stlen = strlen(filename); di->filename = filename;
di->filename = Alloc(char, stlen + 1);
strcpy(di->filename, filename);
} }
} }
OrthoDefer(G, &di->deferred); OrthoDefer(G, std::move(di));
return 1; return 1;
} }
int SceneDeferClick(Block * block, int button, int x, int y, int mod) int CScene::click(int button, int x, int y, int mod) // Originally SceneDeferCli ck!!
{ {
return SceneDeferClickWhen(block, button, x, y, UtilGetSeconds(block->G), mod) ; return SceneDeferClickWhen(this, button, x, y, UtilGetSeconds(m_G), mod);
} }
static int SceneDeferClickWhen(Block * block, int button, int x, int y, double w hen, static int SceneDeferClickWhen(Block * block, int button, int x, int y, double w hen,
int mod) int mod)
{ {
PyMOLGlobals *G = block->G; PyMOLGlobals *G = block->m_G;
DeferredMouse *dm = Calloc(DeferredMouse, 1); auto dm = pymol::make_unique<DeferredMouse>(G);
if(dm) { if(dm) {
DeferredInit(G, &dm->deferred);
dm->block = block; dm->block = block;
dm->button = button; dm->button = button;
dm->x = x; dm->x = x;
dm->y = y; dm->y = y;
dm->when = when; dm->when = when;
dm->mod = mod; dm->mod = mod;
dm->deferred.fn = (DeferredFn *) SceneDeferredClick; dm->fn = (DeferredFn *) SceneDeferredClick;
} }
OrthoDefer(G, &dm->deferred); OrthoDefer(G, std::move(dm));
return 1; return 1;
} }
static int SceneDeferredDrag(DeferredMouse * dm) static int SceneDeferredDrag(DeferredMouse * dm)
{ {
SceneDrag(dm->block, dm->x, dm->y, dm->mod, dm->when); SceneDrag(dm->block, dm->x, dm->y, dm->mod, dm->when);
return 1; return 1;
} }
int SceneDeferDrag(Block * block, int x, int y, int mod) int CScene::drag(int x, int y, int mod) //Originally SceneDeferDrag
{ {
PyMOLGlobals *G = block->G; PyMOLGlobals *G = m_G;
DeferredMouse *dm = Calloc(DeferredMouse, 1); auto dm = pymol::make_unique<DeferredMouse>(G);
if(dm) { if(dm) {
DeferredInit(G, &dm->deferred); dm->block = this;
dm->block = block;
dm->x = x; dm->x = x;
dm->y = y; dm->y = y;
dm->mod = mod; dm->mod = mod;
dm->when = UtilGetSeconds(G); dm->when = UtilGetSeconds(G);
dm->deferred.fn = (DeferredFn *) SceneDeferredDrag; dm->fn = (DeferredFn *) SceneDeferredDrag;
} }
OrthoDefer(G, &dm->deferred); OrthoDefer(G, std::move(dm));
return 1; return 1;
} }
static int SceneDeferredRelease(DeferredMouse * dm) static int SceneDeferredRelease(DeferredMouse * dm)
{ {
SceneRelease(dm->block, dm->button, dm->x, dm->y, dm->mod, dm->when); SceneRelease(dm->block, dm->button, dm->x, dm->y, dm->mod, dm->when);
return 1; return 1;
} }
int SceneDeferRelease(Block * block, int button, int x, int y, int mod) int CScene::release(int button, int x, int y, int mod) // Originally SceneDeferR elease
{ {
PyMOLGlobals *G = block->G; PyMOLGlobals *G = m_G;
DeferredMouse *dm = Calloc(DeferredMouse, 1); auto dm = pymol::make_unique<DeferredMouse>(G);
if(dm) { if(dm) {
DeferredInit(G, &dm->deferred); dm->block = this;
dm->block = block;
dm->button = button; dm->button = button;
dm->x = x; dm->x = x;
dm->y = y; dm->y = y;
dm->mod = mod; dm->mod = mod;
dm->when = UtilGetSeconds(G); dm->when = UtilGetSeconds(G);
dm->deferred.fn = (DeferredFn *) SceneDeferredRelease; dm->fn = (DeferredFn *) SceneDeferredRelease;
} }
OrthoDefer(G, &dm->deferred); OrthoDefer(G, std::move(dm));
return 1; return 1;
} }
/*========================================================================*/ /*========================================================================*/
void SceneFree(PyMOLGlobals * G) void SceneFree(PyMOLGlobals * G)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
#if !defined(PURE_OPENGL_ES_2) || defined(_WEBGL) #if !defined(PURE_OPENGL_ES_2) || defined(_WEBGL)
CGOFree(I->offscreenCGO); CGOFree(I->offscreenCGO);
#endif #endif
if(I->ScrollBar)
ScrollBarFree(I->ScrollBar);
CGOFree(I->AlphaCGO); CGOFree(I->AlphaCGO);
CGOFree(I->offscreenCGO); CGOFree(I->offscreenCGO);
CGOFree(I->offscreenOIT_CGO); CGOFree(I->offscreenOIT_CGO);
CGOFree(I->offscreenOIT_CGO_copy); CGOFree(I->offscreenOIT_CGO_copy);
VLAFreeP(I->SceneVLA); VLAFreeP(I->SceneVLA);
VLAFreeP(I->SceneNameVLA); VLAFreeP(I->SceneNameVLA);
VLAFreeP(I->SlotVLA); VLAFreeP(I->SlotVLA);
VLAFreeP(I->pickVLA);
OrthoFreeBlock(G, I->Block);
I->Obj.clear(); I->Obj.clear();
I->GadgetObjs.clear(); I->GadgetObjs.clear();
I->NonGadgetObjs.clear(); I->NonGadgetObjs.clear();
ScenePurgeImage(G); ScenePurgeImage(G);
CGOFree(G->DebugCGO); CGOFree(G->DebugCGO);
delete G->Scene; delete G->Scene;
} }
/*========================================================================*/ /*========================================================================*/
skipping to change at line 5872 skipping to change at line 5764
SceneSetFrame(G, 0, 0); SceneSetFrame(G, 0, 0);
SceneInvalidate(G); SceneInvalidate(G);
G->Scene->NScene = 0; G->Scene->NScene = 0;
return (ok); return (ok);
} }
/*========================================================================*/ /*========================================================================*/
int SceneInit(PyMOLGlobals * G) int SceneInit(PyMOLGlobals * G)
{ {
CScene *I = NULL; CScene *I = NULL;
I = (G->Scene = new CScene()); I = (G->Scene = new CScene(G));
if(I) { if(I) {
/* all defaults to zero, so only initialize non-zero elements */ /* all defaults to zero, so only initialize non-zero elements */
G->DebugCGO = CGONew(G); G->DebugCGO = CGONew(G);
I->TextColor[0] = 0.2F; I->TextColor[0] = 0.2F;
I->TextColor[1] = 1.0F; I->TextColor[1] = 1.0F;
I->TextColor[2] = 0.2F; I->TextColor[2] = 0.2F;
I->LastClickTime = UtilGetSeconds(G); I->LastClickTime = UtilGetSeconds(G);
SceneSetDefaultView(G); SceneSetDefaultView(G);
I->Scale = 1.0; I->Scale = 1.0;
I->Block = OrthoNewBlock(G, NULL); I->active = true;
I->Block->fClick = SceneDeferClick;
I->Block->fRelease = SceneDeferRelease;
I->Block->fDrag = SceneDeferDrag;
I->Block->fDraw = SceneDraw;
I->Block->fReshape = SceneReshape;
I->Block->active = true;
OrthoAttach(G, I->Block, cOrthoScene); OrthoAttach(G, I, cOrthoScene);
I->DirtyFlag = true; I->DirtyFlag = true;
I->LastRender = UtilGetSeconds(G); I->LastRender = UtilGetSeconds(G);
I->LastFrameTime = UtilGetSeconds(G); I->LastFrameTime = UtilGetSeconds(G);
I->LastSweepTime = UtilGetSeconds(G); I->LastSweepTime = UtilGetSeconds(G);
I->LastStateBuilt = -1; I->LastStateBuilt = -1;
I->CopyNextFlag = true; I->CopyNextFlag = true;
skipping to change at line 5918 skipping to change at line 5804
SceneRestartFrameTimer(G); SceneRestartFrameTimer(G);
SceneRestartPerfTimer(G); SceneRestartPerfTimer(G);
I->Width = 640; /* standard defaults */ I->Width = 640; /* standard defaults */
I->Height = 480; I->Height = 480;
I->VertexScale = 0.01F; I->VertexScale = 0.01F;
/* scene list */ /* scene list */
I->ScrollBar = ScrollBarNew(G, false);
I->Pressed = -1; I->Pressed = -1;
I->Over = -1; I->Over = -1;
I->SceneNameVLA = VLAlloc(char, 10); I->SceneNameVLA = VLAlloc(char, 10);
I->SceneVLA = VLAlloc(SceneElem, 10); I->SceneVLA = VLAlloc(SceneElem, 10);
return 1; return 1;
} else } else
return 0; return 0;
} }
/*========================================================================*/ /*========================================================================*/
void SceneReshape(Block * block, int width, int height) void CScene::reshape(int width, int height)
{ {
PyMOLGlobals *G = block->G; PyMOLGlobals *G = m_G;
CScene *I = G->Scene; CScene *I = G->Scene;
if(I->Block->margin.right) { if(I->margin.right) {
width -= I->Block->margin.right; width -= I->margin.right;
if(width < 1) if(width < 1)
width = 1; width = 1;
} }
if(I->Block->margin.top) { if(I->margin.top) {
height -= I->Block->margin.top; height -= I->margin.top;
} }
I->Width = width; I->Width = width;
I->Height = height; I->Height = height;
I->Block->rect.top = I->Height; I->rect.top = I->Height;
I->Block->rect.left = 0; I->rect.left = 0;
I->Block->rect.bottom = 0; I->rect.bottom = 0;
I->Block->rect.right = I->Width; I->rect.right = I->Width;
if(I->Block->margin.bottom) { if(I->margin.bottom) {
height -= I->Block->margin.bottom; height -= I->margin.bottom;
if(height < 1) if(height < 1)
height = 1; height = 1;
I->Height = height; I->Height = height;
I->Block->rect.bottom = I->Block->rect.top - I->Height; I->rect.bottom = I->rect.top - I->Height;
} }
SceneDirty(G); SceneDirty(G);
if(I->CopyType && (!I->CopyForced)) { if(I->CopyType && (!I->CopyForced)) {
SceneInvalidateCopy(G, false); SceneInvalidateCopy(G, false);
} }
/*MovieClearImages(G); */ /*MovieClearImages(G); */
MovieSetSize(G, I->Width, I->Height); MovieSetSize(G, I->Width, I->Height);
SceneInvalidateStencil(G); SceneInvalidateStencil(G);
} }
/*========================================================================*/ /*========================================================================*/
void SceneDone(PyMOLGlobals * G) void SceneDone(PyMOLGlobals * G)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
if(I->Block)
OrthoFreeBlock(G, I->Block);
} }
/*========================================================================*/ /*========================================================================*/
void SceneResetNormal(PyMOLGlobals * G, int lines) void SceneResetNormal(PyMOLGlobals * G, int lines)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
if(G->HaveGUI && G->ValidContext) { if(G->HaveGUI && G->ValidContext) {
if(lines) if(lines)
glNormal3fv(I->LinesNormal); glNormal3fv(I->LinesNormal);
else else
skipping to change at line 6263 skipping to change at line 6146
SettingGetGlobal_b(G, cSetting_stereo_double_pump_mono) || I->B uttonsShown))) { SettingGetGlobal_b(G, cSetting_stereo_double_pump_mono) || I->B uttonsShown))) {
/* no copies while in stereo mode */ /* no copies while in stereo mode */
if(force || ((!I->DirtyFlag) && (!I->CopyType))) { if(force || ((!I->DirtyFlag) && (!I->CopyType))) {
int x, y, w, h; int x, y, w, h;
if(entire_window) { if(entire_window) {
x = 0; x = 0;
y = 0; y = 0;
h = OrthoGetHeight(G); h = OrthoGetHeight(G);
w = OrthoGetWidth(G); w = OrthoGetWidth(G);
} else { } else {
x = I->Block->rect.left; x = I->rect.left;
y = I->Block->rect.bottom; y = I->rect.bottom;
w = I->Width; w = I->Width;
h = I->Height; h = I->Height;
} }
ScenePurgeImage(G); ScenePurgeImage(G);
buffer_size = 4 * w * h; buffer_size = 4 * w * h;
if(buffer_size) { if(buffer_size) {
I->Image = Calloc(ImageType, 1); I->Image = std::make_shared<pymol::Image>(w, h);
I->Image->data = Alloc(unsigned char, buffer_size);
I->Image->size = buffer_size;
I->Image->width = w;
I->Image->height = h;
if(G->HaveGUI && G->ValidContext) { if(G->HaveGUI && G->ValidContext) {
glReadBuffer(buffer); glReadBuffer(buffer);
PyMOLReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, I->Image->data) ; PyMOLReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, I->Image->bits( ));
} }
} }
I->CopyType = true; I->CopyType = true;
I->Image->needs_alpha_reset = true; I->Image->m_needs_alpha_reset = true;
I->CopyForced = force; I->CopyForced = force;
} }
} }
} }
/*========================================================================*/ /*========================================================================*/
int SceneRovingCheckDirty(PyMOLGlobals * G) int SceneRovingCheckDirty(PyMOLGlobals * G)
{ {
CScene *I = G->Scene; CScene *I = G->Scene;
return (I->RovingDirtyFlag); return (I->RovingDirtyFlag);
skipping to change at line 6386 skipping to change at line 6265
if(force || I->ChangedFlag || ((cur_state != I->LastStateBuilt) && if(force || I->ChangedFlag || ((cur_state != I->LastStateBuilt) &&
(defer_builds_mode > 0))) { (defer_builds_mode > 0))) {
SceneCountFrames(G); SceneCountFrames(G);
if(force || (defer_builds_mode != 5)) { /* mode 5 == immediate mode */ if(force || (defer_builds_mode != 5)) { /* mode 5 == immediate mode */
PyMOL_SetBusy(G->PyMOL, true); /* race condition -- may need to be fix ed */ PyMOL_SetBusy(G->PyMOL, true); /* race condition -- may need to be fix ed */
/* update all gadgets first (single-threaded since they're thread-unsafe) */ /* update all gadgets first (single-threaded since they're thread-unsafe) */
for ( auto it = I->GadgetObjs.begin(); it != I->GadgetObjs.end(); ++it) { for (auto& GadgetObj : I->GadgetObjs) {
(*it)->update(); GadgetObj->update();
} }
{ {
#ifndef _PYMOL_NOPY #ifndef _PYMOL_NOPY
int n_thread = SettingGetGlobal_i(G, cSetting_max_threads); int n_thread = SettingGetGlobal_i(G, cSetting_max_threads);
int multithread = SettingGetGlobal_i(G, cSetting_async_builds); int multithread = SettingGetGlobal_i(G, cSetting_async_builds);
if(multithread && (n_thread > 1)) { if(multithread && (n_thread > 1)) {
int min_start = -1; int min_start = -1;
int max_stop = -1; int max_stop = -1;
int n_frame = SceneGetNFrame(G, NULL); int n_frame = SceneGetNFrame(G, NULL);
int n_obj = 0; int n_obj = 0;
for ( auto it = I->Obj.begin(); it != I->Obj.end(); ++it) { for (auto& obj : I->Obj) {
int start = 0; int start = 0;
int stop = n_frame; int stop = n_frame;
n_obj++; n_obj++;
if((*it)->fGetNFrame) { if(obj->fGetNFrame) {
stop = (*it)->fGetNFrame(*it); stop = obj->fGetNFrame(obj);
} }
/* set start/stop to define the range for this object /* set start/stop to define the range for this object
* depending upon various build settings */ * depending upon various build settings */
ObjectAdjustStateRebuildRange(*it, &start, &stop); ObjectAdjustStateRebuildRange(obj, &start, &stop);
if(min_start < 0) { if(min_start < 0) {
min_start = start; min_start = start;
max_stop = stop; max_stop = stop;
} else { } else {
if(min_start > start) if(min_start > start)
min_start = start; min_start = start;
if(max_stop < stop) if(max_stop < stop)
max_stop = stop; max_stop = stop;
} }
} }
skipping to change at line 6444 skipping to change at line 6323
/* Note: we might want to optimize this by doing multi-threaded updates /* Note: we might want to optimize this by doing multi-threaded updates
for all objects. */ for all objects. */
if(multithread && (n_thread > 1)) { if(multithread && (n_thread > 1)) {
/* multi-threaded geometry update */ /* multi-threaded geometry update */
int cnt = I->NonGadgetObjs.size(); int cnt = I->NonGadgetObjs.size();
if(cnt) { if(cnt) {
CObjectUpdateThreadInfo *thread_info = Alloc(CObjectUpdateThreadInfo , cnt); CObjectUpdateThreadInfo *thread_info = Alloc(CObjectUpdateThreadInfo , cnt);
if(thread_info) { if(thread_info) {
cnt = 0; cnt = 0;
for ( auto it = I->NonGadgetObjs.begin(); it != I->NonGadgetObjs.e for (auto& NonGadgetObj : I->NonGadgetObjs) {
nd(); ++it) { thread_info[cnt++].obj = NonGadgetObj;
thread_info[cnt++].obj = *it;
} }
SceneObjectUpdateSpawn(G, thread_info, n_thread, cnt); SceneObjectUpdateSpawn(G, thread_info, n_thread, cnt);
FreeP(thread_info); FreeP(thread_info);
} }
} }
} else } else
#endif #endif
/* single-threaded update */ /* single-threaded update */
for ( auto it = I->Obj.begin(); it != I->Obj.end(); ++it) { for (auto& obj : I->Obj) {
(*it)->update(); obj->update();
} }
} }
PyMOL_SetBusy(G->PyMOL, false); /* race condition -- may need to be fix ed */ PyMOL_SetBusy(G->PyMOL, false); /* race condition -- may need to be fix ed */
} else { /* defer builds mode == 5 -- for now, only update non-molecular obj ects */ } else { /* defer builds mode == 5 -- for now, only update non-molecular obj ects */
/* single-threaded update */ /* single-threaded update */
for ( auto it = I->Obj.begin(); it != I->Obj.end(); ++it) { for (auto& obj : I->Obj) {
if((*it)->type != cObjectMolecule) { if(obj->type != cObjectMolecule) {
(*it)->update(); obj->update();
} }
} }
} }
I->ChangedFlag = false; I->ChangedFlag = false;
if((defer_builds_mode >= 2) && (force || (defer_builds_mode != 5)) && if((defer_builds_mode >= 2) && (force || (defer_builds_mode != 5)) &&
(cur_state != I->LastStateBuilt)) { (cur_state != I->LastStateBuilt)) {
/* purge graphics representation when no longer used */ /* purge graphics representation when no longer used */
if(I->LastStateBuilt >= 0) { if(I->LastStateBuilt >= 0) {
skipping to change at line 6527 skipping to change at line 6406
PRINTFD(G, FB_Scene) PRINTFD(G, FB_Scene)
" SceneUpdate: leaving...\n" ENDFD; " SceneUpdate: leaving...\n" ENDFD;
} }
/*========================================================================*/ /*========================================================================*/
int SceneRenderCached(PyMOLGlobals * G) int SceneRenderCached(PyMOLGlobals * G)
{ {
/* sets up a cached image buffer is one is available, or if we are /* sets up a cached image buffer is one is available, or if we are
* using cached images by default */ * using cached images by default */
CScene *I = G->Scene; CScene *I = G->Scene;
ImageType *image; std::shared_ptr<pymol::Image> image;
int renderedFlag = false; int renderedFlag = false;
int draw_mode = SettingGetGlobal_i(G, cSetting_draw_mode); int draw_mode = SettingGetGlobal_i(G, cSetting_draw_mode);
PRINTFD(G, FB_Scene) PRINTFD(G, FB_Scene)
" SceneRenderCached: entered.\n" ENDFD; " SceneRenderCached: entered.\n" ENDFD;
G->ShaderMgr->Check_Reload(); G->ShaderMgr->Check_Reload();
if(I->DirtyFlag) { if(I->DirtyFlag) {
int moviePlaying = MoviePlaying(G); int moviePlaying = MoviePlaying(G);
if(I->MovieFrameFlag || (moviePlaying && SettingGetGlobal_b(G, cSetting_cach e_frames))) { if(I->MovieFrameFlag || (moviePlaying && SettingGetGlobal_b(G, cSetting_cach e_frames))) {
I->MovieFrameFlag = false; I->MovieFrameFlag = false;
image = MovieGetImage(G, image = MovieGetImage(G,
MovieFrameToImage(G, MovieFrameToImage(G,
SettingGetGlobal_i(G, cSetting_fra me) - 1)); SettingGetGlobal_i(G, cSetting_fra me) - 1));
if(image) { if(image) {
if(I->Image && (!I->MovieOwnsImageFlag)) if(I->Image){
ScenePurgeImage(G); ScenePurgeImage(G);
I->MovieOwnsImageFlag = true; }
I->CopyType = true; I->CopyType = true;
I->Image = image; I->Image = image;
OrthoDirty(G); OrthoDirty(G);
renderedFlag = true; renderedFlag = true;
} else { } else {
SceneMakeMovieImage(G, true, false, cSceneImage_Default); SceneMakeMovieImage(G, true, false, cSceneImage_Default);
renderedFlag = true; renderedFlag = true;
} }
} else if(draw_mode == 3) { } else if(draw_mode == 3) {
auto show_progress = SettingGet<int>(G, cSetting_show_progress); auto show_progress = SettingGet<int>(G, cSetting_show_progress);
skipping to change at line 6613 skipping to change at line 6492
copy3f(SettingGetGlobal_3fv(G, light_setting_indices[i]), tmp); copy3f(SettingGetGlobal_3fv(G, light_setting_indices[i]), tmp);
normalize3f(tmp); normalize3f(tmp);
sum += 1.f - tmp[2]; sum += 1.f - tmp[2];
} }
sum *= 0.5; sum *= 0.5;
return result / sum; return result / sum;
} }
return result; return result;
} }
/* /**
* Get specular and shininess, adjusted to the number of lights. * Get specular and shininess, adjusted to the number of lights.
* *
* ptr_spec: specular for lights 2-N * @param[out] ptr_spec specular for lights 2-N
* ptr_spec_power: shininess for lights 2-N * @param[out] ptr_spec_power shininess for lights 2-N
* ptr_spec_direct: specular for light 1 * @param[out] ptr_spec_direct specular for light 1
* ptr_spec_direct_power: shininess for light 1 * @param[out] ptr_spec_direct_power shininess for light 1
* @param limit number of lights (e.g. `light_count` setting)
*/ */
void SceneGetAdjustedLightValues(PyMOLGlobals * G, void SceneGetAdjustedLightValues(PyMOLGlobals * G,
float *ptr_spec, float *ptr_spec,
float *ptr_spec_power, float *ptr_spec_power,
float *ptr_spec_direct, float *ptr_spec_direct,
float *ptr_spec_direct_power, float *ptr_spec_direct_power,
int limit) int limit)
{ {
float specular = SettingGetGlobal_f(G, cSetting_specular); float specular = SettingGetGlobal_f(G, cSetting_specular);
if (specular == 1.0F) if (specular == 1.0F)
skipping to change at line 6673 skipping to change at line 6553
}; };
#undef TEMPLATE #undef TEMPLATE
#define TEMPLATE(i) "g_LightSource[" #i "].diffuse" #define TEMPLATE(i) "g_LightSource[" #i "].diffuse"
const char * lightsource_diffuse_names[] = { const char * lightsource_diffuse_names[] = {
TEMPLATE(0), TEMPLATE(1), TEMPLATE(2), TEMPLATE(3), TEMPLATE(4), TEMPLATE(0), TEMPLATE(1), TEMPLATE(2), TEMPLATE(3), TEMPLATE(4),
TEMPLATE(5), TEMPLATE(6), TEMPLATE(7), TEMPLATE(8), TEMPLATE(9) TEMPLATE(5), TEMPLATE(6), TEMPLATE(7), TEMPLATE(8), TEMPLATE(9)
}; };
#undef TEMPLATE #undef TEMPLATE
/* /**
* Sets up lighting for immediate mode if shaderPrg=NULL, otherwise * Sets up lighting for immediate mode if shaderPrg=NULL, otherwise
* sets lighting uniforms for the given shader program. * sets lighting uniforms for the given shader program.
* *
* Supports up to light_count=8 * Supports up to light_count=8
*/ */
void SceneProgramLighting(PyMOLGlobals * G, CShaderPrg * shaderPrg) void SceneProgramLighting(PyMOLGlobals * G, CShaderPrg * shaderPrg)
{ {
/* load up the light positions relative to the camera while /* load up the light positions relative to the camera while
MODELVIEW still has the identity */ MODELVIEW still has the identity */
skipping to change at line 6791 skipping to change at line 6671
} }
#endif #endif
} }
#ifdef _PYMOL_SHARP3D #ifdef _PYMOL_SHARP3D
void sharp3d_begin_left_stereo(void); void sharp3d_begin_left_stereo(void);
void sharp3d_switch_to_right_stereo(void); void sharp3d_switch_to_right_stereo(void);
void sharp3d_end_stereo(void); void sharp3d_end_stereo(void);
#endif #endif
/* /**
* Set up the Scene Fog* member variables and immediate mode fog (incl. * Set up the Scene Fog* member variables and immediate mode fog (incl.
* gl_Fog struct for non-ES2 shaders) * gl_Fog struct for non-ES2 shaders)
*/ */
int SceneSetFog(PyMOLGlobals *G){ int SceneSetFog(PyMOLGlobals *G){
CScene *I = G->Scene; CScene *I = G->Scene;
int fog_active = false; int fog_active = false;
float fog_density = SettingGetGlobal_f(G, cSetting_fog); float fog_density = SettingGetGlobal_f(G, cSetting_fog);
I->FogStart = (I->BackSafe - I->FrontSafe) * SettingGetGlobal_f(G, cSetting_fo g_start) + I->FrontSafe; I->FogStart = (I->BackSafe - I->FrontSafe) * SettingGetGlobal_f(G, cSetting_fo g_start) + I->FrontSafe;
if((fog_density > R_SMALL8) && (fog_density != 1.0F)) { if((fog_density > R_SMALL8) && (fog_density != 1.0F)) {
I->FogEnd = I->FogStart + (I->BackSafe - I->FogStart) / fog_density; I->FogEnd = I->FogStart + (I->BackSafe - I->FogStart) / fog_density;
skipping to change at line 6830 skipping to change at line 6710
if (fog_active) if (fog_active)
glEnable(GL_FOG); glEnable(GL_FOG);
else else
glDisable(GL_FOG); glDisable(GL_FOG);
} }
#endif #endif
return fog_active; return fog_active;
} }
/* /**
* Set the g_Fog_* uniforms for ES2 shaders * Set the g_Fog_* uniforms for ES2 shaders
*/ */
void SceneSetFogUniforms(PyMOLGlobals * G, CShaderPrg * shaderPrg) { void SceneSetFogUniforms(PyMOLGlobals * G, CShaderPrg * shaderPrg) {
CScene *I = G->Scene; CScene *I = G->Scene;
if (shaderPrg) { if (shaderPrg) {
float fogScale = 1.0f / (I->FogEnd - I->FogStart); float fogScale = 1.0f / (I->FogEnd - I->FogStart);
shaderPrg->Set1f("g_Fog_end", I->FogEnd); shaderPrg->Set1f("g_Fog_end", I->FogEnd);
shaderPrg->Set1f("g_Fog_scale", fogScale); shaderPrg->Set1f("g_Fog_scale", fogScale);
} }
} }
skipping to change at line 7281 skipping to change at line 7161
float SceneGetCurrentBackSafe(PyMOLGlobals *G){ float SceneGetCurrentBackSafe(PyMOLGlobals *G){
CScene *I = G->Scene; CScene *I = G->Scene;
return (I->BackSafe); return (I->BackSafe);
} }
float SceneGetCurrentFrontSafe(PyMOLGlobals *G){ float SceneGetCurrentFrontSafe(PyMOLGlobals *G){
CScene *I = G->Scene; CScene *I = G->Scene;
return (I->FrontSafe); return (I->FrontSafe);
} }
/* /**
* Get the field-of-view width at a depth of 1.0 * Get the field-of-view width at a depth of 1.0
*/ */
float GetFovWidth(PyMOLGlobals * G) float GetFovWidth(PyMOLGlobals * G)
{ {
float fov = SettingGetGlobal_f(G, cSetting_field_of_view); float fov = SettingGetGlobal_f(G, cSetting_field_of_view);
return 2.f * tanf(fov * PI / 360.f); return 2.f * tanf(fov * PI / 360.f);
} }
void SceneInvalidatePicking(PyMOLGlobals * G){ void SceneInvalidatePicking(PyMOLGlobals * G){
CScene *I = G->Scene; CScene *I = G->Scene;
 End of changes. 213 change blocks. 
465 lines changed or deleted 333 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)