File indexing completed on 2023-10-01 04:14:08

0001 /***************************************************************************
0002                                cmaproom.cpp
0003                              -------------------
0004     begin                : Sat Mar 10 2001
0005     copyright            : (C) 2001 by Kmud Developer Team
0006     email                : kmud-devel@kmud.de
0007  ***************************************************************************/
0008 
0009 /***************************************************************************
0010  *                                                                         *
0011  *   This program is free software; you can redistribute it and/or modify  *
0012  *   it under the terms of the GNU General Public License as published by  *
0013  *   the Free Software Foundation; either version 2 of the License, or     *
0014  *   (at your option) any later version.                                   *
0015  *                                                                         *
0016  ***************************************************************************/
0017 
0018 #include "cmaproom.h"
0019 
0020 #include <stdlib.h>
0021 #include <math.h>
0022 
0023 #include <qfontmetrics.h>
0024 #include <qregion.h>
0025 #include <qsize.h>
0026 
0027 #include "cmapmanager.h"
0028 #include "cmappath.h"
0029 #include "cmaptext.h"
0030 #include "cmaplevel.h"
0031 #include "cmapelementutil.h"
0032 #include "cmapview.h"
0033 
0034 #include <kdebug.h>
0035 
0036 CMapRoom::CMapRoom(CMapManager *manager,QRect rect,CMapLevel *level) : CMapElement(manager,rect,level)
0037 {
0038   color = QColor(192,192,192);
0039   useDefaultCol = true;
0040   login = false;
0041   label = "";
0042   labelPosition = HIDE;
0043   description = "";
0044   current = false;
0045   getZone()->m_room_id_count=getZone()->m_room_id_count+1;
0046   m_ID = getZone()->m_room_id_count;
0047 
0048   level->getRoomList()->append(this);
0049 
0050   textRemove();
0051 }
0052 
0053 CMapRoom::~CMapRoom()
0054 {
0055   CMapLevel *l = getLevel();
0056   CMapManager *manager = getManager();
0057 
0058   CMapRoom *swapRoom = manager->findFirstRoom(this);
0059   if (l->getRoomList()->count() > 1) {
0060     CMapRoom *firstRoom = l->getRoomList()->first();
0061     CMapRoom *lastRoom = l->getRoomList()->last();
0062     swapRoom = (firstRoom == this) ? lastRoom : firstRoom;
0063   }
0064 
0065   if (current)
0066     manager->setCurrentRoom(swapRoom);
0067 
0068   if (login)
0069     manager->setLoginRoom(swapRoom);
0070 
0071   // Delete the paths for the room
0072   // First make a copy, as deleting rooms alters this list
0073   QList<CMapPath *> paths = pathList;
0074   foreach (CMapPath *path, paths) {
0075     path->setOpsitePath(nullptr);  // prevents a crash
0076     delete path;
0077   }
0078 
0079   // Same for paths connecting with this room
0080   paths = connectingPaths;
0081   foreach (CMapPath *path, paths) {
0082     path->setOpsitePath(nullptr);  // prevents a crash
0083     delete path;
0084   }
0085 
0086   l->getRoomList()->removeAll(this);
0087 
0088   if (textElement)
0089   {
0090     kDebug() << "CMapRoom room delete so delete text element";
0091     getManager()->deleteElement(textElement);
0092   }
0093 }
0094 
0095 void CMapRoom::setLevel(CMapLevel *level)
0096 {
0097   if (getLevel()) getLevel()->getRoomList()->removeAll(this);
0098   level->getRoomList()->append(this);
0099   CMapElement::setLevel(level);
0100 }
0101 
0102 /** This is used to resize the element */
0103 void CMapRoom::resize(QPoint offset,int resizeId)
0104 {
0105   CMapElement::resize(offset,resizeId);
0106 
0107   foreach (CMapPath *path, pathList)
0108 //    if (!path->getSelected())
0109       path->setCords();
0110 
0111   foreach (CMapPath *path, connectingPaths)
0112 //    if (!path->getSelected())
0113       path->setCords();
0114 }
0115 
0116 /** Used to paint the element at a given location and size
0117   * @param p The painer to paint the element to
0118   * @param pos The position to paint the elmenet
0119   * @param size The size the element should be draw 
0120   * @param zone The current zone being viewed */
0121 void CMapRoom::paintElementResize(QPainter *p,QPoint pos,QSize size,CMapZone *)
0122 {
0123     signed int y1,x1,x2,y2;
0124 
0125     x1 = pos.x()+1;
0126     y1 = pos.y()+1;
0127     x2 = pos.x()+size.width()-1;
0128     y2 = pos.y()+size.height()-1;
0129 
0130     // Draw the room
0131     p->setPen(Qt::white);
0132     p->drawLine(x1,y2,x1,y1);
0133     p->drawLine(x1,y1,x2-1,y1);
0134     p->setPen(Qt::black);
0135     p->drawLine(x1,y2,x2,y2);
0136     p->drawLine(x2,y2,x2,y1);
0137 
0138 
0139     // Findout the color to used to draw the room
0140     if (login)
0141     {
0142         p->setBrush(getManager()->getMapData()->loginColor);
0143         p->setPen(getManager()->getMapData()->loginColor);
0144     }
0145     else
0146     {
0147         if (getUseDefaultCol())
0148         {
0149             p->setBrush(getManager()->getMapData()->defaultRoomColor);
0150             p->setPen(getManager()->getMapData()->defaultRoomColor);
0151 
0152         }
0153         else
0154         {
0155             p->setBrush(getColor());
0156             p->setPen(getColor());
0157     }
0158     }
0159 
0160     // Draw the background of the room
0161     p->drawRect(x1+1,y1+1,size.width()-3,size.height()-3);
0162 
0163 }
0164 
0165 void CMapRoom::paint(QPainter *p,CMapZone *currentZone)
0166 {
0167   // This will paint the room
0168   CMapElement::paint(p,currentZone);
0169 
0170   signed int y1,x1;
0171 
0172   x1 = getX()+1;
0173   y1 = getY()+1;
0174 
0175   // If this is the current room the user is in
0176   // then draw the symbol to show that.
0177   if (getCurrentRoom())
0178   {
0179     QColor curColor = getManager()->getMapData()->currentColor;
0180     // If the marker color is similar to the background one, use a different one to ensure that it's seen
0181     if ((!getUseDefaultCol()) && abs (getColor().hue() - curColor.hue()) < 30) curColor.setHsl((curColor.hue() + 180) % 360, curColor.saturation(), curColor.lightness());
0182     p->setPen(curColor);
0183     p->setBrush(curColor);
0184     p->drawEllipse(x1+4,y1+4,getWidth() - 9,getHeight() -9);
0185   }
0186 
0187   // Draw exits
0188   foreach (CMapPath *path, pathList)
0189   {
0190     path->paint(p, currentZone);
0191     if (path->getSrcDir() == UP)
0192     {
0193       p->setPen(Qt::black);
0194       p->setBrush(Qt::black);
0195 
0196       p->drawPoint(x1+4,y1+3);
0197       p->drawPoint(x1+3,y1+4);
0198       p->drawPoint(x1+4,y1+4);
0199       p->drawPoint(x1+5,y1+4);
0200     }
0201 
0202     if (path->getSrcDir() == DOWN)
0203     {
0204       p->setPen(Qt::black);
0205       p->setBrush(Qt::black);
0206 
0207       p->drawPoint(x1+4,y1+getHeight()-5);
0208       p->drawPoint(x1+3,y1+getHeight()-6);
0209       p->drawPoint(x1+4,y1+getHeight()-6);
0210       p->drawPoint(x1+5,y1+getHeight()-6);
0211     }
0212 
0213     if (path->getSrcDir() == SPECIAL)
0214     {
0215       p->setPen(getManager()->getMapData()->specialColor);
0216       p->setBrush(getManager()->getMapData()->specialColor);
0217 
0218       p->drawEllipse(x1+getWidth()-10,y1+5,5,getHeight()-10);
0219     }
0220   }
0221 }
0222 
0223 void CMapRoom::dragPaint(QPoint offset,QPainter *p,CMapZone *)
0224 {
0225   p->setPen(QColor(255, 255, 255, 128));
0226   p->setBrush(QColor(0, 255, 255, 64));
0227     p->drawRect(getX() + offset.x(),getY() + offset.y(),getWidth(),getHeight());
0228 }
0229 
0230 void CMapRoom::lowerPaint(QPainter *p,CMapZone *z)
0231 {
0232     signed int y1,x1;
0233 
0234     x1 = getX()+1-5;
0235     y1 = getY()+1-5;
0236 
0237     p->setPen(getManager()->getMapData()->lowerRoomColor);
0238     QBrush brush(getManager()->getMapData()->lowerRoomColor);
0239     brush.setStyle(Qt::Dense3Pattern);
0240     p->setBrush(brush);
0241     p->drawRect(x1,y1,getWidth()-2,getHeight()-2);
0242 
0243         foreach (CMapPath *path, *getPathList())
0244           path->lowerPaint(p, z);
0245 }
0246 
0247 void CMapRoom::higherPaint(QPainter *p,CMapZone *z)
0248 {
0249     signed int y1,x1;
0250 
0251     x1 = getX()+6;
0252     y1 = getY()+6;
0253 
0254     p->setPen(getManager()->getMapData()->higherRoomColor);
0255     QBrush brush(getManager()->getMapData()->higherRoomColor);
0256     brush.setStyle(Qt::Dense7Pattern);
0257     p->setBrush(brush);
0258     p->drawRect(x1,y1,getWidth()-2,getHeight()-2);
0259 
0260         foreach (CMapPath *path, *getPathList())
0261           path->higherPaint(p, z);
0262 }
0263 
0264 void CMapRoom::setLabel(QString str)
0265 {
0266     label = str;
0267     if (textElement)
0268     {
0269         textElement->setText(str);
0270     }
0271 }
0272 
0273 CMapElement *CMapRoom::copy(void)
0274 {
0275     CMapRoom *room = new CMapRoom (getManager(),getRect(),getLevel());
0276 
0277     room->setColor(color);
0278     room->setDescription(description);
0279     room->setLabel(label);
0280     room->setUseDefaultCol(useDefaultCol);
0281 
0282     QStringList *oldContents = getContentsList();
0283     QStringList *newContents = room->getContentsList();
0284 
0285     for ( QStringList::Iterator it = oldContents->begin(); it != oldContents->end(); ++it )
0286         (*newContents)+=*it;
0287 
0288     room->setLabelPosition(getLabelPosition());
0289 
0290     setCopiedRoom(room);
0291 
0292     return room;
0293 }
0294 
0295 void CMapRoom::addPath (CMapPath *path)
0296 {
0297     pathList.append(path);
0298 }
0299 
0300 CMapPath *CMapRoom::getPathDirection (directionTyp dir,QString specialCmd)
0301 {
0302     CMapPath *path;
0303     if (dir!=SPECIAL)
0304     {
0305         foreach (path, pathList)
0306         {
0307             if (path->getSrcDir()==dir)
0308             {
0309                 return path;
0310             }
0311         }
0312     }
0313     else
0314     {
0315         foreach (path, pathList)
0316         {
0317             if (path->getSrcDir()==dir)
0318             {
0319                 if (path->getSpecialCmd()==specialCmd)
0320                 {
0321                     return path;
0322                 }
0323             }
0324         }
0325     }
0326 
0327     return nullptr;
0328 }
0329 
0330 CMapRoom *CMapRoom::getPathTarget(directionTyp dir,QString specialCmd)
0331 {
0332   CMapPath *path = getPathDirection(dir, specialCmd);
0333   if (!path) return nullptr;
0334   return path->getDestRoom();
0335 }
0336 
0337 directionTyp CMapRoom::bestDirectionToRoom(CMapRoom *room)
0338 {
0339   int x1 = (getHighX() + getX()) / 2;
0340   int y1 = (getHighY() + getY()) / 2;
0341   int x2 = (room->getHighX() + room->getX()) / 2;
0342   int y2 = (room->getHighY() + room->getY()) / 2;
0343   CMapLevel *level1 = getLevel();
0344   CMapLevel *level2 = room->getLevel();
0345 
0346   directionTyp res = SPECIAL;
0347   if (level1 != level2) {
0348     if ((x1 != x2) || (y1 != y2)) res = ::SPECIAL;
0349     else if (level1->getPrevLevel() == level2) res = ::DOWN;
0350     else if (level1->getNextLevel() == level2) res = ::UP;
0351     return res;
0352   }
0353 
0354   double angle = atan2 (x2 - x1, y2 - y1) * 180 / M_PI;
0355   if ((angle <= 22.5) && (angle >= -22.5)) res = ::SOUTH;
0356   else if ((angle <= 67.5) && (angle >= 22.5)) res = ::SOUTHEAST;
0357   else if ((angle <= 112.5) && (angle >= 67.5)) res = ::EAST;
0358   else if ((angle <= 157.5) && (angle >= 112.5)) res = ::NORTHEAST;
0359   else if ((angle <= -22.5) && (angle >= -67.5)) res = ::SOUTHWEST;
0360   else if ((angle <= -67.5) && (angle >= -112.5)) res = ::WEST;
0361   else if ((angle <= -112.5) && (angle >= -157.5)) res = ::NORTHWEST;
0362   else res = ::NORTH;
0363   return res;
0364 }
0365 
0366 CMapRoom::labelPosTyp CMapRoom::getLabelPosition(void)
0367 {
0368     return labelPosition;
0369 }
0370 
0371 void CMapRoom::setLabelPosition(labelPosTyp pos)
0372 {
0373     if (getLabel()=="") pos=HIDE;
0374 
0375     if (pos!=HIDE)
0376     {
0377         labelPosition = pos;
0378         QPoint p;
0379 
0380         QFont font;
0381         if (textElement)
0382         {
0383             font = textElement->getFont();
0384         }
0385         else
0386         {
0387             // FIXME_jp : Needs to be configurable
0388             // font = kapp->font();
0389             font = QFont("times");
0390         }
0391 
0392         QFontMetrics fm(font);
0393         int width = fm.width(getLabel());
0394         int height = fm.height();
0395 
0396         switch (pos)
0397         {
0398             case CUSTOM    : p = textElement->getLowPos(); break;
0399             case NORTH     : p.setX((getX()+(getWidth()/2)) -(width /2)); p.setY(getY() - height -  10); break;
0400             case NORTHEAST : p.setX(getHighX()+10); p.setY(getY() - height - 10); break;
0401             case EAST      : p.setX(getHighX()+10); p.setY((getY()+(getHeight()/2)) - (height/2)); break;
0402             case SOUTHEAST : p.setX(getHighX()+10); p.setY(getHighY() + 10); break;
0403             case SOUTH     : p.setX((getX()+(getWidth()/2)) -(width /2)); p.setY(getHighY() + 10); break;
0404             case SOUTHWEST : p.setX(getX()-width-10); p.setY(getHighY() + 10); break;
0405             case WEST      : p.setX(getX()-width-10); p.setY((getY()+(getHeight()/2)) - (height/2)); break;
0406             case NORTHWEST : p.setX(getX()-width-10); p.setY(getY() - height -  10); break;
0407             default        : if (textElement)
0408                              {
0409                                 getManager()->deleteElement(textElement);
0410                              }
0411                              textRemove();
0412                              return;
0413         }
0414 
0415         if (!textElement)
0416         {
0417             textElement = CMapElementUtil::createText(getManager(), p, getLevel(), getLabel());
0418             textElement->setLinkElement(this);
0419         }
0420         else
0421         {
0422             QRect rect;
0423             rect.setX(p.x());
0424             rect.setY(p.y());
0425             rect.setWidth(width);
0426             rect.setHeight(height);
0427 
0428             textElement->setRect(rect);
0429         }
0430 
0431     }
0432     else
0433     {
0434         if (textElement)
0435         {
0436             getManager()->deleteElement(textElement);
0437 
0438         }
0439         textRemove();
0440     }
0441 }
0442 
0443 void CMapRoom::setLabelPosition(labelPosTyp pos,CMapText *text)
0444 {
0445     if (getLabel()=="") pos=HIDE;
0446 
0447     if (textElement)
0448     {
0449         getManager()->deleteElement(textElement);
0450     }
0451     textRemove();
0452 
0453     textElement = text; 
0454     textElement->setLinkElement(this);
0455 
0456     setLabelPosition(pos);
0457 }
0458 
0459 void CMapRoom::geometryChanged(void)
0460 {
0461     setLabelPosition(getLabelPosition());
0462 }
0463 
0464 void CMapRoom::textRemove(void)
0465 {
0466     textElement=nullptr;
0467     labelPosition = HIDE;
0468 }
0469 
0470 /** Used to load the properties of the element from a list of properties */
0471 void CMapRoom::loadProperties(KConfigGroup properties)
0472 {
0473     CMapElement::loadProperties(properties);
0474 
0475     setLabel(properties.readEntry("Label",getLabel()));
0476 
0477     setDescription(properties.readEntry("Description",getDescription()));
0478     QColor color=getColor();
0479     color=properties.readEntry("Color",color);
0480 
0481     setColor(color);
0482     setUseDefaultCol(properties.readEntry("DefaultColor",getUseDefaultCol()));
0483     setLabelPosition((CMapRoom::labelPosTyp)properties.readEntry("LabelPos",(int)getLabelPosition()));
0484 
0485     if (properties.hasKey("Current"))
0486     {
0487         bool current = properties.readEntry("Current",getCurrentRoom());
0488         setCurrentRoom(current);
0489     
0490         if (current)
0491         {
0492             getManager()->getActiveView()->playerPositionChanged(this);
0493         }
0494     }
0495 
0496     if (properties.hasKey("Login"))
0497     {
0498         bool login = properties.readEntry("Login",getLoginRoom());
0499         setLoginRoom(login);
0500     }
0501     setRoomID(properties.readEntry("RoomID",m_ID));
0502 
0503     if (properties.hasKey("Contents"))
0504     {
0505         *getContentsList()=properties.readEntry("Contents",QStringList());
0506     }
0507 }
0508 
0509 /** Used to this rooms current room status */
0510 void CMapRoom::setCurrentRoom(bool currentRoom)
0511 {
0512     current = currentRoom;
0513     if (currentRoom)
0514         getManager()->setCurrentRoomWithoutUndo(this);
0515 
0516     getManager()->changedElement(this);
0517 }
0518 
0519 /** Used to this rooms current room status */
0520 void CMapRoom::setLoginRoom(bool loginRoom)
0521 {
0522     login = loginRoom;
0523     if (loginRoom)
0524     {
0525         getManager()->setLoginRoomWithoutUndo(this);
0526     }
0527 
0528     getManager()->changedElement(this);
0529 }
0530 
0531 /** Used to save the properties of the element to a list of properties */
0532 void CMapRoom::saveProperties(KConfigGroup properties)
0533 {
0534     CMapElement::saveProperties(properties);
0535     properties.writeEntry("Label",getLabel());
0536     properties.writeEntry("Description",getDescription());
0537     properties.writeEntry("Color",getColor());
0538     properties.writeEntry("DefaultColor",getUseDefaultCol());
0539     //FIXME_jp : For some reason this was comment out, there must have reason. It needs
0540     //           to be there so there must be a bug somewere else now that it is uncommented
0541     properties.writeEntry("LabelPos",(int)getLabelPosition());
0542     properties.writeEntry("RoomID",getRoomID());
0543     properties.writeEntry("Current",getCurrentRoom());
0544     properties.writeEntry("Login",getLoginRoom());
0545 
0546     if (getContentsList()->count()>0)
0547         properties.writeEntry("Contents",*getContentsList());
0548 }
0549 
0550 /** Used to save the element as an XML object
0551   * @param properties The XML object to save the properties too
0552   * @param doc The XML Document */
0553 void CMapRoom::saveQDomElement(QDomDocument *doc,QDomElement *properties)
0554 {
0555     CMapElement::saveQDomElement(doc,properties);
0556 
0557     writeColor(doc,properties,"Color",getColor());
0558     properties->setAttribute("Label",getLabel());
0559     properties->setAttribute("Description",getDescription());
0560     properties->setAttribute("DefaultColor",getUseDefaultCol());
0561     properties->setAttribute("LabelPos",(int)getLabelPosition());   
0562     properties->setAttribute("RoomID",getRoomID());
0563     properties->setAttribute("Login",getLoginRoom());
0564     if (getLoginRoom())
0565     {
0566         properties->setAttribute("LoginRoom","true");
0567     }
0568     else
0569     {
0570         properties->setAttribute("LoginRoom","false");
0571     }
0572     if (getUseDefaultCol())
0573     {
0574         properties->setAttribute("UseDefaultCol","true");
0575     }
0576     else
0577     {
0578         properties->setAttribute("UseDefaultCol","false");
0579     }
0580 
0581 }
0582 
0583 /** Used to load the properties from a XML object
0584   * @param properties The XML object to load the properties from */
0585 void CMapRoom::loadQDomElement(QDomElement *properties)
0586 {
0587     CMapElement::loadQDomElement(properties);
0588 
0589     setLabel(properties->attribute("Label",getLabel()));
0590     setDescription(properties->attribute("Description",getDescription()));
0591     setUseDefaultCol(readBool(properties,"UseDefaultCol",getUseDefaultCol()));  
0592     setRoomID(readInt(properties,"RoomID",getRoomID()));
0593     setColor(readColor(properties,"Color",getColor()));
0594     setLoginRoom(readBool(properties,"LoginRoom",getLoginRoom()));
0595 }
0596 
0597 /** Used to move the element relative to it's current position */
0598 void CMapRoom::moveBy(QPoint offset)
0599 {
0600     CMapElement::moveBy(offset);
0601 
0602     foreach (CMapPath *path, pathList)
0603         path->setCords();
0604 
0605     foreach (CMapPath *path, connectingPaths)
0606         path->setCords();
0607 }
0608 
0609 void CMapRoom::setRoomID(unsigned int id)
0610 {
0611     if (id > getZone()->m_room_id_count)
0612       getZone()->m_room_id_count = id;
0613       
0614     m_ID = id;
0615 }
0616 
0617 unsigned int CMapRoom::getRoomID(void)
0618 {
0619     return m_ID;
0620 }
0621