Draw blank squares for empty blocks in the grid.

Import vectorwrapper, it's just too convenient. It's only used
in one place for now but I will probably use it more from now on.
This commit is contained in:
King_DuckZ 2020-03-28 21:33:46 +01:00
parent 88be1a1247
commit 0d287a60f1
8 changed files with 127 additions and 20 deletions

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "subprojects/cxxopts"]
path = subprojects/cxxopts
url = https://github.com/jarro2783/cxxopts.git
[submodule "subprojects/vectorwrapper"]
path = subprojects/vectorwrapper
url = http://alarmpi.no-ip.org/gitan/King_DuckZ/vectorwrapper.git

View file

@ -50,4 +50,7 @@ cxxopts_incl = include_directories('subprojects/cxxopts/include', '.')
memcard_proj = subproject('memcard')
memcard_dep = memcard_proj.get_variable('memcard_dep')
vectorwrapper_proj = subproject('vectorwrapper')
vectorwrapper_dep = vectorwrapper_proj.get_variable('vectorwrapper_dep')
subdir('src')

View file

@ -100,10 +100,11 @@ void MemoservWin::open_file_from_dialog() {
m_memcards.push_back(mc::psx::make_memory_card(file.toStdString()));
auto& mc = m_memcards.back();
auto grid = std::make_unique<widget::BlockGrid>(this, 3, g_icon_fps);
auto grid = std::make_unique<widget::BlockGrid>(this, 5, 3, g_icon_fps);
grid->set_icon_size(g_icon_size);
for (const auto& block : mc) {
for (std::size_t n = 0; block.has_magic() and n < block.block_count(); ++n) {
grid->emplace_back(make_qt_animation(block, g_icon_size, g_icon_size, g_icon_fps));
grid->push_back(make_qt_animation(block, g_icon_size, g_icon_size));
}
}
m_main_lay->addWidget(grid.release(), 1, m_grid_count);

View file

@ -38,6 +38,11 @@ executable(app_name,
'make_qt_animation.cpp',
'animated_pixmap.cpp',
include_directories: inc,
dependencies: [qt5_dep, fslib_dep, memcard_dep],
dependencies: [
qt5_dep,
fslib_dep,
memcard_dep,
vectorwrapper_dep
],
install: true,
)

45
src/qt/vec.hpp Normal file
View file

@ -0,0 +1,45 @@
/* Copyright 2020, Michele Santullo
* This file is part of memoserv.
*
* Memoserv is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Memoserv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Memoserv. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vectorwrapper/vectorwrapper.hpp>
#include <QPoint>
#include <cstddef>
namespace duck::detail {
struct VecSimpleXYPoint { int x, y; };
} //namespace duck::detail
namespace vwr {
template <>
struct VectorWrapperInfo<QPoint> {
enum { dimensions = 2 };
typedef int scalar_type;
typedef QPoint vector_type;
static_assert(sizeof(duck::detail::VecSimpleXYPoint) == sizeof(QPoint), "Unexpected QPoint size, maybe you will have to provide get_at()");
enum {
offset_x = offsetof(duck::detail::VecSimpleXYPoint, x),
offset_y = offsetof(duck::detail::VecSimpleXYPoint, y)
};
};
} //namespace vwr
namespace duck {
typedef vwr::Vec<QPoint> qtint2;
} //namespace duck

View file

@ -16,18 +16,36 @@
*/
#include "block_grid.hpp"
#include "vec.hpp"
#include <QPainter>
#include <QTimer>
#include <QPixmap>
#include <QPoint>
#include <algorithm>
namespace duck::widget {
namespace {
const constexpr int g_icon_spacing = 3;
[[gnu::const]]
qtint2 scalar_to_point (int scalar, int max) {
return {
scalar % max,
scalar / max
};
}
[[gnu::const]]
qtint2 to_qtint2 (const QSize& sz) {
return {sz.width(), sz.height()};
}
} //unnamed namespace
BlockGrid::BlockGrid (QWidget* parent, unsigned int columns, float fps) :
BlockGrid::BlockGrid (QWidget* parent, unsigned int rows, unsigned int columns, float fps) :
QWidget(parent),
m_anim_timer(new QTimer(this)),
m_icon_size(-1, -1),
m_rows(rows),
m_columns(columns)
{
fps = std::max(fps, 1.0f);
@ -43,9 +61,9 @@ QSize BlockGrid::minimumSizeHint() const {
QSize BlockGrid::sizeHint() const {
if (m_columns) {
const auto w = icon_width() * m_columns + g_icon_spacing * (1 + m_columns);
const unsigned int rows = size() / m_columns;
const auto h = icon_height() * rows + g_icon_spacing * (rows + 1);
const auto w = icon_size().width() * m_columns + g_icon_spacing * (1 + m_columns);
const unsigned int rows = (m_rows ? m_rows : size() / m_columns);
const auto h = icon_size().height() * rows + g_icon_spacing * (rows + 1);
return {static_cast<int>(w), static_cast<int>(h)};
}
@ -54,12 +72,23 @@ QSize BlockGrid::sizeHint() const {
}
}
unsigned int BlockGrid::icon_width() const {
return m_icons.empty() ? static_cast<unsigned int>(g_icon_spacing) : m_icons.front().size().width();
void BlockGrid::set_icon_size (const QSize& sz) {
if (sz != m_icon_size) {
m_icon_size = sz;
m_empty_icon.reset();
if (m_icon_size.isValid()) {
m_empty_icon = std::make_unique<QPixmap>(m_icon_size);
m_empty_icon->fill(QColor(115, 115, 115, 255));
}
}
}
unsigned int BlockGrid::icon_height() const {
return m_icons.empty() ? static_cast<unsigned int>(g_icon_spacing) : m_icons.front().size().height();
void BlockGrid::set_icon_size (int sz) {
set_icon_size(QSize{sz, sz});
}
QSize BlockGrid::icon_size() const {
return m_icon_size.isValid() ? m_icon_size : QSize(g_icon_spacing, g_icon_spacing);
}
void BlockGrid::push_back (AnimatedPixmap&& anim) {
@ -70,6 +99,17 @@ std::size_t BlockGrid::size() const {
return m_icons.size();
}
unsigned int BlockGrid::rows() const {
if (m_rows) {
return m_rows;
}
else {
const auto widget_h = static_cast<unsigned int>(std::max(this->height(), g_icon_spacing));
const auto ico_spacing_uns = static_cast<unsigned int>(g_icon_spacing);
return (widget_h - ico_spacing_uns) / (icon_size().height() + ico_spacing_uns);
}
}
unsigned int BlockGrid::columns() const {
if (m_columns) {
return m_columns;
@ -78,26 +118,29 @@ unsigned int BlockGrid::columns() const {
const auto widget_w = static_cast<unsigned int>(std::max(this->width(), g_icon_spacing));
const auto ico_spacing_uns = static_cast<unsigned int>(g_icon_spacing);
return (widget_w - ico_spacing_uns) / (icon_width() + ico_spacing_uns);
return (widget_w - ico_spacing_uns) / (icon_size().width() + ico_spacing_uns);
}
}
void BlockGrid::paintEvent (QPaintEvent* event) {
QPainter painter(this);
const int max_col = static_cast<int>(this->columns());
int x = 0;
int y = 0;
int count = 0;
for (auto& ico : m_icons) {
x = g_icon_spacing + (count % max_col) * (g_icon_spacing + ico.size().width());
y = g_icon_spacing + (count / max_col) * (g_icon_spacing + ico.size().height());
auto point = g_icon_spacing + scalar_to_point(count, max_col) * (g_icon_spacing + to_qtint2(ico.size()));
if (ico.frame_count()) {
painter.drawPixmap(x, y, ico.current_frame());
painter.drawPixmap(point.x(), point.y(), ico.current_frame());
}
++count;
}
const int total_squares = static_cast<int>(rows() * columns());
for (int z = count; z < total_squares && m_empty_icon; ++z) {
auto point = g_icon_spacing + scalar_to_point(z, max_col) * (g_icon_spacing + to_qtint2(icon_size()));
painter.drawPixmap(point.x(), point.y(), *m_empty_icon);
}
}
void BlockGrid::advance_frame() {

View file

@ -19,6 +19,7 @@
#include "../animated_pixmap.hpp"
#include <QWidget>
#include <QPixmap>
#include <memory>
#include <vector>
@ -28,14 +29,15 @@ namespace duck::widget {
class BlockGrid : public QWidget {
Q_OBJECT
public:
explicit BlockGrid (QWidget* parent=nullptr, unsigned int columns=0, float fps=24.0f);
explicit BlockGrid (QWidget* parent=nullptr, unsigned int rows=0, unsigned int columns=0, float fps=24.0f);
~BlockGrid() noexcept;
QSize minimumSizeHint() const override;
QSize sizeHint() const override;
unsigned int icon_width() const;
unsigned int icon_height() const;
void set_icon_size (const QSize& sz);
void set_icon_size (int sz);
QSize icon_size() const;
void push_back (AnimatedPixmap&& anim);
std::size_t size() const;
@ -47,10 +49,14 @@ private slots:
void advance_frame();
private:
unsigned int rows() const;
unsigned int columns() const;
std::vector<AnimatedPixmap> m_icons;
QTimer* m_anim_timer;
std::unique_ptr<QPixmap> m_empty_icon;
QSize m_icon_size;
unsigned int m_rows;
unsigned int m_columns;
};
} //namespace duck::widget

@ -0,0 +1 @@
Subproject commit 0a90a289a2c354c88130dbf04a4c15c696e0a9de