ActWorld/MapPresent/MapPresent.cpp

177 lines
4.2 KiB
C++
Raw Blame History

#include "MapPresent.h"
#include "UnitDelegate.h"
#include <QVector2D>
#include <cmath>
#include <QVector3D>
#include <QPainter>
MapPresent::MapPresent(QWidget* parent /*= nullptr*/)
:QWidget(parent)
{
_center_index.row = 0;
_center_index.col = 0;
}
PresentIndex MapPresent::indexGet(const QPointF& pos) const
{
decltype(_visible_units) templist;
for (auto& unit : _visible_units) {
if (unit.outline.contains(pos)) {
templist << unit;
}
}
while (templist.size() > 1) {
auto opta = templist[0];
auto optb = templist[1];
auto dista = QVector3D(opta.outline.center()).distanceToPoint(QVector3D(pos));
auto distb = QVector3D(optb.outline.center()).distanceToPoint(QVector3D(pos));
if (dista < distb) {
templist.removeAt(1);
}
else {
templist.removeAt(0);
}
}
if (templist.size())
return templist[0].index;
return PresentIndex();
}
QRectF MapPresent::outlineGet(const PresentIndex& idx) const
{
auto widget_rect = this->rect();
auto widget_center = widget_rect.center();
const float ap_len = _primitive_region_square_len / 2;
auto a2_vec = ap_len * sqrt(3) / 2;
auto n_yinc = QVector3D(a2_vec, ap_len * 3 / 2, 0);
auto n_xinc = QVector3D(a2_vec, -ap_len * 3 / 2, 0);
auto xinc = idx.row - _center_index.row;
auto yinc = idx.col - _center_index.col;
auto target_center = QVector3D(widget_center) + n_yinc * yinc + n_xinc * xinc;
target_center -= QVector3D(ap_len, ap_len, 0);
return QRectF(target_center.toPointF(), QSizeF(ap_len * 2, ap_len * 2));
}
void MapPresent::paintEvent(QPaintEvent* ev)
{
QWidget::paintEvent(ev);
BasicUnitDelegate t;
QPainter p(this);
for (auto opt : _visible_units) {
p.save();
auto rect = opt.outline;
p.translate(rect.topLeft());
rect.moveTo(0, 0);
auto end_pts = t.endPointsGet(rect);
QPainterPath clicp_path;
clicp_path.moveTo(end_pts.first());
for (auto idx = 0; idx < end_pts.size(); ++idx) {
clicp_path.lineTo(end_pts[idx]);
}
p.setClipPath(clicp_path);
opt.outline = rect;
t.paint(&p, opt);
p.restore();
}
}
void MapPresent::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
visibleUnitsTidy();
}
PresentOption AssumeOpt(PresentIndex index, QRectF rf) {
PresentOption opt;
opt.index = index;
opt.outline = rf;
return opt;
}
void MapPresent::visibleUnitsTidy() {
_visible_units.clear();
QRectF curr_outline = this->rect();
_visible_units << AssumeOpt(_center_index, outlineGet(_center_index));
int visible_count = 1, deduce_x = 1;
while (visible_count) {
visible_count = 0;
auto siblings = siblingsGet(_center_index, deduce_x++);
for (auto unit : siblings) {
auto visible_rect = outlineGet(unit);
if (curr_outline.intersects(visible_rect)) {
_visible_units << AssumeOpt(unit, visible_rect);
visible_count++;
}
}
}
// TODO <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٲ<EFBFBD><D9B2><EFBFBD><EFBFBD><EFBFBD>֯<EFBFBD>
}
QList<PresentIndex> MapPresent::siblingsGet(const PresentIndex& center, uint16_t dist) const
{
QList<PresentIndex> e6_points;
e6_points << PresentIndex{ center.row, center.col - dist };
e6_points << PresentIndex{ center.row + dist, center.col };
e6_points << PresentIndex{ center.row + dist, center.col + dist };
e6_points << PresentIndex{ center.row, center.col + dist };
e6_points << PresentIndex{ center.row - dist, center.col };
e6_points << PresentIndex{ center.row - dist, center.col - dist };
e6_points << PresentIndex{ center.row, center.col - dist };
QList<PresentIndex> values;
for (auto idx = 0; idx < 6; ++idx) {
auto ap = e6_points[idx];
auto bp = e6_points[idx + 1];
values << itemFills(ap, bp);
}
return values;
}
QList<PresentIndex> MapPresent::itemFills(const PresentIndex& a, const PresentIndex& b) const
{
QList<PresentIndex> items;
auto sign_row = (a.row == b.row) ? 0 : ((b.row - a.row) / std::abs(a.row - b.row));
auto sign_col = (a.col == b.col) ? 0 : ((b.col - a.col) / std::abs(a.col - b.col));
auto temp_pt = a;
while (temp_pt != b) {
items << temp_pt;
temp_pt += PresentIndex{ sign_row, sign_col };
}
return items;
}
PresentIndex& PresentIndex::operator+=(const PresentIndex& other)
{
row += other.row;
col += other.col;
return *this;
}
bool PresentIndex::operator!=(const PresentIndex& other) const
{
return row != other.row || col != other.col;
}
bool PresentIndex::isValid() const
{
return row != INT_MAX && col != INT_MAX;
}