From 6eae6a2097730ce7363a22d42d94374758498305 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Sat, 15 Oct 2011 13:20:10 +0000
Subject: [PATCH] option to choose step increment for animations (for
 interactive and when saving mpegs -- very useful for large animations, e.g. >
 1000 steps)

---
 Common/Context.h        |  2 +-
 Common/CreateFile.cpp   |  7 ++++---
 Common/DefaultOptions.h |  2 ++
 Common/Options.cpp      | 14 ++++++++++++++
 Common/Options.h        |  1 +
 Fltk/FlGui.cpp          |  8 ++++----
 Fltk/fileDialogs.cpp    | 13 +++++++++++--
 Fltk/graphicWindow.cpp  |  6 +++---
 Fltk/optionWindow.cpp   | 17 +++++++++++++----
 9 files changed, 53 insertions(+), 17 deletions(-)

diff --git a/Common/Context.h b/Common/Context.h
index f2c7acc17b..fd784813f4 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -208,7 +208,7 @@ class CTX {
   // post processing options 
   struct{
     int draw, link, horizontalScales;
-    int smooth, animCycle, combineTime, combineRemoveOrig;
+    int smooth, animCycle, animStep, combineTime, combineRemoveOrig;
     int fileFormat, plugins;
     double animDelay;
   }post;
diff --git a/Common/CreateFile.cpp b/Common/CreateFile.cpp
index 54e2674aba..7e14e14371 100644
--- a/Common/CreateFile.cpp
+++ b/Common/CreateFile.cpp
@@ -469,15 +469,16 @@ void CreateOutputFile(std::string fileName, int format)
                               (int)opt_view_nb_non_empty_timestep(i, GMSH_GET, 0));
       }
       std::vector<std::string> frames;
-      for(int i = 0; i < (CTX::instance()->post.animCycle ? numViews : numSteps); i++){
+      for(int i = 0; i < (CTX::instance()->post.animCycle ? numViews : numSteps); 
+          i += CTX::instance()->post.animStep){
         char tmp[256];
-        sprintf(tmp, ".gmsh-%06d.ppm", i);
+        sprintf(tmp, ".gmsh-%06d.ppm", (int)frames.size());
         frames.push_back(tmp);
       }
       status_play_manual(!CTX::instance()->post.animCycle, 0);
       for(unsigned int i = 0; i < frames.size(); i++){
         CreateOutputFile(CTX::instance()->homeDir + frames[i], FORMAT_PPM);
-        status_play_manual(!CTX::instance()->post.animCycle, 1);
+        status_play_manual(!CTX::instance()->post.animCycle, CTX::instance()->post.animStep);
       }
       int repeat = (int)(CTX::instance()->post.animDelay * 24);
       if(repeat < 1) repeat = 1;
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index caf185bfb3..2eca326cd6 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -1352,6 +1352,8 @@ StringXNumber PostProcessingOptions_Number[] = {
     "Delay (in seconds) between frames in automatic animation mode" },
   { F|O, "AnimationCycle" , opt_post_anim_cycle , 0. ,
     "Cycle through time steps (0) or views (1) for animations" },
+  { F|O, "AnimationStep" , opt_post_anim_step , 1. ,
+    "Step increment for animations" },
 
   { F|O, "CombineRemoveOriginal" , opt_post_combine_remove_orig , 1. ,
     "Remove original views after a Combine operation" },
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 257af24d08..0931528d80 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -6487,6 +6487,20 @@ double opt_post_anim_cycle(OPT_ARGS_NUM)
   return CTX::instance()->post.animCycle;
 }
 
