HAxis sos

This commit is contained in:
guus
2018-08-11 16:46:35 +02:00
commit 510654f8a1
480 changed files with 54126 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
#include "UnrealProject.h"
#include "MiniMap.h"
namespace MiniMap
{
void NodeBase::CircleOverlap(const FVector2D& position, float radius_sqr, TArray<MinimapHandle*>& out_objects)
{
if (objects.empty())
return;
for (auto iter = objects.begin(); iter != objects.end(); iter++)
{
MinimapHandle& obj = **iter;
if (FVector2D::DistSquared(obj.position, position) <= radius_sqr)
out_objects.Add(&obj);
}
}
}

View File

@@ -0,0 +1,325 @@
#pragma once
#include "UnrealProject.h"
#include <unordered_set>
using namespace std;
class ACharacterBase;
namespace MiniMap
{
struct Rect
{
Rect() = default;
Rect(float x, float y, float width, float height) : x(x), y(y), width(width), height(height) {}
Rect(const FVector2D& position, const FVector2D& size) : x(position.X), y(position.Y), width(size.X), height(size.Y) {}
float x;
float y;
float width;
float height;
inline FVector2D position() const
{
return FVector2D(x, y);
}
inline FVector2D size() const
{
return FVector2D(width, height);
}
inline bool contains(const FVector2D& pos) const
{
return pos.X >= x && pos.X <= (x + width) && pos.Y >= y && pos.Y <= (y + height);
}
};
inline Rect GetSubArea(const Rect& area, size_t idx)
{
const FVector2D half_size = area.size() / 2;
const FVector2D position = area.position();
switch (idx)
{
case 0: return Rect(position, half_size);
case 1: return Rect(position + FVector2D(half_size.X, 0), half_size);
case 2: return Rect(position + half_size, half_size);
case 3: return Rect(position + FVector2D(0, half_size.Y), half_size);
}
return area;
}
inline bool RectCircleOverlapSquared(const Rect& area, const FVector2D& position, float radius_sqr)
{
const FVector2D pos = area.position();
const float left = area.x;
const float bottom = area.y;
const float right = area.x + area.width;
const float top = area.y + area.height;
const float x = position.X > right ? right : position.X < left ? left : position.X;
const float y = position.Y > top ? top : position.Y < bottom ? bottom : position.Y;
return FVector2D::DistSquared(position, FVector2D(x, y)) <= radius_sqr;
}
class NonCopyable
{
public:
NonCopyable() = default;
NonCopyable(const NonCopyable& other) = delete;
NonCopyable& operator=(const NonCopyable& other) = delete;
};
class MinimapHandle;
class NodeBase : private NonCopyable
{
protected:
NodeBase(const Rect& area, NodeBase* parent) : area(area), parent(parent) {}
public:
virtual void AddObject(MinimapHandle& obj) = 0;
virtual void RemoveObject(MinimapHandle& obj) = 0;
virtual void ClearRecursive()
{
objects.clear();
}
virtual void ResizeRecursive(const Rect& area)
{
this->area = area;
}
virtual void CircleOverlap(const FVector2D& position, float radius_sqr, TArray<MinimapHandle*>& out_objects);
unordered_set<MinimapHandle*> objects;
Rect area;
NodeBase* parent;
};
class MinimapHandle : private NonCopyable
{
public:
MinimapHandle() : character(nullptr), node(nullptr), root(nullptr) {}
MinimapHandle(const FVector2D& position) : character(nullptr), position(position), node(nullptr), root(nullptr) {}
~MinimapHandle()
{
}
FVector2D position;
class ::ACharacterBase* character;
NodeBase* node;
NodeBase* root;
};
template<size_t level> class TreeNode : public NodeBase
{
public:
TreeNode(const Rect& area, NodeBase* parent) : NodeBase(area, parent), child0(GetSubArea(area, 0), this), child1(GetSubArea(area, 1), this), child2(GetSubArea(area, 2), this), child3(GetSubArea(area, 3), this) {}
typedef TreeNode<level - 1> child_type;
child_type child0;
child_type child1;
child_type child2;
child_type child3;
unordered_set<MinimapHandle*> child_objects;
virtual void AddObject(MinimapHandle& obj) override
{
child_type* children = &child0;
for (size_t i = 0; i < 4; i++)
{
if (children[i].area.contains(obj.position))
{
// Register to child
child_objects.emplace(&obj);
children[i].AddObject(obj);
return;
}
}
// Register to this node
objects.emplace(&obj);
obj.node = this;
}
virtual void RemoveObject(MinimapHandle& obj) override
{
// Check if present in children
auto find_child = child_objects.find(&obj);
if (find_child != child_objects.end())
{
child_type* children = &child0;
for (size_t i = 0; i < 4; i++)
children[i].RemoveObject(obj);
child_objects.erase(find_child);
}
else
{
// Remove from node
auto find = objects.find(&obj);
if (find != objects.end())
objects.erase(find);
}
}
virtual void ClearRecursive() override
{
child_type* children = &child0;
for (size_t i = 0; i < 4; i++)
children[i].ClearRecursive();
NodeBase::ClearRecursive();
child_objects.clear();
}
virtual void ResizeRecursive(const Rect& area) override
{
child_type* children = &child0;
for (size_t i = 0; i < 4; i++)
children[i].ResizeRecursive(GetSubArea(area, i));
NodeBase::ResizeRecursive(area);
}
virtual void CircleOverlap(const FVector2D& position, float radius_sqr, TArray<MinimapHandle*>& out_objects) override
{
if (!child_objects.empty())
{
child_type* children = &child0;
for (size_t i = 0; i < 4; i++)
{
child_type& child = children[i];
if (RectCircleOverlapSquared(child.area, position, radius_sqr))
child.CircleOverlap(position, radius_sqr, out_objects);
}
}
NodeBase::CircleOverlap(position, radius_sqr, out_objects);
}
};
template<size_t level> class RootNode : public TreeNode<level>
{
public:
RootNode(const Rect& area, NodeBase* parent) : TreeNode<level>(area, parent)
{
}
virtual void AddObject(MinimapHandle& obj) override
{
TreeNode<level>::AddObject(obj);
all_objects.emplace(&obj);
}
virtual void RemoveObject(MinimapHandle& obj) override
{
TreeNode<level>::RemoveObject(obj);
auto find = all_objects.find(&obj);
if (find != all_objects.end())
all_objects.erase(find);
}
virtual void ClearRecursive() override
{
for (auto iter = all_objects.begin(); iter != all_objects.end(); iter++)
{
(*iter)->node = nullptr;
(*iter)->root = nullptr;
}
all_objects.clear();
TreeNode<level>::ClearRecursive();
}
void Reparent(MinimapHandle& obj)
{
TreeNode<level>::RemoveObject(obj);
TreeNode<level>::AddObject(obj);
}
unordered_set<MinimapHandle*> all_objects;
};
template<> class TreeNode<0> : public NodeBase
{
public:
TreeNode(const Rect& area, NodeBase* parent) : NodeBase(area, parent)
{
}
void AddObject(MinimapHandle& obj) override
{
objects.emplace(&obj);
obj.node = this;
}
void RemoveObject(MinimapHandle& obj) override
{
auto find = objects.find(&obj);
if (find != objects.end())
objects.erase(find);
}
};
template<size_t depth> class QuadTree : private NonCopyable
{
public:
QuadTree() : m_root_node(Rect(0, 0, 1, 1), nullptr) {}
QuadTree(const Rect& area) : m_root_node(area, nullptr) {}
~QuadTree()
{
m_root_node.ClearRecursive();
}
void AddObject(MinimapHandle& obj)
{
if (obj.root == &m_root_node)
return;
if (obj.root != nullptr)
obj.root->RemoveObject(obj);
// Add object to root
m_root_node.AddObject(obj);
obj.root = &m_root_node;
}
void RemoveObject(MinimapHandle& obj)
{
if (obj.root == nullptr)
return;
if (obj.root != &m_root_node)
return;
// Remove from root
m_root_node.RemoveObject(obj);
obj.node = nullptr;
obj.root = nullptr;
}
void Update()
{
// Update positioning
for (auto iter = m_root_node.all_objects.begin(); iter != m_root_node.all_objects.end(); iter++)
{
MinimapHandle& obj = **iter;
if (!obj.node->area.contains(obj.position) && obj.node->parent)
m_root_node.Reparent(obj);
}
}
void Clear()
{
m_root_node->ClearRecursive();
}
void Resize(const Rect& area)
{
m_root_node.ResizeRecursive(area);
}
int32 Num() const
{
return int32(m_root_node.all_objects.size());
}
bool CircleOverlap(const FVector2D& position, float radius, TArray<MinimapHandle*>& out_objects)
{
out_objects.SetNum(0);
m_root_node.CircleOverlap(position, radius * radius, out_objects);
return out_objects.Num() > 0;
}
RootNode<depth> m_root_node;
};
}

