678 lines
19 KiB
C++
678 lines
19 KiB
C++
// Project Lab - NHTV Igad
|
|
|
|
#include "UnrealProject.h"
|
|
#include "SkillTreeWidget.h"
|
|
#include "SkillTreeObject.h"
|
|
#include "BaseSkillObject.h"
|
|
#include "HexagonTile.h"
|
|
#include "ScrollBox.h"
|
|
#include "SkillWidget.h"
|
|
#include "CanvasPanel.h"
|
|
#include "PlayerControllerBase.h"
|
|
#include "DefaultGameInstance.h"
|
|
#include "CharacterSettings.h"
|
|
#include "SlateBlueprintLibrary.h"
|
|
#include "ToolTipWidget.h"
|
|
#include "AbilityInfo.h"
|
|
#include "SizeBorder.h"
|
|
#include "WidgetLayoutLibrary.h"
|
|
|
|
int32 roundToNearestOdd1(float a_in)
|
|
{
|
|
return 2 * FMath::FloorToInt((a_in / 2) + 0.5f) - 2;
|
|
}
|
|
|
|
int32 roundToNearestEven1(float a_in)
|
|
{
|
|
return 2 * FMath::FloorToInt(a_in / 2);
|
|
}
|
|
|
|
void USkillTreeWidget::NativeOnSkillTreeChanged(ESkillTreeChangeEvent event, UBaseSkillObject* relevantObject)
|
|
{
|
|
// Recalculate dominantDamageType
|
|
int32_t categoryCounters[] = { 0,0,0 };
|
|
int32_t largest = 0;
|
|
for(USkillWidget* skill : m_skillWidgets)
|
|
{
|
|
if(skill->selectedEffect >= 0 && skill->skillAsset)
|
|
{
|
|
if(skill->selectedEffect >= skill->skillAsset->abilityEffects.Num())
|
|
{
|
|
GERROR("CORRUPT SKILL TREE");
|
|
continue;
|
|
}
|
|
|
|
UAbilityInfo* info = skill->skillAsset->abilityEffects[skill->selectedEffect];
|
|
int32_t& myCounter = categoryCounters[(size_t)info->abilityCategory];
|
|
myCounter++;
|
|
|
|
if(myCounter >= largest)
|
|
{
|
|
largest = myCounter;
|
|
dominantAbilityCategory = info->abilityCategory;
|
|
}
|
|
}
|
|
}
|
|
|
|
onSkillTreeChanged.Broadcast(event, relevantObject);
|
|
}
|
|
|
|
USkillTreeWidget::USkillTreeWidget(const FObjectInitializer& init)
|
|
: Super( init )
|
|
{
|
|
m_interactive = true;
|
|
m_shown = false;
|
|
m_lastFocusedWidget = nullptr;
|
|
isValid = false;
|
|
placedSkillHexMap = new FHexMap();
|
|
for (int32 x = 0; x < 13; x++)
|
|
{
|
|
placedSkillHexMap->rawdata[x] = 0;
|
|
}
|
|
}
|
|
|
|
void USkillTreeWidget::NativeConstruct()
|
|
{
|
|
Super::NativeConstruct();
|
|
|
|
UpdateVisibility();
|
|
|
|
// Get the tooltip widget
|
|
m_toolTipWidget = Cast<UToolTipWidget>(WidgetTree->FindWidget("ToolTipSWidget"));
|
|
|
|
m_sizeBorder = Cast<USizeBorder>(WidgetTree->FindWidget("SizeBorder"));
|
|
|
|
if ( !skillTreeAsset ) return;
|
|
TArray<UWidget*> widgets;
|
|
WidgetTree->GetAllWidgets( widgets );
|
|
UScrollBox* scrollBox = NULL;
|
|
m_skillTreeCanvas = WidgetTree->FindWidget<UCanvasPanel>("Main_SkillTree");
|
|
//m_focusBorder = WidgetTree->FindWidget<UBorder>("FocusBorder");
|
|
m_inputCapture = WidgetTree->FindWidget<UBorder>("InputCapture");
|
|
m_inputCapture->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
|
for ( int32 i = 0; i < widgets.Num(); i++ )
|
|
{
|
|
UHexagonTile* tmpHex = Cast<UHexagonTile>( widgets[i] );
|
|
UScrollBox* tmpScrollBox = Cast<UScrollBox>( widgets[i] );
|
|
//USkillWidget* tmpSkill = Cast<USkillWidget>( widgets[i] );
|
|
if ( tmpScrollBox ) scrollBox = tmpScrollBox;
|
|
//if ( tmpSkill ) m_selectedSkill = tmpSkill;
|
|
if ( !tmpHex ) continue;
|
|
tiles.Push( tmpHex );
|
|
bool test = skillTreeAsset->hexMap.Get( tmpHex->x, tmpHex->y );
|
|
if ( test ) tmpHex->SetVisibility( ESlateVisibility::Hidden );
|
|
}
|
|
if ( m_selectedSkill )
|
|
{
|
|
m_selectedSkill->parent = this;
|
|
m_selectedSkill->SetDragable( true );
|
|
}
|
|
else
|
|
{
|
|
YWARNING( "No Selected Skill found!" );
|
|
}
|
|
}
|
|
void USkillTreeWidget::NativeDestruct()
|
|
{
|
|
delete placedSkillHexMap;
|
|
Super::NativeDestruct();
|
|
}
|
|
|
|
void USkillTreeWidget::NativeTick(const FGeometry& MyGeometry, float DeltaTime)
|
|
{
|
|
Super::NativeTick(MyGeometry, DeltaTime);
|
|
|
|
//if ((m_focusBorder && m_focusBorder->IsHovered()) || draggingWidget)
|
|
//{
|
|
// //m_inputCapture->SetVisibility(ESlateVisibility::Visible);
|
|
//}
|
|
//else
|
|
//{
|
|
// //m_inputCapture->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
|
//}
|
|
|
|
if (m_toolTipWidget)
|
|
{
|
|
m_toolTipWidget->showTooltip = false;
|
|
|
|
FVector2D mousePos;
|
|
UWidgetLayoutLibrary::GetMousePositionScaledByDPI(GetOwningPlayer(), mousePos.X, mousePos.Y);
|
|
FIntPoint mouseGridPos = GetGridIndex(mousePos);
|
|
USkillWidget** sw = tileMap.Find(mouseGridPos);
|
|
USkillWidget* skill = sw ? *sw : nullptr;
|
|
if (skill)
|
|
{
|
|
// Reset hovered state
|
|
UAbilityInfo* info = skill->GetSelectedEffectAbility();
|
|
if (info)
|
|
{
|
|
m_toolTipWidget->SetTitle(info->name);
|
|
m_toolTipWidget->SetText(info->description);
|
|
m_toolTipWidget->position = skill->tooltipAreaPosition;
|
|
m_toolTipWidget->size = skill->tooltipAreaSize;
|
|
m_toolTipWidget->showTooltip = true;
|
|
}
|
|
skill->hovered = true;
|
|
}
|
|
if (m_lastFocusedWidget && m_lastFocusedWidget != skill)
|
|
{
|
|
m_lastFocusedWidget->hovered = false;
|
|
}
|
|
m_lastFocusedWidget = skill;
|
|
}
|
|
}
|
|
|
|
FReply USkillTreeWidget::NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
|
|
{
|
|
if(!IsInteractive())
|
|
return FReply::Handled();
|
|
//GWPRINT(L"Skill tree up");
|
|
if(draggingWidget && !draggingWidget->IsUsingController())
|
|
{
|
|
draggingWidget->StopDragging();
|
|
return FReply::Handled();
|
|
}
|
|
return FReply::Handled();
|
|
}
|
|
FReply USkillTreeWidget::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
|
|
{
|
|
if(!IsInteractive())
|
|
return FReply::Handled();
|
|
//GWPRINT(L"Skill tree down");
|
|
FKey button = InMouseEvent.GetEffectingButton();
|
|
if(button == EKeys::LeftMouseButton)
|
|
{
|
|
if(draggingWidget && !draggingWidget->IsUsingController())
|
|
{
|
|
draggingWidget->StopDragging();
|
|
return FReply::Handled();
|
|
}
|
|
else
|
|
{
|
|
if(m_lastFocusedWidget)
|
|
{
|
|
if(m_lastFocusedWidget->hovered)
|
|
m_lastFocusedWidget->StartDragging();
|
|
}
|
|
}
|
|
}
|
|
else if(button == EKeys::RightMouseButton)
|
|
{
|
|
if(!draggingWidget && m_lastFocusedWidget)
|
|
{
|
|
if(m_lastFocusedWidget->hovered)
|
|
{
|
|
m_lastFocusedWidget->OnRequireSkillEffect();
|
|
}
|
|
}
|
|
}
|
|
|
|
return FReply::Handled();
|
|
}
|
|
FReply USkillTreeWidget::NativeOnMouseWheel(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
|
|
{
|
|
//GWPRINT(L"USkillTreeWidget MouseWheel " + InMouseEvent.GetWheelDelta());
|
|
if (draggingWidget)
|
|
{
|
|
float add = 60.0f * FMath::FloorToFloat(InMouseEvent.GetWheelDelta());
|
|
draggingWidget->SetSkillRotation(add + draggingWidget->GetSkillRotation());
|
|
}
|
|
return FReply::Unhandled();
|
|
}
|
|
|
|
void USkillTreeWidget::SetIsInteractive(bool interactive)
|
|
{
|
|
m_interactive = interactive;
|
|
UpdateVisibility();
|
|
}
|
|
void USkillTreeWidget::UpdateVisibility()
|
|
{
|
|
if (m_shown)
|
|
{
|
|
SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
|
}
|
|
else
|
|
{
|
|
SetVisibility(ESlateVisibility::Hidden);
|
|
}
|
|
UImage* validImage = WidgetTree->FindWidget<UImage>("Validation_Image");
|
|
if (m_interactive)
|
|
{
|
|
validImage->SetVisibility(ESlateVisibility::Visible);
|
|
}
|
|
else
|
|
{
|
|
validImage->SetVisibility(ESlateVisibility::Hidden);
|
|
}
|
|
}
|
|
|
|
void WalkTree(TMap<USkillWidget*, TArray<USkillWidget*>>* a_map, TArray<USkillWidget*>* a_checked, TArray<USkillWidget*> a_nodes)
|
|
{
|
|
for (int32 i = 0; i < a_nodes.Num(); i++)
|
|
{
|
|
if (a_checked->Contains(a_nodes[i])) continue;
|
|
a_checked->Push(a_nodes[i]);
|
|
TArray<USkillWidget*>* connected = a_map->Find(a_nodes[i]);
|
|
if (!connected)
|
|
{
|
|
YERROR("Could not find the connected skills.");
|
|
continue;
|
|
}
|
|
WalkTree(a_map, a_checked, *connected);
|
|
}
|
|
}
|
|
|
|
bool USkillTreeWidget::ValidateSkillTree()
|
|
{
|
|
bool rootResult = false;
|
|
bool connectResult = true;
|
|
if (m_skillWidgets.Num() == 0) return true;
|
|
TMap<USkillWidget*, TArray<USkillWidget*>> connectedSkillsMap;
|
|
USkillWidget* rootSkill = NULL;
|
|
for (int32 i = 0; i < m_skillWidgets.Num(); i++)
|
|
{
|
|
TArray<FIntPoint> points = m_skillWidgets[i]->GetPoints();
|
|
if (!rootResult)
|
|
{
|
|
bool rootTest = m_skillWidgets[i]->ContainsRoot(points);
|
|
if (rootTest)
|
|
{
|
|
rootResult = true;
|
|
rootSkill = m_skillWidgets[i];
|
|
}
|
|
}
|
|
TArray<USkillWidget*> connectedSkills = m_skillWidgets[i]->ConnectedSkills(points);
|
|
connectedSkillsMap.Add(m_skillWidgets[i], connectedSkills);
|
|
if ( connectedSkills.Num() == 0 )
|
|
{
|
|
connectResult = false;
|
|
break;
|
|
}
|
|
}
|
|
if (connectResult && rootResult)
|
|
{
|
|
if (!rootSkill)
|
|
{
|
|
YERROR("Root Skill is NULL!");
|
|
return false;
|
|
}
|
|
TArray<USkillWidget*> checkedSkills;
|
|
checkedSkills.Push(rootSkill);
|
|
TArray<USkillWidget*>* connected = connectedSkillsMap.Find(rootSkill);
|
|
if (!connected)
|
|
{
|
|
YPRINT("Root Skill is not attached to any skills!");
|
|
return false;
|
|
}
|
|
WalkTree(&connectedSkillsMap, &checkedSkills, *connected);
|
|
if (m_skillWidgets.Num() != checkedSkills.Num())
|
|
connectResult = false;
|
|
else
|
|
{
|
|
for (int32 i = 0; i < m_skillWidgets.Num(); i++)
|
|
{
|
|
if (!checkedSkills.Contains(m_skillWidgets[i]))
|
|
{
|
|
connectResult = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (m_skillWidgets.Num() == 1 && rootResult)
|
|
isValid = true;
|
|
else
|
|
isValid = (rootResult && connectResult);
|
|
if (isValid)
|
|
{
|
|
UpdateLevel(10.0f);
|
|
}
|
|
else
|
|
{
|
|
UpdateLevel(0.0f);
|
|
}
|
|
return isValid;
|
|
}
|
|
|
|
FSkillTreeState USkillTreeWidget::GetState()
|
|
{
|
|
FSkillTreeState state;
|
|
for(int32 i = 0; i < m_skillWidgets.Num(); i++)
|
|
{
|
|
FSkillTreeStateObject obj;
|
|
USkillWidget* skill = m_skillWidgets[i];
|
|
obj.gridIndex = skill->GetGridIndex() /*- FVector2D(1.5,4) * m_skillTreeCanvas->RenderTransform.Scale.X*/;
|
|
obj.placedPoints = skill->placedPoints;
|
|
obj.skillObject = skill->skillAsset->GetClass();
|
|
obj.rotation = skill->GetSkillRotation();
|
|
obj.selectedEffect = skill->selectedEffect;
|
|
state.objects.Add(obj);
|
|
|
|
//GWPRINT(L"Saving gridIndex " + obj.gridIndex);
|
|
//for(int32 i = 0; i < obj.placedPoints.Num(); i++)
|
|
//{
|
|
// GWPRINT(L"Saving Placed point " + i + L" " + obj.placedPoints[i].X + L", " + obj.placedPoints[i].Y);
|
|
//}
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
TArray<class UBaseSkillObject*> USkillTreeWidget::GetApearanceState()
|
|
{
|
|
return m_skillClasses;
|
|
}
|
|
|
|
void USkillTreeWidget::Clear()
|
|
{
|
|
// Remove all placed hexes
|
|
auto arrayCopy = m_skillWidgets;
|
|
for(int32 i = 0; i < arrayCopy.Num(); i++)
|
|
{
|
|
arrayCopy[i]->RemoveFromParent();
|
|
RemoveSkill(arrayCopy[i], arrayCopy[i]->placedPoints);
|
|
}
|
|
m_skillWidgets.SetNum(0);
|
|
m_skillClasses.SetNum(0);
|
|
tileMap.Reset();
|
|
|
|
// Clear Hex map
|
|
for(int32 x = 0; x < 13; x++)
|
|
{
|
|
placedSkillHexMap->rawdata[x] = 0;
|
|
}
|
|
|
|
isValid = true;
|
|
|
|
// Trigger Callbacks
|
|
NativeOnSkillTreeChanged(ESkillTreeChangeEvent::Cleared, nullptr);
|
|
}
|
|
void USkillTreeWidget::BuildFromState(const FSkillTreeState& state)
|
|
{
|
|
Clear();
|
|
for(int32 i = 0; i < state.objects.Num(); i++)
|
|
{
|
|
const FSkillTreeStateObject& obj = state.objects[i];
|
|
UBaseSkillObject* baseSkill = obj.skillObject->GetDefaultObject<UBaseSkillObject>();
|
|
|
|
if(!baseSkill)
|
|
continue;
|
|
|
|
//GWPRINT(L"gridIndex " + obj.gridIndex);
|
|
//for(int32 i = 0; i < obj.placedPoints.Num(); i++)
|
|
//{
|
|
// GWPRINT(L"Placed point " + i + L" " + obj.placedPoints[i].X + L", " + obj.placedPoints[i].Y);
|
|
//}
|
|
|
|
m_selectedSkill = CreateWidget<USkillWidget>(GetWorld(), WidgetTemplate);
|
|
m_selectedSkill->skillAsset = baseSkill;
|
|
m_selectedSkill->parent = this;
|
|
if(m_skillTreeCanvas)
|
|
m_selectedSkill->SetRenderScale(m_skillTreeCanvas->RenderTransform.Scale);
|
|
m_selectedSkill->SetPlaced();
|
|
if(m_skillTreeCanvas)
|
|
m_skillTreeCanvas->GetParent()->AddChild(m_selectedSkill);
|
|
UCanvasPanelSlot* slot = Cast<UCanvasPanelSlot>(m_selectedSkill->Slot);
|
|
if(slot)
|
|
{
|
|
slot->SetAutoSize(true);
|
|
slot->SetAlignment(FVector2D(-0.5f, -0.5f));
|
|
}
|
|
m_selectedSkill->SetSelectedEffect(obj.selectedEffect);
|
|
m_selectedSkill->placedPoints = obj.placedPoints;
|
|
m_selectedSkill->SetSkillRotation(obj.rotation);
|
|
m_selectedSkill->PlaceOnGridIndex(obj.gridIndex);
|
|
AddSkill(m_selectedSkill, obj.placedPoints);
|
|
}
|
|
}
|
|
|
|
void USkillTreeWidget::RemoveSkill(UBaseSkillObject* skillObject)
|
|
{
|
|
int32 skillID = m_skillClasses.Find(skillObject);
|
|
if (skillID == INDEX_NONE) return;
|
|
CancelSkill(m_skillWidgets[skillID]);
|
|
m_skillWidgets[skillID]->Remove();
|
|
}
|
|
|
|
bool USkillTreeWidget::IsUsingSkill(UBaseSkillObject* skillObject) const
|
|
{
|
|
return m_skillClasses.Contains(skillObject);
|
|
}
|
|
|
|
USkillWidget* USkillTreeWidget::GetUsedSkill(class UBaseSkillObject* skillObject)
|
|
{
|
|
for (int32 i = 0; i < m_skillWidgets.Num(); i++)
|
|
{
|
|
if (m_skillWidgets[i]->skillAsset == skillObject)
|
|
return m_skillWidgets[i];
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void USkillTreeWidget::Save(int32 saveSlot)
|
|
{
|
|
UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());
|
|
UCharacterSettings* settings = inst->GetCharacterSettings();
|
|
|
|
if (saveSlot < 0 || saveSlot >= settings->characterSaves.Num())
|
|
{
|
|
JERROR("Invalid save slot");
|
|
return;
|
|
}
|
|
|
|
settings->characterSaves[saveSlot].skillTreeState = GetState();
|
|
inst->SaveSettings();
|
|
}
|
|
void USkillTreeWidget::Load(int32 saveSlot)
|
|
{
|
|
UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());
|
|
UCharacterSettings* settings = inst->GetCharacterSettings();
|
|
|
|
if (saveSlot < 0 || saveSlot >= settings->characterSaves.Num())
|
|
{
|
|
JERROR("Invalid save slot");
|
|
return;
|
|
}
|
|
|
|
BuildFromState(settings->characterSaves[saveSlot].skillTreeState);
|
|
ValidateSkillTree();
|
|
}
|
|
|
|
FIntPoint USkillTreeWidget::GetGridIndex(FVector2D in) const
|
|
{
|
|
FVector2D result;
|
|
UCanvasPanelSlot* tmpSlot = UWidgetLayoutLibrary::SlotAsCanvasSlot(m_skillTreeCanvas);
|
|
float viewportScale = UWidgetLayoutLibrary::GetViewportScale(const_cast<USkillTreeWidget*>(this));
|
|
FVector2D topLeft;
|
|
float scale = 32.0f * (m_skillTreeCanvas->RenderTransform.Scale.X / 2);
|
|
float XScale = (scale * 1.73205f);
|
|
float YScale = scale;
|
|
if (tmpSlot)
|
|
{
|
|
FVector2D screenTopRight = FVector2D(GEngine->GameViewport->Viewport->GetSizeXY().X * tmpSlot->GetAnchors().Minimum.X, GEngine->GameViewport->Viewport->GetSizeXY().Y * tmpSlot->GetAnchors().Minimum.Y);
|
|
FVector2D offset = tmpSlot->GetPosition() * viewportScale;
|
|
FVector2D widgetTopLeft = ((tmpSlot->GetSize() * m_skillTreeCanvas->RenderTransform.Scale.X * viewportScale) / 2);
|
|
topLeft = screenTopRight + offset - widgetTopLeft;
|
|
topLeft /= viewportScale;
|
|
//topLeft.X -= 16.0f;
|
|
}
|
|
|
|
float XPreFloor = (in.X - topLeft.X) / XScale;
|
|
float YPreFloor = (in.Y - topLeft.Y) / YScale;
|
|
int32 XIndex = FMath::FloorToInt(XPreFloor);
|
|
int32 YIndex = FMath::FloorToInt(YPreFloor);
|
|
/*FVector2D magicOffset = FVector2D(1.5, 4) * m_skillTreeCanvas->RenderTransform.Scale.X;*/
|
|
bool odd = (XIndex % 2) == 1;
|
|
if (odd)
|
|
YIndex = roundToNearestOdd1(YIndex);
|
|
else
|
|
YIndex = roundToNearestEven1(YIndex);
|
|
return FIntPoint(XIndex, (YIndex) / 2.0f);
|
|
}
|
|
|
|
void USkillTreeWidget::StartDragging(USkillWidget* widget)
|
|
{
|
|
check(draggingWidget == nullptr);
|
|
draggingWidget = widget;
|
|
m_inputCapture->SetVisibility(ESlateVisibility::Visible);
|
|
}
|
|
|
|
void USkillTreeWidget::StopDragging(USkillWidget* widget)
|
|
{
|
|
if(draggingWidget != widget)
|
|
{
|
|
GERROR("Calling StopDragging twice");
|
|
}
|
|
draggingWidget = nullptr;
|
|
m_inputCapture->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
|
}
|
|
|
|
void USkillTreeWidget::UpdateTextInfo_Implementation()
|
|
{
|
|
}
|
|
|
|
void USkillTreeWidget::AddSkill(USkillWidget* a_skill, const TArray<FIntPoint>& a_points)
|
|
{
|
|
for ( int32 i = 0; i < a_points.Num(); i++ )
|
|
{
|
|
placedSkillHexMap->Set( a_points[i].X, a_points[i].Y, true );
|
|
|
|
tileMap.Add(a_points[i], a_skill);
|
|
}
|
|
|
|
UWorld* const world = GetWorld();
|
|
if ( !world )
|
|
{
|
|
YWARNING( "Couldn't get the World." );
|
|
return;
|
|
}
|
|
APlayerControllerBase* const controller = Cast<APlayerControllerBase>( GetOwningPlayer() );
|
|
if ( !controller )
|
|
{
|
|
YWARNING( "Couldn't get the Player." );
|
|
return;
|
|
}
|
|
controller->OnLearnSkill( a_skill->skillAsset );
|
|
m_skillWidgets.Add(a_skill);
|
|
m_skillClasses.Add(a_skill->skillAsset);
|
|
|
|
// Trigger Callbacks
|
|
NativeOnSkillTreeChanged(ESkillTreeChangeEvent::Added, a_skill->skillAsset);
|
|
|
|
ValidateSkillTree();
|
|
}
|
|
|
|
void USkillTreeWidget::RemoveSkill( USkillWidget* a_skill, const TArray<FIntPoint>& a_points )
|
|
{
|
|
m_skillClasses.Remove(a_skill->skillAsset);
|
|
m_skillWidgets.Remove(a_skill);
|
|
for ( int32 i = 0; i < a_points.Num(); i++ )
|
|
{
|
|
placedSkillHexMap->Set( a_points[i].X, a_points[i].Y, false );
|
|
tileMap.Remove(a_points[i]);
|
|
}
|
|
|
|
UWorld* const world = GetWorld();
|
|
if ( !world )
|
|
{
|
|
YWARNING( "Couldn't get the World." );
|
|
return;
|
|
}
|
|
APlayerControllerBase* const controller = Cast<APlayerControllerBase>( GetOwningPlayer() );
|
|
if ( !controller )
|
|
{
|
|
YWARNING( "Couldn't get the Player." );
|
|
return;
|
|
}
|
|
controller->OnUnlearnSkill( a_skill->skillAsset );
|
|
|
|
// Trigger Callbacks
|
|
NativeOnSkillTreeChanged(ESkillTreeChangeEvent::Removed, a_skill->skillAsset);
|
|
}
|
|
|
|
USkillWidget* USkillTreeWidget::NewSkill( USkillWidget* a_skill, bool controller )
|
|
{
|
|
return NewSkillFromAsset(a_skill->skillAsset, controller);
|
|
}
|
|
|
|
class USkillWidget* USkillTreeWidget::NewSkillFromAsset(UBaseSkillObject* skillAsset, bool controller /*= false*/)
|
|
{
|
|
if(draggingWidget)
|
|
return NULL;
|
|
//a_skill->Disable();
|
|
m_selectedSkill = CreateWidget<USkillWidget>(GetWorld(), WidgetTemplate);
|
|
m_selectedSkill->skillAsset = skillAsset;
|
|
m_selectedSkill->parent = this;
|
|
m_selectedSkill->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
|
m_selectedSkill->SetDragable(true, controller);
|
|
m_selectedSkill->SetRenderScale(m_skillTreeCanvas->RenderTransform.Scale);
|
|
m_skillTreeCanvas->GetParent()->AddChild(m_selectedSkill);
|
|
m_selectedSkill->SetUserFocus(GetOwningPlayer());
|
|
UCanvasPanelSlot* slot = Cast<UCanvasPanelSlot>(m_selectedSkill->Slot);
|
|
if(slot)
|
|
{
|
|
slot->SetAutoSize(true);
|
|
slot->SetAlignment(FVector2D(-0.5f, -0.5f));
|
|
}
|
|
|
|
if(controller)
|
|
{
|
|
// Set initial position
|
|
m_selectedSkill->MoveSkillAbsolute(lastGridIndex);
|
|
}
|
|
|
|
return m_selectedSkill;
|
|
}
|
|
|
|
void USkillTreeWidget::CancelSkill(USkillWidget* a_skill)
|
|
{
|
|
a_skill->RemoveFromParent();
|
|
ValidateSkillTree();
|
|
}
|
|
|
|
void USkillTreeWidget::Show()
|
|
{
|
|
m_shown = true;
|
|
UpdateVisibility();
|
|
}
|
|
|
|
void USkillTreeWidget::Hide()
|
|
{
|
|
m_shown = false;
|
|
UpdateVisibility();
|
|
}
|
|
|
|
void USkillTreeWidget::UpdateLevel(float level)
|
|
{
|
|
for (int32 i = 0; i < m_skillWidgets.Num(); i++)
|
|
{
|
|
m_skillWidgets[i]->UpdateLevel(level);
|
|
}
|
|
if (IsInteractable())
|
|
{
|
|
UpdateTextInfo();
|
|
}
|
|
}
|
|
|
|
void USkillTreeWidget::UpdateInfo(float skilltreeHeight, float skilltreeOffset)
|
|
{
|
|
for (int32 i = 0; i < m_skillWidgets.Num(); i++)
|
|
{
|
|
m_skillWidgets[i]->UpdateInfo(skilltreeHeight, skilltreeOffset);
|
|
}
|
|
}
|
|
|
|
/*
|
|
void USkillTreeWidget::NativeTick(const FGeometry& MyGeometry, float DeltaTime)
|
|
{
|
|
FVector2D minPos;
|
|
FVector2D maxPos;
|
|
FVector2D viewportPos;
|
|
USlateBlueprintLibrary::LocalToViewport(this, MyGeometry, MyGeometry.GetLocalSize(), maxPos, viewportPos);
|
|
USlateBlueprintLibrary::LocalToViewport(this, MyGeometry, FVector2D(0,0), minPos, viewportPos);
|
|
FVector2D viewportSize = maxPos - minPos;
|
|
for (int32 i = 0; i < m_skillWidgets.Num(); i++)
|
|
{
|
|
m_skillWidgets[i]->UpdateInfo(viewportSize.Y, minPos.Y);
|
|
}
|
|
}
|
|
*/ |