shapeedit.cc

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2002 The Exult Team
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #  include <config.h>
00027 #endif
00028 
00029 #include "studio.h"
00030 #include "servemsg.h"
00031 #include "exult_constants.h"
00032 #include "utils.h"
00033 #include "shapeinf.h"
00034 #include "monstinf.h"
00035 #include "u7drag.h"
00036 #include "shapefile.h"
00037 #include "shapedraw.h"
00038 
00039 using std::cout;
00040 using std::endl;
00041 
00042 /*
00043  *  Widgets in one row of the 'equipment' dialog:
00044  */
00045 struct Equip_row_widgets
00046   {
00047   Shape_draw *draw;   // Where the shape is drawn.
00048   GtkWidget *shape, *name, *chance, *count;
00049   };
00050           // Holds widgets from equip. dialog.
00051 static Equip_row_widgets equip_rows[10] = {0};
00052 
00053 /*
00054  *  Equip window's Okay, Apply buttons.
00055  */
00056 C_EXPORT void on_equip_okay_clicked
00057   (
00058   GtkButton *btn,
00059   gpointer user_data
00060   )
00061   {
00062   ExultStudio::get_instance()->save_equip_window();
00063   ExultStudio::get_instance()->close_equip_window();
00064   }
00065 C_EXPORT void on_equip_apply_clicked
00066   (
00067   GtkButton *btn,
00068   gpointer user_data
00069   )
00070   {
00071   ExultStudio::get_instance()->save_equip_window();
00072   }
00073 
00074 /*
00075  *  Equip window's Cancel button.
00076  */
00077 C_EXPORT void on_equip_cancel_clicked
00078   (
00079   GtkButton *btn,
00080   gpointer user_data
00081   )
00082   {
00083   ExultStudio::get_instance()->close_equip_window();
00084   }
00085 
00086 /*
00087  *  Equip window's close button.
00088  */
00089 C_EXPORT gboolean on_equip_window_delete_event
00090   (
00091   GtkWidget *widget,
00092   GdkEvent *event,
00093   gpointer user_data
00094   )
00095   {
00096   ExultStudio::get_instance()->close_equip_window();
00097   return TRUE;
00098   }
00099 
00100 /*
00101  *  Record # changed, so update what's displayed.
00102  */
00103 C_EXPORT gboolean on_equip_recnum_changed
00104   (
00105   GtkWidget *widget,
00106   gpointer user_data
00107   )
00108   {
00109   int recnum = gtk_spin_button_get_value_as_int(
00110             GTK_SPIN_BUTTON(widget));
00111   ExultStudio::get_instance()->init_equip_window(recnum);
00112   return TRUE;
00113   }
00114 /*
00115  *  Draw shape in one of the Equip dialog rows.
00116  */
00117 C_EXPORT gboolean on_equip_draw_expose_event
00118   (
00119   GtkWidget *widget,    // The view window.
00120   GdkEventExpose *event,
00121   gpointer data     // ->row.
00122   )
00123   {
00124   ExultStudio::get_instance()->show_equip_shape(
00125     (Equip_row_widgets *) data,
00126     event->area.x, event->area.y, event->area.width,
00127               event->area.height);
00128   return (TRUE);
00129   }
00130 /*
00131  *  Shape # on one of the rows was changed.
00132  */
00133 C_EXPORT gboolean on_equip_shape_changed
00134   (
00135   GtkWidget *widget,
00136   gpointer data     // ->row info.
00137   )
00138   {
00139   Equip_row_widgets *eq = (Equip_row_widgets *) data;
00140   ExultStudio *studio = ExultStudio::get_instance();
00141   studio->show_equip_shape(eq);
00142   int shape = gtk_spin_button_get_value_as_int(
00143         GTK_SPIN_BUTTON(eq->shape));
00144   const char *nm = studio->get_shape_name(shape);
00145   gtk_label_set_text(GTK_LABEL(eq->name), nm ? nm : "");
00146   return (TRUE);
00147   }
00148 
00149 /*
00150  *  Callback for when a shape is dropped on one of the Equip draw areas.
00151  */
00152 
00153 static void Equip_shape_dropped
00154   (
00155   int file,     // U7_SHAPE_SHAPES.
00156   int shape,
00157   int frame,
00158   void *udata     // ->row.
00159   )
00160   {
00161   Equip_row_widgets *eq = (Equip_row_widgets *) udata;
00162   if (file == U7_SHAPE_SHAPES && shape >= 0 && shape < 1024)
00163     {     // Set shape #.
00164     gtk_spin_button_set_value(GTK_SPIN_BUTTON(eq->shape), shape);
00165     }
00166   }
00167 
00168 
00169 /*
00170  *  Set up 'equipment' dialog's table, which has 10 identical rows.
00171  */
00172 
00173 static void Setup_equip
00174   (
00175   GtkTable *table,    // Table to fill.
00176   Vga_file *vgafile,    // Shapes.
00177   unsigned char *palbuf,    // Palette for drawing shapes.
00178   Equip_row_widgets rows[10]  // Filled in.
00179   )
00180   {
00181   gtk_table_resize(table, 12, 17);
00182   gtk_widget_show (GTK_WIDGET(table));
00183           // Labels at top:
00184   GtkWidget *label = gtk_label_new ("Shape");
00185   gtk_widget_show (label);
00186   gtk_table_attach (table, label, 0, 3, 0, 1,
00187                       (GtkAttachOptions) (0),
00188                       (GtkAttachOptions) (0), 0, 0);
00189   label = gtk_label_new ("Chance (%)");
00190   gtk_widget_show (label);
00191     gtk_table_attach (table, label, 4, 5, 0, 1,
00192                       (GtkAttachOptions) (0),
00193                       (GtkAttachOptions) (0), 0, 0);
00194   label = gtk_label_new ("Count");
00195   gtk_widget_show (label);
00196   gtk_table_attach (table, label, 6, 7, 0, 1,
00197                       (GtkAttachOptions) (0),
00198                       (GtkAttachOptions) (0), 0, 0);
00199           // Separators:
00200   GtkWidget *vsep = gtk_vseparator_new ();
00201   gtk_widget_show (vsep);
00202   gtk_table_attach (table, vsep, 3, 4, 0, 12,
00203                       (GtkAttachOptions) (0),
00204                       (GtkAttachOptions) (GTK_FILL), 2, 0);
00205   vsep = gtk_vseparator_new ();
00206   gtk_widget_show (vsep);
00207   gtk_table_attach (table, vsep, 5, 6, 0, 12,
00208                       (GtkAttachOptions) (0),
00209                       (GtkAttachOptions) (GTK_FILL), 2, 0);
00210   GtkWidget *hsep = gtk_hseparator_new ();
00211   gtk_widget_show (hsep);
00212   gtk_table_attach (table, hsep, 0, 7, 1, 2,
00213                       (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
00214                       (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
00215 
00216           // Create the rows.
00217   for (int row = 0; row < 10; row++)
00218     {
00219           // Create frame, shape drawing area.
00220     GtkWidget *frame = gtk_frame_new (NULL);
00221     gtk_widget_show (frame);
00222       gtk_table_attach (table, frame, 0, 1, row + 2, row + 3,
00223                       (GtkAttachOptions) (GTK_FILL),
00224                       (GtkAttachOptions) (GTK_FILL), 3, 0);
00225     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
00226 
00227     GtkWidget *drawingarea = gtk_drawing_area_new ();
00228     gtk_widget_show (drawingarea);
00229     gtk_container_add (GTK_CONTAINER(frame), drawingarea);
00230     gtk_widget_set_usize (drawingarea, 20, 40);
00231     if (vgafile && palbuf)
00232       {
00233       rows[row].draw = new Shape_draw(vgafile, palbuf, 
00234                 drawingarea);
00235       gtk_signal_connect(GTK_OBJECT(drawingarea), 
00236         "expose-event", 
00237         GTK_SIGNAL_FUNC(on_equip_draw_expose_event),
00238               &rows[row]);
00239       rows[row].draw->enable_drop(Equip_shape_dropped, 
00240               &rows[row]);
00241       }
00242           // Shape #:
00243       GtkWidget *spin = gtk_spin_button_new (GTK_ADJUSTMENT(
00244       gtk_adjustment_new (1, 0, 1023, 1, 50, 50)), 1, 0);
00245     rows[row].shape = spin;
00246     gtk_widget_show(spin);
00247     gtk_table_attach (table, spin, 1, 2, row + 2, row + 3,
00248                         (GtkAttachOptions) (GTK_FILL),
00249                         (GtkAttachOptions) (0), 0, 0);
00250     gtk_signal_connect(GTK_OBJECT(spin), "changed",
00251         GTK_SIGNAL_FUNC(on_equip_shape_changed),
00252                 &rows[row]);
00253           // Name:
00254     label = gtk_label_new("label1");
00255     rows[row].name = label;
00256     gtk_widget_show (label);
00257     gtk_table_attach (table, label, 2, 3, row + 2, row + 3,
00258                     (GtkAttachOptions) (0),
00259         (GtkAttachOptions) (0), 0, 0);
00260     gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
00261     gtk_misc_set_alignment (GTK_MISC (label), 6.70552e-08, 0.5);
00262           // Chance:
00263     spin = gtk_spin_button_new(GTK_ADJUSTMENT(
00264       gtk_adjustment_new (1, 0, 100, 1, 10, 10)), 1, 0);
00265     rows[row].chance = spin;
00266     gtk_widget_show (spin);
00267     gtk_table_attach (table, spin, 4, 5, row + 2, row + 3,
00268                         (GtkAttachOptions) (GTK_FILL),
00269                         (GtkAttachOptions) (0), 0, 0);
00270           // Count:
00271     spin = gtk_spin_button_new (GTK_ADJUSTMENT(
00272       gtk_adjustment_new (1, 0, 100, 1, 10, 10)), 1, 0);
00273     rows[row].count = spin;
00274     gtk_widget_show(spin);
00275     gtk_table_attach (table, spin, 6, 7, row + 2, row + 3,
00276                       (GtkAttachOptions) (GTK_FILL),
00277                       (GtkAttachOptions) (0), 0, 0);
00278     }
00279   }
00280 
00281 /*
00282  *  Set the fields to a given record.
00283  */
00284 
00285 void ExultStudio::init_equip_window
00286   (
00287   int recnum      // Record # to start with (1-based).
00288   )
00289   {
00290           // Fill in the record.
00291   Equip_record& rec = Monster_info::get_equip(recnum - 1);
00292           // Go through rows.
00293   for (int row = 0; row < 10; row++)
00294     {
00295     Equip_element& elem = rec.get(row);
00296     Equip_row_widgets& widgets = equip_rows[row];
00297     int shnum = elem.get_shapenum();
00298     gtk_spin_button_set_value(GTK_SPIN_BUTTON(widgets.shape), 
00299                   shnum);
00300     const char *nm = get_shape_name(shnum);
00301     gtk_label_set_text(GTK_LABEL(widgets.name), nm);
00302     gtk_spin_button_set_value(GTK_SPIN_BUTTON(widgets.chance),
00303             elem.get_probability());
00304     gtk_spin_button_set_value(GTK_SPIN_BUTTON(widgets.count),
00305             elem.get_quantity());
00306     }
00307   }
00308 
00309 /*
00310  *  Store the fields to a given record.
00311  */
00312 
00313 void ExultStudio::save_equip_window
00314   (
00315   )
00316   {
00317   int recnum = get_spin("equip_recnum");
00318           // Get the record.
00319   Equip_record& rec = Monster_info::get_equip(recnum - 1);
00320           // Go through rows.
00321   for (int row = 0; row < 10; row++)
00322     {
00323     Equip_element& elem = rec.get(row);
00324     Equip_row_widgets& widgets = equip_rows[row];
00325     elem.set(gtk_spin_button_get_value_as_int(
00326           GTK_SPIN_BUTTON(widgets.shape)), 
00327        gtk_spin_button_get_value_as_int(
00328           GTK_SPIN_BUTTON(widgets.chance)),
00329        gtk_spin_button_get_value_as_int(
00330           GTK_SPIN_BUTTON(widgets.count)));
00331     }
00332   shape_info_modified = true;
00333   }
00334 
00335 /*
00336  *  Open the equip-editing window.
00337  */
00338 
00339 void ExultStudio::open_equip_window
00340   (
00341   int recnum      // Record # to start with (1-based).
00342   )
00343   {
00344   int ecnt = Monster_info::get_equip_cnt();
00345   if (recnum <= 0 || recnum > ecnt)
00346     return;
00347   if (!equipwin)      // First time?
00348     {
00349     equipwin = glade_xml_get_widget( app_xml, "equip_window" );
00350     GtkWidget *table = glade_xml_get_widget(app_xml,
00351                 "equip_table");
00352     Setup_equip(GTK_TABLE(table), vgafile->get_ifile(), 
00353               palbuf, equip_rows);
00354     }
00355           // This will cause the data to be set:
00356   set_spin("equip_recnum", recnum, 1, ecnt);
00357   gtk_widget_show(equipwin);
00358 //  show_shinfo_shape();    // Be sure picture is updated.
00359   }
00360 
00361 /*
00362  *  Close the equip window.
00363  */
00364 
00365 void ExultStudio::close_equip_window
00366   (
00367   )
00368   {
00369   if (equipwin)
00370     gtk_widget_hide(equipwin);
00371   }
00372 
00373 /*
00374  *  Paint the shape in one row of the Equip window draw area.
00375  */
00376 
00377 void ExultStudio::show_equip_shape
00378   (
00379   Equip_row_widgets *eq,
00380   int x, int y, int w, int h  // Rectangle. w=-1 to show all.
00381   )
00382   {
00383   if (!eq->draw)
00384     return;
00385   eq->draw->configure();
00386   int shnum = gtk_spin_button_get_value_as_int(
00387             GTK_SPIN_BUTTON(eq->shape));
00388 
00389   if (!shnum)     // Don't draw shape 0.
00390     shnum = -1;
00391   eq->draw->draw_shape_centered(shnum, 0);
00392   if (w != -1)
00393     eq->draw->show(x, y, w, h);
00394   else
00395     eq->draw->show();
00396   }
00397 
00398 /*
00399  *  Shape window's Okay, Apply buttons.
00400  */
00401 C_EXPORT void on_shinfo_okay_clicked
00402   (
00403   GtkButton *btn,
00404   gpointer user_data
00405   )
00406   {
00407   ExultStudio::get_instance()->save_shape_window();
00408   ExultStudio::get_instance()->close_shape_window();
00409   }
00410 C_EXPORT void on_shinfo_apply_clicked
00411   (
00412   GtkButton *btn,
00413   gpointer user_data
00414   )
00415   {
00416   ExultStudio::get_instance()->save_shape_window();
00417   }
00418 
00419 /*
00420  *  Shape window's Cancel button.
00421  */
00422 C_EXPORT void on_shinfo_cancel_clicked
00423   (
00424   GtkButton *btn,
00425   gpointer user_data
00426   )
00427   {
00428   ExultStudio::get_instance()->close_shape_window();
00429   }
00430 
00431 /*
00432  *  Shape window's close button.
00433  */
00434 C_EXPORT gboolean on_shape_window_delete_event
00435   (
00436   GtkWidget *widget,
00437   GdkEvent *event,
00438   gpointer user_data
00439   )
00440   {
00441   ExultStudio::get_instance()->close_shape_window();
00442   return TRUE;
00443   }
00444 
00445 /*
00446  *  Draw shape in draw area.
00447  */
00448 C_EXPORT gboolean on_shinfo_draw_expose_event
00449   (
00450   GtkWidget *widget,    // The view window.
00451   GdkEventExpose *event,
00452   gpointer data     // ->Shape_chooser.
00453   )
00454   {
00455   ExultStudio::get_instance()->show_shinfo_shape(
00456     event->area.x, event->area.y, event->area.width,
00457               event->area.height);
00458   return (TRUE);
00459   }
00460 
00461 /*
00462  *  Shape window's Equip-Edit button.
00463  */
00464 C_EXPORT void on_open_equip_button_clicked
00465   (
00466   GtkButton *btn,
00467   gpointer user_data
00468   )
00469   {
00470   ExultStudio *s = ExultStudio::get_instance();
00471   s->open_equip_window(s->get_spin("shinfo_monster_equip"));
00472   }
00473 
00474 /*
00475  *  Frame # in shape-info window:
00476  */
00477 C_EXPORT void
00478 on_shinfo_frame_changed     (GtkSpinButton *button,
00479            gpointer   user_data)
00480 {
00481   ExultStudio *s = ExultStudio::get_instance();
00482   s->set_shape_notebook_frame(
00483         gtk_spin_button_get_value_as_int(button));
00484           // Force repaint of shape.
00485   gtk_widget_queue_draw(glade_xml_get_widget(s->get_xml(), 
00486               "shinfo_draw"));
00487 }
00488 
00489 
00490 
00491 /*
00492  *  Special-shapes toggles:
00493  */
00494 C_EXPORT void on_shinfo_weapon_check_toggled
00495   (
00496   GtkToggleButton *btn,
00497         gpointer user_data
00498   )
00499   {
00500   bool on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn));
00501   ExultStudio::get_instance()->set_visible("shinfo_weapon_box", on);
00502   }
00503 C_EXPORT void on_shinfo_ammo_check_toggled
00504   (
00505   GtkToggleButton *btn,
00506         gpointer user_data
00507   )
00508   {
00509   bool on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn));
00510   ExultStudio::get_instance()->set_visible("shinfo_ammo_box", on);
00511   }
00512 C_EXPORT void on_shinfo_armor_check_toggled
00513   (
00514   GtkToggleButton *btn,
00515         gpointer user_data
00516   )
00517   {
00518   bool on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn));
00519   ExultStudio::get_instance()->set_visible("shinfo_armor_box", on);
00520   }
00521 C_EXPORT void on_shinfo_monster_check_toggled
00522   (
00523   GtkToggleButton *btn,
00524         gpointer user_data
00525   )
00526   {
00527   bool on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn));
00528   ExultStudio::get_instance()->set_visible("shinfo_monster_box", on);
00529   }
00530 
00531 /*
00532  *  Set frame-dependent fields in the shape-editing notebook.
00533  */
00534 
00535 void ExultStudio::set_shape_notebook_frame
00536   (
00537   int frnum     // Frame # to set.
00538   )
00539   {
00540   Shape_info *info = (Shape_info *)
00541       gtk_object_get_user_data(GTK_OBJECT(shapewin));
00542   if (!info)
00543     return;
00544   set_spin("shinfo_xtiles", info->get_3d_xtiles(frnum));
00545   set_spin("shinfo_ytiles", info->get_3d_ytiles(frnum));
00546   unsigned char wx, wy;   // Weapon-in-hand offset.
00547   info->get_weapon_offset(frnum, wx, wy);
00548   set_spin("shinfo_wihx", wx, 0, 255);  // Negative???
00549   set_spin("shinfo_wihy", wy, 0, 255);
00550   }
00551 
00552 /*
00553  *  Fill in the shape-editing notebook.
00554  */
00555 
00556 void ExultStudio::init_shape_notebook
00557   (
00558   Shape_info& info,
00559   GtkWidget *book,    // The notebook.
00560   int shnum,      // Shape #.
00561   int frnum     // Frame #.
00562   )
00563   {
00564   static int classes[] = {0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 
00565               9, 10, 11, 12, 0};
00566   const int numclasses = sizeof(classes)/sizeof(classes[0]);
00567   int shclass = (unsigned int) info.get_shape_class();
00568   set_optmenu("shinfo_shape_class", shclass < numclasses ?
00569           classes[shclass] : 0);
00570   set_shape_notebook_frame(frnum);
00571   set_spin("shinfo_ztiles", info.get_3d_height());
00572   int spot = info.get_ready_type();
00573   if (spot < 0)
00574     spot = 3;   // Left hand if looks invalid.
00575   else if (spot == 100)
00576     spot = 18;    // LR Hand.  Not sure about this.
00577   else if (spot > 17)
00578     spot = 3;
00579   set_optmenu("shinfo_ready_spot", spot);
00580   set_spin("shinfo_weight", info.get_weight(), 0, 255);
00581   set_spin("shinfo_volume", info.get_volume(), 0, 255);
00582           // Bunch of flags:
00583   set_toggle("shinfo_sfx_check", info.has_sfx());
00584   set_toggle("shinfo_strange_check", info.has_strange_movement());
00585   set_toggle("shinfo_animated_check", info.is_animated());
00586   set_toggle("shinfo_solid_check", info.is_solid());
00587   set_toggle("shinfo_water_check", info.is_water());
00588       // ++++Set poison for flats, field for non-flats.
00589   set_toggle("shinfo_poison_check", info.is_poisonous());
00590   set_toggle("shinfo_field_check", info.is_field());
00591   set_toggle("shinfo_door_check", info.is_door());
00592   set_toggle("shinfo_barge_check", info.is_barge_part());
00593   set_toggle("shinfo_transp_check", info.is_transparent());
00594   set_toggle("shinfo_light_check", info.is_light_source());
00595   set_toggle("shinfo_transl_check", info.has_translucency());
00596   set_toggle("shinfo_obstaclex_check", info.is_xobstacle());
00597   set_toggle("shinfo_obstacley_check", info.is_yobstacle());
00598   set_toggle("shinfo_occludes_check", info.occludes());
00599           // Extras.
00600   Weapon_info *winfo = info.get_weapon_info();
00601   set_toggle("shinfo_weapon_check", winfo != 0);
00602   set_visible("shinfo_weapon_box", winfo != 0);
00603   if (winfo)      // Setup weapon page.
00604     {
00605     set_spin("shinfo_weapon_damage", winfo->get_damage());
00606     set_spin("shinfo_weapon_range", winfo->get_range());
00607     set_optmenu("shinfo_weapon_type", winfo->get_damage_type());
00608     int ammo = winfo->get_ammo_consumed();
00609     int ammo_use = ammo > 0 ? 0 :
00610       winfo->uses_charges() ? 2 :
00611       winfo->is_thrown() ? 3 : 1; // 1 == "None".
00612     set_optmenu("shinfo_weapon_ammo", ammo_use);
00613     set_spin("shinfo_weapon_ammo_shape", ammo, ammo > 0);
00614     set_spin("shinfo_weapon_proj", winfo->get_projectile(),
00615                 0, 1023);
00616     set_optmenu("shinfo_weapon_uses", winfo->get_uses());
00617     set_spin("shinfo_weapon_sfx", winfo->get_sfx(), 0, 1023);
00618     set_spin("shinfo_weapon_hitsfx", winfo->get_hitsfx(), 0, 1023);
00619           // Show usecode in hex.
00620     set_entry("shinfo_weapon_uc", winfo->get_usecode(), true);
00621     static char *powers[] = {
00622           "shinfo_weapon_pow0",
00623           "shinfo_weapon_pow1",
00624           "shinfo_weapon_pow2",
00625           "shinfo_weapon_pow3",
00626           "shinfo_weapon_pow4",
00627           "shinfo_weapon_pow5" };
00628     set_bit_toggles(&powers[0], 
00629       sizeof(powers)/sizeof(powers[0]), winfo->get_powers());
00630     set_toggle("shinfo_weapon_explodes", winfo->explodes());
00631     set_toggle("shinfo_weapon_returns", winfo->returns());
00632     }
00633   Ammo_info *ainfo = info.get_ammo_info();
00634   set_toggle("shinfo_ammo_check", ainfo != 0);
00635   set_visible("shinfo_ammo_box", ainfo != 0);
00636   if (ainfo)      // Setup ammo page.
00637     {
00638     set_spin("shinfo_ammo_damage", ainfo->get_damage());
00639     set_spin("shinfo_ammo_family", ainfo->get_family_shape());
00640     set_optmenu("shinfo_ammo_type", ainfo->get_damage_type());
00641     static char *powers[] = {
00642           "shinfo_ammo_pow0",
00643           "shinfo_ammo_pow1",
00644           "shinfo_ammo_pow2",
00645           "shinfo_ammo_pow3",
00646           "shinfo_ammo_pow4",
00647           "shinfo_ammo_pow5" };
00648     set_bit_toggles(&powers[0], 
00649       sizeof(powers)/sizeof(powers[0]), ainfo->get_powers());
00650           // 'Explode'???
00651     }
00652   Armor_info *arinfo = info.get_armor_info();
00653   set_toggle("shinfo_armor_check", arinfo != 0);
00654   set_visible("shinfo_armor_box", arinfo != 0);
00655   if (arinfo)     // Setup armor page.
00656     {
00657     static char *immun[] = {"shinfo_armor_immun0",
00658           "shinfo_armor_immun1",
00659           "shinfo_armor_immun2",
00660           "shinfo_armor_immun3" };
00661     set_spin("shinfo_armor_value", arinfo->get_prot());
00662     set_bit_toggles(&immun[0], 
00663       sizeof(immun)/sizeof(immun[0]), arinfo->get_immune());
00664     }
00665   Monster_info *minfo = info.get_monster_info();
00666   set_toggle("shinfo_monster_check", minfo != 0);
00667   set_visible("shinfo_monster_box", minfo != 0);
00668   if (minfo)      // Setup monster page.
00669     {
00670     set_spin("shinfo_monster_str", minfo->get_strength());
00671     set_spin("shinfo_monster_dex", minfo->get_dexterity());
00672     set_spin("shinfo_monster_intel", minfo->get_intelligence());
00673     set_spin("shinfo_monster_cmb", minfo->get_combat());
00674     set_spin("shinfo_monster_armor", minfo->get_armor());
00675     set_spin("shinfo_monster_wpn", minfo->get_weapon());
00676     set_spin("shinfo_monster_reach", minfo->get_reach());
00677     set_spin("shinfo_monster_equip", minfo->get_equip_offset());
00678     set_optmenu("shinfo_monster_align", minfo->get_alignment());
00679     static char *vuln[] = { "shinfo_monster_vuln0",
00680           "shinfo_monster_vuln1",
00681           "shinfo_monster_vuln2",
00682           "shinfo_monster_vuln3" };
00683     static char *immun[] = {"shinfo_monster_immun0",
00684           "shinfo_monster_immun1",
00685           "shinfo_monster_immun2",
00686           "shinfo_monster_immun3" };
00687     set_bit_toggles(&vuln[0], sizeof(vuln)/sizeof(vuln[0]),
00688             minfo->get_vulnerable());
00689     set_bit_toggles(&immun[0], 
00690       sizeof(immun)/sizeof(immun[0]), minfo->get_immune());
00691     set_toggle("shinfo_monster_splits", minfo->splits());
00692     set_toggle("shinfo_monster_cant_die", minfo->cant_die());
00693     set_toggle("shinfo_monster_cant_yell", minfo->cant_yell());
00694     set_toggle("shinfo_monster_cant_bleed", minfo->cant_bleed());
00695     set_toggle("shinfo_monster_poison_safe",
00696             minfo->poison_safe());
00697     static char *flags[] = {"shinfo_monster_flag0",
00698           "shinfo_monster_flag1",
00699           "shinfo_monster_flag2",
00700           "shinfo_monster_flag3",
00701           "shinfo_monster_flag4" };
00702     set_bit_toggles(&flags[0],
00703       sizeof(flags)/sizeof(flags[0]), minfo->get_flags());
00704     }
00705   gtk_widget_show(book);
00706   }
00707 
00708 /*
00709  *  Save the shape-editing notebook.
00710  */
00711 
00712 void ExultStudio::save_shape_notebook
00713   (
00714   Shape_info& info,
00715   int shnum,      // Shape #.
00716   int frnum     // Frame #.
00717   )
00718   {
00719   static int classes[] = {0, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14};
00720   info.set_shape_class((Shape_info::Shape_class)
00721       classes[get_optmenu("shinfo_shape_class")]);
00722   info.set_3d(get_spin("shinfo_xtiles"), get_spin("shinfo_ytiles"),
00723             get_spin("shinfo_ztiles"));
00724   int spot = get_optmenu("shinfo_ready_spot");
00725   if (spot == 18)     // LR hand.
00726     spot = 100;
00727   info.set_ready_type(spot);
00728   info.set_weight_volume(get_spin("shinfo_weight"),
00729             get_spin("shinfo_volume"));
00730   info.set_weapon_offset(frnum, get_spin("shinfo_wihx"),
00731                   get_spin("shinfo_wihy"));
00732           // Bunch of flags:
00733   info.set_sfx(get_toggle("shinfo_sfx_check"));
00734   info.set_strange_movement(get_toggle("shinfo_strange_check"));
00735   info.set_animated(get_toggle("shinfo_animated_check"));
00736   info.set_solid(get_toggle("shinfo_solid_check"));
00737   info.set_water(get_toggle("shinfo_water_check"));
00738       // ++++Set poison for flats, field for non-flats.
00739   info.set_field(get_toggle("shinfo_field_check") ||
00740       get_toggle("shinfo_poison_check"));
00741   info.set_door(get_toggle("shinfo_door_check"));
00742   info.set_barge_part(get_toggle("shinfo_barge_check"));
00743   info.set_transparent(get_toggle("shinfo_transp_check"));
00744   info.set_light_source(get_toggle("shinfo_light_check"));
00745   info.set_translucency(get_toggle("shinfo_transl_check"));
00746   info.set_obstacle(get_toggle("shinfo_obstaclex_check"), 
00747       get_toggle("shinfo_obstacley_check"));
00748   info.set_occludes(get_toggle("shinfo_occludes_check"));
00749           // Extras.
00750   if (!get_toggle("shinfo_weapon_check"))
00751     info.set_weapon_info(false);  // Not a weapon.
00752   else
00753     {
00754     Weapon_info *winfo = info.set_weapon_info(true);
00755     winfo->set_damage(
00756       get_spin("shinfo_weapon_damage"),
00757       get_optmenu("shinfo_weapon_type"));
00758     winfo->set_range(get_spin("shinfo_weapon_range"));
00759     int ammo_use = get_optmenu("shinfo_weapon_ammo");
00760     int ammo = ammo_use == 0 ? 
00761         get_spin("shinfo_weapon_ammo_shape")
00762       :  ammo_use == 2 ? -2   // Charges.
00763       :  ammo_use == 3 ? -3   // Thrown.
00764       :  -1;        // None.
00765     winfo->set_ammo(ammo);
00766     winfo->set_projectile(get_spin("shinfo_weapon_proj"));
00767     winfo->set_uses(get_optmenu("shinfo_weapon_uses"));
00768     winfo->set_sfxs(get_spin("shinfo_weapon_sfx"),
00769         get_spin("shinfo_weapon_hitsfx"));
00770           // Get usecode in hex.
00771     winfo->set_usecode(get_num_entry("shinfo_weapon_uc"));
00772     static char *powers[] = {
00773           "shinfo_weapon_pow0",
00774           "shinfo_weapon_pow1",
00775           "shinfo_weapon_pow2",
00776           "shinfo_weapon_pow3",
00777           "shinfo_weapon_pow4",
00778           "shinfo_weapon_pow5" };
00779     winfo->set_powers(get_bit_toggles(&powers[0], 
00780           sizeof(powers)/sizeof(powers[0])));
00781           // 'Explode'???
00782     winfo->set_returns(get_toggle("shinfo_weapon_returns"));
00783     winfo->set_explodes(get_toggle("shinfo_weapon_explodes"));
00784     }
00785   if (!get_toggle("shinfo_ammo_check"))
00786     info.set_ammo_info(false);  // Not ammo.
00787   else
00788     {
00789     Ammo_info *ainfo = info.set_ammo_info(true);
00790     ainfo->set_family_shape(get_spin("shinfo_ammo_family"));
00791     ainfo->set_damage(get_spin("shinfo_ammo_damage"),
00792         get_optmenu("shinfo_ammo_type"));
00793     static char *powers[] = {
00794           "shinfo_ammo_pow0",
00795           "shinfo_ammo_pow1",
00796           "shinfo_ammo_pow2",
00797           "shinfo_ammo_pow3",
00798           "shinfo_ammo_pow4",
00799           "shinfo_ammo_pow5" };
00800     ainfo->set_powers(get_bit_toggles(&powers[0], 
00801           sizeof(powers)/sizeof(powers[0])));
00802           // 'Explode'???
00803     }
00804   if (!get_toggle("shinfo_armor_check"))
00805     info.set_armor_info(false); // Not armor.
00806   else
00807     {
00808     Armor_info *arinfo = info.set_armor_info(true);
00809     static char *immun[] = {"shinfo_armor_immun0",
00810           "shinfo_armor_immun1",
00811           "shinfo_armor_immun2",
00812           "shinfo_armor_immun3" };
00813     arinfo->set_prot(get_spin("shinfo_armor_value"));
00814     arinfo->set_immune(get_bit_toggles(&immun[0], 
00815           sizeof(immun)/sizeof(immun[0])));
00816     }
00817   if (!get_toggle("shinfo_monster_check"))
00818     info.set_monster_info(false);
00819   else
00820     {
00821     Monster_info *minfo = info.set_monster_info(true);
00822     minfo->set_stats(
00823       get_spin("shinfo_monster_str"),
00824       get_spin("shinfo_monster_dex"),
00825       get_spin("shinfo_monster_intel"),
00826       get_spin("shinfo_monster_cmb"),
00827       get_spin("shinfo_monster_armor"),
00828       get_spin("shinfo_monster_wpn"),
00829       get_spin("shinfo_monster_reach"));
00830     minfo->set_equip_offset(get_spin("shinfo_monster_equip"));
00831     minfo->set_alignment(get_optmenu("shinfo_monster_align"));
00832     static char *vuln[] = { "shinfo_monster_vuln0",
00833           "shinfo_monster_vuln1",
00834           "shinfo_monster_vuln2",
00835           "shinfo_monster_vuln3" };
00836     static char *immun[] = {"shinfo_monster_immun0",
00837           "shinfo_monster_immun1",
00838           "shinfo_monster_immun2",
00839           "shinfo_monster_immun3" };
00840     minfo->set_vulnerable(get_bit_toggles(&vuln[0], 
00841             sizeof(vuln)/sizeof(vuln[0])));
00842     minfo->set_immune(get_bit_toggles(&immun[0], 
00843       sizeof(immun)/sizeof(immun[0])));
00844     minfo->set_splits(get_toggle("shinfo_monster_splits"));
00845     minfo->set_cant_die(get_toggle("shinfo_monster_cant_die"));
00846     minfo->set_cant_yell(get_toggle("shinfo_monster_cant_yell"));
00847     minfo->set_cant_bleed(get_toggle("shinfo_monster_cant_bleed"));
00848     minfo->set_poison_safe(
00849         get_toggle("shinfo_monster_poison_safe"));
00850     static char *flags[] = {"shinfo_monster_flag0",
00851           "shinfo_monster_flag1",
00852           "shinfo_monster_flag2",
00853           "shinfo_monster_flag3",
00854           "shinfo_monster_flag4" };
00855     minfo->set_flags(get_bit_toggles(&flags[0],
00856           sizeof(flags)/sizeof(flags[0])));
00857     }
00858   shape_info_modified = true;
00859   }
00860 
00861 /*
00862  *  Open the shape-editing window.
00863  */
00864 
00865 void ExultStudio::open_shape_window
00866   (
00867   int shnum,      // Shape #.
00868   int frnum,      // Frame #.
00869   Shape_file_info *file_info, // For image file shape is in.
00870   char *shname,     // ->shape name, or null.
00871   Shape_info *info    // Info. if in main object shapes.
00872   )
00873   {
00874   if (!shapewin)      // First time?
00875     shapewin = glade_xml_get_widget( app_xml, "shape_window" );
00876   if (shape_draw)     // Ifile might have changed.
00877     delete shape_draw;
00878   shape_draw = 0;
00879   Vga_file *ifile = file_info->get_ifile();
00880   if (ifile && palbuf)
00881     {
00882     shape_draw = new Shape_draw(ifile, palbuf,
00883           glade_xml_get_widget(app_xml, "shinfo_draw"));
00884 //    shape_draw->enable_drop(Shape_shape_dropped, this);
00885     }
00886           // Store ->'s.
00887   gtk_object_set_user_data(GTK_OBJECT(shapewin), info);
00888   gtk_object_set_data(GTK_OBJECT(shapewin), "file_info", file_info);
00889           // Shape/frame.
00890   set_entry("shinfo_shape", shnum, false, false);
00891   int nframes = ifile->get_num_frames(shnum);
00892   set_spin("shinfo_frame", frnum, 0, nframes - 1);
00893           // Store name, #frames.
00894   set_entry("shinfo_name", shname ? shname : "");
00895 //  set_spin("shinfo_num_frames", nframes);
00896           // Show xright, ybelow.
00897   Shape_frame *shape = ifile->get_shape(shnum, frnum);
00898   set_spin("shinfo_originx", shape->get_xright(), 0,
00899               shape->get_width());
00900   set_spin("shinfo_originy", shape->get_ybelow(), 0, 
00901               shape->get_height());
00902           // Get info. notebook.
00903   GtkWidget *notebook = glade_xml_get_widget(app_xml, "shinfo_notebook");
00904   if (info)
00905     init_shape_notebook(*info, notebook, shnum, frnum);
00906   else
00907     gtk_widget_hide(notebook);
00908   gtk_widget_show(shapewin);
00909   show_shinfo_shape();    // Be sure picture is updated.
00910   }
00911 
00912 /*
00913  *  Save the shape-editing window.
00914  */
00915 
00916 void ExultStudio::save_shape_window
00917   (
00918   )
00919   {
00920   int shnum = get_num_entry("shinfo_shape");
00921   int frnum = get_num_entry("shinfo_frame");
00922   Shape_info *info = (Shape_info *)
00923       gtk_object_get_user_data(GTK_OBJECT(shapewin));
00924   Shape_file_info *file_info = (Shape_file_info *)
00925     gtk_object_get_data(GTK_OBJECT(shapewin), "file_info");
00926   Vga_file *ifile = file_info->get_ifile();
00927   if (info &&     // If 'shapes.vga', get name.
00928       shnum < 1024)   // But only for the first 1024.
00929     {
00930     const gchar *nm = get_text_entry("shinfo_name");
00931     if (!nm)
00932       nm = "";
00933     char *oldname = get_shape_name(shnum);
00934     if (!oldname)
00935       oldname = "";
00936     if (strcmp(nm, oldname) != 0)
00937       {   // Name changed.
00938       if (shnum >= names.size())
00939         names.resize(shnum + 1);
00940       delete names[shnum];
00941       names[shnum] = nm ? newstrdup(nm) : 0;
00942       shape_names_modified = true;
00943       }
00944     }
00945           // Update origin.
00946   Shape_frame *shape = ifile->get_shape(shnum, frnum);
00947   int xright = get_spin("shinfo_originx"),
00948       ybelow = get_spin("shinfo_originy");
00949   if (xright != shape->get_xright() || ybelow != shape->get_ybelow())
00950     {     // It changed.
00951     file_info->set_modified();
00952     shape->set_offset(xright, ybelow);
00953     }
00954   if (info)
00955     save_shape_notebook(*info, shnum, frnum);
00956   }
00957 
00958 /*
00959  *  Close the shape-editing window.
00960  */
00961 
00962 void ExultStudio::close_shape_window
00963   (
00964   )
00965   {
00966   if (shapewin)
00967     gtk_widget_hide(shapewin);
00968   }
00969 
00970 /*
00971  *  Paint the shape in the draw area.
00972  */
00973 
00974 void ExultStudio::show_shinfo_shape
00975   (
00976   int x, int y, int w, int h  // Rectangle. w=-1 to show all.
00977   )
00978   {
00979   if (!shape_draw)
00980     return;
00981   shape_draw->configure();
00982           // Yes, this is kind of redundant...
00983   int shnum = get_num_entry("shinfo_shape");
00984   int frnum = get_num_entry("shinfo_frame");
00985   shape_draw->draw_shape_centered(shnum, frnum);
00986   if (w != -1)
00987     shape_draw->show(x, y, w, h);
00988   else
00989     shape_draw->show();
00990   }
00991 

Generated on Mon Jul 9 14:42:48 2007 for ExultEngine by  doxygen 1.5.1