View File

@@ -0,0 +1,10 @@
// Project Lab - NHTV Igad
#include "UnrealProject.h"
#include "MiniMapIconWidget.h"
void UMiniMapIconWidget::SetObjectIcon_Implementation(UTexture2D* texture)
{
// No implementation
}

View File

@@ -0,0 +1,22 @@
// Project Lab - NHTV Igad
#pragma once
#include "Blueprint/UserWidget.h"
#include "MiniMapIconWidget.generated.h"
/**
*
*/
UCLASS()
class UNREALPROJECT_API UMiniMapIconWidget : public UUserWidget
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, Category = "Image")
UImage* image;
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "MiniMap")
void SetObjectIcon(class UTexture2D* texture);
};

View File

@@ -0,0 +1,15 @@
// Project Lab - NHTV Igad
#include "UnrealProject.h"
#include "MiniMapVisionCircle.h"
UMiniMapVisionCircle::UMiniMapVisionCircle(const FObjectInitializer& init) : Super(init)
{
}
void UMiniMapVisionCircle::NativeConstruct()
{
Super::NativeConstruct();
}

View File

@@ -0,0 +1,26 @@
// Project Lab - NHTV Igad
#pragma once
#include "Blueprint/UserWidget.h"
#include "MiniMapVisionCircle.generated.h"
/**
*
*/
UCLASS()
class UNREALPROJECT_API UMiniMapVisionCircle : public UUserWidget
{
GENERATED_BODY()
public:
UMiniMapVisionCircle(const FObjectInitializer& init);
virtual void NativeConstruct() override;
UFUNCTION(BlueprintImplementableEvent, Category = "Vision")
void SetTexture(UTexture2D* texture);
UFUNCTION(BlueprintImplementableEvent, Category = "Vision")
void SetUV(const FVector2D& uv, const FVector2D& scale);
};

