File indexing completed on 2024-04-21 04:05:24
0001 /* 0002 This file is part of the KDE games lskat program 0003 SPDX-FileCopyrightText: 2006 Martin Heni <kde@heni-online.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "pixmapsprite.h" 0009 #include "lskat_debug.h" 0010 0011 // General includes 0012 #include <math.h> 0013 0014 // Qt includes 0015 #include <QGraphicsScene> 0016 0017 // KF includes 0018 #include <KConfig> 0019 #include <KConfigGroup> 0020 0021 // Constructor for the sprite 0022 PixmapSprite::PixmapSprite(const QString &id, ThemeManager *theme, int advancePeriod, int no, QGraphicsScene *canvas) 0023 : Themable(id, theme), QGraphicsPixmapItem(nullptr) 0024 { 0025 canvas->addItem(this); 0026 hide(); 0027 0028 mAnimationState = Idle; 0029 mAdvancePeriod = advancePeriod; 0030 mNo = no; 0031 mCurrentFrame = 0; 0032 mOffsetStatus = true; 0033 0034 if (theme) theme->updateTheme(this); 0035 } 0036 0037 // Constructor for the sprite 0038 PixmapSprite::PixmapSprite(int advancePeriod, int no, QGraphicsScene *canvas) 0039 : Themable(), QGraphicsPixmapItem(nullptr) 0040 { 0041 canvas->addItem(this); 0042 hide(); 0043 0044 mAnimationState = Idle; 0045 mAdvancePeriod = advancePeriod; 0046 mNo = no; 0047 mCurrentFrame = 0; 0048 mOffsetStatus = true; 0049 } 0050 0051 // Main themable function. Called for any theme change. The sprites needs to 0052 // resize and redraw here. 0053 void PixmapSprite::changeTheme() 0054 { 0055 // Clear data 0056 mFrames.clear(); 0057 mHotspots.clear(); 0058 0059 // Get scaling change 0060 double oldscale = this->getScale(); 0061 double scale = thememanager()->getScale(); 0062 Themable::setScale(scale); 0063 0064 // Retrieve theme data from configuration 0065 KConfigGroup config = thememanager()->config(id()); 0066 double width = config.readEntry("width", 1.0); 0067 double height = config.readEntry("height", 0.0); 0068 width *= scale; 0069 height *= scale; 0070 QPointF pos = config.readEntry("pos", QPointF(1.0, 1.0)); 0071 pos *= scale; 0072 // Set fixed z value? 0073 if (config.hasKey("zValue")) 0074 { 0075 double zValue = config.readEntry("zValue", 0.0); 0076 setZValue(zValue); 0077 } 0078 0079 // Centering 0080 bool center = config.readEntry("center", false); 0081 0082 // Animation 0083 mStartFrame = config.readEntry("start-frame", 0); 0084 mEndFrame = config.readEntry("end-frame", 0); 0085 mDelay = config.readEntry("animation-delay", 0); 0086 QString refframe = config.readEntry("ref-frame", QString()); 0087 0088 // Set fixed position or modify current position 0089 if (config.hasKey("pos")) 0090 { 0091 setPos(pos.x(), pos.y()); 0092 } 0093 else 0094 { 0095 setPos(x() * scale / oldscale, y() * scale / oldscale); 0096 } 0097 0098 // SVG graphics 0099 QString svgid = config.readEntry("svgid"); 0100 // Read sequence of frame pixmaps when auto ID given 0101 QPixmap pixmap; 0102 if (svgid == QLatin1String("auto")) 0103 { 0104 const int frameCount = mEndFrame - mStartFrame + 1; 0105 mFrames.reserve(frameCount); 0106 mHotspots.reserve(frameCount); 0107 for (int i = mStartFrame; i <= mEndFrame; i++) 0108 { 0109 QString name = QStringLiteral("frame%1").arg(i); 0110 svgid = config.readEntry(name); 0111 if (!refframe.isNull()) 0112 { 0113 pixmap = thememanager()->getPixmap(svgid, refframe, width); 0114 } 0115 else if (config.hasKey("height")) 0116 { 0117 pixmap = thememanager()->getPixmap(svgid, QSize(int(width), int(height))); 0118 } 0119 else 0120 { 0121 pixmap = thememanager()->getPixmap(svgid, width); 0122 } 0123 mFrames.append(pixmap); 0124 if (center) mHotspots.append(QPointF(pixmap.width() / 2, pixmap.height() / 2)); 0125 else mHotspots.append(QPointF(0.0, 0.0)); 0126 } 0127 } 0128 // Read only one named pixmap 0129 else 0130 { 0131 if (config.hasKey("height")) 0132 { 0133 pixmap = thememanager()->getPixmap(svgid, QSize(int(width), int(height))); 0134 } 0135 else 0136 { 0137 pixmap = thememanager()->getPixmap(svgid, width); 0138 } 0139 mFrames.append(pixmap); 0140 if (center) mHotspots.append(QPointF(pixmap.width() / 2, pixmap.height() / 2)); 0141 else mHotspots.append(QPointF(0.0, 0.0)); 0142 } 0143 0144 // Set pixmap to sprite 0145 setFrame(mCurrentFrame, true); 0146 update(); 0147 } 0148 0149 // Debug only: Retrieve double value from configuration file 0150 double PixmapSprite::getDoubleValue(const QString &item) 0151 { 0152 KConfigGroup config = thememanager()->config(id()); 0153 return config.readEntry(item, 0.0); 0154 } 0155 0156 // Move the sprite to the given relative position 0157 void PixmapSprite::setPosition(const QPointF &pos) 0158 { 0159 mStart = pos; 0160 setPos(mStart.x() * getScale(), mStart.y() * getScale()); 0161 } 0162 0163 // Handle the offset status (true: theme offset, false: no offset) 0164 void PixmapSprite::setOffsetStatus(bool status) 0165 { 0166 mOffsetStatus = status; 0167 changeTheme(); 0168 } 0169 0170 // Start or stop a frame animation 0171 void PixmapSprite::setAnimation(bool status) 0172 { 0173 if (status) mAnimationState = Animated; 0174 else mAnimationState = Idle; 0175 mTime = 0; 0176 setFrame(mStartFrame); 0177 } 0178 0179 // Specify and start a frame animation 0180 void PixmapSprite::setAnimation(int start, int end, int delay) 0181 { 0182 mDelay = delay; 0183 mStartFrame = start; 0184 mEndFrame = end; 0185 setAnimation(true); 0186 } 0187 0188 // Set a new bitmap into the sprite. If the number is the same as the 0189 // current one, nothing is done unless forcing is set to true. 0190 void PixmapSprite::setFrame(int no, bool force) 0191 { 0192 if (!force && no == mCurrentFrame) return; 0193 if (no < 0 || no >= mFrames.count()) return; 0194 setPixmap(mFrames.at(no)); 0195 0196 QPoint offset = thememanager()->getOffset(); 0197 resetTransform(); 0198 if (mOffsetStatus) 0199 { 0200 setTransform(QTransform::fromTranslate(-mHotspots.at(no).x() + offset.x(), -mHotspots.at(no).y() + offset.y()), true); 0201 } 0202 else 0203 { 0204 setTransform(QTransform::fromTranslate(-mHotspots.at(no).x(), -mHotspots.at(no).y()), true); 0205 } 0206 mCurrentFrame = no; 0207 update(); 0208 } 0209 0210 // Standard QGI advance method 0211 void PixmapSprite::advance(int phase) 0212 { 0213 // Ignore phase 0 (collisions) 0214 if (phase == 0) 0215 { 0216 QGraphicsItem::advance(phase); 0217 return; 0218 } 0219 0220 // Increase time 0221 mTime += mAdvancePeriod; 0222 0223 // Handle animation 0224 if (mAnimationState == Animated) 0225 { 0226 // Frame delay passed? 0227 if (mTime > mDelay) 0228 { 0229 mTime = 0; 0230 int frame = mCurrentFrame + 1; 0231 if (frame > mEndFrame) setFrame(mStartFrame); 0232 else setFrame(frame); 0233 } 0234 } 0235 0236 QGraphicsItem::advance(phase); 0237 }