From: toshinagata1964 Date: Fri, 12 Sep 2014 11:11:21 +0000 (+0000) Subject: Implement loading/saving of graphiobjects from/to mbsf files. X-Git-Tag: v1.0.2~71 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=d7798f32d0716020158e6c1eab864f5a8414c91b;p=molby%2FMolby.git Implement loading/saving of graphiobjects from/to mbsf files. git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@570 a2be9bc6-48de-4e38-9406-05402d4bc13c --- diff --git a/MolLib/Molecule.c b/MolLib/Molecule.c index 441eaa1..043b4c1 100755 --- a/MolLib/Molecule.c +++ b/MolLib/Molecule.c @@ -1602,15 +1602,23 @@ MoleculeLoadMbsfFile(Molecule *mp, const char *fname, char **errbuf) 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; @@ -1620,6 +1628,8 @@ MoleculeLoadMbsfFile(Molecule *mp, const char *fname, char **errbuf) 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) { @@ -1627,27 +1637,40 @@ MoleculeLoadMbsfFile(Molecule *mp, const char *fname, char **errbuf) 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; @@ -1826,6 +1849,121 @@ MoleculeLoadMbsfFile(Molecule *mp, const char *fname, char **errbuf) 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 */ } @@ -1835,7 +1973,8 @@ MoleculeLoadMbsfFile(Molecule *mp, const char *fname, char **errbuf) 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) @@ -1877,6 +2016,7 @@ MoleculeLoadMbsfFile(Molecule *mp, const char *fname, char **errbuf) TrackballSetRotate(mp->mview->track, mview_dbuf + 4); } } +*/ return 0; @@ -4568,6 +4708,47 @@ MoleculeWriteToMbsfFile(Molecule *mp, const char *fname, char **errbuf) } 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; diff --git a/MolLib/Ruby_bind/ruby_bind.c b/MolLib/Ruby_bind/ruby_bind.c index b960b1f..72fde31 100644 --- a/MolLib/Ruby_bind/ruby_bind.c +++ b/MolLib/Ruby_bind/ruby_bind.c @@ -4960,11 +4960,11 @@ s_Molecule_Equal(VALUE self, VALUE val) #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) @@ -4990,7 +4990,7 @@ s_Molecule_Loadmbsf(int argc, VALUE *argv, VALUE self) 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; } @@ -5017,13 +5017,13 @@ s_Molecule_Loadpsf(int argc, VALUE *argv, VALUE self) 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; } @@ -5048,7 +5048,7 @@ s_Molecule_Loadpdb(int argc, VALUE *argv, VALUE self) 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; } @@ -5071,7 +5071,7 @@ s_Molecule_Loaddcd(int argc, VALUE *argv, VALUE self) 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; } @@ -5094,7 +5094,7 @@ s_Molecule_Loadtep(int argc, VALUE *argv, VALUE self) 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; } @@ -5117,7 +5117,7 @@ s_Molecule_Loadres(int argc, VALUE *argv, VALUE self) 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; } @@ -5140,7 +5140,7 @@ s_Molecule_Loadfchk(int argc, VALUE *argv, VALUE self) 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; } @@ -5165,7 +5165,7 @@ s_Molecule_Loaddat(int argc, VALUE *argv, VALUE self) 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; } @@ -5185,7 +5185,7 @@ s_Molecule_Savembsf(VALUE self, VALUE fname) 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; } @@ -5205,7 +5205,7 @@ s_Molecule_Savepsf(VALUE self, VALUE fname) 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; } @@ -5225,7 +5225,7 @@ s_Molecule_Savepdb(VALUE self, VALUE fname) 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; } @@ -5245,7 +5245,7 @@ s_Molecule_Savedcd(VALUE self, VALUE fname) 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; } @@ -5320,7 +5320,7 @@ s_Molecule_LoadSave(int argc, VALUE *argv, VALUE self, int loadFlag) 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: @@ -9623,55 +9623,185 @@ s_Molecule_NGraphics(VALUE self) 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 @@ -9682,7 +9812,9 @@ s_Molecule_SetGraphicColor(VALUE self, VALUE gval, VALUE cval) { 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"); @@ -9690,15 +9822,21 @@ s_Molecule_SetGraphicColor(VALUE self, VALUE gval, VALUE cval) 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; } @@ -11389,7 +11527,11 @@ Init_Molby(void) 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); diff --git a/Scripts/loadsave.rb b/Scripts/loadsave.rb index afa2215..ae72290 100755 --- a/Scripts/loadsave.rb +++ b/Scripts/loadsave.rb @@ -1211,4 +1211,14 @@ end_of_header self end + # Plug-in for loading mbsf + def loadmbsf_plugin(s, lineno) + "" + end + + # Plug-in for saving mbsf + def savembsf_plugin + "" + end + end