View File

@@ -0,0 +1,393 @@
// Project Lab - NHTV Igad
#include "UnrealProject.h"
#include "MiniMapVolume.h"
#include "MiniMapIconWidget.h"
#include "MiniMapVisionCircle.h"
#include "NetworkPlayer.h"
#include "BossBase.h"
#include "NPCBase.h"
#include "KOTHBossSpawner.h"
#include "KOTHMinionSpawner.h"
#include "NetworkCharacter.h"
#include "DefaultGameState.h"
#include "DefaultPlayerState.h"
#include "DefaultPlayerController.h"
#include "MiniMapWidget.h"
#include "WidgetLayoutLibrary.h"
#if PLATFORM_SPECIFIC_WIN == 0
#include "HeatMapMetrics.h"
#endif
float AngleTowards(const FVector2D& from, const FVector2D& to)
{
const float angle_rad = FMath::Atan2(from.X - to.X, to.Y - from.Y) + PI;
return FMath::RadiansToDegrees(angle_rad);
}
UMiniMapWidget::UMiniMapWidget(const FObjectInitializer& init) : Super(init)
{
viewRadius = 2000;
}
void UMiniMapWidget::NativeConstruct()
{
Super::NativeConstruct();
// Find the minimap volume
ADefaultGameState* const gameState = Cast<ADefaultGameState>(GetWorld()->GetGameState());
if(IsValid(gameState))
{
for (TActorIterator<AMiniMapVolume> iter(GetWorld()); iter; ++iter)
{
AMiniMapVolume* const volume = *iter;
volume->SetActorRotation(FRotator(0, 0, 0));
const FVector pos = volume->GetActorLocation();
const FVector area = volume->area->GetScaledBoxExtent();
m_size = FMath::Max(area.X, area.Y);
m_min.X = -m_size + pos.X;
m_min.Y = -m_size + pos.Y;
m_max.X = m_size + pos.X;
m_max.Y = m_size + pos.Y;
m_size *= 2;
m_viewRadius = (viewRadius / (area.X * 2));
gameState->minimapQuadtree.Resize(MiniMap::Rect(FVector2D(m_min), FVector2D(m_size, m_size)));
return;
}
}
JERROR("Failed to locate Mini Map volume");
}
void UMiniMapWidget::NativeTick(const FGeometry& geometry, float deltaTime)
{
Super::NativeTick(geometry, deltaTime);
m_arrowAnim = FMath::Fmod(m_arrowAnim + deltaTime, 1.0f);
// Reset the state of all current widgets
{
// Set widgets hidden
for (int32 i = 0; i < m_miniMapIconWidgetPool.Num(); i++)
{
m_miniMapIconWidgetPool[i]->SetVisibility(ESlateVisibility::Hidden);
// Reset rotations
FWidgetTransform trans = m_miniMapIconWidgetPool[i]->image->RenderTransform;
trans.Angle = 0;
m_miniMapIconWidgetPool[i]->image->SetRenderTransform(trans);
}
// Set existing arrows hidden
for (int32 i = 0; i < m_arrowMapIconWidgetPool.Num(); i++)
m_arrowMapIconWidgetPool[i]->SetVisibility(ESlateVisibility::Hidden);
// Allocate the neccesairy vision circles
for (int32 i = 0; i < m_viewCircleWidgetPool.Num(); i++)
m_viewCircleWidgetPool[i]->SetVisibility(ESlateVisibility::Hidden);
}
// Begin the rendering
UWorld* const world = GetWorld();
if (!IsValid(world)) return;
ADefaultGameState* const gameState = Cast<ADefaultGameState>(world->GetGameState());
if (!IsValid(gameState))
return;
// Get the local team
m_localTeam = -1;
AController* controller = world->GetGameInstance()->GetFirstLocalPlayerController();
ACharacterBase* localPlayer = nullptr;
if (IsValid(controller))
{
ADefaultPlayerController* const playerController = Cast<ADefaultPlayerController>(controller);
localPlayer = Cast<ACharacterBase>(playerController->GetPawn());
if (playerController->PlayerState)
m_localTeam = Cast<ADefaultPlayerState>(playerController->PlayerState)->GetTeam();
}
// Failed to fetch local team
if (m_localTeam == -1)
return;
gameState->minimapQuadtree.Update();
map<int32, unordered_set<ACharacterBase*>> drawActors;
unordered_set<ACharacterBase*>& friendlyPlayerSet = drawActors.emplace(m_localTeam, unordered_set<ACharacterBase*>()).first->second;
// Fetch the friendly viewpoints
for (TActorIterator<ACharacterBase> iter(world); iter; ++iter)
{
ACharacterBase* const character = *iter;
if (IsValid(character))
{
if (character->GetTeam() == m_localTeam)
friendlyPlayerSet.emplace(character);
}
}
// Fetch all the visible units around the friendly viewpoints
for (auto iter = friendlyPlayerSet.begin(); iter != friendlyPlayerSet.end(); iter++)
{
ACharacterBase* const character = (*iter);
FVector2D position = FVector2D(character->GetActorLocation().X, character->GetActorLocation().Y);
if (gameState->minimapQuadtree.CircleOverlap(position, character->visionRadius, m_handleBuffer))
{
for (int32 i = 0; i < m_handleBuffer.Num(); i++)
{
ACharacterBase* const visibleCharacter = m_handleBuffer[i]->character;
if(IsValid(visibleCharacter))
drawActors[visibleCharacter->GetTeam()].emplace(visibleCharacter);
}
}
}
// Fetch the minion camps
TArray<AKOTHSpawnerBase*> minionCamps;
AKOTHBossSpawner* bossCamp = nullptr;
FVector2D bossCampPos;
for (TActorIterator<AKOTHSpawnerBase> iter(world); iter; ++iter)
{
AKOTHSpawnerBase* camp = *iter;
if (camp->IsA<AKOTHBossSpawner>())
{
bossCamp = Cast<AKOTHBossSpawner>(camp);
const FVector2D charPos = FVector2D(camp->GetActorLocation().X, camp->GetActorLocation().Y);
bossCampPos = ConvertWorldToMinimap(charPos);
}
minionCamps.Add(camp);
}
// Draw the minion camps
m_widgetIndex = 0;
m_arrowIndex = 0;
m_circleIndex = 0;
for (int32 i = 0; i < minionCamps.Num(); i++)
{
UMiniMapIconWidget* const widget = m_AllocateWidget();
UCanvasPanelSlot* const slot = Cast<UCanvasPanelSlot>(widget->Slot);
widget->SetVisibility(ESlateVisibility::Visible);
AKOTHSpawnerBase* const camp = minionCamps[i];
const FVector2D charPos = FVector2D(camp->GetActorLocation().X, camp->GetActorLocation().Y);
FVector2D relativePos = ConvertWorldToMinimap(charPos);
// Set sprite position
FVector2D spriteSize = geometry.GetLocalSize() * 0.07f;
slot->SetPosition(geometry.GetLocalSize() * relativePos - spriteSize * 0.5f);
slot->SetSize(spriteSize);
SetObjectIcon(campIcon, widget);
FLinearColor color = enemyColor;
if (camp->team >= NPCTeam::Team1) // NPC Controlled
color = playerColor;
else if (int32(camp->team) == int32(m_localTeam)) // Friendly
color = allyColor;
else if (int32(camp->team) == 0) // Contested
color = neutralColor;
widget->image->Brush.TintColor = color;
// Draw arrows
if (bossCamp && int32(camp->team) > 0 && camp->team < NPCTeam::Team1 && camp != bossCamp)
{
const int32 arrowCount = int32(FVector2D::Distance(relativePos, bossCampPos) * 25);
if (arrowCount > 0)
{
const float step = 1.0f / float(arrowCount);
for (int32 i = 0; i < arrowCount; i++)
{
UMiniMapIconWidget* arrow = m_AllocateArrow();
arrow->SetVisibility(ESlateVisibility::Visible);
UCanvasPanelSlot* const slot = Cast<UCanvasPanelSlot>(arrow->Slot);
// Lerp towards the target
color.A = arrowCount > 1 ? (i == 0 ? m_arrowAnim : i == arrowCount - 1 ? (1.f - m_arrowAnim) : 1) : 1;
const FVector2D setPos = FMath::Lerp(relativePos, bossCampPos, step * float(i) + step * m_arrowAnim);
FWidgetTransform trans = arrow->image->RenderTransform;
trans.Angle = AngleTowards(setPos, bossCampPos);
arrow->image->SetRenderTransform(trans);
arrow->image->Brush.TintColor = color;
const FVector2D spriteSize = geometry.GetLocalSize() * 0.04f;
slot->SetSize(spriteSize);
slot->SetPosition(geometry.GetLocalSize() * setPos - spriteSize * 0.5f);
}
}
}
}
// Generate draw order (Draw local team last)
TArray<int32> teamDrawOrder;
for (auto iter = drawActors.rbegin(); iter != drawActors.rend(); iter++)
{
if (iter->first == m_localTeam)
continue;
teamDrawOrder.Add(iter->first);
}
teamDrawOrder.Add(m_localTeam);
// Draw the actual characters to the minimap
int32 circleIndex = 0;
for (size_t i = 0; i < teamDrawOrder.Num(); i++)
{
const int32 team = teamDrawOrder[i];
auto& set = drawActors[team];
for (auto charIter = set.begin(); charIter != set.end(); charIter++)
{
ACharacterBase* const character = *charIter;
if (character == localPlayer)
continue;
UMiniMapIconWidget* const widget = m_AllocateWidget();
m_DrawCreature(geometry, widget, character);
}
}
// Draw the local player last
if (localPlayer)
m_DrawCreature(geometry, m_AllocateWidget(), localPlayer);
}
void UMiniMapWidget::m_DrawCreature(const FGeometry& geometry, UMiniMapIconWidget* widget, class ACharacterBase* character)
{
widget->SetVisibility(ESlateVisibility::Visible);
UCanvasPanelSlot* const slot = Cast<UCanvasPanelSlot>(widget->Slot);
const int32 actorTeam = character->GetTeam();
const FVector2D charPos = FVector2D(character->GetActorLocation().X, character->GetActorLocation().Y);
FVector2D relativePos = ConvertWorldToMinimap(charPos);
// Rotation
const float drawPlayerAngle = character->GetActorRotation().Yaw;
// Set sprite position
FVector2D spriteSize = geometry.GetLocalSize() * 0.07f;
slot->SetPosition(geometry.GetLocalSize() * relativePos - spriteSize * 0.5f);
slot->SetSize(spriteSize);
FWidgetTransform trans = widget->image->RenderTransform;
trans.Angle = 0;
// Set icon based on the object type
if (character->IsA<ABossBase>())
SetObjectIcon(bossIcon, widget);
else if (character->IsA<ANPCBase>())
SetObjectIcon(creatureIcon, widget);
else
{
trans.Angle = drawPlayerAngle;
SetObjectIcon(playerIcon, widget);
}
widget->image->SetRenderTransform(trans);
// Set the color
if (!(character->IsA<ANetworkPlayer>() && character->IsLocallyControlled()))
{
if (actorTeam != m_localTeam)
{
// Neutral or enemy?
if (actorTeam == 0)
widget->image->Brush.TintColor = neutralColor;
else
widget->image->Brush.TintColor = enemyColor;
}
else
widget->image->Brush.TintColor = allyColor;
}
else
widget->image->Brush.TintColor = playerColor;
// Update the view circle
if (actorTeam == m_localTeam)
{
UMiniMapVisionCircle* const circle = m_AllocateVisionCircle();
circle->SetVisibility(ESlateVisibility::Visible);
UCanvasPanelSlot* const circleSlot = Cast<UCanvasPanelSlot>(circle->Slot);
if (IsValid(circleSlot))
{
const float diameter = (character->visionRadius * 2) / m_size;
FVector2D size = geometry.GetLocalSize() * diameter;
size = FVector2D(FMath::RoundToFloat(size.X), FMath::RoundToFloat(size.Y));
FVector2D pos = geometry.GetLocalSize() * relativePos - size * 0.5f;
pos = FVector2D(FMath::RoundToFloat(pos.X), FMath::RoundToFloat(pos.Y));
circleSlot->SetPosition(pos);
circleSlot->SetSize(size);
circle->SetUV(pos / geometry.GetLocalSize(), size / geometry.GetLocalSize());
}
}
}
UMiniMapIconWidget* UMiniMapWidget::m_AllocateWidget()
{
UMiniMapIconWidget* widget = nullptr;
if (m_widgetIndex >= m_miniMapIconWidgetPool.Num())
{
widget = CreateWidget<UMiniMapIconWidget>(GetWorld(), iconWidget);
iconLayer->AddChild(widget);
m_miniMapIconWidgetPool.Add(widget);
}
else
widget = m_miniMapIconWidgetPool[m_widgetIndex];
m_widgetIndex++;
return widget;
}
UMiniMapIconWidget* UMiniMapWidget::m_AllocateArrow()
{
UMiniMapIconWidget* arrow = nullptr;
if (m_arrowIndex >= m_arrowMapIconWidgetPool.Num())
{
arrow = CreateWidget<UMiniMapIconWidget>(GetWorld(), iconWidget);
arrowLayer->AddChild(arrow);
m_arrowMapIconWidgetPool.Add(arrow);
SetObjectIcon(arrowIcon, arrow);
}
else
arrow = m_arrowMapIconWidgetPool[m_arrowIndex];
m_arrowIndex++;
return arrow;
}
UMiniMapVisionCircle* UMiniMapWidget::m_AllocateVisionCircle()
{
UMiniMapVisionCircle* circle = nullptr;
if (m_circleIndex >= m_viewCircleWidgetPool.Num())
{
circle = CreateWidget<UMiniMapVisionCircle>(GetWorld(), visionCircleWidget);
visionLayer->AddChild(circle);
m_viewCircleWidgetPool.Add(circle);
circle->SetTexture(backgroundTexture);
}
else
circle = m_viewCircleWidgetPool[m_circleIndex];
m_circleIndex++;
return circle;
}
FVector2D UMiniMapWidget::ConvertWorldToMinimap(const FVector2D& pos)
{
const FVector2D scale = FVector2D(m_max.X - m_min.X, m_max.Y - m_min.Y);
FVector2D relativePos = (pos - m_min) / scale;
FVector2D returnPos = FVector2D(relativePos.Y, relativePos.X);
returnPos.Y = 1.0f - returnPos.Y;
return returnPos;
}
void UMiniMapWidget::SetObjectIcon_Implementation(UTexture2D* texture, UMiniMapIconWidget* widget)
{
// No implementation
}
void UMiniMapWidget::SetMinimapInfo_Implementation(FVector2D player0, FVector2D player1, float radius)
{
// No implementation
}

