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