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 |