layer1/Setting.cpp (2,764 lines of code) (raw):
/*
A* -------------------------------------------------------------------
B* This file contains source code for the PyMOL computer program
C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
D* -------------------------------------------------------------------
E* It is unlawful to modify or remove this copyright notice.
F* -------------------------------------------------------------------
G* Please see the accompanying LICENSE file for further information.
H* -------------------------------------------------------------------
I* Additional authors of this source file include:
-*
-*
-*
Z* -------------------------------------------------------------------
*/
#include"os_python.h"
#include"os_proprietary.h"
#include"os_predef.h"
#include"os_std.h"
#include"Base.h"
#include"OOMac.h"
#include"MemoryDebug.h"
#include"Ortho.h"
#include"Setting.h"
#include"Scene.h"
#include"ButMode.h"
#include"CGO.h"
#include"Executive.h"
#include"Editor.h"
#include"P.h"
#include"Util.h"
#include"main.h"
#include"PConv.h"
#include"Wizard.h"
#include"Seq.h"
#include"PyMOLOptions.h"
#include"OVContext.h"
#include"ShaderMgr.h"
#include"Sphere.h"
#include"Selector.h"
#include"Parse.h"
/*
* Setting level info table
*
* Levels are not hierarchical at the atom/bond level, that's why a simple
* sorted enumeration is not sufficient.
*
* global < object < object-state
* object-state < atom < atom-state
* object-state < bond < bond-state
*/
const SettingLevelInfoType SettingLevelInfo[] = {
{"unused" , 0x00}, // 0b00000000
{"global" , 0x00}, // 0b00000000
{"object" , 0x01}, // 0b00000001
{"object-state" , 0x03}, // 0b00000011
{"atom" , 0x07}, // 0b00000111
{"atom-state" , 0x0F}, // 0b00001111
{"bond" , 0x13}, // 0b00010011
{"bond-state" , 0x33}, // 0b00110011
{NULL, 0}
};
// The following defines the static SettingInfo table
#define SETTINGINFO_IMPLEMENTATION
#include "SettingInfo.h"
template <> const char * SettingGet<const char *>(int index, const CSetting * I);
// get level name for setting index (for feedback)
const char * SettingLevelGetName(PyMOLGlobals * G, int index) {
return SettingLevelInfo[SettingInfo[index].level].name;
}
// check if setting index is valid in given level-mask
bool SettingLevelCheckMask(PyMOLGlobals * G, int index, unsigned char mask) {
unsigned char validmask = SettingLevelInfo[SettingInfo[index].level].mask;
return (0 == (mask & ~validmask));
}
// check if setting index is valid in given level
bool SettingLevelCheck(PyMOLGlobals * G, int index, unsigned char level) {
return SettingLevelCheckMask(G, index, SettingLevelInfo[level].mask);
}
/* ================================================================== */
static CSetting *SettingCopyAll(PyMOLGlobals * G, const CSetting * src, CSetting * dst)
{
if(!dst) {
dst = Calloc(CSetting, 1);
} else {
SettingPurge(dst);
}
SettingInit(G, dst);
if(dst && src) {
/* simply overwriting existing data (if any) ... in the future we
may need to release references etc. before doing this */
unsigned int size = VLAGetSize(src->info);
VLACheck(dst->info, SettingRec, size - 1);
UtilCopyMem(dst->info, src->info, sizeof(SettingRec) * size);
dst->size = src->size;
// need to properly copy strings
for (int index = 0; index < cSetting_INIT; ++index) {
if (SettingInfo[index].type == cSetting_string
&& src->info[index].str_) {
dst->info[index].str_ = new std::string(*src->info[index].str_);
}
}
}
return dst;
}
void SettingStoreDefault(PyMOLGlobals * G)
{
G->Default = SettingCopyAll(G, G->Setting, G->Default);
}
void SettingPurgeDefault(PyMOLGlobals * G)
{
if(G->Default) {
SettingPurge(G->Default);
FreeP(G->Default);
G->Default = NULL;
}
}
void SettingUniqueDetachChain(PyMOLGlobals * G, int unique_id)
{
CSettingUnique *I = G->SettingUnique;
OVreturn_word result;
if(OVreturn_IS_OK(result = OVOneToOne_GetForward(I->id2offset, unique_id))) {
int offset = result.word;
int next;
OVOneToOne_DelForward(I->id2offset, unique_id);
{
SettingUniqueEntry *entry;
while(offset) {
entry = I->entry + offset;
next = entry->next;
entry->next = I->next_free;
I->next_free = offset;
offset = next;
}
}
} else {
/* uncaught error */
}
}
static void SettingUniqueExpand(PyMOLGlobals * G)
{
CSettingUnique *I = G->SettingUnique;
if(!I->next_free) {
int new_n_alloc = (I->n_alloc * 3) / 2;
int a;
VLACheck(I->entry, SettingUniqueEntry, new_n_alloc);
for(a = I->n_alloc; a < new_n_alloc; a++) {
I->entry[a].next = I->next_free;
I->next_free = a;
}
I->n_alloc = new_n_alloc;
}
}
static
SettingUniqueEntry *SettingFindSettingUniqueEntry(PyMOLGlobals * G, int unique_id, int setting_id)
{
CSettingUnique *I = G->SettingUnique;
OVreturn_word result;
if(OVreturn_IS_OK(result = OVOneToOne_GetForward(I->id2offset, unique_id))) {
SettingUniqueEntry *entry;
for (int offset = result.word; offset; offset = entry->next) {
entry = I->entry + offset;
if(entry->setting_id == setting_id) {
return entry;
}
}
}
return NULL;
}
int SettingUniqueCheck(PyMOLGlobals * G, int unique_id, int setting_id)
{
return SettingFindSettingUniqueEntry(G, unique_id, setting_id) != NULL;
}
/*
* Return true for convertible types and set int-compatible types to int
*/
inline bool type_upcast(int &type) {
switch (type) {
case cSetting_int:
case cSetting_color:
case cSetting_boolean:
type = cSetting_int;
case cSetting_float:
return true;
}
return false;
}
bool SettingUniqueGetTypedValuePtr(PyMOLGlobals * G, int unique_id, int setting_id,
int setting_type, void * value)
{
auto entry = SettingFindSettingUniqueEntry(G, unique_id, setting_id);
if (!entry)
return false;
int type_from = SettingInfo[setting_id].type;
if (type_from != setting_type) {
if (!type_upcast(type_from) ||
!type_upcast(setting_type)) {
PRINTFB(G, FB_Setting, FB_Errors)
" Setting-Error: type mismatch\n" ENDFB(G);
return false;
}
}
if (setting_type == cSetting_float3){
*(const float **) value = entry->value.float3_;
} else if (setting_type == type_from) {
*(int *) value = entry->value.int_;
} else if (setting_type == cSetting_int) {
*(int *) value = (int) entry->value.float_;
} else { // setting_type == cSetting_float
*(float *) value = (float) entry->value.int_;
}
return true;
}
/*
* Warning: Returns colors as (fff) tuple instead of color index
*/
PyObject *SettingUniqueGetPyObject(PyMOLGlobals * G, int unique_id, int index)
{
int type = SettingGetType(G, index);
union {
int val_i;
float val_f;
const float * ptr_3f;
};
if (SettingUniqueGetTypedValuePtr(G, unique_id, index, type, &ptr_3f)) {
switch (type) {
case cSetting_boolean:
return CPythonVal_New_Boolean(val_i);
case cSetting_int:
return CPythonVal_New_Integer(val_i);
case cSetting_float:
return CPythonVal_New_Float(val_f);
case cSetting_color:
#ifdef _PYMOL_NOPY
return CPythonVal_New_Integer(val_i);
#else
return PYOBJECT_CALLFUNCTION(G->P_inst->colortype, "i", val_i);
#endif
case cSetting_float3:
{
PyObject *result = PyTuple_New(3);
PyTuple_SET_ITEM(result, 0, CPythonVal_New_Float(ptr_3f[0]));
PyTuple_SET_ITEM(result, 1, CPythonVal_New_Float(ptr_3f[1]));
PyTuple_SET_ITEM(result, 2, CPythonVal_New_Float(ptr_3f[2]));
return result;
}
}
}
return NULL;
}
static int SettingUniqueEntry_IsSame(SettingUniqueEntry *entry, int setting_type, const void *value){
if (SettingInfo[entry->setting_id].type != setting_type){
return 0;
}
if (setting_type == cSetting_float3){
const float *v = (float*)value, *ev = entry->value.float3_;
return v[0]==ev[0] && v[1]==ev[1] && v[2]==ev[2];
} else {
return (entry->value.int_ == *(int *) value);
}
}
static void SettingUniqueEntry_Set(SettingUniqueEntry *entry, int value_type, const void *value){
int setting_type = SettingGetType(entry->setting_id);
switch (value_type) {
case cSetting_boolean:
case cSetting_int:
case cSetting_color:
if (setting_type == cSetting_float) {
entry->value.float_ = *(int*) value;
} else {
entry->value.int_ = *(int *) value;
}
break;
case cSetting_float:
if (setting_type != cSetting_float) {
entry->value.int_ = *(float *) value;
} else {
entry->value.float_ = *(float *) value;
}
break;
case cSetting_float3:
memcpy(entry->value.float3_, *(const float **) value, sizeof(float) * 3);
break;
default:
printf("SettingUniqueEntry_Set-Error: unsupported type %d\n", value_type);
}
}
/*
* Return false if setting was not set (nothing changed)
*/
bool SettingUniqueUnset(PyMOLGlobals * G, int unique_id, int setting_id)
{
auto I = G->SettingUnique;
auto result = OVOneToOne_GetForward(I->id2offset, unique_id);
if (OVreturn_IS_OK(result)) {
for (int prev = 0, offset = result.word; offset;
prev = offset, offset = I->entry[offset].next) {
if (I->entry[offset].setting_id != setting_id)
continue;
if(!prev) { /* if first entry in list */
OVOneToOne_DelForward(I->id2offset, unique_id);
if(I->entry[offset].next) { /* set new list start */
OVOneToOne_Set(I->id2offset, unique_id, I->entry[offset].next);
}
} else { /* otherwise excise from middle or end */
I->entry[prev].next = I->entry[offset].next;
}
I->entry[offset].next = I->next_free;
I->next_free = offset;
return true;
}
}
return false;
}
int SettingUniqueSetTypedValue(PyMOLGlobals * G, int unique_id, int setting_id,
int setting_type, const void *value)
/* set value to NULL in order to delete setting */
{
CSettingUnique *I = G->SettingUnique;
OVreturn_word result;
int isset = false;
if (!value) {
return SettingUniqueUnset(G, unique_id, setting_id);
}
if(OVreturn_IS_OK((result = OVOneToOne_GetForward(I->id2offset, unique_id)))) { /* setting list exists for atom */
int offset = result.word;
int prev = 0;
int found = false;
while(offset) {
SettingUniqueEntry *entry = I->entry + offset;
if(entry->setting_id == setting_id) {
found = true; /* this setting is already defined */
if (!SettingUniqueEntry_IsSame(entry, setting_type, value)){
SettingUniqueEntry_Set(entry, setting_type, value);
isset = true;
}
break;
}
prev = offset;
offset = entry->next;
}
if((!found) && value) { /* setting not found in existing list, so append new value */
if(!I->next_free)
SettingUniqueExpand(G);
if(I->next_free) {
offset = I->next_free;
{
SettingUniqueEntry *entry = I->entry + offset;
I->next_free = entry->next;
entry->next = 0;
if(prev) { /* append onto existing list */
I->entry[prev].next = offset;
entry->setting_id = setting_id;
SettingUniqueEntry_Set(entry, setting_type, value);
isset = true;
} else if(OVreturn_IS_OK(OVOneToOne_Set(I->id2offset, unique_id, offset))) {
/* create new list */
entry->setting_id = setting_id;
SettingUniqueEntry_Set(entry, setting_type, value);
isset = true;
}
}
}
}
} else if(value && (result.status == OVstatus_NOT_FOUND)) { /* new setting list for atom */
if(!I->next_free)
SettingUniqueExpand(G);
if(I->next_free) {
int offset = I->next_free;
SettingUniqueEntry *entry = I->entry + offset;
if(OVreturn_IS_OK(OVOneToOne_Set(I->id2offset, unique_id, offset))) {
I->next_free = entry->next;
entry->setting_id = setting_id;
entry->next = 0;
SettingUniqueEntry_Set(entry, setting_type, value);
isset = true;
}
}
} else {
/* unhandled error */
}
return isset;
}
#ifndef _PYMOL_NOPY
bool SettingUniqueSetPyObject(PyMOLGlobals * G, int unique_id, int index, PyObject *value)
{
if (!value)
return SettingUniqueUnset(G, unique_id, index);
int type = SettingGetType(G, index);
float val_3f[3];
union {
int val_i;
float val_f;
float * ptr_3f;
};
switch (type) {
case cSetting_boolean:
case cSetting_int:
ok_assert(1, PConvPyObjectToInt(value, &val_i));
break;
case cSetting_float:
ok_assert(1, PConvPyObjectToFloat(value, &val_f));
break;
case cSetting_color:
if (!PConvPyIntToInt(value, &val_i)) {
OrthoLineType sval;
ok_assert(1, PConvPyStrToStr(value, sval, OrthoLineLength));
val_i = ColorGetIndex(G, sval);
}
break;
case cSetting_float3:
if (!PConvPyListOrTupleToFloatArrayInPlace(value, val_3f, 3)) {
OrthoLineType sval;
ok_assert(1, PConvPyStrToStr(value, sval, OrthoLineLength) &&
sscanf(sval, "%f%f%f", &val_3f[0], &val_3f[1], &val_3f[2]) == 3);
}
ptr_3f = val_3f;
break;
default:
PRINTFB(G, FB_Python, FB_Errors)
" Python-Error: atom-state-level setting unsupported type=%d\n", type ENDFB(G);
return false;
}
return SettingUniqueSetTypedValue(G, unique_id, index, type, &val_i);
ok_except1:
PRINTFB(G, FB_Setting, FB_Errors)
" Setting-Error: type mismatch\n" ENDFB(G);
return false;
}
#endif
void SettingUniqueResetAll(PyMOLGlobals * G)
{
CSettingUnique *I = G->SettingUnique;
OVOneToOne_Reset(I->id2offset);
{
int a;
I->n_alloc = 10;
VLAFreeP(I->entry);
I->entry = VLACalloc(SettingUniqueEntry, I->n_alloc);
/* note: intentially skip index 0 */
for(a = 2; a < 10; a++) {
I->entry[a].next = a - 1;
}
I->next_free = I->n_alloc - 1;
}
}
int SettingUniquePrintAll(PyMOLGlobals * G, int src_unique_id)
{
int ok = true;
CSettingUnique *I = G->SettingUnique;
OVreturn_word src_result;
printf("SettingUniquePrintAll: ");
if(OVreturn_IS_OK(src_result = OVOneToOne_GetForward(I->id2offset, src_unique_id))) {
int src_offset = src_result.word;
SettingUniqueEntry *src_entry;
while(ok && src_offset) {
{
src_entry = I->entry + src_offset;
{
int setting_id = src_entry->setting_id;
int setting_type = SettingInfo[setting_id].type;
const char * setting_name = SettingInfo[setting_id].name;
switch (setting_type) {
case cSetting_int:
case cSetting_color:
case cSetting_boolean:
printf("%s:%d:%d:%d ", setting_name, setting_id, setting_type, src_entry->value.int_);
break;
case cSetting_float:
printf("%s:%d:%d:%f ", setting_name, setting_id, setting_type, src_entry->value.float_);
break;
case cSetting_float3:
printf("%s:%d:%d:%f,%f,%f ", setting_name, setting_id, setting_type, src_entry->value.float3_[0],
src_entry->value.float3_[1],
src_entry->value.float3_[2]);
break;
case cSetting_string:
printf("%s:%d:%d:s%d ", setting_name, setting_id, setting_type, src_entry->value.int_);
break;
}
}
}
src_offset = I->entry[src_offset].next; /* src_entry invalid, since I->entry may have changed */
}
}
printf("\n");
return ok;
}
int SettingUniqueCopyAll(PyMOLGlobals * G, int src_unique_id, int dst_unique_id)
{
int ok = true;
CSettingUnique *I = G->SettingUnique;
OVreturn_word dst_result;
if(OVreturn_IS_OK((dst_result = OVOneToOne_GetForward(I->id2offset, dst_unique_id)))) { /* setting list exists for atom */
PRINTFB(G, FB_Setting, FB_Errors)
" SettingUniqueCopyAll-Bug: merging settings not implemented\n"
ENDFB(G);
ok = false;
} else if(dst_result.status == OVstatus_NOT_FOUND) { /* new setting list for atom */
OVreturn_word src_result;
if(OVreturn_IS_OK(src_result = OVOneToOne_GetForward(I->id2offset, src_unique_id))) {
int dst_offset = 0;
for (int src_offset = src_result.word; src_offset;
src_offset = I->entry[src_offset].next) {
SettingUniqueExpand(G); // this may reallocate I->entry
if (!dst_offset) {
OVOneToOne_Set(I->id2offset, dst_unique_id, I->next_free);
} else {
I->entry[dst_offset].next = I->next_free;
}
dst_offset = I->next_free;
I->next_free = I->entry[dst_offset].next;
I->entry[dst_offset] = I->entry[src_offset];
I->entry[dst_offset].next = 0;
}
}
} else {
ok = false;
/* unhandled error */
}
return ok;
}
static void SettingUniqueInit(PyMOLGlobals * G)
{
CSettingUnique *I = G->SettingUnique;
if((I = (G->SettingUnique = Calloc(CSettingUnique, 1)))) {
I->id2offset = OVOneToOne_New(G->Context->heap);
{
int a;
I->n_alloc = 10;
I->entry = VLACalloc(SettingUniqueEntry, I->n_alloc);
/* note: intentially skip index 0 */
for(a = 2; a < 10; a++) {
I->entry[a].next = a - 1; /* 1-based linked list with 0 as sentinel */
}
I->next_free = I->n_alloc - 1;
}
}
}
static void SettingUniqueFree(PyMOLGlobals * G)
{
CSettingUnique *I = G->SettingUnique;
VLAFreeP(I->entry);
OVOneToOne_Del(I->id2offset);
FreeP(I);
}
/*
* For unique_id remapping during partial session loading
*/
int SettingUniqueConvertOldSessionID(PyMOLGlobals * G, int old_unique_id)
{
CSettingUnique *I = G->SettingUnique;
int unique_id = old_unique_id;
if(I->old2new) {
OVreturn_word ret;
if(OVreturn_IS_OK(ret = OVOneToOne_GetForward(I->old2new, old_unique_id))) {
unique_id = ret.word;
} else {
unique_id = AtomInfoGetNewUniqueID(G);
OVOneToOne_Set(I->old2new, old_unique_id, unique_id);
}
} else {
AtomInfoReserveUniqueID(G, unique_id);
}
return unique_id;
}
/*
* Return true if the given setting index should not be stored to PSE.
*
* Blacklisted are unused and system-dependent settings.
*/
static bool is_session_blacklisted(int index) {
if (index >= cSetting_INIT ||
SettingInfo[index].level == cSettingLevel_unused) {
return true;
}
switch (index) {
case cSetting_antialias_shader:
case cSetting_ati_bugs:
case cSetting_cache_max:
case cSetting_cgo_shader_ub_color:
case cSetting_cgo_shader_ub_flags:
case cSetting_cgo_shader_ub_normal:
case cSetting_colored_feedback:
case cSetting_cylinder_shader_ff_workaround:
case cSetting_defer_updates:
case cSetting_fast_idle:
case cSetting_internal_feedback:
case cSetting_internal_gui:
case cSetting_internal_prompt:
case cSetting_logging:
case cSetting_max_threads:
case cSetting_mouse_grid:
case cSetting_mouse_scale:
case cSetting_nb_spheres_use_shader:
case cSetting_no_idle:
case cSetting_nvidia_bugs:
case cSetting_presentation:
case cSetting_precomputed_lighting:
case cSetting_render_as_cylinders:
case cSetting_security:
case cSetting_session_changed:
case cSetting_session_file:
case cSetting_session_migration:
case cSetting_session_version_check:
case cSetting_shaders_from_disk:
case cSetting_show_progress:
case cSetting_slow_idle:
case cSetting_stereo:
case cSetting_stereo_double_pump_mono:
case cSetting_stereo_mode:
case cSetting_suspend_deferred:
case cSetting_suspend_undo:
case cSetting_suspend_undo_atom_count:
case cSetting_suspend_updates:
case cSetting_text:
case cSetting_trilines:
case cSetting_use_geometry_shaders:
case cSetting_use_shaders:
case cSetting_pick32bit:
case cSetting_display_scale_factor:
#ifdef _PYMOL_IOS
case cSetting_cgo_sphere_quality:
case cSetting_dynamic_measures:
case cSetting_label_outline_color:
case cSetting_mouse_selection_mode:
case cSetting_sphere_mode:
case cSetting_sphere_quality:
case cSetting_stick_ball:
case cSetting_virtual_trackball:
#elif defined(_PYMOL_ACTIVEX)
case cSetting_async_builds:
#endif
return true;
}
return false;
}
int SettingUniqueFromPyList(PyMOLGlobals * G, PyObject * list, int partial_restore)
{
int ok = true;
if(!partial_restore) {
SettingUniqueResetAll(G);
}
if(list)
if(PyList_Check(list)) {
ov_size n_id = PyList_Size(list);
ov_size a;
for(a = 0; a < n_id; a++) {
PyObject *id_list = PyList_GetItem(list, a);
int unique_id;
if(ok)
ok = PyList_Check(id_list);
if(ok)
ok = (PyList_Size(id_list) > 1);
if(ok)
ok = PConvPyIntToInt(PyList_GetItem(id_list, 0), &unique_id);
if(ok && partial_restore) {
unique_id = SettingUniqueConvertOldSessionID(G, unique_id);
}
if(ok) {
ov_size n_set = 0;
PyObject *setting_list = PyList_GetItem(id_list, 1);
if(ok)
ok = PyList_Check(setting_list);
if(ok)
n_set = PyList_Size(setting_list);
if(ok) {
ov_size b;
for(b = 0; b < n_set; b++) {
PyObject *entry_list = PyList_GetItem(setting_list, b);
if(ok)
ok = PyList_Check(entry_list);
if(ok)
ok = (PyList_Size(entry_list) > 2);
if(ok) {
int setting_id;
int setting_type;
union {
int int_;
float float_;
} value_store;
if(ok)
ok = PConvPyIntToInt(PyList_GetItem(entry_list, 0), &setting_id);
if(ok)
ok = PConvPyIntToInt(PyList_GetItem(entry_list, 1), &setting_type);
if(ok)
switch (setting_type) {
case cSetting_int:
case cSetting_color:
case cSetting_boolean:
ok = PConvPyIntToInt(PyList_GetItem(entry_list, 2),
&value_store.int_);
break;
case cSetting_float:
ok = PConvPyFloatToFloat(PyList_GetItem(entry_list, 2),
&value_store.float_);
break;
}
if(ok) {
SettingUniqueSetTypedValue(G, unique_id, setting_id,
setting_type, &value_store);
}
}
}
}
}
}
}
return ok;
}
PyObject *SettingUniqueAsPyList(PyMOLGlobals * G)
{
PyObject *result = NULL;
CSettingUnique *I = G->SettingUnique;
{
ov_word hidden = 0;
OVreturn_word ret;
int n_entry = 0;
while(1) {
ret = OVOneToOne_IterateForward(I->id2offset, &hidden);
if(ret.status != OVstatus_YES)
break;
n_entry++;
}
result = PyList_New(n_entry);
if(result) {
hidden = 0;
n_entry = 0;
while(1) {
PyObject *setting_list = NULL;
int save_offset, unique_id;
ret = OVOneToOne_IterateForward(I->id2offset, &hidden);
if(ret.status != OVstatus_YES)
break;
unique_id = ret.word;
if(OVreturn_IS_OK(ret = OVOneToOne_GetForward(I->id2offset, unique_id))) {
int offset = ret.word;
int n_set = 0;
/* count number of settings for this unique_id */
SettingUniqueEntry *entry;
save_offset = offset;
while(offset) {
entry = I->entry + offset;
n_set++;
offset = entry->next;
}
/* create and insert list for each setting */
setting_list = PyList_New(n_set);
n_set = 0;
offset = save_offset;
while(offset) {
PyObject *setting_entry = PyList_New(3);
entry = I->entry + offset;
int type = SettingInfo[entry->setting_id].type;
PyList_SetItem(setting_entry, 0, PyInt_FromLong(entry->setting_id));
PyList_SetItem(setting_entry, 1, PyInt_FromLong(type));
switch (type) {
case cSetting_int:
case cSetting_color:
case cSetting_boolean:
PyList_SetItem(setting_entry, 2, PyInt_FromLong(entry->value.int_));
break;
case cSetting_float:
PyList_SetItem(setting_entry, 2,
PyFloat_FromDouble(*(float *) &entry->value.float_));
break;
case cSetting_float3:
PyList_SetItem(setting_entry, 2,
PConvFloatArrayToPyList((float *) &entry->value.float3_, 3));
break;
}
PyList_SetItem(setting_list, n_set, setting_entry);
n_set++;
offset = entry->next;
}
}
/* add this unique_id set into the overall list */
{
PyObject *unique_list = PyList_New(2);
PyList_SetItem(unique_list, 0, PyInt_FromLong(unique_id));
PyList_SetItem(unique_list, 1, setting_list);
PyList_SetItem(result, n_entry, unique_list);
}
n_entry++;
}
}
}
return (PConvAutoNone(result));
}
int SettingSetSmart_i(PyMOLGlobals * G, CSetting * set1, CSetting * set2, int index,
int value)
{
int dummy;
if(set1 && SettingGetIfDefined_i(G, set1, index, &dummy)) {
return SettingSet_i(set1, index, value);
}
if(set2 && SettingGetIfDefined_i(G, set2, index, &dummy)) {
return SettingSet_i(set2, index, value);
}
return SettingSetGlobal_i(G, index, value);
}
int SettingSetGlobalsFromPyList(PyMOLGlobals * G, PyObject * list)
{
int ok = true;
CSetting *I = G->Setting;
if(list)
if(PyList_Check(list))
ok = SettingFromPyList(I, list);
/* restore the following settings */
if(G->Option->no_quit) {
SettingSet_b(I, cSetting_presentation_auto_quit, 0);
}
ColorUpdateFrontFromSettings(G);
return (ok);
}
PyObject *SettingGetGlobalsAsPyList(PyMOLGlobals * G)
{
PyObject *result = NULL;
CSetting *I = G->Setting;
result = SettingAsPyList(I);
return (PConvAutoNone(result));
}
static PyObject *get_list(CSetting * I, int index, bool incl_blacklisted)
{
PyObject *result = NULL, *value = NULL;
int setting_type = SettingInfo[index].type;
if (!incl_blacklisted && is_session_blacklisted(index)) {
return NULL;
}
switch (setting_type) {
case cSetting_boolean:
case cSetting_int:
case cSetting_color:
value = PyInt_FromLong(I->info[index].int_);
break;
case cSetting_float:
value = PyFloat_FromDouble(I->info[index].float_);
break;
case cSetting_float3:
value = PConvFloatArrayToPyList(I->info[index].float3_, 3);
break;
case cSetting_string:
value = PyString_FromString(SettingGet<const char *>(index, I));
break;
}
if (value) {
result = PyList_New(3);
PyList_SetItem(result, 0, PyInt_FromLong(index));
PyList_SetItem(result, 1, PyInt_FromLong(setting_type));
PyList_SetItem(result, 2, value);
}
return result;
}
PyObject *SettingAsPyList(CSetting * I, bool incl_blacklisted)
{
PyObject *result = NULL;
int a;
if(I) {
std::vector<PyObject*> list;
list.reserve(cSetting_INIT);
for(a = 0; a < cSetting_INIT; a++) {
if(I->info[a].defined) {
PyObject * item = get_list(I, a, incl_blacklisted);
if (item != NULL) {
list.push_back(item);
}
}
}
result = PConvToPyObject(list);
}
return (PConvAutoNone(result));
}
/*========================================================================*/
static int SettingCheckUseShaders(CSetting * I, int quiet)
{
PyMOLGlobals * G = I->G;
if (SettingGetGlobal_i(G, cSetting_use_shaders)){
if (G->ShaderMgr->IsConfigured() && !G->ShaderMgr->ShadersPresent()){
SettingSet_b(I, cSetting_use_shaders, 0);
if (!quiet){
PRINTFB(G, FB_Setting, FB_Warnings)
"Setting-Error: use_shaders cannot be set when Shaders are not available, setting use_shaders back to false\n"
ENDFB(G);
}
return 1;
}
}
return 0;
}
/*========================================================================*/
static int set_list(CSetting * I, PyObject * list)
{
int index = -1;
int setting_type = -1;
union {
int val_i;
float val_f;
float val_3f[3];
const char * val_s;
};
if (list == NULL || CPythonVal_IsNone(list))
return true;
ok_assert(1, PyList_Check(list));
ok_assert(1, CPythonVal_PConvPyIntToInt_From_List(I->G, list, 0, &index));
ok_assert(1, CPythonVal_PConvPyIntToInt_From_List(I->G, list, 1, &setting_type));
if (is_session_blacklisted(index))
return true;
switch (setting_type) {
case cSetting_boolean:
case cSetting_int:
case cSetting_color:
ok_assert(1, CPythonVal_PConvPyIntToInt_From_List(I->G, list, 2, &val_i));
if (setting_type == cSetting_color)
val_i = ColorConvertOldSessionIndex(I->G, val_i);
SettingSet_i(I, index, val_i);
break;
case cSetting_float:
ok_assert(1, CPythonVal_PConvPyFloatToFloat_From_List(I->G, list, 2, &val_f));
SettingSet_f(I, index, val_f);
break;
case cSetting_float3:
ok_assert(1, CPythonVal_PConvPyListToFloatArrayInPlaceAutoZero_From_List(I->G, list, 2, val_3f, 3));
SettingSet_3fv(I, index, val_3f);
break;
case cSetting_string:
ok_assert(1, val_s = PyString_AsString(PyList_GetItem(list, 2)));
SettingSet_s(I, index, val_s);
break;
default:
ok_raise(1);
}
return true;
ok_except1:
printf(" set_list-Error: i=%d, t=%d\n", index, setting_type);
return false;
}
/*========================================================================*/
/*
* Used to set object and object-state level settings from PSEs
*/
CSetting *SettingNewFromPyList(PyMOLGlobals * G, PyObject * list)
{
int ok = true;
ov_size size;
ov_size a;
CSetting *I = NULL;
if(ok)
ok = (list != NULL);
if(ok)
ok = PyList_Check(list);
if(ok) {
I = SettingNew(G);
size = PyList_Size(list);
for(a = 0; a < size; a++) {
if(ok)
ok = set_list(I, PyList_GetItem(list, a));
}
}
return (I);
}
/*========================================================================*/
int SettingFromPyList(CSetting * I, PyObject * list)
{
int ok = true;
ov_size size;
ov_size a;
if(ok)
ok = (I != NULL);
if(ok)
ok = PyList_Check(list);
if(ok) {
size = PyList_Size(list);
for(a = 0; a < size; a++) {
if(!set_list(I, PyList_GetItem(list, a)))
ok = false;
}
}
return (ok);
}
/*========================================================================*/
/*
* Get the indices of all settings that have changed since last calling
* this function. Resets the "changed" flag.
*
* NOTE: assumes blocked interpreter
*
* name: object name or NULL/"" for global settings
* state: object state
*/
std::vector<int> SettingGetUpdateList(PyMOLGlobals * G, const char * name, int state)
{
CSetting **handle, *I = G->Setting;
int a;
int n;
std::vector<int> result;
if (name && name[0]) {
// object-state settings
CObject *obj = ExecutiveFindObjectByName(G, name);
if (!obj ||
!(handle = obj->fGetSettingHandle(obj, state)) ||
!(I = *handle))
// not found -> empty list
return result;
}
n = VLAGetSize(I->info);
for(a = 0; a < n; a++) {
if(I->info[a].changed) {
I->info[a].changed = false;
result.push_back(a);
}
}
return (result);
}
/*========================================================================*/
void SettingCheckHandle(PyMOLGlobals * G, CSetting ** handle)
{
if(!*handle)
*handle = SettingNew(G);
}
/*========================================================================*/
int SettingGetTextValue(PyMOLGlobals * G, const CSetting * set1, const CSetting * set2, int index,
char *buffer)
{
const char * sptr = SettingGetTextPtr(G, set1, set2, index, buffer);
if(!sptr)
return 0;
if (sptr != buffer) {
if(strlen(sptr) > OrthoLineLength) {
PRINTFB(G, FB_Setting, FB_Warnings)
"Setting-Warning: text longer than OrthoLineLength" ENDFB(G);
}
strncpy(buffer, sptr, OrthoLineLength);
}
return 1;
}
/*========================================================================*/
/*
* Returns a pointer to the internal string representation if available,
* or it formats the value into buffer and returns a pointer to buffer.
*/
const char * SettingGetTextPtr(PyMOLGlobals * G, const CSetting * set1, const CSetting * set2,
int index, char *buffer)
{
int type;
const char *sptr = NULL;
const float *ptr;
type = SettingGetType(G, index);
switch (type) {
case cSetting_boolean:
sprintf(buffer, SettingGet_b(G, set1, set2, index) ? "on" : "off");
break;
case cSetting_int:
sprintf(buffer, "%d", SettingGet_i(G, set1, set2, index));
break;
case cSetting_float:
sprintf(buffer, "%1.5f", SettingGet_f(G, set1, set2, index));
break;
case cSetting_float3:
ptr = SettingGet_3fv(G, set1, set2, index);
sprintf(buffer, "[ %1.5f, %1.5f, %1.5f ]", ptr[0], ptr[1], ptr[2]);
break;
case cSetting_color:
{
int color = SettingGet_color(G, set1, set2, index);
switch (color) {
case cColorAtomic:
strcpy(buffer, "atomic");
break;
case cColorObject:
strcpy(buffer, "object");
break;
case cColorFront:
strcpy(buffer, "front");
break;
case cColorBack:
strcpy(buffer, "back");
break;
case -1:
strcpy(buffer, "default");
break;
default:
sptr = ColorGetName(G, color);
if(sptr)
return sptr;
strcpy(buffer, "invalid");
}
}
break;
case cSetting_string:
return SettingGet_s(G, set1, set2, index);
default:
return NULL;
}
return buffer;
}
#ifndef _PYMOL_NOPY
/*========================================================================*/
int SettingSetFromTuple(PyMOLGlobals * G, CSetting * I, int index, PyObject * tuple)
/* must have interpret locked to make this call */
{
PyObject *value;
int type;
int ok = true;
if(!I)
I = G->Setting; /* fall back on global settings */
/* this data structure has been pre-checked at the python level... */
type = PyInt_AsLong(PyTuple_GetItem(tuple, 0));
value = PyTuple_GetItem(tuple, 1);
switch (type) {
case cSetting_boolean:
case cSetting_int:
SettingSet_i(I, index, PyInt_AsLong(value));
break;
case cSetting_float:
SettingSet_f(I, index, (float) PyFloat_AsDouble(value));
break;
case cSetting_float3:
float tmp[3];
PyArg_ParseTuple(value, "fff", tmp, tmp + 1, tmp + 2);
SettingSet_3fv(I, index, tmp);
break;
case cSetting_color:
SettingSet_color(I, index, PyString_AsString(value));
break;
case cSetting_string:
SettingSet_s(I, index, PyString_AsString(value));
break;
default:
ok = false;
break;
}
return (ok);
}
#endif
/*========================================================================*/
int SettingStringToTypedValue(PyMOLGlobals * G, int index, const char *st, int *type,
int *value)
{
int ok = true;
int newvalue ;
float newfvalue;
/* this data structure has been pre-checked at the python level... */
*type = SettingGetType(G, index);
switch (*type) {
case cSetting_boolean:
if((!*st) || (*st == '0') || (*st == 'F') || WordMatchExact(G, st, "on", true)
|| WordMatchExact(G, st, "false", true)){
newvalue = 0;
} else {
newvalue = 1;
}
if (newvalue != *value){
*value = newvalue;
} else {
ok = false;
}
break;
case cSetting_int:
if(sscanf(st, "%d", &newvalue) != 1){
ok = false;
} else if (newvalue!=*value){
*value = newvalue;
} else {
ok = false;
}
break;
case cSetting_float:
if(sscanf(st, "%f", &newfvalue) != 1){
ok = false;
} else if (newfvalue != *((float *) value)){
*(float*)value = newfvalue;
} else {
ok = false;
}
break;
case cSetting_color:
{
int color_index = ColorGetIndex(G, st);
if (*(value) != color_index){
*(value) = color_index;
} else {
ok = false;
}
}
break;
default:
ok = false;
break;
}
return (ok);
}
int SettingSetFromString(PyMOLGlobals * G, CSetting * I, int index, const char *st)
{
int type;
int ok = true;
if(!I)
I = G->Setting; /* fall back on global settings */
/* this data structure has been pre-checked at the python level... */
type = SettingGetType(G, index);
switch (type) {
case cSetting_boolean:
if((!*st) || (*st == '0') || (*st == 'F') || WordMatchExact(G, st, "on", true)
|| WordMatchExact(G, st, "false", true))
SettingSet_b(I, index, 0);
else
SettingSet_b(I, index, 1);
break;
case cSetting_int:
{
int tmp;
if(sscanf(st, "%d", &tmp) == 1)
SettingSet_i(I, index, tmp);
else
ok = false;
}
break;
case cSetting_float:
{
float tmp;
if(sscanf(st, "%f", &tmp) == 1)
SettingSet_f(I, index, tmp);
else
ok = false;
}
break;
case cSetting_float3:
{
float tmp[3];
if(sscanf(st, "%f%f%f", tmp, tmp + 1, tmp + 2) == 3)
SettingSet_3fv(I, index, tmp);
else
ok = false;
}
break;
case cSetting_color:
SettingSet_color(I, index, st);
break;
case cSetting_string:
SettingSet_s(I, index, st);
break;
default:
ok = false;
break;
}
return (ok);
}
/*========================================================================*/
#ifndef _PYMOL_NOPY
/*
* Warning: Returns colors as (fff) tuple instead of color index
*/
PyObject *SettingGetPyObject(PyMOLGlobals * G, const CSetting * set1, const CSetting * set2, int index)
{ /* assumes blocked python interpeter */
PyObject *result = NULL;
const float *ptr;
int type = SettingGetType(G, index);
switch (type) {
case cSetting_boolean:
result = CPythonVal_New_Boolean(SettingGet_b(G, set1, set2, index));
break;
case cSetting_int:
result = CPythonVal_New_Integer(SettingGet_i(G, set1, set2, index));
break;
case cSetting_float:
result = CPythonVal_New_Float(SettingGet_f(G, set1, set2, index));
break;
case cSetting_float3:
ptr = SettingGet_3fv(G, set1, set2, index);
result = Py_BuildValue("(fff)", ptr[0], ptr[1], ptr[2]);
break;
case cSetting_color:
{
int retcol = SettingGet_color(G, set1, set2, index);
if (retcol > 0){
const float *col;
col = ColorGet(G, retcol);
result = Py_BuildValue("(fff)", col[0], col[1], col[2]);
}
}
break;
case cSetting_string:
result = PyString_FromString(SettingGet_s(G, set1, set2, index));
break;
}
return result;
}
PyObject *SettingGetTuple(PyMOLGlobals * G, const CSetting * set1, const CSetting * set2, int index)
{ /* assumes blocked python interpeter */
PyObject *result = NULL;
const float *ptr;
int type = SettingGetType(G, index);
switch (type) {
case cSetting_boolean:
case cSetting_int:
case cSetting_color:
result = Py_BuildValue("ii", type, SettingGet_i(G, set1, set2, index));
break;
case cSetting_float:
result = Py_BuildValue("if", type, SettingGet_f(G, set1, set2, index));
break;
case cSetting_float3:
ptr = SettingGet_3fv(G, set1, set2, index);
result = Py_BuildValue("i(fff)", type, ptr[0], ptr[1], ptr[2]);
break;
case cSetting_string:
result = Py_BuildValue("is", type, SettingGet_s(G, set1, set2, index));
break;
default:
result = PConvAutoNone(Py_None);
break;
}
return result;
}
#endif
/*========================================================================*/
CSetting *SettingNew(PyMOLGlobals * G)
{
OOAlloc(G, CSetting);
SettingInit(G, I);
return (I);
}
/*========================================================================*/
void SettingPurge(CSetting * I)
{
if(I) {
// need to free strings
for(int index = 0; index < cSetting_INIT; ++index) {
if (SettingInfo[index].type == cSetting_string) {
I->info[index].delete_s();
}
}
VLAFreeP(I->info);
I->size = 0;
}
}
/*========================================================================*/
void SettingFreeP(CSetting * I)
{
if(I)
SettingPurge(I);
OOFreeP(I);
}
/*========================================================================*/
void SettingInit(PyMOLGlobals * G, CSetting * I)
{
I->G = G;
I->size = sizeof(int); /* insures offset is never zero, except when undef */
I->info = (SettingRec*) VLAMalloc(cSetting_INIT, sizeof(SettingRec), 5, 1); /* auto-zero */
}
/*========================================================================*/
/*
* Return false if type is numeric and default value is non-zero.
*/
bool SettingIsDefaultZero(int index)
{
switch (SettingInfo[index].type) {
case cSetting_boolean:
case cSetting_int:
case cSetting_float:
if (SettingInfo[index].value.i[0] == 0)
return true;
return false;
}
return true;
}
/*========================================================================*/
/*
* Restore the default value from `src` or `SettingInfo`
*/
void SettingRestoreDefault(CSetting * I, int index, const CSetting * src)
{
// 1) from stored default if provided
if (src) {
UtilCopyMem(I->info + index, src->info + index, sizeof(SettingRec));
// need to properly copy strings
if (SettingInfo[index].type == cSetting_string && src->info[index].str_) {
I->info[index].str_ = new std::string(*src->info[index].str_);
}
return;
}
// 2) from SettingInfo
auto &rec = SettingInfo[index];
switch (rec.type) {
case cSetting_blank:
break;
case cSetting_boolean:
case cSetting_int:
I->info[index].set_i(rec.value.i[0]);
break;
case cSetting_float:
I->info[index].set_f(rec.value.f[0]);
break;
case cSetting_float3:
I->info[index].set_3f(rec.value.f);
break;
case cSetting_string:
I->info[index].delete_s();
break;
case cSetting_color:
SettingSet_color(I, index, rec.value.s);
break;
default:
// coding error
printf(" ERROR: unkown type\n");
};
I->info[index].defined = false;
}
/*========================================================================*/
int SettingUnset(CSetting * I, int index)
{
if(I) {
SettingRec *sr = I->info + index;
if (!sr->defined) {
return false;
}
sr->defined = false;
sr->changed = true;
}
return true;
}
/*========================================================================*/
int SettingGetType(int index)
{
return (SettingInfo[index].type);
}
/*========================================================================*/
template <>
int SettingGet<int>(int index, const CSetting * I)
{
PyMOLGlobals *G = I->G;
int result;
switch (SettingInfo[index].type) {
case cSetting_boolean:
case cSetting_int:
case cSetting_color:
result = I->info[index].int_;
break;
case cSetting_float:
result = (int) I->info[index].float_;
break;
default:
PRINTFB(G, FB_Setting, FB_Errors)
"Setting-Error: type read mismatch (int) %d\n", index ENDFB(G);
result = 0;
break;
}
return (result);
}
/*========================================================================*/
template <>
bool SettingGet<bool>(int index, const CSetting * I)
{
PyMOLGlobals *G = I->G;
switch (SettingInfo[index].type) {
case cSetting_boolean:
case cSetting_int:
case cSetting_float:
return I->info[index].int_ != 0;
default:
PRINTFB(G, FB_Setting, FB_Errors)
"Setting-Error: type read mismatch (boolean) %d\n", index ENDFB(G);
return false;
}
}
/*========================================================================*/
template <>
float SettingGet<float>(int index, const CSetting * I)
{
float result;
PyMOLGlobals *G = I->G;
switch (SettingInfo[index].type) {
case cSetting_color:
PRINTFB(G, FB_Setting, FB_Warnings)
" Setting-Warning: type read mismatch (float/color) %d\n", index ENDFB(G);
case cSetting_boolean:
case cSetting_int:
result = (float) I->info[index].int_;
break;
case cSetting_float:
result = I->info[index].float_;
break;
default:
PRINTFB(G, FB_Setting, FB_Errors)
"Setting-Error: type read mismatch (float) %d\n", index ENDFB(G);
result = 0.0F;
}
return (result);
}
/*========================================================================*/
template <>
const char * SettingGet<const char *>(int index, const CSetting * I)
{
const char *result;
PyMOLGlobals *G = I->G;
switch (SettingInfo[index].type) {
case cSetting_string:
if(I->info[index].str_) {
result = I->info[index].str_->c_str();
} else {
result = SettingInfo[index].value.s;
}
break;
default:
PRINTFB(G, FB_Setting, FB_Errors)
"Setting-Error: type read mismatch (string) %d\n", index ENDFB(G);
result = NULL;
}
return (char*) result;
}
/*========================================================================*/
template <>
const float * SettingGet<const float *>(int index, const CSetting * I)
{
if (SettingInfo[index].type != cSetting_float3) {
PyMOLGlobals *G = I->G;
PRINTFB(G, FB_Setting, FB_Errors)
" Setting-Error: type read mismatch (float3) %d\n", index ENDFB(G);
return NULL;
}
return I->info[index].float3_;
}
/*========================================================================*/
int SettingSet_i(CSetting * I, int index, int value)
{
int ok = true;
if(I) {
PyMOLGlobals *G = I->G;
{
int setting_type = SettingInfo[index].type;
switch (setting_type) {
case cSetting_boolean:
case cSetting_int:
case cSetting_color:
I->info[index].set_i(value);
break;
case cSetting_float:
I->info[index].set_f((float) value);
break;
default:
PRINTFB(G, FB_Setting, FB_Errors)
"Setting-Error: type set mismatch (integer) %d\n", index ENDFB(G);
ok = false;
}
}
} else {
ok = false;
}
return (ok);
}
/*========================================================================*/
static int SettingSet_color_from_3f(CSetting * I, int index, const float * vector)
{
int color_index;
float vals[3];
copy3f(vector, vals);
clamp3f(vals);
color_index = Color3fToInt(I->G, vals);
return SettingSet_i(I, index, color_index);
}
int SettingSet_color(CSetting * I, int index, const char *value)
{
int ok = true;
int color_index;
if(I) {
PyMOLGlobals *G = I->G;
color_index = ColorGetIndex(G, value);
if((color_index == -1) && (strcmp(value, "-1") &&
strcmp(value, "-2") &&
strcmp(value, "-3") &&
strcmp(value, "-4") &&
strcmp(value, "-5") && strcmp(value, "default"))) {
float vals[3];
ok = ParseFloat3List(value, vals);
if (ok){
clamp3f(vals);
color_index = cColor_TRGB_Bits |
((int) (255 * vals[0] + 0.49999F)) << 16 |
((int) (255 * vals[1] + 0.49999F)) << 8 |
((int) (255 * vals[2] + 0.49999F));
} else {
PRINTFB(G, FB_Setting, FB_Errors)
"Setting-Error: unknown color '%s'\n", value ENDFB(G);
}
}
if (ok){
SettingSet_i(I, index, color_index);
}
}
return (ok);
}
/*========================================================================*/
int SettingSet_f(CSetting * I, int index, float value)
{
int ok = true;
if(I) {
PyMOLGlobals *G = I->G;
{
int setting_type = SettingInfo[index].type;
switch (setting_type) {
case cSetting_boolean:
case cSetting_int:
case cSetting_color:
I->info[index].set_i((int) value);
break;
case cSetting_float:
I->info[index].set_f(value);
break;
default:
PRINTFB(G, FB_Setting, FB_Errors)
"Setting-Error: type set mismatch (float) %d\n", index ENDFB(G);
ok = false;
}
}
} else {
ok = false;
}
return (ok);
}
/*========================================================================*/
int SettingSet_s(CSetting * I, int index, const char *value)
{
int ok = true;
if(I) {
PyMOLGlobals *G = I->G;
{
int setting_type = SettingInfo[index].type;
switch (setting_type) {
case cSetting_string:
I->info[index].set_s(value);
break;
case cSetting_color:
return SettingSet_color(I, index, value);
default:
PRINTFB(G, FB_Setting, FB_Errors)
"Setting-Error: type set mismatch (string) %d\n", index ENDFB(G);
ok = false;
}
}
} else {
ok = false;
}
return (ok);
}
/*========================================================================*/
int SettingSet_3fv(CSetting * I, int index, const float *vector)
{
switch (SettingInfo[index].type) {
case cSetting_float3:
I->info[index].set_3f(vector);
return true;
case cSetting_color:
return SettingSet_color_from_3f(I, index, vector);
default:
PyMOLGlobals *G = I->G;
PRINTFB(G, FB_Setting, FB_Errors)
"Setting-Error: type set mismatch (float3) %d\n", index ENDFB(G);
return false;
}
}
/*========================================================================*/
int SettingGetIndex(PyMOLGlobals * G, const char *name)
{
OVreturn_word result = get_setting_id(G->PyMOL, name);
if (OVreturn_IS_OK(result))
return result.word;
return -1;
}
/*========================================================================*/
int SettingGetName(PyMOLGlobals * G, int index, SettingName name)
{
UtilNCopy(name, SettingInfo[index].name, sizeof(SettingName));
return (name[0] != 0);
}
/*========================================================================*/
const char * SettingGetName(int index)
{
return SettingInfo[index].name;
}
/*========================================================================*/
void SettingGenerateSideEffects(PyMOLGlobals * G, int index, const char *sele, int state, int quiet)
{
const char *inv_sele = (sele && sele[0]) ? sele : cKeywordAll;
auto &rec = SettingInfo[index];
if (rec.level == cSettingLevel_unused) {
const char * name = rec.name;
if (!quiet && name && name[0]){
PRINTFB(G, FB_Setting, FB_Warnings)
" Setting-Warning: '%s' is no longer used\n", name
ENDFB(G);
}
return;
}
// range check for int (global only)
if (rec.type == cSetting_int && rec.hasMinMax() && !(sele && sele[0])) {
int value = SettingGetGlobal_i(G, index);
bool clamped = true;
if (value < rec.value.i[1]) {
value = rec.value.i[1];
} else if (value > rec.value.i[2]) {
value = rec.value.i[2];
} else {
clamped = false;
}
if (clamped) {
PRINTFB(G, FB_Setting, FB_Warnings)
" Setting-Warning: %s range = [%d,%d]; setting to %d.\n",
rec.name, rec.value.i[1], rec.value.i[2], value ENDFB(G);
SettingSetGlobal_i(G, index, value);
}
}
switch (index) {
case cSetting_stereo:
SceneUpdateStereo(G);
G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
break;
case cSetting_pick_surface:
if (SettingGetGlobal_b(G, cSetting_use_shaders)){
SceneInvalidatePicking(G); // right now, when pick_surface is off, wipes each CGO's pickColor array
}
ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvColor);
break;
case cSetting_pickable:
ExecutiveInvalidateRep(G, inv_sele, cRepAll, cRepInvAll);
SceneChanged(G);
break;
case cSetting_grid_mode:
if (!SettingGetGlobal_i(G, cSetting_grid_mode))
G->ShaderMgr->ResetUniformSet();
case cSetting_grid_slot:
ExecutiveInvalidateGroups(G, false);
SceneChanged(G);
break;
case cSetting_grid_max:
SceneChanged(G);
break;
case cSetting_defer_builds_mode:
ExecutiveRebuildAll(G);
break;
case cSetting_seq_view:
case cSetting_seq_view_label_spacing:
case cSetting_seq_view_label_mode:
case cSetting_seq_view_label_start:
case cSetting_seq_view_format:
case cSetting_seq_view_color:
case cSetting_seq_view_unaligned_mode:
case cSetting_seq_view_gap_mode:
SeqChanged(G);
break;
case cSetting_seq_view_fill_color:
case cSetting_seq_view_fill_char:
case cSetting_seq_view_label_color:
OrthoDirty(G);
break;
case cSetting_show_frame_rate:
OrthoDirty(G);
break;
case cSetting_group_full_member_names:
case cSetting_group_arrow_prefix:
OrthoDirty(G);
break;
case cSetting_static_singletons:
SeqChanged(G);
break;
case cSetting_seq_view_location:
PParse(G, "cmd.viewport(-1,-1)");
SeqChanged(G);
break;
case cSetting_seq_view_overlay:
PParse(G, "cmd.viewport(-1,-1)");
break;
case cSetting_stereo_mode:
case cSetting_anaglyph_mode:
G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
SceneUpdateStereoMode(G);
OrthoInvalidateDoDraw(G);
OrthoDirty(G);
PyMOL_NeedRedisplay(G->PyMOL);
break;
case cSetting_precomputed_lighting:
G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
case cSetting_light_count:
case cSetting_spec_count:
G->ShaderMgr->Set_Reload_Bits(RELOAD_CALLCOMPUTELIGHTING);
case cSetting_dot_lighting:
case cSetting_mesh_lighting:
case cSetting_cgo_lighting:
case cSetting_field_of_view:
case cSetting_fog_start:
case cSetting_two_sided_lighting:
case cSetting_transparency_global_sort:
case cSetting_dot_normals:
case cSetting_mesh_normals:
SceneInvalidate(G);
break;
case cSetting_spec_power:
if (!quiet){
PRINTFB(G, FB_Setting, FB_Debugging)
"Setting-Details: spec_power is depreciated in PyMOL 1.5. This option will not work in future versions. Please set shininess to set the specular exponent for movable light sources.\n"
ENDFB(G);
}
SceneInvalidate(G);
break;
case cSetting_light:
case cSetting_light2:
case cSetting_light3:
case cSetting_light4:
case cSetting_light5:
case cSetting_light6:
case cSetting_light7:
case cSetting_reflect:
case cSetting_direct:
case cSetting_ambient:
case cSetting_specular:
case cSetting_specular_intensity:
case cSetting_shininess:
case cSetting_spec_reflect:
case cSetting_spec_direct:
case cSetting_spec_direct_power:
case cSetting_power:
case cSetting_reflect_power:
if (SettingGetGlobal_b(G, cSetting_precomputed_lighting))
G->ShaderMgr->Set_Reload_Bits(RELOAD_CALLCOMPUTELIGHTING);
SceneInvalidate(G);
break;
case cSetting_use_display_lists:
case cSetting_simplify_display_lists:
case cSetting_excl_display_lists_shaders:
if (!quiet){
PRINTFB(G, FB_Setting, FB_Debugging)
"Setting-Details: display lists were depreciated in PyMOL 1.7.x. The settings use_display_lists, simplify_display_lists, and excl_display_lists_shaders no longer work.\n"
ENDFB(G);
}
case cSetting_use_geometry_shaders:
if (SettingGetGlobal_i(G, cSetting_use_geometry_shaders) &&
G->ShaderMgr->IsConfigured() && !G->ShaderMgr->GeometryShadersPresent()) {
SettingSet_b(G->Setting, cSetting_use_geometry_shaders, 0);
if (!quiet){
PRINTFB(G, FB_Setting, FB_Warnings)
"Setting-Error: geometry shaders not available\n" ENDFB(G);
}
return;
}
G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
ExecutiveInvalidateRep(G, inv_sele, cRepLabel, cRepInvRep);
{
// check if lines need to be invalidated
bool line_as_cylinders = SettingGetGlobal_b(G, cSetting_use_shaders) &&
SettingGetGlobal_b(G, cSetting_render_as_cylinders) &&
SettingGetGlobal_b(G, cSetting_line_as_cylinders);
if (!line_as_cylinders && !SettingGetGlobal_b(G, cSetting_trilines)){
ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
}
}
break;
case cSetting_shaders_from_disk:
G->ShaderMgr->Set_Reload_Bits(RELOAD_ALL_SHADERS);
SceneInvalidate(G);
break;
case cSetting_use_shaders:
{
short changed = 0;
if (SettingGetGlobal_b(G, cSetting_use_shaders)){
if (SettingCheckUseShaders(G->Setting, quiet)){
return;
}
}
SceneInvalidate(G);
if (SettingGetGlobal_b(G, cSetting_sphere_use_shader)){
ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
changed = 1;
}
if (SettingGetGlobal_b(G, cSetting_ribbon_use_shader)){
ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
changed = 1;
}
if (SettingGetGlobal_b(G, cSetting_nonbonded_use_shader)){
ExecutiveInvalidateRep(G, inv_sele, cRepNonbonded, cRepInvRep);
changed = 1;
}
if (SettingGetGlobal_i(G, cSetting_nb_spheres_use_shader)){
changed = 1;
}
if (SettingGetGlobal_b(G, cSetting_dash_use_shader)){
ExecutiveInvalidateRep(G, inv_sele, cRepAngle, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepDihedral, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepDash, cRepInvRep);
changed = 1;
}
if (SettingGetGlobal_b(G, cSetting_line_use_shader)){
ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
changed = 1;
}
if (SettingGetGlobal_b(G, cSetting_cartoon_use_shader)){
ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
changed = 1;
}
if (SettingGetGlobal_b(G, cSetting_cgo_use_shader) ||
SettingGetGlobal_b(G, cSetting_stick_as_cylinders)){
ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvRep);
changed = 1;
}
if (SettingGetGlobal_b(G, cSetting_stick_use_shader) ||
SettingGetGlobal_b(G, cSetting_stick_as_cylinders) ||
(SettingGetGlobal_b(G, cSetting_stick_ball) &&
SettingGetGlobal_b(G, cSetting_valence))){
ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
changed = 1;
}
if (SettingGetGlobal_b(G, cSetting_surface_use_shader) ||
SettingGetGlobal_b(G, cSetting_dot_use_shader) ||
SettingGetGlobal_b(G, cSetting_mesh_use_shader)){
changed = 1;
}
if (changed){
SceneChanged(G);
}
}
break;
case cSetting_stereo_shift:
case cSetting_stereo_angle:
case cSetting_stereo_dynamic_strength:
SceneInvalidate(G);
break;
case cSetting_scene_buttons:
case cSetting_scene_buttons_mode:
SceneInvalidate(G);
OrthoInvalidateDoDraw(G);
break;
case cSetting_dash_round_ends:
case cSetting_dash_color:
if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_dash_use_shader)){
ExecutiveInvalidateRep(G, "all", cRepDash, cRepInvRep);
}
SceneInvalidate(G);
break;
case cSetting_angle_color:
if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_dash_use_shader)){
ExecutiveInvalidateRep(G, "all", cRepAngle, cRepInvRep);
}
SceneInvalidate(G);
break;
case cSetting_dihedral_color:
if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_dash_use_shader)){
ExecutiveInvalidateRep(G, "all", cRepDihedral, cRepInvRep);
}
SceneInvalidate(G);
break;
case cSetting_mouse_selection_mode:
OrthoDirty(G);
break;
case cSetting_internal_gui_control_size:
WizardRefresh(G);
OrthoDirty(G);
break;
case cSetting_hide_underscore_names:
ExecutiveInvalidateGroups(G, false);
OrthoDirty(G);
break;
case cSetting_gradient_spacing:
case cSetting_gradient_max_length:
case cSetting_gradient_min_length:
case cSetting_gradient_normal_min_dot:
case cSetting_gradient_step_size:
case cSetting_gradient_min_slope:
case cSetting_gradient_symmetry:
ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvRep);
SceneChanged(G);
break;
case cSetting_min_mesh_spacing:
case cSetting_mesh_grid_max:
case cSetting_mesh_cutoff:
case cSetting_mesh_carve_state:
case cSetting_mesh_carve_cutoff:
case cSetting_mesh_carve_selection:
case cSetting_mesh_clear_state:
case cSetting_mesh_clear_cutoff:
case cSetting_mesh_clear_selection:
case cSetting_mesh_mode:
case cSetting_mesh_type:
case cSetting_mesh_solvent:
case cSetting_mesh_quality:
case cSetting_mesh_skip:
ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvRep);
SceneChanged(G);
break;
case cSetting_valence:
case cSetting_valence_mode:
case cSetting_valence_size:
case cSetting_valence_zero_mode:
case cSetting_valence_zero_scale:
case cSetting_half_bonds:
case cSetting_line_stick_helper:
case cSetting_hide_long_bonds:
ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
SceneChanged(G);
break;
case cSetting_stick_transparency:
case cSetting_stick_debug:
case cSetting_stick_round_nub:
case cSetting_stick_as_cylinders:
case cSetting_stick_good_geometry:
ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
SceneChanged(G);
break;
case cSetting_line_use_shader:
if (SettingGetGlobal_b(G, cSetting_use_shaders)){
ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
SceneChanged(G);
}
break;
case cSetting_ribbon_use_shader:
if (SettingGetGlobal_b(G, cSetting_use_shaders)){
ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
SceneChanged(G);
}
break;
case cSetting_dot_as_spheres:
SceneInvalidate(G);
SceneChanged(G);
break;
case cSetting_dot_use_shader:
if (SettingGetGlobal_b(G, cSetting_use_shaders)){
ExecutiveInvalidateRep(G, inv_sele, cRepDot, cRepInvRep);
SceneChanged(G);
}
break;
case cSetting_nonbonded_use_shader:
if (SettingGetGlobal_b(G, cSetting_use_shaders)){
ExecutiveInvalidateRep(G, inv_sele, cRepNonbonded, cRepInvRep);
SceneChanged(G);
}
break;
case cSetting_nb_spheres_size:
ExecutiveInvalidateRep(G, inv_sele, cRepNonbondedSphere, cRepInvRep);
SceneChanged(G);
break;
case cSetting_nb_spheres_use_shader:
if (SettingGetGlobal_b(G, cSetting_use_shaders)){
SceneChanged(G);
}
break;
case cSetting_render_as_cylinders:
ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
case cSetting_mesh_as_cylinders:
case cSetting_line_as_cylinders:
case cSetting_ribbon_as_cylinders:
case cSetting_dash_as_cylinders:
if (index == cSetting_dash_as_cylinders) {
ExecutiveInvalidateRep(G, inv_sele, cRepAngle, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepDihedral, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepDash, cRepInvRep);
}
case cSetting_nonbonded_as_cylinders:
case cSetting_alignment_as_cylinders:
case cSetting_cartoon_nucleic_acid_as_cylinders:
if (SettingGetGlobal_b(G, cSetting_render_as_cylinders)){
if (G->ShaderMgr->shaders_present && !G->ShaderMgr->ShaderPrgExists("cylinder")){
SettingSet_b(G->Setting, cSetting_render_as_cylinders, 0);
if (!quiet){
PRINTFB(G, FB_Setting, FB_Warnings)
"Setting-Error: render_as_cylinders cannot be set when the Cylinder Shader is not available, setting render_as_cylinder back to false\n"
ENDFB(G);
}
return;
}
switch (index){
case cSetting_render_as_cylinders:
case cSetting_cartoon_nucleic_acid_as_cylinders:
case cSetting_use_shaders:
if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_render_as_cylinders)){
ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
}
}
SceneChanged(G);
}
break;
case cSetting_mesh_use_shader:
if (SettingGetGlobal_b(G, cSetting_use_shaders)){
SceneChanged(G);
}
break;
case cSetting_slice_height_scale:
case cSetting_slice_height_map:
case cSetting_slice_grid:
case cSetting_slice_dynamic_grid:
case cSetting_slice_dynamic_grid_resolution:
ExecutiveInvalidateRep(G, inv_sele, cRepSlice, cRepInvRep);
SceneChanged(G);
break;
case cSetting_label_font_id:
case cSetting_label_size:
ExecutiveInvalidateRep(G, inv_sele, cRepLabel, cRepInvRep);
SceneChanged(G);
break;
case cSetting_retain_order:
case cSetting_pdb_hetatm_sort:
case cSetting_pdb_insertions_go_first:
ExecutiveSort(G, inv_sele);
break;
case cSetting_roving_lines:
case cSetting_roving_sticks:
case cSetting_roving_spheres:
case cSetting_roving_labels:
case cSetting_roving_selection:
case cSetting_roving_ribbon:
case cSetting_roving_cartoon:
case cSetting_roving_polar_contacts:
case cSetting_roving_polar_cutoff:
case cSetting_roving_nonbonded:
case cSetting_roving_nb_spheres:
case cSetting_roving_map1_level:
case cSetting_roving_map2_level:
case cSetting_roving_map3_level:
case cSetting_roving_map1_name:
case cSetting_roving_map2_name:
case cSetting_roving_map3_name:
case cSetting_roving_isosurface:
case cSetting_roving_isomesh:
SceneRovingChanged(G);
break;
case cSetting_roving_byres:
case cSetting_roving_detail:
SceneRovingDirty(G);
break;
case cSetting_dash_transparency:
case cSetting_dash_length:
case cSetting_dash_gap:
case cSetting_dash_radius:
case cSetting_dash_width:
case cSetting_angle_size:
case cSetting_label_digits:
case cSetting_label_distance_digits:
case cSetting_label_angle_digits:
case cSetting_label_dihedral_digits:
case cSetting_angle_label_position:
case cSetting_dihedral_size:
case cSetting_dihedral_label_position:
ExecutiveRebuildAllObjectDist(G);
SceneChanged(G);
break;
case cSetting_button_mode:
EditorMouseInvalid(G);
OrthoDirty(G);
break;
case cSetting_stick_radius:
case cSetting_stick_h_scale:
ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep); /* base width */
SceneChanged(G);
break;
case cSetting_nb_spheres_quality:
{
ExecutiveInvalidateRep(G, inv_sele, cRepNonbondedSphere, cRepInvRep);
SceneChanged(G);
}
case cSetting_cgo_sphere_quality:
case cSetting_cgo_debug:
{
ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvRep);
SceneChanged(G);
break;
}
case cSetting_stick_quality:
case cSetting_stick_ball:
case cSetting_stick_nub:
case cSetting_stick_ball_ratio:
case cSetting_stick_ball_color:
case cSetting_stick_fixed_radius:
case cSetting_stick_valence_scale:
case cSetting_stick_overlap:
case cSetting_stick_color:
case cSetting_stick_use_shader:
ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
SceneChanged(G);
break;
case cSetting_clamp_colors:
case cSetting_ramp_blend_nearby_colors:
ExecutiveInvalidateRep(G, inv_sele, cRepAll, cRepInvColor);
SceneChanged(G);
break;
case cSetting_label_color:
case cSetting_label_outline_color:
case cSetting_label_position:
ExecutiveRebuildAllObjectDist(G);
ExecutiveInvalidateRep(G, inv_sele, cRepLabel, cRepInvRep);
SceneChanged(G);
break;
case cSetting_cartoon_color:
ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
SceneChanged(G);
break;
case cSetting_ribbon_color:
ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
SceneChanged(G);
break;
case cSetting_cgo_line_width:
case cSetting_line_width:
{
GLfloat *range = G->ShaderMgr->GetLineWidthRange();
float line_width = SettingGetGlobal_f(G, index);
{
if (line_width <= 0.f){
PRINTFB(G, FB_Setting, FB_Warnings)
" Setting-Warning: %s is set incorrectly (%f), setting to 1\n",
rec.name, line_width ENDFB(G);
SettingSetGlobal_f(G, index, 1.f);
} else if (G->HaveGUI && range[1] > 0.f && line_width > range[1]) {
PRINTFB(G, FB_Setting, FB_Warnings)
" Setting-Warning: %s is out of range of the graphics card's "
"capability (range: %f-%f), lines might not be rendered correctly\n",
rec.name, range[0], range[1] ENDFB(G);
}
}
}
case cSetting_line_color:
case cSetting_line_radius:
ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepNonbonded, cRepInvRep);
SceneChanged(G);
break;
case cSetting_scenes_changed:
{
int scene_buttons = SettingGetGlobal_i(G, cSetting_scene_buttons);
if (scene_buttons)
OrthoInvalidateDoDraw(G);
}
break;
case cSetting_button_mode_name:
{
int internal_gui_mode = SettingGetGlobal_i(G, cSetting_internal_gui_mode);
if (internal_gui_mode){
OrthoInvalidateDoDraw(G);
}
}
break;
case cSetting_scene_current_name:
SceneRestartFrameTimer(G);
break;
case cSetting_mesh_width:
ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvColor);
SceneChanged(G);
break;
case cSetting_ellipsoid_probability:
case cSetting_ellipsoid_scale:
case cSetting_ellipsoid_color:
case cSetting_ellipsoid_transparency:
ExecutiveInvalidateRep(G, inv_sele, cRepEllipsoid, cRepInvRep);
SceneChanged(G);
break;
case cSetting_ellipsoid_quality:
case cSetting_cgo_ellipsoid_quality:
ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepEllipsoid, cRepInvRep);
SceneChanged(G);
break;
case cSetting_mesh_color:
case cSetting_mesh_negative_color:
ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvColor);
SceneChanged(G);
break;
case cSetting_ray_color_ramps:
ExecutiveInvalidateRep(G, inv_sele, cRepAll, cRepInvColor);
SceneChanged(G);
break;
case cSetting_sphere_mode:
ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
SceneInvalidate(G);
break;
case cSetting_cull_spheres:
case cSetting_sphere_scale:
case cSetting_sphere_transparency:
case cSetting_sphere_solvent:
case cSetting_sphere_point_max_size:
case cSetting_sphere_point_size:
case cSetting_sphere_use_shader:
ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
SceneInvalidate(G);
break;
case cSetting_sphere_quality:
ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepNonbondedSphere, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
SceneChanged(G);
break;
case cSetting_nonbonded_size:
case cSetting_nonbonded_transparency:
ExecutiveInvalidateRep(G, inv_sele, cRepNonbonded, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepNonbondedSphere, cRepInvRep);
SceneChanged(G);
break;
case cSetting_mesh_radius:
ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvColor);
SceneChanged(G);
break;
case cSetting_ambient_occlusion_scale:
SceneChanged(G);
break;
case cSetting_ambient_occlusion_mode:
ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvColor);
switch (SettingGetGlobal_i(G, cSetting_ambient_occlusion_mode) % 4){
case 1:
SettingSetGlobal_i(G, cSetting_ambient_occlusion_smooth, 10);
SettingSetGlobal_f(G, cSetting_ambient_occlusion_scale, 25.f);
break;
case 2:
SettingSetGlobal_i(G, cSetting_ambient_occlusion_smooth, 5);
SettingSetGlobal_f(G, cSetting_ambient_occlusion_scale, .9f);
break;
case 3:
SettingSetGlobal_i(G, cSetting_ambient_occlusion_smooth, 5);
SettingSetGlobal_f(G, cSetting_ambient_occlusion_scale, 1.1f);
break;
}
SceneChanged(G);
break;
case cSetting_ambient_occlusion_smooth:
case cSetting_surface_negative_color:
case cSetting_surface_color:
case cSetting_surface_ramp_above_mode:
case cSetting_transparency:
ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvColor);
SceneChanged(G);
break;
case cSetting_dot_color:
ExecutiveInvalidateRep(G, inv_sele, cRepDot, cRepInvColor);
SceneChanged(G);
break;
case cSetting_sphere_color:
ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvColor);
SceneChanged(G);
break;
case cSetting_surface_quality:
case cSetting_surface_mode:
case cSetting_surface_normal:
case cSetting_surface_type:
case cSetting_surface_carve_state:
case cSetting_surface_carve_cutoff:
case cSetting_surface_carve_selection:
case cSetting_surface_carve_normal_cutoff:
case cSetting_surface_clear_state:
case cSetting_surface_clear_cutoff:
case cSetting_surface_clear_selection:
case cSetting_surface_trim_cutoff:
case cSetting_surface_trim_factor:
case cSetting_surface_circumscribe:
case cSetting_surface_solvent:
case cSetting_surface_proximity:
case cSetting_surface_cavity_mode:
case cSetting_surface_cavity_radius:
case cSetting_surface_cavity_cutoff:
case cSetting_cavity_cull:
case cSetting_surface_smooth_edges:
ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvRep);
SceneChanged(G);
break;
case cSetting_surface_use_shader:
SceneChanged(G);
break;
case cSetting_surface_negative_visible:
ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvRep);
SceneChanged(G);
break;
case cSetting_mesh_negative_visible:
ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvAll);
SceneChanged(G);
break;
case cSetting_solvent_radius:
ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepDot, cRepInvRep);
SceneChanged(G);
break;
case cSetting_trace_atoms_mode:
ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
SceneChanged(G);
break;
case cSetting_ribbon_smooth:
case cSetting_ribbon_power:
case cSetting_ribbon_power_b:
case cSetting_ribbon_sampling:
case cSetting_ribbon_radius:
case cSetting_ribbon_width:
case cSetting_ribbon_throw:
case cSetting_ribbon_trace_atoms:
case cSetting_ribbon_transparency:
ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
SceneChanged(G);
break;
case cSetting_draw_mode:
ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
break;
case cSetting_cartoon_side_chain_helper:
case cSetting_cartoon_nucleic_acid_mode:
ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepEllipsoid, cRepInvRep);
SceneChanged(G);
break;
case cSetting_ribbon_side_chain_helper:
case cSetting_ribbon_nucleic_acid_mode:
ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepEllipsoid, cRepInvRep);
SceneChanged(G);
break;
case cSetting_ray_trace_mode: /* affects loop quality */
G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
case cSetting_cartoon_transparency:
case cSetting_cartoon_ring_transparency:
case cSetting_cartoon_trace_atoms:
case cSetting_cartoon_refine:
case cSetting_cartoon_nucleic_acid_color:
case cSetting_cartoon_ring_mode:
case cSetting_cartoon_ring_finder:
case cSetting_cartoon_ring_width:
case cSetting_cartoon_ring_color:
case cSetting_cartoon_ladder_mode:
case cSetting_cartoon_ladder_radius:
case cSetting_cartoon_ladder_color:
case cSetting_cartoon_sampling:
case cSetting_cartoon_loop_quality:
case cSetting_cartoon_loop_radius:
case cSetting_cartoon_loop_cap:
case cSetting_cartoon_tube_quality:
case cSetting_cartoon_tube_radius:
case cSetting_cartoon_tube_cap:
case cSetting_cartoon_putty_quality:
case cSetting_cartoon_putty_radius:
case cSetting_cartoon_putty_range:
case cSetting_cartoon_putty_scale_min:
case cSetting_cartoon_putty_scale_max:
case cSetting_cartoon_putty_scale_power:
case cSetting_cartoon_putty_transform:
case cSetting_cartoon_power:
case cSetting_cartoon_power_b:
case cSetting_cartoon_ring_radius:
case cSetting_cartoon_rect_length:
case cSetting_cartoon_rect_width:
case cSetting_cartoon_oval_length:
case cSetting_cartoon_oval_width:
case cSetting_cartoon_oval_quality:
case cSetting_cartoon_round_helices:
case cSetting_cartoon_flat_sheets:
case cSetting_cartoon_refine_normals:
case cSetting_cartoon_smooth_loops:
case cSetting_cartoon_dumbbell_width:
case cSetting_cartoon_dumbbell_length:
case cSetting_cartoon_dumbbell_radius:
case cSetting_cartoon_fancy_helices:
case cSetting_cartoon_fancy_sheets:
case cSetting_cartoon_cylindrical_helices:
case cSetting_cartoon_refine_tips:
case cSetting_cartoon_helix_radius:
case cSetting_cartoon_throw:
case cSetting_cartoon_debug:
case cSetting_cartoon_highlight_color:
case cSetting_cartoon_discrete_colors:
case cSetting_cartoon_smooth_first:
case cSetting_cartoon_smooth_last:
case cSetting_cartoon_smooth_cycles:
case cSetting_cartoon_flat_cycles:
case cSetting_cartoon_gap_cutoff:
case cSetting_cartoon_all_alt:
ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
SceneChanged(G);
break;
case cSetting_cartoon_use_shader:
if (SettingGetGlobal_b(G, cSetting_use_shaders)){
ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
SceneChanged(G);
}
break;
case cSetting_cgo_use_shader:
if (SettingGetGlobal_b(G, cSetting_use_shaders)){
ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvRep);
SceneChanged(G);
}
break;
case cSetting_cgo_shader_ub_flags:
if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_cgo_use_shader)){
ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
SceneChanged(G);
}
break;
case cSetting_cgo_shader_ub_color:
if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_cgo_use_shader)){
ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
SceneChanged(G);
}
break;
case cSetting_cgo_shader_ub_normal:
if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_cgo_use_shader)){
ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
// if spheres rendered with geometry, then normals are used
// this should really only invalidate spheres that use normals (sphere_mode=0, not sure about other modes)
// but invalidating all spheres for now
ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
SceneChanged(G);
}
break;
case cSetting_trilines:
ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepDash, cRepInvRep);
ExecutiveInvalidateRep(G, inv_sele, cRepNonbonded, cRepInvRep);
SceneChanged(G);
break;
case cSetting_dot_width:
case cSetting_dot_radius:
case cSetting_dot_density:
case cSetting_dot_mode:
case cSetting_dot_solvent:
case cSetting_dot_hydrogens:
case cSetting_trim_dots:
ExecutiveInvalidateRep(G, inv_sele, cRepDot, cRepInvRep);
SceneChanged(G);
break;
case cSetting_bg_gradient:
ColorUpdateFrontFromSettings(G);
ExecutiveInvalidateRep(G, inv_sele, cRepAll, cRepInvColor);
G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
SceneChanged(G);
break;
case cSetting_bg_image_mode:
case cSetting_bg_image_filename:
G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
case cSetting_bg_image_linear:
case cSetting_bg_image_tilesize:
OrthoBackgroundTextureNeedsUpdate(G);
SceneChanged(G);
break;
case cSetting_bg_rgb_top:
case cSetting_bg_rgb_bottom:
{
/* clamp this value */
const char * bg_image_filename = SettingGet_s(G, NULL, NULL, cSetting_bg_image_filename);
if(!(bg_image_filename && bg_image_filename[0]) &&
SettingGetGlobal_b(G, cSetting_bg_gradient) && !OrthoBackgroundDataIsSet(G)) {
ColorUpdateFrontFromSettings(G);
ExecutiveInvalidateRep(G, inv_sele, cRepAll, cRepInvColor);
OrthoBackgroundTextureNeedsUpdate(G);
}
}
SceneChanged(G);
break;
case cSetting_bg_rgb:
{
/* clamp this value */
const float *v = ColorGet(G, SettingGet_color(G, NULL, NULL, cSetting_bg_rgb));
{
const char * bg_image_filename = SettingGet_s(G, NULL, NULL, cSetting_bg_image_filename);
if(!(bg_image_filename && bg_image_filename[0]) && !OrthoBackgroundDataIsSet(G)) {
ColorUpdateFront(G, v);
ExecutiveInvalidateRep(G, inv_sele, cRepAll, cRepInvColor);
}
}
}
SceneChanged(G);
break;
case cSetting_selection_width:
case cSetting_selection_width_scale:
case cSetting_selection_width_max:
case cSetting_selection_round_points:
ExecutiveInvalidateSelectionIndicatorsCGO(G);
case cSetting_line_smooth:
case cSetting_ortho:
case cSetting_chromadepth:
case cSetting_transparency_mode:
if (index == cSetting_transparency_mode)
#ifdef _WEBGL
#endif
ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvAll);
case cSetting_depth_cue:
case cSetting_fog:
case cSetting_ray_transparency_oblique:
G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
case cSetting_ray_transparency_oblique_power:
SceneInvalidate(G);
break;
case cSetting_sculpting:
OrthoDirty(G);
break;
case cSetting_auto_overlay:
OrthoRemoveAutoOverlay(G); /* always start clean */
break;
case cSetting_overlay:
case cSetting_overlay_lines:
case cSetting_text:
OrthoDirty(G);
break;
case cSetting_internal_gui_mode:
case cSetting_internal_gui_width:
case cSetting_internal_gui:
case cSetting_internal_feedback:
case cSetting_mouse_grid:
case cSetting_movie_panel_row_height:
case cSetting_movie_panel:
if(!SettingGetGlobal_b(G, cSetting_suspend_updates)) {
OrthoCommandIn(G, "viewport");
}
break;
case cSetting_suspend_updates:
if(!SettingGetGlobal_b(G, cSetting_suspend_updates)) {
SceneChanged(G); /* force big update upon resumption */
OrthoDirty(G);
}
break;
case cSetting_security:
G->Security = SettingGetGlobal_i(G, cSetting_security);
break;
case cSetting_all_states:
case cSetting_state:
case cSetting_frame:
ExecutiveInvalidateSelectionIndicatorsCGO(G);
SceneInvalidatePicking(G);
SceneChanged(G);
break;
case cSetting_dynamic_width:
case cSetting_dynamic_width_factor:
case cSetting_dynamic_width_min:
case cSetting_dynamic_width_max:
SceneChanged(G);
break;
case cSetting_rock:
case cSetting_sweep_mode:
case cSetting_sweep_phase:
case cSetting_sweep_angle:
case cSetting_sweep_speed:
SceneRestartSweepTimer(G);
break;
case cSetting_motion_power:
case cSetting_motion_bias:
case cSetting_motion_simple:
case cSetting_motion_linear:
case cSetting_motion_hand:
case cSetting_movie_loop:
if(SettingGetGlobal_b(G, cSetting_movie_auto_interpolate)) {
ExecutiveMotionReinterpolate(G);
}
break;
case cSetting_volume_bit_depth:
ExecutiveInvalidateRep(G, inv_sele, cRepVolume, cRepInvAll);
SceneInvalidate(G);
break;
case cSetting_volume_layers:
ExecutiveInvalidateRep(G, inv_sele, cRepVolume, cRepInvColor);
SceneInvalidate(G);
break;
case cSetting_cgo_transparency:
SceneInvalidate(G);
SceneChanged(G);
break;
case cSetting_label_connector_mode:
{
int lc_mode = SettingGetGlobal_i(G, cSetting_label_connector_mode);
if(lc_mode < 0 || lc_mode > 4){
if (!quiet){
PRINTFB(G, FB_Setting, FB_Warnings)
"Setting-Warning: label_connector_mode range = [0,4]"
ENDFB(G);
}
}
}
case cSetting_float_labels:
case cSetting_label_z_target:
case cSetting_label_connector:
case cSetting_label_connector_color:
case cSetting_label_connector_width:
case cSetting_label_connector_ext_length:
case cSetting_label_bg_color:
case cSetting_label_placement_offset:
case cSetting_label_relative_mode:
case cSetting_label_screen_point:
case cSetting_label_multiline_spacing:
case cSetting_label_multiline_justification:
case cSetting_label_padding:
case cSetting_label_bg_transparency:
case cSetting_label_bg_outline:
case cSetting_ray_label_connector_flat:
ExecutiveInvalidateRep(G, inv_sele, cRepLabel, cRepInvAll );
break;
case cSetting_surface_color_smoothing:
case cSetting_surface_color_smoothing_threshold:
ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvColor);
SceneChanged(G);
break;
case cSetting_smooth_half_bonds:
SceneChanged(G);
break;
case cSetting_antialias_shader:
case cSetting_atom_type_format:
case cSetting_colored_feedback:
case cSetting_load_atom_props_default:
case cSetting_load_object_props_default:
case cSetting_suspend_undo:
case cSetting_volume_mode:
PRINTFB(G, FB_Setting, FB_Warnings)
" Setting-Warning: %s is not supported in Open-Source version of PyMOL\n",
SettingInfo[index].name
ENDFB(G);
break;
break;
case cSetting_surface_debug:
if (SettingGetGlobal_b(G, cSetting_use_shaders)){
ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvColor);
}
break;
case cSetting_pick32bit:
ExecutiveInvalidateRep(G, NULL, cRepAll, cRepInvRep);
SceneChanged(G);
break;
case cSetting_display_scale_factor:
{
int scaleFactor = SettingGetGlobal_i(G, cSetting_display_scale_factor);
if (scaleFactor > 0) {
_gScaleFactor = scaleFactor;
ExecutiveInvalidateRep(G, NULL, cRepLabel, cRepInvRep);
OrthoCommandIn(G, "viewport");
} else {
SettingSetGlobal_i(G, cSetting_display_scale_factor, 1);
PRINTFB(G, FB_Setting, FB_Warnings)
"Setting-Error: Cannot set a display scale factor of 0\n"
ENDFB(G);
}
}
default:
break;
}
}
/*========================================================================*/
void SettingFreeGlobal(PyMOLGlobals * G)
{
CSetting *I = G->Setting;
SettingUniqueFree(G);
SettingPurge(I);
if(G->Default) {
SettingPurge(G->Default);
FreeP(G->Default);
}
FreeP(G->Setting);
}
/*========================================================================*/
void SettingInitGlobal(PyMOLGlobals * G, int alloc, int reset_gui, int use_default)
{
CSetting *I = G->Setting;
/* use function pointers to prevent the compiler from inlining every
call in this block (a waste of RAM and time) */
int (*set_i) (CSetting * I, int index, int value) = SettingSet_i;
int (*set_b) (CSetting * I, int index, int value) = SettingSet_b;
if(alloc || !I) {
I = (G->Setting = Calloc(CSetting, 1));
SettingUniqueInit(G);
SettingInit(G, I);
}
if(G->Default && use_default) {
SettingCopyAll(G, G->Default, G->Setting);
} else {
// copy defaults from SettingInfo table
for(int index = 0; index < cSetting_INIT; ++index) {
if (!reset_gui) switch (index) {
case cSetting_internal_gui_width:
case cSetting_internal_gui:
continue;
}
SettingRestoreDefault(I, index);
}
// open-source has no volume_mode=1
set_i(I, cSetting_volume_mode, 0);
// command line arguments overwrites
set_b(I, cSetting_auto_show_lines, G->Option->sphere_mode < 0);
set_i(I, cSetting_auto_zoom, G->Option->zoom_mode);
set_b(I, cSetting_auto_show_nonbonded, G->Option->sphere_mode < 0);
set_b(I, cSetting_presentation, G->Option->presentation);
set_i(I, cSetting_defer_builds_mode, G->Option->defer_builds_mode);
set_b(I, cSetting_presentation_auto_quit, !G->Option->no_quit);
set_b(I, cSetting_auto_show_spheres, G->Option->sphere_mode >= 0);
set_i(I, cSetting_internal_feedback, G->Option->internal_feedback);
if(G->Option->stereo_mode) {
set_i(I, cSetting_stereo_mode, G->Option->stereo_mode);
} else if(G->StereoCapable || G->Option->blue_line) {
set_i(I, cSetting_stereo_mode, cStereo_quadbuffer); /* quadbuffer if we can */
}
if(G->Option->retina) {
_gScaleFactor = 2;
set_i(I, cSetting_display_scale_factor, _gScaleFactor);
}
/* In order to get electrostatic potentials in kT from the Coulomb equation...
PyMOL charges: Q, in e
PyMOL distances: r, in Angstrom
Coulomb Constant: K = 8.987552e9 ((J*m)/(C^2))
Angstrom Convertor: 1 A = 1e-10 m
Coulomb Convertor: 1 e = 1.60217733e-19 C
Angstrom Convertor: 1 A = 10e-10 m
Dielectric Constant: D (unitless)
ePot = (KQ)/(Dr) =
8.987552e9 J*m 1.6021773e-19 C 1.6021773e-19 C 1 A Q
---------------- * --------------- * --------------- * ---------- * --- =
C^2 1 e 1 e 1e-10 m Dr
2.3070795237e-18 J*A Q
= ---------------------- * ---
e^2 Dr
Boltzmann Constant: k = 1.380658e-23 (J/K)
Temperature: 300 Kelvin
kT = 1.380658e-23 * 300 = 4.141974e-21 J
2.3070795237e-18 J*A 1 kT Q
ePot = --------------------- * ------------------ * ---
e^2 4.141974e-21 J Dr
557.00000 kT*A Q
ePot = -------------- * --- which will give kT/e units when applied
e^2 Dr
*/
#ifdef WIN32
/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
set_b(I, cSetting_cache_display, 0);
#ifndef _PYMOL_ACTIVEX
{
SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);
{
DWORD count = SysInfo.dwNumberOfProcessors;
if(count > 1) {
set_i(I, cSetting_max_threads, count);
}
}
}
/* END PROPRIETARY CODE SEGMENT */
#endif
#endif
#ifndef _PYMOL_FREETYPE
set_i(I, cSetting_label_font_id, 0);
#endif
#ifdef _PYMOL_IOS
#endif
}
G->ShaderMgr->Set_Reload_Bits(RELOAD_ALL_SHADERS);
}
int SettingCheckFontID(PyMOLGlobals * G, CSetting * set1, CSetting * set2, int font_id){
int ret = font_id;
if (font_id < 5){ // we are no longer supporting GLUT labels since they are not resizeable
PRINTFB(G, FB_Setting, FB_Warnings)
"RepLabel-Warning: GLUT labels (label_font_id 0-4) are no longer available for labelling\n the scene since they are not resizeable label_font_id=%d setting back to 5 (default) \n",
font_id ENDFB(G);
if (SettingGet_i(G, set1, NULL, cSetting_label_font_id) == font_id && SettingSet_i(set1, cSetting_label_font_id, 5)){
} else if (SettingGet_i(G, set2, NULL, cSetting_label_font_id) == font_id && SettingSet_i(set2, cSetting_label_font_id, 5)){
} else if (SettingGetGlobal_i(G, cSetting_label_font_id) == font_id){
SettingSetGlobal_i(G, cSetting_label_font_id, 5);
};
ret = 5;
}
return ret;
}
/*
* State index iterator constructor, see Setting.h for documentation.
*/
StateIterator::StateIterator(PyMOLGlobals * G, CSetting * set, int state_, int nstate) {
if(state_ == -2) {
// current state
state_ = SettingGet_i(G, set, NULL, cSetting_state) - 1;
}
if(state_ == -1) {
// all states
state = 0;
end = nstate;
} else {
// given state or static singleton
state = (state_ > 0 && nstate == 1
&& SettingGet_b(G, set, NULL, cSetting_static_singletons)) ? 0 : state_;
end = state + 1;
}
if (state < 0)
state = 0;
if (end > nstate)
end = nstate;
state--;
}
/*
* Helper function to init CPyMOL.Setting, a (name: index) dictionary.
* Called in PyMOL_InitAPI
*/
bool CPyMOLInitSetting(OVLexicon * Lex, OVOneToOne * Setting) {
for(int index = 0; index < cSetting_INIT; ++index) {
auto &rec = SettingInfo[index];
if (rec.level == cSettingLevel_unused)
continue;
OVreturn_word result = OVLexicon_GetFromCString(Lex, rec.name);
if( !OVreturn_IS_OK(result) ||
!OVreturn_IS_OK(OVOneToOne_Set(Setting, result.word, index)))
return false;
}
return true;
}
#ifndef _PYMOL_NOPY
/*
* Export the settings names to Python a as (name: index) dictionary.
* Replacement for pymol.settings.SettingIndex
*/
PyObject * SettingGetSettingIndices() {
PyObject * val;
PyObject * dict = PyDict_New();
for(int index = 0; index < cSetting_INIT; ++index) {
auto &rec = SettingInfo[index];
if (rec.level == cSettingLevel_unused)
continue;
if ((val = PyInt_FromLong(index))) {
PyDict_SetItemString(dict, rec.name, val);
Py_DECREF(val);
}
}
return dict;
}
/*
* Return a list of all setting indices for the given unique id
*/
PyObject * SettingUniqueGetIndicesAsPyList(PyMOLGlobals * G, int unique_id)
{
CSettingUnique *I = G->SettingUnique;
PyObject * list = PyList_New(0);
OVreturn_word result;
if(unique_id && OVreturn_IS_OK(result = OVOneToOne_GetForward(I->id2offset, unique_id))) {
SettingUniqueEntry *entry;
for (int offset = result.word; offset; offset = entry->next) {
entry = I->entry + offset;
PyObject *item = PyInt_FromLong(entry->setting_id);
PyList_Append(list, item);
Py_DECREF(item);
}
}
return list;
}
#endif
/*
* Getters for templatted programming
*/
const CSetting * _SettingGetFirstDefined(int index,
PyMOLGlobals * G,
const CSetting * set1,
const CSetting * set2) {
if (set1 && set1->info[index].defined)
return set1;
if (set2 && set2->info[index].defined)
return set2;
return G->Setting;
}