Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a map renderer class #1171

Merged
merged 1 commit into from
Aug 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ add_library(
plrdlg_common.cpp
pregameoptions.cpp
ratesdlg.cpp
renderer.cpp
repodlgs_common.cpp
reqtree.cpp
sciencedlg.cpp
Expand Down
35 changes: 15 additions & 20 deletions client/mapview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "mapview_common.h"
#include "mapview_g.h"
#include "minimap_panel.h"
#include "renderer.h"
#include "sprite.h"
#include "text.h"
#include "tilespec.h"
Expand Down Expand Up @@ -134,7 +135,7 @@ void draw_calculated_trade_routes(QPainter *painter)
Constructor for map
*/
map_view::map_view()
: QWidget(),
: QWidget(), m_renderer(new freeciv::renderer(this)),
m_scale_animation(std::make_unique<QPropertyAnimation>(this, "scale"))
{
menu_click = false;
Expand Down Expand Up @@ -209,6 +210,11 @@ void map_view::zoom_reset() { set_scale(1); }
*/
void map_view::zoom_out() { set_scale(scale() / 1.2); }

/**
* Retrieves the current scale (zoom level) of the map.
*/
double map_view::scale() const { return m_renderer->scale(); }

/**
* Sets the map scale.
*/
Expand All @@ -226,11 +232,7 @@ void map_view::set_scale(double scale)
*/
void map_view::set_scale_now(double scale)
{
m_scale = scale;
// When zoomed in, we pretend that the canvas is smaller than it is. This
// makes text look bad, but everything else is drawn correctly.
map_canvas_resized(width() / m_scale, height() / m_scale);

m_renderer->set_scale(scale);
emit scale_changed(m_scale);
}

Expand Down Expand Up @@ -314,26 +316,19 @@ void map_view::paintEvent(QPaintEvent *event)
QPainter painter;

painter.begin(this);
paint(&painter, event);
m_renderer->render(painter, event->region());
painter.scale(1 / scale(), 1 / scale());
draw_calculated_trade_routes(&painter);
painter.end();
}

/**
Redraws given rectangle on map
* The widget has been resized.
*/
void map_view::paint(QPainter *painter, QPaintEvent *event)
void map_view::resizeEvent(QResizeEvent *event)
{
if (scale() != 1) {
painter->setRenderHint(QPainter::SmoothPixmapTransform);
}
auto widget_rect = QRectF(event->rect());
auto mapview_rect =
QRectF(widget_rect.left() / scale(), widget_rect.top() / scale(),
widget_rect.width() / scale(), widget_rect.height() / scale());
painter->drawPixmap(widget_rect, *mapview.store, mapview_rect);

painter->scale(1 / scale(), 1 / scale());
draw_calculated_trade_routes(painter);
m_renderer->set_viewport_size(event->size());
event->accept();
}

/**
Expand Down
8 changes: 6 additions & 2 deletions client/mapview.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class QPaintEvent;
class QPainter;

class fcwidget;
namespace freeciv {
class renderer;
}

bool is_point_in_area(int x, int y, int px, int py, int pxe, int pye);
void draw_calculated_trade_routes(QPainter *painter);
Expand All @@ -51,7 +54,6 @@ class map_view : public QWidget {

public:
map_view();
void paint(QPainter *painter, QPaintEvent *event);
void find_place(int pos_x, int pos_y, int &w, int &h, int wdth, int hght,
int recursive_nr, bool direction = false);
void resume_searching(int pos_x, int pos_y, int &w, int &h, int wdtht,
Expand All @@ -63,7 +65,7 @@ class map_view : public QWidget {

bool menu_click;

double scale() const { return m_scale; }
double scale() const;

freeciv::tileset_debugger *debugger() const { return m_debugger; }

Expand All @@ -89,6 +91,7 @@ public slots:
void mouseMoveEvent(QMouseEvent *event) override;
void focusOutEvent(QFocusEvent *event) override;
void leaveEvent(QEvent *event) override;
void resizeEvent(QResizeEvent *event) override;

private slots:
void set_scale_now(double scale);
Expand All @@ -98,6 +101,7 @@ private slots:
bool stored_autocenter;
int cursor_frame{0};
int cursor;
freeciv::renderer *m_renderer;
double m_scale = 1;
std::unique_ptr<QPropertyAnimation> m_scale_animation;
QPointer<freeciv::tileset_debugger> m_debugger = nullptr;
Expand Down
1 change: 0 additions & 1 deletion client/page_game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,6 @@ bool fc_game_tab_widget::event(QEvent *event)
? static_cast<QResizeEvent *>(event)->size()
: this->size();
if (event->type() == QEvent::Resize) {
map_canvas_resized(size.width(), size.height());
queen()->message->resize(
qRound((size.width() * king()->qt_settings.chat_fwidth)),
qRound((size.height() * king()->qt_settings.chat_fheight)));
Expand Down
85 changes: 85 additions & 0 deletions client/renderer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* SPDX-FileCopyrightText: 2022 Louis Moureaux <[email protected]>
*
* SPDX-License-Identifier: GPLv3-or-later
*/

#include "renderer.h"

#include "mapview_common.h"

namespace freeciv {

/**
* @class renderer
* @brief Renders the map on widgets
*
* This class is used to draw the map. It can handle zoom via the @ref scale
* property.
*
* @property scale By how much the map is scaled before being drawn (a scale
* of 2 means that everything is 2x bigger)
*/

/**
* Constructor.
*/
renderer::renderer(QObject *parent) : QObject(parent) {}

/**
* Changes the scale of the rendering (zooms in or out).
*/
void renderer::set_scale(double scale)
{
m_scale = scale;

// When zoomed in, we pretend that the canvas is smaller than it actually
// is. This makes text look bad, but everything else is drawn correctly.
map_canvas_resized(m_viewport_size.width() / m_scale,
m_viewport_size.height() / m_scale);
}

/**
* Instructs the renderer to draw a viewport with a different size.
*/
void renderer::set_viewport_size(const QSize &size)
{
m_viewport_size = size;

// When zoomed in, we pretend that the canvas is smaller than it actually
// is. This makes text look bad, but everything else is drawn correctly.
map_canvas_resized(m_viewport_size.width() / m_scale,
m_viewport_size.height() / m_scale);
}

/**
* Renders the specified region of the visible portion of the map on @c
* painter.
* @see @ref render(QPainter&, const QRect&)
*/
void renderer::render(QPainter &painter, const QRegion &region) const
{
for (const auto &rect : region) {
render(painter, rect);
}
}

/**
* Renders the specified area of the visible portion of the map on @c
* painter. This is meant to be used directly from @c paintEvent, so the
* position of
* @c area is relative to the @ref viewport.
*/
void renderer::render(QPainter &painter, const QRect &area) const
{
if (scale() != 1) {
painter.setRenderHint(QPainter::SmoothPixmapTransform);
}

auto mapview_rect =
QRectF(area.left() / scale(), area.top() / scale(),
area.width() / scale(), area.height() / scale());
painter.drawPixmap(area, *mapview.store, mapview_rect);
}

} // namespace freeciv
41 changes: 41 additions & 0 deletions client/renderer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2022 Louis Moureaux <[email protected]>
*
* SPDX-License-Identifier: GPLv3-or-later
*/

#pragma once

#include <QObject>
#include <QPainter>
#include <QRect>
#include <QRegion>
#include <QSize>

namespace freeciv {

class renderer : public QObject {
lmoureaux marked this conversation as resolved.
Show resolved Hide resolved
Q_OBJECT
Q_PROPERTY(double scale READ scale WRITE set_scale);

public:
explicit renderer(QObject *parent = nullptr);
virtual ~renderer() = default;

/// The scale (zoom) at which rendering is performed
double scale() const { return m_scale; }
void set_scale(double scale);

/// The current dimensions of the viewport
QSize viewport_size() const { return m_viewport_size; }
void set_viewport_size(const QSize &size);

void render(QPainter &painter, const QRegion &region) const;
void render(QPainter &painter, const QRect &area) const;

private:
double m_scale = 1.0;
QSize m_viewport_size;
};

} // namespace freeciv