File indexing completed on 2024-10-06 03:45:27
0001 /* 0002 This file is part of the KDE games kwin4 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 0010 // own 0011 #include "kfourinline_debug.h" 0012 // KF 0013 #include <KConfig> 0014 #include <KConfigGroup> 0015 // Qt 0016 #include <QGraphicsScene> 0017 // Std 0018 #include <cmath> 0019 0020 // Constructor for the sprite 0021 PixmapSprite::PixmapSprite(const QString &id, ThemeManager *theme, int no, QGraphicsScene *canvas) 0022 : Themeable(id, theme) 0023 , QGraphicsPixmapItem() 0024 { 0025 canvas->addItem(this); 0026 hide(); 0027 setAcceptHoverEvents(false); 0028 0029 mAnimationState = Idle; 0030 mNo = no; 0031 mCurrentFrame = 0; 0032 mOffsetStatus = true; 0033 0034 if (theme) 0035 theme->updateTheme(this); 0036 } 0037 0038 // Constructor for the sprite 0039 PixmapSprite::PixmapSprite(int no, QGraphicsScene *canvas) 0040 : Themeable() 0041 , QGraphicsPixmapItem() 0042 { 0043 canvas->addItem(this); 0044 hide(); 0045 0046 mAnimationState = Idle; 0047 mNo = no; 0048 mCurrentFrame = 0; 0049 mOffsetStatus = true; 0050 } 0051 0052 // Main themeable function. Called for any theme change. The sprites needs to 0053 // resize and redraw here. 0054 void PixmapSprite::changeTheme() 0055 { 0056 // Clear data 0057 mFrames.clear(); 0058 mHotspots.clear(); 0059 0060 // Get scaling change 0061 double oldscale = this->getScale(); 0062 double scale = thememanager()->getScale(); 0063 Themeable::setScale(scale); 0064 0065 // Retrieve theme data from configuration 0066 KConfigGroup config = thememanager()->config(id()); 0067 double width = config.readEntry("width", 1.0); 0068 double height = config.readEntry("height", 0.0); 0069 width *= scale; 0070 height *= scale; 0071 QPointF pos = config.readEntry("pos", QPointF(1.0, 1.0)); 0072 pos *= scale; 0073 // Set fixed z value? 0074 if (config.hasKey("zValue")) { 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 setPos(pos.x(), pos.y()); 0091 } else { 0092 setPos(x() * scale / oldscale, y() * scale / oldscale); 0093 } 0094 0095 // SVG graphics 0096 QString svgid = config.readEntry("svgid"); 0097 // Read sequence of frame pixmaps when auto ID given 0098 QPixmap pixmap; 0099 if (svgid == QLatin1String("auto")) { 0100 for (int i = mStartFrame; i <= mEndFrame; i++) { 0101 QString name = QStringLiteral("frame%1").arg(i); 0102 svgid = config.readEntry(name); 0103 QSize size; 0104 if (!refframe.isNull()) { 0105 size = thememanager()->pixmapSize(svgid, refframe, width); 0106 } else if (config.hasKey("height")) { 0107 size =QSize(int(width), int(height)); 0108 } else { 0109 size = thememanager()->pixmapSize(svgid, width); 0110 } 0111 pixmap = thememanager()->getPixmap(svgid, size); 0112 mFrames.append(pixmap); 0113 if (center) 0114 mHotspots.append(QPointF(size.width() / 2, size.height() / 2)); 0115 else 0116 mHotspots.append(QPointF(0.0, 0.0)); 0117 } 0118 } 0119 // Read only one named pixmap 0120 else { 0121 QSize size; 0122 if (config.hasKey("height")) { 0123 size = QSize(int(width), int(height)); 0124 } else { 0125 size = thememanager()->pixmapSize(svgid, width); 0126 } 0127 pixmap = thememanager()->getPixmap(svgid, size); 0128 mFrames.append(pixmap); 0129 if (center) 0130 mHotspots.append(QPointF(size.width() / 2, size.height() / 2)); 0131 else 0132 mHotspots.append(QPointF(0.0, 0.0)); 0133 } 0134 0135 // Set theme offset (probably not really necessary here) 0136 QPoint offset = thememanager()->getOffset(); 0137 resetTransform(); 0138 if (mOffsetStatus) 0139 setTransform(QTransform::fromTranslate(offset.x(), offset.y()), true); 0140 0141 // Set pixmap to sprite 0142 setFrame(mCurrentFrame, true); 0143 update(); 0144 } 0145 0146 // Debug only: Retrieve double value from configuration file 0147 double PixmapSprite::getDoubleValue(const QString &item) 0148 { 0149 KConfigGroup config = thememanager()->config(id()); 0150 return config.readEntry(item, 0.0); 0151 } 0152 0153 // Move the sprite to the given relative position 0154 void PixmapSprite::setPosition(QPointF pos) 0155 { 0156 mStart = pos; 0157 setPos(mStart.x() * getScale(), mStart.y() * getScale()); 0158 } 0159 0160 // Handle the offset status (true: theme offset, false: no offset) 0161 void PixmapSprite::setOffsetStatus(bool status) 0162 { 0163 mOffsetStatus = status; 0164 changeTheme(); 0165 } 0166 0167 // Store the logical board coordinates for theme changes 0168 void PixmapSprite::setLogicalPos(QPoint pos) 0169 { 0170 mLPos = pos; 0171 } 0172 0173 // Retrieve the logical board coordinates for theme changes 0174 QPoint PixmapSprite::logicalPos() 0175 { 0176 return mLPos; 0177 } 0178 0179 // Start or stop a frame animation 0180 void PixmapSprite::setAnimation(bool status) 0181 { 0182 if (status) 0183 mAnimationState = Animated; 0184 else 0185 mAnimationState = Idle; 0186 mTime.start(); 0187 setFrame(mStartFrame); 0188 } 0189 0190 // Specify and start a frame animation 0191 void PixmapSprite::setAnimation(int start, int end, int delay) 0192 { 0193 mDelay = delay; 0194 mStartFrame = start; 0195 mEndFrame = end; 0196 setAnimation(true); 0197 } 0198 0199 // Set a new bitmap into the sprite. If the number is the same as the 0200 // current one, nothing is done unless forcing is set to true. 0201 void PixmapSprite::setFrame(int no, bool force) 0202 { 0203 if (!force && no == mCurrentFrame) 0204 return; 0205 if (no < 0 || no >= mFrames.count()) 0206 return; 0207 setPixmap(mFrames.at(no)); 0208 0209 QPoint offset = thememanager()->getOffset(); 0210 0211 // Set new item's scene transformation: Hotspot plus global theme offset 0212 resetTransform(); 0213 if (mOffsetStatus) { 0214 setTransform(QTransform::fromTranslate(-mHotspots.at(no).x() + offset.x(), -mHotspots.at(no).y() + offset.y()), true); 0215 } else { 0216 setTransform(QTransform::fromTranslate(-mHotspots.at(no).x(), -mHotspots.at(no).y()), true); 0217 } 0218 mCurrentFrame = no; 0219 update(); 0220 } 0221 0222 // Standard QGI advance method 0223 void PixmapSprite::advance(int phase) 0224 { 0225 int elapsed = mTime.elapsed(); 0226 0227 // Ignore phase 0 (collisions) 0228 if (phase == 0) { 0229 QGraphicsItem::advance(phase); 0230 return; 0231 } 0232 0233 // Handle animation 0234 if (mAnimationState == Animated) { 0235 // Frame delay passed? 0236 int frames = elapsed / mDelay; 0237 int curFrame = frames % (mEndFrame - mStartFrame) + mStartFrame; 0238 setFrame(curFrame); 0239 } 0240 0241 QGraphicsItem::advance(phase); 0242 }