//***************************************************************************************** // Truevision - a 3d modeler for gnome and povray // // prism.cc // // Vincent LE PRINCE // Copyright (C) 2000-2005 Vincent LE PRINCE // This file is part of the TRUEVISION Package // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ //******************************************************************************************* #include "include/prism.h" #include "include/viewmanager.h" #include "include/objectlist.h" #include "include/tvio.h" #include "include/preferences.h" #include "include/utils3d.h" // Prism preview subdivisions const int PrismSubdivision = 12; const int PrismSplineSubdivision = 10; /* Some files do not define M_PI... */ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif // Spline type const int prism_spline_type_num = 4; const gchar * prism_spline_type_list[prism_spline_type_num] = { N_("Linear"), N_("Quadratic"), N_("Cubic"), N_("Bezier") }; const char *prism_spline_type_keys[prism_spline_type_num] = { "linear_spline", "quadratic_spline", "cubic_spline", "bezier_spline" }; // Sweep type const int sweep_type_num = 2; const gchar * sweep_type_list[ sweep_type_num ] = { N_("Linear"), N_("Conic") }; const char *prism_sweep_type_keys[ sweep_type_num ] = { "linear_sweep", "conic_sweep" }; //************************************** // Prism - Constructeur //************************************** Prism::Prism( app_objs *appref ) : Object3D_with_material( appref ) { type = TV_OBJ3D_PRISM; category = TV_OBJ3D_OBJECTS; set_name( "Prism" ); spline_edit_box = NULL; in_undo = false; in_update = false; // Spline Spline2D *spline = new Spline2D( TV_SPLINE2D_LINEAR, PrismSplineSubdivision ); spline->set_for_lathe( false ); spline->add_point( 0.2, 0.2, -0.1, 0.1, 0.1, -0.1 ); spline->add_point( 0.2, -0.2 , 0.1, 0.1, -0.1, -0.1 ); spline->add_point( -0.2, -0.2, 0.1, -0.1, -0.1, 0.1 ); spline->add_point( -0.2, 0.2, -0.1, -0.1, 0.1,0.1 ); splines.push_back( spline ); // Base location = new ObjParam_point( N_("Location"), "LOC", NULL, app_ref, true ); location->set( 0, 0, 0 ); size = new ObjParam_scale( N_("Size"), "SIZE", NULL, app_ref, true ); size->set( 1, 1, 1 ); rotation = new ObjParam_rotation( N_("Rotation"), "ROT", NULL, app_ref, true ); rotation->set( 0, 0, 0 ); edit = new ObjParam_bool_activator( N_("Edit"), "EDIT", N_("Edit Prism"), app_ref, true, true ); sturm = new ObjParam_bool( N_("Sturm"), "STURM", N_("Use alternative root solver"), app_ref, true, false ); spline_type = new ObjParam_option_combo( N_("Spline mode"), "SPLINET", NULL, app_ref, true ); spline_type->set_list( prism_spline_type_list, prism_spline_type_num, 0 ); sweep_type = new ObjParam_option_combo( N_("Sweep mode"), "SWEEP", NULL, app_ref, true ); sweep_type->set_list( sweep_type_list, sweep_type_num, 0 ); open = new ObjParam_bool( N_("Open"), "OPEN", N_("Open caps"), app_ref, true, false ); height1 = new ObjParam_float( N_("Height 1"), "HEI1", N_("Height of base end"), app_ref, true, 0 ); height1->set_range( 50, -50, 0.1, 5 ); height2 = new ObjParam_float( N_("Height 2"), "HEI2", N_("Height of cap end"), app_ref, true, 0.2 ); height2->set_range( 50, -50, 0.1, 5 ); current_point_num = new ObjParam_int( N_("Point #"), "PNUM", NULL, app_ref, true, 1 ); current_point_num->set_range( spline->size(), 1, 1 ); current_point_num->set_send_undo( false ); current_spline_num = new ObjParam_int( N_("Spline #"), "SNUM", NULL, app_ref, true, 1 ); current_spline_num->set_range( splines.size(), 1, 1 ); current_spline_num->set_send_undo( false ); current_point = new ObjParam_point_2d( N_("Position"), "POS", NULL, app_ref, false, true ); current_point->set_send_undo( false ); current_point_ctrl1 = new ObjParam_point_2d( N_("Control1"), "CTRL1", NULL, app_ref, false, true ); current_point_ctrl1->set_send_undo( false ); current_point_ctrl2 = new ObjParam_point_2d( N_("Control2"), "CTRL2", NULL, app_ref, false, true ); current_point_ctrl2->set_send_undo( false ); } Prism::Prism( Prism & ref ) : Object3D_with_material( ref ) { in_undo = false; spline_edit_box = NULL; in_update = false; location = new ObjParam_point( *ref.location ); size = new ObjParam_scale( *ref.size ); rotation = new ObjParam_rotation( *ref.rotation ); edit = new ObjParam_bool_activator( *ref.edit ); sturm = new ObjParam_bool( *ref.sturm ); spline_type = new ObjParam_option_combo( *ref.spline_type ); sweep_type = new ObjParam_option_combo( *ref.sweep_type ); current_point_num = new ObjParam_int( *ref.current_point_num ); current_spline_num = new ObjParam_int( *ref.current_spline_num ); current_point = new ObjParam_point_2d( *ref.current_point ); current_point_ctrl1 = new ObjParam_point_2d( *ref.current_point_ctrl1 ); current_point_ctrl2 = new ObjParam_point_2d( *ref.current_point_ctrl2 ); open = new ObjParam_bool( *ref.open ); height1 = new ObjParam_float( *ref.height1 ); height2 = new ObjParam_float( *ref.height2 ); for ( unsigned int i = 0 ; i < ref.splines.size() ; i++ ) splines.push_back( ref.splines[i]->auto_copy() ); current_point_num->set_range( splines[ current_spline_num->value() - 1 ]->size(), 1, 1 ); } Prism::~Prism() { delete location; delete size; delete rotation; delete edit; delete sturm; delete spline_type; delete sweep_type; delete current_point_num; delete current_spline_num; delete current_point; delete current_point_ctrl1; delete current_point_ctrl2; splines.clear(); delete open; delete height1; delete height2; } //************************************** // Display // Dessin de la boite //************************************** void Prism::display( glview *view, bool set_col ) { if ( hidden->value() ) return; if ( location->changed() || size->changed() || rotation->changed() || edit->changed() || spline_type->changed() \ || current_point_num->changed() || current_point->changed() || current_point_ctrl1->changed() || current_point_ctrl1->changed() \ || sweep_type->changed() || open->changed() || height1->changed() || height2->changed() || current_spline_num->changed()) list.invalidate(); PREF_DEF int quality = PrismSplineSubdivision + pref->preview_quality->value()*4; // Mode Edition // Sans liste et avec picking pour les points, mais pas pour les lignes if ( edit->value() ) { OBJLIST_DEF int selected_point = current_point_num->value() - 1; set_color(); glPushMatrix(); int mode; pick_name = -1; for ( unsigned int sp = 0 ; sp < splines.size() ; sp++ ) { Spline2D *spline = splines[sp]; glGetIntegerv( GL_RENDER_MODE, &mode ); spline->set_type( (SplineType)spline_type->value() ); spline->set_subdivisions( quality ); // Lines ( linear, quadradtic, cubic or bezier... ) if ( mode != GL_SELECT ) // Draw all { spline->gl_display_segments(); if ( spline_type->value() != (int)TV_SPLINE2D_LINEAR ) { glEnable( GL_LINE_STIPPLE ); glLineStipple( 1, 0xAAA ); glBegin( GL_LINES ); if ( spline_type->value() == (int)TV_SPLINE2D_QUADRATIC ) { spline->display_point( 0 ); spline->display_point( 1 ); } if ( spline_type->value() == (int)TV_SPLINE2D_CUBIC ) { int size = spline->size(); spline->display_point( 0 ); spline->display_point( 1 ); spline->display_point( size-2 ); spline->display_point( size-1 ); } if ( spline_type->value() == (int)TV_SPLINE2D_BEZIER && sp == (unsigned)(current_spline_num->value() - 1) ) { spline->display_point( selected_point ); spline->display_point_ctrl1( selected_point ); spline->display_point( selected_point ); spline->display_point_ctrl2( selected_point ); } glEnd(); glDisable( GL_LINE_STIPPLE ); } } // end non select mode // Draw Points ( much, much easier :) int size = spline->size(); for ( int i = 0 ; i < size ; i++ ) { int pick = objlist->get_pick_name(); if ( pick_name == -1 ) pick_name = pick; glLoadName( pick ); if ( i != selected_point || sp != (unsigned)(current_spline_num->value() - 1)) { glBegin( GL_POINTS ); spline->display_point(i); glEnd(); } else { if ( selected_ctrl == 0 ) glColor3f( 1.0, 0, 0 ); glPointSize( 6 ); glBegin( GL_POINTS ); spline->display_point( selected_point ); glEnd(); set_color(); if ( spline_type->value() == TV_SPLINE2D_BEZIER ) { pick = objlist->get_pick_name(); glLoadName( pick ); if ( selected_ctrl == 1 ) glColor3f( 1.0, 0, 0 ); glBegin( GL_POINTS ); spline->display_point_ctrl1( selected_point ); glEnd(); set_color(); pick = objlist->get_pick_name(); glLoadName( pick ); if ( selected_ctrl == 2 ) glColor3f( 1.0, 0, 0 ); glBegin( GL_POINTS ); spline->display_point_ctrl2( selected_point ); glEnd(); } glPointSize( 4 ); set_color(); } last_pick_name = pick; } glPopMatrix(); list.end(); } } else // Prism opengl drawing // No point selection, we got a list { Object3D::display( view ); if ( set_col ) set_color(); if ( ! list.exec() ) { // mise à zero des parametres location->unchange(); size->unchange(); rotation->unchange(); edit->unchange(); spline_type->unchange(); sweep_type->unchange(); current_point_num->unchange(); current_spline_num->unchange(); current_point->unchange(); current_point_ctrl1->unchange(); current_point_ctrl2->unchange(); open->unchange(); height1->unchange(); height2->unchange(); // creation de la liste si necessaire list.begin(); glPushMatrix(); // Position et direction gfloat x, y, z; gfloat a, b, c; location->get( x, y, z ); glTranslatef( x, y, z ); rotation->gl_rotate(); size->get( a, b, c ); glScalef( a, b, c ); float *xcoords, *ycoords, *prev_xcoords=NULL, *prev_ycoords = NULL; int ptnum = 0, prev_ptnum=0; bool pair = true; float hei1 = height1->value(); float hei2 = height2->value(); for ( unsigned int sp = 0 ; sp < splines.size() ; sp++ ) { Spline2D *spline = splines[sp]; spline->set_type( (SplineType)spline_type->value() ); spline->set_subdivisions( quality ); spline->get_segments( ptnum, xcoords, ycoords ); for ( int i = 0 ; i < ptnum-1 ; i++ ) { glBegin( GL_QUAD_STRIP ); for ( int slice = 0 ; slice < ptnum ; slice++ ) { if ( sweep_type->value() == 0 ) { if ( slice == 0) get_normal( xcoords[slice], hei1, ycoords[slice], xcoords[slice+1], hei2, ycoords[ slice+1] , xcoords[slice], hei2, ycoords[ slice ], pair ); else if ( slice < ptnum - 1 ) get_normal( xcoords[slice-1], hei1, ycoords[slice-1], xcoords[slice+1], hei2, ycoords[ slice+1] , xcoords[slice-1], hei2, ycoords[ slice-1 ], pair ); glVertex3f( xcoords[slice], hei1, ycoords[slice] ); glVertex3f( xcoords[slice], hei2, ycoords[slice] ); } else { if ( slice == 0) get_normal( xcoords[slice], hei1, ycoords[slice], xcoords[slice+1], hei2, ycoords[ slice+1] , xcoords[slice], hei2, ycoords[ slice ], pair ); else if ( slice < ptnum - 1 ) get_normal(0, hei1, 0, xcoords[slice+1], hei2, ycoords[ slice+1] , xcoords[slice-1], hei2, ycoords[ slice-1 ], pair ); glVertex3f( hei1*xcoords[slice], hei1, hei1*ycoords[slice] ); glVertex3f( hei2*xcoords[slice], hei2, hei2*ycoords[slice] ); } } glEnd(); } if ( !open->value() ) { if ( pair && sp == splines.size()-1 ) { if ( sweep_type->value() == 0 ) { glBegin( GL_TRIANGLE_FAN ); if ( hei1 < hei2 ) glNormal3f( 0, -1, 0 ); else glNormal3f( 0, 1, 0 ); glVertex3f( 0, hei1, 0 ); for ( int i = 0 ; i < ptnum ; i++ ) glVertex3f( xcoords[i], hei1, ycoords[i] ); glEnd(); } glBegin( GL_TRIANGLE_FAN ); if ( hei1 < hei2 ) glNormal3f( 0, 1, 0 ); else glNormal3f( 0, -1, 0 ); glVertex3f( 0, hei2, 0 ); if ( sweep_type->value() == 0 ) for ( int i = 0 ; i < ptnum ; i++ ) glVertex3f( xcoords[i], hei2, ycoords[i] ); else for ( int i = 0 ; i < ptnum ; i++ ) glVertex3f( hei2*xcoords[i], hei2, hei2*ycoords[i] ); glEnd(); } if ( !pair ) { if ( sweep_type->value() == 0 ) { glBegin( GL_QUAD_STRIP ); if ( hei1 < hei2 ) glNormal3f( 0, -1, 0 ); else glNormal3f( 0, 1, 0 ); for ( int i = 0 ; i < ptnum && i < prev_ptnum ; i++ ) { glVertex3f( xcoords[i], hei1, ycoords[i] ); glVertex3f( prev_xcoords[i], hei1, prev_ycoords[i] ); } glEnd(); if ( ptnum < prev_ptnum ) { glBegin( GL_TRIANGLE_FAN ); glVertex3f( xcoords[ptnum-1], hei1, ycoords[ptnum-1] ); for ( int i = ptnum-1 ; i < prev_ptnum ; i++ ) glVertex3f( prev_xcoords[i], hei1, prev_ycoords[i] ); glEnd(); } if ( ptnum > prev_ptnum ) { glBegin( GL_TRIANGLE_FAN ); glVertex3f( prev_xcoords[prev_ptnum-1], hei1, prev_ycoords[prev_ptnum-1] ); for ( int i = prev_ptnum-1 ; i < ptnum ; i++ ) glVertex3f( xcoords[i], hei1, ycoords[i] ); glEnd(); } } glBegin( GL_QUAD_STRIP ); if ( hei1 < hei2 ) glNormal3f( 0, 1, 0 ); else glNormal3f( 0, -1, 0 ); for ( int i = 0 ; i < ptnum && i < prev_ptnum ; i++ ) { glVertex3f( xcoords[i], hei2, ycoords[i] ); glVertex3f( prev_xcoords[i], hei2, prev_ycoords[i] ); } glEnd(); if ( ptnum < prev_ptnum ) { glBegin( GL_TRIANGLE_FAN ); glVertex3f( xcoords[ptnum-1], hei2, ycoords[ptnum-1] ); for ( int i = ptnum-1 ; i < prev_ptnum ; i++ ) glVertex3f( prev_xcoords[i], hei2, prev_ycoords[i] ); glEnd(); } if ( ptnum > prev_ptnum ) { glBegin( GL_TRIANGLE_FAN ); glVertex3f( prev_xcoords[prev_ptnum-1], hei2, prev_ycoords[prev_ptnum-1] ); for ( int i = prev_ptnum-1 ; i < ptnum ; i++ ) glVertex3f( xcoords[i], hei2, ycoords[i] ); glEnd(); } } } if ( pair && sp != splines.size() ) { prev_xcoords = xcoords; prev_ycoords = ycoords; prev_ptnum = ptnum; } else { delete xcoords; delete ycoords; if ( prev_xcoords != NULL ) delete prev_xcoords; if ( prev_ycoords != NULL ) delete prev_ycoords; } pair = !pair; } glPopMatrix(); list.end(); } } } //*********************************************** // Edit //*********************************************** void Prism::edit_widget( GtkWidget *wid ) { PREF_DEF bool tt = pref->tooltips->value(); // Options communes Object3D::edit_widget( wid ); // Spline edition new_frame( edit_cont, N_("Prism edition") ); new_table_no_frame( frame, 6 ); sweep_type->get_widget( table, tt, 1 ); height1->get_widget( table, tt, 2 ); height2->get_widget( table, tt, 3 ); open->get_widget( table, tt, 4 ); spline_type->get_widget( table, tt, 5 ); edit->get_widget( table, tt, 6 ); spline_edit_box = dlg_simple_box_frame( N_("Splines edition"), frame ); current_spline_num->get_widget( spline_edit_box, tt ); // Bouttons spline num GtkWidget *hbox = gtk_hbox_new( TRUE, 3 ); gtk_box_pack_start( GTK_BOX(spline_edit_box), hbox, TRUE, TRUE, 1 ); GtkWidget *button = gtk_button_new_with_label( _("Add spline") ); gtk_box_pack_start( GTK_BOX(hbox), button, TRUE, TRUE, 1 ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_prism_append_spline), this ); button = gtk_button_new_with_label( _("Delete spline") ); gtk_box_pack_start( GTK_BOX(hbox), button, TRUE, TRUE, 1 ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_prism_delete_spline), this ); current_point_num->get_widget( spline_edit_box, tt ); current_point->get_widget( spline_edit_box, tt, sign_prism_current_point_changed, this ); current_point_ctrl1->get_widget( spline_edit_box, tt, sign_prism_current_point_changed, this ); current_point_ctrl2->get_widget( spline_edit_box, tt, sign_prism_current_point_changed, this ); // Bouttons spline edit hbox = gtk_hbox_new( TRUE, 3 ); gtk_box_pack_start( GTK_BOX(spline_edit_box), hbox, TRUE, TRUE, 1 ); button = gtk_button_new_with_label( _("Append") ); gtk_box_pack_start( GTK_BOX(hbox), button, TRUE, TRUE, 1 ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_prism_append_point), this ); button = gtk_button_new_with_label( _("Prepend") ); gtk_box_pack_start( GTK_BOX(hbox), button, TRUE, TRUE, 1 ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_prism_prepend_point), this ); button = gtk_button_new_with_label( _("Insert") ); gtk_box_pack_start( GTK_BOX(hbox), button, TRUE, TRUE, 1 ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_prism_insert_point), this ); button = gtk_button_new_with_label( _("Delete") ); gtk_box_pack_start( GTK_BOX(hbox), button, TRUE, TRUE, 1 ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_prism_delete_point), this ); // Options de geometrie new_table( edit_cont, _("General settings"), 4 ); location->get_widget( table, tt, 1 ); size->get_widget( table, tt, 2 ); rotation->get_widget( table, tt, 3 ); sturm->get_widget( table, tt, 4 ); get_texture_widgets( edit_cont, tt ); gtk_widget_show_all( wid ); edit->set_target( spline_edit_box ); edit->toggle(); current_spline_num->connect_signal( GTK_SIGNAL_FUNC(sign_prism_current_spline_num_changed), this ); current_spline_num_changed(); current_point_num->connect_signal( GTK_SIGNAL_FUNC(sign_prism_current_point_num_changed), this ); //current_point_num_changed(); } //*********************************************** // Mouse drag //*********************************************** void Prism::mouse_drag( struct drag_info *drag ) { VMAN_DEF OBJLIST_DEF switch( vmanager->get_pointer_mode() ) { case TV_PMODE_SELECT: case TV_PMODE_TRANSLATE: if ( edit->value() ) { if ( selected_ctrl == 0 ) current_point->mouse_drag( drag ); if ( selected_ctrl == 1 ) current_point_ctrl1->mouse_drag( drag ); if ( selected_ctrl == 2 ) current_point_ctrl2->mouse_drag( drag ); } else location->mouse_drag( drag ); break; case TV_PMODE_SCALE: { size->mouse_drag( drag ); } break; case TV_PMODE_ROTATE: { rotation->mouse_drag( drag ); break; } case TV_PMODE_CUSTOM: ((ObjParam_point*)(objlist->get_current_param()))->mouse_drag( drag ); break; default: break; } } //*********************************************** // Pref_changed //*********************************************** void Prism::pref_changed() { Object3D::pref_changed(); location->pref_changed(); size->pref_changed(); rotation->pref_changed(); edit->pref_changed(); sturm->pref_changed(); spline_type->pref_changed(); sweep_type->pref_changed(); current_point_num->pref_changed(); current_spline_num->pref_changed(); current_point->pref_changed(); current_point_ctrl1->pref_changed(); current_point_ctrl2->pref_changed(); open->pref_changed(); height1->pref_changed(); height2->pref_changed(); } //*********************************************** // Destroy editor //*********************************************** void Prism::destroy_editor() { Object3D::destroy_editor(); location->clear_widget(); size->clear_widget(); texture->clear_widget(); rotation->clear_widget(); edit->clear_widget(); sturm->clear_widget(); spline_type->clear_widget(); sweep_type->clear_widget(); current_point_num->clear_widget(); current_spline_num->clear_widget(); current_point->clear_widget(); current_point_ctrl1->clear_widget(); current_point_ctrl2->clear_widget(); open->clear_widget(); height1->clear_widget(); height2->clear_widget(); if ( spline_edit_box != NULL ) spline_edit_box = NULL; } //*********************************************** // Output to povray //*********************************************** void Prism::output_to_povray_pass1( ofstream & file ) { file << "\n\n// Prism : " << name->value(); file << "\n#declare "; get_underscore_name( file ); file << " ="; int sptype = spline_type->value(); int swtype = sweep_type->value(); file << "\nprism {\n\t" << prism_spline_type_keys[ sptype ] << ' ' << prism_sweep_type_keys[ swtype ] ; file << "\n\t" << height1->value() << ", " << height2->value() << ", "; int psize = 0; for ( unsigned int i = 0 ; i < splines.size() ; i++ ) psize += splines[i]->size() + 1; if ( sptype == TV_SPLINE2D_CUBIC ) psize += splines.size() ; if ( spline_type->value() == TV_SPLINE2D_BEZIER ) psize = ( psize - splines.size() )*4; file << psize << ",\n\t"; for ( unsigned int i = 0 ; i < splines.size() ; i++ ) { splines[i]->set_type( (SplineType)spline_type->value() ); splines[i]->output_to_povray( file ); if ( i < splines.size() -1 ) file << ", "; } if ( open->value() ) file << "\n\topen"; float a, b, c, x, y, z; Object3D_with_material::output_to_povray_pass1( file ); file << "\n\t"; size->get( a, b, c ); file << "scale <" << a << "," << b << "," << c << ">"; rotation->output_to_povray( file ); location->get( x, y, z ); file << "\n\ttranslate <" << x << "," << y << "," << -z << "> \n\t"; if ( sturm->value() ) file << "sturm\n\t"; file << "\n}"; } //*********************************************** // Save & load //*********************************************** void Prism::save( ofstream & file ) { file << "\nPRISM{\n"; save_basics( file ); location->save( file ); size->save( file ); rotation->save( file ); texture->save( file ); edit->save( file ); sturm->save( file ); spline_type->save( file ); sweep_type->save( file ); open->save( file ); height1->save( file ); height2->save( file ); for ( unsigned int i = 0 ; i < splines.size() ; i++ ) splines[i]->save( file ); file << "\n}"; } bool Prism::load( ifstream & file, char *ltag ) { if ( strcmp( ltag, "PRISM" ) ) return false; set_load_progress( file ); splines.clear(); char * tag = NULL; do { tag = tvio_get_next_tag( file ); if ( tag == NULL ) break; if ( load_basics( file, tag ) ) continue; if ( location->load( file, tag ) ) continue; if ( size->load( file, tag ) ) continue; if ( rotation->load( file, tag ) ) continue; if ( edit->load( file, tag ) ) continue; if ( sturm->load( file, tag ) ) continue; if ( spline_type->load( file, tag ) ) continue; if ( sweep_type->load( file, tag ) ) continue; if ( open->load( file, tag ) ) continue; if ( height1->load( file, tag ) ) continue; if ( height2->load( file, tag ) ) continue; if ( ! strcmp( tag, "SPLINE2D" ) ) { Spline2D *spline = new Spline2D( TV_SPLINE2D_LINEAR, PrismSplineSubdivision ); spline->load( file, tag ); spline->set_for_lathe( false ); splines.push_back( spline ); continue; } tvio_skip_section(file ); } while ( tag != NULL ); current_spline_num->set_range( splines.size(), 1, 1); current_point_num->set_range( splines[0]->size(), 1, 1 ); return true; } //******************************************************* // Spline Edition //******************************************************* void Prism::current_spline_num_changed() { if ( spline_edit_box == NULL ) return; if ( current_spline_num->in_update ) return; if ( in_update ) return; in_update = true; Spline2D *spline = splines[ current_spline_num->value() - 1 ]; if ( current_point_num->value() > spline->size() ) current_point_num->set(0); current_spline_num->update_widget(); in_update = false; current_point_num_changed(); } void Prism::current_point_num_changed() { Spline2D *spline = splines[ current_spline_num->value() -1 ]; if ( spline_edit_box == NULL ) return; if ( current_point_num->in_update ) return; if ( in_update ) return; in_update = true; selected_ctrl = 0; int i = current_point_num->value() - 1; current_point->set( spline->getx(i), spline->gety(i) ); current_point->update_widget(); current_point->unchange(); float a[2]; spline->get_point_ctrl1( i, a ); current_point_ctrl1->set( a[0], a[1] ); current_point_ctrl1->update_widget(); current_point_ctrl1->unchange(); spline->get_point_ctrl2( i, a ); current_point_ctrl2->set( a[0], a[1] ); current_point_ctrl2->update_widget(); current_point_ctrl2->unchange(); current_point_num->update_widget(); in_update = false; } void Prism::current_point_changed() { if ( in_update ) return; if ( spline_edit_box == NULL ) return; if ( current_point->in_update ) return; if ( current_point_ctrl1->in_update ) return; if ( current_point_ctrl2->in_update ) return; Spline2D *spline = splines[ current_spline_num->value() -1 ]; int i = current_point_num->value() - 1; float x, y, z, c1x, c1y, c2x, c2y; if ( current_point->change_is_reversible() || current_point_ctrl1->change_is_reversible() || current_point_ctrl1->change_is_reversible() ) push_undo_item(); if ( !current_point->is_in_drag() && !current_point_ctrl1->is_in_drag() && !current_point_ctrl2->is_in_drag()) push_undo_item(); current_point->flush(); current_point_ctrl1->flush(); current_point_ctrl2->flush(); current_point->get( x, y, z ); current_point_ctrl1->get( c1x, c1y, z ); current_point_ctrl2->get( c2x, c2y, z ); spline->set_point( i, x, y, c1x, c1y, c2x, c2y ); list.invalidate(); VMAN_DEF vmanager->refresh(); } void Prism::delete_point() { Spline2D *spline = splines[ current_spline_num->value() -1 ]; int size = spline->size(); if ( size <= 4 ) return; push_undo_item(); int selected_point = current_point_num->value() - 1; spline->delete_point( selected_point ); current_point_num->reset_range( 1, size-1 ); current_point_num_changed(); list.invalidate(); VMAN_DEF vmanager->refresh(); } void Prism::append_point() { push_undo_item(); Spline2D *spline = splines[ current_spline_num->value() -1 ]; spline->append(); int size = spline->size(); current_point_num->reset_range( 1, size ); current_point_num->set( size ); current_point_num->update_widget(); current_point_num_changed(); list.invalidate(); VMAN_DEF vmanager->refresh(); } void Prism::prepend_point() { push_undo_item(); Spline2D *spline = splines[ current_spline_num->value() -1 ]; spline->prepend(); int size = spline->size(); current_point_num->reset_range( 1, size ); current_point_num->set( 1 ); current_point_num->update_widget(); current_point_num_changed(); list.invalidate(); VMAN_DEF vmanager->refresh(); } void Prism::insert_point() { int selected_point = current_point_num->value() - 1; if ( selected_point == 0 ) return; push_undo_item(); Spline2D *spline = splines[ current_spline_num->value() -1 ]; spline->insert( selected_point ); current_point_num->reset_range( 1, spline->size() ); current_point_num_changed(); list.invalidate(); VMAN_DEF vmanager->refresh(); } bool Prism::pick_test( int pname ) { int selected_point = current_point_num->value() - 1; unsigned int selected_spline = current_spline_num->value() - 1; //cout << "\nPrism pick test :"; //cout << "\n\tpname = " << pname; //cout << "\n\tpick_name = " << pick_name; //cout << "\n\tlast pick name = " << last_pick_name; //cout.flush(); if ( edit->value() ) { int offset = ( spline_type->value() == TV_SPLINE2D_BEZIER ) ? 2 : 0; if ( pname >= pick_name && pname <= last_pick_name ) { int cur_pname = pick_name; for ( unsigned int i = 0 ; i < splines.size() ; i++ ) { offset = ( spline_type->value() == TV_SPLINE2D_BEZIER && i == selected_spline ) ? 2 : 0; int max_pname = cur_pname + splines[i]->size() + offset - 1; if ( pname <= max_pname ) { current_spline_num->set( i +1 ); if ( offset == 0 ) { current_point_num->set( pname - cur_pname +1 ); } else { selected_ctrl = 0; int pointed = pname - cur_pname; if ( pointed < selected_point ) { current_point_num->set( pointed + 1 ); } if ( pointed > selected_point + 2 ) { current_point_num->set( pointed-1 ); } if ( pointed > selected_point && pointed <= selected_point + 2 ) selected_ctrl = pointed - selected_point; //cout << "\n\tselected = " << selected; //cout << "\n\tpointed = " << pointed; //cout << "\n\tselected ctrl = " << selected_ctrl; //cout.flush(); } break; } cur_pname += max_pname; } if ( selected_spline != (unsigned int )(current_spline_num->value() - 1) ) current_spline_num_changed(); else if ( selected_point != current_point_num->value() -1 ) { current_point_num_changed(); } list.invalidate(); VMAN_DEF vmanager->refresh(); return true; } else return false; } else { if ( pname == pick_name ) return true; else return false; } return false; } void Prism::undo( Object3D *copy ) { in_undo = true; Prism *changed = (Prism*)copy; changed->splines.swap( splines ); current_spline_num->reset_range( 1, splines.size() ); VMAN_DEF vmanager->refresh(); current_spline_num->update_widget(); in_undo = false; } void Prism::append_spline() { Spline2D *spline = new Spline2D( TV_SPLINE2D_LINEAR, PrismSplineSubdivision ); spline->set_for_lathe( false ); spline->add_point( 0.2, 0.2, -0.1, 0.1, 0.1, -0.1 ); spline->add_point( 0.2, -0.2 , 0.1, 0.1, -0.1, -0.1 ); spline->add_point( -0.2, -0.2, 0.1, -0.1, -0.1, 0.1 ); spline->add_point( -0.2, 0.2, -0.1, -0.1, 0.1,0.1 ); splines.push_back( spline ); current_spline_num->reset_range( 1, splines.size() ); current_spline_num->set( splines.size() ); VMAN_DEF vmanager->refresh(); current_spline_num->update_widget(); } void Prism::delete_spline() { if ( splines.size() == 1 ) return; int spline_num = current_spline_num->value() -1; Spline2D *spline = splines[ spline_num ]; splines.erase( splines.begin() + spline_num ); delete spline; current_spline_num->reset_range( 1, splines.size() ); if ( (unsigned int )current_spline_num->value() > splines.size() ) current_spline_num->set( splines.size() ); VMAN_DEF vmanager->refresh(); //current_spline_num_changed(); current_spline_num->update_widget(); }