From e5846ed637cd29dabce2de2d350b39349fdf28ea Mon Sep 17 00:00:00 2001 From: codeboss <2422523675@qq.com> Date: Sun, 12 Oct 2025 23:04:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=BC=93=E5=AD=98=E6=9C=BA?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ActWorld/main.cpp | 1 + MapPresent/MapPresent.cpp | 89 +++++++++++++++++++++++++++++-------- MapPresent/MapPresent.h | 21 +++++++-- MapPresent/UnitDelegate.cpp | 9 +++- 4 files changed, 97 insertions(+), 23 deletions(-) diff --git a/ActWorld/main.cpp b/ActWorld/main.cpp index 011ba73..147e790 100644 --- a/ActWorld/main.cpp +++ b/ActWorld/main.cpp @@ -12,6 +12,7 @@ int main(int argc, char* argv[]) MapPresent p; p.show(); + p.zoomTo(1); //QObject::connect(&p, &MapPresent::mouseIn, [=]() { // qDebug() << "Mouse Enter"; diff --git a/MapPresent/MapPresent.cpp b/MapPresent/MapPresent.cpp index f51239d..ed88b6b 100644 --- a/MapPresent/MapPresent.cpp +++ b/MapPresent/MapPresent.cpp @@ -20,15 +20,34 @@ MapPresent::MapPresent(QWidget* parent /*= nullptr*/) _type_present_delegate[delegate->unitType()] = delegate; connect(this, &MapPresent::mouseOut, delegate, &BasicUnitDelegate::hotClear); connect(this, &MapPresent::mouseHover, delegate, &BasicUnitDelegate::hotIndexSet); - connect(delegate, &BasicUnitDelegate::updateRequest, [=]() { this->update(); }); + connect(delegate, &BasicUnitDelegate::updateRequest, [=](const PresentIndex& idx) { + if (idx.isValid() && !_updated_units.contains(idx)) { + _updated_units.append(idx); + } + + this->update(); + }); this->setMouseTracking(true); } +void MapPresent::zoomTo(double percent) +{ + this->_scale_times = std::max(1.0 / 2, percent); + this->visible_units_tidy(); + + this->update(); +} + +double MapPresent::zoomTimes() const +{ + return _scale_times; +} + PresentIndex MapPresent::indexGet(const QPointF& pos) const { QList templist; - for (auto unit : _visible_units) { + for (auto& unit : _visible_units) { if (unit.outline.contains(pos)) { templist << unit; @@ -59,7 +78,7 @@ QRectF MapPresent::outlineGet(const PresentIndex& idx) const auto widget_rect = this->rect(); auto widget_center = widget_rect.center(); - const float ap_len = _primitive_region_len / 2; + const float ap_len = _primitive_region_len * _scale_times / 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); @@ -75,24 +94,34 @@ QRectF MapPresent::outlineGet(const PresentIndex& idx) const void MapPresent::paintEvent(QPaintEvent* ev) { QWidget::paintEvent(ev); - UnitPresentDelegate& t = *_type_present_delegate[0]; - QPainter p(this); - for (auto opt : _visible_units) { - p.save(); + if (_updated_units.size()) { + QPainter pic_painter(&_paint_buffer); + + for (auto idx : _updated_units) { + pic_painter.save(); - auto rect = opt.outline; - p.translate(rect.topLeft()); - rect.moveTo(0, 0); + auto opt = _visible_units[idx]; + auto rect = opt.outline; + pic_painter.translate(rect.topLeft()); + rect.moveTo(0, 0); - auto clip_path = BasicUnitDelegate::clipPathGet(rect); - p.setClipPath(clip_path); + auto clip_path = BasicUnitDelegate::clipPathGet(rect); + pic_painter.setClipPath(clip_path); - opt.outline = rect; - t.paint(&p, opt); + opt.outline = rect; + UnitPresentDelegate& t = *_type_present_delegate[0]; + t.paint(&pic_painter, opt); - p.restore(); + pic_painter.restore(); + } + + _updated_units.clear(); } + + QPainter widget_painter(this); + // 转发累积 + widget_painter.drawPixmap(rect(), _paint_buffer); } void MapPresent::resizeEvent(QResizeEvent* event) @@ -138,8 +167,9 @@ void MapPresent::visible_units_tidy() { _visible_units.clear(); QRectF curr_outline = this->rect(); - _visible_units << AssumeOpt(_center_index, outlineGet(_center_index)); + _paint_buffer = QPixmap(curr_outline.toRect().size()); + _visible_units[_center_index] = AssumeOpt(_center_index, outlineGet(_center_index)); int visible_count = 1, deduce_x = 1; while (visible_count) { visible_count = 0; @@ -148,13 +178,14 @@ void MapPresent::visible_units_tidy() { for (auto unit : siblings) { auto visible_rect = outlineGet(unit); if (curr_outline.intersects(visible_rect)) { - _visible_units << AssumeOpt(unit, visible_rect); + _visible_units[unit] = AssumeOpt(unit, visible_rect); visible_count++; } } } - // TODO 构建快速测试组织结构 + for (auto optx : _visible_units) + _updated_units.append(optx.index); } QList MapPresent::siblingsGet(const PresentIndex& center, uint16_t dist) const @@ -192,6 +223,21 @@ QList MapPresent::item_supply(const PresentIndex& a, const Present return items; } +void MapPresent::unit_option_paint(QPainter& widget_painter, const PresentOption& xopt) +{ + auto opt = xopt; + auto rect = opt.outline; + widget_painter.translate(rect.topLeft()); + rect.moveTo(0, 0); + + auto clip_path = BasicUnitDelegate::clipPathGet(rect); + widget_painter.setClipPath(clip_path); + + opt.outline = rect; + UnitPresentDelegate& t = *_type_present_delegate[0]; + t.paint(&widget_painter, opt); +} + PresentIndex& PresentIndex::operator+=(const PresentIndex& other) { row += other.row; @@ -209,6 +255,13 @@ bool PresentIndex::isValid() const return row != INT_MAX && col != INT_MAX; } +bool PresentIndex::operator<(const PresentIndex& other) const +{ + if (row == other.row) + return col < other.col; + return row < other.row; +} + bool PresentIndex::operator==(const PresentIndex& other) const { return row == other.row && col == other.col; diff --git a/MapPresent/MapPresent.h b/MapPresent/MapPresent.h index 67bbb95..c5bb5c5 100644 --- a/MapPresent/MapPresent.h +++ b/MapPresent/MapPresent.h @@ -3,6 +3,7 @@ #include "mappresent_global.h" #include #include +#include /// @@ -23,6 +24,7 @@ struct MAPPRESENT_EXPORT PresentIndex { PresentIndex& operator+=(const PresentIndex& other); bool operator!=(const PresentIndex& other) const; bool operator==(const PresentIndex& other) const; + bool operator<(const PresentIndex& other) const; }; /// @@ -79,11 +81,11 @@ private: /// /// 初级区域矩形变长 /// - const float _primitive_region_len = 100; + const float _primitive_region_len = 64; /// /// 缩放倍数 /// - short _scale_times = 1; + double _scale_times = 1; /// /// 当前瓦片地图中心索引 /// @@ -91,9 +93,18 @@ private: // =================================== /// + /// 绘制中转缓冲区 + /// + QPixmap _paint_buffer; + /// /// 试图核心索引 /// - QList _visible_units; + QMap _visible_units; + /// + /// 被更新的单元索引 + /// + QList _updated_units; + /// /// 可视化单元整理 /// @@ -111,11 +122,15 @@ private: /// 类型化绘制委托 /// QHash _type_present_delegate; + void unit_option_paint(QPainter& widget_painter, const PresentOption &opt); public: MapPresent(QWidget* parent = nullptr); + void zoomTo(double percent); + double zoomTimes() const; + /// /// 通过widget上定位获取绘制索引 /// diff --git a/MapPresent/UnitDelegate.cpp b/MapPresent/UnitDelegate.cpp index bd31676..e010bf2 100644 --- a/MapPresent/UnitDelegate.cpp +++ b/MapPresent/UnitDelegate.cpp @@ -38,7 +38,7 @@ void BasicUnitDelegate::paint(QPainter* p, const PresentOption& option) ft.setPixelSize(alen * 0.3); p->setFont(ft); - p->setPen(Qt::white); + p->setPen(Qt::black); 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); @@ -69,14 +69,19 @@ QPainterPath BasicUnitDelegate::clipPathGet(const QRectF& rect) void BasicUnitDelegate::hotClear() { + auto prev_idx = _hot_index; _hot_index = PresentIndex(); - emit this->updateRequest(_hot_index); + + emit this->updateRequest(prev_idx); } void BasicUnitDelegate::hotIndexSet(const PresentIndex& idx) { if (_hot_index != idx) { + auto prev_idx = _hot_index; _hot_index = idx; + + emit this->updateRequest(prev_idx); emit this->updateRequest(idx); } }