小圆点数量不会递增的方法

//懒汉式加载
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);

        if(isVisibleToUser){
            getLunBo();
//line是线性布局

 if(line!=null&&line.getChildCount()>0){
                line.removeAllViews();
                img.clear();
                point.clear();
            }
        }
    }
我们将在UE5编辑器插件中实现以下功能: 1. 在关卡工具栏添加按钮 2. 点击按钮弹出Slate窗口 3. 窗口内嵌小地图,支持放大/缩小/移动 4. 小地图用圆点标注指定物品位置 5. 支持鼠标框选圆点并统计数量 6. 点击圆点可查看物品信息 实现方案如下: mermaid graph TDA[插件模块] --> B[工具栏按钮]A --> C[Slate窗口] C --> D[小地图控件] D --> E[地图导航 缩放/平移] D --> F[物品位置映射] D --> G[圆点绘制] D --> H[框选交互] D --> I[点击交互] C --> J[信息面板] 步骤1:创建插件基础 1. 创建"EditorMapViewer"插件(选择编辑器工具栏按钮模板) 2. 目录结构: 3. EditorMapViewer/ ├── Resources/ ├── Source/ │ ├── EditorMapViewer/ │ │ ├── Private/ │ │ │ ├── EditorMapViewerCommands.cpp │ │ │ ├── EditorMapViewerModule.cpp │ │ │ ├── SMapViewerWindow.cpp │ │ │ ├── SMapViewport.cpp │ │ ├── Public/ │ │ │ ├── EditorMapViewerCommands.h │ │ │ ├── EditorMapViewerModule.h │ │ │ ├── SMapViewerWindow.h │ │ │ ├── SMapViewport.h │ ├── EditorMapViewer.Build.cs 步骤2:实现小地图视口控件(核心) SMapViewport.h: C++ #pragma once#include "CoreMinimal.h"#include "Widgets/SCompoundWidget.h"#include "Engine/World.h"class SMapViewport : public SCompoundWidget { public:SLATE_BEGIN_ARGS(SMapViewport) {}SLATE_ARGUMENT(TWeakObjectPtr<UWorld>, World)SLATE_END_ARGS() void Construct(const FArguments& InArgs); // 鼠标交互处理virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;virtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;virtual FReply OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; private:// 绘制函数virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override; // 坐标转换:世界坐标 -> 小地图坐标FVector2D WorldToMap(const FVector& WorldPos) const; // 获取当前关卡中所有指定物品void RefreshItemData(); // 地图导航void PanMap(const FVector2D& PanAmount);void ZoomMap(float ZoomDelta, const FVector2D& MousePosition); TWeakObjectPtr<UWorld> World; TArray<TPair<FVector, FString>> Items; // 物品位置和信息 FVector2D MapPanOffset = FVector2D::ZeroVector;float MapScale = 1.0f; FVector2D SelectionStart; FVector2D SelectionEnd;bool bIsPanning = false;bool bIsSelecting = false; }; SMapViewport.cpp: C++ #include "SMapViewport.h"#include "Editor.h"#include "EngineUtils.h"#include "SlateOptMacros.h"#include "Widgets/Layout/SScrollBox.h" BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void SMapViewport::Construct(const FArguments& InArgs) { World = InArgs._World;RefreshItemData(); } END_SLATE_FUNCTION_BUILD_OPTIMIZATION FVector2D SMapViewport::WorldToMap(const FVector& WorldPos) const {// 简单投影:忽略Y轴(根据需求调整)return FVector2D(WorldPos.X, WorldPos.Z) * MapScale + MapPanOffset; } void SMapViewport::RefreshItemData() { Items.Empty();if (!World.IsValid()) return; // 示例:获取所有PointLight(替换为你的物品类)for (TActorIterator<APointLight> It(World.Get()); It; ++It) {if (*It) { Items.Add(TPair<FVector, FString>(It->GetActorLocation(), It->GetActorLabel())); } } } FReply SMapViewport::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) {if (MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton) {// 检查是否点击到物品const FVector2D LocalPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());for (const auto& Item : Items) {const FVector2D ItemPos = WorldToMap(Item.Key);if (FVector2D::Distance(ItemPos, LocalPos) < 10.0f) {// 点击物品事件(可扩展为显示信息)FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(Item.Value));return FReply::Handled(); } } // 开始框选 SelectionStart = LocalPos; SelectionEnd = LocalPos; bIsSelecting = true;return FReply::Handled().CaptureMouse(AsShared()); }else if (MouseEvent.GetEffectingButton() == EKeys::RightMouseButton) {// 开始平移 bIsPanning = true;return FReply::Handled().CaptureMouse(AsShared()); }return FReply::Unhandled(); } FReply SMapViewport::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) {if (bIsPanning) {PanMap(MouseEvent.GetCursorDelta());return FReply::Handled(); }else if (bIsSelecting) { SelectionEnd = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());return FReply::Handled(); }return FReply::Unhandled(); } FReply SMapViewport::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) {if ((MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton && bIsSelecting) || (MouseEvent.GetEffectingButton() == EKeys::RightMouseButton && bIsPanning)) { bIsPanning = false; bIsSelecting = false; // 框选统计if (MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton) { FBox2D SelectionBox(SelectionStart, SelectionEnd); int32 SelectedCount = 0; for (const auto& Item : Items) {if (SelectionBox.IsInside(WorldToMap(Item.Key))) { SelectedCount++; } } // 显示统计结果 FNotificationInfo Info(FText::FromString(FString::Printf(TEXT("选中物品数量: %d"), SelectedCount)));FSlateNotificationManager::Get().AddNotification(Info); } return FReply::Handled().ReleaseMouseCapture(); }return FReply::Unhandled(); } FReply SMapViewport::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) {ZoomMap(MouseEvent.GetWheelDelta(), MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()));return FReply::Handled(); } void SMapViewport::PanMap(const FVector2D& PanAmount) { MapPanOffset += PanAmount; } void SMapViewport::ZoomMap(float ZoomDelta, const FVector2D& MousePosition) {const float OldScale = MapScale; MapScale = FMath::Clamp(MapScale + ZoomDelta * 0.1f, 0.1f, 5.0f); // 以鼠标为中心缩放 MapPanOffset = MousePosition - (MousePosition - MapPanOffset) * (MapScale / OldScale); } int32 SMapViewport::OnPaint(...) const {// 1. 绘制背景FSlateDrawElement::MakeBox(...); // 2. 绘制物品圆点for (const auto& Item : Items) {const FVector2D Pos = WorldToMap(Item.Key);FSlateDrawElement::MakeCircle( OutDrawElements, LayerId++, AllottedGeometry.ToPaintGeometry(Pos - FVector2D(5,5), FVector2D(10,10)),FLinearColor::Red ); } // 3. 绘制框选矩形if (bIsSelecting) {FSlateDrawElement::MakeBox( OutDrawElements, LayerId++, AllottedGeometry.ToPaintGeometry( SelectionStart, SelectionEnd - SelectionStart ),FLinearColor::Green ); } return LayerId; } 步骤3:实现主窗口 SMapViewerWindow.h: C++ #pragma once#include "CoreMinimal.h"#include "Widgets/SCompoundWidget.h"class SMapViewport; class SMapViewerWindow : public SCompoundWidget { public:SLATE_BEGIN_ARGS(SMapViewerWindow) {}SLATE_END_ARGS() void Construct(const FArguments& InArgs); private: TSharedPtr<SMapViewport> MapViewport; TSharedPtr<STextBlock> InfoText; }; SMapViewerWindow.cpp: C++ #include "SMapViewerWindow.h"#include "SMapViewport.h"#include "Editor.h"BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void SMapViewerWindow::Construct(const FArguments& InArgs){ ChildSlot [SNew(SVerticalBox) +SVerticalBox::Slot().FillHeight(1.0f) [SAssignNew(MapViewport, SMapViewport) .World(GEditor->GetEditorWorldContext().World()) ] +SVerticalBox::Slot().AutoHeight().Padding(5) [SAssignNew(InfoText, STextBlock) .Text(LOCTEXT("DefaultHint", "左键框选物品 | 右键拖动 | 滚轮缩放")) ] ]; } END_SLATE_FUNCTION_BUILD_OPTIMIZATION 步骤4:集成到插件模块 EditorMapViewerModule.cpp: C++ void FEditorMapViewerModule::OnOpenMapViewer(){ TSharedRef<SWindow> Window = SNew(SWindow) .Title(LOCTEXT("WindowTitle", "关卡物品地图查看器")) .ClientSize(FVector2D(800, 600)); Window->SetContent(SNew(SMapViewerWindow)); // 添加到编辑器窗口 FSlateApplication::Get().AddWindow(Window); } 步骤5:配置构建文件 EditorMapViewer.Build.cs: C# PrivateDependencyModuleNames.AddRange(new string[] {"CoreUObject","Engine","Slate","SlateCore","EditorStyle","UnrealEd","LevelEditor","InputCore","RenderCore", // 新增"RHI", // 新增"ApplicationCore" // 新增 }); 要求完善OnPaint函数,不能简写,所有函数参数都要写出来,小圆点的功能也要写完整,点击更行按钮后要更行绘制小圆点
11-20
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值