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:
parent
88be1a1247
commit
0d287a60f1
8 changed files with 127 additions and 20 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +1,6 @@
|
||||||
[submodule "subprojects/cxxopts"]
|
[submodule "subprojects/cxxopts"]
|
||||||
path = subprojects/cxxopts
|
path = subprojects/cxxopts
|
||||||
url = https://github.com/jarro2783/cxxopts.git
|
url = https://github.com/jarro2783/cxxopts.git
|
||||||
|
[submodule "subprojects/vectorwrapper"]
|
||||||
|
path = subprojects/vectorwrapper
|
||||||
|
url = http://alarmpi.no-ip.org/gitan/King_DuckZ/vectorwrapper.git
|
||||||
|
|
|
@ -50,4 +50,7 @@ cxxopts_incl = include_directories('subprojects/cxxopts/include', '.')
|
||||||
memcard_proj = subproject('memcard')
|
memcard_proj = subproject('memcard')
|
||||||
memcard_dep = memcard_proj.get_variable('memcard_dep')
|
memcard_dep = memcard_proj.get_variable('memcard_dep')
|
||||||
|
|
||||||
|
vectorwrapper_proj = subproject('vectorwrapper')
|
||||||
|
vectorwrapper_dep = vectorwrapper_proj.get_variable('vectorwrapper_dep')
|
||||||
|
|
||||||
subdir('src')
|
subdir('src')
|
||||||
|
|
|
@ -100,10 +100,11 @@ void MemoservWin::open_file_from_dialog() {
|
||||||
|
|
||||||
m_memcards.push_back(mc::psx::make_memory_card(file.toStdString()));
|
m_memcards.push_back(mc::psx::make_memory_card(file.toStdString()));
|
||||||
auto& mc = m_memcards.back();
|
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 (const auto& block : mc) {
|
||||||
for (std::size_t n = 0; block.has_magic() and n < block.block_count(); ++n) {
|
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);
|
m_main_lay->addWidget(grid.release(), 1, m_grid_count);
|
||||||
|
|
|
@ -38,6 +38,11 @@ executable(app_name,
|
||||||
'make_qt_animation.cpp',
|
'make_qt_animation.cpp',
|
||||||
'animated_pixmap.cpp',
|
'animated_pixmap.cpp',
|
||||||
include_directories: inc,
|
include_directories: inc,
|
||||||
dependencies: [qt5_dep, fslib_dep, memcard_dep],
|
dependencies: [
|
||||||
|
qt5_dep,
|
||||||
|
fslib_dep,
|
||||||
|
memcard_dep,
|
||||||
|
vectorwrapper_dep
|
||||||
|
],
|
||||||
install: true,
|
install: true,
|
||||||
)
|
)
|
||||||
|
|
45
src/qt/vec.hpp
Normal file
45
src/qt/vec.hpp
Normal 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
|
|
@ -16,18 +16,36 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "block_grid.hpp"
|
#include "block_grid.hpp"
|
||||||
|
#include "vec.hpp"
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QPoint>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace duck::widget {
|
namespace duck::widget {
|
||||||
namespace {
|
namespace {
|
||||||
const constexpr int g_icon_spacing = 3;
|
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
|
} //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),
|
QWidget(parent),
|
||||||
m_anim_timer(new QTimer(this)),
|
m_anim_timer(new QTimer(this)),
|
||||||
|
m_icon_size(-1, -1),
|
||||||
|
m_rows(rows),
|
||||||
m_columns(columns)
|
m_columns(columns)
|
||||||
{
|
{
|
||||||
fps = std::max(fps, 1.0f);
|
fps = std::max(fps, 1.0f);
|
||||||
|
@ -43,9 +61,9 @@ QSize BlockGrid::minimumSizeHint() const {
|
||||||
|
|
||||||
QSize BlockGrid::sizeHint() const {
|
QSize BlockGrid::sizeHint() const {
|
||||||
if (m_columns) {
|
if (m_columns) {
|
||||||
const auto w = icon_width() * m_columns + g_icon_spacing * (1 + m_columns);
|
const auto w = icon_size().width() * m_columns + g_icon_spacing * (1 + m_columns);
|
||||||
const unsigned int rows = size() / m_columns;
|
const unsigned int rows = (m_rows ? m_rows : size() / m_columns);
|
||||||
const auto h = icon_height() * rows + g_icon_spacing * (rows + 1);
|
const auto h = icon_size().height() * rows + g_icon_spacing * (rows + 1);
|
||||||
|
|
||||||
return {static_cast<int>(w), static_cast<int>(h)};
|
return {static_cast<int>(w), static_cast<int>(h)};
|
||||||
}
|
}
|
||||||
|
@ -54,12 +72,23 @@ QSize BlockGrid::sizeHint() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int BlockGrid::icon_width() const {
|
void BlockGrid::set_icon_size (const QSize& sz) {
|
||||||
return m_icons.empty() ? static_cast<unsigned int>(g_icon_spacing) : m_icons.front().size().width();
|
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 {
|
void BlockGrid::set_icon_size (int sz) {
|
||||||
return m_icons.empty() ? static_cast<unsigned int>(g_icon_spacing) : m_icons.front().size().height();
|
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) {
|
void BlockGrid::push_back (AnimatedPixmap&& anim) {
|
||||||
|
@ -70,6 +99,17 @@ std::size_t BlockGrid::size() const {
|
||||||
return m_icons.size();
|
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 {
|
unsigned int BlockGrid::columns() const {
|
||||||
if (m_columns) {
|
if (m_columns) {
|
||||||
return 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 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);
|
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) {
|
void BlockGrid::paintEvent (QPaintEvent* event) {
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
const int max_col = static_cast<int>(this->columns());
|
const int max_col = static_cast<int>(this->columns());
|
||||||
int x = 0;
|
|
||||||
int y = 0;
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for (auto& ico : m_icons) {
|
for (auto& ico : m_icons) {
|
||||||
x = g_icon_spacing + (count % max_col) * (g_icon_spacing + ico.size().width());
|
auto point = g_icon_spacing + scalar_to_point(count, max_col) * (g_icon_spacing + to_qtint2(ico.size()));
|
||||||
y = g_icon_spacing + (count / max_col) * (g_icon_spacing + ico.size().height());
|
|
||||||
if (ico.frame_count()) {
|
if (ico.frame_count()) {
|
||||||
painter.drawPixmap(x, y, ico.current_frame());
|
painter.drawPixmap(point.x(), point.y(), ico.current_frame());
|
||||||
}
|
}
|
||||||
|
|
||||||
++count;
|
++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() {
|
void BlockGrid::advance_frame() {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "../animated_pixmap.hpp"
|
#include "../animated_pixmap.hpp"
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QPixmap>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -28,14 +29,15 @@ namespace duck::widget {
|
||||||
class BlockGrid : public QWidget {
|
class BlockGrid : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
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;
|
~BlockGrid() noexcept;
|
||||||
|
|
||||||
QSize minimumSizeHint() const override;
|
QSize minimumSizeHint() const override;
|
||||||
QSize sizeHint() const override;
|
QSize sizeHint() const override;
|
||||||
|
|
||||||
unsigned int icon_width() const;
|
void set_icon_size (const QSize& sz);
|
||||||
unsigned int icon_height() const;
|
void set_icon_size (int sz);
|
||||||
|
QSize icon_size() const;
|
||||||
|
|
||||||
void push_back (AnimatedPixmap&& anim);
|
void push_back (AnimatedPixmap&& anim);
|
||||||
std::size_t size() const;
|
std::size_t size() const;
|
||||||
|
@ -47,10 +49,14 @@ private slots:
|
||||||
void advance_frame();
|
void advance_frame();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
unsigned int rows() const;
|
||||||
unsigned int columns() const;
|
unsigned int columns() const;
|
||||||
|
|
||||||
std::vector<AnimatedPixmap> m_icons;
|
std::vector<AnimatedPixmap> m_icons;
|
||||||
QTimer* m_anim_timer;
|
QTimer* m_anim_timer;
|
||||||
|
std::unique_ptr<QPixmap> m_empty_icon;
|
||||||
|
QSize m_icon_size;
|
||||||
|
unsigned int m_rows;
|
||||||
unsigned int m_columns;
|
unsigned int m_columns;
|
||||||
};
|
};
|
||||||
} //namespace duck::widget
|
} //namespace duck::widget
|
||||||
|
|
1
subprojects/vectorwrapper
Submodule
1
subprojects/vectorwrapper
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 0a90a289a2c354c88130dbf04a4c15c696e0a9de
|
Loading…
Add table
Reference in a new issue