00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "py_commands.h"
00022 #include "CmdMaterial.h"
00023 #include "utilities.h"
00024 #include "MaterialList.h"
00025 #include "CommandQueue.h"
00026 #include "VMDApp.h"
00027 #include <stdlib.h>
00028 #include <ctype.h>
00029
00030 static const char listall_doc[] =
00031 "Lists all currently defined materials\n\n"
00032 "Returns:\n"
00033 " (list of str): Available material names";
00034 static PyObject* py_listall(PyObject *self, PyObject *args) {
00035 VMDApp *app;
00036 if (!(app = get_vmdapp()))
00037 return NULL;
00038
00039 MaterialList *mlist = app->materialList;
00040
00041 PyObject *newlist = PyList_New(0);
00042 if (!newlist)
00043 goto failure;
00044
00045
00046
00047 int i;
00048 for (i = 0; i < mlist->num(); i++) {
00049 PyObject *tmp = as_pystring(mlist->material_name(i));
00050 PyList_Append(newlist, tmp);
00051 Py_XDECREF(tmp);
00052
00053 if (PyErr_Occurred())
00054 goto failure;
00055 }
00056 return newlist;
00057
00058 failure:
00059 PyErr_SetString(PyExc_ValueError, "Cannot get materials");
00060 Py_XDECREF(newlist);
00061 return NULL;
00062 }
00063
00064
00065 static const char settings_doc[] =
00066 "Get settings that comprise the definition of a given material\n\n"
00067 "Args:\n"
00068 " name (str): Material name to query\n"
00069 "Returns:\n"
00070 " (dict str->str): Material properties and values";
00071 static PyObject* py_settings(PyObject *self, PyObject *args, PyObject *kwargs) {
00072 const char *kwlist[] = {"name", NULL};
00073 char *name;
00074
00075 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:material.settings",
00076 (char**) kwlist, &name))
00077 return NULL;
00078
00079 VMDApp *app;
00080 if (!(app = get_vmdapp()))
00081 return NULL;
00082
00083 MaterialList *mlist = app->materialList;
00084 int ind = mlist->material_index(name);
00085 if (ind < 0) {
00086 PyErr_Format(PyExc_ValueError, "No such material '%s'", name);
00087 return NULL;
00088 }
00089
00090 PyObject *dict = PyDict_New();
00091 PyDict_SetItemString(dict, "ambient",
00092 PyFloat_FromDouble(mlist->get_ambient(ind)));
00093 PyDict_SetItemString(dict, "specular",
00094 PyFloat_FromDouble(mlist->get_specular(ind)));
00095 PyDict_SetItemString(dict, "diffuse",
00096 PyFloat_FromDouble(mlist->get_diffuse(ind)));
00097 PyDict_SetItemString(dict, "shininess",
00098 PyFloat_FromDouble(mlist->get_shininess(ind)));
00099 PyDict_SetItemString(dict, "mirror",
00100 PyFloat_FromDouble(mlist->get_mirror(ind)));
00101 PyDict_SetItemString(dict, "opacity",
00102 PyFloat_FromDouble(mlist->get_opacity(ind)));
00103 PyDict_SetItemString(dict, "outline",
00104 PyFloat_FromDouble(mlist->get_outline(ind)));
00105 PyDict_SetItemString(dict, "outlinewidth",
00106 PyFloat_FromDouble(mlist->get_outlinewidth(ind)));
00107
00108
00109 PyDict_SetItemString(dict, "transmode",
00110 mlist->get_transmode(ind) ? Py_True : Py_False);
00111 Py_INCREF(PyDict_GetItemString(dict, "transmode"));
00112
00113 if (PyErr_Occurred()) {
00114 PyErr_Format(PyExc_ValueError, "Error getting settings for material '%s'",
00115 name);
00116 Py_DECREF(dict);
00117 return NULL;
00118 }
00119
00120 return dict;
00121 }
00122
00123
00124 static const char default_doc[] =
00125 "Restore the default settings of a material\n\n"
00126 "Args:\n"
00127 " name (str): Material name to restore";
00128 static PyObject* py_set_default(PyObject *self, PyObject *args,
00129 PyObject *kwargs) {
00130 const char *kwlist[] = {"name", NULL};
00131 char *name;
00132 int ind;
00133
00134 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:material.default",
00135 (char**) kwlist, &name))
00136 return NULL;
00137
00138 VMDApp *app;
00139 if (!(app = get_vmdapp()))
00140 return NULL;
00141
00142
00143 ind = app->materialList->material_index(name);
00144 if (ind < 0) {
00145 PyErr_Format(PyExc_ValueError, "No such material '%s'", name);
00146 return NULL;
00147 }
00148
00149 if (!app->material_restore_default(ind)) {
00150 PyErr_Format(PyExc_ValueError, "Material '%s' has no default settings",
00151 name);
00152 return NULL;
00153 }
00154
00155 Py_INCREF(Py_None);
00156 return Py_None;
00157 }
00158
00159
00160 static const char add_doc[] =
00161 "Create a new material with the given name. Optionally, copy material settings\n"
00162 "from an existing material. If no name is given, make up a new name\n\n"
00163 "Args:\n"
00164 " name (str): Name of new material. If None, will be made up if copy is None\n"
00165 " copy (str): Name of material to copy settings from. If None,\n"
00166 " material settings will be initialized to Opaque material";
00167 static PyObject* py_add(PyObject *self, PyObject *args, PyObject *kwargs) {
00168 const char *kwlist[] = {"name", "copy", NULL};
00169 char *name = NULL, *copy = NULL;
00170 char *result;
00171
00172 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zz:material.add",
00173 (char**) kwlist, &name, ©))
00174 return NULL;
00175
00176 VMDApp *app;
00177 if (!(app = get_vmdapp()))
00178 return NULL;
00179
00180 MaterialList *mlist = app->materialList;
00181
00182
00183 if (name && mlist->material_index(name) >= 0) {
00184 PyErr_Format(PyExc_ValueError, "Material '%s' already exists", name);
00185 return NULL;
00186 }
00187
00188
00189 if (copy && mlist->material_index(copy) < 0) {
00190 PyErr_Format(PyExc_ValueError, "Material to copy '%s' doesn't exist", copy);
00191 return NULL;
00192 }
00193
00194 if (!(result = (char*) app->material_add(name, copy))) {
00195 PyErr_Format(PyExc_ValueError, "Unable to add material '%s'", name);
00196 return NULL;
00197 }
00198
00199 return as_pystring(result);
00200 }
00201
00202
00203 static const char del_doc[] =
00204 "Deletes a material with given name\n\n"
00205 "Args:\n"
00206 " name (str): Material to delete";
00207 static PyObject* py_matdelete(PyObject *self, PyObject *args, PyObject *kwargs) {
00208 const char *kwlist[] = {"name", NULL};
00209 char *name = NULL;
00210
00211 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z:material.delete",
00212 (char**) kwlist, &name))
00213 return NULL;
00214
00215 VMDApp *app;
00216 if (!(app = get_vmdapp()))
00217 return NULL;
00218
00219 if (!app->material_delete(name)) {
00220 PyErr_Format(PyExc_ValueError, "Unable to delete material '%s'", name);
00221 return NULL;
00222 }
00223
00224 Py_INCREF(Py_None);
00225 return Py_None;
00226 }
00227
00228
00229 static const char rename_doc[] =
00230 "Change the name of an existing material\n\n"
00231 "Args:\n"
00232 " name (str): Name of material to change\n"
00233 " newname (str): New name for material";
00234 static PyObject* py_rename(PyObject *self, PyObject *args, PyObject *kwargs) {
00235 const char *kwlist[] = {"name", "newname", NULL};
00236 char *oldname, *newname;
00237
00238 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss:material.rename",
00239 (char**) kwlist, &oldname, &newname))
00240 return NULL;
00241
00242 VMDApp *app;
00243 if (!(app = get_vmdapp()))
00244 return NULL;
00245
00246 MaterialList *mlist = app->materialList;
00247
00248
00249 if (mlist->material_index(oldname) < 0) {
00250 PyErr_Format(PyExc_ValueError, "Material '%s' to rename doesn't exist",
00251 oldname);
00252 return NULL;
00253 }
00254
00255
00256 if (mlist->material_index(newname) >= 0) {
00257 PyErr_Format(PyExc_ValueError, "New name '%s' is already a material",
00258 newname);
00259 return NULL;
00260 }
00261
00262 if (!app->material_rename(oldname, newname)) {
00263 PyErr_Format(PyExc_ValueError, "Could not change material name '%s'->'%s'",
00264 oldname, newname);
00265 return NULL;
00266 }
00267
00268 Py_INCREF(Py_None);
00269 return Py_None;
00270 }
00271
00272
00273 static const char change_doc[] =
00274 "Change properties of a material. All property arguments are optional and are\n"
00275 "used to set the new value of each property.\n\n"
00276 "Args:\n"
00277 " name (str): Material name to change\n"
00278 " ambient (float): Ambient light of material\n"
00279 " diffuse (float): Diffuse light scattering of material\n"
00280 " specular (float): Amount of specular highlights from material\n"
00281 " shininess (float): Shininess of material\n"
00282 " mirror (float): Reflectivity of material\n"
00283 " opacity (float): Opacity of material\n"
00284 " outline (float): Amount of outline on material\n"
00285 " outline_width (float): Width of outline on material\n"
00286 " transmode (bool): If angle-modulated transparency should be used\n";
00287 static PyObject* py_change(PyObject *self, PyObject *args, PyObject *kwargs) {
00288 const char *kwlist[] = {"name", "ambient", "diffuse", "specular", "shininess",
00289 "mirror", "opacity", "outline", "outlinewidth",
00290 "transmode", NULL};
00291 float ambient, specular, diffuse, shininess, mirror, opacity;
00292 float outline, outlinewidth;
00293 int transmode;
00294 char *name;
00295
00296 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ffffffffO&:material.change",
00297 (char**) kwlist, &name, &ambient, &diffuse,
00298 &specular, &shininess, &mirror, &opacity,
00299 &outline, &outlinewidth, convert_bool,
00300 &transmode))
00301 return NULL;
00302
00303 VMDApp *app;
00304 if (!(app = get_vmdapp()))
00305 return NULL;
00306
00307
00308 MaterialList *mlist = app->materialList;
00309 if (mlist->material_index(name) < 0) {
00310 PyErr_Format(PyExc_ValueError, "Material '%s' to change does not exist",
00311 name);
00312 return NULL;
00313 }
00314
00315 if (PyDict_GetItemString(kwargs, "ambient"))
00316 app->material_change(name, MAT_AMBIENT, ambient);
00317 if (PyDict_GetItemString(kwargs, "specular"))
00318 app->material_change(name, MAT_SPECULAR, specular);
00319 if (PyDict_GetItemString(kwargs, "diffuse"))
00320 app->material_change(name, MAT_DIFFUSE, diffuse);
00321 if (PyDict_GetItemString(kwargs, "shininess"))
00322 app->material_change(name, MAT_SHININESS, shininess);
00323 if (PyDict_GetItemString(kwargs, "mirror"))
00324 app->material_change(name, MAT_MIRROR, mirror);
00325 if (PyDict_GetItemString(kwargs, "opacity"))
00326 app->material_change(name, MAT_OPACITY, opacity);
00327 if (PyDict_GetItemString(kwargs, "outline"))
00328 app->material_change(name, MAT_OUTLINE, outline);
00329 if (PyDict_GetItemString(kwargs, "outlinewidth"))
00330 app->material_change(name, MAT_OUTLINEWIDTH, outlinewidth);
00331 if (PyDict_GetItemString(kwargs, "transmode"))
00332 app->material_change(name, MAT_TRANSMODE, (float) transmode);
00333
00334 Py_INCREF(Py_None);
00335 return Py_None;
00336 }
00337
00338
00339 static PyMethodDef methods[] = {
00340 {"listall", (PyCFunction)py_listall, METH_NOARGS, listall_doc},
00341 {"settings", (PyCFunction)py_settings, METH_VARARGS | METH_KEYWORDS, settings_doc},
00342 {"add", (PyCFunction)py_add, METH_VARARGS | METH_KEYWORDS, add_doc},
00343 {"delete", (PyCFunction)py_matdelete, METH_VARARGS | METH_KEYWORDS, del_doc},
00344 {"rename", (PyCFunction)py_rename, METH_VARARGS | METH_KEYWORDS, rename_doc},
00345 {"change", (PyCFunction)py_change, METH_VARARGS | METH_KEYWORDS, change_doc },
00346 {"default", (PyCFunction)py_set_default, METH_VARARGS | METH_KEYWORDS, default_doc },
00347 {NULL, NULL}
00348 };
00349
00350
00351 static const char material_moddoc[] =
00352 "Methods to control the materials used to render molecules or graphics objects";
00353
00354
00355 #if PY_MAJOR_VERSION >= 3
00356 static struct PyModuleDef materialdef = {
00357 PyModuleDef_HEAD_INIT,
00358 "material",
00359 material_moddoc,
00360 -1,
00361 methods,
00362 };
00363 #endif
00364
00365
00366 PyObject* initmaterial(void) {
00367 #if PY_MAJOR_VERSION >= 3
00368 PyObject *m = PyModule_Create(&materialdef);
00369 #else
00370 PyObject *m = Py_InitModule3("material", methods, material_moddoc);
00371 #endif
00372 return m;
00373 }
00374