CelticCraft/Plugins/VoxelFree/Source/Voxel/Private/VoxelTools/VoxelToolHelpers.cpp

213 lines
6 KiB
C++
Raw Normal View History

2023-07-03 16:17:13 +00:00
// Copyright 2020 Phyronnaz
#include "VoxelTools/VoxelToolHelpers.h"
#include "VoxelRender/IVoxelLODManager.h"
#include "IVoxelPool.h"
#include "Engine/Engine.h"
#include "Async/Async.h"
FVoxelLatentActionAsyncWork::FVoxelLatentActionAsyncWork(FName Name)
: FVoxelAsyncWorkWithWait(Name, 1e9)
{
}
uint32 FVoxelLatentActionAsyncWork::GetPriority() const
{
return 0;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
FVoxelLatentActionAsyncWork_WithWorld::FVoxelLatentActionAsyncWork_WithWorld(
FName Name,
TWeakObjectPtr<AVoxelWorld> World,
TFunction<void(FVoxelData&)> Function)
: FVoxelLatentActionAsyncWork(Name)
, World(World)
, Data(World->GetDataSharedPtr())
, Function(MoveTemp(Function))
{
}
void FVoxelLatentActionAsyncWork_WithWorld::DoWork()
{
const auto PinnedData = Data.Pin();
if (PinnedData.IsValid())
{
Function(*PinnedData);
}
}
bool FVoxelLatentActionAsyncWork_WithWorld::IsValid() const
{
return World.IsValid() && Data.IsValid();
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
FVoxelLatentActionAsyncWork_WithoutWorld::FVoxelLatentActionAsyncWork_WithoutWorld(FName Name, TFunction<void()> Function, TFunction<bool()> IsValidLambda)
: FVoxelLatentActionAsyncWork(Name)
, Function(MoveTemp(Function))
, IsValidLambda(MoveTemp(IsValidLambda))
{
}
void FVoxelLatentActionAsyncWork_WithoutWorld::DoWork()
{
Function();
}
bool FVoxelLatentActionAsyncWork_WithoutWorld::IsValid() const
{
return IsValidLambda();
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void FVoxelToolHelpers::UpdateWorld(AVoxelWorld* World, const FVoxelIntBox& Bounds)
{
check(World);
World->GetLODManager().UpdateBounds(Bounds);
}
void FVoxelToolHelpers::StartAsyncEditTask(AVoxelWorld* World, IVoxelQueuedWork* Work)
{
if (World)
{
World->GetPool().QueueTask(EVoxelTaskType::AsyncEditFunctions, Work);
}
else
{
// Should be safe as async tasks should be flushed on close
AsyncTask(ENamedThreads::AnyThread, [Work]() { Work->DoThreadedWork(); });
}
}
float FVoxelToolHelpers::GetRealDistance(AVoxelWorld* World, float Distance, bool bConvertToVoxelSpace)
{
if (bConvertToVoxelSpace)
{
return Distance / World->VoxelSize;
}
else
{
return Distance;
}
}
FVoxelVector FVoxelToolHelpers::GetRealPosition(AVoxelWorld* World, const FVector& Position, bool bConvertToVoxelSpace)
{
if (bConvertToVoxelSpace)
{
return World->GlobalToLocalFloat(Position);
}
else
{
return Position;
}
}
FTransform FVoxelToolHelpers::GetRealTransform(AVoxelWorld* World, FTransform Transform, bool bConvertToVoxelSpace)
{
if (bConvertToVoxelSpace)
{
Transform *= World->GetActorTransform().Inverse();
Transform.ScaleTranslation(1.f / World->VoxelSize);
}
return Transform;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool FVoxelToolHelpers::StartLatentAction(UObject* WorldContextObject, FLatentActionInfo LatentInfo, FName Name, bool bHideLatentWarnings, TFunction<FPendingLatentAction*()> CreateLatentAction)
{
if (UWorld* WorldContext = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull))
{
FLatentActionManager& LatentActionManager = WorldContext->GetLatentActionManager();
if (!LatentActionManager.FindExistingAction<FPendingLatentAction>(LatentInfo.CallbackTarget, LatentInfo.UUID))
{
auto* LatentAction = CreateLatentAction();
LatentActionManager.AddNewAction(
LatentInfo.CallbackTarget,
LatentInfo.UUID,
LatentAction);
return true;
}
else
{
if (!bHideLatentWarnings)
{
FVoxelMessages::Info(
FString::Printf(
TEXT("%s: task already pending for this node (tick HideLatentWarnings on the node to hide this message)."),
*Name.ToString()));
}
return false;
}
}
else
{
FVoxelMessages::Info(
FString::Printf(
TEXT("%s: invalid world context object."),
*Name.ToString()));
return false;
}
}
bool FVoxelToolHelpers::StartAsyncLatentAction_WithWorld(
UObject* WorldContextObject,
FLatentActionInfo LatentInfo,
AVoxelWorld* World,
FName Name,
bool bHideLatentWarnings,
TFunction<void(FVoxelData&)> DoWork,
EVoxelUpdateRender UpdateRender,
const FVoxelIntBox& BoundsToUpdate)
{
return StartAsyncLatentActionImpl<FVoxelLatentActionAsyncWork_WithWorld>(
WorldContextObject,
LatentInfo,
World,
Name,
bHideLatentWarnings,
[&]() { return new FVoxelLatentActionAsyncWork_WithWorld(Name, World, DoWork); },
[=](FVoxelLatentActionAsyncWork_WithWorld& Work)
{
if (UpdateRender == EVoxelUpdateRender::UpdateRender && Work.World.IsValid())
{
UpdateWorld(Work.World.Get(), BoundsToUpdate);
}
});
}
bool FVoxelToolHelpers::StartAsyncLatentAction_WithoutWorld(
UObject* WorldContextObject,
FLatentActionInfo LatentInfo,
FName Name,
bool bHideLatentWarnings,
TFunction<void()> DoWork,
TFunction<bool()> IsValid)
{
return StartAsyncLatentActionImpl<FVoxelLatentActionAsyncWork_WithoutWorld>(
WorldContextObject,
LatentInfo,
nullptr,
Name,
bHideLatentWarnings,
[&]() { return new FVoxelLatentActionAsyncWork_WithoutWorld(Name, DoWork, MoveTemp(IsValid)); },
[=](auto&) {});
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////