//***************************************************************************************** // Truevision - a 3d modeler for gnome and povray // // mateditor.cc // // The material editror // class definition in matlist.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/matlist.h" #include "include/preferences.h" #include "include/interface.h" #include "config.h" #include "include/tvio.h" #include "include/viewmanager.h" #include "include/matlib.h" #include "include/scene.h" #include "include/undo.h" //************************************** // Definitions //************************************** const char *edit_butt_tt_text[MAX_EDIT_BUTTONS] = { _("New material"), _("Delete"), _("Copy"), _("Paste"), _("Move up"), _("Move down") }; const char *edit_butt_pix[MAX_EDIT_BUTTONS] = { GNOME_STOCK_PIXMAP_NEW, GNOME_STOCK_PIXMAP_CLOSE, GNOME_STOCK_PIXMAP_COPY, GNOME_STOCK_PIXMAP_PASTE, GNOME_STOCK_PIXMAP_UP, GNOME_STOCK_PIXMAP_DOWN }; //************************************** // Raise texeditor // // Material editor dialog //************************************** void MatList::raise_texeditor( int mat ) { if ( GTK_IS_DIALOG(ed_dialog) ) { gdk_window_raise( ed_dialog->window ); return; } if ( mat_liste.size() < 1 ) return; PREF_DEF ed_applied = false; bool tt = pref->tooltips->value(); // Dialog creation ed_dialog = gtk_dialog_new_with_buttons( _("Material editor"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, GTK_STOCK_HELP, GTK_RESPONSE_HELP, NULL ); g_signal_connect( G_OBJECT(ed_dialog), "response", G_CALLBACK(sign_ed_dlg_click), this ); g_signal_connect( G_OBJECT(ed_dialog), "close", G_CALLBACK(sign_ed_dlg_destroy), this ); // Restore geometry if wanted if ( pref->save_dlg_geo->value() ) { if ( pref->med_xpos->value() < 0 ) pref->med_xpos->set(0); if ( pref->med_ypos->value() < 0 ) pref->med_ypos->set(0); gtk_widget_set_uposition( ed_dialog, pref->med_xpos->value(), pref->med_ypos->value() ); gtk_window_set_default_size( GTK_WINDOW(ed_dialog), pref->med_xsize->value(), pref->med_ysize->value() ); } // Boxes GtkWidget *hbox = gtk_hbox_new( FALSE, 2 ); gtk_box_pack_start( GTK_BOX(GTK_DIALOG(ed_dialog)->vbox), hbox, TRUE, TRUE, 2 ); GtkWidget *vbox1 = gtk_vbox_new( FALSE, 2 ); gtk_box_pack_start( GTK_BOX(hbox), vbox1, FALSE, TRUE, 2 ); // Material selector edited = ( current != -1 ) ? current : 0; if ( mat != -1 ) edited = mat; texed_select->set_list( (const char **)&(mat_name_list[1]), mat_liste.size(), edited ); texed_select->get_widget( vbox1, tt ); texed_select->connect_signal( GTK_SIGNAL_FUNC(sign_ed_dlg_select), this ); // Material items tree 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(vbox1), scrolled, TRUE, TRUE, 4 ); editor_tree_store = gtk_tree_store_new( 2, G_TYPE_STRING, G_TYPE_POINTER ); editor_tree = gtk_tree_view_new_with_model( GTK_TREE_MODEL(editor_tree_store) ); gtk_container_add( GTK_CONTAINER(scrolled), editor_tree ); GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes ( N_("Name"), renderer, "text", 0, NULL); gtk_tree_view_append_column( GTK_TREE_VIEW(editor_tree), column ); editor_tree_selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(editor_tree) ); gtk_tree_selection_set_mode ( editor_tree_selection, GTK_SELECTION_SINGLE ); g_signal_connect( G_OBJECT(editor_tree_selection), "changed", G_CALLBACK(sign_matlist_editor_tree_select), this ); // Material management buttons GtkWidget *bbox = gtk_hbox_new( FALSE, 3 ); gtk_box_pack_start( GTK_BOX(vbox1), bbox, FALSE, TRUE, 2 ); GtkWidget *pix = NULL; for ( int i = 0 ; i < MAX_EDIT_BUTTONS ; i ++ ) { edit_butt_wid[i] = gtk_button_new(); gtk_box_pack_start( GTK_BOX(bbox), edit_butt_wid[i], TRUE, FALSE, 0 ); gtk_signal_connect( GTK_OBJECT(edit_butt_wid[i]), "clicked", GTK_SIGNAL_FUNC(sign_edit_button_clicked), this ); pix = gtk_image_new_from_stock( edit_butt_pix[i], GTK_ICON_SIZE_BUTTON ); gtk_container_add( GTK_CONTAINER(edit_butt_wid[i]), pix ); edit_butt_tt_wid[i] = gtk_tooltips_new(); gtk_tooltips_set_tip( edit_butt_tt_wid[i], edit_butt_wid[i], edit_butt_tt_text[i], NULL ); if ( !pref->tooltips->value() ) gtk_tooltips_disable( edit_butt_tt_wid[i] ); } edit_box = gtk_vbox_new( FALSE, 2 ); gtk_box_pack_start( GTK_BOX(hbox), edit_box, TRUE, TRUE, 2 ); mat_liste[edited]->get_editor( GTK_TREE_VIEW(editor_tree), editor_tree_store, editor_tree_selection, edit_box ); // Material preview GtkWidget *prev_box = gtk_vbox_new( FALSE, 2 ); gtk_box_pack_start( GTK_BOX(hbox), prev_box, TRUE, TRUE, 2 ); preview = new MaterialPreview( app_ref ); preview->set_size( 140, 140 ); preview->set_current_material( mat_liste[edited] ); preview->get_widget( prev_box, tt ); gtk_widget_show_all(ed_dialog); in_change = false; } //**************************************************** // ed_dlg_select // // Material selection callback from editor combo box // *************************************************** void MatList::ed_dlg_select() { if ( in_change ) return; if ( texed_select->in_update ) return; texed_select->flush(); if ( edited == texed_select->value() ) return; if ( edited != -1 ) { mat_liste[edited]->flush_material(); mat_liste[edited]->save_node_state(); mat_liste[edited]->destroy_editor(); mat_liste[edited]->remove_from_tree(); } edited = texed_select->value() ; if ( edited == -1 ) return; mat_liste[edited]->get_editor( GTK_TREE_VIEW(editor_tree), editor_tree_store, editor_tree_selection, edit_box ); preview->set_current_material( mat_liste[edited] ); } //**************************************************** // clicked ed_dlg // // Material editor dialog callbacks // *************************************************** void MatList::clicked_ed_dlg( gint button ) { if ( edited != -1 ) mat_liste[edited]->flush_material(); VMAN_DEF switch( button ) { default: case GTK_RESPONSE_CLOSE: preview->cancel_preview(); close_ed_dlg(); vmanager->force_refresh(); break; case GTK_RESPONSE_HELP: truevision_help_display( "truevision.xml", "sect-gui-mateditor", NULL ); break; case GTK_RESPONSE_APPLY: vmanager->force_refresh(); break; } } //**************************************************** // close ed_dlg // // Material editor close // *************************************************** void MatList::close_ed_dlg() { if ( !GTK_IS_DIALOG(ed_dialog) ) return; in_change = true; preview->save_preview_settings(); PREF_DEF if ( pref->save_dlg_geo->value() ) { gint x,y; gdk_window_get_root_origin( ed_dialog->window, &x, &y ); pref->med_xpos->set( x ); pref->med_ypos->set( y ); pref->med_xsize->set( ed_dialog->allocation.width ); pref->med_ysize->set( ed_dialog->allocation.height ); } if ( edited != -1 ) mat_liste[edited]->destroy_editor(); gtk_widget_destroy( ed_dialog ); ed_dialog = NULL; delete preview; in_change = false; } //**************************************************** // edit button clicked // // Material editor dialog buttons callbacks // *************************************************** // Material editor buttons : cut / copy / paste / move up / move down const char *matnames[] ={ N_("Material"), N_("Texture"), N_("Interior"), N_("Finish"), N_("pigment"), N_("Normal"), N_("Media"), N_("Density") }; // Material editor tree button clicked callback void MatList::edit_button_clicked( GtkWidget *wid ) { int button = -1; for ( int i = 0 ; i < MAX_EDIT_BUTTONS ; i ++ ) if ( wid == edit_butt_wid[i] ) { button = i; break; } if ( button == -1 ) return; if ( edited == -1 ) return; SCENE_DEF UNDO_DEF switch ( button ) { // New case 0: { scene->set_modified(); Material *tex = (Material*)(new PovMaterial( app_ref, "MATERIAL" )); mat_liste.push_back( tex ); tex->add_to_list( select_list_store ); update_mat_name_list(); select_row( mat_liste.size()-1 ); undoman->push( TV_UNDO_MAT_CREATE, tex, -1 ); texed_select->set( mat_liste.size() -1 ); texed_select->update_widget(); ed_dlg_select(); } break; // Delete case 1: mat_liste[edited]->delete_mat_item(); break; // Copy case 2: { if ( copied_item != NULL ) delete copied_item; MaterialItem *target = mat_liste[edited]->get_selected_item(); target->flush(); copied_item = target->duplicate_yourself(); } break; // Paste case 3: { if ( copied_item == NULL ) return; bool res = mat_liste[edited]->get_selected_item()->paste( copied_item ); if ( ! res ) app_warning( _("Cannot paste here item of type :"), matnames[ (int)copied_item->get_type() ] ); } break; // Move up case 4: mat_liste[edited]->move_mat_item( 0 ); break; // Move up case 5: mat_liste[edited]->move_mat_item( 1 ); break; default: break; } } //**************************************************** // update texeditor // // Update tex list from outside ( the editor ) // *************************************************** void MatList::update_texeditor() { if ( !GTK_IS_DIALOG(ed_dialog) ) return; if ( mat_liste.size() < 1 ) { close_ed_dlg(); return; } int current_index = edited; if ( current_index == -1 ) { current_index = 0; edited = -1; } texed_select->set_list( (const char **)&mat_name_list[1], mat_liste.size(), current_index ); texed_select->update_widget(); }