Merge branch 'master' into Improve-HighlightedPopUpColor
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include "Engine/Threading/Threading.h"
|
||||
#include "Engine/Threading/Task.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Profiler/ProfilerMemory.h"
|
||||
#include "Engine/Scripting/BinaryModule.h"
|
||||
#include "Engine/Scripting/Scripting.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MAssembly.h"
|
||||
@@ -219,6 +220,7 @@ namespace
|
||||
if (module == GetBinaryModuleCorlib())
|
||||
return;
|
||||
PROFILE_CPU();
|
||||
PROFILE_MEM(EngineDebug);
|
||||
|
||||
#if USE_CSHARP
|
||||
if (auto* managedModule = dynamic_cast<ManagedBinaryModule*>(module))
|
||||
@@ -381,6 +383,7 @@ DebugCommandsService DebugCommandsServiceInstance;
|
||||
|
||||
void DebugCommands::Execute(StringView command)
|
||||
{
|
||||
PROFILE_MEM(EngineDebug);
|
||||
// TODO: fix missing string handle on 1st command execution (command gets invalid after InitCommands due to dotnet GC or dotnet interop handles flush)
|
||||
String commandCopy = command;
|
||||
command = commandCopy;
|
||||
@@ -423,6 +426,7 @@ void DebugCommands::Search(StringView searchText, Array<StringView>& matches, bo
|
||||
{
|
||||
if (searchText.IsEmpty())
|
||||
return;
|
||||
PROFILE_MEM(EngineDebug);
|
||||
// TODO: fix missing string handle on 1st command execution (command gets invalid after InitCommands due to dotnet GC or dotnet interop handles flush)
|
||||
String searchTextCopy = searchText;
|
||||
searchText = searchTextCopy;
|
||||
|
||||
@@ -480,6 +480,7 @@ DebugDrawCall WriteLists(int32& vertexCounter, const Array<T>& listA, const Arra
|
||||
|
||||
FORCE_INLINE DebugTriangle* AppendTriangles(int32 count, float duration, bool depthTest)
|
||||
{
|
||||
PROFILE_MEM(EngineDebug);
|
||||
Array<DebugTriangle>* list;
|
||||
if (depthTest)
|
||||
list = duration > 0 ? &Context->DebugDrawDepthTest.DefaultTriangles : &Context->DebugDrawDepthTest.OneFrameTriangles;
|
||||
@@ -492,6 +493,7 @@ FORCE_INLINE DebugTriangle* AppendTriangles(int32 count, float duration, bool de
|
||||
|
||||
FORCE_INLINE DebugTriangle* AppendWireTriangles(int32 count, float duration, bool depthTest)
|
||||
{
|
||||
PROFILE_MEM(EngineDebug);
|
||||
Array<DebugTriangle>* list;
|
||||
if (depthTest)
|
||||
list = duration > 0 ? &Context->DebugDrawDepthTest.DefaultWireTriangles : &Context->DebugDrawDepthTest.OneFrameWireTriangles;
|
||||
@@ -539,7 +541,7 @@ DebugDrawService DebugDrawServiceInstance;
|
||||
|
||||
bool DebugDrawService::Init()
|
||||
{
|
||||
PROFILE_MEM(Graphics);
|
||||
PROFILE_MEM(EngineDebug);
|
||||
Context = &GlobalContext;
|
||||
|
||||
// Init wireframe sphere cache
|
||||
@@ -658,7 +660,7 @@ void DebugDrawService::Update()
|
||||
}
|
||||
|
||||
PROFILE_CPU();
|
||||
PROFILE_MEM(Graphics);
|
||||
PROFILE_MEM(EngineDebug);
|
||||
|
||||
// Update lists
|
||||
float deltaTime = Time::Update.DeltaTime.GetTotalSeconds();
|
||||
@@ -1114,6 +1116,7 @@ void DebugDraw::DrawRay(const Ray& ray, const Color& color, float length, float
|
||||
|
||||
void DebugDraw::DrawLine(const Vector3& start, const Vector3& end, const Color& color, float duration, bool depthTest)
|
||||
{
|
||||
PROFILE_MEM(EngineDebug);
|
||||
const Float3 startF = start - Context->Origin, endF = end - Context->Origin;
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
if (duration > 0)
|
||||
@@ -1132,6 +1135,7 @@ void DebugDraw::DrawLine(const Vector3& start, const Vector3& end, const Color&
|
||||
|
||||
void DebugDraw::DrawLine(const Vector3& start, const Vector3& end, const Color& startColor, const Color& endColor, float duration, bool depthTest)
|
||||
{
|
||||
PROFILE_MEM(EngineDebug);
|
||||
const Float3 startF = start - Context->Origin, endF = end - Context->Origin;
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
if (duration > 0)
|
||||
@@ -1161,6 +1165,7 @@ void DebugDraw::DrawLines(const Span<Float3>& lines, const Matrix& transform, co
|
||||
}
|
||||
|
||||
// Draw lines
|
||||
PROFILE_MEM(EngineDebug);
|
||||
const Float3* p = lines.Get();
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
const Matrix transformF = transform * Matrix::Translation(-Context->Origin);
|
||||
@@ -1200,6 +1205,7 @@ void DebugDraw::DrawLines(GPUBuffer* lines, const Matrix& transform, float durat
|
||||
}
|
||||
|
||||
// Draw lines
|
||||
PROFILE_MEM(EngineDebug);
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
auto& geometry = debugDrawData.GeometryBuffers.AddOne();
|
||||
geometry.Buffer = lines;
|
||||
@@ -1224,6 +1230,7 @@ void DebugDraw::DrawLines(const Span<Double3>& lines, const Matrix& transform, c
|
||||
}
|
||||
|
||||
// Draw lines
|
||||
PROFILE_MEM(EngineDebug);
|
||||
const Double3* p = lines.Get();
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
const Matrix transformF = transform * Matrix::Translation(-Context->Origin);
|
||||
@@ -1270,6 +1277,7 @@ void DebugDraw::DrawBezier(const Vector3& p1, const Vector3& p2, const Vector3&
|
||||
const float segmentCountInv = 1.0f / (float)segmentCount;
|
||||
|
||||
// Draw segmented curve from lines
|
||||
PROFILE_MEM(EngineDebug);
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
if (duration > 0)
|
||||
{
|
||||
@@ -1310,6 +1318,7 @@ void DebugDraw::DrawWireBox(const BoundingBox& box, const Color& color, float du
|
||||
c -= Context->Origin;
|
||||
|
||||
// Draw lines
|
||||
PROFILE_MEM(EngineDebug);
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
if (duration > 0)
|
||||
{
|
||||
@@ -1344,6 +1353,7 @@ void DebugDraw::DrawWireFrustum(const BoundingFrustum& frustum, const Color& col
|
||||
c -= Context->Origin;
|
||||
|
||||
// Draw lines
|
||||
PROFILE_MEM(EngineDebug);
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
if (duration > 0)
|
||||
{
|
||||
@@ -1378,6 +1388,7 @@ void DebugDraw::DrawWireBox(const OrientedBoundingBox& box, const Color& color,
|
||||
c -= Context->Origin;
|
||||
|
||||
// Draw lines
|
||||
PROFILE_MEM(EngineDebug);
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
if (duration > 0)
|
||||
{
|
||||
@@ -1419,6 +1430,7 @@ void DebugDraw::DrawWireSphere(const BoundingSphere& sphere, const Color& color,
|
||||
auto& cache = SphereCache[index];
|
||||
|
||||
// Draw lines of the unit sphere after linear transform
|
||||
PROFILE_MEM(EngineDebug);
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
if (duration > 0)
|
||||
{
|
||||
@@ -1454,6 +1466,7 @@ void DebugDraw::DrawSphere(const BoundingSphere& sphere, const Color& color, flo
|
||||
list = duration > 0 ? &Context->DebugDrawDepthTest.DefaultTriangles : &Context->DebugDrawDepthTest.OneFrameTriangles;
|
||||
else
|
||||
list = duration > 0 ? &Context->DebugDrawDefault.DefaultTriangles : &Context->DebugDrawDefault.OneFrameTriangles;
|
||||
PROFILE_MEM(EngineDebug);
|
||||
list->EnsureCapacity(list->Count() + SphereTriangleCache.Count());
|
||||
|
||||
const Float3 centerF = sphere.Center - Context->Origin;
|
||||
@@ -1485,6 +1498,7 @@ void DebugDraw::DrawCircle(const Vector3& position, const Float3& normal, float
|
||||
Matrix::Multiply(scale, world, matrix);
|
||||
|
||||
// Draw lines of the unit circle after linear transform
|
||||
PROFILE_MEM(EngineDebug);
|
||||
Float3 prev = Float3::Transform(CircleCache[0], matrix);
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
for (int32 i = 1; i < DEBUG_DRAW_CIRCLE_VERTICES;)
|
||||
@@ -1515,6 +1529,7 @@ void DebugDraw::DrawWireTriangle(const Vector3& v0, const Vector3& v1, const Vec
|
||||
|
||||
void DebugDraw::DrawTriangle(const Vector3& v0, const Vector3& v1, const Vector3& v2, const Color& color, float duration, bool depthTest)
|
||||
{
|
||||
PROFILE_MEM(EngineDebug);
|
||||
DebugTriangle t;
|
||||
t.Color = Color32(color);
|
||||
t.TimeLeft = duration;
|
||||
@@ -1570,6 +1585,7 @@ void DebugDraw::DrawTriangles(GPUBuffer* triangles, const Matrix& transform, flo
|
||||
DebugLog::ThrowException("Cannot draw debug lines with incorrect amount of items in array");
|
||||
return;
|
||||
}
|
||||
PROFILE_MEM(EngineDebug);
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
auto& geometry = debugDrawData.GeometryBuffers.AddOne();
|
||||
geometry.Buffer = triangles;
|
||||
@@ -1859,6 +1875,7 @@ void DebugDraw::DrawWireCapsule(const Vector3& position, const Quaternion& orien
|
||||
Matrix::Multiply(rotation, translation, world);
|
||||
|
||||
// Write vertices
|
||||
PROFILE_MEM(EngineDebug);
|
||||
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
|
||||
Color32 color32(color);
|
||||
if (duration > 0)
|
||||
@@ -1953,6 +1970,7 @@ namespace
|
||||
void DrawCylinder(Array<DebugTriangle>* list, const Vector3& position, const Quaternion& orientation, float radius, float height, const Color& color, float duration)
|
||||
{
|
||||
// Setup cache
|
||||
PROFILE_MEM(EngineDebug);
|
||||
Float3 CylinderCache[DEBUG_DRAW_CYLINDER_VERTICES];
|
||||
const float angleBetweenFacets = TWO_PI / DEBUG_DRAW_CYLINDER_RESOLUTION;
|
||||
const float verticalOffset = height * 0.5f;
|
||||
@@ -2024,6 +2042,7 @@ namespace
|
||||
|
||||
void DrawCone(Array<DebugTriangle>* list, const Vector3& position, const Quaternion& orientation, float radius, float angleXY, float angleXZ, const Color& color, float duration)
|
||||
{
|
||||
PROFILE_MEM(EngineDebug);
|
||||
const float tolerance = 0.001f;
|
||||
const float angle1 = Math::Clamp(angleXY, tolerance, PI - tolerance);
|
||||
const float angle2 = Math::Clamp(angleXZ, tolerance, PI - tolerance);
|
||||
@@ -2113,6 +2132,7 @@ void DebugDraw::DrawArc(const Vector3& position, const Quaternion& orientation,
|
||||
{
|
||||
if (angle <= 0)
|
||||
return;
|
||||
PROFILE_MEM(EngineDebug);
|
||||
if (angle > TWO_PI)
|
||||
angle = TWO_PI;
|
||||
Array<DebugTriangle>* list;
|
||||
@@ -2145,6 +2165,7 @@ void DebugDraw::DrawWireArc(const Vector3& position, const Quaternion& orientati
|
||||
{
|
||||
if (angle <= 0)
|
||||
return;
|
||||
PROFILE_MEM(EngineDebug);
|
||||
if (angle > TWO_PI)
|
||||
angle = TWO_PI;
|
||||
const int32 resolution = Math::CeilToInt((float)DEBUG_DRAW_CONE_RESOLUTION / TWO_PI * angle);
|
||||
@@ -2211,6 +2232,7 @@ void DebugDraw::DrawBox(const BoundingBox& box, const Color& color, float durati
|
||||
list = duration > 0 ? &Context->DebugDrawDepthTest.DefaultTriangles : &Context->DebugDrawDepthTest.OneFrameTriangles;
|
||||
else
|
||||
list = duration > 0 ? &Context->DebugDrawDefault.DefaultTriangles : &Context->DebugDrawDefault.OneFrameTriangles;
|
||||
PROFILE_MEM(EngineDebug);
|
||||
list->EnsureCapacity(list->Count() + 36);
|
||||
for (int i0 = 0; i0 < 36;)
|
||||
{
|
||||
@@ -2239,6 +2261,7 @@ void DebugDraw::DrawBox(const OrientedBoundingBox& box, const Color& color, floa
|
||||
list = duration > 0 ? &Context->DebugDrawDepthTest.DefaultTriangles : &Context->DebugDrawDepthTest.OneFrameTriangles;
|
||||
else
|
||||
list = duration > 0 ? &Context->DebugDrawDefault.DefaultTriangles : &Context->DebugDrawDefault.OneFrameTriangles;
|
||||
PROFILE_MEM(EngineDebug);
|
||||
list->EnsureCapacity(list->Count() + 36);
|
||||
for (int i0 = 0; i0 < 36;)
|
||||
{
|
||||
@@ -2254,6 +2277,7 @@ void DebugDraw::DrawText(const StringView& text, const Float2& position, const C
|
||||
{
|
||||
if (text.Length() == 0 || size < 4)
|
||||
return;
|
||||
PROFILE_MEM(EngineDebug);
|
||||
Array<DebugText2D>* list = duration > 0 ? &Context->DebugDrawDefault.DefaultText2D : &Context->DebugDrawDefault.OneFrameText2D;
|
||||
auto& t = list->AddOne();
|
||||
t.Text.Resize(text.Length() + 1);
|
||||
@@ -2269,6 +2293,7 @@ void DebugDraw::DrawText(const StringView& text, const Vector3& position, const
|
||||
{
|
||||
if (text.Length() == 0 || size < 4)
|
||||
return;
|
||||
PROFILE_MEM(EngineDebug);
|
||||
Array<DebugText3D>* list = duration > 0 ? &Context->DebugDrawDefault.DefaultText3D : &Context->DebugDrawDefault.OneFrameText3D;
|
||||
auto& t = list->AddOne();
|
||||
t.Text.Resize(text.Length() + 1);
|
||||
@@ -2286,6 +2311,7 @@ void DebugDraw::DrawText(const StringView& text, const Transform& transform, con
|
||||
{
|
||||
if (text.Length() == 0 || size < 4)
|
||||
return;
|
||||
PROFILE_MEM(EngineDebug);
|
||||
Array<DebugText3D>* list = duration > 0 ? &Context->DebugDrawDefault.DefaultText3D : &Context->DebugDrawDefault.OneFrameText3D;
|
||||
auto& t = list->AddOne();
|
||||
t.Text.Resize(text.Length() + 1);
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace
|
||||
elements.Get()[j].Slot = (byte)slot;
|
||||
}
|
||||
}
|
||||
GPUVertexLayout* result = anyValid ? GPUVertexLayout::Get(elements) : nullptr;
|
||||
GPUVertexLayout* result = anyValid ? GPUVertexLayout::Get(elements, true) : nullptr;
|
||||
VertexBufferCache.Add(key, result);
|
||||
return result;
|
||||
}
|
||||
@@ -97,6 +97,7 @@ GPUVertexLayout::GPUVertexLayout()
|
||||
void GPUVertexLayout::SetElements(const Elements& elements, bool explicitOffsets)
|
||||
{
|
||||
uint32 offsets[GPU_MAX_VB_BINDED + 1] = {};
|
||||
uint32 maxOffset[GPU_MAX_VB_BINDED + 1] = {};
|
||||
_elements = elements;
|
||||
for (int32 i = 0; i < _elements.Count(); i++)
|
||||
{
|
||||
@@ -108,9 +109,10 @@ void GPUVertexLayout::SetElements(const Elements& elements, bool explicitOffsets
|
||||
else
|
||||
e.Offset = (byte)offset;
|
||||
offset += PixelFormatExtensions::SizeInBytes(e.Format);
|
||||
maxOffset[e.Slot] = Math::Max(maxOffset[e.Slot], offset);
|
||||
}
|
||||
_stride = 0;
|
||||
for (uint32 offset : offsets)
|
||||
for (uint32 offset : maxOffset)
|
||||
_stride += offset;
|
||||
}
|
||||
|
||||
@@ -139,7 +141,7 @@ VertexElement GPUVertexLayout::FindElement(VertexElement::Types type) const
|
||||
GPUVertexLayout* GPUVertexLayout::Get(const Elements& elements, bool explicitOffsets)
|
||||
{
|
||||
// Hash input layout
|
||||
uint32 hash = 0;
|
||||
uint32 hash = explicitOffsets ? 131 : 0;
|
||||
for (const VertexElement& element : elements)
|
||||
{
|
||||
CombineHash(hash, GetHash(element));
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "Engine/Graphics/Shaders/GPUShaderProgram.h"
|
||||
#include "Engine/Core/Types/DataContainer.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "../IncludeDirectXHeaders.h"
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
@@ -3,16 +3,9 @@
|
||||
#if GRAPHICS_API_DIRECTX12
|
||||
|
||||
#include "Engine/Graphics/Config.h"
|
||||
#include "Engine/Platform/Platform.h"
|
||||
#include "../IncludeDirectXHeaders.h"
|
||||
#if USE_PIX && GPU_ALLOW_PROFILE_EVENTS
|
||||
// Include these header files before pix3
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#define NOGDI
|
||||
#define NODRAWTEXT
|
||||
//#define NOCTLMGR
|
||||
#define NOFLATSBAPIS
|
||||
#include <Windows.h>
|
||||
#include <d3d12.h>
|
||||
#include <ThirdParty/WinPixEventRuntime/pix3.h>
|
||||
#endif
|
||||
#include "GPUContextDX12.h"
|
||||
|
||||
@@ -25,6 +25,7 @@ NavMesh::NavMesh(const SpawnParams& params)
|
||||
void NavMesh::SaveNavMesh()
|
||||
{
|
||||
#if COMPILE_WITH_ASSETS_IMPORTER
|
||||
PROFILE_MEM(NavigationMesh);
|
||||
|
||||
// Skip if scene is missing
|
||||
const auto scene = GetScene();
|
||||
@@ -111,7 +112,7 @@ void NavMesh::OnAssetLoaded(Asset* asset, void* caller)
|
||||
if (Data.Tiles.HasItems())
|
||||
return;
|
||||
ScopeLock lock(DataAsset->Locker);
|
||||
PROFILE_MEM(Navigation);
|
||||
PROFILE_MEM(NavigationMesh);
|
||||
|
||||
// Remove added tiles
|
||||
if (_navMeshActive)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#if USE_EDITOR
|
||||
#include "Editor/Editor.h"
|
||||
#include "Editor/Managed/ManagedEditor.h"
|
||||
#include "NavMeshBuilder.h"
|
||||
#include "Navigation.h"
|
||||
#endif
|
||||
|
||||
NavMeshBoundsVolume::NavMeshBoundsVolume(const SpawnParams& params)
|
||||
@@ -55,9 +55,30 @@ void NavMeshBoundsVolume::OnBoundsChanged(const BoundingBox& prevBounds)
|
||||
// Auto-rebuild modified navmesh area
|
||||
if (IsDuringPlay() && IsActiveInHierarchy() && !Editor::IsPlayMode && Editor::Managed->CanAutoBuildNavMesh())
|
||||
{
|
||||
BoundingBox dirtyBounds;
|
||||
BoundingBox::Merge(prevBounds, _box, dirtyBounds);
|
||||
NavMeshBuilder::Build(GetScene(), dirtyBounds, ManagedEditor::ManagedEditorOptions.AutoRebuildNavMeshTimeoutMs);
|
||||
if (_box.Intersects(prevBounds))
|
||||
{
|
||||
// Bounds were moved a bit so merge into a single request (for performance reasons)
|
||||
BoundingBox dirtyBounds;
|
||||
BoundingBox::Merge(prevBounds, _box, dirtyBounds);
|
||||
Navigation::BuildNavMesh(dirtyBounds, ManagedEditor::ManagedEditorOptions.AutoRebuildNavMeshTimeoutMs);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dirty each bounds in separate
|
||||
Navigation::BuildNavMesh(prevBounds, ManagedEditor::ManagedEditorOptions.AutoRebuildNavMeshTimeoutMs);
|
||||
Navigation::BuildNavMesh(_box, ManagedEditor::ManagedEditorOptions.AutoRebuildNavMeshTimeoutMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NavMeshBoundsVolume::OnActiveInTreeChanged()
|
||||
{
|
||||
BoxVolume::OnActiveInTreeChanged();
|
||||
|
||||
// Auto-rebuild
|
||||
if (IsDuringPlay() && !Editor::IsPlayMode && Editor::Managed->CanAutoBuildNavMesh())
|
||||
{
|
||||
Navigation::BuildNavMesh(_box, ManagedEditor::ManagedEditorOptions.AutoRebuildNavMeshTimeoutMs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ protected:
|
||||
void OnDisable() override;
|
||||
#if USE_EDITOR
|
||||
void OnBoundsChanged(const BoundingBox& prevBounds) override;
|
||||
void OnActiveInTreeChanged() override;
|
||||
Color GetWiresColor() override;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#if COMPILE_WITH_NAV_MESH_BUILDER
|
||||
|
||||
#include "NavMeshBuilder.h"
|
||||
#include "Navigation.h"
|
||||
#include "NavMesh.h"
|
||||
#include "NavigationSettings.h"
|
||||
#include "NavMeshBoundsVolume.h"
|
||||
@@ -706,6 +707,7 @@ struct BuildRequest
|
||||
ScriptingObjectReference<Scene> Scene;
|
||||
DateTime Time;
|
||||
BoundingBox DirtyBounds;
|
||||
bool SpecificScene;
|
||||
};
|
||||
|
||||
CriticalSection NavBuildQueueLocker;
|
||||
@@ -713,6 +715,7 @@ Array<BuildRequest> NavBuildQueue;
|
||||
|
||||
CriticalSection NavBuildTasksLocker;
|
||||
int32 NavBuildTasksMaxCount = 0;
|
||||
bool NavBuildCheckMissingNavMeshes = false;
|
||||
Array<class NavMeshTileBuildTask*> NavBuildTasks;
|
||||
|
||||
class NavMeshTileBuildTask : public ThreadPoolTask
|
||||
@@ -733,7 +736,7 @@ public:
|
||||
bool Run() override
|
||||
{
|
||||
PROFILE_CPU_NAMED("BuildNavMeshTile");
|
||||
PROFILE_MEM(Navigation);
|
||||
PROFILE_MEM(NavigationBuilding);
|
||||
const auto navMesh = NavMesh.Get();
|
||||
if (!navMesh)
|
||||
return false;
|
||||
@@ -776,13 +779,13 @@ void CancelNavMeshTileBuildTasks(NavMeshRuntime* runtime)
|
||||
NavBuildTasksLocker.Unlock();
|
||||
}
|
||||
|
||||
void CancelNavMeshTileBuildTasks(NavMeshRuntime* runtime, int32 x, int32 y)
|
||||
void CancelNavMeshTileBuildTasks(NavMeshRuntime* runtime, int32 x, int32 y, NavMesh* navMesh)
|
||||
{
|
||||
NavBuildTasksLocker.Lock();
|
||||
for (int32 i = 0; i < NavBuildTasks.Count(); i++)
|
||||
{
|
||||
auto task = NavBuildTasks[i];
|
||||
if (task->Runtime == runtime && task->X == x && task->Y == y)
|
||||
if (task->Runtime == runtime && task->X == x && task->Y == y && task->NavMesh == navMesh)
|
||||
{
|
||||
NavBuildTasksLocker.Unlock();
|
||||
|
||||
@@ -838,7 +841,7 @@ void NavMeshBuilder::Init()
|
||||
Level::SceneUnloading.Bind<OnSceneUnloading>();
|
||||
}
|
||||
|
||||
bool NavMeshBuilder::IsBuildingNavMesh()
|
||||
bool Navigation::IsBuildingNavMesh()
|
||||
{
|
||||
NavBuildTasksLocker.Lock();
|
||||
const bool hasAnyTask = NavBuildTasks.HasItems();
|
||||
@@ -847,7 +850,7 @@ bool NavMeshBuilder::IsBuildingNavMesh()
|
||||
return hasAnyTask;
|
||||
}
|
||||
|
||||
float NavMeshBuilder::GetNavMeshBuildingProgress()
|
||||
float Navigation::GetNavMeshBuildingProgress()
|
||||
{
|
||||
NavBuildTasksLocker.Lock();
|
||||
float result = 1.0f;
|
||||
@@ -907,15 +910,13 @@ void BuildDirtyBounds(Scene* scene, NavMesh* navMesh, const BoundingBox& dirtyBo
|
||||
// Align dirty bounds to tile size
|
||||
BoundingBox dirtyBoundsNavMesh;
|
||||
BoundingBox::Transform(dirtyBounds, worldToNavMesh, dirtyBoundsNavMesh);
|
||||
BoundingBox dirtyBoundsAligned;
|
||||
dirtyBoundsAligned.Minimum = Float3::Floor(dirtyBoundsNavMesh.Minimum / tileSize) * tileSize;
|
||||
dirtyBoundsAligned.Maximum = Float3::Ceil(dirtyBoundsNavMesh.Maximum / tileSize) * tileSize;
|
||||
dirtyBoundsNavMesh.Minimum = Float3::Floor(dirtyBoundsNavMesh.Minimum / tileSize) * tileSize;
|
||||
dirtyBoundsNavMesh.Maximum = Float3::Ceil(dirtyBoundsNavMesh.Maximum / tileSize) * tileSize;
|
||||
|
||||
// Calculate tiles range for the given navigation dirty bounds (aligned to tiles size)
|
||||
const Int3 tilesMin(dirtyBoundsAligned.Minimum / tileSize);
|
||||
const Int3 tilesMax(dirtyBoundsAligned.Maximum / tileSize);
|
||||
const int32 tilesX = tilesMax.X - tilesMin.X;
|
||||
const int32 tilesY = tilesMax.Z - tilesMin.Z;
|
||||
const Int3 tilesMin(dirtyBoundsNavMesh.Minimum / tileSize);
|
||||
const Int3 tilesMax(dirtyBoundsNavMesh.Maximum / tileSize);
|
||||
const int32 tilesXZ = (tilesMax.X - tilesMin.X) * (tilesMax.Z - tilesMin.Z);
|
||||
|
||||
{
|
||||
PROFILE_CPU_NAMED("Prepare");
|
||||
@@ -932,18 +933,18 @@ void BuildDirtyBounds(Scene* scene, NavMesh* navMesh, const BoundingBox& dirtyBo
|
||||
// Remove all tiles from navmesh runtime
|
||||
runtime->RemoveTiles(navMesh);
|
||||
runtime->SetTileSize(tileSize);
|
||||
runtime->EnsureCapacity(tilesX * tilesY);
|
||||
runtime->EnsureCapacity(tilesXZ);
|
||||
|
||||
// Remove all tiles from navmesh data
|
||||
navMesh->Data.TileSize = tileSize;
|
||||
navMesh->Data.Tiles.Clear();
|
||||
navMesh->Data.Tiles.EnsureCapacity(tilesX * tilesX);
|
||||
navMesh->Data.Tiles.EnsureCapacity(tilesXZ);
|
||||
navMesh->IsDataDirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ensure to have enough memory for tiles
|
||||
runtime->EnsureCapacity(tilesX * tilesY);
|
||||
runtime->EnsureCapacity(tilesXZ);
|
||||
}
|
||||
|
||||
runtime->Locker.Unlock();
|
||||
@@ -959,11 +960,10 @@ void BuildDirtyBounds(Scene* scene, NavMesh* navMesh, const BoundingBox& dirtyBo
|
||||
|
||||
// Cache navmesh volumes
|
||||
Array<BoundingBox, InlinedAllocation<8>> volumes;
|
||||
for (int32 i = 0; i < scene->Navigation.Volumes.Count(); i++)
|
||||
for (const NavMeshBoundsVolume* volume : scene->Navigation.Volumes)
|
||||
{
|
||||
const auto volume = scene->Navigation.Volumes.Get()[i];
|
||||
if (!volume->AgentsMask.IsNavMeshSupported(navMesh->Properties) ||
|
||||
!volume->GetBox().Intersects(dirtyBoundsAligned))
|
||||
!volume->GetBox().Intersects(dirtyBoundsNavMesh))
|
||||
continue;
|
||||
auto& bounds = volumes.AddOne();
|
||||
BoundingBox::Transform(volume->GetBox(), worldToNavMesh, bounds);
|
||||
@@ -1026,7 +1026,7 @@ void BuildDirtyBounds(Scene* scene, NavMesh* navMesh, const BoundingBox& dirtyBo
|
||||
for (const auto& tile : unusedTiles)
|
||||
{
|
||||
// Wait for any async tasks that are producing this tile
|
||||
CancelNavMeshTileBuildTasks(runtime, tile.X, tile.Y);
|
||||
CancelNavMeshTileBuildTasks(runtime, tile.X, tile.Y, navMesh);
|
||||
}
|
||||
runtime->Locker.Lock();
|
||||
for (const auto& tile : unusedTiles)
|
||||
@@ -1095,6 +1095,7 @@ void BuildDirtyBounds(Scene* scene, const BoundingBox& dirtyBounds, bool rebuild
|
||||
else if (settings->AutoAddMissingNavMeshes)
|
||||
{
|
||||
// Spawn missing navmesh
|
||||
PROFILE_MEM(Navigation);
|
||||
navMesh = New<NavMesh>();
|
||||
navMesh->SetStaticFlags(StaticFlags::FullyStatic);
|
||||
navMesh->SetName(TEXT("NavMesh.") + navMeshProperties.Name);
|
||||
@@ -1108,39 +1109,6 @@ void BuildDirtyBounds(Scene* scene, const BoundingBox& dirtyBounds, bool rebuild
|
||||
{
|
||||
BuildDirtyBounds(scene, navMesh, dirtyBounds, rebuild);
|
||||
}
|
||||
|
||||
// Remove unused navmeshes
|
||||
if (settings->AutoRemoveMissingNavMeshes)
|
||||
{
|
||||
for (NavMesh* navMesh : scene->Navigation.Meshes)
|
||||
{
|
||||
// Skip used navmeshes
|
||||
if (navMesh->Data.Tiles.HasItems())
|
||||
continue;
|
||||
|
||||
// Skip navmeshes during async building
|
||||
int32 usageCount = 0;
|
||||
NavBuildTasksLocker.Lock();
|
||||
for (int32 i = 0; i < NavBuildTasks.Count(); i++)
|
||||
{
|
||||
if (NavBuildTasks.Get()[i]->NavMesh == navMesh)
|
||||
usageCount++;
|
||||
}
|
||||
NavBuildTasksLocker.Unlock();
|
||||
if (usageCount != 0)
|
||||
continue;
|
||||
|
||||
navMesh->DeleteObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BuildWholeScene(Scene* scene)
|
||||
{
|
||||
// Compute total navigation area bounds
|
||||
const BoundingBox worldBounds = scene->Navigation.GetNavigationBounds();
|
||||
|
||||
BuildDirtyBounds(scene, worldBounds, true);
|
||||
}
|
||||
|
||||
void ClearNavigation(Scene* scene)
|
||||
@@ -1154,22 +1122,58 @@ void ClearNavigation(Scene* scene)
|
||||
}
|
||||
}
|
||||
|
||||
void BuildNavigation(BuildRequest& request)
|
||||
{
|
||||
// If scene is not specified then build all loaded scenes
|
||||
if (!request.Scene)
|
||||
{
|
||||
for (Scene* scene : Level::Scenes)
|
||||
{
|
||||
request.Scene = scene;
|
||||
BuildNavigation(request);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Early out if scene is not using navigation
|
||||
if (request.Scene->Navigation.Volumes.IsEmpty())
|
||||
{
|
||||
ClearNavigation(request.Scene);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if similar request is already in a queue
|
||||
for (auto& e : NavBuildQueue)
|
||||
{
|
||||
if (e.Scene == request.Scene && (e.DirtyBounds == request.DirtyBounds || request.DirtyBounds == BoundingBox::Empty))
|
||||
{
|
||||
e = request;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Enqueue request
|
||||
NavBuildQueue.Add(request);
|
||||
}
|
||||
|
||||
void NavMeshBuilder::Update()
|
||||
{
|
||||
PROFILE_MEM(Navigation);
|
||||
PROFILE_MEM(NavigationBuilding);
|
||||
ScopeLock lock(NavBuildQueueLocker);
|
||||
|
||||
// Process nav mesh building requests and kick the tasks
|
||||
const auto now = DateTime::NowUTC();
|
||||
bool didRebuild = false;
|
||||
for (int32 i = 0; NavBuildQueue.HasItems() && i < NavBuildQueue.Count(); i++)
|
||||
{
|
||||
auto req = NavBuildQueue.Get()[i];
|
||||
if (now - req.Time >= 0)
|
||||
{
|
||||
NavBuildQueue.RemoveAt(i--);
|
||||
const auto scene = req.Scene.Get();
|
||||
Scene* scene = req.Scene.Get();
|
||||
if (!scene)
|
||||
continue;
|
||||
bool rebuild = req.DirtyBounds == BoundingBox::Empty;
|
||||
|
||||
// Early out if scene has no bounds volumes to define nav mesh area
|
||||
if (scene->Navigation.Volumes.IsEmpty())
|
||||
@@ -1179,80 +1183,69 @@ void NavMeshBuilder::Update()
|
||||
}
|
||||
|
||||
// Check if build a custom dirty bounds or whole scene
|
||||
if (req.DirtyBounds == BoundingBox::Empty)
|
||||
{
|
||||
BuildWholeScene(scene);
|
||||
}
|
||||
if (rebuild)
|
||||
req.DirtyBounds = scene->Navigation.GetNavigationBounds(); // Compute total navigation area bounds
|
||||
if (didRebuild)
|
||||
rebuild = false; // When rebuilding navmesh for multiple scenes, rebuild only the first one (other scenes will use additive update)
|
||||
else
|
||||
didRebuild = true;
|
||||
BuildDirtyBounds(scene, req.DirtyBounds, rebuild);
|
||||
NavBuildCheckMissingNavMeshes = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove unused navmeshes (when all active tasks are done)
|
||||
// TODO: ignore AutoRemoveMissingNavMeshes in game and make it editor-only?
|
||||
if (NavBuildCheckMissingNavMeshes && NavBuildTasksMaxCount == 0 && NavigationSettings::Get()->AutoRemoveMissingNavMeshes)
|
||||
{
|
||||
NavBuildCheckMissingNavMeshes = false;
|
||||
NavBuildTasksLocker.Lock();
|
||||
int32 taskCount = NavBuildTasks.Count();
|
||||
NavBuildTasksLocker.Unlock();
|
||||
if (taskCount == 0)
|
||||
{
|
||||
for (Scene* scene : Level::Scenes)
|
||||
{
|
||||
BuildDirtyBounds(scene, req.DirtyBounds, false);
|
||||
for (NavMesh* navMesh : scene->Navigation.Meshes)
|
||||
{
|
||||
if (!navMesh->Data.Tiles.HasItems())
|
||||
{
|
||||
navMesh->DeleteObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NavMeshBuilder::Build(Scene* scene, float timeoutMs)
|
||||
void Navigation::BuildNavMesh(Scene* scene, float timeoutMs)
|
||||
{
|
||||
if (!scene)
|
||||
{
|
||||
LOG(Warning, "Could not generate navmesh without scene.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Early out if scene is not using navigation
|
||||
if (scene->Navigation.Volumes.IsEmpty())
|
||||
{
|
||||
ClearNavigation(scene);
|
||||
return;
|
||||
}
|
||||
|
||||
PROFILE_CPU_NAMED("NavMeshBuilder");
|
||||
PROFILE_MEM(Navigation);
|
||||
PROFILE_CPU();
|
||||
PROFILE_MEM(NavigationBuilding);
|
||||
ScopeLock lock(NavBuildQueueLocker);
|
||||
|
||||
BuildRequest req;
|
||||
req.Scene = scene;
|
||||
req.Time = DateTime::NowUTC() + TimeSpan::FromMilliseconds(timeoutMs);
|
||||
req.DirtyBounds = BoundingBox::Empty;
|
||||
|
||||
for (int32 i = 0; i < NavBuildQueue.Count(); i++)
|
||||
{
|
||||
auto& e = NavBuildQueue.Get()[i];
|
||||
if (e.Scene == scene && e.DirtyBounds == req.DirtyBounds)
|
||||
{
|
||||
e = req;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NavBuildQueue.Add(req);
|
||||
req.SpecificScene = scene != nullptr;
|
||||
BuildNavigation(req);
|
||||
}
|
||||
|
||||
void NavMeshBuilder::Build(Scene* scene, const BoundingBox& dirtyBounds, float timeoutMs)
|
||||
void Navigation::BuildNavMesh(const BoundingBox& dirtyBounds, Scene* scene, float timeoutMs)
|
||||
{
|
||||
if (!scene)
|
||||
{
|
||||
LOG(Warning, "Could not generate navmesh without scene.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Early out if scene is not using navigation
|
||||
if (scene->Navigation.Volumes.IsEmpty())
|
||||
{
|
||||
ClearNavigation(scene);
|
||||
return;
|
||||
}
|
||||
|
||||
PROFILE_CPU_NAMED("NavMeshBuilder");
|
||||
PROFILE_MEM(Navigation);
|
||||
if (dirtyBounds.GetVolume() <= ZeroTolerance)
|
||||
return; // Skip updating empty bounds
|
||||
PROFILE_CPU();
|
||||
PROFILE_MEM(NavigationBuilding);
|
||||
ScopeLock lock(NavBuildQueueLocker);
|
||||
|
||||
BuildRequest req;
|
||||
req.Scene = scene;
|
||||
req.Time = DateTime::NowUTC() + TimeSpan::FromMilliseconds(timeoutMs);
|
||||
req.DirtyBounds = dirtyBounds;
|
||||
|
||||
NavBuildQueue.Add(req);
|
||||
req.SpecificScene = scene != nullptr;
|
||||
BuildNavigation(req);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,11 +15,7 @@ class FLAXENGINE_API NavMeshBuilder
|
||||
{
|
||||
public:
|
||||
static void Init();
|
||||
static bool IsBuildingNavMesh();
|
||||
static float GetNavMeshBuildingProgress();
|
||||
static void Update();
|
||||
static void Build(Scene* scene, float timeoutMs);
|
||||
static void Build(Scene* scene, const BoundingBox& dirtyBounds, float timeoutMs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
#include "NavMesh.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Random.h"
|
||||
#if COMPILE_WITH_DEBUG_DRAW
|
||||
#include "Engine/Level/Scene/Scene.h"
|
||||
#endif
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Profiler/ProfilerMemory.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
@@ -326,7 +329,7 @@ void NavMeshRuntime::EnsureCapacity(int32 tilesToAddCount)
|
||||
if (newTilesCount <= capacity)
|
||||
return;
|
||||
PROFILE_CPU_NAMED("NavMeshRuntime.EnsureCapacity");
|
||||
PROFILE_MEM(Navigation);
|
||||
PROFILE_MEM(NavigationMesh);
|
||||
|
||||
// Navmesh tiles capacity growing rule
|
||||
int32 newCapacity = capacity ? capacity : 32;
|
||||
@@ -387,7 +390,7 @@ void NavMeshRuntime::AddTiles(NavMesh* navMesh)
|
||||
return;
|
||||
auto& data = navMesh->Data;
|
||||
PROFILE_CPU_NAMED("NavMeshRuntime.AddTiles");
|
||||
PROFILE_MEM(Navigation);
|
||||
PROFILE_MEM(NavigationMesh);
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
// Validate data (must match navmesh) or init navmesh to match the tiles options
|
||||
@@ -419,7 +422,7 @@ void NavMeshRuntime::AddTile(NavMesh* navMesh, NavMeshTileData& tileData)
|
||||
ASSERT(navMesh);
|
||||
auto& data = navMesh->Data;
|
||||
PROFILE_CPU_NAMED("NavMeshRuntime.AddTile");
|
||||
PROFILE_MEM(Navigation);
|
||||
PROFILE_MEM(NavigationMesh);
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
// Validate data (must match navmesh) or init navmesh to match the tiles options
|
||||
@@ -603,7 +606,21 @@ void NavMeshRuntime::DebugDraw()
|
||||
if (!tile->header)
|
||||
continue;
|
||||
|
||||
//DebugDraw::DrawWireBox(*(BoundingBox*)&tile->header->bmin[0], Color::CadetBlue);
|
||||
#if 0
|
||||
// Debug draw tile bounds and owner scene name
|
||||
BoundingBox tileBounds = *(BoundingBox*)&tile->header->bmin[0];
|
||||
DebugDraw::DrawWireBox(tileBounds, Color::CadetBlue);
|
||||
// TODO: build map from tile coords to tile data to avoid this loop
|
||||
for (const auto& e : _tiles)
|
||||
{
|
||||
if (e.X == tile->header->x && e.Y == tile->header->y && e.Layer == tile->header->layer)
|
||||
{
|
||||
if (e.NavMesh && e.NavMesh->GetScene())
|
||||
DebugDraw::DrawText(e.NavMesh->GetScene()->GetName(), tileBounds.Minimum + tileBounds.GetSize() * Float3(0.5f, 0.8f, 0.5f), Color::CadetBlue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < tile->header->polyCount; i++)
|
||||
{
|
||||
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
/// <param name="startPosition">The start position.</param>
|
||||
/// <param name="hitInfo">The result hit information. Valid only when query succeed.</param>
|
||||
/// <param name="maxDistance">The maximum distance to search for wall (search radius).</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool FindDistanceToWall(const Vector3& startPosition, NavMeshHit& hitInfo, float maxDistance = MAX_float) const;
|
||||
|
||||
/// <summary>
|
||||
@@ -187,7 +187,7 @@ public:
|
||||
/// <param name="startPosition">The start position.</param>
|
||||
/// <param name="endPosition">The end position.</param>
|
||||
/// <param name="hitInfo">The result hit information. Valid only when query succeed.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool RayCast(const Vector3& startPosition, const Vector3& endPosition, API_PARAM(Out) NavMeshHit& hitInfo) const;
|
||||
|
||||
public:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "NavModifierVolume.h"
|
||||
#include "NavigationSettings.h"
|
||||
#include "NavMeshBuilder.h"
|
||||
#include "Navigation.h"
|
||||
#include "Engine/Level/Scene/Scene.h"
|
||||
#include "Engine/Serialization/Serialization.h"
|
||||
#if USE_EDITOR
|
||||
@@ -83,7 +83,7 @@ void NavModifierVolume::OnBoundsChanged(const BoundingBox& prevBounds)
|
||||
#else
|
||||
const float timeoutMs = 0.0f;
|
||||
#endif
|
||||
NavMeshBuilder::Build(GetScene(), dirtyBounds, timeoutMs);
|
||||
Navigation::BuildNavMesh(dirtyBounds, GetScene(), timeoutMs);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ NavigationService NavigationServiceInstance;
|
||||
|
||||
void* dtAllocDefault(size_t size, dtAllocHint)
|
||||
{
|
||||
PROFILE_MEM(Navigation);
|
||||
PROFILE_MEM(NavigationMesh);
|
||||
return Allocator::Allocate(size);
|
||||
}
|
||||
|
||||
@@ -382,30 +382,6 @@ bool Navigation::RayCast(const Vector3& startPosition, const Vector3& endPositio
|
||||
return NavMeshes.First()->RayCast(startPosition, endPosition, hitInfo);
|
||||
}
|
||||
|
||||
#if COMPILE_WITH_NAV_MESH_BUILDER
|
||||
|
||||
bool Navigation::IsBuildingNavMesh()
|
||||
{
|
||||
return NavMeshBuilder::IsBuildingNavMesh();
|
||||
}
|
||||
|
||||
float Navigation::GetNavMeshBuildingProgress()
|
||||
{
|
||||
return NavMeshBuilder::GetNavMeshBuildingProgress();
|
||||
}
|
||||
|
||||
void Navigation::BuildNavMesh(Scene* scene, float timeoutMs)
|
||||
{
|
||||
NavMeshBuilder::Build(scene, timeoutMs);
|
||||
}
|
||||
|
||||
void Navigation::BuildNavMesh(Scene* scene, const BoundingBox& dirtyBounds, float timeoutMs)
|
||||
{
|
||||
NavMeshBuilder::Build(scene, dirtyBounds, timeoutMs);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if COMPILE_WITH_DEBUG_DRAW
|
||||
|
||||
void Navigation::DrawNavMesh()
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
/// <param name="startPosition">The start position.</param>
|
||||
/// <param name="hitInfo">The result hit information. Valid only when query succeed.</param>
|
||||
/// <param name="maxDistance">The maximum distance to search for wall (search radius).</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool FindDistanceToWall(const Vector3& startPosition, API_PARAM(Out) NavMeshHit& hitInfo, float maxDistance = MAX_float);
|
||||
|
||||
/// <summary>
|
||||
@@ -81,12 +81,10 @@ public:
|
||||
/// <param name="startPosition">The start position.</param>
|
||||
/// <param name="endPosition">The end position.</param>
|
||||
/// <param name="hitInfo">The result hit information. Valid only when query succeed.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool RayCast(const Vector3& startPosition, const Vector3& endPosition, API_PARAM(Out) NavMeshHit& hitInfo);
|
||||
|
||||
public:
|
||||
#if COMPILE_WITH_NAV_MESH_BUILDER
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if navigation system is during navmesh building (any request is valid or async task active).
|
||||
/// </summary>
|
||||
@@ -100,32 +98,49 @@ public:
|
||||
/// <summary>
|
||||
/// Builds the Nav Mesh for the given scene (discards all its tiles).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Requests are enqueued till the next game scripts update. Actual navmesh building in done via Thread Pool tasks in a background to prevent game thread stalls.
|
||||
/// </remarks>
|
||||
/// <param name="scene">The scene.</param>
|
||||
/// <remarks>Requests are enqueued till the next game scripts update. Actual navmesh building in done via Thread Pool tasks in a background to prevent game thread stalls.</remarks>
|
||||
/// <param name="scene">The scene. Pass null to build navmesh for all loaded scenes.</param>
|
||||
/// <param name="timeoutMs">The timeout to wait before building Nav Mesh (in milliseconds).</param>
|
||||
API_FUNCTION() static void BuildNavMesh(Scene* scene, float timeoutMs = 50);
|
||||
API_FUNCTION() static void BuildNavMesh(Scene* scene = nullptr, float timeoutMs = 50);
|
||||
|
||||
/// <summary>
|
||||
/// Builds the Nav Mesh for the given scene (builds only the tiles overlapping the given bounding box).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Requests are enqueued till the next game scripts update. Actual navmesh building in done via Thread Pool tasks in a background to prevent game thread stalls.
|
||||
/// </remarks>
|
||||
/// <remarks>Requests are enqueued till the next game scripts update. Actual navmesh building in done via Thread Pool tasks in a background to prevent game thread stalls.</remarks>
|
||||
/// <param name="dirtyBounds">The bounds in world-space to build overlapping tiles.</param>
|
||||
/// <param name="scene">The scene. Pass null to build navmesh for all loaded scenes that intersect with a given bounds.</param>
|
||||
/// <param name="timeoutMs">The timeout to wait before building Nav Mesh (in milliseconds).</param>
|
||||
API_FUNCTION() static void BuildNavMesh(const BoundingBox& dirtyBounds, Scene* scene = nullptr, float timeoutMs = 50);
|
||||
|
||||
/// <summary>
|
||||
/// Builds the Nav Mesh for all the loaded scenes (builds only the tiles overlapping the given bounding box).
|
||||
/// </summary>
|
||||
/// <remarks>Requests are enqueued till the next game scripts update. Actual navmesh building in done via Thread Pool tasks in a background to prevent game thread stalls.</remarks>
|
||||
/// <param name="dirtyBounds">The bounds in world-space to build overlapping tiles.</param>
|
||||
/// <param name="timeoutMs">The timeout to wait before building Nav Mesh (in milliseconds).</param>
|
||||
API_FUNCTION() static void BuildNavMesh(const BoundingBox& dirtyBounds, float timeoutMs = 50)
|
||||
{
|
||||
BuildNavMesh(dirtyBounds, nullptr, timeoutMs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds the Nav Mesh for the given scene (builds only the tiles overlapping the given bounding box).
|
||||
/// [Deprecated in v1.12]
|
||||
/// </summary>
|
||||
/// <remarks>Requests are enqueued till the next game scripts update. Actual navmesh building in done via Thread Pool tasks in a background to prevent game thread stalls.</remarks>
|
||||
/// <param name="scene">The scene.</param>
|
||||
/// <param name="dirtyBounds">The bounds in world-space to build overlapping tiles.</param>
|
||||
/// <param name="timeoutMs">The timeout to wait before building Nav Mesh (in milliseconds).</param>
|
||||
API_FUNCTION() static void BuildNavMesh(Scene* scene, const BoundingBox& dirtyBounds, float timeoutMs = 50);
|
||||
|
||||
API_FUNCTION() DEPRECATED("Use BuildNavMesh with reordered arguments instead") static void BuildNavMesh(Scene* scene, const BoundingBox& dirtyBounds, float timeoutMs = 50)
|
||||
{
|
||||
BuildNavMesh(dirtyBounds, scene, timeoutMs);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if COMPILE_WITH_DEBUG_DRAW
|
||||
|
||||
/// <summary>
|
||||
/// Draws the navigation for all the scenes (uses DebugDraw interface).
|
||||
/// </summary>
|
||||
static void DrawNavMesh();
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -2784,6 +2784,69 @@ float PhysicsBackend::ComputeShapeSqrDistanceToPoint(void* shape, const Vector3&
|
||||
{
|
||||
auto shapePhysX = (PxShape*)shape;
|
||||
const PxTransform trans(C2P(position), C2P(orientation));
|
||||
|
||||
// Special case for heightfield collider (not implemented in PhysX)
|
||||
if (shapePhysX->getGeometryType() == PxGeometryType::eHEIGHTFIELD)
|
||||
{
|
||||
// Do a bunch of raycasts in all directions to find the closest point on the heightfield
|
||||
PxVec3 origin = C2P(point);
|
||||
Array<PxVec3> unitDirections;
|
||||
constexpr int32 resolution = 32;
|
||||
unitDirections.EnsureCapacity((resolution + 1) * (resolution + 1));
|
||||
for (int32 i = 0; i <= resolution; i++)
|
||||
{
|
||||
float phi = PI * (float)i / resolution;
|
||||
float sinPhi = Math::Sin(phi);
|
||||
float cosPhi = Math::Cos(phi);
|
||||
for (int32 j = 0; j <= resolution; j++)
|
||||
{
|
||||
float theta = 2.0f * PI * (float)j / resolution;
|
||||
float cosTheta = Math::Cos(theta);
|
||||
float sinTheta = Math::Sin(theta);
|
||||
|
||||
PxVec3 v;
|
||||
v.x = cosTheta * sinPhi;
|
||||
v.y = cosPhi;
|
||||
v.z = sinTheta * sinPhi;
|
||||
|
||||
// All generated vectors are unit vectors (length 1)
|
||||
unitDirections.Add(v);
|
||||
}
|
||||
}
|
||||
|
||||
PxReal maxDistance = PX_MAX_REAL; // Search indefinitely
|
||||
PxQueryFilterData filterData;
|
||||
filterData.data.word0 = (PxU32)shapePhysX->getSimulationFilterData().word0;
|
||||
PxHitFlags hitFlags = PxHitFlag::ePOSITION | PxHitFlag::eMESH_BOTH_SIDES; // Both sides added for if it is underneath the height field
|
||||
PxRaycastBuffer buffer;
|
||||
auto scene = shapePhysX->getActor()->getScene();
|
||||
|
||||
PxReal closestDistance = maxDistance;
|
||||
PxVec3 tempClosestPoint;
|
||||
for (PxVec3& unitDir : unitDirections)
|
||||
{
|
||||
bool hitResult = scene->raycast(origin, unitDir, maxDistance, buffer, hitFlags, filterData);
|
||||
if (hitResult)
|
||||
{
|
||||
auto& hit = buffer.getAnyHit(0);
|
||||
if (hit.distance < closestDistance && hit.distance > 0.0f)
|
||||
{
|
||||
tempClosestPoint = hit.position;
|
||||
closestDistance = hit.distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (closestDistance < maxDistance)
|
||||
{
|
||||
*closestPoint = P2C(tempClosestPoint);
|
||||
return closestDistance * closestDistance; // Result is squared distance
|
||||
}
|
||||
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
// Default point distance for other collider queries
|
||||
#if USE_LARGE_WORLDS
|
||||
PxVec3 closestPointPx;
|
||||
float result = PxGeometryQuery::pointDistance(C2P(point), shapePhysX->getGeometry(), trans, &closestPointPx);
|
||||
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
/// <param name="end">The end position of the line.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool LineCast(const Vector3& start, const Vector3& end, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -113,18 +113,18 @@ public:
|
||||
/// <param name="hitInfo">The result hit information. Valid only when method returns true.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool LineCast(const Vector3& start, const Vector3& end, API_PARAM(Out) RayCastHit& hitInfo, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
// <summary>
|
||||
/// Performs a line between two points in the scene, returns all hitpoints infos.
|
||||
/// Performs a line between two points in the scene, returns all hit points info.
|
||||
/// </summary>
|
||||
/// <param name="start">The origin of the ray.</param>
|
||||
/// <param name="end">The end position of the line.</param>
|
||||
/// <param name="results">The result hits. Valid only when method returns true.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool LineCastAll(const Vector3& start, const Vector3& end, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -135,7 +135,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool RayCast(const Vector3& origin, const Vector3& direction, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -147,7 +147,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool RayCast(const Vector3& origin, const Vector3& direction, API_PARAM(Out) RayCastHit& hitInfo, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -159,7 +159,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool RayCastAll(const Vector3& origin, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -172,7 +172,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if box hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if box hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool BoxCast(const Vector3& center, const Vector3& halfExtents, const Vector3& direction, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -186,7 +186,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if box hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if box hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool BoxCast(const Vector3& center, const Vector3& halfExtents, const Vector3& direction, API_PARAM(Out) RayCastHit& hitInfo, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -200,7 +200,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if box hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if box hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool BoxCastAll(const Vector3& center, const Vector3& halfExtents, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -212,7 +212,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if sphere hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if sphere hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool SphereCast(const Vector3& center, float radius, const Vector3& direction, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -225,7 +225,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if sphere hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if sphere hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool SphereCast(const Vector3& center, float radius, const Vector3& direction, API_PARAM(Out) RayCastHit& hitInfo, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -238,7 +238,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if sphere hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if sphere hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool SphereCastAll(const Vector3& center, float radius, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -252,7 +252,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if capsule hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if capsule hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool CapsuleCast(const Vector3& center, float radius, float height, const Vector3& direction, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -267,7 +267,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if capsule hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if capsule hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool CapsuleCast(const Vector3& center, float radius, float height, const Vector3& direction, API_PARAM(Out) RayCastHit& hitInfo, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -282,7 +282,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if capsule hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if capsule hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool CapsuleCastAll(const Vector3& center, float radius, float height, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -296,7 +296,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if convex mesh hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if convex mesh hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool ConvexCast(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, const Vector3& direction, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -311,7 +311,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if convex mesh hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if convex mesh hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool ConvexCast(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, const Vector3& direction, API_PARAM(Out) RayCastHit& hitInfo, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -326,7 +326,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if convex mesh hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if convex mesh hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() static bool ConvexCastAll(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -375,7 +375,7 @@ public:
|
||||
API_FUNCTION() static bool CheckConvex(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given box.
|
||||
/// Finds all colliders touching or inside the given box.
|
||||
/// </summary>
|
||||
/// <param name="center">The box center.</param>
|
||||
/// <param name="halfExtents">The half size of the box in each direction.</param>
|
||||
@@ -387,7 +387,7 @@ public:
|
||||
API_FUNCTION() static bool OverlapBox(const Vector3& center, const Vector3& halfExtents, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given sphere.
|
||||
/// Finds all colliders touching or inside the given sphere.
|
||||
/// </summary>
|
||||
/// <param name="center">The sphere center.</param>
|
||||
/// <param name="radius">The radius of the sphere.</param>
|
||||
@@ -398,7 +398,7 @@ public:
|
||||
API_FUNCTION() static bool OverlapSphere(const Vector3& center, float radius, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given capsule.
|
||||
/// Finds all colliders touching or inside the given capsule.
|
||||
/// </summary>
|
||||
/// <param name="center">The capsule center.</param>
|
||||
/// <param name="radius">The radius of the capsule.</param>
|
||||
@@ -411,7 +411,7 @@ public:
|
||||
API_FUNCTION() static bool OverlapCapsule(const Vector3& center, float radius, float height, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given convex mesh.
|
||||
/// Finds all colliders touching or inside the given convex mesh.
|
||||
/// </summary>
|
||||
/// <param name="center">The convex mesh center.</param>
|
||||
/// <param name="convexMesh">Collision data of the convex mesh.</param>
|
||||
@@ -424,7 +424,7 @@ public:
|
||||
API_FUNCTION() static bool OverlapConvex(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given box.
|
||||
/// Finds all colliders touching or inside the given box.
|
||||
/// </summary>
|
||||
/// <param name="center">The box center.</param>
|
||||
/// <param name="halfExtents">The half size of the box in each direction.</param>
|
||||
@@ -436,7 +436,7 @@ public:
|
||||
API_FUNCTION() static bool OverlapBox(const Vector3& center, const Vector3& halfExtents, API_PARAM(Out) Array<PhysicsColliderActor*, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given sphere.
|
||||
/// Finds all colliders touching or inside the given sphere.
|
||||
/// </summary>
|
||||
/// <param name="center">The sphere center.</param>
|
||||
/// <param name="radius">The radius of the sphere.</param>
|
||||
@@ -447,7 +447,7 @@ public:
|
||||
API_FUNCTION() static bool OverlapSphere(const Vector3& center, float radius, API_PARAM(Out) Array<PhysicsColliderActor*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given capsule.
|
||||
/// Finds all colliders touching or inside the given capsule.
|
||||
/// </summary>
|
||||
/// <param name="center">The capsule center.</param>
|
||||
/// <param name="radius">The radius of the capsule.</param>
|
||||
@@ -460,7 +460,7 @@ public:
|
||||
API_FUNCTION() static bool OverlapCapsule(const Vector3& center, float radius, float height, API_PARAM(Out) Array<PhysicsColliderActor*, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given convex mesh.
|
||||
/// Finds all colliders touching or inside the given convex mesh.
|
||||
/// </summary>
|
||||
/// <param name="center">The convex mesh center.</param>
|
||||
/// <param name="convexMesh">Collision data of the convex mesh.</param>
|
||||
|
||||
@@ -140,7 +140,7 @@ public:
|
||||
/// <param name="end">The end position of the line.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool LineCast(const Vector3& start, const Vector3& end, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -151,18 +151,18 @@ public:
|
||||
/// <param name="hitInfo">The result hit information. Valid only when method returns true.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool LineCast(const Vector3& start, const Vector3& end, API_PARAM(Out) RayCastHit& hitInfo, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
// <summary>
|
||||
/// Performs a line between two points in the scene, returns all hitpoints infos.
|
||||
/// Performs a line between two points in the scene, returns all hit points info.
|
||||
/// </summary>
|
||||
/// <param name="start">The origin of the ray.</param>
|
||||
/// <param name="end">The normalized direction of the ray.</param>
|
||||
/// <param name="results">The result hits. Valid only when method returns true.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool LineCastAll(const Vector3& start, const Vector3& end, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -173,7 +173,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool RayCast(const Vector3& origin, const Vector3& direction, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -185,7 +185,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool RayCast(const Vector3& origin, const Vector3& direction, API_PARAM(Out) RayCastHit& hitInfo, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -197,7 +197,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if ray hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if ray hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool RayCastAll(const Vector3& origin, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -210,7 +210,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if box hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if box hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool BoxCast(const Vector3& center, const Vector3& halfExtents, const Vector3& direction, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -224,7 +224,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if box hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if box hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool BoxCast(const Vector3& center, const Vector3& halfExtents, const Vector3& direction, API_PARAM(Out) RayCastHit& hitInfo, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -238,7 +238,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if box hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if box hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool BoxCastAll(const Vector3& center, const Vector3& halfExtents, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -250,7 +250,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if sphere hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if sphere hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool SphereCast(const Vector3& center, float radius, const Vector3& direction, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -263,7 +263,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if sphere hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if sphere hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool SphereCast(const Vector3& center, float radius, const Vector3& direction, API_PARAM(Out) RayCastHit& hitInfo, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -276,7 +276,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if sphere hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if sphere hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool SphereCastAll(const Vector3& center, float radius, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -290,7 +290,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if capsule hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if capsule hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool CapsuleCast(const Vector3& center, float radius, float height, const Vector3& direction, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -305,7 +305,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if capsule hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if capsule hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool CapsuleCast(const Vector3& center, float radius, float height, const Vector3& direction, API_PARAM(Out) RayCastHit& hitInfo, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -320,7 +320,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if capsule hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if capsule hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool CapsuleCastAll(const Vector3& center, float radius, float height, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -334,7 +334,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if convex mesh hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if convex mesh hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool ConvexCast(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, const Vector3& direction, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -349,7 +349,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if convex mesh hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if convex mesh hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool ConvexCast(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, const Vector3& direction, API_PARAM(Out) RayCastHit& hitInfo, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -364,7 +364,7 @@ public:
|
||||
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
|
||||
/// <param name="layerMask">The layer mask used to filter the results.</param>
|
||||
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
|
||||
/// <returns>True if convex mesh hits an matching object, otherwise false.</returns>
|
||||
/// <returns>True if convex mesh hits a matching object, otherwise false.</returns>
|
||||
API_FUNCTION() bool ConvexCastAll(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
@@ -413,7 +413,7 @@ public:
|
||||
API_FUNCTION() bool CheckConvex(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given box.
|
||||
/// Finds all colliders touching or inside the given box.
|
||||
/// </summary>
|
||||
/// <param name="center">The box center.</param>
|
||||
/// <param name="halfExtents">The half size of the box in each direction.</param>
|
||||
@@ -425,7 +425,7 @@ public:
|
||||
API_FUNCTION() bool OverlapBox(const Vector3& center, const Vector3& halfExtents, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given sphere.
|
||||
/// Finds all colliders touching or inside the given sphere.
|
||||
/// </summary>
|
||||
/// <param name="center">The sphere center.</param>
|
||||
/// <param name="radius">The radius of the sphere.</param>
|
||||
@@ -436,7 +436,7 @@ public:
|
||||
API_FUNCTION() bool OverlapSphere(const Vector3& center, float radius, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given capsule.
|
||||
/// Finds all colliders touching or inside the given capsule.
|
||||
/// </summary>
|
||||
/// <param name="center">The capsule center.</param>
|
||||
/// <param name="radius">The radius of the capsule.</param>
|
||||
@@ -449,7 +449,7 @@ public:
|
||||
API_FUNCTION() bool OverlapCapsule(const Vector3& center, float radius, float height, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given convex mesh.
|
||||
/// Finds all colliders touching or inside the given convex mesh.
|
||||
/// </summary>
|
||||
/// <param name="center">The convex mesh center.</param>
|
||||
/// <param name="convexMesh">Collision data of the convex mesh.</param>
|
||||
@@ -462,7 +462,7 @@ public:
|
||||
API_FUNCTION() bool OverlapConvex(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given box.
|
||||
/// Finds all colliders touching or inside the given box.
|
||||
/// </summary>
|
||||
/// <param name="center">The box center.</param>
|
||||
/// <param name="halfExtents">The half size of the box in each direction.</param>
|
||||
@@ -474,7 +474,7 @@ public:
|
||||
API_FUNCTION() bool OverlapBox(const Vector3& center, const Vector3& halfExtents, API_PARAM(Out) Array<PhysicsColliderActor*, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given sphere.
|
||||
/// Finds all colliders touching or inside the given sphere.
|
||||
/// </summary>
|
||||
/// <param name="center">The sphere center.</param>
|
||||
/// <param name="radius">The radius of the sphere.</param>
|
||||
@@ -485,7 +485,7 @@ public:
|
||||
API_FUNCTION() bool OverlapSphere(const Vector3& center, float radius, API_PARAM(Out) Array<PhysicsColliderActor*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given capsule.
|
||||
/// Finds all colliders touching or inside the given capsule.
|
||||
/// </summary>
|
||||
/// <param name="center">The capsule center.</param>
|
||||
/// <param name="radius">The radius of the capsule.</param>
|
||||
@@ -498,7 +498,7 @@ public:
|
||||
API_FUNCTION() bool OverlapCapsule(const Vector3& center, float radius, float height, API_PARAM(Out) Array<PhysicsColliderActor*, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all colliders touching or inside of the given convex mesh.
|
||||
/// Finds all colliders touching or inside the given convex mesh.
|
||||
/// </summary>
|
||||
/// <param name="center">The convex mesh center.</param>
|
||||
/// <param name="convexMesh">Collision data of the convex mesh.</param>
|
||||
|
||||
@@ -243,6 +243,7 @@ void InitProfilerMemory(const Char* cmdLine, int32 stage)
|
||||
#define INIT_PARENT(parent, child) GroupParents[(int32)ProfilerMemory::Groups::child] = (uint8)ProfilerMemory::Groups::parent
|
||||
INIT_PARENT(Engine, EngineThreading);
|
||||
INIT_PARENT(Engine, EngineDelegate);
|
||||
INIT_PARENT(Engine, EngineDebug);
|
||||
INIT_PARENT(Malloc, MallocArena);
|
||||
INIT_PARENT(Graphics, GraphicsTextures);
|
||||
INIT_PARENT(Graphics, GraphicsRenderTargets);
|
||||
@@ -260,6 +261,8 @@ void InitProfilerMemory(const Char* cmdLine, int32 stage)
|
||||
INIT_PARENT(Content, ContentFiles);
|
||||
INIT_PARENT(Level, LevelFoliage);
|
||||
INIT_PARENT(Level, LevelTerrain);
|
||||
INIT_PARENT(Navigation, NavigationMesh);
|
||||
INIT_PARENT(Navigation, NavigationBuilding);
|
||||
INIT_PARENT(Scripting, ScriptingVisual);
|
||||
INIT_PARENT(Scripting, ScriptingCSharp);
|
||||
INIT_PARENT(ScriptingCSharp, ScriptingCSharpGCCommitted);
|
||||
|
||||
@@ -44,6 +44,8 @@ public:
|
||||
EngineThreading,
|
||||
// Memory used by Delegate (engine events system to store all references).
|
||||
EngineDelegate,
|
||||
// Memory used by debug tools (eg. DebugDraw, DebugCommands or DebugLog).
|
||||
EngineDebug,
|
||||
|
||||
// Total graphics memory usage.
|
||||
Graphics,
|
||||
@@ -105,6 +107,10 @@ public:
|
||||
|
||||
// Total navigation system memory.
|
||||
Navigation,
|
||||
// Navigation mesh memory.
|
||||
NavigationMesh,
|
||||
// Navigation mesh builder memory.
|
||||
NavigationBuilding,
|
||||
|
||||
// Total networking system memory.
|
||||
Networking,
|
||||
|
||||
@@ -148,9 +148,8 @@ Task* Task::StartNew(Function<bool()>::Signature& action, Object* target)
|
||||
|
||||
void Task::Execute()
|
||||
{
|
||||
if (IsCanceled())
|
||||
if (!IsQueued())
|
||||
return;
|
||||
ASSERT(IsQueued());
|
||||
SetState(TaskState::Running);
|
||||
|
||||
// Perform an operation
|
||||
|
||||
@@ -449,8 +449,7 @@ namespace FlaxEngine.GUI
|
||||
/// <inheritdoc />
|
||||
public override bool RayCast(ref Float2 location, out Control hit)
|
||||
{
|
||||
var p = location / _scale;
|
||||
if (RayCastChildren(ref p, out hit))
|
||||
if (RayCastChildren(ref location, out hit))
|
||||
return true;
|
||||
return base.RayCast(ref location, out hit);
|
||||
}
|
||||
|
||||
@@ -143,6 +143,40 @@ namespace FlaxEngine.GUI
|
||||
context.Caret.X = 0;
|
||||
OnLineAdded(ref context, _text.Length - 1);
|
||||
}
|
||||
|
||||
// Organize lines vertically
|
||||
if (_textBlocks.Count != 0)
|
||||
{
|
||||
var lastBlock = _textBlocks[_textBlocks.Count - 1];
|
||||
|
||||
// Get style (global or leftover from style stack or the last lime)
|
||||
var verticalAlignments = _textStyle.Alignment;
|
||||
if (context.StyleStack.Count > 1)
|
||||
verticalAlignments = context.StyleStack.Peek().Alignment;
|
||||
else if ((lastBlock.Style.Alignment & TextBlockStyle.Alignments.VerticalMask) != TextBlockStyle.Alignments.Baseline)
|
||||
verticalAlignments = lastBlock.Style.Alignment;
|
||||
|
||||
var totalSize = lastBlock.Bounds.BottomRight;
|
||||
var sizeOffset = Size - totalSize;
|
||||
var textBlocks = CollectionsMarshal.AsSpan(_textBlocks);
|
||||
if ((verticalAlignments & TextBlockStyle.Alignments.Middle) == TextBlockStyle.Alignments.Middle)
|
||||
{
|
||||
sizeOffset.Y *= 0.5f;
|
||||
for (int i = 0; i < _textBlocks.Count; i++)
|
||||
{
|
||||
ref TextBlock textBlock = ref textBlocks[i];
|
||||
textBlock.Bounds.Location.Y += sizeOffset.Y;
|
||||
}
|
||||
}
|
||||
else if ((verticalAlignments & TextBlockStyle.Alignments.Bottom) == TextBlockStyle.Alignments.Bottom)
|
||||
{
|
||||
for (int i = 0; i < _textBlocks.Count; i++)
|
||||
{
|
||||
ref TextBlock textBlock = ref textBlocks[i];
|
||||
textBlock.Bounds.Location.Y += sizeOffset.Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -239,14 +273,15 @@ namespace FlaxEngine.GUI
|
||||
}
|
||||
|
||||
// Organize text blocks within line
|
||||
var horizontalAlignments = TextBlockStyle.Alignments.Baseline;
|
||||
var verticalAlignments = TextBlockStyle.Alignments.Baseline;
|
||||
var lineAlignments = TextBlockStyle.Alignments.Baseline;
|
||||
for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++)
|
||||
{
|
||||
ref TextBlock textBlock = ref textBlocks[i];
|
||||
var vOffset = lineSize.Y - textBlock.Bounds.Height;
|
||||
horizontalAlignments |= textBlock.Style.Alignment & TextBlockStyle.Alignments.HorizontalMask;
|
||||
verticalAlignments |= textBlock.Style.Alignment & TextBlockStyle.Alignments.VerticalMask;
|
||||
if (i == context.LineStartTextBlockIndex)
|
||||
lineAlignments = textBlock.Style.Alignment;
|
||||
else
|
||||
lineAlignments &= textBlock.Style.Alignment;
|
||||
switch (textBlock.Style.Alignment & TextBlockStyle.Alignments.VerticalMask)
|
||||
{
|
||||
case TextBlockStyle.Alignments.Baseline:
|
||||
@@ -275,9 +310,9 @@ namespace FlaxEngine.GUI
|
||||
}
|
||||
}
|
||||
|
||||
// Organize blocks within whole container
|
||||
// Organize whole line horizontally
|
||||
var sizeOffset = Size - lineSize;
|
||||
if ((horizontalAlignments & TextBlockStyle.Alignments.Center) == TextBlockStyle.Alignments.Center)
|
||||
if ((lineAlignments & TextBlockStyle.Alignments.Center) == TextBlockStyle.Alignments.Center)
|
||||
{
|
||||
sizeOffset.X *= 0.5f;
|
||||
for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++)
|
||||
@@ -286,7 +321,7 @@ namespace FlaxEngine.GUI
|
||||
textBlock.Bounds.Location.X += sizeOffset.X;
|
||||
}
|
||||
}
|
||||
else if ((horizontalAlignments & TextBlockStyle.Alignments.Right) == TextBlockStyle.Alignments.Right)
|
||||
else if ((lineAlignments & TextBlockStyle.Alignments.Right) == TextBlockStyle.Alignments.Right)
|
||||
{
|
||||
for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++)
|
||||
{
|
||||
@@ -294,23 +329,6 @@ namespace FlaxEngine.GUI
|
||||
textBlock.Bounds.Location.X += sizeOffset.X;
|
||||
}
|
||||
}
|
||||
if ((verticalAlignments & TextBlockStyle.Alignments.Middle) == TextBlockStyle.Alignments.Middle)
|
||||
{
|
||||
sizeOffset.Y *= 0.5f;
|
||||
for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++)
|
||||
{
|
||||
ref TextBlock textBlock = ref textBlocks[i];
|
||||
textBlock.Bounds.Location.Y += sizeOffset.Y;
|
||||
}
|
||||
}
|
||||
else if ((verticalAlignments & TextBlockStyle.Alignments.Bottom) == TextBlockStyle.Alignments.Bottom)
|
||||
{
|
||||
for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++)
|
||||
{
|
||||
ref TextBlock textBlock = ref textBlocks[i];
|
||||
textBlock.Bounds.Location.Y += sizeOffset.Y;
|
||||
}
|
||||
}
|
||||
|
||||
// Move to the next line
|
||||
context.LineStartCharacterIndex = lineEnd + 1;
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace FlaxEngine.GUI
|
||||
// Setup size
|
||||
var font = imageBlock.Style.Font.GetFont();
|
||||
if (font)
|
||||
imageBlock.Bounds.Size = new Float2(font.Height);
|
||||
imageBlock.Bounds.Size = new Float2(font.Ascender);
|
||||
var imageSize = image.Size;
|
||||
imageBlock.Bounds.Size.X *= imageSize.X / imageSize.Y; // Keep original aspect ratio
|
||||
bool hasWidth = TryParseNumberTag(ref tag, "width", imageBlock.Bounds.Width, out var width);
|
||||
@@ -215,16 +215,16 @@ namespace FlaxEngine.GUI
|
||||
switch (valign)
|
||||
{
|
||||
case "top":
|
||||
style.Alignment = TextBlockStyle.Alignments.Top;
|
||||
style.Alignment |= TextBlockStyle.Alignments.Top;
|
||||
break;
|
||||
case "bottom":
|
||||
style.Alignment = TextBlockStyle.Alignments.Bottom;
|
||||
style.Alignment |= TextBlockStyle.Alignments.Bottom;
|
||||
break;
|
||||
case "middle":
|
||||
style.Alignment = TextBlockStyle.Alignments.Middle;
|
||||
style.Alignment |= TextBlockStyle.Alignments.Middle;
|
||||
break;
|
||||
case "baseline":
|
||||
style.Alignment = TextBlockStyle.Alignments.Baseline;
|
||||
style.Alignment |= TextBlockStyle.Alignments.Baseline;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -243,17 +243,17 @@ namespace FlaxEngine.GUI
|
||||
var style = context.StyleStack.Peek();
|
||||
if (tag.Attributes.TryGetValue(string.Empty, out var valign))
|
||||
{
|
||||
style.Alignment &= ~TextBlockStyle.Alignments.VerticalMask;
|
||||
style.Alignment &= ~TextBlockStyle.Alignments.HorizontalMask;
|
||||
switch (valign)
|
||||
{
|
||||
case "left":
|
||||
style.Alignment = TextBlockStyle.Alignments.Left;
|
||||
style.Alignment |= TextBlockStyle.Alignments.Left;
|
||||
break;
|
||||
case "right":
|
||||
style.Alignment = TextBlockStyle.Alignments.Right;
|
||||
style.Alignment |= TextBlockStyle.Alignments.Right;
|
||||
break;
|
||||
case "center":
|
||||
style.Alignment = TextBlockStyle.Alignments.Center;
|
||||
style.Alignment |= TextBlockStyle.Alignments.Center;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -270,7 +270,8 @@ namespace FlaxEngine.GUI
|
||||
else
|
||||
{
|
||||
var style = context.StyleStack.Peek();
|
||||
style.Alignment = TextBlockStyle.Alignments.Center;
|
||||
style.Alignment &= ~TextBlockStyle.Alignments.HorizontalMask;
|
||||
style.Alignment |= TextBlockStyle.Alignments.Center;
|
||||
context.StyleStack.Push(style);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user