1 | /******************************************************************* |
2 | * |
3 | * Copyright 2006 Dmitry Suzdalev <dimsuz@gmail.com> |
4 | * Copyright 2007 Carsten Niehaus <cniehaus@kde.org> |
5 | * Copyright 2010 Brian Croom <brian.s.croom@gmail.com> |
6 | * |
7 | * This file is part of the KDE project "KAtomic" |
8 | * |
9 | * KAtomic is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by |
11 | * the Free Software Foundation; either version 2, or (at your option) |
12 | * any later version. |
13 | * |
14 | * KAtomic is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU General Public License |
20 | * along with KAtomic; see the file COPYING. If not, write to |
21 | * the Free Software Foundation, 51 Franklin Street, Fifth Floor, |
22 | * Boston, MA 02110-1301, USA. |
23 | * |
24 | ********************************************************************/ |
25 | |
26 | #include "fielditem.h" |
27 | |
28 | #include <QPainter> |
29 | #include <QTimeLine> |
30 | |
31 | #include <kdebug.h> |
32 | #include <klocale.h> |
33 | #include "molecule.h" |
34 | #include "playfield.h" |
35 | |
36 | FieldItem::FieldItem( KGameRenderer* renderer, const QString& spriteKey, QGraphicsScene* scene ) |
37 | : KGameRenderedItem( renderer, spriteKey ), m_fieldX(0), m_fieldY(0) |
38 | { |
39 | if( scene ) |
40 | scene->addItem( this ); |
41 | setShapeMode( BoundingRectShape ); |
42 | } |
43 | |
44 | |
45 | static const char* arrow_spriteKeys[] = {"arrow_Up" , "arrow_Down" , "arrow_Left" , "arrow_Right" }; |
46 | |
47 | ArrowFieldItem::ArrowFieldItem( KGameRenderer* renderer, PlayField::Direction dir, QGraphicsScene* scene ) |
48 | : FieldItem( renderer, arrow_spriteKeys[dir], scene ) |
49 | { |
50 | setOpacity(0.0); //start invisible |
51 | m_timeLine = new QTimeLine(200); |
52 | m_timeLine->setFrameRange( 0, 30 ); |
53 | connect(m_timeLine, SIGNAL(valueChanged(qreal)), SLOT(setOpacity(qreal)) ); |
54 | } |
55 | |
56 | ArrowFieldItem::~ArrowFieldItem() |
57 | { |
58 | delete m_timeLine; |
59 | } |
60 | |
61 | void ArrowFieldItem::setOpacity( qreal opacity ) |
62 | { |
63 | //NOTE: This method is only there because QGI::setOpacity is not a slot. |
64 | QGraphicsItem::setOpacity(opacity); |
65 | } |
66 | |
67 | QVariant ArrowFieldItem::itemChange( GraphicsItemChange change, const QVariant& value ) |
68 | { |
69 | if(change == ItemVisibleChange) |
70 | { |
71 | if(value.toBool()) |
72 | { |
73 | m_timeLine->stop(); |
74 | m_timeLine->setCurrentTime(0); |
75 | m_timeLine->start(); |
76 | } |
77 | } |
78 | return value; |
79 | } |
80 | |
81 | |
82 | |
83 | AtomFieldItem::AtomFieldItem( KGameRenderer* renderer, const atom& at, QGraphicsScene* scene ) |
84 | : FieldItem(renderer, s_names.value(at.obj), scene), m_atomNum(-1) |
85 | { |
86 | if(s_names.empty()) |
87 | { |
88 | fillNameHashes(); |
89 | setSpriteKey(s_names.value(at.obj)); // It wasn't yet filled in when the constructor was called |
90 | } |
91 | |
92 | // create the bonds as child items |
93 | for (int c = 0; c < MAX_CONNS_PER_ATOM; c++) |
94 | { |
95 | char conn = at.conn[c]; |
96 | if (!conn) |
97 | break; |
98 | |
99 | KGameRenderedItem* bond = new KGameRenderedItem(renderer, s_bondNames.value(conn), this); |
100 | bond->setFlag(QGraphicsItem::ItemStacksBehindParent); |
101 | } |
102 | } |
103 | |
104 | void AtomFieldItem::setRenderSize(const QSize& renderSize) |
105 | { |
106 | KGameRenderedItem::setRenderSize(renderSize); |
107 | |
108 | QList<QGraphicsItem*> bonds = childItems(); |
109 | foreach(QGraphicsItem* item, bonds) |
110 | { |
111 | dynamic_cast<KGameRenderedItem*>(item)->setRenderSize(renderSize); |
112 | } |
113 | } |
114 | |
115 | QHash<char, QString> AtomFieldItem::s_names; |
116 | QHash<char, QString> AtomFieldItem::s_bondNames; |
117 | |
118 | void AtomFieldItem::fillNameHashes() |
119 | { |
120 | s_names['1'] = "atom_H" ; |
121 | s_names['2'] = "atom_C" ; |
122 | s_names['3'] = "atom_O" ; |
123 | s_names['4'] = "atom_N" ; |
124 | s_names['5'] = "atom_S" ; |
125 | s_names['6'] = "atom_F" ; |
126 | s_names['7'] = "atom_Cl" ; |
127 | s_names['8'] = "atom_Br" ; |
128 | s_names['9'] = "atom_P" ; |
129 | s_names['0'] = "atom_J" ; |
130 | s_names['o'] = "atom_Crystal" ; |
131 | s_names['A'] = "connector_Hor" ; |
132 | s_names['B'] = "connector_Slash" ; |
133 | s_names['C'] = "connector_Ver" ; |
134 | s_names['D'] = "connector_Backslash" ; |
135 | s_names['#'] = "wall" ; |
136 | s_names['<'] = "arrow_Left" ; |
137 | s_names['>'] = "arrow_Right" ; |
138 | s_names['^'] = "arrow_Up" ; |
139 | s_names['_'] = "arrow_Down" ; |
140 | s_names['E'] = "atom_flask0" ; |
141 | s_names['F'] = "atom_flask1" ; |
142 | s_names['G'] = "atom_flask2" ; |
143 | s_names['H'] = "atom_flask3" ; |
144 | s_names['I'] = "atom_flask4" ; |
145 | s_names['J'] = "atom_flask5" ; |
146 | s_names['K'] = "atom_flask6" ; |
147 | s_names['L'] = "atom_flask7" ; |
148 | |
149 | s_bondNames['a'] = "bond_I_Top" ; |
150 | s_bondNames['b'] = "bond_I_TopRight" ; |
151 | s_bondNames['c'] = "bond_I_Right" ; |
152 | s_bondNames['d'] = "bond_I_BotRight" ; |
153 | s_bondNames['e'] = "bond_I_Bottom" ; |
154 | s_bondNames['f'] = "bond_I_BotLeft" ; |
155 | s_bondNames['g'] = "bond_I_Left" ; |
156 | s_bondNames['h'] = "bond_I_TopLeft" ; |
157 | |
158 | s_bondNames['A'] = "bond_II_Top" ; |
159 | s_bondNames['B'] = "bond_II_Right" ; |
160 | s_bondNames['C'] = "bond_II_Bottom" ; |
161 | s_bondNames['D'] = "bond_II_Left" ; |
162 | |
163 | s_bondNames['E'] = "bond_III_Top" ; |
164 | s_bondNames['F'] = "bond_III_Right" ; |
165 | s_bondNames['G'] = "bond_III_Bottom" ; |
166 | s_bondNames['H'] = "bond_III_Left" ; |
167 | } |
168 | |
169 | QPixmap AtomFieldItem::renderAtom( KGameRenderer* renderer, const atom& at, int size ) |
170 | { |
171 | if (size == 0) return QPixmap(); |
172 | |
173 | QPixmap atomPix = renderer->spritePixmap(s_names.value(at.obj), QSize(size, size)); |
174 | |
175 | QPainter p; |
176 | QPixmap bonds(size,size); |
177 | bonds.fill(Qt::transparent); |
178 | for (int c = 0; c < MAX_CONNS_PER_ATOM; c++) |
179 | { |
180 | char conn = at.conn[c]; |
181 | if (!conn) |
182 | break; |
183 | |
184 | QPixmap pix = renderer->spritePixmap(s_bondNames.value(conn), QSize(size, size)); |
185 | |
186 | p.begin(&bonds); |
187 | p.drawPixmap(0,0, pix); |
188 | p.end(); |
189 | } |
190 | |
191 | p.begin(&bonds); |
192 | p.drawPixmap(0,0, atomPix); |
193 | p.end(); |
194 | return bonds; |
195 | } |
196 | |
197 | // ----------------- MoleculePreviewItem ---------------------------- |
198 | |
199 | MoleculePreviewItem::MoleculePreviewItem( PlayField* scene ) |
200 | : QGraphicsItem( 0, scene ), m_renderer(scene->renderer()), m_width(0), |
201 | m_atomSize(20), m_maxAtomSize(30), m_mol( 0 ) |
202 | { |
203 | } |
204 | |
205 | MoleculePreviewItem::~MoleculePreviewItem() |
206 | { |
207 | } |
208 | |
209 | void MoleculePreviewItem::setMolecule( const Molecule* mol ) |
210 | { |
211 | m_mol = mol; |
212 | setWidth( m_width ); // trigger atom size update |
213 | } |
214 | |
215 | void MoleculePreviewItem::setMaxAtomSize(int maxSize) |
216 | { |
217 | m_maxAtomSize = maxSize; |
218 | setWidth( m_width ); // trigger atom size update |
219 | } |
220 | |
221 | void MoleculePreviewItem::setWidth(int width) |
222 | { |
223 | m_width = width; |
224 | |
225 | if(!m_mol) |
226 | return; |
227 | int w = m_mol->width(); |
228 | int h = m_mol->height(); |
229 | int atomSize = width / qMax(w,h); |
230 | m_atomSize = qMin(atomSize, m_maxAtomSize); |
231 | update(); |
232 | } |
233 | |
234 | void MoleculePreviewItem::paint( QPainter * painter, const QStyleOptionGraphicsItem*, QWidget *) |
235 | { |
236 | if ( m_width == 0 || m_mol == 0 ) |
237 | return; |
238 | |
239 | painter->save(); |
240 | painter->setBrush(Qt::gray); |
241 | painter->setOpacity(0.5); |
242 | painter->drawRect(boundingRect()); |
243 | painter->setOpacity(1.0); |
244 | |
245 | int originX = m_width/2 - m_atomSize*m_mol->width()/2; |
246 | int originY = m_width/2 - m_atomSize*m_mol->height()/2; |
247 | |
248 | // Paint the playing field |
249 | for (int i = 0; i < MOLECULE_SIZE; i++) |
250 | for (int j = 0; j < MOLECULE_SIZE; j++) |
251 | { |
252 | int x = originX + i * m_atomSize; |
253 | int y = originY + j * m_atomSize; |
254 | |
255 | if (m_mol->getAtom(i,j) == 0) |
256 | continue; |
257 | |
258 | int atomIdx = m_mol->getAtom(i,j); |
259 | QPixmap aPix = AtomFieldItem::renderAtom(m_renderer, m_mol->getAtom(atomIdx), m_atomSize); |
260 | painter->drawPixmap(x, y, aPix); |
261 | } |
262 | painter->restore(); |
263 | } |
264 | |
265 | #include "fielditem.moc" |
266 | |