//***************************************************************************************** // Truevision - a 3d modeler for gnome and povray // // spheresweep.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/spheresweep.h" #include "include/viewmanager.h" #include "include/objectlist.h" #include "include/tvio.h" #include "include/preferences.h" /* Some files do not define M_PI... */ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif // Spline type const int spline3d_type_num = 3; const gchar * spline3d_type_list[spline3d_type_num] = { N_("Linear"), N_("Cubic"), N_("B Spline") }; const char *spline3d_type_keys[spline3d_type_num] = { "linear_spline", "cubic_spline", "b_spline" }; //************************************** // SphereSweep - Constructor //************************************** SphereSweep::SphereSweep( app_objs *appref ) : Object3D_with_material( appref ) { // Init type = TV_OBJ3D_SPHERESWEEP; category = TV_OBJ3D_OBJECTS; set_name( "SphereSweep" ); spline_edit_box = NULL; in_undo = false; in_update = false; // Spline - default definition spline = new Spline3D( TV_SPLINE3D_LINEAR, 10 ); spline->add_point( 0,0.1, 0, 0.1 ); spline->add_point( 0.1, 0.1, 0.1, 0.1 ); spline->add_point( 0.2, 0.1,0.2, 0.1 ); spline->add_point( 0.3, 0.1, 0.3, 0.1 ); // 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 SphereSweep"), app_ref, true, true ); tolerance = new ObjParam_float( N_("Tolerance"), "TOLER", NULL, app_ref, false, 0.00001 ); tolerance->set_range( 1, 0.000001, 0.000001, 6 ); spline_type = new ObjParam_option_combo( N_("Spline mode"), "SPLINET", NULL, app_ref, true ); spline_type->set_list( spline3d_type_list, spline3d_type_num, 0 ); 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_point = new ObjParam_point( N_("Position"), "POS", NULL, app_ref, true ); current_point->set_send_undo( false ); radius = new ObjParam_float( N_("Sphere radius"), "RAD", NULL, app_ref, true, true ); radius->set_range( 500, 0, 0.01, 5 ); radius->set_send_undo( false ); } //**************************************************** // Copy constructor //**************************************************** SphereSweep::SphereSweep( SphereSweep & 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 ); tolerance = new ObjParam_float( *ref.tolerance ); spline_type = new ObjParam_option_combo( *ref.spline_type ); current_point_num = new ObjParam_int( *ref.current_point_num ); current_point = new ObjParam_point( *ref.current_point ); radius = new ObjParam_float( *ref.radius ); spline = ref.spline->auto_copy(); current_point_num->set_range( spline->size(), 1, 1 ); } //**************************************************** // Destructor //**************************************************** SphereSweep::~SphereSweep() { delete location; delete size; delete rotation; delete edit; delete tolerance; delete spline_type; delete current_point_num; delete current_point; delete radius; delete spline; } //************************************** // Display // Dessin de la boite //************************************** void SphereSweep::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() || radius->changed() ) list.invalidate(); PREF_DEF int quality = 10 + pref->preview_quality->value()*4; // Edition mode display // no display list / a picking name for each point if ( edit->value() ) { OBJLIST_DEF int selected_point = current_point_num->value() - 1; set_color(); glPushMatrix(); int spline_size = spline->size(); // Get render mode from OpenGL ( Normal or Select ) int mode; glGetIntegerv( GL_RENDER_MODE, &mode ); // Normal drawing mode // display all, including lines ( segments betwenn points ) if ( mode != GL_SELECT ) { // Draw linear lines in stipple mode glEnable( GL_LINE_STIPPLE ); glLineStipple( 1, 0xAAA ); spline->set_type( TV_SPLINE3D_LINEAR ); spline->set_subdivisions( quality ); spline->gl_display_segments(); glDisable( GL_LINE_STIPPLE ); // Draw Spline in plain mode ( as a curve this time ) spline->set_type( (SplineType3D)spline_type->value() ); spline->set_subdivisions( 20 ); spline->gl_display_segments(); // Draw circles at each pointn except the last one for ( int i = 0 ; i < spline_size-1 ; i++ ) { float xcoords[ quality ], ycoords[ quality ], zcoords[ quality ]; float a[3] = { spline->getx(i), spline->gety(i), spline->getz(i) }; float b[3] = { spline->getx(i+1), spline->gety(i+1), spline->getz(i+1) }; float rad = spline->get_extra_param( i ); get_circle_points( a, b, rad, xcoords, ycoords, zcoords, NULL, NULL, NULL, quality ); glBegin( GL_LINE_LOOP ); for ( int j = 0 ; j < quality ; j++ ) glVertex3f( xcoords[j], ycoords[j], zcoords[j] ); glEnd(); } // Draw last point circle,orientation is calculated from previous point // For other points it is calculated with next point float xcoords[ quality ], ycoords[ quality ], zcoords[ quality ]; float a[3] = { spline->getx(spline_size-1), spline->gety(spline_size-1), spline->getz(spline_size-1) }; float b[3] = { spline->getx(spline_size-2), spline->gety(spline_size-2), spline->getz(spline_size-2) }; float rad = spline->get_extra_param( spline_size-1 ); get_circle_points( a, b, rad, xcoords, ycoords, zcoords, NULL, NULL, NULL, quality, true ); glBegin( GL_LINE_LOOP ); for ( int j = 0 ; j < quality ; j++ ) glVertex3f( xcoords[j], ycoords[j], zcoords[j] ); glEnd(); } // Draw Points ( much, much easier :) // We only draw this for selection mode ( with pick names ) pick_name = -1; for ( int i = 0 ; i < spline_size ; i++ ) { int pick = objlist->get_pick_name(); if ( pick_name == -1 ) pick_name = pick; glLoadName( pick ); if ( i != selected_point ) { glBegin( GL_POINTS ); spline->display_point(i); glEnd(); } else { glColor3f( 1.0, 0, 0 ); glPointSize( 6 ); glBegin( GL_POINTS ); spline->display_point( selected_point ); glEnd(); set_color(); glPointSize( 4 ); set_color(); } } glPopMatrix(); list.end(); } else { // Preview mode :) // SphereSweep opengl drawing // No point selection, we have a display list Object3D::display( view ); if ( set_col ) set_color(); if ( ! list.exec() ) { // parameters unchange for list validation location->unchange(); size->unchange(); rotation->unchange(); edit->unchange(); spline_type->unchange(); current_point_num->unchange(); current_point->unchange(); spline->set_type( (SplineType3D)spline_type->value() ); int spline_size = spline->size(); // create list if necessary list.begin(); glPushMatrix(); // Poistion and 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 ); // Linear spline preview // This one is easy : draw tubes from one point to another // and a sphere at each point if ( spline_type->value() == TV_SPLINE3D_LINEAR ) { for ( int i = 0 ; i < spline_size ; i++ ) { float center[3] = { spline->getx(i), spline->gety(i), spline->getz(i) }; float radius1 = spline->get_extra_param( i ); // Draw a Sphere at each point glPushMatrix(); glTranslatef( center[0], center[1], center[2] ); GLUquadricObj *quadobj = gluNewQuadric(); if ( !quadobj ) { app_warning( _("Out of memory" ) ); return; } gluQuadricDrawStyle( quadobj, GLU_FILL ); gluSphere(quadobj, radius1 , quality, quality ); glPopMatrix(); // Draw a tube to next point if ( i == spline_size -1 ) break; float direction[3] = { spline->getx(i+1), spline->gety(i+1), spline->getz(i+1) }; float radius2 = spline->get_extra_param( i+1 ); float points[2][3][quality]; float normals[2][3][quality]; get_circle_points( center, direction, radius1, points[0][0], points[0][1], points[0][2], normals[0][0], normals[0][1], normals[0][2],quality ); get_circle_points( direction, center, radius2, points[1][0], points[1][1], points[1][2], normals[1][0], normals[1][1], normals[1][2],quality, true ); glBegin( GL_QUAD_STRIP ); for ( int j = 0 ; j < quality ; j++ ) { glNormal3f( normals[0][0][j],normals[0][1][j], normals[0][2][j] ); glVertex3f( points[0][0][j], points[0][1][j], points[0][2][j] ); glNormal3f( normals[1][0][j],normals[1][1][j], normals[1][2][j] ); glVertex3f( points[1][0][j], points[1][1][j], points[1][2][j] ); } glNormal3f( normals[0][0][0],normals[0][1][0], normals[0][2][0] ); glVertex3f( points[0][0][0], points[0][1][0], points[0][2][0] ); glNormal3f( normals[1][0][0],normals[1][1][0], normals[1][2][0] ); glVertex3f( points[1][0][0], points[1][1][0], points[1][2][0] ); glEnd(); } } else { // Cubic splines and B-splines preview // Much more difficult :( // Calculate spline points and radius interpolation float *splinex, *spliney, *splinez; float *radices; int ptnum; spline->set_subdivisions( quality ); spline->get_segments( ptnum, splinex, spliney, splinez ); spline->interpolate_extra_param( ptnum, radices ); //cout << "\nptnum = " << ptnum; cout.flush(); // Initialize buffers int point_num = ptnum + quality*2; float spline_x[point_num], spline_y[point_num], spline_z[point_num]; float radius[point_num]; //cout << "\npoint num = " << point_num; cout.flush(); // add some points for start/end half spheres float start_radius = radices[0]; float end_radius = radices[ptnum-1]; float start_dir[3] = { splinex[1] - splinex[0], spliney[1] - spliney[0], splinez[1] - splinez[0] }; float end_dir[3] = { splinex[ptnum-2] - splinex[ptnum-1], spliney[ptnum-2] - spliney[ptnum-1], splinez[ptnum-2] - splinez[ptnum-1] }; float start_dir_norm = 0; float end_dir_norm = 0; for ( int i = 0 ; i < 3 ; i++ ) { start_dir_norm += start_dir[i]*start_dir[i]; end_dir_norm += end_dir[i]*end_dir[i]; } start_dir_norm = sqrt( start_dir_norm ); end_dir_norm = sqrt( end_dir_norm ); for ( int i = 0 ; i < 3 ; i++ ) { start_dir[i] = start_dir[i] / start_dir_norm * start_radius / (float)quality; end_dir[i] = end_dir[i] / end_dir_norm * end_radius / (float)quality; } // Copy spline values for ( int i = 0 ; i < ptnum ; i ++ ) { int ind = quality + i; spline_x[ind] = splinex[i]; spline_y[ind] = spliney[i]; spline_z[ind] = splinez[i]; radius[ind] = radices[i]; } for ( int i = 1 ; i < quality+1 ; i++ ) { spline_x[ quality - i ] = spline_x[ quality - i + 1 ] - start_dir[0]; spline_y[ quality - i ] = spline_y[ quality - i + 1 ] - start_dir[1]; spline_z[ quality - i ] = spline_z[ quality - i + 1 ] - start_dir[2]; spline_x[ point_num - quality + i -2 ] = spline_x[ point_num - quality + i - 3 ] - end_dir[0]; spline_y[ point_num - quality + i -2] = spline_y[ point_num - quality + i - 3 ] - end_dir[1]; spline_z[ point_num - quality + i -2 ] = spline_z[ point_num - quality + i - 3 ] - end_dir[2]; float angle = acos((float)i / (float)quality); radius[ quality - i ] = sin(angle)*start_radius; radius[ point_num - quality + i -2 ] = sin(angle) * end_radius; } delete splinex; delete spliney; delete splinez; // Get circles and normals float points[point_num][3][quality]; float normals[point_num][3][quality]; for ( int i = 0 ; i < point_num-1 ; i++ ) { float center[3] = { spline_x[i], spline_y[i], spline_z[i] }; int offset; if ( i != point_num -3 ) offset = i+2; else offset = i+1; float direction[3] = { spline_x[offset], spline_y[offset], spline_z[offset] }; get_circle_points( center, direction, radius[i], points[i][0], points[i][1], points[i][2], normals[i][0], normals[i][1], normals[i][2],quality ); } // Draw strips between circles for ( int i = 0 ; i < point_num-2 ; i++ ) { glBegin( GL_QUAD_STRIP ); for ( int j = 0 ; j < quality ; j++ ) { glNormal3f( normals[i][0][j],normals[i][1][j], normals[i][2][j] ); glVertex3f( points[i][0][j], points[i][1][j], points[i][2][j] ); glNormal3f( normals[i+1][0][j],normals[i+1][1][j], normals[i+1][2][j] ); glVertex3f( points[i+1][0][j], points[i+1][1][j], points[i+1][2][j] ); } glNormal3f( normals[i][0][0],normals[i][1][0], normals[i][2][0] ); glVertex3f( points[i][0][0], points[i][1][0], points[i][2][0] ); glNormal3f( normals[i+1][0][0],normals[i+1][1][0], normals[i+1][2][0] ); glVertex3f( points[i+1][0][0], points[i+1][1][0], points[i+1][2][0] ); glEnd(); } } glPopMatrix(); list.end(); } } } void SphereSweep::get_circle_points( float *center, float *direction, float radius, float *xcoords, float *ycoords, float * zcoords, float *xnorm, float *ynorm, float * znorm, int divisions, bool inv_dir ) { // calculate direction vector double vector[3] = { direction[0] - center [0], direction[1] - center [1], direction[2] - center [2], }; double denom = sqrt( vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2] ); if ( inv_dir ) for ( int i = 0 ; i < 3 ; i++ ) vector[i] /= -denom; else for ( int i = 0 ; i < 3 ; i++ ) vector[i] /= denom; // convert it as rotation angles double a1 = -asin( vector[1] ); double a2 = asin( vector[0] / cos(a1) ); double a2b = asin( vector[0] / cos(M_PI-a1) ); double vals[4][2] = { { a1, a2 }, { a1, M_PI-a2 }, { M_PI-a1, a2b }, { M_PI-a1, M_PI-a2b } }; int i = 0; for ( i= 0; i < 4 ; i++ ) { a1 = vals[i][0]; a2 = vals[i][1]; double offset = fabs( vector[2 ] - cos(a1)*cos(a2) ); offset += fabs( vector[1] + sin(a1) ); offset += fabs( vector[0] - cos(a1)*sin(a2) ); if ( offset < 0.01 ) break; } double cosa1 = cos(a1); double sina1 = sin(a1); double cosa2 = cos(a2); double sina2 = sin(a2); // calculating points and normals float epsilon = 2*M_PI / (float)divisions; float angle = 0; for ( int i = 0 ; i < divisions ; i++ ) { float y = radius * sin(angle); float x = radius * cos(angle); if ( xnorm != NULL ) { xnorm[i] = x*cosa2 + y*sina1*sina2; ynorm[i] = y*cosa1; znorm[i] = y*sina1 *cosa2 - x*sina2; } xcoords[i] = x*cosa2 + y*sina1*sina2 + center[0]; ycoords[i] = y*cosa1 + center[1]; zcoords[i] = y*sina1 *cosa2 - x*sina2 + center[2]; angle += epsilon; } } //*********************************************** // Edit //*********************************************** void SphereSweep::edit_widget( GtkWidget *wid ) { PREF_DEF bool tt = pref->tooltips->value(); // Options communes Object3D::edit_widget( wid ); // Spline edition new_frame( edit_cont, N_("SphereSweep edition") ); new_table_no_frame( frame, 2 ); spline_type->get_widget( table, tt, 1 ); edit->get_widget( table, tt, 2 ); spline_edit_box = dlg_simple_box_frame( N_("Spline edition"), frame ); current_point_num->get_widget( spline_edit_box, tt ); current_point->get_widget( spline_edit_box, tt, sign_ssweep_current_point_changed, this ); current_point->reduce_size(); radius->get_widget( spline_edit_box, tt , sign_ssweep_current_point_changed, this); // Bouttons 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( N_("Append") ); gtk_box_pack_start( GTK_BOX(hbox), button, TRUE, TRUE, 1 ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_ssweep_append_point), this ); button = gtk_button_new_with_label( N_("Prepend") ); gtk_box_pack_start( GTK_BOX(hbox), button, TRUE, TRUE, 1 ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_ssweep_prepend_point), this ); button = gtk_button_new_with_label( N_("Insert") ); gtk_box_pack_start( GTK_BOX(hbox), button, TRUE, TRUE, 1 ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_ssweep_insert_point), this ); button = gtk_button_new_with_label( N_("Delete") ); gtk_box_pack_start( GTK_BOX(hbox), button, TRUE, TRUE, 1 ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_ssweep_delete_point), this ); // Options de geometrie new_table( edit_cont, N_("General settings"), 4 ); location->get_widget( table, tt, 1 ); size->get_widget( table, tt, 2 ); rotation->get_widget( table, tt, 3 ); tolerance->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_point_num->connect_signal( GTK_SIGNAL_FUNC(sign_ssweep_current_point_num_changed), this ); current_point_num_changed(); } //*********************************************** // Mouse drag //*********************************************** void SphereSweep::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() ) current_point->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 SphereSweep::pref_changed() { Object3D::pref_changed(); location->pref_changed(); size->pref_changed(); rotation->pref_changed(); edit->pref_changed(); tolerance->pref_changed(); spline_type->pref_changed(); current_point_num->pref_changed(); current_point->pref_changed(); radius->pref_changed(); } //*********************************************** // Destroy editor //*********************************************** void SphereSweep::destroy_editor() { Object3D::destroy_editor(); location->clear_widget(); size->clear_widget(); texture->clear_widget(); rotation->clear_widget(); edit->clear_widget(); tolerance->clear_widget(); spline_type->clear_widget(); current_point_num->clear_widget(); current_point->clear_widget(); radius->clear_widget(); if ( spline_edit_box != NULL ) spline_edit_box = NULL; } //*********************************************** // Output to povray //*********************************************** void SphereSweep::output_to_povray_pass1( ofstream & file ) { file << "\n\n// SphereSweep : " << name->value(); file << "\n#declare "; get_underscore_name( file ); file << " ="; int sptype = spline_type->value(); file << "\nsphere_sweep {\n\t" << spline3d_type_keys[ sptype ]; int psize = spline->size(); file << "\n\t" << psize << ",\n\t"; spline->set_type( (SplineType3D)spline_type->value() ); spline->output_to_povray( file ); file << "\n\ttolerance " << tolerance->value(); 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"; file << "\n}"; } //*********************************************** // Save & load //*********************************************** void SphereSweep::save( ofstream & file ) { file << "\nSPHERESWEEP{\n"; save_basics( file ); location->save( file ); size->save( file ); rotation->save( file ); texture->save( file ); edit->save( file ); tolerance->save( file ); spline_type->save( file ); spline->save( file ); file << "\n}"; } bool SphereSweep::load( ifstream & file, char *ltag ) { if ( strcmp( ltag, "SPHERESWEEP" ) ) return false; set_load_progress( file ); 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 ( tolerance->load( file, tag ) ) continue; if ( spline_type->load( file, tag ) ) continue; if ( spline->load( file, tag ) ) continue; tvio_skip_section(file ); } while ( tag != NULL ); current_point_num->set_range( spline->size(), 1, 1 ); return true; } //******************************************************* // Spline Edition //******************************************************* void SphereSweep::current_point_num_changed() { if ( spline_edit_box == NULL ) return; if ( current_point_num->in_update ) return; if ( in_update ) return; in_update = true; int i = current_point_num->value() - 1; current_point->set( spline->getx(i), spline->gety(i), spline->getz(i) ); current_point->update_widget(); current_point->unchange(); current_point_num->update_widget(); radius->set( spline->get_extra_param(i) ); radius->update_widget(); radius->unchange(); radius->update_widget(); in_update = false; } void SphereSweep::current_point_changed() { if ( in_update ) return; if ( spline_edit_box == NULL ) return; if ( current_point->in_update ) return; int i = current_point_num->value() - 1; float x, y, z, ext; if ( current_point->change_is_reversible() ) push_undo_item(); if ( !current_point->is_in_drag() ) push_undo_item(); current_point->flush(); current_point->get( x, y, z ); radius->flush(); ext = radius->value(); spline->set_point( i, x, y, z, ext ); list.invalidate(); VMAN_DEF vmanager->refresh(); } void SphereSweep::delete_point() { 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 SphereSweep::append_point() { push_undo_item(); 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 SphereSweep::prepend_point() { push_undo_item(); 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 SphereSweep::insert_point() { int selected_point = current_point_num->value() - 1; if ( selected_point == 0 ) return; push_undo_item(); spline->insert( selected_point ); current_point_num->reset_range( 1, spline->size() ); current_point_num_changed(); list.invalidate(); VMAN_DEF vmanager->refresh(); } bool SphereSweep::pick_test( int pname ) { int selected_point = current_point_num->value() - 1; if ( edit->value() ) { if ( ( pname >= pick_name ) && ( pname <= pick_name + spline->size() ) ) { int pointed = pname - pick_name; current_point_num->set( pointed + 1 ); 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 SphereSweep::undo( Object3D *copy ) { in_undo = true; SphereSweep *changed = (SphereSweep*)copy; Spline3D *sp = changed->spline; changed->spline = spline; spline = sp; int spline_size = spline->size(); current_point_num->reset_range( 1, spline_size ); if ( current_point_num->value() > spline_size ) current_point_num->set( spline_size ); current_point_num_changed(); VMAN_DEF vmanager->refresh(); in_undo = false; }