File indexing completed on 2024-04-28 04:05:20

0001 /*
0002     SPDX-FileCopyrightText: 2015 Jakob Gruber <jakob.gruber@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "scene.h"
0008 
0009 #include "src/constants.h"
0010 
0011 Scene::Scene(QSharedPointer<Picmi> game, QObject *parent) :
0012     QGraphicsScene(parent), m_game(game), m_position(0, 0)
0013 {
0014     init();
0015 }
0016 
0017 void Scene::forwardKeyPressEvent(QKeyEvent *event) {
0018     m_cells[xy_to_i(m_position.x(), m_position.y())]->keyPressEvent(event);
0019 }
0020 
0021 void Scene::loadBanners() {
0022     m_pause_banner = new PauseBannerItem();
0023     m_items.push_back(m_pause_banner);
0024     addItem(m_pause_banner);
0025 }
0026 
0027 void Scene::loadBackground() {
0028     BackgroundItem *p = new BackgroundItem(Renderer::Background, 0, 0);
0029     m_items.push_back(p);
0030     addItem(p);
0031 }
0032 
0033 void Scene::loadCells() {
0034     for (int y = 0; y < m_game->height(); y++) {
0035         for (int x = 0; x < m_game->width(); x++) {
0036             PixmapItem *p = new PixmapItem(Renderer::CellFrame, x, y);
0037             p->setZValue(ZVALUE_CELLFRAME);
0038             m_items.push_back(p);
0039             m_group->addToGroup(p);
0040 
0041             GameCellItem *q = new GameCellItem(x, y, m_game, this);
0042             m_items.push_back(q);
0043             m_cells.push_back(q);
0044             m_group->addToGroup(q);
0045 
0046             HighlightItem *item = new HighlightItem(Renderer::Highlight, x, y);
0047             m_items.push_back(item);
0048             m_highlights.push_back(item);
0049             m_group->addToGroup(item);
0050         }
0051     }
0052 }
0053 
0054 void Scene::loadOverView() {
0055     m_overview_group = new QGraphicsItemGroup;
0056     m_overview_group->setEnabled(false);
0057     for (int y = 0; y < m_game->height(); y++) {
0058         for (int x = 0; x < m_game->width(); x++) {
0059             OverviewCellItem *q = new OverviewCellItem(x, y, m_game);
0060             m_items.push_back(q);
0061             m_overview_cells.push_back(q);
0062             m_overview_group->addToGroup(q);
0063         }
0064     }
0065     m_group->addToGroup(m_overview_group);
0066 }
0067 
0068 void Scene::loadStreaks() {
0069     for (int x = 0; x < m_game->width(); x++) {
0070         StreakVBackgroundItem *p = new StreakVBackgroundItem((x % 2) ? Renderer::Streak1 : Renderer::Streak2, x);
0071         m_items.push_back(p);
0072         m_group->addToGroup(p);
0073 
0074         ColStreakItem *q = new ColStreakItem(m_game, x);
0075         m_items.push_back(q);
0076         m_col_streaks.push_back(q);
0077         m_group->addToGroup(q);
0078 
0079         m_streak_strings.append(q->toPlainText());
0080     }
0081 
0082     for (int y = 0; y < m_game->height(); y++) {
0083         StreakHBackgroundItem *p = new StreakHBackgroundItem((y % 2) ? Renderer::Streak1 : Renderer::Streak2, y);
0084         m_items.push_back(p);
0085         m_group->addToGroup(p);
0086 
0087         RowStreakItem *q = new RowStreakItem(m_game, y);
0088         m_items.push_back(q);
0089         m_row_streaks.push_back(q);
0090         m_group->addToGroup(q);
0091 
0092         m_streak_strings.append(q->toPlainText());
0093     }
0094 }
0095 
0096 void Scene::loadDividers() {
0097     for (int x = SECTION_SIZE - 1; x < m_game->width() - 1; x += SECTION_SIZE) {
0098         for (int y = 0; y < m_game->height(); y++) {
0099             PixmapItem *item = new PixmapItem(Renderer::Divider, x, y);
0100             item->setZValue(ZVALUE_DIVIDER);
0101             m_items.push_back(item);
0102             m_group->addToGroup(item);
0103         }
0104     }
0105 
0106     for (int y = SECTION_SIZE - 1; y < m_game->height() - 1; y += SECTION_SIZE) {
0107         for (int x = 0; x < m_game->width(); x++) {
0108             PixmapItem *item = new PixmapItem(Renderer::Divider, x + 1, y);
0109             item->setRotation(90);
0110             item->setZValue(ZVALUE_DIVIDER);
0111             m_items.push_back(item);
0112             m_group->addToGroup(item);
0113         }
0114     }
0115 }
0116 
0117 void Scene::init() {
0118     const int tilesize = Renderer::instance()->getTilesize();
0119     const int x_offset = Renderer::instance()->getXOffset();
0120     const int y_offset = Renderer::instance()->getYOffset();
0121 
0122     setSceneRect(QRectF(0, 0, m_game->width() * tilesize + x_offset,
0123                         m_game->height() * tilesize + y_offset));
0124 
0125     m_group = new QGraphicsItemGroup;
0126 
0127     loadBanners();
0128     loadBackground();
0129     loadCells();
0130     loadOverView();
0131     loadStreaks();
0132     loadDividers();
0133 
0134     m_group->setHandlesChildEvents(false);
0135     m_group->setPos(x_offset, y_offset);
0136     addItem(m_group);
0137 
0138     m_cells[0]->setFocus();
0139     updateHighlights();
0140 
0141     connect(m_game.data(), &Picmi::gameCompleted, this, &Scene::onGameCompleted);
0142 }
0143 
0144 void Scene::refresh() {
0145     for (int i = 0; i < (int)m_cells.size(); i++) {
0146         m_cells[i]->refresh();
0147         m_overview_cells[i]->refresh();
0148     }
0149     for (int i = 0; i < (int)m_row_streaks.size(); i++) {
0150         m_row_streaks[i]->refresh();
0151     }
0152     for (int i = 0; i < (int)m_col_streaks.size(); i++) {
0153         m_col_streaks[i]->refresh();
0154     }
0155 }
0156 
0157 void Scene::refresh(const QPoint &p) {
0158     const int index = xy_to_i(p.x(), p.y());
0159 
0160     m_cells[index]->refresh();
0161     m_overview_cells[index]->refresh();
0162     m_row_streaks[p.y()]->refresh();
0163     m_col_streaks[p.x()]->refresh();
0164 }
0165 
0166 void Scene::setPaused(bool paused) {
0167     m_game->setPaused(paused);
0168     m_group->setVisible(!paused);
0169     m_pause_banner->setVisible(paused);
0170 }
0171 
0172 void Scene::press(int x, int y, Board::State state) {
0173 
0174     m_position.setX(x);
0175     m_position.setY(y);
0176     m_cells[xy_to_i(x, y)]->setFocus();
0177     updateHighlights();
0178 
0179     m_game->setState(x, y, state);
0180 
0181     refresh(QPoint(x, y));
0182 }
0183 
0184 void Scene::onGameCompleted() {
0185     hideHighlights();
0186     refresh();
0187 }
0188 
0189 void Scene::hover(int x, int y) {
0190     m_position.setX(x);
0191     m_position.setY(y);
0192 
0193     m_cells[xy_to_i(x, y)]->setFocus();
0194 
0195     updateHighlights();
0196 }
0197 
0198 void Scene::updateHighlights() {
0199     for (int i = 0; i < (int)m_highlights.size(); i++) {
0200         m_highlights[i]->highlight(m_position);
0201     }
0202 }
0203 
0204 void Scene::hideHighlights() {
0205     for (int i = 0; i < (int)m_highlights.size(); i++) {
0206         m_highlights[i]->setVisible(false);
0207     }
0208 }
0209 
0210 void Scene::move(int dx, int dy) {
0211     int x = m_position.x() + dx;
0212     int y = m_position.y() + dy;
0213     while (x < 0) {
0214         x += m_game->width();
0215     }
0216     while (y < 0) {
0217         y += m_game->height();
0218     }
0219     hover(x % m_game->width(), y % m_game->height());
0220 }
0221 
0222 int Scene::xy_to_i(int x, int y) const {
0223     return y * m_game->width() + x;
0224 }
0225 
0226 void Scene::setOverviewPos() {
0227     int grid = Renderer::instance()->getOverviewTilesize();
0228     int streak_width = Renderer::instance()->getXOffset();
0229     int streak_height = Renderer::instance()->getYOffset();
0230 
0231     /* dimensions of overview */
0232     int height = grid * m_game->height();
0233     int width = grid * m_game->width();
0234 
0235     int xoffset = (streak_width - width) / 2;
0236     int yoffset = (streak_height - height) / 2;
0237 
0238     /*  */
0239     m_overview_group->setPos(xoffset - streak_width, yoffset - streak_height);
0240 
0241 }
0242 
0243 void Scene::setGroupPos(const QSize &size) {
0244     int grid = Renderer::instance()->getTilesize();
0245     int streak_width = Renderer::instance()->getXOffset();
0246     int streak_height = Renderer::instance()->getYOffset();
0247 
0248     /* dimensions of cell area + streaks */
0249     int height = grid * m_game->height() + streak_height;
0250     int width = grid * m_game->width() + streak_width;
0251 
0252     int xoffset = (size.width() - width) / 2;
0253     int yoffset = (size.height() - height) / 2;
0254 
0255     /* m_group contains all elements of the playing field. (0,0) is located
0256        at the left upper corner of the cells area, meaning streaks are located
0257        at negative coordinates.
0258        center the entire area within the available window size */
0259     m_group->setPos(xoffset + streak_width, yoffset + streak_height);
0260 
0261 }
0262 
0263 void Scene::resize(const QSize &size) {
0264     Renderer::instance()->setSize(size, m_game->width(), m_game->height(),
0265                                   m_streak_strings);
0266     setSceneRect(QRectF(0, 0, size.width(), size.height()));
0267     setGroupPos(size);
0268     setOverviewPos();
0269 
0270     for (int i = 0; i < (int)m_items.size(); i++) {
0271         m_items[i]->reload(size);
0272     }
0273 }
0274 
0275 #include "moc_scene.cpp"