File indexing completed on 2024-05-19 07:52:02
0001 /* 0002 This file is part of the game 'KJumpingCube' 0003 0004 SPDX-FileCopyrightText: 1998-2000 Matthias Kiefer <matthias.kiefer@gmx.de> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "kcubewidget.h" 0010 0011 #include <QPainter> 0012 #include <QMouseEvent> 0013 #include <QPaintEvent> 0014 #include <QPixmap> 0015 0016 /* ****************************************************** ** 0017 ** static elements ** 0018 ** ****************************************************** */ 0019 bool KCubeWidget::_clicksAllowed=true; 0020 0021 void KCubeWidget::enableClicks(bool flag) 0022 { 0023 _clicksAllowed=flag; 0024 } 0025 0026 /* ****************************************************** ** 0027 ** public functions ** 0028 ** ****************************************************** */ 0029 0030 KCubeWidget::KCubeWidget (QWidget* parent) 0031 : QFrame(parent) 0032 { 0033 setMinimumSize (20,20); 0034 setFrameStyle(QFrame::Panel | QFrame::Raised); 0035 int h = height(); 0036 int w = width(); 0037 setLineWidth ((h<w?h:w) / 14); // Make QFrame::Raised width proportional. 0038 0039 setCoordinates (0, 0, 2); 0040 0041 migrating = 0; 0042 m_scale = 1.0; 0043 m_row = 0; 0044 m_col = 0; 0045 m_owner = Nobody; 0046 m_value = 1; 0047 0048 pixmaps = nullptr; 0049 blinking = None; 0050 0051 // show values 0052 update(); 0053 } 0054 0055 KCubeWidget::~KCubeWidget() 0056 { 0057 } 0058 0059 void KCubeWidget::setPixmaps (QList<QPixmap> * ptr) 0060 { 0061 pixmaps = ptr; 0062 } 0063 0064 void KCubeWidget::setOwner (Player newOwner) 0065 { 0066 if (newOwner != m_owner) { 0067 m_owner = newOwner; 0068 updateColors(); 0069 } 0070 } 0071 0072 void KCubeWidget::setValue(int newValue) 0073 { 0074 if (newValue != m_value) { 0075 m_value = newValue; 0076 update(); 0077 } 0078 } 0079 0080 void KCubeWidget::shrink (qreal scale) 0081 { 0082 migrating = 0; 0083 m_scale = scale; 0084 update(); 0085 } 0086 0087 void KCubeWidget::expand (qreal scale) 0088 { 0089 migrating = 1; 0090 m_scale = scale; 0091 blinking = None; // Remove overloaded cube's dark color. 0092 update(); 0093 } 0094 0095 void KCubeWidget::migrateDot (int rowDiff, int colDiff, int step, Player player) 0096 { 0097 migrating = 2; 0098 qreal scale = (step < 4) ? 1.0 - 0.3 * step : 0.0; 0099 m_rowDiff = rowDiff * scale; // Calculate relative position of dot. 0100 m_colDiff = colDiff * scale; 0101 // If owner changes, fade in new color as dot approaches centre of cube. 0102 m_player = player; 0103 m_opacity = (step < 4) ? 0.2 * (step + 1) : 1.0; 0104 update(); 0105 } 0106 0107 void KCubeWidget::setCoordinates (int row, int col, int limit) 0108 { 0109 m_row = row; 0110 m_col = col; 0111 m_limit = limit; 0112 } 0113 0114 /* ****************************************************** ** 0115 ** public slots ** 0116 ** ****************************************************** */ 0117 0118 void KCubeWidget::reset() 0119 { 0120 blinking = None; 0121 setValue (1); 0122 setOwner (Nobody); 0123 update(); 0124 } 0125 0126 0127 void KCubeWidget::updateColors() 0128 { 0129 update(); 0130 } 0131 0132 /* ****************************************************** ** 0133 ** Event handler ** 0134 ** ****************************************************** */ 0135 0136 void KCubeWidget::mouseReleaseEvent(QMouseEvent *e) 0137 { 0138 // only accept click if it was inside this cube 0139 const QPoint mousePos = e->position().toPoint(); 0140 if (mousePos.x() < 0 || mousePos.x() > width() || mousePos.y() < 0 || mousePos.y() > height()) 0141 return; 0142 0143 if(e->button() == Qt::LeftButton && _clicksAllowed) { 0144 e->accept(); 0145 Q_EMIT clicked (m_row, m_col); 0146 } 0147 } 0148 0149 void KCubeWidget::paintEvent(QPaintEvent * /* ev unused */) 0150 { 0151 if ((pixmaps == nullptr) || (pixmaps->isEmpty())) 0152 return; 0153 0154 int width = this->width(); 0155 int height = this->height(); 0156 0157 QPainter p(this); 0158 0159 SVGElement el = Neutral; 0160 if (owner() == One) 0161 el = Player1; 0162 else if (owner() == Two) 0163 el = Player2; 0164 0165 // if ((migrating == 2) && (m_player != owner())) // && (m_scale < 0.5)) 0166 // el = m_element; 0167 0168 int pmw = pixmaps->at(el).width(); 0169 int pmh = pixmaps->at(el).height(); 0170 p.drawPixmap ((width - pmw)/2, (height - pmh)/2, pixmaps->at(el)); 0171 if ((migrating == 2) && (m_player != owner())) { 0172 el = (m_player == One) ? Player1 : Player2; 0173 p.setOpacity (m_opacity); // Cube is being captured: fade in new color. 0174 p.drawPixmap ((width - pmw)/2, (height - pmh)/2, pixmaps->at(el)); 0175 p.setOpacity (1.0); 0176 } 0177 0178 QPixmap pip = pixmaps->at(Pip); 0179 int dia = pip.width(); 0180 0181 // Normally scale = 1.0, but it will be less during the first part of an 0182 // animation that shows a cube taking over its neighboring cubes. 0183 0184 int w = m_scale * width; // The size of the pattern of pips. 0185 int h = m_scale * height; 0186 int cx = width/2; // The center point of the cube face. 0187 int cy = height/2; 0188 int tlx = (width - w) / 2; // The top left corner of the pattern of pips. 0189 int tly = (height - h) / 2; 0190 0191 int points = (migrating == 1) ? 0 : value(); 0192 if (migrating == 2) { 0193 int dRow = m_rowDiff * width / 2; 0194 int dCol = m_colDiff * height / 2; 0195 p.drawPixmap (cx + dRow - dia/2, cy + dCol - dia/2, pip); 0196 } 0197 0198 switch (points) { 0199 case 0: 0200 // Show the pattern of pips migrating to neighboring cubes: 0201 // one pip in the center and one migrating to each neighbor. 0202 p.drawPixmap (cx - dia/2, cy - dia/2, pip); 0203 if (m_scale > 1.0) { // The migrating dots have all left this cube. 0204 break; 0205 } 0206 if (m_row > 0) // Neighbor above, if any. 0207 p.drawPixmap (tlx - dia/2, cy - dia/2, pip); 0208 if (m_row < m_limit) // Neighbor below, if any. 0209 p.drawPixmap (width - tlx - dia/2, cy - dia/2, pip); 0210 if (m_col > 0) // Neighbor to left, if any. 0211 p.drawPixmap (cx - dia/2, tly - dia/2, pip); 0212 if (m_col < m_limit) // Neighbor to right, if any. 0213 p.drawPixmap (cx - dia/2, height - tly - dia/2, pip); 0214 break; 0215 0216 // Otherwise show a pattern for the current number of pips. It may be 0217 // scaled down during the first part of an animation that shows a cube 0218 // taking over its neighboring cubes. 0219 case 1: 0220 p.drawPixmap (tlx + (w - dia)/2, tly + (h - dia)/2, pip); 0221 break; 0222 0223 case 3: 0224 p.drawPixmap (tlx + (w - dia)/2, tly + (h - dia)/2, pip); 0225 [[fallthrough]]; 0226 case 2: 0227 p.drawPixmap (tlx + (w/2 - dia)/2, tly + (h/2 - dia)/2, pip); 0228 p.drawPixmap (tlx + (3*w/2 - dia)/2, tly + (3*h/2 - dia)/2, pip); 0229 break; 0230 0231 case 5: 0232 p.drawPixmap (tlx + (w - dia)/2, tly + (h - dia)/2, pip); 0233 [[fallthrough]]; 0234 case 4: 0235 p.drawPixmap (tlx + (w/2 - dia)/2, tly + (h/2 - dia)/2, pip); 0236 p.drawPixmap (tlx + (w/2 - dia)/2, tly + (3*h/2 - dia)/2, pip); 0237 p.drawPixmap (tlx + (3*w/2 - dia)/2, tly + (h/2 - dia)/2, pip); 0238 p.drawPixmap (tlx + (3*w/2 - dia)/2, tly + (3*h/2 - dia)/2, pip); 0239 break; 0240 0241 case 8: 0242 p.drawPixmap (tlx + (w - dia)/2, tly + 2*h/3 - dia/2, pip); 0243 [[fallthrough]]; 0244 case 7: 0245 p.drawPixmap (tlx + (w - dia)/2, tly + h/3 - dia/2, pip); 0246 [[fallthrough]]; 0247 case 6: 0248 p.drawPixmap (tlx + (w/2 - dia)/2, tly + (h/2 - dia)/2, pip); 0249 p.drawPixmap (tlx + (w/2 - dia)/2, tly + (h - dia)/2, pip); 0250 p.drawPixmap (tlx + (w/2 - dia)/2, tly + (3*h/2 - dia)/2, pip); 0251 p.drawPixmap (tlx + (3*w/2 - dia)/2, tly + (h/2 - dia)/2, pip); 0252 p.drawPixmap (tlx + (3*w/2 - dia)/2, tly + (h - dia)/2, pip); 0253 p.drawPixmap (tlx + (3*w/2 - dia)/2, tly + (3*h/2 - dia)/2, pip); 0254 break; 0255 0256 default: 0257 QString s = QString::asprintf("%d",points); 0258 p.setPen(Qt::black); 0259 p.drawText(tlx + w/2,tly + h/2,s); 0260 break; 0261 } 0262 0263 // This is used to highlight a cube and also to perform the hint animation. 0264 switch (blinking) { 0265 case Light: 0266 p.drawPixmap ((width - pmw)/2, (height - pmh)/2, pixmaps->at(BlinkLight)); 0267 break; 0268 case Dark: 0269 p.drawPixmap ((width - pmw)/2, (height - pmh)/2, pixmaps->at(BlinkDark)); 0270 break; 0271 default: 0272 break; 0273 } 0274 migrating = 0; 0275 m_scale = 1.0; 0276 0277 p.end(); 0278 } 0279 0280 #include "moc_kcubewidget.cpp"