View File

@@ -0,0 +1,89 @@
// Project Lab - NHTV Igad
#pragma once
#include "Blueprint/UserWidget.h"
#include <map>
#include "Minimap.h"
#include "MiniMapWidget.generated.h"
/**
*
*/
UCLASS()
class UNREALPROJECT_API UMiniMapWidget : public UUserWidget
{
GENERATED_BODY()
public:
UMiniMapWidget(const FObjectInitializer& init);
UFUNCTION(BlueprintNativeEvent, Category = "MiniMap")
void SetObjectIcon(class UTexture2D* texture, class UMiniMapIconWidget* widget);
virtual void NativeConstruct() override;
virtual void NativeTick(const FGeometry& geometry, float deltaTime) override;
UPROPERTY(EditAnywhere, Category = "MiniMap")
float viewRadius;
UPROPERTY(EditAnywhere, Category = "Minimap")
FLinearColor playerColor;
UPROPERTY(EditAnywhere, Category = "Minimap")
FLinearColor allyColor;
UPROPERTY(EditAnywhere, Category = "Minimap")
FLinearColor enemyColor;
UPROPERTY(EditAnywhere, Category = "Minimap")
FLinearColor neutralColor;
UPROPERTY(EditAnywhere, Category = "MiniMap")
UTexture2D* playerIcon;
UPROPERTY(EditAnywhere, Category = "MiniMap")
UTexture2D* creatureIcon;
UPROPERTY(EditAnywhere, Category = "MiniMap")
UTexture2D* bossIcon;
UPROPERTY(EditAnywhere, Category = "MiniMap")
UTexture2D* campIcon;
UPROPERTY(EditAnywhere, Category = "MiniMap")
UTexture2D* arrowIcon;
UFUNCTION(BlueprintNativeEvent, Category = "MiniMap")
void SetMinimapInfo(FVector2D player0, FVector2D player1, float radius);
FVector2D ConvertWorldToMinimap(const FVector2D& pos);
UPROPERTY(EditAnywhere, Category = "MiniMap")
TSubclassOf<class UMiniMapIconWidget> iconWidget;
UPROPERTY(EditAnywhere, Category = "MiniMap")
TSubclassOf<class UMiniMapVisionCircle> visionCircleWidget;
UPROPERTY(BlueprintReadWrite, Category = "MiniMap")
UCanvasPanel* iconLayer;
UPROPERTY(BlueprintReadWrite, Category = "MiniMap")
UCanvasPanel* arrowLayer;
UPROPERTY(BlueprintReadWrite, Category = "MiniMap")
UTexture2D* backgroundTexture;
UPROPERTY(BlueprintReadWrite, Category = "MiniMap")
UCanvasPanel* visionLayer;
private:
void m_DrawCreature(const FGeometry& geometry, UMiniMapIconWidget* widget, class ACharacterBase* character);
UMiniMapIconWidget* m_AllocateWidget();
UMiniMapIconWidget* m_AllocateArrow();
UMiniMapVisionCircle* m_AllocateVisionCircle();
TArray<class UMiniMapIconWidget*> m_miniMapIconWidgetPool;
TArray<class UMiniMapIconWidget*> m_arrowMapIconWidgetPool;
TArray<class UMiniMapVisionCircle*> m_viewCircleWidgetPool;
TArray<MiniMap::MinimapHandle*> m_handleBuffer;
FVector2D m_min;
FVector2D m_max;
float m_size;
float m_viewRadius;
float m_arrowAnim;
int32 m_localTeam;
int32 m_widgetIndex;
int32 m_arrowIndex;
int32 m_circleIndex;
};