Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

py_material.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: py_material.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.37 $       $Date: 2019/05/30 15:02:15 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *  Python interface for managing materials.
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   // Need to avoid double counting references since PyList_Append does
00046   // not steal a reference and increments the count itself
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   // Transmode is a boolean, so handle reference counting
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   // Get material index from name
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, &copy))
00174     return NULL;
00175 
00176   VMDApp *app;
00177   if (!(app = get_vmdapp()))
00178     return NULL;
00179 
00180   MaterialList *mlist = app->materialList;
00181 
00182   // Check that the new material name does not yet exist
00183   if (name && mlist->material_index(name) >= 0) {
00184     PyErr_Format(PyExc_ValueError, "Material '%s' already exists", name);
00185     return NULL;
00186   }
00187 
00188   // Check that the copy source material does exist
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   // Check current material is defined
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   // Check new name is not yet defined
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; // XXX treated as a boolean flag
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   // Check that material exists
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 

Generated on Thu Apr 18 02:45:29 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002