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