eggedit.cc

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2000-2001 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 "u7drag.h"
00031 #include "servemsg.h"
00032 #include "objserial.h"
00033 #include "exult_constants.h"
00034 #include "shapefile.h"
00035 #include "shapedraw.h"
00036 
00037 using std::cout;
00038 using std::cerr;
00039 using std::endl;
00040 /*
00041  *  Open egg window.
00042  */
00043 
00044 C_EXPORT void on_open_egg_activate
00045   (
00046   GtkMenuItem     *menuitem,
00047         gpointer         user_data
00048   )
00049   {
00050   ExultStudio *studio = ExultStudio::get_instance();
00051   studio->open_egg_window();
00052   }
00053 
00054 /*
00055  *  Egg window's Apply button.
00056  */
00057 C_EXPORT void on_egg_apply_btn_clicked
00058   (
00059   GtkButton *btn,
00060   gpointer user_data
00061   )
00062   {
00063   ExultStudio::get_instance()->save_egg_window();
00064   }
00065 
00066 /*
00067  *  Egg window's Cancel button.
00068  */
00069 C_EXPORT void on_egg_cancel_btn_clicked
00070   (
00071   GtkButton *btn,
00072   gpointer user_data
00073   )
00074   {
00075   ExultStudio::get_instance()->close_egg_window();
00076   }
00077 
00078 /*
00079  *  Egg window's close button.
00080  */
00081 C_EXPORT gboolean on_egg_window_delete_event
00082   (
00083   GtkWidget *widget,
00084   GdkEvent *event,
00085   gpointer user_data
00086   )
00087   {
00088   ExultStudio::get_instance()->close_egg_window();
00089   return TRUE;
00090   }
00091 
00092 /*
00093  *  Draw shape in egg 'monster' area.
00094  */
00095 C_EXPORT gboolean on_egg_monster_draw_expose_event
00096   (
00097   GtkWidget *widget,    // The view window.
00098   GdkEventExpose *event,
00099   gpointer data     // ->Shape_chooser.
00100   )
00101   {
00102   ExultStudio::get_instance()->show_egg_monster(
00103     event->area.x, event->area.y, event->area.width,
00104               event->area.height);
00105   return (TRUE);
00106   }
00107 
00108 /*
00109  *  Monster shape # lost focus, so update shape displayed.
00110  */
00111 C_EXPORT gboolean on_monst_shape_focus_out_event
00112   (
00113   GtkWidget *widget,
00114   GdkEventFocus *event,
00115   gpointer user_data
00116   )
00117   {
00118   ExultStudio::get_instance()->show_egg_monster();
00119   return FALSE;
00120   }
00121 /*
00122  *  "Teleport coords" toggled.
00123  */
00124 C_EXPORT void on_teleport_coord_toggled
00125   (
00126   GtkToggleButton *btn,
00127         gpointer user_data
00128   )
00129   {
00130   ExultStudio *studio = ExultStudio::get_instance();
00131   bool on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn));
00132   studio->set_sensitive("teleport_x", on);
00133   studio->set_sensitive("teleport_y", on);
00134   studio->set_sensitive("teleport_eggnum", !on);
00135   }
00136 
00137 /*
00138  *  Callback for when a shape is dropped on the Egg 'monster' area.
00139  */
00140 
00141 static void Egg_monster_dropped
00142   (
00143   int file,     // U7_SHAPE_SHAPES.
00144   int shape,
00145   int frame,
00146   void *udata
00147   )
00148   {
00149   if (file == U7_SHAPE_SHAPES && shape >= 0 && shape < 1024)
00150     ((ExultStudio *) udata)->set_egg_monster(shape, frame);
00151   }
00152 
00153 #ifdef WIN32
00154 
00155 static void Drop_dragged_shape(int shape, int frame, int x, int y, void *data)
00156 {
00157   cout << "Dropped a shape: " << shape << "," << frame << " " << data << endl;
00158 
00159   Egg_monster_dropped(U7_SHAPE_SHAPES, shape, frame, data);
00160 }
00161 
00162 #endif
00163 
00164 /*
00165  *  Open the egg-editing window.
00166  */
00167 
00168 void ExultStudio::open_egg_window
00169   (
00170   unsigned char *data,    // Serialized egg, or null.
00171   int datalen
00172   )
00173   {
00174   bool first_time = false;
00175   if (!eggwin)      // First time?
00176     {
00177     first_time = true;
00178     eggwin = glade_xml_get_widget( app_xml, "egg_window" );
00179     if (vgafile && palbuf)
00180       {
00181       egg_monster_draw = new Shape_draw(vgafile->get_ifile(),
00182                  palbuf,
00183           glade_xml_get_widget(app_xml, "egg_monster_draw"));
00184       egg_monster_draw->enable_drop(Egg_monster_dropped,
00185                 this);
00186       }
00187     egg_ctx = gtk_statusbar_get_context_id(
00188       GTK_STATUSBAR(glade_xml_get_widget(
00189         app_xml, "egg_status")), "Egg Editor");
00190     }
00191           // Init. egg address to null.
00192   gtk_object_set_user_data(GTK_OBJECT(eggwin), 0);
00193           // Make 'apply' sensitive.
00194   gtk_widget_set_sensitive(glade_xml_get_widget(app_xml, 
00195             "egg_apply_btn"), true);
00196   if (data)
00197     {
00198     if (!init_egg_window(data, datalen))
00199       return;
00200     }
00201   else if (first_time)    // Init. empty dialog first time.
00202     {
00203     set_toggle("teleport_coord", true);
00204     set_sensitive("teleport_x", true);
00205     set_sensitive("teleport_y", true);
00206     set_sensitive("teleport_eggnum", false);
00207     }
00208   gtk_widget_show(eggwin);
00209 
00210 #ifdef WIN32
00211   if (first_time || !eggdnd)
00212     Windnd::CreateStudioDropDest(eggdnd, egghwnd, Drop_dragged_shape, NULL, NULL, (void*) this);
00213 #endif
00214   }
00215 
00216 /*
00217  *  Close the egg-editing window.
00218  */
00219 
00220 void ExultStudio::close_egg_window
00221   (
00222   )
00223   {
00224   if (eggwin) {
00225     gtk_widget_hide(eggwin);
00226 #ifdef WIN32
00227     Windnd::DestroyStudioDropDest(eggdnd, egghwnd);
00228 #endif
00229   }
00230   }
00231 
00232 /*
00233  *  Init. the egg editor with data from Exult.
00234  *
00235  *  Output: 0 if error (reported).
00236  */
00237 
00238 int ExultStudio::init_egg_window
00239   (
00240   unsigned char *data,
00241   int datalen
00242   )
00243   {
00244   unsigned long addr;
00245   int tx, ty, tz;
00246   int shape, frame;
00247   int type;
00248   int criteria;
00249   int probability;
00250   int distance;
00251   bool nocturnal, once, hatched, auto_reset;
00252   int data1, data2;
00253   if (!Egg_object_in(data, datalen, addr, tx, ty, tz, shape, frame,
00254     type, criteria, probability, distance, 
00255     nocturnal, once, hatched, auto_reset,
00256     data1, data2))
00257     {
00258     cout << "Error decoding egg" << endl;
00259     return 0;
00260     }
00261           // Store address with window.
00262   gtk_object_set_user_data(GTK_OBJECT(eggwin), (gpointer) addr);
00263   GtkWidget *notebook = glade_xml_get_widget(app_xml, "notebook1");
00264   if (notebook)     // 1st is monster (1).
00265     gtk_notebook_set_page(GTK_NOTEBOOK(notebook), type - 1);
00266   set_spin("probability", probability);
00267   set_spin("distance", distance);
00268   set_optmenu("criteria", criteria);
00269   set_toggle("nocturnal", nocturnal);
00270   set_toggle("once", once);
00271   set_toggle("hatched", hatched);
00272   set_toggle("autoreset", auto_reset);
00273   switch (type)     // Set notebook page.
00274     {
00275   case 1:       // Monster:
00276     {
00277     int shnum = data2&1023, frnum = data2>>10;
00278     set_entry("monst_shape", shnum);
00279     set_entry("monst_frame", frnum);
00280     set_optmenu("monst_schedule", data1>>8);
00281     set_optmenu("monst_align", data1&3);
00282     set_spin("monst_count", (data1&0xff)>>2);
00283     break;
00284     }
00285   case 2:       // Jukebox:
00286     set_spin("juke_song", data1&0xff);
00287     set_toggle("juke_cont", (data1>>8)&0x01);
00288     break;
00289   case 3:       // Sound effect:
00290     set_spin("sfx_number", data1&0xff);
00291     set_toggle("sfx_cont", (data1>>8)&0x01);
00292     break;
00293   case 4:       // Voice:
00294     set_spin("speech_number", data1&0xff);
00295     break;
00296   case 5:       // Usecode:
00297     set_entry("usecode_number", data2, true);
00298     set_spin("usecode_quality", data1&0xff);
00299     break;
00300   case 6:       // Missile:
00301     set_entry("missile_shape", data1); 
00302     set_optmenu("missile_dir", data2&0xff);
00303     set_spin("missile_delay", data2>>8);
00304     break;
00305   case 7:       // Teleport:
00306     {
00307     int qual = data1&0xff;
00308     if (qual == 255)
00309       {
00310       set_toggle("teleport_coord", true);
00311       int schunk = data1 >> 8;
00312       set_entry("teleport_x",
00313         (schunk%12)*c_tiles_per_schunk +(data2&0xff),
00314                 true);
00315       set_entry("teleport_y",
00316         (schunk/12)*c_tiles_per_schunk +(data2>>8),
00317                 true);
00318       set_spin("teleport_eggnum", 0, false);
00319       }
00320     else      // Egg #.
00321       {
00322       set_toggle("teleport_coord", false);
00323       set_entry("teleport_x", 0, false, false);
00324       set_entry("teleport_y", 0, false, false);
00325       set_spin("teleport_eggnum", qual);
00326       }
00327     break;
00328     }
00329   case 8:       // Weather:
00330     set_optmenu("weather_type", data1&0xff); 
00331     set_spin("weather_length", data1>>8);
00332     break;
00333   case 9:       // Path:
00334     set_spin("pathegg_num", data1&0xff);
00335     break;
00336   case 10:      // Button:
00337     set_spin("btnegg_distance", data1&0xff);
00338     break;
00339   default:
00340     break;
00341     }
00342   return 1;
00343   }
00344 
00345 /*
00346  *  Callback for when user clicked where egg should be inserted.
00347  */
00348 
00349 static void Egg_response
00350   (
00351   Exult_server::Msg_type id,
00352   unsigned char *data,
00353   int datalen,
00354   void * /* client */
00355   )
00356   {
00357   if (id == Exult_server::user_responded)
00358     ExultStudio::get_instance()->close_egg_window();
00359   //+++++cancel??
00360   }
00361 
00362 /*
00363  *  Send updated egg info. back to Exult.
00364  *
00365  *  Output: 0 if error (reported).
00366  */
00367 
00368 int ExultStudio::save_egg_window
00369   (
00370   )
00371   {
00372   cout << "In save_egg_window()" << endl;
00373   unsigned char data[Exult_server::maxlength];
00374           // Get egg (null if creating new).
00375   unsigned long addr = (unsigned long) gtk_object_get_user_data(
00376               GTK_OBJECT(eggwin));
00377   int tx = -1, ty = -1, tz = -1;  // +++++For now.
00378   int shape = -1, frame = -1; // For now.
00379   int type = -1;
00380   GtkWidget *notebook = glade_xml_get_widget(app_xml, "notebook1");
00381   if (notebook)     // 1st is monster (1).
00382     type = 1 + gtk_notebook_get_current_page(
00383             GTK_NOTEBOOK(notebook));
00384   else
00385     {
00386     cout << "Can't find notebook widget" << endl;
00387     return 0;
00388     }
00389   int criteria = get_optmenu("criteria");
00390   int probability = get_spin("probability");
00391   int distance = get_spin("distance");
00392   bool nocturnal = get_toggle("nocturnal"),
00393     once = get_toggle("once"),
00394     hatched = get_toggle("hatched"), 
00395     auto_reset = get_toggle("autoreset");
00396   int data1 = -1, data2 = -1;
00397   switch (type)     // Set notebook page.
00398     {
00399   case 1:       // Monster:
00400     data2 = (get_num_entry("monst_shape")&1023) +
00401       (get_num_entry("monst_frame")<<10);
00402     data1 = (get_optmenu("monst_schedule")<<8) +
00403       (get_optmenu("monst_align")&3) +
00404       (get_spin("monst_count")<<2);
00405     break;
00406   case 2:       // Jukebox:
00407     data1 = (get_spin("juke_song")&0xff) +
00408       (get_toggle("juke_cont")<<8);
00409     break;
00410   case 3:       // Sound effect:
00411     data1 = (get_spin("sfx_number")&0xff) +
00412       (get_toggle("sfx_cont")<<8);
00413     break;
00414   case 4:       // Voice:
00415     data1 = get_spin("speech_number")&0xff;
00416     break;
00417   case 5:       // Usecode:
00418     data2 = get_num_entry("usecode_number");
00419     data1 = get_spin("usecode_quality")&0xff;
00420     break;
00421   case 6:       // Missile:
00422     data1 = get_num_entry("missile_shape");
00423     data2 = (get_optmenu("missile_dir")&0xff) +
00424       (get_spin("missile_delay")<<8);
00425     break;
00426   case 7:       // Teleport:
00427     if (get_toggle("teleport_coord"))
00428       {   // Abs. coords.
00429       int tx = get_num_entry("teleport_x"),
00430           ty = get_num_entry("teleport_y");
00431       data2 = (tx&0xff) + ((ty&0xff)<<8);
00432       int sx = tx/c_tiles_per_schunk,
00433           sy = ty/c_tiles_per_schunk;
00434       data1 = 255 + ((sy*12 + sx)<<8);
00435       }
00436     else      // Egg #.
00437       data1 = get_spin("teleport_eggnum")&0xff;
00438     break;
00439   case 8:       // Weather:
00440     data1 = (get_optmenu("weather_type")&0xff) +
00441       (get_spin("weather_length")<<8);
00442     break;
00443   case 9:       // Path:
00444     data1 = get_spin("pathegg_num")&0xff;
00445     break;
00446   case 10:      // Button:
00447     data1 = get_spin("btnegg_distance")&0xff;
00448     break;
00449   default:
00450     cout << "Unknown egg type" << endl;
00451     return 0;
00452     }
00453   if (Egg_object_out(server_socket, addr, tx, ty, tz,
00454     shape, frame, type, criteria, probability, distance,
00455     nocturnal, once, hatched, auto_reset, data1, data2) == -1)
00456     {
00457     cout << "Error sending egg data to server" <<endl;
00458     return 0;
00459     }
00460   cout << "Sent egg data to server" << endl;
00461   if (!addr)
00462     {
00463     set_statusbar("egg_status", egg_ctx,
00464           "Click on map at place to insert egg");
00465           // Make 'apply' insensitive.
00466     gtk_widget_set_sensitive(glade_xml_get_widget(app_xml, 
00467             "egg_apply_btn"), false);
00468     waiting_for_server = Egg_response;
00469     return 1;   // Leave window open.
00470     }
00471   close_egg_window();
00472   return 1;
00473   }
00474 
00475 /*
00476  *  Paint the shape in the egg 'monster' notebook page.
00477  */
00478 
00479 void ExultStudio::show_egg_monster
00480   (
00481   int x, int y, int w, int h  // Rectangle. w=-1 to show all.
00482   )
00483   {
00484   if (!egg_monster_draw)
00485     return;
00486   egg_monster_draw->configure();
00487           // Yes, this is kind of redundant...
00488   int shnum = get_num_entry("monst_shape");
00489   int frnum = get_num_entry("monst_frame");
00490   egg_monster_draw->draw_shape_centered(shnum, frnum);
00491   if (w != -1)
00492     egg_monster_draw->show(x, y, w, h);
00493   else
00494     egg_monster_draw->show();
00495   }
00496 
00497 /*
00498  *  Set egg monster shape.
00499  */
00500 
00501 void ExultStudio::set_egg_monster
00502   (
00503   int shape,
00504   int frame
00505   )
00506   {
00507   set_entry("monst_shape", shape);
00508   set_entry("monst_frame", frame);
00509   show_egg_monster();
00510   }
00511 

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