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

smview.C

Go to the documentation of this file.
00001 #include "std/fstream.H"
00002 #include "disp/animator.H"
00003 #include "disp/recorder.H"
00004 #include "geom/gl_util.H"
00005 #include "geom/distrib.H"
00006 #include "geom/recorder_ui.H"
00007 #include "geom/texture.H"
00008 #include "geom/world.H"
00009 #include "gtex/ref_image.H"
00010 #include "gtex/buffer_ref_image.H"
00011 #include "gtex/curvature_ui.H"
00012 #include "gtex/fader_texture.H"
00013 #include "gtex/flat_shade.H"
00014 #include "gtex/key_line.H"
00015 #include "gtex/sil_frame.H"
00016 #include "manip/cam_pz.H"
00017 #include "manip/cam_fp.H"
00018 #include "mesh/hybrid.H"
00019 #include "mesh/lmesh.H"
00020 #include "mesh/objreader.H"
00021 #include "mesh/patch.H"
00022 #include "mlib/points.H"
00023 
00024 using namespace mlib;
00025 
00026 #include "std/run_avg.H"
00027 #include "std/stop_watch.H"
00028 #include "std/support.H"
00029 #include "std/time.H"
00030 #include "widgets/alert_box.H"
00031 #include "widgets/file_select.H"
00032 #include "widgets/fps.H"
00033 #include "widgets/menu.H"
00034 
00035 #include "base_jotapp/base_jotapp.H"
00036 
00037 /* KeyMenu Callback Function Prototypes */
00038 
00039 int bk_camera(const Event& ev, State *& s);
00040 int fwd_camera(const Event& ev, State *& s);
00041 
00042 int next_texture(const Event&, State *&);
00043 
00044 int rotate_camera(const Event& ev, State *&);
00045 
00046 int toggle_buffer(const Event&, State *&);
00047 
00048 int toggle_antialias(const Event&, State *&);
00049 int next_antialias(const Event&, State *&);
00050 
00051 int freeze_sils(const Event&, State *&);
00052 
00053 int toggle_random_sils(const Event&, State *&);
00054 
00055 int toggle_hidden_lines(const Event&, State *&);
00056 
00057 int debug_cb(const Event& ev, State *&);
00058 
00059 int clear_cb(const Event&, State *&);
00060 
00061 void alert_cbs(void *ptr, void *dptr, int idx, int but_idx);
00062 
00063 void do_clear();
00064 
00065 int save_cb(const Event&, State *&);
00066 int load_cb(const Event&, State *&);
00067 
00068 void file_cbs(void *ptr, int idx, int action, str_ptr path, str_ptr file);
00069 
00070 void do_save(str_ptr fullpath);
00071 void do_load(str_ptr fullpath);
00072 
00073 int animation_keys(const Event &e, State *&s);
00074 
00075 int render_mode(const Event &e, State *&s);
00076 
00077 int toggle_recorder(const Event &, State *&);
00078 int rec_play(const Event &, State *&);
00079 int rec_rec(const Event &, State *&);
00080 int rec_stop(const Event &, State *&);
00081 int rec_pause(const Event &, State *&);
00082 
00083 int toggle_repair(const Event &, State *&);
00084 
00085 int undo_redo(const Event &e, State *&);
00086 
00087 int quit(const Event&, State *&);
00088 
00089 int refine(const Event&, State *&);
00090 
00091 int cycle_subdiv_loc_calc(const Event&, State *&);
00092 
00093 int clear_selections(const Event&, State *&);
00094 
00095 int unrefine(const Event&, State *&);
00096 
00097 int toggle_transp(const Event&e, State *&);
00098 
00099 int write(const Event&, State *&);
00100 
00101 int print_mesh(const Event&, State *&);
00102 
00103 int write_xformed(const Event&, State *&);
00104 
00105 int write_merged_meshes(const Event&, State *&);
00106 
00107 int save_config(const Event &e, State *&);
00108 
00109 int clear_creases(const Event&, State*&);
00110 
00111 int toggle_no_text(const Event&, State*&);
00112 
00113 int toggle_show_secondary_faces(const Event&, State *&);
00114 
00115 int recreate_creases(const Event&, State *&);
00116 int toggle_crease(const Event &, State *&);
00117 
00118 int split_mesh(const Event &e, State *&);
00119 
00120 int kill_component(const Event &, State *&);
00121 
00122 int print_key_menu(const Event&, State *&);
00123 
00124 int toggle_curvature_ui(const Event&, State *&);
00125 
00126 /**********************************************************************
00127  * SMVIEWapp Class
00128  **********************************************************************/
00129 
00130 class SMVIEWapp : public BaseJOTapp {
00131 
00132  public:   
00133    /******** PUBLIC MEMBER CLASSES ********/
00134 
00135    class WINDOWjot : public BaseJOTapp::WINDOW
00136    {
00137     public:
00138       State          _otherstart;
00139 
00140       WINDOWjot(WINSYS *win) : WINDOW(win) {}
00141    };
00142 
00143  protected:  
00144    /******** STATIC MEMBER VARIABLES ********/
00145 
00146    /******** MEMBER VARIABLES ********/
00147 
00148    /******** STATIC MEMBER METHODS ********/
00149 
00150    static void splash_cb(void *j, void *jd, int, int) {
00151       ((SMVIEWapp *)j)->_windows[0]->_view->set_focus();
00152    }
00153 
00154  public:
00155    /******** CONSTRUCTOR/DECONSTRUCTOR *******/
00156 
00157     SMVIEWapp(int argc, char **argv) : BaseJOTapp(argc, argv) {}
00158 
00159    /******** BaseJOTapp METHODS ********/
00160  protected:  
00161 
00162    virtual WINDOW*   new_window(WINSYS *win) { return new WINDOWjot(win);}
00163 
00164    virtual void      init_scene();
00165 
00166    virtual void      init_interact_cb(WINDOW &base_window);
00167    
00168    virtual void      init_kbd(WINDOW &base_window);
00169 
00170    virtual void      init_fsa();
00171 
00172  public:
00173    virtual void init() 
00174    {
00175       srand48((long)the_time());
00176 
00177       BaseJOTapp::init();
00178       
00179       //Puts focus on main window -- in case some
00180       //GLUI window tries to take initial focus.
00181       //If the splash alert box shows, this is called
00182       //after the popup is dismissed instead.
00183       splash_cb(this,NULL,0,0);
00184    }
00185 };
00186 
00187 /*****************************************************************
00188  * SMVIEWapp Methods
00189  *****************************************************************/
00190 
00191 /////////////////////////////////////
00192 // init_scene()
00193 /////////////////////////////////////
00194 void  
00195 SMVIEWapp::init_scene() 
00196 {
00197    int i;
00198 
00199    //Add fps and keyboard navigator
00200    BaseJOTapp::init_scene();
00201    
00202    // Set rendering style to smooth shading unless an environment
00203    // variable gives a different default:
00204    for (i=0; i<_windows.num(); i++) {
00205       _windows[i]->_view->set_rendering(
00206          Config::get_var_str("JOT_RENDER_STYLE", **RSMOOTH_SHADE));
00207    }
00208 
00209 }
00210 
00211 /////////////////////////////////////
00212 // init_interact_cb()
00213 /////////////////////////////////////
00214 void  
00215 SMVIEWapp::init_interact_cb(WINDOW &base_window) 
00216 {
00217    BaseJOTapp::init_interact_cb(base_window);
00218 
00219 //   WINDOWjot &win = (WINDOWjot &) base_window;
00220 
00221 //    init_draw_int(win);
00222 }
00223 
00224 /////////////////////////////////////
00225 // init_kbd()
00226 /////////////////////////////////////
00227 
00228 void
00229 SMVIEWapp::init_kbd(WINDOW &base_window)
00230 {
00231    
00232    BaseJOTapp::init_kbd(base_window);
00233    
00234    // add a mess of key commands (in alphabetical order!):
00235 
00236    _key_menu->add_menu_item('a', "Toggle antialias", &toggle_antialias);
00237    _key_menu->add_menu_item('A', "Toggle next antialias", &next_antialias);
00238    _key_menu->add_menu_item('b', "Toggle buffer", &toggle_buffer);
00239    _key_menu->add_menu_item('c', "Clear (delete) all objects", &clear_cb);
00240    // key 'C' falls into AnimationKeys
00241    _key_menu->add_menu_item('D', "Toggle no_text", &toggle_no_text);
00242    _key_menu->add_menu_item('d', "Debug callback", &debug_cb);
00243    _key_menu->add_menu_item('F', "Freeze sils", &freeze_sils);
00244    _key_menu->add_menu_item('i', "Recreate Creases", &recreate_creases);
00245    _key_menu->add_menu_item('k', "Clear creases", &clear_creases);   
00246    _key_menu->add_menu_item('l', "Load File", &load_cb);   
00247    _key_menu->add_menu_item('N', "Next texture", &next_texture);
00248    _key_menu->add_menu_item('p', "Print mesh statistics", &print_mesh);
00249    _key_menu->add_menu_item('r', "Rotate", &rotate_camera);
00250    _key_menu->add_menu_item('s', "Save", &save_cb);
00251    _key_menu->add_menu_item('S', "Cycle subdivision loc calc", &cycle_subdiv_loc_calc);
00252    _key_menu->add_menu_item("t", "Refine mesh", &refine);
00253    _key_menu->add_menu_item('U', "Unrefine mesh", &unrefine);
00254    _key_menu->add_menu_item('w', "Write mesh", &write);
00255    _key_menu->add_menu_item('W', "Write_xformed mesh", &write_xformed);
00256    // key 'X' is used below by the animation controls
00257    _key_menu->add_menu_item('Z', "Toggle hidden lines in Key Line rendering style",
00258            &toggle_hidden_lines);
00259    _key_menu->add_menu_item('=', "Toggle random sils", &toggle_random_sils);
00260 
00261    // This method handles all key presses to the view's
00262    // recorder and animator
00263    _key_menu->add_menu_item("CX/*-+24568", "Animation keys",  &animation_keys);
00264 
00265    _key_menu->add_menu_item("\r\n\x8\x7f", "Undo Redo", &undo_redo);
00266    
00267    _key_menu->add_menu_item("!@#", "Render mode", &render_mode);
00268 
00269    _key_menu->add_menu_item("%", "Toggle Curvature gTexture UI", &toggle_curvature_ui);
00270 }
00271 
00272 /////////////////////////////////////
00273 // init_fsa()
00274 /////////////////////////////////////
00275 void        
00276 SMVIEWapp::init_fsa() 
00277 {
00278    BaseJOTapp::init_fsa();
00279 
00280    for (int i = 0; i < _windows.num(); i++) 
00281    {
00282       WINDOWjot *winjot = (WINDOWjot *) _windows[i];
00283       VIEWint_list::add(_windows[i]->_view, &winjot->_otherstart);
00284    }
00285 
00286 }
00287 
00288 /**********************************************************************
00289  * main()
00290  **********************************************************************/
00291 int
00292 main(int argc, char **argv)
00293 {
00294    SMVIEWapp app(argc, argv);
00295    
00296    app.init();
00297    app.Run();
00298 
00299    return 0;
00300 }
00301 
00302 //============================================================================//
00303 
00304 /* KeyMenu Callback Functions */
00305 
00306 // Dialog box callback constants:
00307 
00308 enum alert_cb_t {
00309    ALERT_CLEAR_CB = 0,
00310    ALERT_SAVE_JOT_OVERWRITE_CB,
00311    ALERT_SAVE_JOT_FAILED_CB,
00312    ALERT_LOAD_JOT_FAILED_CB
00313 };
00314 
00315 enum file_cb_t {
00316    FILE_SAVE_JOT_CB = 0,
00317    FILE_LOAD_JOT_CB
00318    //FILE_SAVE_SM_CB, etc.
00319 }; 
00320 
00321 // find_mesh:
00322 //    (Convenience method.)  Some key callbacks operate on
00323 //    a specific mesh.  Here we return the mesh that is
00324 //    currently the "center of interest", or (if none),
00325 //    the one that is currently under the cursor.
00326 inline BMESH*
00327 find_mesh()
00328 {
00329    BMESH* ret = BMESH::center_of_interest();
00330    return ret ? ret : VisRefImage::get_mesh();
00331 }
00332 
00333 inline BMESH*
00334 find_ctrl_mesh()
00335 {
00336    return get_ctrl_mesh(find_mesh());
00337 }
00338 
00339 int
00340 bk_camera(const Event& ev, State *& s)
00341 {
00342    ((VIEWptr) (ev.view()))->bk_cam_hist();
00343    return 0;
00344 }
00345 
00346 int
00347 fwd_camera(const Event& ev, State *& s)
00348 {
00349    ((VIEWptr) (ev.view()))->fwd_cam_hist();
00350    return 0;
00351 }
00352 
00353 int
00354 next_texture(const Event&, State *&)
00355 {
00356    Patch* patch = VisRefImage::get_ctrl_patch();
00357 
00358    if (patch) {
00359       patch->next_texture();
00360       WORLD::message(patch->cur_tex()->class_name());
00361    }
00362 
00363    return 0;
00364 }
00365 
00366 
00367 int
00368 rotate_camera(const Event& ev, State *&)
00369 {
00370    CAMptr      cam (ev.view()->cam());
00371    CAMdataptr  data(cam->data());
00372 
00373    cam->set_zoom(1);
00374    cam->set_min(NDCpt(XYpt(-1,-1)));
00375    cam->data()->changed();
00376 
00377    XYpt        cpt   = data->center();
00378    double      radsq = sqr(1+fabs(cpt[0])); // squared rad of virtual cylinder
00379 
00380    //Hacking - Toss in some XY pts
00381    //to simulate a mouse movement
00382    //that produces rotation...
00383    //XYpt        tp    = ptr->old(); 
00384    //XYpt        te    = ptr->cur();
00385    XYpt        tp    = XYpt(0.485, 0.5); 
00386    XYpt        te    = XYpt(0.5,0.5);
00387 
00388 
00389    Wvec   op  (tp[0], 0, 0);             // get start and end X coordinates
00390    Wvec   oe  (te[0], 0, 0);             //    of cursor motion
00391    double opsq = op * op, oesq = oe * oe;
00392    double lop  = opsq > radsq ? 0 : sqrt(radsq - opsq);
00393    double loe  = oesq > radsq ? 0 : sqrt(radsq - oesq);
00394    Wvec   nop  = Wvec(op[0], 0, lop).normalized();
00395    Wvec   noe  = Wvec(oe[0], 0, loe).normalized();
00396    double dot  = nop * noe;
00397 
00398    if (fabs(dot) > 0.0001) {
00399       data->rotate(Wline(data->center(), Wvec::Y()),
00400                    -2*Acos(dot) * Sign(te[0]-tp[0]));
00401 
00402       double rdist = te[1]-tp[1];
00403 
00404       CAMdata   dd = CAMdata(*data);
00405 
00406       Wline raxe(data->center(),data->right_v());
00407       data->rotate(raxe, rdist);
00408       data->set_up(data->from() + Wvec::Y());
00409       if (data->right_v() * dd.right_v() < 0)
00410          *data = dd;
00411    }
00412 
00413    return 0;
00414 }
00415 
00416 
00417 int
00418 toggle_buffer(const Event& ev, State *&)
00419 {
00420    BufferRefImage *buf = BufferRefImage::lookup(ev.view());
00421    if (buf)
00422       {
00423          if (buf->is_observing())
00424             {
00425                cerr << "DrawInt: BufferRefImage was observing -- Toggling OFF..\n";
00426                buf->unobserve();
00427             }
00428          else
00429             {
00430                cerr << "DrawInt: BufferRefImage was NOT observing -- Toggling ON...\n";
00431                buf->observe();
00432             }
00433       }
00434 
00435    return 0;
00436 }
00437 
00438 int
00439 toggle_antialias(const Event&, State *&)
00440 {
00441 
00442    int a = VIEW::peek()->get_antialias_enable();
00443 
00444    VIEW::peek()->set_antialias_enable(!a);
00445 
00446    if (VIEW::peek()->get_antialias_enable())
00447       {
00448          WORLD::message(str_ptr("Antialiasing: ENALBED Jitters: ") + 
00449                         str_ptr(VIEW::get_jitter_num(VIEW::peek()->get_antialias_mode())));
00450       }
00451    else
00452       {
00453          WORLD::message(str_ptr("Antialiasing: DISABLED Jitters: ") + 
00454                         str_ptr(VIEW::get_jitter_num(VIEW::peek()->get_antialias_mode())));
00455       }
00456 
00457    return 0;
00458 }
00459 
00460 int
00461 next_antialias(const Event&, State *&)
00462 {
00463 
00464    int m = VIEW::peek()->get_antialias_mode();
00465 
00466    VIEW::peek()->set_antialias_mode((m+1)%VIEW::get_jitter_mode_num());
00467 
00468    if (VIEW::peek()->get_antialias_enable())
00469       {
00470          WORLD::message(str_ptr("Antialiasing: ENALBED Jitters: ") + 
00471                         str_ptr(VIEW::get_jitter_num(VIEW::peek()->get_antialias_mode())));
00472       }
00473    else
00474       {
00475          WORLD::message(str_ptr("Antialiasing: DISABLED Jitters: ") + 
00476                         str_ptr(VIEW::get_jitter_num(VIEW::peek()->get_antialias_mode())));
00477       }
00478 
00479    return 0;
00480 }
00481 
00482 int
00483 freeze_sils(const Event&, State *&)
00484 {
00485    BMESH::_freeze_sils = !BMESH::_freeze_sils;
00486 
00487    return 0;
00488 }
00489 
00490 int
00491 toggle_random_sils(const Event&, State *&)
00492 {
00493    BMESH::toggle_random_sils();
00494    char msg[256];
00495    sprintf(msg, "Randomized silhouettes: %s",
00496            BMESH::_random_sils ? "ON" : "OFF");
00497    WORLD::message(msg);
00498    return 0;
00499 }
00500 
00501 int
00502 toggle_hidden_lines(const Event&, State *&)
00503 {
00504    KeyLineTexture::toggle_show_hidden_lines();
00505 
00506    return 0;
00507 }
00508 
00509 // temporary debugging function
00510 inline bool
00511 is_sec(Bface* f)
00512 {
00513    return f && f->is_secondary();
00514 }
00515 
00516 // temporary debugging class
00517 class BadEdgeFilter : public SimplexFilter {
00518  public:
00519    virtual bool accept(CBsimplex* s) const {
00520       if (!is_edge(s))
00521          return false;
00522       Bedge* e = (Bedge*)s;
00523       return (e->is_multi() && (is_sec(e->f1()) || is_sec(e->f2())));
00524    }
00525 };
00526 
00527 /*****************************************************************
00528  * avg_bface_pix_area()
00529  *
00530  *   stuff for measuring average apparent size of triangles
00531  *   in PIXELS. invoked in debug_cb() below.
00532  *****************************************************************/
00533 inline Wpt
00534 map_centroid(CBface* f, CWpt& eye, CWvec& t)
00535 {
00536    // Return the point along the line of sight that is the
00537    // same distance from the "eye" as the distance to the
00538    // centroid of the face.
00539 
00540    assert(f);
00541    Wpt c = (f->is_quad() ? f->quad_centroid() : f->centroid());
00542    return eye + t*c.dist(eye);
00543 }
00544 
00545 inline double
00546 get_area(CBface* f)
00547 {
00548    return (f->is_quad() ? (f->quad_area()/2) : f->area());
00549 }
00550 
00551 inline double
00552 normalized_pix_area(CBface* f, CWpt& eye, CWvec& t, CWvec& x, CWvec& y)
00553 {
00554    //    c ---------- .                               
00555    //    |            |                                
00556    //    |            |                                
00557    //    |     o      |                                
00558    //    |            |                                
00559    //    |            |                                
00560    //    a ---------- b                                
00561    //
00562    // In above diagram, o is center of screen,
00563    // the square is parallel w/ the image plane
00564    // and has the same area as f. We project
00565    // the corners a, b, c into PIXEL space and
00566    // return the area of the square.
00567 
00568    // XXX - ignoring mesh xform
00569 
00570    if (!(f && f->mesh())) return 0;
00571    Wpt o = map_centroid(f, eye, t);
00572    double s = sqrt(get_area(f))/2;
00573    PIXEL a = (o - (x + y)*s);
00574    PIXEL b = (o + (x - y)*s);
00575    PIXEL c = (o - (x - y)*s);
00576    return fabs(det(b-a, c-a));
00577 }
00578 
00579 inline double
00580 avg_bface_pix_area(BMESH* mesh)
00581 {
00582    if (!mesh) return 0;
00583 
00584    CAMdataptr cam = VIEW::peek_cam()->data();
00585    Wpt eye = cam->from();
00586    Wvec  t = cam->   at_v().normalized();
00587    Wvec  x = cam->right_v().normalized();
00588    Wvec  y = cam->  pup_v().normalized();
00589 
00590    RunningAvg<double> ret(0);
00591    for (int i=0; i<mesh->nfaces(); i++)
00592       ret.add(normalized_pix_area(mesh->bf(i), eye, t, x, y));
00593    return ret.val();
00594 }
00595 
00596 extern bool draw_skin_only;
00597 
00598 inline bool
00599 print_edge_info(CBedge_list& edges)
00600 {
00601    bool ret = false;
00602    err_msg("********");
00603    for (int i=0; i<edges.num(); i++) {
00604       int n = edges[i]->nfaces();
00605       int a = edges[i]->num_all_faces();
00606       err_msg("  %2d: %d top, %d lower", i, n, a - n);
00607 
00608       if (a > n) {
00609          WORLD::show(edges[i]->v1()->loc(), edges[i]->v2()->loc(), 4);
00610          ret = true;
00611       }
00612    }
00613    return ret;
00614 }
00615 
00616 inline void
00617 debug_vis_ref_img(CNDCpt& p)
00618 {
00619    VisRefImage* vis = VisRefImage::lookup();
00620    if (!vis) {
00621       cerr << "debug_vis_ref_img: no vis ref image" << endl;
00622       return;
00623    }
00624    if (vis->need_update()) {
00625       cerr << "debug_vis_ref_img: vis ref image is out of date!" << endl;
00626       return;
00627    }
00628    cerr << "debug_vis_ref_img: NDCpt " << p << endl
00629         << "  val: " << vis->val  (p) << endl
00630         << "  red: " << vis->red  (p) << ", "
00631         << "  green: " << vis->green(p) << ", "
00632         << "  blue: " << vis->blue (p) << ", "
00633         << "  alpha: " << vis->alpha(p) << endl;
00634 }
00635 
00636 int
00637 debug_cb(const Event& ev, State *&)
00638 {
00639    switch (ev._c) {
00640     case 'd': {
00641        FlatShadeTexture::toggle_debug_uv();
00642        WORLD::message(
00643           str_ptr("Debug UV: ") + (FlatShadeTexture::debug_uv() ? "ON" : "OFF")
00644           );
00645        break;
00646     }
00647     default:
00648       ;
00649    }
00650 
00651    return 0;
00652 }
00653 
00654 int
00655 clear_cb(const Event&, State *&)
00656 {
00657 
00658    AlertBox *box = VIEW::peek()->win()->alert_box();
00659 
00660    box->set_title("Warning");
00661    box->set_icon(AlertBox::EXCLAMATION_ICON);
00662    box->add_text("You are about to delete everything!");
00663    box->add_text("Sure?"); 
00664    box->add_button("Yes");
00665    box->add_button("No");
00666    box->set_default(0);
00667 
00668    if (box->display(true, alert_cbs, NULL, NULL, ALERT_CLEAR_CB))
00669       cerr << "clear_cb() - AlertBox displayed.\n";
00670    else
00671       cerr << "clear_cb() - AlertBox **FAILED** to display!!\n";
00672 
00673    return 0;
00674 }
00675 
00676 void 
00677 alert_cbs(void *ptr, void *dptr, int idx, int but_idx)
00678 {
00679    //Dispatch the appropriate alertbox callback...
00680    switch(idx)
00681    {
00682       case ALERT_CLEAR_CB:
00683          if (but_idx == 0)  //yes
00684          {
00685             do_clear();
00686          }
00687          else //no
00688          {
00689             assert(but_idx == 1);
00690             //chill
00691          }
00692       break;
00693       case ALERT_SAVE_JOT_OVERWRITE_CB:
00694          if (but_idx == 0) //yes
00695          {
00696             do_save((char *)dptr);
00697          }
00698          else if (but_idx == 1) //no
00699          {
00700             //try again...
00701             Event e; State *s=NULL;
00702             save_cb(e, s);
00703          }
00704          else //cancel
00705          {
00706             assert(but_idx == 2);
00707             //do nothing
00708          }
00709          //Free up that char buffer...
00710          delete[] (char *)dptr;
00711       break;
00712       case ALERT_SAVE_JOT_FAILED_CB:
00713          assert(but_idx == 0);
00714       break;
00715       case ALERT_LOAD_JOT_FAILED_CB:
00716          assert(but_idx == 0);
00717       break;
00718       default:
00719          assert(0);
00720    }
00721 }
00722 
00723 void 
00724 do_clear()
00725 {
00726    // wipe out everything!!!!!!!!!!!!!!
00727    // except the floor and non-meshes
00728 
00729 //    // clear strokes in current easel
00730 //    if (cur_easel())
00731 //       cur_easel()->removeEasel();
00732 
00733    // copy this list because otherwise it's hard to iterate over it
00734    // without crashing while it's changing radically underfoot:
00735    GELlist drawn = DRAWN;
00736 
00737    // undraw all meshes and draw axes
00738    for (int i=0; i<drawn.num(); i++) {
00739       if (gel_to_bmesh(drawn[i]))
00740          // XXX -- should create undoable multi command
00741          WORLD::undisplay(drawn[i]);
00742    }
00743 }
00744 
00745 int
00746 save_cb(const Event&, State *&)
00747 {
00748 
00749    FileSelect *sel = VIEW::peek()->win()->file_select();
00750 
00751    sel->set_title("Save Scene");
00752    sel->set_action("Save");
00753    sel->set_icon(FileSelect::SAVE_ICON);
00754    sel->set_path(".");
00755    sel->set_filter("*.jot");
00756 
00757    str_ptr fname = ((IOManager::basename() != NULL_STR) ? (IOManager::basename()) : (str_ptr("out"))) + ".jot";
00758 
00759    sel->set_file(fname);
00760    
00761 
00762    if (sel->display(true, file_cbs, NULL, FILE_SAVE_JOT_CB))
00763       cerr << "save_cb() - FileSelect displayed.\n";
00764    else
00765       cerr << "save_cb() - FileSelect **FAILED** to display!!\n";
00766 
00767    return 0;
00768 }
00769 
00770 
00771 int
00772 load_cb(const Event&, State *&)
00773 {
00774 
00775    FileSelect *sel = VIEW::peek()->win()->file_select();
00776 
00777    sel->set_title("Load Scene");
00778    sel->set_action("Load");
00779    sel->set_icon(FileSelect::LOAD_ICON);
00780    sel->set_path(".");
00781    sel->set_file("");
00782    sel->set_filter("*.jot");
00783    
00784 
00785    if (sel->display(true, file_cbs, NULL, FILE_LOAD_JOT_CB))
00786       cerr << "load_cb() - FileSelect displayed.\n";
00787    else
00788       cerr << "load_cb() - FileSelect **FAILED** to display!!\n";
00789 
00790    return 0;
00791 }
00792 
00793 void 
00794 file_cbs(void *ptr, int idx, int action, str_ptr path, str_ptr file)
00795 {
00796    str_ptr fullpath = path + file;
00797    //Dispatch the appropriate fileselect callback...
00798    switch(idx)
00799    {
00800       case FILE_SAVE_JOT_CB:
00801          if (action == FileSelect::OK_ACTION)
00802          {
00803             bool exists; FILE *foo; exists=!!(foo=fopen(**(fullpath),"r"));if(exists)fclose(foo); 
00804 
00805             if (!exists)
00806             {
00807                do_save(fullpath);
00808             }
00809             else
00810             {
00811                AlertBox *box = VIEW::peek()->win()->alert_box();
00812 
00813                box->set_title("Warning");
00814                box->set_icon(AlertBox::EXCLAMATION_ICON);
00815                box->add_text("Destination exists:");
00816                box->add_text(fullpath);
00817                box->add_text("Overwrite?"); 
00818                box->add_button("Yes");
00819                box->add_button("No");
00820                box->add_button("Cancel");
00821                box->set_default(0);
00822                
00823                //Can't send the fullpath str_ptr in a void * because
00824                //the it vanishes when this function end, but before
00825                //the alert box generates a callback (with the void *
00826                //passed along for use). We'll alloc a string instead,
00827                //and free it in the callback...
00828 
00829                char *fp = new char[(int)fullpath.len()+1]; assert(fp); strcpy(fp,**fullpath); 
00830 
00831                if (box->display(true, alert_cbs, ptr, fp, ALERT_SAVE_JOT_OVERWRITE_CB))
00832                   cerr << "clear_cb() - AlertBox displayed.\n";
00833                else
00834                   cerr << "clear_cb() - AlertBox **FAILED** to display!!\n";
00835             }
00836          }
00837       break;
00838       case FILE_LOAD_JOT_CB:
00839          if (action == FileSelect::OK_ACTION)
00840          {
00841             do_load(fullpath);
00842          }
00843       break;
00844       default:
00845          assert(0);
00846    }
00847 }
00848 
00849 void 
00850 do_save(str_ptr fullpath)
00851 {
00852    SAVEobs::save_status_t status;
00853 
00854    cerr << "\ndo_save() - Saving...\n";
00855 
00856    NetStream s(fullpath, NetStream::ascii_w); 
00857 
00858    int old_cursor = VIEW::peek()->get_cursor();
00859    VIEW::peek()->set_cursor(WINSYS::CURSOR_WAIT);
00860    SAVEobs::notify_save_obs(s, status, true, true);   
00861    VIEW::peek()->set_cursor(old_cursor);
00862 
00863    if (status == SAVEobs::SAVE_ERROR_NONE)
00864    {
00865       cerr << "do_save() - ...done.\n";
00866 
00867       WORLD::message(str_ptr("Saved '") + fullpath + "'");
00868    }
00869    else
00870    {
00871       cerr << "do_save() - ...aborted!!!" << endl;
00872       
00873       WORLD::message(str_ptr("Problem saving '") + fullpath + "'");
00874 
00875       AlertBox *box = VIEW::peek()->win()->alert_box();
00876 
00877       box->set_title("Warning");
00878       box->set_icon(AlertBox::WARNING_ICON);
00879       box->add_text("Problem saving scene to file:");
00880       box->add_text(fullpath);
00881       box->add_button("OK");
00882       box->set_default(0);
00883 
00884       switch(status)
00885       {
00886          case SAVEobs::SAVE_ERROR_STREAM:
00887             box->add_text("Couldn't create output stream.");
00888          break;
00889          case SAVEobs::SAVE_ERROR_WRITE:
00890             box->add_text("Error occurred during write.");
00891          break;
00892          case SAVEobs::SAVE_ERROR_CWD:
00893             box->add_text("Error changing current working directory.");
00894          break;
00895          default:
00896             assert(0);
00897       }
00898 
00899       if (box->display(true, alert_cbs, NULL, NULL, ALERT_SAVE_JOT_FAILED_CB))
00900          cerr << "do_save() - AlertBox displayed.\n";
00901       else
00902          cerr << "do_save() - AlertBox **FAILED** to display!!\n";
00903    }
00904 
00905 }
00906 
00907 void 
00908 do_load(str_ptr fullpath)
00909 {
00910    LOADobs::load_status_t status;
00911 
00912    cerr << "\ndo_load() - Loading...\n";
00913 
00914    NetStream s(fullpath, NetStream::ascii_r);
00915 
00916    // Clear the scene first, then hope nothing goes wrong in
00917    // loading cuz if it does we should then unclear the
00918    // scene, but we're not prepared to do that...
00919    do_clear();
00920    
00921    int old_cursor = VIEW::peek()->get_cursor();
00922    VIEW::peek()->set_cursor(WINSYS::CURSOR_WAIT);
00923    LOADobs::notify_load_obs(s, status, true, true);
00924    VIEW::peek()->set_cursor(old_cursor);
00925 
00926    if (status == LOADobs::LOAD_ERROR_NONE) {
00927       cerr << "do_load() - ...done.\n";
00928 
00929       WORLD::message(str_ptr("Loaded '") + fullpath + "'");
00930 
00931    } else {
00932       // XXX  - should unclear the scene to restore current state
00933       //        to what it was before the load attempt.
00934 
00935       cerr << "do_load() - ...aborted!!!" << endl;
00936       
00937       WORLD::message(str_ptr("Problem loading '") + fullpath + "'");
00938 
00939       AlertBox *box = VIEW::peek()->win()->alert_box();
00940 
00941       box->set_title("Warning");
00942       box->set_icon(AlertBox::WARNING_ICON);
00943       box->add_text("Problem loading scene from file:");
00944       box->add_text(fullpath);
00945       box->add_button("OK");
00946       box->set_default(0);
00947 
00948       switch(status) {
00949        case LOADobs::LOAD_ERROR_STREAM:
00950          box->add_text("Couldn't create input stream.");
00951          break;
00952        case LOADobs::LOAD_ERROR_JOT:
00953          box->add_text("The anticipated #jot header was found.");
00954          box->add_text("Error occurred while reading remaining file.");
00955          break;
00956        case LOADobs::LOAD_ERROR_CWD:
00957          box->add_text("Error changing current working directory.");
00958          break;
00959        case LOADobs::LOAD_ERROR_AUX:
00960          box->set_icon(AlertBox::INFO_ICON);
00961          box->add_text("Failed to load as jot format file.");
00962          box->add_text("Succeeded with an auxillary file parser!");
00963          break;
00964        case LOADobs::LOAD_ERROR_READ:
00965          box->add_text("Error occurred during read.");
00966          break;
00967        default:
00968          assert(0);
00969       }
00970 
00971       if (box->display(true, alert_cbs, NULL, NULL, ALERT_LOAD_JOT_FAILED_CB))
00972          cerr << "do_save() - AlertBox displayed.\n";
00973       else
00974          cerr << "do_save() - AlertBox **FAILED** to display!!\n";
00975    }
00976 }
00977 
00978 int
00979 animation_keys(const Event &e, State *&s)
00980 {
00981    //Here we handle the keys for both the Recorder and Animator
00982    
00983    //*It cannot be the case that both are 'ON' simultaneously*
00984 
00985    assert(!(VIEW::peek()->recorder()->on() && VIEW::peek()->animator()->on()));
00986 
00987    //If they're both 'off' just check the activation keys
00988    if(!VIEW::peek()->recorder()->on() && !VIEW::peek()->animator()->on())
00989       {
00990          switch (e._c) 
00991             {
00992              case 'C': 
00993                return toggle_recorder(e,s);
00994                break;
00995              case 'X':
00996                VIEW::peek()->animator()->toggle_activation();
00997                break;
00998             };
00999       }
01000    //If the recorder's on just check its keys
01001    else if(VIEW::peek()->recorder()->on())
01002       {
01003          switch (e._c) 
01004             {
01005              case 'X': 
01006                WORLD::message("Deactivate recorder first!");
01007                break;
01008              case 'C': 
01009                return toggle_recorder(e,s);
01010                break;
01011              case '/':
01012                return rec_play(e,s);
01013                break;
01014              case '*':
01015                return rec_rec(e,s);
01016                break;
01017              case '-':
01018                return rec_stop(e,s);
01019                break;
01020              case '+':
01021                return rec_pause(e,s);
01022                break;
01023             };
01024       }
01025    //If the animators's on just check its keys
01026    else if(VIEW::peek()->animator()->on())
01027       {
01028          switch (e._c) 
01029             {
01030              case 'C': 
01031                WORLD::message("Deactivate recorder first!");
01032                break;
01033              case 'X': 
01034                VIEW::peek()->animator()->toggle_activation();
01035                break;
01036              case '/':
01037                VIEW::peek()->animator()->press_play();
01038                break;
01039              case '*':
01040                VIEW::peek()->animator()->press_render();
01041                break;
01042              case '-':
01043                VIEW::peek()->animator()->press_sync();
01044                break;
01045              case '+':
01046                VIEW::peek()->animator()->press_stop();
01047                break;
01048              case '5':
01049                VIEW::peek()->animator()->press_beginning();
01050                break;
01051              case '4':
01052                VIEW::peek()->animator()->press_step_rev();
01053                break;
01054              case '6':
01055                VIEW::peek()->animator()->press_step_fwd();
01056                break;
01057              case '2':
01058                VIEW::peek()->animator()->press_jog_rev();
01059                break;
01060              case '8':
01061                VIEW::peek()->animator()->press_jog_fwd();
01062                break;
01063             };
01064       }
01065    else
01066       {
01067          //HUH!?
01068          assert(0);
01069          return 0;
01070       }
01071 
01072    return 0;
01073 }
01074 
01075 int
01076 render_mode(const Event &e, State *&s)
01077 {
01078    switch (e._c) 
01079       {
01080        case '!': 
01081          WORLD::message("Rendering ALL Objects.");
01082          VIEW::peek()->set_render_mode(VIEW::NORMAL_MODE);
01083          break;
01084        case '@':
01085          WORLD::message("Rendering OPAQUE Objects.");
01086          VIEW::peek()->set_render_mode(VIEW::OPAQUE_MODE);
01087          break;
01088        case '#':
01089          WORLD::message("Rendering TRANSPARENT Objects.");
01090          VIEW::peek()->set_render_mode(VIEW::TRANSPARENT_MODE);
01091          break;
01092        default:
01093          //huh!?
01094          break;
01095       };
01096 
01097    return 0;
01098 }
01099 
01100 int 
01101 toggle_recorder (const Event &, State *&)
01102 {
01103    Recorder* _rec =VIEW::peek()->recorder();
01104    if ( _rec == NULL)
01105       return 0;
01106    if (_rec->on())
01107       _rec->deactivate();
01108    else {
01109       if (_rec->get_ui() == NULL) {
01110          _rec->set_ui(new RecorderUI(_rec));
01111          _rec->_name_buf = str_ptr ("default");
01112          _rec->new_path();
01113       }
01114       _rec->activate();
01115    }
01116    return 1;
01117 }
01118 
01119 int 
01120 rec_play (const Event &, State *&)
01121 {
01122   
01123    Recorder* _rec = NULL;
01124    if ( ( _rec =VIEW::peek()->recorder()) == NULL ) return 0;
01125    _rec->rec_play();
01126    return 1;
01127 }
01128 
01129 int 
01130 rec_rec (const Event &, State *&)
01131 {
01132   
01133    Recorder* _rec = NULL;
01134    if ( ( _rec =VIEW::peek()->recorder()) == NULL ) return 0;
01135    _rec->rec_record();
01136    return 1;
01137 }
01138 
01139 int 
01140 rec_stop (const Event &, State *&)
01141 {
01142   
01143    Recorder* _rec = NULL;
01144    if ( ( _rec =VIEW::peek()->recorder()) == NULL ) return 0;
01145    _rec->rec_stop();
01146    return 1;
01147 }
01148 
01149 int 
01150 rec_pause (const Event &, State *&)
01151 {
01152   
01153    Recorder* _rec = NULL;
01154    if ( ( _rec =VIEW::peek()->recorder()) == NULL ) return 0;
01155    _rec->rec_pause();
01156    return 1;
01157 }
01158 
01159 int
01160 set_pen(const Event & ev, State *&)
01161 {
01162    
01163    if (ev._c == '.') 
01164    {
01165       BaseJOTapp::instance()->next_pen();
01166    }
01167    else if (ev._c == ',') 
01168    {
01169       BaseJOTapp::instance()->prev_pen();
01170    }
01171 
01172    VIEW::peek()->set_focus();
01173 
01174    return 0;
01175 }
01176 
01177 int
01178 undo_redo(const Event &e, State *&)
01179 {
01180    switch (e._c) {
01181     case '\n':
01182     case '\r':
01183       WORLD::redo();
01184       break;
01185     case '\x8' :
01186     case '\x7f':
01187       WORLD::undo();
01188       break;
01189     default:
01190       err_msg("undo_redo: unknown key: %d (ASCII decimal code)",
01191               int(e._c));
01192    }
01193 
01194    return 0;
01195 }
01196 
01197 
01198 int
01199 quit(const Event&, State *&)
01200 {
01201    if (Config::get_var_bool("DEBUG_STRPOOL",false))
01202       err_msg("strpool load factor: %f", STR::load_factor());
01203 
01204    WORLD::Quit();
01205 
01206    return 0;
01207 }
01208 
01209 int
01210 refine(const Event&, State *&)
01211 {
01212    BMESH* m = find_ctrl_mesh();
01213    if (!m || !LMESH::isa(m))
01214       return 0;
01215 
01216    LMESH* ctrl_mesh = (LMESH*)m;
01217 
01218    if (Config::get_var_bool("DEBUG_VOLUME_PRESERVATION",false))
01219       cerr << "Current mesh volume=" << ctrl_mesh->volume() <<endl;
01220 
01221    if (ctrl_mesh && ctrl_mesh->loc_calc() && **ctrl_mesh->loc_calc()->name())
01222       WORLD::message(**ctrl_mesh->loc_calc()->name());
01223 
01224    ctrl_mesh->refine();
01225    if (Config::get_var_bool("DEBUG_VOLUME_PRESERVATION",false))
01226       cerr << "Refined mesh volume=" << ctrl_mesh->volume() <<endl;
01227 
01228    return 0;
01229 }
01230 
01231 int
01232 cycle_subdiv_loc_calc(const Event&, State *&)
01233 {
01234    BMESH* m = find_ctrl_mesh();
01235    if (!m || !LMESH::isa(m))
01236       return 0;
01237 
01238    static int k=0;
01239    LMESH* ctrl_mesh = (LMESH*)m;
01240    SubdivLocCalc* calc = 0;
01241    switch (++k % 3) {
01242     case 0: calc = new LoopLoc;           break;
01243     case 1: calc = new Hybrid2Loc;        break; 
01244     case 2: calc = new HybridVolPreserve; break;
01245    }
01246    assert(calc != 0);
01247    ctrl_mesh->set_subdiv_loc_calc(calc);
01248    ctrl_mesh->update();
01249    WORLD::message(calc->name() + " scheme in use");
01250 
01251    return 0;
01252 }
01253 
01254 int
01255 clear_selections(const Event&, State *&)
01256 {
01257    MeshGlobal::deselect_all_edges();
01258    MeshGlobal::deselect_all_faces();
01259    return 0;
01260 }
01261 
01262 
01263 int
01264 unrefine(const Event&, State *&)
01265 {
01266    BMESH* m = find_ctrl_mesh();
01267    if (!m || !LMESH::isa(m))
01268       return 0;
01269 
01270    ((LMESH*)m)->unrefine();
01271 
01272    return 0;
01273 }
01274 
01275 inline BMESHptr
01276 control_mesh(CBMESHptr& m)
01277 {
01278    // return the control mesh for the given mesh.
01279    // if it's not a LMESH just return the mesh itself.
01280    return (m && LMESH::isa(&*m)) ? BMESHptr(((LMESH*)&*m)->control_mesh()) : m;
01281 }
01282 
01283 int 
01284 toggle_sil_frame(const Event&, State *&)
01285 {
01286    BMESH* mesh = find_ctrl_mesh();
01287    if (!mesh)
01288       return 0;
01289 
01290    mesh->toggle_render_style(SilFrameTexture::static_name());
01291 
01292    return 0;
01293 }
01294 
01295 
01296 int
01297 toggle_transp(const Event&e, State *&)
01298 {
01299    RAYhit ray(VisRefImage::get_cursor());
01300    e.view()->intersect(ray);
01301    
01302    if (ray.success() && ray.appear() ) {
01303       if (ray.appear()->has_transp() ) {
01304          ray.appear()->unset_transp();
01305       }
01306       else {
01307          ray.appear()->set_transp(.5);
01308       }
01309    }
01310    
01311    return 0;
01312 }
01313 
01314 int
01315 write(const Event&, State *&)
01316 {
01317    BMESH* mesh = find_mesh();
01318 
01319    if (!mesh) {
01320       cerr << "write - No mesh... aborting.\n";
01321       return 0;
01322    }
01323 
01324    mesh->print();
01325 
01326    str_ptr fname = "out.sm";   
01327 
01328    if (mesh->write_file(**fname)) {
01329       WORLD::message(str_ptr("Wrote mesh: ") + fname);
01330    } else {
01331       WORLD::message(str_ptr("Failed to write mesh: ") + fname);
01332    }
01333 
01334    return 1;
01335 }
01336 
01337 int
01338 print_mesh(const Event&, State *&)
01339 {
01340    BMESH* mesh = find_mesh();
01341    if (mesh)
01342       mesh->print();
01343    return 0;
01344 }
01345 
01346 int
01347 write_xformed(const Event&, State *&)
01348 {
01349    BMESH* mesh = find_mesh();
01350    if (!mesh) {
01351       return 0;
01352    }
01353 
01354    //Same as above, but it applies the xform
01355    //to the mesh before saving it.
01356 
01357    MOD::tick();
01358    mesh->transform(mesh->xform(), MOD());
01359 
01360    // write it
01361    if (mesh->write_file("out.sm")) {
01362       WORLD::message("Wrote ***TRANSFORMED*** mesh to out.sm");
01363    } else {
01364       WORLD::message("Couldn't write mesh file: out.sm");
01365    }
01366 
01367    MOD::tick();
01368    mesh->transform(mesh->inv_xform(), MOD());
01369 
01370    return 1;
01371 }
01372 
01373 int
01374 save_config(const Event &e, State *&)
01375 {
01376    bool ret;
01377    
01378    ret = Config::save_config(Config::JOT_ROOT() + "jot.cfg");
01379 
01380    if (ret)
01381       WORLD::message(str_ptr("Wrote config to ") + Config::JOT_ROOT() + "jot.cfg");
01382    else
01383       WORLD::message(str_ptr("FAILED!! Writing config to ") + Config::JOT_ROOT() + "jot.cfg");
01384 
01385    return 1;
01386 }
01387 
01388 
01389 /*************************************************************************
01390  * Function Name: clear_creases
01391  * Parameters: const Event&, State *&
01392  * Returns: int
01393  * Effects: 
01394  *************************************************************************/
01395 int
01396 clear_creases(const Event&, State*&)
01397 {
01398    BMESH* mesh = find_ctrl_mesh();
01399    if (!mesh)
01400       return 0;
01401 
01402    WORLD::message("Clearing creases");
01403    mesh->clear_creases();
01404 
01405    return 0;
01406 }
01407 
01408 
01409 int
01410 toggle_no_text(const Event&, State*&)
01411 {
01412    if (!TEXT2D::toggle_suppress_draw())
01413       WORLD::message("Text on");
01414       
01415    return 0;
01416 }
01417 
01418 /*************************************************************************
01419  * Function Name: recreate_creases
01420  * Parameters: const Event&, State *&
01421  * Returns: int
01422  * Effects: 
01423  *************************************************************************/
01424 int
01425 recreate_creases(const Event&, State *&)
01426 {
01427    BMESH* mesh = find_ctrl_mesh();
01428    if (!mesh)
01429       return 0;
01430 
01431    WORLD::message("Recreating creases");
01432    for (int k = mesh->nedges()-1; k>=0; k--)
01433       mesh->be(k)->compute_crease(0.5);
01434    mesh->changed();
01435 
01436    return 0;
01437 }
01438 
01439 int
01440 toggle_crease(const Event &, State *&)
01441 {
01442    VisRefImage *vis_ref = VisRefImage::lookup(VIEW::peek());
01443    vis_ref->update();
01444    Wpt obj_pt;
01445    Bface* face = vis_ref->intersect(VisRefImage::get_cursor(), obj_pt);
01446 
01447    if (face) {
01448       Wvec bc;
01449       face->project_barycentric(obj_pt, bc);
01450       int i=0;
01451       if (bc[0] < bc[1])
01452          i = (bc[0] < bc[2]) ? 0 : 2;
01453       else
01454          i = (bc[1] < bc[2]) ? 1 : 2;
01455       Bvert *vert = face->v(i+1);
01456       Bedge *edge = face->opposite_edge(vert);
01457       
01458       edge->set_crease(!edge->is_crease());
01459       face->mesh()->changed(); 
01460    }
01461    return 0;
01462 }
01463 
01464 int
01465 toggle_curvature_ui(const Event&, State *&)
01466 {
01467    
01468    if(CurvatureUISingleton::Instance().is_vis(VIEW::peek())){
01469       
01470       CurvatureUISingleton::Instance().hide(VIEW::peek());
01471       
01472    } else {
01473       
01474          CurvatureUISingleton::Instance().show(VIEW::peek());
01475          VIEW::peek()->set_focus();
01476          
01477    }
01478 
01479    return 0;
01480    
01481 }
01482 
01483 // end of file jot.C

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