continue;
if (buf[0] == '\n')
break;
+ if (mp->mview == NULL || mp->mview->track == NULL)
+ continue; /* Skip (this should not happen though) */
/* scale; trx try trz; theta_deg x y z */
- if ((i == 0 && sscanf(buf, "%lf", &mview_dbuf[0]) < 1)
+ if ((i == 0 && sscanf(buf, "%lf", &dbuf[0]) < 1)
|| (i == 1 && sscanf(buf, "%lf %lf %lf",
- &mview_dbuf[1], &mview_dbuf[2], &mview_dbuf[3]) < 3)
+ &dbuf[1], &dbuf[2], &dbuf[3]) < 3)
|| (i == 2 && sscanf(buf, "%lf %lf %lf %lf",
- &mview_dbuf[4], &mview_dbuf[5], &mview_dbuf[6], &mview_dbuf[7]) < 4)) {
+ &dbuf[4], &dbuf[5], &dbuf[6], &dbuf[7]) < 4)) {
s_append_asprintf(errbuf, "line %d: bad trackball format", lineNumber);
goto err_exit;
}
+ if (i == 0)
+ TrackballSetScale(mp->mview->track, dbuf[0]);
+ else if (i == 1)
+ TrackballSetTranslate(mp->mview->track, dbuf + 1);
+ else if (i == 2)
+ TrackballSetRotate(mp->mview->track, dbuf + 4);
i++;
}
continue;
continue;
if (buf[0] == '\n')
break;
+ if (mp->mview == NULL)
+ continue; /* Skip (this should not happen, though) */
bufp = buf;
comp = strsep(&bufp, " \t");
if (bufp != NULL) {
bufp++;
valp = strsep(&bufp, "\n");
} else valp = NULL;
- /* In the following, the redundant "!= NULL" is to suppress suprious warning */
- if ((strcmp(comp, "show_unit_cell") == 0 && (i = 1))
- || (strcmp(comp, "show_periodic_box") == 0 && (i = 2))
- || (strcmp(comp, "show_expanded_atoms") == 0 && (i = 3))
- || (strcmp(comp, "show_ellipsoids") == 0 && (i = 4))
- || (strcmp(comp, "show_hydrogens") == 0 && (i = 5))
- || (strcmp(comp, "show_dummy_atoms") == 0 && (i = 6))
- || (strcmp(comp, "show_rotation_center") == 0 && (i = 7))
- || (strcmp(comp, "show_graphite_flag") == 0 && (i = 8))
- || (strcmp(comp, "show_periodic_image_flag") == 0 && (i = 9))
- || (strcmp(comp, "show_graphite") == 0 && (i = 10))
- || (strcmp(comp, "atom_resolution") == 0 && (i = 11))
- || (strcmp(comp, "bond_resolution") == 0 && (i = 12))) {
- mview_ibuf[i - 1] = atoi(valp);
- } else if ((strcmp(comp, "atom_radius") == 0 && (i = 8))
- || (strcmp(comp, "bond_radius") == 0 && (i = 9))) {
- mview_dbuf[i] = strtod(valp, NULL);
- } else if (strcmp(comp, "show_periodic_image") == 0) {
- sscanf(valp, "%d %d %d %d %d %d",
- &mview_ibuf[12], &mview_ibuf[13], &mview_ibuf[14],
- &mview_ibuf[15], &mview_ibuf[16], &mview_ibuf[17]);
+ if (strcmp(comp, "show_unit_cell") == 0)
+ mp->mview->showUnitCell = atoi(valp);
+ else if (strcmp(comp, "show_periodic_box") == 0)
+ mp->mview->showPeriodicBox = atoi(valp);
+ else if (strcmp(comp, "show_expanded_atoms") == 0)
+ mp->mview->showExpandedAtoms = atoi(valp);
+ else if (strcmp(comp, "show_ellipsoids") == 0)
+ mp->mview->showEllipsoids = atoi(valp);
+ else if (strcmp(comp, "show_hydrogens") == 0)
+ mp->mview->showHydrogens = atoi(valp);
+ else if (strcmp(comp, "show_dummy_atoms") == 0)
+ mp->mview->showDummyAtoms = atoi(valp);
+ else if (strcmp(comp, "show_rotation_center") == 0)
+ mp->mview->showRotationCenter = atoi(valp);
+ else if (strcmp(comp, "show_graphite_flag") == 0)
+ mp->mview->showGraphiteFlag = atoi(valp);
+ else if (strcmp(comp, "show_periodic_image_flag") == 0)
+ mp->mview->showPeriodicImageFlag = atoi(valp);
+ else if (strcmp(comp, "show_graphite") == 0)
+ mp->mview->showGraphite = atoi(valp);
+ else if (strcmp(comp, "show_expanded_atoms") == 0)
+ mp->mview->showExpandedAtoms = atoi(valp);
+ else if (strcmp(comp, "atom_resolution") == 0 && (i = atoi(valp)) >= 6)
+ mp->mview->atomResolution = i;
+ else if (strcmp(comp, "bond_resolution") == 0 && (i = atoi(valp)) >= 4)
+ mp->mview->bondResolution = i;
+ else if (strcmp(comp, "atom_radius") == 0)
+ mp->mview->atomRadius = strtod(valp, NULL);
+ else if (strcmp(comp, "bond_radius") == 0)
+ mp->mview->bondRadius = strtod(valp, NULL);
+ else if (strcmp(comp, "show_periodic_image") == 0) {
+ sscanf(valp, "%d %d %d %d %d %d", &ibuf[0], &ibuf[1], &ibuf[2], &ibuf[3], &ibuf[4], &ibuf[5]);
+ for (i = 0; i < 6; i++)
+ mp->mview->showPeriodicImage[i] = ibuf[i];
}
}
continue;
i = ibuf[0] + 1; /* For next entry */
}
continue;
+ } else if (strcmp(buf, "!:graphics") == 0) {
+ while (ReadLine(buf, sizeof buf, fp, &lineNumber) > 0) {
+ MainViewGraphic *gp = NULL;
+ if (buf[0] == '!')
+ continue;
+ if (buf[0] == '\n')
+ break;
+ if (mp->mview == NULL)
+ continue; /* Skip */
+ if (strcmp(buf, "line\n") == 0) {
+ ibuf[0] = kMainViewGraphicLine;
+ } else if (strcmp(buf, "poly\n") == 0) {
+ ibuf[0] = kMainViewGraphicPoly;
+ } else if (strcmp(buf, "cylinder\n") == 0) {
+ ibuf[0] = kMainViewGraphicCylinder;
+ } else if (strcmp(buf, "cone\n") == 0) {
+ ibuf[0] = kMainViewGraphicCone;
+ } else if (strcmp(buf, "ellipsoid\n") == 0) {
+ ibuf[0] = kMainViewGraphicEllipsoid;
+ } else {
+ continue; /* Skip */
+ }
+ gp = (MainViewGraphic *)calloc(sizeof(MainViewGraphic), 1);
+ gp->kind = ibuf[0];
+ i = 0;
+ while (ReadLine(buf, sizeof buf, fp, &lineNumber) > 0) {
+ if (buf[0] == '!')
+ continue;
+ if (buf[0] == '\n')
+ break;
+ if (i == 0) {
+ if (sscanf(buf, "%d %d", &ibuf[0], &ibuf[1]) < 2) {
+ s_append_asprintf(errbuf, "line %d: the closed/visible flags cannot be read for graphic object", lineNumber);
+ goto err_exit;
+ }
+ gp->closed = ibuf[0];
+ gp->visible = ibuf[1];
+ } else if (i == 1) {
+ if (sscanf(buf, "%lf %lf %lf %lf", &dbuf[0], &dbuf[1], &dbuf[2], &dbuf[3]) < 4) {
+ s_append_asprintf(errbuf, "line %d: the color cannot be read for graphic object", lineNumber);
+ goto err_exit;
+ }
+ for (j = 0; j < 4; j++)
+ gp->rgba[j] = dbuf[j];
+ } else if (i == 2) {
+ j = atoi(buf);
+ if (j < 0) {
+ s_append_asprintf(errbuf, "line %d: the number of control points must be non-negative", lineNumber);
+ goto err_exit;
+ }
+ if (j > 0)
+ NewArray(&gp->points, &gp->npoints, sizeof(GLfloat) * 3, j);
+ } else if (i >= 3 && i < gp->npoints + 3) {
+ if (sscanf(buf, "%lf %lf %lf", &dbuf[0], &dbuf[1], &dbuf[2]) < 3) {
+ s_append_asprintf(errbuf, "line %d: the control point cannot be read for graphic object", lineNumber);
+ goto err_exit;
+ }
+ j = (i - 3) * 3;
+ gp->points[j++] = dbuf[0];
+ gp->points[j++] = dbuf[1];
+ gp->points[j] = dbuf[2];
+ } else if (i == gp->npoints + 3) {
+ j = atoi(buf);
+ if (j < 0) {
+ s_append_asprintf(errbuf, "line %d: the number of normals must be non-negative", lineNumber);
+ goto err_exit;
+ }
+ if (j > 0)
+ NewArray(&gp->normals, &gp->nnormals, sizeof(GLfloat) * 3, j);
+ } else if (i >= gp->npoints + 3 && i < gp->npoints + gp->nnormals + 3) {
+ if (sscanf(buf, "%lf %lf %lf", &dbuf[0], &dbuf[1], &dbuf[2]) < 3) {
+ s_append_asprintf(errbuf, "line %d: the normal vector cannot be read for graphic object", lineNumber);
+ goto err_exit;
+ }
+ j = (i - gp->npoints - 3) * 3;
+ gp->normals[j++] = dbuf[0];
+ gp->normals[j++] = dbuf[1];
+ gp->normals[j] = dbuf[2];
+ } else break;
+ i++;
+ }
+ MainView_insertGraphic(mp->mview, -1, gp);
+ free(gp);
+ if (buf[0] == '\n')
+ break;
+ }
+ continue;
+ } else if (strncmp(buf, "!:@", 3) == 0) {
+ /* Plug-in implemented in the ruby world */
+ Int stringLen;
+ char *stringBuf, *returnString;
+ i = strlen(buf);
+ NewArray(&stringBuf, &stringLen, sizeof(char), i + 1);
+ strcpy(stringBuf, buf);
+ k = lineNumber;
+ while (ReadLine(buf, sizeof buf, fp, &lineNumber) > 0) {
+ /* The comment lines are _not_ skipped */
+ if (buf[0] == '\n')
+ break;
+ j = strlen(buf);
+ AssignArray(&stringBuf, &stringLen, sizeof(char), i + j, NULL);
+ strncpy(stringBuf + i, buf, j);
+ i += j;
+ }
+ if (MolActionCreateAndPerform(mp, SCRIPT_ACTION("si;s"),
+ "proc { |i| loadmbsf_plugin(i) rescue \"line #{i}: #{$i.to_s}\" }",
+ stringBuf, k, &returnString) != 0) {
+ s_append_asprintf(errbuf, "line %d: cannot invoke Ruby plugin", lineNumber);
+ goto err_exit;
+ } else if (returnString[0] != 0) {
+ s_append_asprintf(errbuf, "%s", returnString);
+ goto err_exit;
+ }
+ free(stringBuf);
+ continue;
}
/* Unknown sections are silently ignored */
}
md_arena_set_molecule(mp->arena, mp);
fclose(fp);
- if (mp->mview != NULL) {
+
+/* if (mp->mview != NULL) {
if (mview_ibuf[0] != kUndefined)
mp->mview->showUnitCell = mview_ibuf[0];
if (mview_ibuf[1] != kUndefined)
TrackballSetRotate(mp->mview->track, mview_dbuf + 4);
}
}
+*/
return 0;
}
fprintf(fp, "\n");
}
+
+ if (mp->mview != NULL && mp->mview->ngraphics > 0) {
+ MainViewGraphic *gp;
+ fprintf(fp, "!:graphics\n");
+ for (i = 0; i < mp->mview->ngraphics; i++) {
+ gp = mp->mview->graphics + i;
+ switch (gp->kind) {
+ case kMainViewGraphicLine: fprintf(fp, "line\n"); break;
+ case kMainViewGraphicPoly: fprintf(fp, "poly\n"); break;
+ case kMainViewGraphicCylinder: fprintf(fp, "cylinder\n"); break;
+ case kMainViewGraphicCone: fprintf(fp, "cone\n"); break;
+ case kMainViewGraphicEllipsoid: fprintf(fp, "ellipsoid\n"); break;
+ default: fprintf(fp, "unknown\n"); break;
+ }
+ fprintf(fp, "%d %d\n", gp->closed, gp->visible);
+ fprintf(fp, "%.4f %.4f %.4f %.4f\n", gp->rgba[0], gp->rgba[1], gp->rgba[2], gp->rgba[3]);
+ fprintf(fp, "%d\n", gp->npoints);
+ for (j = 0; j < gp->npoints; j++)
+ fprintf(fp, "%.6f %.6f %.6f\n", gp->points[j * 3], gp->points[j * 3 + 1], gp->points[j * 3 + 2]);
+ fprintf(fp, "%d\n", gp->nnormals);
+ for (j = 0; j < gp->nnormals; j++)
+ fprintf(fp, "%.6f %.6f %.6f\n", gp->normals[j * 3], gp->normals[j * 3 + 1], gp->normals[j * 3 + 2]);
+ }
+ fprintf(fp, "\n");
+ }
+
+ /* Plug-in in the Ruby world */
+ {
+ char *outMessage;
+ if (MolActionCreateAndPerform(mp, SCRIPT_ACTION(";s"),
+ "proc { savembsf_plugin rescue \"Plug-in error: #{$!.to_s}\" }", &outMessage) == 0) {
+ if (outMessage[0] != 0) {
+ if (strncmp(outMessage, "Plug-in", 7) == 0) {
+ s_append_asprintf(errbuf, "%s", outMessage);
+ } else {
+ fprintf(fp, "%s\n", outMessage);
+ }
+ }
+ free(outMessage);
+ }
+ }
fclose(fp);
return 0;
#pragma mark ------ Load/Save ------
static void
-s_Molecule_RaiseOnLoadSave(int status, const char *msg, const char *fname)
+s_Molecule_RaiseOnLoadSave(int status, int isloading, const char *msg, const char *fname)
{
if (gLoadSaveErrorMessage != NULL) {
MyAppCallback_setConsoleColor(1);
- MyAppCallback_showScriptMessage("On loading %s:\n%s\n", fname, gLoadSaveErrorMessage);
+ MyAppCallback_showScriptMessage("On %s %s:\n%s\n", (isloading ? "loading" : "saving"), fname, gLoadSaveErrorMessage);
MyAppCallback_setConsoleColor(0);
}
if (status != 0)
rb_scan_args(argc, argv, "1", &fname);
fstr = FileStringValuePtr(fname);
retval = MoleculeLoadMbsfFile(mol, fstr, &gLoadSaveErrorMessage);
- s_Molecule_RaiseOnLoadSave(retval, "Failed to load mbsf", fstr);
+ s_Molecule_RaiseOnLoadSave(retval, 1, "Failed to load mbsf", fstr);
return Qtrue;
}
rb_scan_args(argc, argv, "11", &fname, &pdbname);
fstr = FileStringValuePtr(fname);
retval = MoleculeLoadPsfFile(mol, fstr, &gLoadSaveErrorMessage);
- s_Molecule_RaiseOnLoadSave(retval, "Failed to load psf", fstr);
+ s_Molecule_RaiseOnLoadSave(retval, 1, "Failed to load psf", fstr);
pdbstr = NULL;
if (!NIL_P(pdbname)) {
pdbstr = strdup(FileStringValuePtr(pdbname));
retval = MoleculeReadCoordinatesFromPdbFile(mol, pdbstr, &gLoadSaveErrorMessage);
free(pdbstr);
- s_Molecule_RaiseOnLoadSave(retval, "Failed to load coordinates from pdb", pdbstr);
+ s_Molecule_RaiseOnLoadSave(retval, 1, "Failed to load coordinates from pdb", pdbstr);
}
return Qtrue;
}
MoleculeClearLoadSaveErrorMessage();
fstr = FileStringValuePtr(fname);
retval = MoleculeReadCoordinatesFromPdbFile(mol, fstr, &gLoadSaveErrorMessage);
- s_Molecule_RaiseOnLoadSave(retval, "Failed to load pdb", fstr);
+ s_Molecule_RaiseOnLoadSave(retval, 1, "Failed to load pdb", fstr);
return Qtrue;
}
MoleculeClearLoadSaveErrorMessage();
fstr = FileStringValuePtr(fname);
retval = MoleculeReadCoordinatesFromDcdFile(mol, fstr, &gLoadSaveErrorMessage);
- s_Molecule_RaiseOnLoadSave(retval, "Failed to load dcd", fstr);
+ s_Molecule_RaiseOnLoadSave(retval, 1, "Failed to load dcd", fstr);
return Qtrue;
}
MoleculeClearLoadSaveErrorMessage();
fstr = FileStringValuePtr(fname);
retval = MoleculeLoadTepFile(mol, fstr, &gLoadSaveErrorMessage);
- s_Molecule_RaiseOnLoadSave(retval, "Failed to load ORTEP file", fstr);
+ s_Molecule_RaiseOnLoadSave(retval, 1, "Failed to load ORTEP file", fstr);
return Qtrue;
}
MoleculeClearLoadSaveErrorMessage();
fstr = FileStringValuePtr(fname);
retval = MoleculeLoadShelxFile(mol, fstr, &gLoadSaveErrorMessage);
- s_Molecule_RaiseOnLoadSave(retval, "Failed to load SHELX res file", fstr);
+ s_Molecule_RaiseOnLoadSave(retval, 1, "Failed to load SHELX res file", fstr);
return Qtrue;
}
MoleculeClearLoadSaveErrorMessage();
fstr = FileStringValuePtr(fname);
retval = MoleculeLoadGaussianFchkFile(mol, fstr, &gLoadSaveErrorMessage);
- s_Molecule_RaiseOnLoadSave(retval, "Failed to load Gaussian fchk", fstr);
+ s_Molecule_RaiseOnLoadSave(retval, 1, "Failed to load Gaussian fchk", fstr);
return Qtrue;
}
MyAppCallback_showProgressPanel("Loading GAMESS dat file...");
retval = MoleculeLoadGamessDatFile(mol, fstr, &gLoadSaveErrorMessage);
MyAppCallback_hideProgressPanel();
- s_Molecule_RaiseOnLoadSave(retval, "Failed to load GAMESS dat", fstr);
+ s_Molecule_RaiseOnLoadSave(retval, 1, "Failed to load GAMESS dat", fstr);
return Qtrue;
}
MoleculeClearLoadSaveErrorMessage();
fstr = FileStringValuePtr(fname);
retval = MoleculeWriteToMbsfFile(mol, fstr, &gLoadSaveErrorMessage);
- s_Molecule_RaiseOnLoadSave(retval, "Failed to save mbsf", fstr);
+ s_Molecule_RaiseOnLoadSave(retval, 0, "Failed to save mbsf", fstr);
return Qtrue;
}
MoleculeClearLoadSaveErrorMessage();
fstr = FileStringValuePtr(fname);
retval = MoleculeWriteToPsfFile(mol, fstr, &gLoadSaveErrorMessage);
- s_Molecule_RaiseOnLoadSave(retval, "Failed to save psf", fstr);
+ s_Molecule_RaiseOnLoadSave(retval, 0, "Failed to save psf", fstr);
return Qtrue;
}
MoleculeClearLoadSaveErrorMessage();
fstr = FileStringValuePtr(fname);
retval = MoleculeWriteToPdbFile(mol, fstr, &gLoadSaveErrorMessage);
- s_Molecule_RaiseOnLoadSave(retval, "Failed to save pdb", fstr);
+ s_Molecule_RaiseOnLoadSave(retval, 0, "Failed to save pdb", fstr);
return Qtrue;
}
MoleculeClearLoadSaveErrorMessage();
fstr = FileStringValuePtr(fname);
retval = MoleculeWriteToDcdFile(mol, fstr, &gLoadSaveErrorMessage);
- s_Molecule_RaiseOnLoadSave(retval, "Failed to save dcd", fstr);
+ s_Molecule_RaiseOnLoadSave(retval, 0, "Failed to save dcd", fstr);
return Qtrue;
}
failure:
rval = rb_str_to_str(argv[0]);
asprintf(&p, "Failed to %s file %s", (loadFlag ? "load" : "save"), type);
- s_Molecule_RaiseOnLoadSave(1, p, StringValuePtr(rval));
+ s_Molecule_RaiseOnLoadSave(1, loadFlag, p, StringValuePtr(rval));
return Qnil; /* Does not reach here */
success:
rb_raise(rb_eMolbyError, "this molecule has no associated graphic view");
return INT2NUM(mol->mview->ngraphics);
}
-
+
/*
* call-seq:
- * set_graphic_point(graphic_index, point_index, new_value) -> new_value
+ * get_graphic_point(graphic_index, point_index) -> value
+ * get_graphic_points(graphic_index) -> values
*
- * Change the point_index-th control point of graphic_index-th graphic object
+ * Get the point_index-th control point of graphic_index-th graphic object.
+ * Get an array of all control points with the given values.
*
*/
static VALUE
-s_Molecule_SetGraphicPoint(VALUE self, VALUE gval, VALUE pval, VALUE nval)
+s_Molecule_GetGraphicPoint(int argc, VALUE *argv, VALUE self)
{
MainViewGraphic *gp;
Molecule *mol;
- int index;
+ int index, pindex;
Vector v;
+ VALUE gval, pval;
Data_Get_Struct(self, Molecule, mol);
if (mol->mview == NULL)
rb_raise(rb_eMolbyError, "this molecule has no associated graphic view");
+ rb_scan_args(argc, argv, "11", &gval, &pval);
index = NUM2INT(rb_Integer(gval));
if (index < 0 || index >= mol->mview->ngraphics)
rb_raise(rb_eArgError, "the graphic index is out of range");
gp = mol->mview->graphics + index;
- index = NUM2INT(rb_Integer(pval));
- if (index < 0 || index >= gp->npoints)
- rb_raise(rb_eArgError, "the point index is out of range");
- if (rb_obj_is_kind_of(nval, rb_cNumeric)) {
- if ((gp->kind == kMainViewGraphicCylinder || gp->kind == kMainViewGraphicCone) && index == 2) {
- v.x = NUM2DBL(rb_Float(nval));
- v.y = v.z = 0;
- } else if (gp->kind == kMainViewGraphicEllipsoid && index == 1) {
- gp->points[3] = gp->points[7] = gp->points[11] = NUM2DBL(rb_Float(nval));
- gp->points[4] = gp->points[5] = gp->points[6] = gp->points[8] = gp->points[9] = gp->points[10] = 0;
- return nval;
- } else rb_raise(rb_eArgError, "the argument must be an array-like object");
+ if (pval != Qnil) {
+ pindex = NUM2INT(rb_Integer(pval));
+ if (pindex < 0 || pindex >= gp->npoints)
+ rb_raise(rb_eArgError, "the point index is out of range");
+ v.x = gp->points[pindex * 3];
+ v.y = gp->points[pindex * 3 + 1];
+ v.z = gp->points[pindex * 3 + 2];
+ if ((gp->kind == kMainViewGraphicCylinder || gp->kind == kMainViewGraphicCone) && pindex == 2) {
+ return rb_float_new(v.x);
+ } else {
+ return ValueFromVector(&v);
+ }
+ } else {
+ pval = rb_ary_new();
+ for (pindex = 0; pindex < gp->npoints; pindex++) {
+ v.x = gp->points[pindex * 3];
+ v.y = gp->points[pindex * 3 + 1];
+ v.z = gp->points[pindex * 3 + 2];
+ rb_ary_push(pval, ValueFromVector(&v));
+ }
+ return pval;
+ }
+}
+
+/*
+ * call-seq:
+ * set_graphic_point(graphic_index, point_index, new_value) -> new_value
+ * set_graphic_points(graphic_index, new_values) -> new_values
+ *
+ * Change the point_index-th control point of graphic_index-th graphic object.
+ * Replace the control points with the given values.
+ *
+ */
+static VALUE
+s_Molecule_SetGraphicPoint(int argc, VALUE *argv, VALUE self)
+{
+ MainViewGraphic *gp;
+ Molecule *mol;
+ int index, pindex;
+ Vector v, v0;
+ VALUE gval, pval, nval;
+ MolAction *act;
+ Data_Get_Struct(self, Molecule, mol);
+ if (mol->mview == NULL)
+ rb_raise(rb_eMolbyError, "this molecule has no associated graphic view");
+ rb_scan_args(argc, argv, "21", &gval, &pval, &nval);
+ index = NUM2INT(rb_Integer(gval));
+ if (index < 0 || index >= mol->mview->ngraphics)
+ rb_raise(rb_eArgError, "the graphic index is out of range");
+ gp = mol->mview->graphics + index;
+ if (nval != Qnil) {
+ pindex = NUM2INT(rb_Integer(pval));
+ if (pindex < 0 || pindex >= gp->npoints)
+ rb_raise(rb_eArgError, "the point index is out of range");
+ v0.x = gp->points[pindex * 3];
+ v0.y = gp->points[pindex * 3 + 1];
+ v0.z = gp->points[pindex * 3 + 2];
+ if (rb_obj_is_kind_of(nval, rb_cNumeric)) {
+ if ((gp->kind == kMainViewGraphicCylinder || gp->kind == kMainViewGraphicCone) && pindex == 2) {
+ v.x = NUM2DBL(rb_Float(nval));
+ v.y = v.z = 0;
+ } else if (gp->kind == kMainViewGraphicEllipsoid && pindex == 1) {
+ v.x = NUM2DBL(rb_Float(nval));
+ v.y = v.z = 0;
+ gp->points[7] = gp->points[11] = v.x;
+ gp->points[6] = gp->points[8] = gp->points[9] = gp->points[10] = 0;
+ } else rb_raise(rb_eArgError, "the argument must be an array-like object");
+ } else {
+ if (nval == Qnil) {
+ v.x = kInvalidFloat;
+ v.y = v.z = 0.0;
+ } else VectorFromValue(nval, &v);
+ }
+ gp->points[pindex * 3] = v.x;
+ gp->points[pindex * 3 + 1] = v.y;
+ gp->points[pindex * 3 + 2] = v.z;
+ act = MolActionNew(SCRIPT_ACTION("iiv"), "set_graphic_point", index, pindex, &v0);
} else {
- if (nval == Qnil) {
- v.x = kInvalidFloat;
- v.y = v.z = 0.0;
- } else VectorFromValue(nval, &v);
- }
- gp->points[index * 3] = v.x;
- gp->points[index * 3 + 1] = v.y;
- gp->points[index * 3 + 2] = v.z;
+ VALUE aval;
+ int len;
+ Vector *vp = (Vector *)malloc(sizeof(Vector) * gp->npoints);
+ for (pindex = 0; pindex < gp->npoints; pindex++) {
+ vp[pindex].x = gp->points[pindex * 3];
+ vp[pindex].y = gp->points[pindex * 3 + 1];
+ vp[pindex].z = gp->points[pindex * 3 + 2];
+ }
+ act = MolActionNew(SCRIPT_ACTION("iV"), "set_graphic_points", index, gp->npoints, vp);
+ free(vp);
+ pval = rb_ary_to_ary(pval);
+ len = RARRAY_LEN(pval);
+ if (gp->npoints < len) {
+ gp->points = (GLfloat *)realloc(gp->points, sizeof(GLfloat) * 3 * len);
+ gp->npoints = len;
+ } else if (gp->npoints > len) {
+ int len2 = 3;
+ switch (gp->kind) {
+ case kMainViewGraphicLine: len2 = 2; break;
+ case kMainViewGraphicPoly: len2 = 3; break;
+ case kMainViewGraphicCylinder: len2 = 3; break;
+ case kMainViewGraphicCone: len2 = 3; break;
+ case kMainViewGraphicEllipsoid: len2 = 4; break;
+ }
+ if (len2 < len)
+ len2 = len;
+ gp->npoints = len2;
+ }
+ for (pindex = 0; pindex < len && pindex < gp->npoints; pindex++) {
+ aval = RARRAY_PTR(pval)[pindex];
+ if ((gp->kind == kMainViewGraphicCylinder || gp->kind == kMainViewGraphicCone) && pindex == 2) {
+ v.x = NUM2DBL(rb_Float(aval));
+ v.y = v.z = 0;
+ } else if (gp->kind == kMainViewGraphicEllipsoid && pindex == 1 && len == 2) {
+ v.x = NUM2DBL(rb_Float(aval));
+ v.y = v.z = 0;
+ gp->points[7] = gp->points[11] = v.x;
+ gp->points[6] = gp->points[8] = gp->points[9] = gp->points[10] = 0;
+ break;
+ } else VectorFromValue(aval, &v);
+ gp->points[pindex * 3] = v.x;
+ gp->points[pindex * 3 + 1] = v.y;
+ gp->points[pindex * 3 + 2] = v.z;
+ }
+ }
+ MolActionCallback_registerUndo(mol, act);
+ MolActionRelease(act);
MoleculeCallback_notifyModification(mol, 0);
return nval;
}
/*
* call-seq:
+ * get_graphic_color(graphic_index) -> value
+ *
+ * Get the color of graphic_index-th graphic object
+ */
+static VALUE
+s_Molecule_GetGraphicColor(VALUE self, VALUE gval)
+{
+ MainViewGraphic *gp;
+ Molecule *mol;
+ int index;
+ Data_Get_Struct(self, Molecule, mol);
+ if (mol->mview == NULL)
+ rb_raise(rb_eMolbyError, "this molecule has no associated graphic view");
+ index = NUM2INT(rb_Integer(gval));
+ if (index < 0 || index >= mol->mview->ngraphics)
+ rb_raise(rb_eArgError, "the graphic index is out of range");
+ gp = mol->mview->graphics + index;
+ return rb_ary_new3(4, rb_float_new(gp->rgba[0]), rb_float_new(gp->rgba[1]), rb_float_new(gp->rgba[2]), rb_float_new(gp->rgba[3]));
+}
+
+/*
+ * call-seq:
* set_graphic_color(graphic_index, new_value) -> new_value
*
* Change the color of graphic_index-th graphic object
{
MainViewGraphic *gp;
Molecule *mol;
- int index, n;
+ MolAction *act;
+ double c[4];
+ int index, i, n;
Data_Get_Struct(self, Molecule, mol);
if (mol->mview == NULL)
rb_raise(rb_eMolbyError, "this molecule has no associated graphic view");
if (index < 0 || index >= mol->mview->ngraphics)
rb_raise(rb_eArgError, "the graphic index is out of range");
gp = mol->mview->graphics + index;
+ for (i = 0; i < 4; i++)
+ c[i] = gp->rgba[i];
cval = rb_ary_to_ary(cval);
n = RARRAY_LEN(cval);
if (n != 3 && n != 4)
rb_raise(rb_eArgError, "the color argument must have 3 or 4 numbers");
- for (index = 0; index < n; index++) {
- gp->rgba[index] = NUM2DBL(rb_Float(RARRAY_PTR(cval)[index]));
+
+ for (i = 0; i < n; i++) {
+ gp->rgba[i] = NUM2DBL(rb_Float(RARRAY_PTR(cval)[i]));
}
if (n == 3)
gp->rgba[3] = 1.0;
+ act = MolActionNew(SCRIPT_ACTION("iD"), "set_graphic_color", index, 4, c);
+ MolActionCallback_registerUndo(mol, act);
+ MolActionRelease(act);
MoleculeCallback_notifyModification(mol, 0);
return cval;
}
rb_define_method(rb_cMolecule, "create_graphic", s_Molecule_CreateGraphic, -1);
rb_define_method(rb_cMolecule, "remove_graphic", s_Molecule_RemoveGraphic, 1);
rb_define_method(rb_cMolecule, "ngraphics", s_Molecule_NGraphics, 0);
- rb_define_method(rb_cMolecule, "set_graphic_point", s_Molecule_SetGraphicPoint, 3);
+ rb_define_method(rb_cMolecule, "get_graphic_point", s_Molecule_GetGraphicPoint, -1);
+ rb_define_method(rb_cMolecule, "set_graphic_point", s_Molecule_SetGraphicPoint, -1);
+ rb_define_alias(rb_cMolecule, "get_graphic_points", "get_graphic_point");
+ rb_define_alias(rb_cMolecule, "set_graphic_points", "set_graphic_point");
+ rb_define_method(rb_cMolecule, "get_graphic_color", s_Molecule_SetGraphicColor, 1);
rb_define_method(rb_cMolecule, "set_graphic_color", s_Molecule_SetGraphicColor, 2);
rb_define_method(rb_cMolecule, "show_graphic", s_Molecule_ShowGraphic, 1);
rb_define_method(rb_cMolecule, "hide_graphic", s_Molecule_HideGraphic, 1);