Gump.cc

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2000 The Exult Team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #  include <config.h>
00021 #endif
00022 
00023 #include "game.h"
00024 #include "gamewin.h"
00025 #include "Gump_button.h"
00026 #include "Gump.h"
00027 #include "misc_buttons.h"
00028 #include "contain.h"
00029 #include "objiter.h"
00030 #include "Gump_manager.h"
00031 #include "cheat.h"
00032 
00033 /*
00034  *  Create a gump.
00035  */
00036 
00037 Gump::Gump
00038   (
00039   Container_game_object *cont,  // Container it represents.
00040   int initx, int inity,     // Coords. on screen.
00041   int shnum,      // Shape #.
00042   ShapeFile shfile
00043   ) : ShapeID(shnum, 0, shfile), container(cont), x(initx), y(inity), check_button(0)
00044 {
00045 }
00046 
00047 /*
00048  *  Create, centered on screen.
00049  */
00050 
00051 Gump::Gump
00052   (
00053   Container_game_object *cont,  // Container it represents.
00054   int shnum,      // Shape #.
00055   ShapeFile shfile
00056   ) : ShapeID(shnum, 0, shfile), container(cont), check_button(0)
00057 {
00058   Shape_frame *shape = get_shape();
00059   x = (gwin->get_width() - shape->get_width())/2;
00060   y = (gwin->get_height() - shape->get_height())/2;
00061 }
00062 
00063 /*
00064  *  Delete gump.
00065  */
00066 
00067 Gump::~Gump()
00068 {
00069   if( check_button )
00070   {
00071     delete check_button;
00072     check_button = 0;
00073   } 
00074 }
00075 
00076 /*
00077  *   Set centered.  
00078  */
00079 void Gump::set_pos()
00080 {
00081   Shape_frame *shape = get_shape();
00082   x = (gwin->get_width() - shape->get_width())/2;
00083   y = (gwin->get_height() - shape->get_height())/2;
00084 }
00085 
00086 /*
00087  *  Sets object area and creates checkmark button
00088  */
00089 
00090 void Gump::set_object_area
00091   (
00092   Rectangle area,
00093   int checkx,
00094   int checky
00095   )
00096 {
00097   object_area = area;
00098   checkx += 16; checky -= 12;
00099   check_button = new Checkmark_button(this, checkx, checky);
00100 }
00101 
00102 /*
00103  *  Get screen rectangle for one of our objects.
00104  */
00105 
00106 Rectangle Gump::get_shape_rect
00107   (
00108   Game_object *obj
00109   )
00110 {
00111   Shape_frame *s = obj->get_shape();
00112   if (!s)
00113     return Rectangle(0, 0, 0, 0);
00114   return Rectangle(x + object_area.x + obj->get_cx() - s->get_xleft(), 
00115        y + object_area.y + obj->get_cy() - s->get_yabove(), 
00116          s->get_width(), s->get_height());
00117 }
00118 
00119 /*
00120  *  Get screen location of object within.
00121  */
00122 
00123 void Gump::get_shape_location
00124   (
00125   Game_object *obj, 
00126   int& ox, int& oy
00127   )
00128 {
00129   ox = x + object_area.x + obj->get_cx(),
00130   oy = y + object_area.y + obj->get_cy();
00131 }
00132 
00133 /*
00134  *  Find object a screen point is on.
00135  *
00136  *  Output: Object found, or null.
00137  */
00138 
00139 Game_object *Gump::find_object
00140   (
00141   int mx, int my      // Mouse pos. on screen.
00142   )
00143 {
00144   int cnt = 0;
00145   Game_object *list[100];
00146   if (!container)
00147     return (0);
00148   Object_iterator next(container->get_objects());
00149   Game_object *obj;
00150   Shape_frame *s;
00151 
00152   int ox, oy;
00153 
00154   while ((obj = next.get_next()) != 0)
00155   {
00156     Rectangle box = get_shape_rect(obj);
00157     if (box.has_point(mx, my))
00158     {
00159       s = obj->get_shape();
00160       get_shape_location(obj, ox, oy);
00161       if (s->has_point(mx-ox, my-oy))
00162         list[cnt++] = obj;
00163     }
00164     obj = obj->get_next();
00165   }
00166           // ++++++Return top item.
00167   return (cnt ? list[cnt - 1] : 0);
00168 }
00169 
00170 /*
00171  *  Get the entire screen rectangle covered by this gump and its contents.
00172  */
00173 
00174 Rectangle Gump::get_dirty
00175   (
00176   )
00177 {
00178   Rectangle rect = get_rect();
00179   if (!container)
00180     return rect;
00181   Object_iterator next(container->get_objects());
00182   Game_object *obj;
00183   while ((obj = next.get_next()) != 0)
00184   {
00185     Rectangle orect = get_shape_rect(obj);
00186     rect = rect.add(orect);
00187   }
00188   return rect;
00189 }
00190 
00191 /*
00192  *  Get object this belongs to.
00193  */
00194 
00195 Game_object *Gump::get_owner()
00196 { 
00197   return container; 
00198 }
00199 
00200 /*
00201  *  Is a given screen point on the checkmark?
00202  *
00203  *  Output: ->button if so.
00204  */
00205 
00206 Gump_button *Gump::on_button
00207   (
00208   int mx, int my      // Point in window.
00209   )
00210 {
00211   return (check_button->on_button(mx, my) ?
00212       check_button : 0);
00213 }
00214 
00215 /*
00216  *  Add an object.  If mx, my, sx, sy are all -1, the object's position
00217  *  is calculated by 'paint()'.  If they're all -2, it's assumed that
00218  *  obj->cx, obj->cy are already correct.
00219  *
00220  *  Output: 0 if cannot add it.
00221  */
00222 
00223 int Gump::add
00224   (
00225   Game_object *obj,
00226   int mx, int my,     // Mouse location.
00227   int sx, int sy,     // Screen location of obj's hotspot.
00228   bool dont_check,    // Skip volume check.
00229   bool combine      // True to try to combine obj.  MAY
00230           //   cause obj to be deleted.
00231   )
00232 {
00233   if (!container || (!dont_check && !container->has_room(obj)))
00234     return (0);   // Full.
00235           // Dropping on same thing?
00236   Game_object *onobj = find_object(mx, my);
00237           // If possible, combine.
00238 
00239   if (onobj && onobj != obj && onobj->drop(obj))
00240     return (1);
00241 
00242   if (!container->add(obj, dont_check)) // DON'T combine here.
00243     return (0);
00244 
00245           // Not a valid spot?
00246   if (sx == -1 && sy == -1 && mx == -1 && my == -1)
00247           // Let paint() set spot.
00248     obj->set_chunk(255, 255);
00249           // -2's mean cx, cy are already set.
00250   else if (sx != -2 && sy != -2 && mx != -2 && my != -2)
00251   {     // Put it where desired.
00252     sx -= x + object_area.x;// Get point rel. to object_area.
00253     sy -= y + object_area.y;
00254     Shape_frame *shape = obj->get_shape();
00255           // But shift within range.
00256     if (sx - shape->get_xleft() < 0)
00257       sx = shape->get_xleft();
00258     else if (sx + shape->get_xright() > object_area.w)
00259       sx = object_area.w - shape->get_xright();
00260     if (sy - shape->get_yabove() < 0)
00261       sy = shape->get_yabove();
00262     else if (sy + shape->get_ybelow() > object_area.h)
00263       sy = object_area.h - shape->get_ybelow();
00264     obj->set_chunk(sx, sy);
00265   }
00266   return (1);
00267 }
00268 
00269 /*
00270  *  Remove object.
00271  */
00272 
00273 void Gump::remove
00274   (
00275   Game_object *obj
00276   )
00277 {
00278   container->remove(obj); 
00279 
00280   // Paint Objects
00281   Rectangle box = object_area;  // Paint objects inside.
00282   box.shift(x, y);    // Set box to screen location.
00283 
00284 
00285   gwin->set_all_dirty();
00286   gwin->paint_dirty();
00287 }
00288 
00289 /*
00290  *  Paint on screen.
00291  */
00292 
00293 void Gump::paint
00294   (
00295   )
00296 {
00297     // Paint the gump itself.
00298   paint_shape(x, y);
00299     
00300     // Paint red "checkmark".
00301   if (check_button) check_button->paint();
00302 
00303   if (!container)
00304     return;     // Empty.
00305   Object_list& objects = container->get_objects();
00306   if (objects.is_empty())
00307     return;     // Empty.
00308   Rectangle box = object_area;  // Paint objects inside.
00309   box.shift(x, y);    // Set box to screen location.
00310   int cury = 0, curx = 0;
00311   int endy = box.h, endx = box.w;
00312   int loop = 0;     // # of times covering container.
00313   Game_object *obj;
00314   Object_iterator next(objects);
00315   while ((obj = next.get_next()) != 0)
00316   {
00317     Shape_frame *shape = obj->get_shape();
00318     if (!shape)
00319       continue;
00320     int objx = obj->get_cx() - shape->get_xleft() + 
00321               1 + object_area.x;
00322     int objy = obj->get_cy() - shape->get_yabove() + 
00323               1 + object_area.y;
00324           // Does obj. appear to be placed?
00325     if (!object_area.has_point(objx, objy) ||
00326         !object_area.has_point(objx + shape->get_xright() - 1,
00327           objy + shape->get_ybelow() - 1))
00328     {   // No.
00329       int px = curx + shape->get_width(),
00330           py = cury + shape->get_height();
00331       if (px > endx)
00332         px = endx;
00333       if (py > endy)
00334         py = endy;
00335       obj->set_chunk(px - shape->get_xright(),
00336           py - shape->get_ybelow());
00337           // Mostly avoid overlap.
00338       curx += shape->get_width() - 1;
00339       if (curx >= endx)
00340       {
00341         cury += 8;
00342         curx = 0;
00343         if (cury >= endy)
00344           cury = 2*(++loop);
00345       }
00346     }
00347     obj->paint_shape(box.x + obj->get_cx(),box.y + obj->get_cy());
00348     obj = obj->get_next();
00349   }
00350           // Outline selections in this gump.
00351   const Game_object_vector& sel = cheat.get_selected();
00352   for (Game_object_vector::const_iterator it = sel.begin();
00353             it != sel.end(); ++it)
00354     {
00355     Game_object *obj = *it;
00356     if (container == obj->get_owner())
00357       {
00358       int x, y;
00359       get_shape_location(obj, x, y);
00360       obj->ShapeID::paint_outline(x, y, HIT_PIXEL);
00361       }
00362     }
00363 }
00364 
00365 /*
00366  *  Close and delete.
00367  */
00368 
00369 void Gump::close
00370   (
00371   )
00372 {
00373   gumpman->close_gump(this);
00374 }
00375 
00376 /*
00377  *  Does the gump have this spot
00378  */
00379 bool Gump::has_point(int sx, int sy)
00380 {
00381   Shape_frame *s = get_shape();
00382 
00383   if (s && s->has_point(sx - x, sy - y)) return true;
00384 
00385   return false;
00386 }
00387 
00388 /*
00389  *  Get screen area used by a gump.
00390  */
00391 
00392 Rectangle Gump::get_rect()
00393 {
00394   Shape_frame *s = get_shape();
00395 
00396   if (!s) return Rectangle(0,0,0,0);
00397     
00398   return Rectangle(x - s->get_xleft(),  y - s->get_yabove(),
00399       s->get_width(), s->get_height());
00400 }
00401 
00402 
00403 /*
00404  *  Container_gump Initialize
00405  */
00406 
00407 void Container_gump::initialize
00408   (
00409   int shnum
00410   )
00411 {
00412   if(shnum==game->get_shape("gumps/box"))
00413   {
00414     set_object_area(Rectangle(46, 28, 74, 32), 8, 56);
00415   }
00416   else if(shnum==game->get_shape("gumps/crate"))
00417   {
00418     set_object_area(Rectangle(50, 20, 80, 24), 8, 64);
00419   }
00420   else if(shnum==game->get_shape("gumps/barrel"))
00421   {
00422     set_object_area(Rectangle(32, 32, 40, 40), 12, 124);
00423   }
00424   else if(shnum==game->get_shape("gumps/bag"))
00425   {
00426     set_object_area(Rectangle(48, 20, 66, 44), 8, 66);
00427   }
00428   else if(shnum==game->get_shape("gumps/backpack"))
00429   {
00430     set_object_area(Rectangle(36, 36, 85, 40), 8, 62);
00431   }
00432   else if(shnum==game->get_shape("gumps/basket"))
00433   {
00434     set_object_area(Rectangle(42, 32, 70, 26), 8, 56);
00435   }
00436   else if(shnum==game->get_shape("gumps/chest"))
00437   {
00438     set_object_area(Rectangle(40, 18, 60, 37), 8, 46);
00439   }
00440   else if(shnum==game->get_shape("gumps/shipshold"))
00441   {
00442     set_object_area(Rectangle(38, 10, 82, 80), 8, 92);
00443   }
00444   else if(shnum==game->get_shape("gumps/drawer"))
00445   {
00446     set_object_area(Rectangle(36, 12, 70, 26), 8, 46);
00447   }
00448   else if(shnum==game->get_shape("gumps/tree"))
00449   {
00450     set_object_area(Rectangle(62, 22, 36, 44), 9, 100);
00451   }
00452   else if(shnum==game->get_shape("gumps/body"))
00453   {
00454     set_object_area(Rectangle(36, 46, 84, 40), 8, 70);
00455   }
00456   else
00457     set_object_area(Rectangle(52, 22, 60, 40));
00458 }
00459 

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