1 // This file is part of Dust Racing 2D.
2 // Copyright (C) 2011 Jussi Lind <jussi.lind@iki.fi>
3 //
4 // Dust Racing 2D is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 // Dust Racing 2D is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Dust Racing 2D. If not, see <http://www.gnu.org/licenses/>.
15 
16 #include "tracktile.hpp"
17 #include "mainwindow.hpp"
18 #include "tileanimator.hpp"
19 
20 #include "../common/config.hpp"
21 
22 #include <QAction>
23 #include <QGraphicsLineItem>
24 #include <QGraphicsScene>
25 #include <QGraphicsView>
26 #include <QPainter>
27 
28 TrackTile * TrackTile::m_activeTile = nullptr;
29 
TrackTile(QPointF location,QPoint matrixLocation,const QString & type)30 TrackTile::TrackTile(QPointF location, QPoint matrixLocation, const QString & type)
31   : TrackTileBase(location, matrixLocation, type)
32   , m_size(QSizeF(width(), height()))
33   , m_active(false)
34   , m_animator(new TileAnimator(this))
35   , m_added(false)
36 {
37     setPos(location);
38 }
39 
TrackTile(const TrackTile & other)40 TrackTile::TrackTile(const TrackTile & other)
41   : QGraphicsItem()
42   , TrackTileBase(other.location(), other.matrixLocation(), other.tileType())
43   , m_size(other.m_size)
44   , m_active(false)
45   , m_animator(new TileAnimator(this))
46   , m_added(false)
47 {
48     setPos(other.location());
49     setRotation(other.rotation());
50     setComputerHint(other.computerHint());
51     setExcludeFromMinimap(other.excludeFromMinimap());
52 }
53 
boundingRect() const54 QRectF TrackTile::boundingRect() const
55 {
56     return QRectF(-m_size.width() / 2, -m_size.height() / 2, m_size.width(), m_size.height());
57 }
58 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)59 void TrackTile::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
60 {
61     Q_UNUSED(widget)
62     Q_UNUSED(option)
63 
64     painter->save();
65 
66     QPen pen;
67     pen.setJoinStyle(Qt::MiterJoin);
68 
69     // Render the tile pixmap if tile is not cleared.
70     if (tileType() != "clear")
71     {
72         painter->drawPixmap(static_cast<int>(boundingRect().x()), static_cast<int>(boundingRect().y()),
73                             static_cast<int>(boundingRect().width()), static_cast<int>(boundingRect().height()),
74                             m_pixmap);
75 
76         // Mark the tile if it has computer hints set
77         if (computerHint() == TrackTile::ComputerHint::BrakeHard)
78         {
79             painter->fillRect(boundingRect(), QBrush(QColor(255, 0, 0, 128)));
80         }
81         else if (computerHint() == TrackTile::ComputerHint::Brake)
82         {
83             painter->fillRect(boundingRect(), QBrush(QColor(128, 0, 0, 128)));
84         }
85     }
86     else
87     {
88         painter->drawPixmap(static_cast<int>(boundingRect().x()), static_cast<int>(boundingRect().y()),
89                             static_cast<int>(boundingRect().width()), static_cast<int>(boundingRect().height()),
90                             QPixmap(Config::Editor::CLEAR_ICON_PATH));
91 
92         pen.setColor(QColor(0, 0, 0));
93         painter->setPen(pen);
94         painter->drawRect(boundingRect());
95     }
96 
97     // Render highlight
98     if (m_active)
99     {
100         painter->fillRect(boundingRect(), QBrush(QColor(0, 0, 0, 64)));
101     }
102 
103     painter->restore();
104 }
105 
setActive(bool active)106 void TrackTile::setActive(bool active)
107 {
108     m_active = active;
109 
110     if (active && TrackTile::m_activeTile != this)
111     {
112         if (TrackTile::m_activeTile)
113         {
114             TrackTile::m_activeTile->setActive(false);
115         }
116 
117         TrackTile::m_activeTile = this;
118     }
119 
120     update();
121 }
122 
setActiveTile(TrackTile * tile)123 void TrackTile::setActiveTile(TrackTile * tile)
124 {
125     if (tile)
126     {
127         tile->setActive(true);
128     }
129     else
130     {
131         if (activeTile())
132         {
133             activeTile()->setActive(false);
134         }
135 
136         TrackTile::m_activeTile = nullptr;
137     }
138 }
139 
activeTile()140 TrackTile * TrackTile::activeTile()
141 {
142     return TrackTile::m_activeTile;
143 }
144 
rotate90CW()145 bool TrackTile::rotate90CW()
146 {
147     return m_animator->rotate90CW();
148 }
149 
rotate90CCW()150 bool TrackTile::rotate90CCW()
151 {
152     return m_animator->rotate90CCW();
153 }
154 
setTileType(const QString & type)155 void TrackTile::setTileType(const QString & type)
156 {
157     TrackTileBase::setTileType(type);
158     update();
159 }
160 
setComputerHint(ComputerHint hint)161 void TrackTile::setComputerHint(ComputerHint hint)
162 {
163     TrackTileBase::setComputerHint(hint);
164     update();
165 }
166 
setLocation(QPointF location)167 void TrackTile::setLocation(QPointF location)
168 {
169     TrackTileBase::setLocation(location);
170 
171     setPos(location);
172     update();
173 }
174 
pixmap() const175 QPixmap TrackTile::pixmap() const
176 {
177     return m_pixmap;
178 }
179 
setPixmap(const QPixmap & pixmap)180 void TrackTile::setPixmap(const QPixmap & pixmap)
181 {
182     m_pixmap = pixmap;
183     update();
184 }
185 
swap(TrackTile & other)186 void TrackTile::swap(TrackTile & other)
187 {
188     // Swap tile types
189     const auto sourceType = tileType();
190     setTileType(other.tileType());
191     other.setTileType(sourceType);
192 
193     // Swap tile pixmaps
194     const auto sourcePixmap = pixmap();
195     setPixmap(other.pixmap());
196     other.setPixmap(sourcePixmap);
197 
198     // Swap tile rotations
199     const auto sourceAngle = rotation();
200     setRotation(other.rotation());
201     other.setRotation(sourceAngle);
202 
203     // Swap computer hints
204     const auto sourceHint = computerHint();
205     setComputerHint(other.computerHint());
206     other.setComputerHint(sourceHint);
207 }
208 
setAdded(bool state)209 void TrackTile::setAdded(bool state)
210 {
211     m_added = state;
212 }
213 
added() const214 bool TrackTile::added() const
215 {
216     return m_added;
217 }
218 
~TrackTile()219 TrackTile::~TrackTile()
220 {
221     delete m_animator;
222 }
223