添加鼠标指向基元索引检测

This commit is contained in:
codeboss 2025-10-11 23:03:22 +08:00
parent 901b660a64
commit 7edb3aba43
6 changed files with 131 additions and 78 deletions

View File

@ -1,20 +1,45 @@
#include "MapPresent.h" #include "MapPresent.h"
#include "UnitDelegate.h"
#include <QVector2D>
#include <cmath>
#include <QVector3D>
#include <QPainter>
MapPresent::MapPresent(QWidget* parent /*= nullptr*/) MapPresent::MapPresent(QWidget* parent /*= nullptr*/)
:QWidget(parent) :QWidget(parent)
{ {
_center_index.row = 0;
_center_index.col = 0;
} }
#include <QVector2D>
#include <cmath>
PresentIndex MapPresent::indexGet(const QPointF& pos) const 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(); return PresentIndex();
} }
#include <QVector3D>
QRectF MapPresent::outlineGet(const PresentIndex& idx) const QRectF MapPresent::outlineGet(const PresentIndex& idx) const
{ {
auto widget_rect = this->rect(); auto widget_rect = this->rect();
@ -33,7 +58,6 @@ QRectF MapPresent::outlineGet(const PresentIndex& idx) const
return QRectF(target_center.toPointF(), QSizeF(ap_len * 2, ap_len * 2)); return QRectF(target_center.toPointF(), QSizeF(ap_len * 2, ap_len * 2));
} }
#include <QPainter>
void MapPresent::paintEvent(QPaintEvent* ev) void MapPresent::paintEvent(QPaintEvent* ev)
{ {
QWidget::paintEvent(ev); QWidget::paintEvent(ev);
@ -43,7 +67,7 @@ void MapPresent::paintEvent(QPaintEvent* ev)
for (auto opt : _visible_units) { for (auto opt : _visible_units) {
p.save(); p.save();
auto rect = opt.selfOutline; auto rect = opt.outline;
p.translate(rect.topLeft()); p.translate(rect.topLeft());
rect.moveTo(0, 0); rect.moveTo(0, 0);
@ -55,7 +79,7 @@ void MapPresent::paintEvent(QPaintEvent* ev)
} }
p.setClipPath(clicp_path); p.setClipPath(clicp_path);
opt.selfOutline = rect; opt.outline = rect;
t.paint(&p, opt); t.paint(&p, opt);
p.restore(); p.restore();
@ -71,8 +95,8 @@ void MapPresent::resizeEvent(QResizeEvent* event)
PresentOption AssumeOpt(PresentIndex index, QRectF rf) { PresentOption AssumeOpt(PresentIndex index, QRectF rf) {
PresentOption opt; PresentOption opt;
opt.selfIndex = index; opt.index = index;
opt.selfOutline = rf; opt.outline = rf;
return opt; return opt;
} }
@ -146,53 +170,7 @@ bool PresentIndex::operator!=(const PresentIndex& other) const
return row != other.row || col != other.col; return row != other.row || col != other.col;
} }
int BasicUnitDelegate::unitType() const bool PresentIndex::isValid() const
{ {
return 0; return row != INT_MAX && col != INT_MAX;
}
void BasicUnitDelegate::paint(QPainter* p, const PresentOption& option)
{
auto rect = option.selfOutline;
auto center = rect.center();
auto alen = rect.width() / 2;
const float xspan = alen * sqrt(3) / 2;
QRadialGradient brush(center, alen);
p->fillRect(rect, brush);
QList<QPointF> points = endPointsGet(rect);
QVector<QLineF> lines;
for (auto idx = 0; idx < 6; ++idx) {
lines << QLineF(points[idx], points[idx + 1]);
}
p->drawLines(lines);
auto ft = p->font();
ft.setPixelSize(alen * 0.3);
p->setFont(ft);
p->setPen(Qt::white);
auto text_rect = QRectF(center.x() - xspan, center.y() - alen / 2, xspan * 2, alen);
auto text_str = QString("(%1,%2)").arg(option.selfIndex.row).arg(option.selfIndex.col);
p->drawText(text_rect, Qt::AlignCenter, text_str);
}
QList<QPointF> BasicUnitDelegate::endPointsGet(const QRectF& rect)
{
auto center = rect.center();
auto alen = rect.width() / 2;
const float xspan = alen * sqrt(3) / 2;
QList<QPointF> points;
points << QPointF(center.x() - xspan, center.y() - alen / 2);
points << QPointF(center.x(), 0);
points << QPointF(center.x() + xspan, center.y() - alen / 2);
points << QPointF(center.x() + xspan, center.y() + alen / 2);
points << QPointF(center.x(), rect.height());
points << QPointF(center.x() - xspan, center.y() + alen / 2);
points << QPointF(center.x() - xspan, center.y() - alen / 2);
return points;
} }

View File

