Gump.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2003-2007  The Pentagram Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (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 #include "pent_include.h"
00020 #include "Gump.h"
00021 #include "RenderSurface.h"
00022 #include "Shape.h"
00023 #include "ShapeFrame.h"
00024 #include "ShapeArchive.h"
00025 #include "GameData.h"
00026 #include "GumpNotifyProcess.h"
00027 #include "Kernel.h"
00028 #include "IDataSource.h"
00029 #include "ODataSource.h"
00030 #include "ObjectManager.h"
00031 #include "ScalerGump.h"
00032 #include "GUIApp.h"
00033 
00034 DEFINE_RUNTIME_CLASSTYPE_CODE(Gump,Object);
00035 
00036 Gump::Gump()
00037         : Object(), parent(0), children()
00038 {
00039 }
00040 
00041 Gump::Gump(int inX, int inY, int Width, int Height, uint16 inOwner,
00042                    uint32 inFlags, sint32 inLayer) : 
00043         Object(), owner(inOwner), parent(0), x(inX), y(inY),
00044         dims(0,0,Width,Height), flags(inFlags), layer(inLayer), index(-1),
00045         shape(0), framenum(0), children(), focus_child(0), notifier(0),
00046         process_result(0)
00047 {
00048         assignObjId(); // gumps always get an objid
00049 }
00050 
00051 Gump::~Gump()
00052 {
00053         // Get rid of focus
00054         if (focus_child) focus_child->OnFocus(false);
00055         focus_child = 0;
00056 
00057         // Delete all children
00058         std::list<Gump*>::iterator it = children.begin();
00059         std::list<Gump*>::iterator end = children.end();
00060 
00061         while (it != end)
00062         {
00063                 Gump *g = *it;
00064                 it = children.erase(it);
00065                 delete g;
00066         }
00067 }
00068 
00069 void Gump::InitGump(Gump *newparent, bool take_focus)
00070 {
00071         if (newparent)
00072                 newparent->AddChild(this, take_focus);
00073         else
00074                 GUIApp::get_instance()->addGump(this);
00075 
00076         if (owner && !notifier) CreateNotifier();
00077 }
00078 
00079 void Gump::SetShape(FrameID frame, bool adjustsize)
00080 {
00081         shape = GameData::get_instance()->getShape(frame);
00082         framenum = frame.framenum;
00083 
00084         if (adjustsize && shape) {
00085                 ShapeFrame* sf = shape->getFrame(framenum);
00086                 dims.w = sf->width;
00087                 dims.h = sf->height;
00088         }
00089 }
00090 
00091 
00092 void Gump::CreateNotifier()
00093 {
00094         assert(notifier == 0);
00095 
00096         // Create us a GumpNotifyProcess
00097         GumpNotifyProcess *p = new GumpNotifyProcess(owner);
00098         p->setGump(this);
00099         notifier = Kernel::get_instance()->addProcess(p);
00100 }
00101 
00102 void Gump::SetNotifyProcess(GumpNotifyProcess* proc)
00103 {
00104         assert(notifier == 0);
00105         notifier = proc->getPid();
00106 }
00107 
00108 GumpNotifyProcess* Gump::GetNotifyProcess()
00109 {
00110         return p_dynamic_cast<GumpNotifyProcess*>(Kernel::get_instance()->
00111                                                                                           getProcess(notifier));
00112 }
00113 
00114 
00115 void Gump::Close(bool no_del)
00116 {
00117         GumpNotifyProcess* p = GetNotifyProcess();
00118         if (p) {
00119                 p->notifyClosing(process_result);
00120         }
00121         notifier = 0;
00122 
00123         if (!parent) 
00124         {
00125                 flags |= FLAG_CLOSING;
00126                 if (!no_del) delete this;
00127         }
00128         else
00129         {
00130                 flags |= FLAG_CLOSING;
00131                 if (!no_del) flags |= FLAG_CLOSE_AND_DEL;
00132         }
00133 }
00134 
00135 void Gump::RenderSurfaceChanged()
00136 {
00137         // Iterate all children
00138         std::list<Gump*>::reverse_iterator it = children.rbegin();
00139         std::list<Gump*>::reverse_iterator end = children.rend();
00140 
00141         while (it != end)
00142         {
00143                 (*it)->RenderSurfaceChanged();
00144                 ++it;
00145         }
00146 }
00147 
00148 bool Gump::Run(const uint32 framenum)
00149 {
00150         // Iterate all children
00151         std::list<Gump*>::iterator it = children.begin();
00152         std::list<Gump*>::iterator end = children.end();
00153         bool repaint = false;
00154 
00155         while (it != end)
00156         {
00157                 Gump *g = *it;
00158 
00159                 // Run the child if it's not closing
00160                 if (!(g->flags & FLAG_CLOSING)) if (g->Run(framenum)) repaint = true;
00161 
00162                 // If closing, we can kill it
00163                 if (g->flags & FLAG_CLOSING)
00164                 {
00165                         it = children.erase(it);
00166                         FindNewFocusChild();
00167                         if (g->flags & FLAG_CLOSE_AND_DEL) delete g;
00168                 }
00169                 else
00170                 {
00171                         ++it;
00172                 }
00173         }       
00174         return repaint;
00175 }
00176 
00177 void Gump::CloseItemDependents()
00178 {
00179         // Close it, and return
00180         if (flags & FLAG_ITEM_DEPENDENT) 
00181         {
00182                 Close();
00183                 return;
00184         }
00185 
00186         // Pass the MapChanged message to all the children
00187         std::list<Gump*>::iterator it = children.begin();
00188         std::list<Gump*>::iterator end = children.end();
00189 
00190         while (it != end)
00191         {
00192                 Gump *g = *it;
00193 
00194                 // Pass to child if it's not closing
00195                 if (!(g->flags & FLAG_CLOSING)) g->CloseItemDependents();
00196 
00197                 // If closing, we can kill it
00198                 if (g->flags & FLAG_CLOSING)
00199                 {
00200                         it = children.erase(it);
00201                         FindNewFocusChild();
00202                         if (g->flags & FLAG_CLOSE_AND_DEL) delete g;
00203                 }
00204                 else
00205                 {
00206                         ++it;
00207                 }
00208         }
00209 }
00210 
00211 bool Gump::GetMouseCursor(int mx, int my, Shape &shape, sint32 &frame)
00212 {
00213         ParentToGump(mx,my);
00214 
00215 
00216         bool ret = false;
00217 
00218         // This reverse iterates the children
00219         std::list<Gump*>::reverse_iterator it;
00220         for (it = children.rbegin(); it != children.rend(); ++it)
00221         {
00222                 Gump *g = *it;
00223 
00224                 // Not if closing
00225                 if (g->flags & FLAG_CLOSING) continue;
00226 
00227                 // It's got the point
00228                 if (g->PointOnGump(mx,my))
00229                         ret = g->GetMouseCursor(mx, my, shape, frame);
00230 
00231                 if (ret) break;
00232         }
00233 
00234         return ret;
00235 }
00236 
00237 void Gump::Paint(RenderSurface *surf, sint32 lerp_factor, bool scaled)
00238 {
00239         // Don't paint if hidden
00240         if (IsHidden()) return;
00241 
00242         // Get old Origin
00243         int ox=0, oy=0;
00244         surf->GetOrigin(ox, oy);
00245 
00246         // Set the new Origin
00247         int nx=0, ny=0;
00248         GumpToParent(nx,ny);
00249         surf->SetOrigin(ox+nx, oy+ny);
00250 
00251         // Get Old Clipping Rect
00252         Pentagram::Rect old_rect;
00253         surf->GetClippingRect(old_rect);
00254 
00255         // Set new clipping rect
00256         Pentagram::Rect new_rect = dims;
00257         new_rect.Intersect(old_rect);
00258         surf->SetClippingRect(new_rect);
00259 
00260         // Paint This
00261         PaintThis(surf, lerp_factor, scaled);
00262 
00263         // Paint children
00264         PaintChildren(surf, lerp_factor, scaled);
00265 
00266         // Reset The Clipping Rect
00267         surf->SetClippingRect(old_rect);
00268 
00269         // Reset The Origin
00270         surf->SetOrigin(ox, oy);
00271 }
00272 
00273 void Gump::PaintThis(RenderSurface* surf, sint32 /*lerp_factor*/, bool /*scaled*/)
00274 {
00275         if (shape)
00276         {
00277 #if 0
00278                 Pentagram::Rect sr;
00279                 ShapeFrame *f = shape->getFrame(framenum);
00280                 sr.h = f->height;
00281                 sr.w = f->height;
00282                 sr.x = -f->xoff;
00283                 sr.y = -f->yoff;
00284 
00285                 if (surf->CheckClipped(sr))
00286 #endif
00287                         surf->Paint(shape, framenum, 0, 0);
00288 #if 0
00289                 else
00290                         surf->PaintNoClip(shape, framenum, 0, 0);
00291 #endif
00292         }
00293 }
00294 
00295 void Gump::PaintChildren(RenderSurface *surf, sint32 lerp_factor, bool scaled)
00296 {
00297         // Iterate all children
00298         std::list<Gump*>::iterator it = children.begin();
00299         std::list<Gump*>::iterator end = children.end();
00300 
00301         while (it != end)
00302         {
00303                 Gump *g = *it;
00304                 // Paint if not closing
00305                 if (!(g->flags & FLAG_CLOSING)) 
00306                         g->Paint(surf, lerp_factor, scaled);
00307 
00308                 ++it;
00309         }       
00310 }
00311 
00312 void Gump::PaintCompositing(RenderSurface* surf, sint32 lerp_factor,
00313                                                         sint32 sx, sint32 sy)
00314 {
00315         // Don't paint if hidden
00316         if (IsHidden()) return;
00317 
00318         // Get old Origin
00319         int ox=0, oy=0;
00320         surf->GetOrigin(ox, oy);
00321 
00322         // FIXME - Big accuracy problems here with the origin and clipping rect
00323 
00324         // Set the new Origin
00325         surf->SetOrigin(0,0);
00326 
00327         // Get Old Clipping Rect
00328         Pentagram::Rect old_rect;
00329         surf->GetClippingRect(old_rect);
00330 
00331         // Set new clipping rect
00332         int cx=dims.x,cy=dims.y,cw=dims.w,ch=dims.h;
00333         GumpRectToScreenSpace(cx,cy,cw,ch,ROUND_OUTSIDE);
00334         Pentagram::Rect new_rect(cx,cy,cw,ch);
00335         new_rect.Intersect(old_rect);
00336         surf->SetClippingRect(new_rect);
00337 
00338         // Iterate all children
00339         std::list<Gump*>::reverse_iterator it = children.rbegin();
00340         std::list<Gump*>::reverse_iterator end = children.rend();
00341 
00342         while (it != end)
00343         {
00344                 Gump *g = *it;
00345                 // Paint if not closing
00346                 if (!g->IsClosing()) 
00347                         g->PaintCompositing(surf, lerp_factor, sx, sy);
00348 
00349                 ++it;
00350         }       
00351 
00352         // Paint This
00353         PaintComposited(surf, lerp_factor, sx, sy);
00354 
00355         // Reset The Clipping Rect
00356         surf->SetClippingRect(old_rect);
00357 
00358         // Reset The Origin
00359         surf->SetOrigin(ox, oy);
00360 }
00361 
00362 void Gump::PaintComposited(RenderSurface* /*surf*/, sint32 /*lerp_factor*/, sint32 /*scalex*/, sint32 /*scaley*/)
00363 {
00364 }
00365 
00366 Gump* Gump::FindGump(int mx, int my)
00367 {
00368         int gx = mx, gy = my;
00369         ParentToGump(gx, gy);
00370         Gump* gump = 0;
00371 
00372         // Iterate all children
00373         std::list<Gump*>::reverse_iterator it = children.rbegin();
00374         std::list<Gump*>::reverse_iterator end = children.rend();
00375 
00376         while (it != end && !gump)
00377         {
00378                 Gump *g = *it;
00379                 gump = g->FindGump(gx, gy);
00380                 ++it;
00381         }
00382 
00383         // it's over a child
00384         if (gump) return gump;
00385 
00386         // it's over this gump
00387         if (PointOnGump(mx, my)) return this;
00388 
00389         return 0;               
00390 }
00391 
00392 void Gump::setRelativePosition(Gump::Position pos, int xoffset, int yoffset)
00393 {
00394         if (parent)
00395         {
00396                 Pentagram::Rect rect;
00397                 parent->GetDims(rect);
00398 
00399                 switch (pos)
00400                 {
00401                 case CENTER:
00402                         Move(rect.w / 2 - dims.w / 2 + xoffset,
00403                                  rect.h / 2 - dims.h / 2 + yoffset);
00404                         break;
00405                 case TOP_LEFT:
00406                         Move(xoffset, yoffset);
00407                         break;
00408                 case TOP_RIGHT:
00409                         Move(rect.w - dims.w + xoffset, yoffset);
00410                         break;
00411                 case BOTTOM_LEFT:
00412                         Move(xoffset, rect.h - dims.h + yoffset);
00413                         break;
00414                 case BOTTOM_RIGHT:
00415                         Move(rect.w - dims.w + xoffset, rect.h - dims.h + yoffset);
00416                         break;
00417                 case TOP_CENTER:
00418                         Move(rect.w / 2 - dims.w / 2 + xoffset, yoffset);
00419                         break;
00420                 case BOTTOM_CENTER:
00421                         Move(rect.w / 2 - dims.w / 2 + xoffset, rect.h - dims.h + yoffset);
00422                         break;
00423                 default:
00424                         break;
00425                 }
00426         }
00427 }
00428 
00429 bool Gump::PointOnGump(int mx, int my)
00430 {
00431         int gx = mx, gy = my;
00432         ParentToGump(gx,gy);
00433 
00434         // First check again rectangle
00435         if (!dims.InRect(gx,gy)) {
00436                 return false;
00437         }
00438 
00439         if (!shape) {
00440                 // no shape? Then if it's in the rectangle it's on the gump.
00441                 return true;
00442         }
00443 
00444         ShapeFrame* sf = shape->getFrame(framenum);
00445         assert(sf);
00446         if (sf->hasPoint(gx, gy)) {
00447                 return true;
00448         }
00449 
00450         // reverse-iterate children
00451         std::list<Gump*>::reverse_iterator it;
00452         for (it = children.rbegin(); it != children.rend(); ++it)
00453         {
00454                 Gump *g = *it;
00455 
00456                 // It's got the point
00457                 if (g->PointOnGump(gx,gy)) return true;
00458         }
00459 
00460         return false;
00461 }
00462 
00463 // Convert a screen space point to a gump point
00464 void Gump::ScreenSpaceToGump(int &sx, int &sy, PointRoundDir r)
00465 {
00466         // This is a recursive operation. We get each
00467         // parent to convert the point into their local
00468         // coords. 
00469         if (parent) parent->ScreenSpaceToGump(sx,sy,r);
00470 
00471         ParentToGump(sx,sy,r);
00472 }
00473 
00474 // Convert a gump point to a screen space point
00475 void Gump::GumpToScreenSpace(int &gx, int &gy, PointRoundDir r)
00476 {
00477         // This is a recursive operation. We get each
00478         // gump to convert the point to their parent
00479 
00480         GumpToParent(gx,gy,r);
00481 
00482         if (parent) parent->GumpToScreenSpace(gx,gy,r);
00483 }
00484 
00485 // Convert a parent relative point to a gump point
00486 void Gump::ParentToGump(int &px, int &py, PointRoundDir)
00487 {
00488         px -= x;
00489         px += dims.x;
00490         py -= y;
00491         py += dims.y;
00492 }
00493 
00494 // Convert a gump point to parent relative point
00495 void Gump::GumpToParent(int &gx, int &gy, PointRoundDir)
00496 {
00497         gx -= dims.x;
00498         gx += x;
00499         gy -= dims.y;
00500         gy += y;
00501 }
00502 
00503 // Transform a rectangle to screenspace from gumpspace
00504 void Gump::GumpRectToScreenSpace(int &gx, int &gy, int &gw, int &gh,
00505                                                                  RectRoundDir r)
00506 {
00507         PointRoundDir tl = (r==ROUND_INSIDE ? ROUND_BOTTOMRIGHT : ROUND_TOPLEFT);
00508         PointRoundDir br = (r==ROUND_OUTSIDE ? ROUND_BOTTOMRIGHT : ROUND_TOPLEFT);
00509 
00510         int x1 = gx, y1 = gy;
00511         int x2 = gx+gw, y2 = gy+gh;
00512         GumpToScreenSpace(x1,y1,tl);
00513         GumpToScreenSpace(x2,y2,br);
00514         gx = x1;
00515         gy = y1;
00516         if (gw != 0) gw = x2-x1;
00517         if (gh != 0) gh = y2-y1;
00518 }
00519 
00520 // Transform a rectangle to gumpspace from screenspace
00521 void Gump::ScreenSpaceToGumpRect(int &sx, int &sy, int &sw, int &sh,
00522                                                                  RectRoundDir r)
00523 {
00524         PointRoundDir tl = (r==ROUND_INSIDE ? ROUND_BOTTOMRIGHT : ROUND_TOPLEFT);
00525         PointRoundDir br = (r==ROUND_OUTSIDE ? ROUND_BOTTOMRIGHT : ROUND_TOPLEFT);
00526 
00527         int x1 = sx, y1 = sy;
00528         int x2 = sx+sw, y2 = sy+sh;
00529         ScreenSpaceToGump(x1,y1,tl);
00530         ScreenSpaceToGump(x2,y2,br);
00531         sx = x1;
00532         sy = y1;
00533         if (sw != 0) sw = x2-x1;
00534         if (sh != 0) sh = y2-y1;
00535 }
00536 
00537 uint16 Gump::TraceObjId(int mx, int my)
00538 {
00539         // Convert to local coords
00540         int gx = mx,gy = my;
00541         ParentToGump(gx,gy);
00542 
00543         uint16 objid = 0;
00544 
00545         // reverse-iterate children
00546         std::list<Gump*>::reverse_iterator it;
00547         for (it = children.rbegin(); it != children.rend(); ++it)
00548         {
00549                 Gump *g = *it;
00550 
00551                 // Not if closing
00552                 if (g->flags & FLAG_CLOSING) continue;
00553 
00554                 // It's got the point
00555                 if (g->PointOnGump(gx,gy)) objid = g->TraceObjId(gx, gy);
00556 
00557                 if (objid && objid != 65535) break;
00558         }
00559 
00560 //      if (!objid || objid == 65535)
00561 //              if (PointOnGump(mx,my))
00562 //                      objid = getObjId();
00563 
00564         return objid;
00565 }
00566 
00567 bool Gump::GetLocationOfItem(uint16 itemid, int &gx, int &gy,
00568                                                          sint32 lerp_factor)
00569 {
00570         gx = 0;
00571         gy = 0;
00572         return false;
00573 }
00574 
00575 // Find a child gump of the specified type
00576 Gump* Gump::FindGump(const RunTimeClassType &t, bool recursive,
00577                                          bool no_inheritance)
00578 {
00579         // If that is our type, then return us!
00580         if (GetClassType() == t) return this;
00581         else if (!no_inheritance && IsOfType(t)) return this;
00582 
00583         // Iterate all children
00584         std::list<Gump*>::iterator      it = children.begin();
00585         std::list<Gump*>::iterator      end = children.end();
00586 
00587         for (;it != end; ++it)
00588         {
00589                 Gump *g = *it;
00590 
00591                 // Not if closing
00592                 if (g->flags & FLAG_CLOSING) continue;
00593 
00594                 if (g->GetClassType() == t) return g;
00595                 else if (!no_inheritance && g->IsOfType(t)) return g;
00596         }
00597 
00598         if (!recursive) return 0;
00599 
00600         // Recursive Iterate all children
00601         it = children.begin();
00602         end = children.end();
00603 
00604         for (;it != end; ++it)
00605         {
00606                 Gump *g = (*it);
00607                         
00608                 // Not if closing
00609                 if (g->flags & FLAG_CLOSING) continue;
00610 
00611                 g = g->FindGump(t,recursive,no_inheritance);
00612 
00613                 if (g) return g;
00614         }
00615 
00616         return 0;
00617 }
00618 
00619 // Makes this gump the focus
00620 void Gump::MakeFocus()
00621 {
00622         // By default we WONT do anything
00623         if (parent)
00624         {
00625                 if (parent->focus_child) parent->focus_child->OnFocus(false);
00626                 parent->focus_child = this;
00627         }
00628         OnFocus(true);
00629 }
00630 
00631 void Gump::FindNewFocusChild()
00632 {
00633         if (focus_child) focus_child->OnFocus(false);
00634         focus_child = 0;
00635 
00636         // Now add the gump to use as the new focus
00637         std::list<Gump*>::reverse_iterator      it = children.rbegin();
00638 
00639         if (it != children.rend())
00640         {
00641                 (*it)->MakeFocus();
00642         }
00643 }
00644 
00645 
00646 // Adds a child to the list
00647 void Gump::AddChild(Gump *gump, bool take_focus)
00648 {
00649         if (!gump) return;
00650 
00651         // Remove it if required
00652         Gump *old_parent = gump->GetParent();
00653         if (old_parent) old_parent->RemoveChild(gump);
00654 
00655         // Now add the gump in the correct spot
00656         std::list<Gump*>::iterator      it = children.begin();
00657         std::list<Gump*>::iterator      end = children.end();
00658 
00659         for (;it != end; ++it)
00660         {
00661                 Gump *other = *it;
00662 
00663                 // Why don't we check for FLAG_CLOSING here?
00664                 // Because we want to make sure that the sort order is always valid
00665 
00666                 // If we are same layer as focus and we wont take it, we will not be
00667                 // placed in front of it
00668                 if (!take_focus && other == focus_child && other->layer == gump->layer)
00669                         break;
00670 
00671                 // Lower layers get placed before higher layers
00672                 if (other->layer > gump->layer) break;
00673         }
00674 
00675         // Now add it
00676         children.insert(it, gump);
00677         gump->parent = this;
00678 
00679         // Make the gump the focus if needed
00680         if (take_focus || !focus_child)
00681         {
00682                 if (focus_child) focus_child->OnFocus(false);
00683                 gump->OnFocus(true);
00684                 focus_child = gump;
00685         }
00686 }
00687 
00688 // Remove a gump from the list
00689 void Gump::RemoveChild(Gump *gump)
00690 {
00691         if (!gump) return;
00692 
00693         // Remove it
00694         children.remove(gump);
00695         gump->parent = 0;
00696 
00697         // Remove focus, the give upper most gump the focus
00698         if (gump == focus_child) 
00699         {
00700                 FindNewFocusChild();
00701         }
00702 }
00703 
00704 void Gump::MoveChildToFront(Gump* gump)
00705 {
00706         if (!gump) return;
00707 
00708         children.remove(gump);
00709 
00710         std::list<Gump*>::iterator      it = children.begin();
00711         std::list<Gump*>::iterator      end = children.end();
00712         for (;it != end; ++it)
00713         {
00714                 Gump *other = *it;
00715 
00716                 // Lower layers get placed before higher layers
00717                 if (other->layer > gump->layer) break;
00718         }
00719 
00720         children.insert(it, gump);
00721 }
00722 
00723 
00724 Gump * Gump::GetRootGump()
00725 {
00726         if (!parent) return this;
00727         return parent->GetRootGump();
00728 }
00729 
00730 
00731 bool Gump::StartDraggingChild(Gump* gump, int mx, int my)
00732 {
00733         return false;
00734 }
00735 
00736 void Gump::DraggingChild(Gump* gump, int mx, int my)
00737 {
00738         CANT_HAPPEN();
00739 }
00740 
00741 void Gump::StopDraggingChild(Gump* gump)
00742 {
00743         CANT_HAPPEN();
00744 }
00745 
00746 //
00747 // Input handling
00748 //
00749 
00750 Gump *Gump::OnMouseDown(int button, int mx, int my)
00751 {
00752         // Convert to local coords
00753         ParentToGump(mx,my);
00754 
00755         Gump *handled = 0;
00756 
00757         // Iterate children backwards
00758         std::list<Gump*>::reverse_iterator it;
00759         for (it = children.rbegin(); it != children.rend(); ++it) {
00760                 Gump *g = *it;
00761 
00762                 // Not if closing
00763                 if (g->flags & FLAG_CLOSING || g->IsHidden()) continue;
00764 
00765                 // It's got the point
00766                 if (g->PointOnGump(mx,my)) handled = g->OnMouseDown(button, mx, my);
00767 
00768                 if (handled) break;
00769         }
00770 
00771         return handled;
00772 }
00773 
00774 Gump *Gump::OnMouseMotion(int mx, int my)
00775 {
00776         // Convert to local coords
00777         ParentToGump(mx,my);
00778 
00779         Gump *handled = 0;
00780 
00781         // Iterate children backwards
00782         std::list<Gump*>::reverse_iterator it;
00783         for (it = children.rbegin(); it != children.rend(); ++it) {
00784                 Gump *g = *it;
00785 
00786                 // Not if closing
00787                 if (g->flags & FLAG_CLOSING || g->IsHidden()) continue;
00788 
00789                 // It's got the point
00790                 if (g->PointOnGump(mx,my)) handled = g->OnMouseMotion(mx, my);
00791 
00792                 if (handled) break;
00793         }
00794 
00795         // All gumps need to handle mouse motion
00796         if (!handled) handled = this;
00797 
00798         return handled;
00799 }
00800 
00801 //
00802 // KeyInput
00803 //
00804 bool Gump::OnKeyDown(int key, int mod)
00805 {
00806         bool handled = false;
00807         if (focus_child) handled = focus_child->OnKeyDown(key, mod);
00808         return handled;
00809 }
00810 
00811 bool Gump::OnKeyUp(int key)
00812 {
00813         bool handled = false;
00814         if (focus_child) handled = focus_child->OnKeyUp(key);
00815         return handled;
00816 }
00817 
00818 bool Gump::OnTextInput(int unicode)
00819 {
00820         bool handled = false;
00821         if (focus_child) handled = focus_child->OnTextInput(unicode);
00822         return handled;
00823 }
00824 
00825 bool Gump::mustSave(bool toplevel)
00826 {
00827         // DONT_SAVE flag
00828         if (flags & FLAG_DONT_SAVE)
00829                 return false;
00830 
00831         if (toplevel) {
00832                 // don't save gumps with parents, unless parent is a core gump
00833                 if (parent && !(parent->flags & FLAG_CORE_GUMP))
00834                         return false;
00835         }
00836 
00837         return true;
00838 }
00839 
00840 void Gump::saveData(ODataSource* ods)
00841 {
00842         Object::saveData(ods);
00843 
00844         ods->write2(owner);
00845         ods->write4(static_cast<uint32>(x));
00846         ods->write4(static_cast<uint32>(y));
00847         ods->write4(static_cast<uint32>(dims.x));
00848         ods->write4(static_cast<uint32>(dims.y));
00849         ods->write4(static_cast<uint32>(dims.w));
00850         ods->write4(static_cast<uint32>(dims.h));
00851         ods->write4(flags);
00852         ods->write4(static_cast<uint32>(layer));
00853         ods->write4(static_cast<uint32>(index));
00854 
00855         uint16 flex = 0;
00856         uint32 shapenum = 0;
00857         if (shape)
00858         {
00859                 shape->getShapeId(flex, shapenum);
00860         }
00861         ods->write2(flex);
00862         ods->write4(shapenum);
00863         
00864         ods->write4(framenum);
00865         if (focus_child)
00866                 ods->write2(focus_child->getObjId());
00867         else
00868                 ods->write2(0);
00869         ods->write2(notifier);
00870         ods->write4(process_result);
00871 
00872         unsigned int childcount = 0;
00873         std::list<Gump*>::iterator it;
00874         for (it = children.begin(); it != children.end(); ++it) {
00875                 if (!(*it)->mustSave(false)) continue;
00876                 childcount++;
00877         }
00878         
00879         // write children:
00880         ods->write4(childcount);
00881         for (it = children.begin(); it != children.end(); ++it) {
00882                 if (!(*it)->mustSave(false)) continue;
00883 
00884                 (*it)->save(ods);
00885         }
00886 }
00887 
00888 bool Gump::loadData(IDataSource* ids, uint32 version)
00889 {
00890         if (!Object::loadData(ids, version)) return false;
00891 
00892         owner = ids->read2();
00893         x = static_cast<sint32>(ids->read4());
00894         y = static_cast<sint32>(ids->read4());
00895 
00896         int dx = static_cast<sint32>(ids->read4());
00897         int dy = static_cast<sint32>(ids->read4());
00898         int dw = static_cast<sint32>(ids->read4());
00899         int dh = static_cast<sint32>(ids->read4());
00900         dims.Set(dx, dy, dw, dh);
00901 
00902         flags = ids->read4();
00903         layer = static_cast<sint32>(ids->read4());
00904         index = static_cast<sint32>(ids->read4());
00905 
00906         shape = 0;
00907         ShapeArchive * flex = GameData::get_instance()->getShapeFlex(ids->read2());
00908         uint32 shapenum = ids->read4();
00909         if (flex)
00910         {
00911                 shape = flex->getShape(shapenum);
00912         }
00913 
00914         framenum = ids->read4();
00915         uint16 focusid = ids->read2();
00916         focus_child = 0;
00917         notifier = ids->read2();
00918         process_result = ids->read4();
00919 
00920         // read children
00921         uint32 childcount = ids->read4();
00922         for (unsigned int i = 0; i < childcount; ++i) {
00923                 Object* obj = ObjectManager::get_instance()->loadObject(ids, version);
00924                 Gump* child = p_dynamic_cast<Gump*>(obj);
00925                 if (!child) return false;
00926 
00927                 AddChild(child, false);
00928 
00929                 if (child->getObjId() == focusid)
00930                         focus_child = child;
00931 
00932         }
00933 
00934         return true;
00935 }
00936 
00937 // Colourless Protection

Generated on Fri Jul 27 22:27:17 2007 for pentagram by  doxygen 1.4.7