Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

animator.C

Go to the documentation of this file.
00001 // animator.C
00002 
00003 #include "disp/animator.H"
00004 #include "net/io_manager.H"
00005 #include "std/config.H"
00006 
00007 // The disp library shouldn't reference anything in the geom
00008 // library.  (Doing so causes link problems in some apps,
00009 // e.g. cpmesh). The following hack lets those apps compile by
00010 // defining the symbol DONT_LINK_GEOM_IN_DISP:
00011 
00012 #ifdef DONT_LINK_GEOM_IN_DISP
00013 inline void
00014 show_msg(Cstr_ptr& msg)
00015 {
00016    err_msg("%s", **msg);
00017 }
00018 #else
00019 #include "geom/world.H"
00020 inline void
00021 show_msg(Cstr_ptr& msg)
00022 {
00023    WORLD::message(msg);
00024 }
00025 #endif
00026 
00027 static bool debug = true; // "for now"
00028 /*****************************************************************
00029  * Animator
00030  *****************************************************************/
00031 TAGlist* Animator::_a_tags = 0;
00032 
00033 Animator::Animator(VIEWptr view) :
00034    _view(view),
00035    _name("animation"),
00036    _fps(12),
00037    _start_frame(0),
00038    _end_frame(0),
00039    _cur_frame(0),
00040    _jog_size(10),
00041    _loop(false),
00042    _on(false),
00043    _play_on(false),
00044    _rend_on(false),
00045    _sync_on(false),
00046    _time_scale(1.0)
00047 {
00048    // Since the animator is stopped, the clock must also be stopped:
00049    _timer.reset_hold();
00050 }
00051 
00052 /////////////////////////////////////
00053 // toggle_activation()
00054 /////////////////////////////////////
00055 void
00056 Animator::toggle_activation()
00057 {
00058    if (!_on) {
00059       if (_fps <= 0) {
00060          show_msg("Cannot activate Animator!");
00061          err_adv(debug, "Animator::toggle_activation() - No fps set");
00062       } else if (_start_frame < 0) {
00063          show_msg("Cannot activate Animator!");
00064          err_adv(debug, "Animator::toggle_activation() - No start_frame set");
00065       } else if (_end_frame < _start_frame) {
00066          show_msg("Cannot activate Animator!");
00067          err_adv(debug, "Animator::toggle_activation() - Bad end_frame");
00068       } else if (_name == NULL_STR) {
00069          show_msg("Cannot activate Animator!");
00070          err_adv(debug, "Animator::toggle_activation() - No name set");
00071       } else {
00072          show_msg("Animator ON");
00073          _on = true;
00074          _timer.set_elapsed_time(0); // reset time to 0
00075       }
00076    } else {
00077       _on = false;
00078       show_msg("Animator OFF");
00079    }
00080 }
00081 
00082 /////////////////////////////////////
00083 // press_beginning()
00084 /////////////////////////////////////
00085 void
00086 Animator::press_beginning()
00087 {
00088    _timer.set_elapsed_time(0);
00089    _cur_frame = _start_frame;
00090 }
00091 
00092 /////////////////////////////////////
00093 // press_play()
00094 /////////////////////////////////////
00095 void
00096 Animator::press_play()
00097 {
00098    if (!_play_on) {
00099       _play_on = true;
00100       _timer.resume();
00101       show_msg("Playing...");
00102    } else {
00103       show_msg("Already Playing!");
00104    }
00105 }
00106 
00107 /////////////////////////////////////
00108 // press_stop()
00109 /////////////////////////////////////
00110 void
00111 Animator::press_stop()
00112 {
00113    if (_play_on) {
00114       _play_on = false;
00115       _timer.pause();
00116       show_msg("Stopped");
00117    } else {
00118       show_msg("Already Stopped");
00119    }
00120 }
00121 
00122 /////////////////////////////////////
00123 // press_render()
00124 /////////////////////////////////////
00125 
00126 void
00127 Animator::press_render()
00128 {
00129    if (_rend_on) {
00130       _rend_on = false;
00131 
00132       show_msg("Render to Disk Mode OFF");
00133    } else {
00134       if (_sync_on) {
00135          _rend_on = true;
00136          show_msg("Render to Disk Mode ON");
00137       } else {
00138          show_msg("Engage time sync mode first!");
00139       }
00140    }
00141 }
00142 
00143 /////////////////////////////////////
00144 // press_sync()
00145 /////////////////////////////////////
00146 void
00147 Animator::press_sync()
00148 {
00149    if (_rend_on) {
00150       //Sanity check
00151       assert(_sync_on);
00152       show_msg("Disengage render to disk mode first!");
00153    } else {
00154       if (_sync_on) {
00155          _sync_on = false;
00156          show_msg("Time Sync Mode OFF");
00157       } else {
00158          _sync_on = true;
00159          show_msg("Time Sync Mode ON");
00160       }
00161    }
00162 }
00163 
00164 inline int
00165 wrap(int a, int b, int c)
00166 {
00167    // Given b <= c, if a is outside the interval [b,c], then
00168    // remap it inside the interval by making it "wrap around."
00169    // E.g.:
00170    //
00171    //   wrap(11, 3, 9) == 5
00172    //
00173    // because
00174    //
00175    //   3 + (11 - 3)%(9 - 3) == 5
00176 
00177    int d = c - b;
00178    if (d == 0)
00179       return b;   // b == c, so return b
00180    assert(d > 0); // c > b
00181    if (a < b) {
00182       return c + div(a-b,d).rem;
00183    } else if (a > c) {
00184       return b + div(a-b,d).rem;
00185    } else {
00186       return a;
00187    }
00188 }
00189 
00190 void
00191 Animator::inc_frame(int inc)
00192 {
00193    // advance the frame by the given amount, either clamping the
00194    // result to [start,end] or wrapping around in that interval:
00195 
00196    _cur_frame = _loop ?
00197       wrap (_cur_frame + inc, _start_frame, _end_frame) :
00198       clamp(_cur_frame + inc, _start_frame, _end_frame);
00199 }
00200 
00201 /////////////////////////////////////
00202 // step()
00203 /////////////////////////////////////
00204 void
00205 Animator::step(int inc)
00206 {
00207    char buf[1024];
00208    if (_play_on) {
00209       show_msg("Press stop before stepping");
00210       return;
00211    } else if (_sync_on) {
00212       // sync mode: advance the frame number by requested amount
00213       inc_frame(inc);
00214       sprintf(buf,"Frame %d of %d to %d", _cur_frame, _start_frame, _end_frame);
00215       show_msg(buf);
00216    } else {
00217       // real-time mode. advance the time by dt = inc / fps
00218       assert(_timer.is_paused());
00219       assert(_fps != 0);
00220       double dt = double(inc)/_fps;
00221       _timer.inc_elapsed_time(dt);
00222       sprintf(buf,"Advanced time by %1.3f seconds", dt);
00223       show_msg(buf);
00224       return;
00225    }
00226 }
00227 
00228 /////////////////////////////////////
00229 // pre_draw_CB()
00230 /////////////////////////////////////
00231 double
00232 Animator::pre_draw_CB()
00233 {
00234    assert(_on);
00235 
00236    if (_sync_on) {
00237       return _time_scale * (_cur_frame - _start_frame) / _fps;
00238    } else {
00239       return _time_scale * _timer.elapsed_time();
00240    }
00241 }
00242 
00243 /////////////////////////////////////
00244 // post_draw_CB()
00245 /////////////////////////////////////
00246 
00247 void
00248 Animator::post_draw_CB()
00249 {
00250    bool use_alpha = Config::get_var_bool("GRAB_ALPHA",true);
00251 
00252    if (_play_on && _rend_on) {
00253       // grab the current frame and write it to disk
00254       char buf[1024];
00255       sprintf (buf, "%s[%dFPS][%dto%d]-%05d.png",
00256                **_name, _fps, _start_frame, _end_frame, _cur_frame);
00257       err_msg("Animator::post_draw_CB() - Writing '%s'...", buf);
00258 
00259       int w,h;
00260       VIEW_SIZE (w,h);
00261       Image output (w, h, use_alpha ? 4 : 3); // 4 bytes for rgba, 3 for rgb
00262       VIEWimpl* impl = _view->impl();
00263       if (impl) {
00264          _view->set_grabbing_screen(1);
00265          impl->prepare_buf_read();
00266          impl->read_pixels(output.data(),use_alpha);
00267          _view->set_grabbing_screen(0);
00268          impl->end_buf_read();
00269       }
00270       if (!output.write_png(buf)) {
00271          err_msg("Animator::post_draw_CB() - Error writing file!");
00272       }
00273    }
00274    // in sync mode, advance the frame number:
00275    if (_sync_on && _play_on) {
00276       if (_cur_frame >= _end_frame && !_loop) {
00277          // if not looping and the last frame is finished, stop
00278          press_stop();
00279       } else {
00280          // otherwise, increment frame count
00281          // (loop to beginning if in loop mode)
00282          inc_frame(1);
00283       }
00284    }
00285 }
00286 
00287 STDdstream&
00288 Animator::format(STDdstream &d)  const
00289 {
00290    STDdstream &ret = DATA_ITEM::format(d);
00291 
00292    // After saving out the Animator class, check if indeed multiple
00293    // frames exist (i.e. animation!), and step through frame-by-frame,
00294    // loading each frame, and saving to the new location...
00295 
00296    if ( (_fps > 0) &&
00297         (_start_frame >=0) &&
00298         (_end_frame > _start_frame) &&
00299         (_name != NULL_STR) ) {
00300       cerr << "Animator::format: Found .jot file containing multiple frames."
00301            << endl
00302            << "Each frame will be loaded and resaved..." << endl;
00303 
00304       str_ptr bname, lname, sname;
00305 
00306       char buf[6];
00307 
00308       LOADobs::load_status_t lstatus;
00309       SAVEobs::save_status_t sstatus;
00310 
00311       for (int i = _end_frame; i >= _start_frame; i--) {
00312          sprintf(buf, "%05d", i);
00313 
00314          str_ptr bname = _name + "[" + buf + "].jot";
00315 
00316          str_ptr lname = IOManager::cached_prefix() + bname;
00317          str_ptr sname = IOManager::current_prefix() + bname;
00318 
00319          err_msg("Animator::format() - Saving frame: '%s'...", **bname);
00320 
00321          //Keep scope issolated so load stream closes before saving
00322          //just in case we're overwriting...
00323          {
00324             NetStream l(lname, NetStream::ascii_r);
00325             LOADobs::notify_load_obs(l, lstatus, true, false);
00326 
00327             if (lstatus != LOADobs::LOAD_ERROR_NONE) {
00328                cerr << "Animator::format: Error loading scene update frame: "
00329                     << lname << ", Aborting..." << endl;
00330                break;
00331             }
00332          }
00333 
00334          {
00335             NetStream s(sname, NetStream::ascii_w);
00336             SAVEobs::notify_save_obs(s, sstatus, true, false);
00337 
00338             if (sstatus != SAVEobs::SAVE_ERROR_NONE) {
00339                cerr << "Animator::format: Error saving scene update frame: "
00340                     << sname << ", Aborting..." << endl;
00341                break;
00342             }
00343          }
00344       }
00345    }
00346 
00347    return ret;
00348 }
00349 
00350 /////////////////////////////////////
00351 // tags()
00352 /////////////////////////////////////
00353 CTAGlist &
00354 Animator::tags() const
00355 {
00356    if (!_a_tags) {
00357       _a_tags = new TAGlist;
00358 
00359       *_a_tags += new TAG_val<Animator,int>(
00360          "fps",
00361          &Animator::fps_);
00362       *_a_tags += new TAG_val<Animator,int>(
00363          "start_frame",
00364          &Animator::start_frame_);
00365       *_a_tags += new TAG_val<Animator,int>(
00366          "end_frame",
00367          &Animator::end_frame_);
00368 
00369 
00370       *_a_tags += new TAG_meth<Animator>(
00371          "name",
00372          &Animator::put_name,
00373          &Animator::get_name,
00374          1);
00375    }
00376    return *_a_tags;
00377 }
00378 /////////////////////////////////////
00379 // get_name()
00380 /////////////////////////////////////
00381 void
00382 Animator::get_name (TAGformat &d)
00383 {
00384    str_ptr str, space;
00385    *d >> str;
00386 
00387    if (!(*d).ascii())
00388       *d >> space;
00389 
00390    if (str == "NULL_STR") {
00391       _name = NULL_STR;
00392       err_mesg(ERR_LEV_SPAM, "Animator::get_name() - Loaded NULL string.");
00393    } else {
00394       _name = str;
00395       err_mesg(ERR_LEV_SPAM, "Animator::get_name() - Loaded string: '%s'.", **str);
00396    }
00397 
00398 }
00399 
00400 /////////////////////////////////////
00401 // put_name()
00402 /////////////////////////////////////
00403 void
00404 Animator::put_name (TAGformat &d) const
00405 {
00406    d.id();
00407    if (_name == NULL_STR) {
00408       err_mesg(ERR_LEV_SPAM, "Animator::put_name() - Wrote NULL string.");
00409       *d << "NULL_STR";
00410       *d << " ";
00411    } else {
00412       *d << _name;
00413       *d << " ";
00414       err_mesg(ERR_LEV_SPAM, "Animator::put_name() - Wrote string: '%s'.", **_name);
00415    }
00416    d.end_id();
00417 }
00418 
00419 // end of file animator.C

Generated on Mon Sep 18 11:39:28 2006 for jot by  doxygen 1.4.4