+double opt_post_anim_step(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET){
+    CTX::instance()->post.animStep = (int)val;
+    if(CTX::instance()->post.animStep < 1) CTX::instance()->post.animStep = 1;
+  }
+#if defined(HAVE_FLTK)
+  if(FlGui::available() && (action & GMSH_GUI))
+    FlGui::instance()->options->post.value[1]->value
+      (CTX::instance()->post.animStep);
+#endif
+  return CTX::instance()->post.animStep;
+}
+
 double opt_post_combine_remove_orig(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
diff --git a/Common/Options.h b/Common/Options.h
index fe5cb6cfd6..b8f1be9bd4 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -609,6 +609,7 @@ double opt_post_link(OPT_ARGS_NUM);
 double opt_post_smooth(OPT_ARGS_NUM);
 double opt_post_anim_delay(OPT_ARGS_NUM);
 double opt_post_anim_cycle(OPT_ARGS_NUM);
+double opt_post_anim_step(OPT_ARGS_NUM);
 double opt_post_combine_remove_orig(OPT_ARGS_NUM);
 double opt_post_plugins(OPT_ARGS_NUM);
 double opt_post_nb_views(OPT_ARGS_NUM);
diff --git a/Fltk/FlGui.cpp b/Fltk/FlGui.cpp
index 0e37e4b530..b6ea2aa985 100644
--- a/Fltk/FlGui.cpp
+++ b/Fltk/FlGui.cpp
@@ -675,19 +675,19 @@ int FlGui::testGlobalShortcuts(int event)
 int FlGui::testArrowShortcuts()
 {
   if(Fl::test_shortcut(FL_Left)) {
-    status_play_manual(1, -1);
+    status_play_manual(1, -CTX::instance()->post.animStep);
     return 1;
   }
   else if(Fl::test_shortcut(FL_Right)) {
-    status_play_manual(1, 1);
+    status_play_manual(1, CTX::instance()->post.animStep);
     return 1;
   }
   else if(Fl::test_shortcut(FL_Up)) {
-    status_play_manual(0, -1);
+    status_play_manual(0, -CTX::instance()->post.animStep);
     return 1;
   }
   else if(Fl::test_shortcut(FL_Down)) {
-    status_play_manual(0, 1);
+    status_play_manual(0, CTX::instance()->post.animStep);
     return 1;
   }
   return 0;
diff --git a/Fltk/fileDialogs.cpp b/Fltk/fileDialogs.cpp
index 7909415dc7..b49431fad5 100644
--- a/Fltk/fileDialogs.cpp
+++ b/Fltk/fileDialogs.cpp
@@ -360,14 +360,14 @@ int mpegFileDialog(const char *name)
     Fl_Window *window;
     Fl_Round_Button *b[2];
     Fl_Check_Button *c[2];
-    Fl_Value_Input *v[1];
+    Fl_Value_Input *v[2];
     Fl_Button *ok, *cancel;
   };
   static _mpegFileDialog *dialog = NULL;
 
   if(!dialog){
     dialog = new _mpegFileDialog;
-    int h = 3 * WB + 6 * BH, w = 2 * BB + 3 * WB, y = WB;
+    int h = 3 * WB + 7 * BH, w = 2 * BB + 3 * WB, y = WB;
     dialog->window = new Fl_Double_Window(w, h, "MPEG Options");
     dialog->window->box(GMSH_WINDOW_BOX);
     dialog->window->set_modal();
@@ -388,6 +388,13 @@ int mpegFileDialog(const char *name)
     dialog->v[0]->step(1. / 24.);
     dialog->v[0]->precision(3);
     dialog->v[0]->align(FL_ALIGN_RIGHT);
+
+    dialog->v[1] = new Fl_Value_Input
+      (WB, y, BB / 2, BH, "Increment step"); y += BH;
+    dialog->v[1]->minimum(1);
+    dialog->v[1]->maximum(100);
+    dialog->v[1]->step(1);
+    dialog->v[1]->align(FL_ALIGN_RIGHT);
     
     dialog->c[0] = new Fl_Check_Button
       (WB, y, 2 * BB + WB, BH, "Composite all window tiles"); y += BH;
@@ -406,6 +413,7 @@ int mpegFileDialog(const char *name)
   dialog->b[0]->value(!CTX::instance()->post.animCycle);
   dialog->b[1]->value(CTX::instance()->post.animCycle);
   dialog->v[0]->value(CTX::instance()->post.animDelay);
+  dialog->v[1]->value(CTX::instance()->post.animStep);
   dialog->c[0]->value(CTX::instance()->print.compositeWindows);
   dialog->c[1]->value(CTX::instance()->print.deleteTmpFiles);
   dialog->window->show();
@@ -418,6 +426,7 @@ int mpegFileDialog(const char *name)
       if (o == dialog->ok) {
         opt_post_anim_cycle(0, GMSH_SET | GMSH_GUI, (int)dialog->b[1]->value());
         opt_post_anim_delay(0, GMSH_SET | GMSH_GUI, dialog->v[0]->value());
+        opt_post_anim_step(0, GMSH_SET | GMSH_GUI, (int)dialog->v[1]->value());
         opt_print_composite_windows(0, GMSH_SET | GMSH_GUI, (int)dialog->c[0]->value());
         opt_print_delete_tmp_files(0, GMSH_SET | GMSH_GUI, (int)dialog->c[1]->value());
         CreateOutputFile(name, FORMAT_MPEG);
diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index a611d9a8d1..79f648bd3b 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -362,7 +362,7 @@ static void status_play_cb(Fl_Widget *w, void *data)
       break;
     if(GetTimeInSeconds() - anim_time > CTX::instance()->post.animDelay) {
       anim_time = GetTimeInSeconds();
-      status_play_manual(!CTX::instance()->post.animCycle, 1);
+      status_play_manual(!CTX::instance()->post.animCycle, CTX::instance()->post.animStep);
     }
     FlGui::instance()->check();
   }
@@ -392,12 +392,12 @@ static void status_rewind_cb(Fl_Widget *w, void *data)
 
 static void status_stepbackward_cb(Fl_Widget *w, void *data)
 {
-  status_play_manual(!CTX::instance()->post.animCycle, -1);
+  status_play_manual(!CTX::instance()->post.animCycle, -CTX::instance()->post.animStep);
 }
 
 static void status_stepforward_cb(Fl_Widget *w, void *data)
 {
-  status_play_manual(!CTX::instance()->post.animCycle, 1);
+  status_play_manual(!CTX::instance()->post.animCycle, CTX::instance()->post.animStep);
 }
 
 static void remove_graphic_window_cb(Fl_Widget *w, void *data)
diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp
index d224d43ad2..fd87a09151 100644
--- a/Fltk/optionWindow.cpp
+++ b/Fltk/optionWindow.cpp
@@ -540,6 +540,7 @@ static void post_options_ok_cb(Fl_Widget *w, void *data)
   opt_post_horizontal_scales(0, GMSH_SET, o->post.butt[2]->value());
 
   opt_post_anim_delay(0, GMSH_SET, o->post.value[0]->value());
+  opt_post_anim_step(0, GMSH_SET, o->post.value[1]->value());
 
   opt_post_link(0, GMSH_SET, o->post.choice[0]->value());
 
@@ -2574,25 +2575,33 @@ optionWindow::optionWindow(int deltaFontSize)
       post.choice[0]->callback(post_options_ok_cb);
 
       post.value[0] = new Fl_Value_Input
-        (L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Animation delay");
+        (L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Frame duration (in seconds)");
       post.value[0]->minimum(0);
       post.value[0]->maximum(10);
       post.value[0]->step(0.01);
       post.value[0]->align(FL_ALIGN_RIGHT);
       post.value[0]->callback(post_options_ok_cb);
 
+      post.value[1] = new Fl_Value_Input
+        (L + 2 * WB, 2 * WB + 3 * BH, IW, BH, "Animation increment step");
+      post.value[1]->minimum(1);
+      post.value[1]->maximum(100);
+      post.value[1]->step(1);
+      post.value[1]->align(FL_ALIGN_RIGHT);
+      post.value[1]->callback(post_options_ok_cb);
+
       post.butt[0] = new Fl_Check_Button
-        (L + 2 * WB, 2 * WB + 3 * BH, BW, BH, "Cycle through views instead of time steps");
+        (L + 2 * WB, 2 * WB + 4 * BH, BW, BH, "Cycle through views instead of time steps");
       post.butt[0]->type(FL_TOGGLE_BUTTON);
       post.butt[0]->callback(post_options_ok_cb);
 
       post.butt[1] = new Fl_Check_Button
-        (L + 2 * WB, 2 * WB + 4 * BH, BW, BH, "Remove original views after combination");
+        (L + 2 * WB, 2 * WB + 5 * BH, BW, BH, "Remove original views after combination");
       post.butt[1]->type(FL_TOGGLE_BUTTON);
       post.butt[1]->callback(post_options_ok_cb);
 
       post.butt[2] = new Fl_Check_Button
-        (L + 2 * WB, 2 * WB + 5 * BH, BW, BH, "Draw value scales horizontally");
+        (L + 2 * WB, 2 * WB + 6 * BH, BW, BH, "Draw value scales horizontally");
       post.butt[2]->type(FL_TOGGLE_BUTTON);
       post.butt[2]->callback(post_options_ok_cb);
 
-- 
GitLab