//***************************************************************************************** // Truevision - a 3d modeler for gnome and povray // // object3d.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/object3d.h" #include "include/objectlist.h" #include "include/interface.h" #include "include/preferences.h" #include "include/viewmanager.h" #include "include/scene.h" #include "include/undo.h" //************************************** // Définition //************************************** app_objs *Object3D::app_ref = NULL; GtkTreeStore *Object3D::tree_store= NULL; GtkWidget *Object3D::tree_view= NULL; GtkTreeSelection *Object3D::tree_selection= NULL; //************************************** // Noms des objets //************************************** const int obj_num = 38; const char *obj_names[ obj_num ] = { N_("Camera"), N_("Point light"), N_("Spot light"), N_("Cylindrical Light"), N_("Area Light"), N_("Box"), N_("Sphere"), N_("Cylinder"), N_("Cone"), N_("Background"), N_("Union"), N_("Merge"), N_("Intersection"), N_("Difference"), N_("Plane"), N_("Sky Sphere"), N_("Torus"), N_("Atmospheric Media"), N_("Disc"), N_("Heightfield"), N_("Superellipsoid"), N_("Fog"), N_("Light Group"), N_("Blob"), N_("Blob Sphere"), N_("Blob Cylinder"), N_("Text"), N_("Lathe"), N_("Link"), N_("Group"), N_("Prism"), N_("Isosurface"), N_("Julia Fractal"), N_("Parametric"), N_("Pov Script"), N_("Sphere sweep"), N_("Bicubic patch"), N_("Script object"), }; const char *obj_helpid[ obj_num ] = { "sect-camera", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "sect-athmos-bkgd", NULL, NULL, NULL, NULL, NULL, "sect-athmos-sky", NULL, "sect-athmos-amed", NULL, NULL, NULL, "sect-athmos-fog", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; //************************************** // Constructeur //************************************** Object3D::Object3D( app_objs *appref ) { app_ref = appref; parent = NULL; layer = NULL; hidden = new ObjParam_bool( N_("hide"), "HIDDE", NULL, app_ref, true, false ); render = new ObjParam_bool( N_("render"), "RENDER", NULL, app_ref, false, true ); hollow = new ObjParam_bool( N_("hollow"), "HOLLOW", NULL, app_ref, false, false ); no_shadow = new ObjParam_bool(N_("no shadow"), "NOSHAD", NULL, app_ref, false, false ); inverse = new ObjParam_bool( N_("inverse"), "INV", NULL, app_ref, false, false ); no_image = new ObjParam_bool( N_("no image"), "NOIMG", NULL, app_ref, false, false ); no_reflection = new ObjParam_bool( N_("no reflection"), "NOREFL", NULL, app_ref, false, false ); double_illuminate = new ObjParam_bool( N_("double illuminate"), "DBILL", NULL, app_ref, false, false ); name = new TvWidget_entry( N_("Name"), "NAME", NULL, app_ref ); selected = false; nm_entry = NULL; tree_view = NULL; } Object3D::Object3D( Object3D & ref ) { type = ref.type; parent = ref.parent; layer = ref.layer; category = ref.category; frame = NULL; edit_cont = NULL; widget = NULL; hidden = new ObjParam_bool( *ref.hidden ); render = new ObjParam_bool( *ref.render ); hollow = new ObjParam_bool( *ref.hollow ); no_shadow = new ObjParam_bool( *ref.no_shadow ); inverse = new ObjParam_bool( *ref.inverse ); no_image = new ObjParam_bool( *ref.no_image ); no_reflection = new ObjParam_bool( *ref.no_reflection ); double_illuminate = new ObjParam_bool( *ref.double_illuminate ); selected = false; tree_view = NULL; nm_entry = NULL; name = new TvWidget_entry( N_("Name"), "NAME", NULL, app_ref ); set_name( ref.name->value() ); } //************************************** // Destructeur //************************************** Object3D::~Object3D() { delete hidden; delete render; delete hollow; delete no_shadow; delete name; delete inverse; delete no_image; delete no_reflection; delete double_illuminate; } void Object3D::unselect() { selected = false; //if ( ctree != NULL ) gtk_ctree_unselect( ctree, ctree_node ); //list.invalidate(); } char * Object3D::get_type_name() { return (char*)obj_names[ type ]; } //************************************** // Set Name //************************************** void Object3D::name_changed() { if ( !name->has_changed() ) return; set_name( name->get_current_value() ); SCENE_DEF scene->set_modified(); } void Object3D::set_name( char *nm ) { OBJLIST_DEF char *test = new char[ strlen(nm) + 1 ]; strcpy( test, nm ); char *res = objlist->create_name( test ); if ( res != NULL ) { name->set(res); delete res; } else name->set(test); delete test; name->update_widget(); if ( GTK_IS_WIDGET(tree_view) ) gtk_tree_store_set( tree_store, &node_iter, 4, name->value(), -1 ); objlist->update_ref_list(); } void Object3D::check_name() { char *nm = name->value(); char *test = new char[ strlen(nm) + 1 ]; strcpy( test, nm ); name->set( NULL ); set_name( test ); delete test; } void Object3D::get_underscore_name( ofstream & file ) { char *nom = name->value(); //file << nom; int len = strlen( nom ); file << "obj_"; for ( int i = 0 ; i < len ; i++ ) file << (( nom[i] == ' ' || nom[i] == '#' || nom[i] == '-' || nom[i] == '+' || nom[i] == '=' ) ? '_' : nom[i]); } //************************************** // Set Picking name //************************************** void Object3D::display( glview *view, bool set_color ) { OBJLIST_DEF pick_name = objlist->get_pick_name(); glLoadName( pick_name ); } //************************************** // Set Color //************************************** void Object3D::set_color() { PREF_DEF if ( selected ) pref->objsel_color->gl_set_rgb(); else pref->obj_color->gl_set_rgb(); } void Object3D_with_material::set_color() { PREF_DEF if ( ! selected && texture->get_current() == NULL && parent != NULL ) { parent->set_color(); return; } if ( selected ) pref->objsel_color->gl_set_rgb(); else if ( ! texture->gl_set_material() ) pref->obj_color->gl_set_rgb(); } //************************************** // Add to tree //************************************** void Object3D::add_to_tree( GtkWidget *view, GtkTreeStore *store, GtkTreeSelection *sel, GtkTreeIter *parent, GtkTreeIter *sibling, const gchar *pixspe ) { tree_view = view; tree_store = store; tree_selection = sel; parent_node_iter = parent; GdkPixbuf *obj_pixbuf = NULL; char *pixmap = NULL; if ( pixspe != NULL ) pixmap = tv_get_pixmap( (char*)pixspe ); else pixmap = tv_get_pixmap( "object_default.xpm" ); obj_pixbuf = gdk_pixbuf_new_from_file( pixmap, NULL ); delete pixmap; GdkPixbuf *visible_pixbuf = NULL; if ( ! hidden->value() ) { char *pixmap = tv_get_pixmap( "object_visible.xpm" ); visible_pixbuf = gdk_pixbuf_new_from_file( pixmap, NULL ); delete pixmap; } GdkPixbuf *render_pixbuf = NULL; if ( render->value() ) { char *pixmap = tv_get_pixmap( "render.xpm" ); render_pixbuf = gdk_pixbuf_new_from_file( pixmap, NULL ); delete pixmap; } if ( parent != NULL ) { gtk_tree_store_insert_before( tree_store, &node_iter, parent, sibling ); } else { gtk_tree_store_append( tree_store, &node_iter, NULL ); } gtk_tree_store_set( tree_store, &node_iter, 1, visible_pixbuf, 2, render_pixbuf, 0, obj_pixbuf, 3, (gchar*)obj_names[type], 4, name->value(), 5, this, -1); } void Object3D::destroy() { gtk_tree_store_remove( tree_store, &node_iter ); delete this; } //************************************** // Editeur //************************************** void Object3D::edit_widget_base( GtkWidget *wid ) { OBJLIST_DEF PREF_DEF bool tt = pref->tooltips->value(); objlist->clear_current_param(); widget = wid; // Type de l'objet GtkWidget *frame = gtk_frame_new(NULL); gtk_box_pack_start( GTK_BOX(wid), frame, FALSE, TRUE, 0 ); GtkWidget *label = gtk_label_new( obj_names[type] ); gtk_container_add( GTK_CONTAINER(frame), label ); // Nom name->get_widget( wid, tt ); name->connect_signal( GTK_SIGNAL_FUNC(sign_entry), this ); name->connect_signal2( GTK_SIGNAL_FUNC(sign_entry2), this ); // Container GtkWidget *scrolled = gtk_scrolled_window_new( NULL, NULL ); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); gtk_box_pack_start( GTK_BOX(wid), scrolled, TRUE, TRUE, 4 ); GtkWidget *viewp = gtk_viewport_new( NULL, NULL ); gtk_viewport_set_shadow_type( GTK_VIEWPORT(viewp), GTK_SHADOW_ETCHED_IN /*GTK_SHADOW_NONE*/ ); gtk_container_add( GTK_CONTAINER(scrolled), viewp ); edit_cont = gtk_vbox_new( FALSE, 0 ); gtk_container_set_border_width( GTK_CONTAINER(edit_cont), 1 ); gtk_container_add( GTK_CONTAINER(viewp), edit_cont ); } void Object3D::edit_widget( GtkWidget *wid , bool solid_object ) { PREF_DEF bool tt = pref->tooltips->value(); edit_widget_base( wid ); hidden->get_widget( edit_cont, tt ); hidden->connect_signal( GTK_SIGNAL_FUNC(sign_hidden_changed), this ); render->get_widget( edit_cont, tt ); render->connect_signal( GTK_SIGNAL_FUNC(sign_render_changed), this ); if ( !solid_object ) return; hollow->get_widget( edit_cont, tt ); no_shadow->get_widget( edit_cont, tt ); no_image->get_widget( edit_cont, tt ); no_reflection->get_widget( edit_cont, tt ); inverse->get_widget( edit_cont, tt ); double_illuminate->get_widget( edit_cont, tt ); } //************************************** // Frame & Table //************************************** void Object3D::new_frame( GtkWidget *wid, char *nom ) { GtkWidget *Frame = gtk_frame_new( nom ); gtk_box_pack_start( GTK_BOX(wid), Frame, FALSE, TRUE, 6 ); frame = gtk_vbox_new( FALSE, 0 ); gtk_container_add( GTK_CONTAINER(Frame), frame ); gtk_container_set_border_width( GTK_CONTAINER(frame), 3 ); } void Object3D::new_table( GtkWidget *wid, char *nom, int rows ) { GtkWidget *Frame = gtk_frame_new( nom ); gtk_box_pack_start( GTK_BOX(wid), Frame, FALSE, TRUE, 6 ); table = gtk_table_new( rows, 4, FALSE ); gtk_container_add( GTK_CONTAINER(Frame), table ); gtk_container_set_border_width( GTK_CONTAINER(table), 3 ); } void Object3D::new_table_no_frame( GtkWidget *box, int rows ) { table = gtk_table_new( rows, 4, FALSE ); //gtk_container_add( GTK_CONTAINER(box), table ); gtk_box_pack_start( GTK_BOX(box), table, FALSE, TRUE, 6 ); gtk_container_set_border_width( GTK_CONTAINER(table), 3 ); } //************************************** // Pref_changed //************************************** void Object3D::pref_changed() { hidden->pref_changed(); render->pref_changed(); hollow->pref_changed(); no_shadow->pref_changed(); inverse->pref_changed(); no_image->pref_changed(); no_reflection->pref_changed(); double_illuminate->pref_changed(); list.invalidate(); } //************************************** // Destroy editor //************************************** void Object3D::destroy_editor() { flush(); gtk_widget_destroy( widget ); hidden->clear_widget(); render->clear_widget(); hollow->clear_widget(); no_shadow->clear_widget(); name->clear_widget(); inverse->clear_widget(); no_image->clear_widget(); no_reflection->clear_widget(); double_illuminate->clear_widget(); } //************************************** // Set visibility pix //************************************** void Object3D::set_visibility_pix() { GdkPixbuf *visible_pixbuf = NULL; if ( ! hidden->value() ) { char *pixmap = tv_get_pixmap( "object_visible.xpm" ); visible_pixbuf = gdk_pixbuf_new_from_file( pixmap, NULL ); delete pixmap; } gtk_tree_store_set( tree_store, &node_iter, 1, visible_pixbuf, -1); } void Object3D::set_render_pix() { GdkPixbuf *render_pixbuf = NULL; if ( render->value() ) { char *pixmap = tv_get_pixmap( "render.xpm" ); render_pixbuf = gdk_pixbuf_new_from_file( pixmap, NULL ); delete pixmap; } gtk_tree_store_set( tree_store, &node_iter, 2, render_pixbuf, -1); } //************************************** // MOUSE //************************************** /*void Object3D::mouse_translate( float dest[3], float normal[3], float ox, float oy, float x, float y ) { //float xoffset = x - ox; //float yoffset = y - oy; }*/ //************************************** // Output to povray //************************************** void Object3D::output_to_povray_pass1( ofstream & file ) { if ( hollow->value() ) file << "\n\thollow "; if ( no_shadow->value() ) file << "\n\tno_shadow"; if ( inverse->value() ) file << "\n\tinverse"; if ( no_image->value() ) file << "\n\tno_image"; if ( no_reflection->value() ) file << "\n\tno_reflection"; if ( double_illuminate->value() ) file << "\n\tdouble_illuminate"; //file << "\n\t"; } void Object3D::save_basics( ofstream & file ) { SCENE_DEF scene->set_save_progress(); name->save( file ); hidden->save( file ); hollow->save( file ); render->save( file ); no_shadow->save( file ); inverse->save( file ); no_image->save( file ); no_reflection->save( file ); double_illuminate->save( file ); } bool Object3D::load_basics( ifstream & file, char *tag ) { if ( name->load( file, tag ) ) { check_name(); return true; } if ( hidden->load( file, tag ) ) return true; if ( hollow->load( file, tag ) ) return true; if ( render->load( file, tag ) ) return true; if ( no_shadow->load( file, tag ) ) return true; if ( inverse->load( file, tag ) ) return true; if ( no_image->load( file, tag ) ) return true; if ( no_reflection->load( file, tag ) ) return true; if ( double_illuminate->load( file, tag ) ) return true; return false; } void Object3D::set_load_progress( ifstream & file ) { SCENE_DEF scene->set_load_progress( file ); } //------------------------------------------------- // Object 3D with material //------------------------------------------------- Object3D_with_material::Object3D_with_material( app_objs *appref ) : Object3D( appref ) { texture = new ObjParam_texref( N_("Material"), "MAT", NULL, app_ref, false ); target = new ObjParam_bool( N_("Target"), "PTARG", NULL, app_ref, false, false ); spacing = new ObjParam_float( N_("Spacing"), "PSPACE", NULL, app_ref, false, 1 ); spacing->set_range( 20, 0, 0.1, 6 ); refraction = new ObjParam_bool( N_("Refraction"), "PREFRAC", NULL, app_ref, false, false ); reflection = new ObjParam_bool( N_("Reflection"), "PREFLEC", NULL, app_ref, false, false ); collect = new ObjParam_bool( N_("Collect"), "PCOL", NULL, app_ref, false, true ); pass_through = new ObjParam_bool( N_("Pass trough"), "PPT", NULL, app_ref, false, false ); } Object3D_with_material::Object3D_with_material( Object3D_with_material & ref ) : Object3D( ref ) { texture = new ObjParam_texref( *ref.texture ); target = new ObjParam_bool( *ref.target ); spacing = new ObjParam_float( *ref.spacing ); refraction = new ObjParam_bool( *ref.refraction ); reflection = new ObjParam_bool( *ref.reflection ); collect = new ObjParam_bool( *ref.collect ); pass_through = new ObjParam_bool( *ref.pass_through ); } Object3D_with_material::~Object3D_with_material() { delete texture; delete target; delete spacing; delete refraction; delete reflection; delete collect; delete pass_through; } void Object3D_with_material::get_texture_widgets( GtkWidget *wid, bool tt ) { new_table_no_frame( wid, 1 ); texture->get_widget( table, tt, 1 ); //GtkWidget *box = dlg_simple_box_frame( N_("Photons"), wid ); new_table( wid, N_("Photons"),6 ); target->get_widget( table, tt, 1 ); spacing->get_widget( table, tt ,2 ); refraction->get_widget( table, tt, 3 ); reflection->get_widget( table, tt, 4 ); collect->get_widget( table, tt, 5 ); pass_through->get_widget( table, tt, 6 ); } void Object3D_with_material::destroy_editor() { flush(); Object3D::destroy_editor(); target->clear_widget(); spacing->clear_widget(); refraction->clear_widget(); reflection->clear_widget(); collect->clear_widget(); pass_through->clear_widget(); } void Object3D_with_material::save_basics( ofstream & file ) { Object3D::save_basics( file ); texture->save( file ); target->save( file ); spacing->save( file ); refraction->save( file ); reflection->save( file ); collect->save( file ); pass_through->save( file ); } bool Object3D_with_material::load_basics( ifstream & file, char *tag ) { if ( Object3D::load_basics( file, tag ) ) return true; if ( texture->load( file , tag ) ) return true; if ( target->load( file , tag ) ) return true; if ( spacing->load( file , tag ) ) return true; if ( refraction->load( file , tag ) ) return true; if ( reflection->load( file , tag ) ) return true; if ( collect->load( file , tag ) ) return true; if ( pass_through->load( file , tag ) ) return true; return false; } void Object3D_with_material::output_to_povray_pass1( ofstream & file ) { Object3D::output_to_povray_pass1( file ); file << "\n\tphotons {"; if ( target->value() ) file << "\n\t\ttarget " << spacing->value(); if ( refraction->value() ) file << "\n\t\trefraction on"; if ( reflection->value() ) file << "\n\t\treflection on"; if ( ! collect->value() ) file << "\n\t\tcollect off"; if ( pass_through->value() ) file << "\n\t\tpass_through"; file << "\n\t}\n"; texture->output_to_povray( file ); } void Object3D::push_undo_item() { Object3D *copy = duplicate_yourself(); UNDO_DEF undoman->push( TV_UNDO_OBJ3D_CHANGED, this, copy ); } void Object3D::help_on_object() { char *id = (char*)obj_helpid[ type ]; if ( id == NULL ) { app_warning( N_("Sorry no help available for "), obj_names[ type ] ); return; } truevision_help_display( "truevision.xml", id, NULL ); }