@ -6,15 +6,17 @@
/// <summary> /// <summary>
/// 绘制索引 /// 绘制索引
/// </summary> /// </summary>
struct PresentIndex { struct MAPPRESENT_EXPORT PresentIndex {
/// <summary> /// <summary>
/// 行号 /// 行号
/// </summary> /// </summary>
int row = 0; int row = INT_MAX;
/// <summary> /// <summary>
/// 列号 /// 列号
/// </summary> /// </summary>
int col = 0; int col = INT_MAX;
bool isValid() const;
PresentIndex& operator+=(const PresentIndex& other); PresentIndex& operator+=(const PresentIndex& other);
bool operator!=(const PresentIndex& other) const; bool operator!=(const PresentIndex& other) const;
@ -27,11 +29,11 @@ struct PresentOption {
/// <summary> /// <summary>
/// 当前所绘制索引 /// 当前所绘制索引
/// </summary> /// </summary>
PresentIndex selfIndex; PresentIndex index;
/// <summary> /// <summary>
/// 当前绘制外缘 /// 当前绘制外缘
/// </summary> /// </summary>
QRectF selfOutline; QRectF outline;
bool isMouseOver = false; bool isMouseOver = false;
bool isSelected = false; bool isSelected = false;
@ -56,14 +58,6 @@ public:
virtual void paint(QPainter* p, const PresentOption& option) = 0; virtual void paint(QPainter* p, const PresentOption& option) = 0;
}; };
class BasicUnitDelegate : public UnitPresentDelegate {
public:
int unitType() const override;
void paint(QPainter* p, const PresentOption& option) override;
QList<QPointF> endPointsGet(const QRectF &rect);
};
/// <summary> /// <summary>
/// 基础地图绘制 /// 基础地图绘制
/// </summary> /// </summary>
@ -84,6 +78,15 @@ private:
/// </summary> /// </summary>
PresentIndex _center_index; PresentIndex _center_index;
// ===================================
QList<PresentOption> _visible_units;
void visibleUnitsTidy();
QList<PresentIndex> siblingsGet(const PresentIndex& center, uint16_t dist = 1) const;
QList<PresentIndex> itemFills(const PresentIndex& a, const PresentIndex& b) const;
public: public:
MapPresent(QWidget* parent = nullptr); MapPresent(QWidget* parent = nullptr);
@ -100,17 +103,13 @@ public:
/// <returns></returns> /// <returns></returns>
QRectF outlineGet(const PresentIndex& idx) const; QRectF outlineGet(const PresentIndex& idx) const;
signals:
void mouseEnter();
void mouseOut();
void mouseHover();
protected: protected:
void paintEvent(QPaintEvent* ev) override; void paintEvent(QPaintEvent* ev) override;
void resizeEvent(QResizeEvent* event) override; void resizeEvent(QResizeEvent* event) override;
private:
QList<PresentOption> _visible_units;
void visibleUnitsTidy();
QList<PresentIndex> siblingsGet(const PresentIndex &center, uint16_t dist=1) const;
QList<PresentIndex> itemFills(const PresentIndex &a, const PresentIndex &b) const;
}; };

View File

@ -94,7 +94,9 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="UnitDelegate.cpp" />
<ClInclude Include="mappresent_global.h" /> <ClInclude Include="mappresent_global.h" />
<ClInclude Include="UnitDelegate.h" />
<QtMoc Include="MapPresent.h" /> <QtMoc Include="MapPresent.h" />
<ClCompile Include="MapPresent.cpp" /> <ClCompile Include="MapPresent.cpp" />
</ItemGroup> </ItemGroup>

View File

@ -29,10 +29,18 @@
<ClCompile Include="MapPresent.cpp"> <ClCompile Include="MapPresent.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClInclude Include="UnitDelegate.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtMoc Include="MapPresent.h"> <QtMoc Include="MapPresent.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</QtMoc> </QtMoc>
</ItemGroup> </ItemGroup>
<ItemGroup>
<ClCompile Include="UnitDelegate.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,53 @@
#include "UnitDelegate.h"
#include <QPainter>
int BasicUnitDelegate::unitType() const
{
return 0;
}
void BasicUnitDelegate::paint(QPainter* p, const PresentOption& option)
{
auto rect = option.outline;
auto center = rect.center();
auto alen = rect.width() / 2;
const float xspan = alen * sqrt(3) / 2;
QRadialGradient brush(center, alen);
p->fillRect(rect, brush);
QList<QPointF> points = endPointsGet(rect);
QVector<QLineF> lines;
for (auto idx = 0; idx < 6; ++idx) {
lines << QLineF(points[idx], points[idx + 1]);
}
p->drawLines(lines);
auto ft = p->font();
ft.setPixelSize(alen * 0.3);
p->setFont(ft);
p->setPen(Qt::white);
auto text_rect = QRectF(center.x() - xspan, center.y() - alen / 2, xspan * 2, alen);
auto text_str = QString("(%1,%2)").arg(option.index.row).arg(option.index.col);
p->drawText(text_rect, Qt::AlignCenter, text_str);
}
QList<QPointF> BasicUnitDelegate::endPointsGet(const QRectF& rect)
{
auto center = rect.center();
auto alen = rect.width() / 2;
const float xspan = alen * sqrt(3) / 2;
QList<QPointF> points;
points << QPointF(center.x() - xspan, center.y() - alen / 2);
points << QPointF(center.x(), 0);
points << QPointF(center.x() + xspan, center.y() - alen / 2);
points << QPointF(center.x() + xspan, center.y() + alen / 2);
points << QPointF(center.x(), rect.height());
points << QPointF(center.x() - xspan, center.y() + alen / 2);
points << QPointF(center.x() - xspan, center.y() - alen / 2);
return points;
}

13
MapPresent/UnitDelegate.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include "MapPresent.h"
/// <summary>
/// 샘뇟왕겜데禱삥齡官辜
/// </summary>
class BasicUnitDelegate : public UnitPresentDelegate {
public:
int unitType() const override;
void paint(QPainter* p, const PresentOption& option) override;
QList<QPointF> endPointsGet(const QRectF& rect);
};