// colors: Takes one argument, either a tuple of three floats, a string // color name, or an integer color index static PyObject *graphics_color(PyObject *self, PyObject *args) { int id; PyObject *obj; int result = -1; if (!PyArg_ParseTuple(args, (char *)"iO:graphics.color", &id, &obj)) return NULL; MoleculeGraphics *mol = mol_from_id(id); if (!mol) return NULL; if (PyInt_Check(obj)) { int index = PyInt_AsLong(obj); if (index >= 0 && index < MAXCOLORS) result = mol->use_color(index); } else if (PyString_Check(obj)) { char *name = PyString_AsString(obj); VMDApp *app = get_vmdapp(); int index = app->color_index(name); if (index >= 0) result = mol->use_color(index); } if (result >= 0) return PyInt_FromLong(result); PyErr_SetString(PyExc_ValueError, (char *)"Invalid color"); return NULL; }
static PyObject *set_colors(PyObject *self, PyObject *args) { PyObject *newdict; if (!PyArg_ParseTuple(args, (char *)"O!", &PyDict_Type, &newdict)) return NULL; VMDApp *app = get_vmdapp(); PyObject *keys = PyDict_Keys(newdict); PyObject *vals = PyDict_Values(newdict); int error = 0; for (int i=0; i<PyList_Size(keys); i++) { char *keyname = PyString_AsString(PyList_GET_ITEM(keys, i)); if (PyErr_Occurred()) { error = 1; break; } if (app->color_index(keyname) < 0) { PyErr_SetString(PyExc_ValueError, (char *)"Unknown color"); error = 1; break; } PyObject *newtuple = PyList_GET_ITEM(vals, i); if (!PyTuple_Check(newtuple) || PyTuple_Size(newtuple) != 3) { PyErr_SetString(PyExc_ValueError, (char *)"color definition must be 3-tuple of floats"); error = 1; break; } float rgb[3]; for (int j=0; j<3; j++) rgb[j] = (float)PyFloat_AsDouble(PyTuple_GET_ITEM(newtuple, j)); if (PyErr_Occurred()) { error = 1; break; } app->color_changevalue(keyname, rgb[0], rgb[1], rgb[2]); } Py_DECREF(keys); Py_DECREF(vals); if (error) return NULL; Py_INCREF(Py_None); return Py_None; }
static PyObject* py_set_colors(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *newdict, *newtuple, *keys, *vals; const char *kwnames[] = {"colors", NULL}; PyObject *retval = NULL; char *keyname; float rgb[3]; VMDApp *app; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:color.set_colors", (char**) kwnames, &PyDict_Type, &newdict)) return NULL; if (!(app = get_vmdapp())) return NULL; keys = PyDict_Keys(newdict); vals = PyDict_Values(newdict); for (int i=0; i<PyList_Size(keys); i++) { // Get color name from input dictionary keyname = as_charptr(PyList_GetItem(keys, i)); if (PyErr_Occurred()) goto cleanup; // Check this color name actually exists if (app->color_index(keyname) < 0) { PyErr_Format(PyExc_ValueError, "Unknown color '%s'", keyname); goto cleanup; } // Unpack value tuples into 3 floats newtuple = PyList_GetItem(vals, i); if (!PyTuple_Check(newtuple) || PyTuple_Size(newtuple) != 3) { PyErr_SetString(PyExc_ValueError, "color definition must be 3-tuple of floats"); goto cleanup; } for (int j=0; j<3; j++) { rgb[j] = (float)PyFloat_AsDouble(PyTuple_GET_ITEM(newtuple, j)); if (PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, "color definition must be floats"); goto cleanup; } } // Finally actually change the color app->color_change_rgb(keyname, rgb[0], rgb[1], rgb[2]); } retval = Py_None; // Getting the keys and values from the dictionary makes a new reference. // We tell Python we're done with it so as to not leak memory. // This needs to happen even if there was a problem setting color, which is // why we don't return NULL from the error checking statements above. cleanup: Py_DECREF(keys); Py_DECREF(vals); Py_XINCREF(retval); return retval; }