diff --git a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
index 4b2acaa3614f85c672d4453f6c3a11a493a60c13..247356b1ccdfed6d77209320c36640967a3bb6ec 100644
--- a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
+++ b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
@@ -4,7 +4,7 @@
#include "GPUInstancedLineComponent.h"
#include "InstancedMeshLineRendering.h" // Only needed for logging
-//#pragma optimize("", off)
+#pragma optimize("", off)
UGPUInstancedLineComponent::UGPUInstancedLineComponent(const FObjectInitializer& ObjectInitializer)
@@ -24,6 +24,12 @@ UGPUInstancedLineComponent::UGPUInstancedLineComponent(const FObjectInitializer&
UMaterial* LineMaterial = LineMaterialAsset.Object;
SetStaticMesh(LineAsset);
SetMaterial(0, LineMaterial);
+
+
+ UMaterialInterface* LineMaterialInterface = LoadObject<UMaterialInterface>(NULL, TEXT("/InstancedMeshLineRendering/DynamicLineMaterial.DynamicLineMaterial"), NULL, LOAD_None, NULL);
+ DynamicLineMaterial = UMaterialInstanceDynamic::Create(LineMaterialInterface, GetTransientPackage());
+ check(DynamicLineMaterial);
+
// three color values + width + 1 texture index value
// r | g | b | w | i_T
@@ -31,6 +37,7 @@ UGPUInstancedLineComponent::UGPUInstancedLineComponent(const FObjectInitializer&
CurrentTextureMarker = FIntPoint(0, 0);
CurrentTextureIndex = 0,
+ NextFreeId = 0;
TextureWidth = 2048;
TextureHeight = 2048;
@@ -83,36 +90,37 @@ void UGPUInstancedLineComponent::UpdateWholeTexture()
void UGPUInstancedLineComponent::Init()
{
+ if(PositionTexture != nullptr)
+ {
+ UE_LOG(LogLineRendering, Error, TEXT("UGPUInstancedLineComponent::Init PositionTexture already exists!"));
+ }
UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::Init Creating Texture"));
PositionTexture = UTexture2D::CreateTransient(TextureWidth, TextureHeight, PF_A32B32G32R32F);
// Allocate the texture RHI
PositionTexture->UpdateResource();
- UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::Init Creating MID"));
-
- DynamicLineMaterial = CreateAndSetMaterialInstanceDynamic(0);// UMaterialInstanceDynamic::Create(LineMat, this, "DynamicLineMaterialMID");
if (DynamicLineMaterial == nullptr) // FOR WHATEVER REASON I HAVE NO IDEA
{
- DynamicLineMaterial = UMaterialInstanceDynamic::Create(GetStaticMesh()->GetMaterial(0), this);// UMaterialInstanceDynamic::Create(LineMat, this, "DynamicLineMaterialMID");
- SetMaterial(0, DynamicLineMaterial);
+ UE_LOG(LogLineRendering, Fatal, TEXT("UGPUInstancedLineComponent::Init MID was nullptr!"));
}
- if(DynamicLineMaterial)
+ else
{
+ UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::Init Setting MID"));
+
+ SetMaterial(0, DynamicLineMaterial);
DynamicLineMaterial->SetTextureParameterValue("PositionTexture", PositionTexture);
DynamicLineMaterial->SetScalarParameterValue("TextureWidth", TextureWidth);
}
- else
- UE_LOG(LogLineRendering, Error, TEXT("UGPUInstancedLineComponent::Init DynamicLineMaterial was nullptr"));
- UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::Init Resetting Data"));
- LineMap.Empty();
- LinearLineData.Empty();
- NextFreeId = 0;
- CurrentTextureIndex = 0;
- CurrentTextureMarker = FIntPoint(0, 0);
- ClearInstances();
+ //UE_LOG(LogLineRendering, Display, TEXT("UGPUInstancedLineComponent::Init Resetting Data"));
+ //LineMap.Empty();
+ //LinearLineData.Empty();
+ //NextFreeId = 0;
+ //CurrentTextureIndex = 0;
+ //CurrentTextureMarker = FIntPoint(0, 0);
+ //ClearInstances();
- RegisterSerializedEditorLines();
+ //RegisterSerializedEditorLines();
bIsInitialized = true;
@@ -121,23 +129,28 @@ void UGPUInstancedLineComponent::Init()
//{
// AddLineFromEditorData(EditorLine);
//}
-
-}
-void UGPUInstancedLineComponent::RegisterSerializedEditorLines()
-{
+ // Update the texture
- // Here's to hoping the respective id field doesn't get serialized...
-
- for (FEditorLineData& EditorLine : EditorLines)
- {
- if(EditorLine.RespectiveLineId == -1)
- {
- AddLineFromEditorData(EditorLine);
- }
- }
+ // Theoretically we could serialize the texture as well, but that seems like too much work
+ UpdateWholeTexture();
+
}
+//void UGPUInstancedLineComponent::RegisterSerializedEditorLines()
+//{
+//
+// // Here's to hoping the respective id field doesn't get serialized...
+//
+// for (FEditorLineData& EditorLine : EditorLines)
+// {
+// if(EditorLine.RespectiveLineId == -1 || !LineMap.Contains(EditorLine.RespectiveLineId))
+// {
+// AddLineFromEditorData(EditorLine);
+// }
+// }
+//}
+
void UGPUInstancedLineComponent::UpdateAllEditorLines()
{
for (const FEditorLineData& EditorLine : EditorLines)
@@ -224,7 +237,7 @@ void UGPUInstancedLineComponent::BeginPlay()
Super::BeginPlay();
// todo don't think this is needed here
- RegisterSerializedEditorLines();
+ //RegisterSerializedEditorLines();
//Init();
if(!bIsInitialized)
@@ -245,7 +258,7 @@ void UGPUInstancedLineComponent::PostInitProperties()
#if WITH_EDITOR
void UGPUInstancedLineComponent::PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent)
{
- if (PropertyChangedEvent.Property != NULL)
+ if (PropertyChangedEvent.Property != NULL && bIsInitialized)
{
if (PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(UGPUInstancedLineComponent, EditorLines))
{
@@ -467,6 +480,14 @@ void UGPUInstancedLineComponent::BeginDestroy()
ReleaseData();
}
+void UGPUInstancedLineComponent::Serialize(FArchive& Ar)
+{
+ Super::Serialize(Ar);
+
+
+
+}
+
void UGPUInstancedLineComponent::ReserveMemory(int32 NumberOfSegments, int32 NumberOfLines)
{
const int32 Total = NumberOfSegments * NumberOfLines;
@@ -496,14 +517,14 @@ bool UGPUInstancedLineComponent::ResizeTexture(int32 Width, int32 Height)
// This might be a bit awkward as the line map is a *map*, and not just an array.
// Some lines might be re-ordered in the texture, but that should be fine.
- for(TPair<int32, GPULineArray>& Line : LineMap)
+ for(TPair<int32, FGPULineArray>& Line : LineMap)
{
- for (GPULineIndices& LineIndices : Line.Value)
+ for (FGPULineIndices& LineIndices : Line.Value.IndexArray)
{
// Key is instance id, value is texture index.
- if(LineIndices.Key >= 0)
- SetCustomDataValue(LineIndices.Key, 4, CurrentTextureIndex, false);
- LineIndices.Value = CurrentTextureIndex;
+ if(LineIndices.InstanceIndex >= 0)
+ SetCustomDataValue(LineIndices.InstanceIndex, 4, CurrentTextureIndex, false);
+ LineIndices.TextureIndex = CurrentTextureIndex;
CurrentTextureIndex++;
MoveTextureMarker();
}
@@ -556,8 +577,8 @@ void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int3
const FLinearColor Color = UniformColor ? Colors[0] : Colors[LineIndex];
const float Width = UniformWidth ? Widths[0] : Widths[LineIndex];
- GPULineArray& NewLineArray = LineMap.Add(NextFreeId, GPULineArray());
- NewLineArray.Reserve(NumberOfSegmentsPerLine + 1);
+ FGPULineArray& NewLineArray = LineMap.Add(NextFreeId, FGPULineArray());
+ NewLineArray.IndexArray.Reserve(NumberOfSegmentsPerLine + 1);
for (int32 PointIndex = 0; PointIndex < NumberOfSegmentsPerLine; ++PointIndex)
{
@@ -568,12 +589,12 @@ void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int3
SetCustomDataValue(InstanceId, 2, Color.B, false);
SetCustomDataValue(InstanceId, 3, Width, false);
SetCustomDataValue(InstanceId, 4, static_cast<float>(CurrentTextureIndex), false); // Segment Start
- NewLineArray.Add(TPair<int32, int32>{InstanceId, LineIndex * (NumberOfSegmentsPerLine + 1) + PointIndex});
+ NewLineArray.IndexArray.Add({InstanceId, LineIndex * (NumberOfSegmentsPerLine + 1) + PointIndex});
CurrentTextureIndex++;
MoveTextureMarker();
}
- NewLineArray.Add(TPair<int32, int32>{-1, LineIndex * (NumberOfSegmentsPerLine + 1) + NumberOfSegmentsPerLine});
+ NewLineArray.IndexArray.Add({-1, LineIndex * (NumberOfSegmentsPerLine + 1) + NumberOfSegmentsPerLine});
MoveTextureMarker();
CurrentTextureIndex++;
NextFreeId++;
@@ -592,8 +613,8 @@ int32 UGPUInstancedLineComponent::AddLine(const TArray<FVector>& Line, FLinearCo
return -1;
}
// 1.
- GPULineArray& NewLineArray = LineMap.Add(NextFreeId, GPULineArray());
- NewLineArray.Reserve(Line.Num());
+ FGPULineArray& NewLineArray = LineMap.Add(NextFreeId, FGPULineArray());
+ NewLineArray.IndexArray.Reserve(Line.Num());
const int32 LineId = NextFreeId;
NextFreeId++; // TODO Fix Id system as this can possibly overflow.
@@ -613,13 +634,13 @@ int32 UGPUInstancedLineComponent::AddLine(const TArray<FVector>& Line, FLinearCo
SetCustomDataValue(InstanceId, 2, Color.B, false);
SetCustomDataValue(InstanceId, 3, Width, false);
SetCustomDataValue(InstanceId, 4, static_cast<float>(CurrentTextureIndex), false); // Segment Start
- NewLineArray.Add(TPair<int32, int32>{InstanceId, LinearLineData.Num() + PointIndex});
+ NewLineArray.IndexArray.Add({InstanceId, LinearLineData.Num() + PointIndex});
CurrentTextureIndex++;
MoveTextureMarker();
}
// Add the last point which does not correspond to a transform/instance, but needs to be added to the texture still such that the second last instance can read it:
- NewLineArray.Add(TPair<int32, int32>{-1, LinearLineData.Num() + NumberSegments});
+ NewLineArray.IndexArray.Add({-1, LinearLineData.Num() + NumberSegments});
MoveTextureMarker();
CurrentTextureIndex++;
@@ -670,18 +691,18 @@ bool UGPUInstancedLineComponent::AddPoint(int32 LineId, const FVector& Point)
// Adding a point to the last line is easy. Adding it to a line the middle is awkward and requires an almost complete recalculation
// Get color and width of the line
- GPULineArray& Line = LineMap[LineId];
+ FGPULineArray& Line = LineMap[LineId];
- const float R = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats];
- const float G = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats + 1];
- const float B = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats + 2];
- const float Width = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats + 3];
+ const float R = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats];
+ const float G = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 1];
+ const float B = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 2];
+ const float Width = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 3];
const FIntPoint InitialTextureMarker = CurrentTextureMarker;
// Check if it's the last line:
- GPULineIndices& Indices = Line.Last();
+ FGPULineIndices& Indices = Line.IndexArray.Last();
const int32 InstanceId = AddInstanceWorldSpace(FTransform::Identity);
SetCustomDataValue(InstanceId, 0, R, false);
SetCustomDataValue(InstanceId, 1, G, false);
@@ -689,11 +710,11 @@ bool UGPUInstancedLineComponent::AddPoint(int32 LineId, const FVector& Point)
SetCustomDataValue(InstanceId, 3, Width, false);
// Update the latest dummy entry to point to the actual segment.
- Line.Last().Key = InstanceId;
+ Line.IndexArray.Last().InstanceIndex = InstanceId;
// Set remaining custom data for the newly created segment:
- SetCustomDataValue(InstanceId, 4, static_cast<float>(Indices.Value), false); // Segment Start
+ SetCustomDataValue(InstanceId, 4, static_cast<float>(Indices.TextureIndex), false); // Segment Start
- FVector4& PreviousLastPoint = LinearLineData[Indices.Value];
+ FVector4& PreviousLastPoint = LinearLineData[Indices.TextureIndex];
PreviousLastPoint.W = 1.0; // This isn't the line end anymore.
if(LineId == NextFreeId - 1)
@@ -702,7 +723,7 @@ bool UGPUInstancedLineComponent::AddPoint(int32 LineId, const FVector& Point)
LinearLineData.Add(FVector4(Point, -1)); // This is the last point now.
// Add a new dummy entry for the last point
- Line.Add(GPULineIndices{ -1, LinearLineData.Num() - 1 });
+ Line.IndexArray.Add(FGPULineIndices{ -1, LinearLineData.Num() - 1 });
CurrentTextureIndex++;
MoveTextureMarker();
@@ -756,26 +777,26 @@ bool UGPUInstancedLineComponent::AddPoint(int32 LineId, const FVector& Point)
// This is slightly more complicated as all the indices after the added point need to be adjusted.
// Additionally, the point needs to be inserted into the texture, shifting the whole thing.
- const int32 NewPointTextureIndex = Indices.Value + 1;
+ const int32 NewPointTextureIndex = Indices.TextureIndex + 1;
// Update all LineMap Indices that have a texture index larger than the newly inserted point. Todo: Make more efficient, maybe remove map and swap to array:
- for (TPair<int32, GPULineArray>& Pair : LineMap)
+ for (TPair<int32, FGPULineArray>& Pair : LineMap)
{
- GPULineArray& LineArray = Pair.Value;
- if (LineArray[0].Value >= NewPointTextureIndex)
+ FGPULineArray& LineArray = Pair.Value;
+ if (LineArray.IndexArray[0].TextureIndex >= NewPointTextureIndex)
{
// Need to increase all indices by 1 and adjust the custom data
- for (int32 i = 0; i < LineArray.Num(); ++i)
+ for (int32 i = 0; i < LineArray.IndexArray.Num(); ++i)
{
- LineArray[i].Value++;
- SetCustomDataValue(LineArray[i].Key, 4, LineArray[i].Value, false);
+ LineArray.IndexArray[i].TextureIndex++;
+ SetCustomDataValue(LineArray.IndexArray[i].InstanceIndex, 4, LineArray.IndexArray[i].TextureIndex, false);
}
}
}
// Insert the point into the LinearData:
LinearLineData.Insert(FVector4(Point, -1), NewPointTextureIndex);
// Add it to the LineMap - this is the new dummy segment because we add it at the end of the line
- Line.Add(GPULineIndices{ -1, NewPointTextureIndex });
+ Line.IndexArray.Add(FGPULineIndices{ -1, NewPointTextureIndex });
//SetCustomDataValue(InstanceId, 4, NewPointTextureIndex, true);
CurrentTextureIndex++;
@@ -792,15 +813,15 @@ bool UGPUInstancedLineComponent::InsertPoint(int32 LineId, int32 SegmentId, cons
{
TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UGPUInstancedLineComponent::InsertPoint"))
- GPULineArray& Line = LineMap[LineId];
+ FGPULineArray& Line = LineMap[LineId];
- if (SegmentId == Line.Num())
+ if (SegmentId == Line.IndexArray.Num())
{
return AddPoint(LineId, Point);
}
- const float Width = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats + 3];
+ const float Width = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 3];
- const int32 LinearDataIndex = Line[SegmentId].Value;
+ const int32 LinearDataIndex = Line.IndexArray[SegmentId].TextureIndex;
// Add a new segment BEFORE the current one.
const int32 InstanceId = AddInstanceWorldSpace(FTransform::Identity);
@@ -819,27 +840,27 @@ bool UGPUInstancedLineComponent::InsertPoint(int32 LineId, int32 SegmentId, cons
// This was the old start point
LinearLineData[LinearDataIndex + 1].W = 1;
}
- Line.Insert(GPULineIndices{ InstanceId, LinearDataIndex }, SegmentId);
+ Line.IndexArray.Insert(FGPULineIndices{ InstanceId, LinearDataIndex }, SegmentId);
SetCustomDataValue(InstanceId, 4, LinearDataIndex, false);
// Update the rest of the line
- for(int32 i = SegmentId + 1; i < Line.Num(); ++i)
+ for(int32 i = SegmentId + 1; i < Line.IndexArray.Num(); ++i)
{
- Line[i].Value++;
- SetCustomDataValue(Line[i].Key, 4, Line[i].Value);
+ Line.IndexArray[i].TextureIndex++;
+ SetCustomDataValue(Line.IndexArray[i].InstanceIndex, 4, Line.IndexArray[i].TextureIndex);
}
// Update all following lines
- for (TPair<int32, GPULineArray>& Pair : LineMap)
+ for (TPair<int32, FGPULineArray>& Pair : LineMap)
{
- GPULineArray& LineArray = Pair.Value;
- if (LineArray[0].Value > LinearDataIndex)
+ FGPULineArray& LineArray = Pair.Value;
+ if (LineArray.IndexArray[0].TextureIndex > LinearDataIndex)
{
// Need to increase all indices by 1 and adjust the custom data
- for (int32 i = 0; i < LineArray.Num(); ++i)
+ for (int32 i = 0; i < LineArray.IndexArray.Num(); ++i)
{
- LineArray[i].Value++;
- SetCustomDataValue(LineArray[i].Key, 4, LineArray[i].Value, false);
+ LineArray.IndexArray[i].TextureIndex++;
+ SetCustomDataValue(LineArray.IndexArray[i].InstanceIndex, 4, LineArray.IndexArray[i].TextureIndex, false);
}
}
}
@@ -857,10 +878,10 @@ bool UGPUInstancedLineComponent::InsertPoint(int32 LineId, int32 SegmentId, cons
bool UGPUInstancedLineComponent::InsertPointWithSameColor(int32 LineId, int32 SegmentId, const FVector& Point)
{
- GPULineArray& Line = LineMap[LineId];
- const float R = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats];
- const float G = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats + 1];
- const float B = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats + 2];
+ FGPULineArray& Line = LineMap[LineId];
+ const float R = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats];
+ const float G = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 1];
+ const float B = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 2];
return InsertPoint(LineId, SegmentId, Point, { R, G, B });
}
@@ -878,18 +899,18 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
// Adding a point to the last line is easy. Adding it to a line the middle is awkward and requires an almost complete recalculation
// Get color and width of the line
- GPULineArray& Line = LineMap[LineId];
- const float R = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats];
- const float G = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats + 1];
- const float B = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats + 2];
- const float Width = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats + 3];
+ FGPULineArray& Line = LineMap[LineId];
+ const float R = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats];
+ const float G = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 1];
+ const float B = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 2];
+ const float Width = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 3];
const FIntPoint InitialTextureMarker = CurrentTextureMarker;
// Check if it's the last line:
- GPULineIndices& Indices = Line.Last();
- const int32 PointTextureIndex = Indices.Value;
- FVector4& PreviousLastPoint = LinearLineData[Indices.Value];
+ FGPULineIndices& Indices = Line.IndexArray.Last();
+ const int32 PointTextureIndex = Indices.TextureIndex;
+ FVector4& PreviousLastPoint = LinearLineData[Indices.TextureIndex];
PreviousLastPoint.W = 1.0; // This isn't the line end anymore.
if (LineId == NextFreeId - 1)
@@ -906,9 +927,9 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
// Update the latest dummy entry to point to the actual segment.
if (PointIndex == 0)
- Line.Last().Key = InstanceId;
+ Line.IndexArray.Last().InstanceIndex = InstanceId;
else
- Line.Add(TPair<int32, int32>{InstanceId, LinearLineData.Num() - 1 + PointIndex});
+ Line.IndexArray.Add({InstanceId, LinearLineData.Num() - 1 + PointIndex});
CurrentTextureIndex++;
MoveTextureMarker();
}
@@ -917,7 +938,7 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
LinearLineData.Last().W = -1;
// Add a new dummy entry for the last point
- Line.Add(GPULineIndices{ -1, LinearLineData.Num() - 1 });
+ Line.IndexArray.Add({ -1, LinearLineData.Num() - 1 });
CurrentTextureIndex++;
MoveTextureMarker();
@@ -949,19 +970,19 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
// This is slightly more complicated as all the indices after the added points need to be adjusted.
// Additionally, the points needs to be inserted into the texture, shifting the whole thing.
- const int32 NewPointTextureIndex = Indices.Value + 1;
+ const int32 NewPointTextureIndex = Indices.TextureIndex + 1;
// Update all LineMap Indices that have a texture index larger than the newly inserted point. Todo: Make more efficient, maybe remove map and swap to array:
- for (TPair<int32, GPULineArray>& Pair : LineMap)
+ for (TPair<int32, FGPULineArray>& Pair : LineMap)
{
- GPULineArray& LineArray = Pair.Value;
- if (LineArray[0].Value >= NewPointTextureIndex)
+ FGPULineArray& LineArray = Pair.Value;
+ if (LineArray.IndexArray[0].TextureIndex >= NewPointTextureIndex)
{
// Need to increase all indices by 1 and adjust the custom data
- for (int32 i = 0; i < LineArray.Num(); ++i)
+ for (int32 i = 0; i < LineArray.IndexArray.Num(); ++i)
{
- LineArray[i].Value += Points.Num();
- SetCustomDataValue(LineArray[i].Key, 4, LineArray[i].Value, false);
+ LineArray.IndexArray[i].TextureIndex += Points.Num();
+ SetCustomDataValue(LineArray.IndexArray[i].InstanceIndex, 4, LineArray.IndexArray[i].TextureIndex, false);
}
}
}
@@ -978,10 +999,10 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
// Update the latest dummy entry to point to the actual segment.
if (PointIndex == 0)
- Line.Last().Key = InstanceId;
+ Line.IndexArray.Last().InstanceIndex = InstanceId;
else
{
- Line.Add(TPair<int32, int32>{InstanceId, NewPointTextureIndex + PointIndex - 1});
+ Line.IndexArray.Add({InstanceId, NewPointTextureIndex + PointIndex - 1});
CurrentTextureIndex++;
MoveTextureMarker();
}
@@ -994,7 +1015,7 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
LinearLineData.Insert(TextureData, NewPointTextureIndex);
// Add it to the LineMap - this is the new dummy segment because we add it at the end of the line
- Line.Add(GPULineIndices{ -1, NewPointTextureIndex + Points.Num() - 1 });
+ Line.IndexArray.Add({ -1, NewPointTextureIndex + Points.Num() - 1 });
//SetCustomDataValue(InstanceId, 4, NewPointTextureIndex, true);
CurrentTextureIndex++;
@@ -1011,18 +1032,18 @@ bool UGPUInstancedLineComponent::InsertPoints(int32 LineId, int32 SegmentId, con
{
TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UGPUInstancedLineComponent::InsertPoint"))
- GPULineArray& Line = LineMap[LineId];
+ FGPULineArray& Line = LineMap[LineId];
- if (SegmentId == Line.Num())
+ if (SegmentId == Line.IndexArray.Num())
{
return AddPoints(LineId, Points);
}
- const float R = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats];
- const float G = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats + 1];
- const float B = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats + 2];
- const float Width = PerInstanceSMCustomData[Line[0].Key * NumCustomDataFloats + 3];
+ const float R = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats];
+ const float G = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 1];
+ const float B = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 2];
+ const float Width = PerInstanceSMCustomData[Line.IndexArray[0].InstanceIndex * NumCustomDataFloats + 3];
- const int32 LinearDataIndex = Line[SegmentId].Value;
+ const int32 LinearDataIndex = Line.IndexArray[SegmentId].TextureIndex;
LinearLineData.Insert(TArray<FVector4>(Points), LinearDataIndex);
if (SegmentId == 0)
{
@@ -1040,30 +1061,30 @@ bool UGPUInstancedLineComponent::InsertPoints(int32 LineId, int32 SegmentId, con
SetCustomDataValue(InstanceId, 2, B, false);
SetCustomDataValue(InstanceId, 3, Width, false);
- Line.Insert(GPULineIndices{ InstanceId, LinearDataIndex + PointIndex }, SegmentId + PointIndex);
+ Line.IndexArray.Insert({ InstanceId, LinearDataIndex + PointIndex }, SegmentId + PointIndex);
SetCustomDataValue(InstanceId, 4, LinearDataIndex + PointIndex, false);
CurrentTextureIndex++;
MoveTextureMarker();
}
// Update the rest of the line
- for (int32 i = SegmentId + Points.Num(); i < Line.Num(); ++i)
+ for (int32 i = SegmentId + Points.Num(); i < Line.IndexArray.Num(); ++i)
{
- Line[i].Value += Points.Num();
- SetCustomDataValue(Line[i].Key, 4, Line[i].Value);
+ Line.IndexArray[i].TextureIndex += Points.Num();
+ SetCustomDataValue(Line.IndexArray[i].InstanceIndex, 4, Line.IndexArray[i].TextureIndex);
}
// Update all following lines
- for (TPair<int32, GPULineArray>& Pair : LineMap)
+ for (TPair<int32, FGPULineArray>& Pair : LineMap)
{
- GPULineArray& LineArray = Pair.Value;
- if (LineArray[0].Value > LinearDataIndex)
+ FGPULineArray& LineArray = Pair.Value;
+ if (LineArray.IndexArray[0].TextureIndex > LinearDataIndex)
{
// Need to increase all indices by 1 and adjust the custom data
- for (int32 i = 0; i < LineArray.Num(); ++i)
+ for (int32 i = 0; i < LineArray.IndexArray.Num(); ++i)
{
- LineArray[i].Value += Points.Num();
- SetCustomDataValue(LineArray[i].Key, 4, LineArray[i].Value, false);
+ LineArray.IndexArray[i].TextureIndex += Points.Num();
+ SetCustomDataValue(LineArray.IndexArray[i].InstanceIndex, 4, LineArray.IndexArray[i].TextureIndex, false);
}
}
}
@@ -1081,9 +1102,9 @@ bool UGPUInstancedLineComponent::UpdateLine(int32 LineId, TArray<FVector>& Point
{
TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UGPUInstancedLineComponent::UpdateLine"))
- const GPULineArray& Line = LineMap[LineId];
+ const FGPULineArray& Line = LineMap[LineId];
- if(Line.Num() != Points.Num())
+ if(Line.IndexArray.Num() != Points.Num())
{
return false;
}
@@ -1091,7 +1112,7 @@ bool UGPUInstancedLineComponent::UpdateLine(int32 LineId, TArray<FVector>& Point
TArray<FVector4>* TextureData = new TArray<FVector4>(MoveTemp(Points));
TextureData->Last().W = -1;
(*TextureData)[0].W = 0;
- const int32 TextureIndex = Line[0].Value;
+ const int32 TextureIndex = Line.IndexArray[0].TextureIndex;
const FIntPoint StartIndex(TextureIndex % TextureWidth, TextureIndex / TextureWidth);
FMemory::Memcpy(LinearLineData.GetData() + TextureIndex, TextureData->GetData(), TextureData->Num() * sizeof(FVector4));
@@ -1179,16 +1200,16 @@ bool UGPUInstancedLineComponent::DrawLinesDirectly(int32 LineIdStart, TArray<FVe
bool UGPUInstancedLineComponent::UpdatePoint(int32 LineId, int32 PointId, const FVector& Point)
{
// Should check for validity
- const GPULineIndices& PointIndices = LineMap[LineId][PointId];
+ const FGPULineIndices& PointIndices = LineMap[LineId].IndexArray[PointId];
// Only need to update the linear data - don't overwrite W as the line start/end doesn't change
- LinearLineData[PointIndices.Value].X = Point.X;
- LinearLineData[PointIndices.Value].Y = Point.Y;
- LinearLineData[PointIndices.Value].Z = Point.Z;
+ LinearLineData[PointIndices.TextureIndex].X = Point.X;
+ LinearLineData[PointIndices.TextureIndex].Y = Point.Y;
+ LinearLineData[PointIndices.TextureIndex].Z = Point.Z;
- const int32 InstanceId = (PointIndices.Key != -1) ? PointIndices.Key : LineMap[LineId][PointId - 1].Key;
+ const int32 InstanceId = (PointIndices.InstanceIndex != -1) ? PointIndices.InstanceIndex : LineMap[LineId].IndexArray[PointId - 1].InstanceIndex;
- const int32 TextureIndex = PointIndices.Value;
+ const int32 TextureIndex = PointIndices.TextureIndex;
//const int32 Y = PerInstanceSMCustomData[InstanceId * NumCustomDataFloats + 5];
const int32 X = TextureIndex % TextureWidth;
const int32 Y = TextureIndex / TextureWidth;
@@ -1205,7 +1226,7 @@ bool UGPUInstancedLineComponent::UpdatePoint(int32 LineId, int32 PointId, const
// Copy for now - no need to do that
- TArray<FVector4>* TextureData = new TArray<FVector4>{ LinearLineData[PointIndices.Value] };
+ TArray<FVector4>* TextureData = new TArray<FVector4>{ LinearLineData[PointIndices.TextureIndex] };
PositionTexture->UpdateTextureRegions(0, 1, Region, TextureWidth * sizeof(FVector4), sizeof(FVector4), (uint8*)TextureData->GetData(),
@@ -1224,31 +1245,31 @@ bool UGPUInstancedLineComponent::UpdatePoints(int32 LineId, int32 StartingPointI
{
TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UGPUInstancedLineComponent::UpdatePoints"))
- const GPULineArray& Line = LineMap[LineId];
+ const FGPULineArray& Line = LineMap[LineId];
- if (Line.Num() < Points.Num() || StartingPointId + Points.Num() > Line.Num())
+ if (Line.IndexArray.Num() < Points.Num() || StartingPointId + Points.Num() > Line.IndexArray.Num())
{
return false;
}
- if(Line.Num() == Points.Num() && StartingPointId == 0)
+ if(Line.IndexArray.Num() == Points.Num() && StartingPointId == 0)
{
return UpdateLine(LineId, Points);
}
// Should check for validity
- const GPULineIndices& FirstPointIndices = LineMap[LineId][StartingPointId];
+ const FGPULineIndices& FirstPointIndices = LineMap[LineId].IndexArray[StartingPointId];
TArray<FVector4>* TextureData = new TArray<FVector4>(MoveTemp(Points));
if(StartingPointId == 0)
{
(*TextureData)[0].W = 0;
}
- if (StartingPointId + Points.Num() == Line.Num())
+ if (StartingPointId + Points.Num() == Line.IndexArray.Num())
{
TextureData->Last().W = -1;
}
- const int32 StartTextureIndex = Line[StartingPointId].Value;
+ const int32 StartTextureIndex = Line.IndexArray[StartingPointId].TextureIndex;
const FIntPoint StartIndex(StartTextureIndex % TextureWidth, StartTextureIndex / TextureWidth);
FMemory::Memcpy(LinearLineData.GetData() + StartTextureIndex, TextureData->GetData(), TextureData->Num() * sizeof(FVector4));
@@ -1270,20 +1291,20 @@ bool UGPUInstancedLineComponent::RemoveLine(int32 LineId)
{
TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UGPUInstancedLineComponent::RemoveLine"))
- const GPULineArray& Line = LineMap[LineId];
- const int32 LineLength = Line.Num();
- const int32 LineTextureIndex = Line[0].Value;
+ const FGPULineArray& Line = LineMap[LineId];
+ const int32 LineLength = Line.IndexArray.Num();
+ const int32 LineTextureIndex = Line.IndexArray[0].TextureIndex;
// Because ISM are so great, they reshuffle id's on removal....
// This means we can't just remove consecutive ids, but need to actually re-calculate them EVERY SINGLE TIME
// As instances of a line aren't guaranteed to be in order, collect and sort the indices first, then start top down.
//
TArray<int32> InstancesToRemove;
- InstancesToRemove.Reserve(Line.Num());
+ InstancesToRemove.Reserve(Line.IndexArray.Num());
- for(int32 PointIndex = 0; PointIndex < Line.Num() - 1; PointIndex++)
+ for(int32 PointIndex = 0; PointIndex < Line.IndexArray.Num() - 1; PointIndex++)
{
- InstancesToRemove.Add(Line[PointIndex].Key);
+ InstancesToRemove.Add(Line.IndexArray[PointIndex].InstanceIndex);
}
InstancesToRemove.Sort();
@@ -1298,12 +1319,12 @@ bool UGPUInstancedLineComponent::RemoveLine(int32 LineId)
LineMap.Remove(LineId);
// Update all following lines
- for (TPair<int32, GPULineArray>& Pair : LineMap)
+ for (TPair<int32, FGPULineArray>& Pair : LineMap)
{
- GPULineArray& LineArray = Pair.Value;
- for (int32 i = 0; i < LineArray.Num(); ++i)
+ FGPULineArray& LineArray = Pair.Value;
+ for (int32 i = 0; i < LineArray.IndexArray.Num(); ++i)
{
- if (LineArray[i].Key >= InstancesToRemove[0])
+ if (LineArray.IndexArray[i].InstanceIndex >= InstancesToRemove[0])
{
// Apparently unreal also shuffles the instance indices, this might bite us later on
@@ -1311,17 +1332,17 @@ bool UGPUInstancedLineComponent::RemoveLine(int32 LineId)
for(int32 Index = InstancesToRemove.Num(); Index > 0; --Index)
{
- if (LineArray[i].Key >= InstancesToRemove[Index - 1])
+ if (LineArray.IndexArray[i].InstanceIndex >= InstancesToRemove[Index - 1])
{
- LineArray[i].Key -= Index;
+ LineArray.IndexArray[i].InstanceIndex -= Index;
break;
}
}
}
- if (LineArray[0].Value >= LineTextureIndex)
+ if (LineArray.IndexArray[0].TextureIndex >= LineTextureIndex)
{
- LineArray[i].Value -= LineLength;
- SetCustomDataValue(LineArray[i].Key, 4, LineArray[i].Value, false);
+ LineArray.IndexArray[i].TextureIndex -= LineLength;
+ SetCustomDataValue(LineArray.IndexArray[i].InstanceIndex, 4, LineArray.IndexArray[i].TextureIndex, false);
}
}
}
@@ -1364,10 +1385,10 @@ bool UGPUInstancedLineComponent::RemovePoint(int32 LineId, int32 PointId)
{
TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UGPUInstancedLineComponent::RemovePoint"))
- GPULineArray& Line = LineMap[LineId];
- const GPULineIndices& Indices = Line[PointId];
- const int32 LineTextureIndex = Indices.Value;
- int32 RemovedInstanceId = Indices.Key;
+ FGPULineArray& Line = LineMap[LineId];
+ const FGPULineIndices& Indices = Line.IndexArray[PointId];
+ const int32 LineTextureIndex = Indices.TextureIndex;
+ int32 RemovedInstanceId = Indices.InstanceIndex;
if (PointId == 0)
{
@@ -1377,42 +1398,42 @@ bool UGPUInstancedLineComponent::RemovePoint(int32 LineId, int32 PointId)
LinearLineData.RemoveAt(LineTextureIndex);
// Last point is special
- if(PointId == Line.Num() - 1)
+ if(PointId == Line.IndexArray.Num() - 1)
{
- LinearLineData[Line[PointId - 1].Value].W = -1;
- RemovedInstanceId = Line[PointId - 1].Key;
- RemoveInstance(Line[PointId - 1].Key);
- Line[PointId - 1].Key = -1;
+ LinearLineData[Line.IndexArray[PointId - 1].TextureIndex].W = -1;
+ RemovedInstanceId = Line.IndexArray[PointId - 1].InstanceIndex;
+ RemoveInstance(Line.IndexArray[PointId - 1].InstanceIndex);
+ Line.IndexArray[PointId - 1].InstanceIndex = -1;
}
else
{
// Update the following segments in this line:
- for (int32 i = PointId + 1; i < Line.Num(); ++i)
+ for (int32 i = PointId + 1; i < Line.IndexArray.Num(); ++i)
{
- Line[i].Value -= 1;
- SetCustomDataValue(Line[i].Key, 4, Line[i].Value, false);
+ Line.IndexArray[i].TextureIndex -= 1;
+ SetCustomDataValue(Line.IndexArray[i].InstanceIndex, 4, Line.IndexArray[i].TextureIndex, false);
}
MarkRenderStateDirty();
RemoveInstance(RemovedInstanceId);
}
- Line.RemoveAt(PointId);
+ Line.IndexArray.RemoveAt(PointId);
// Update all following lines
- for (TPair<int32, GPULineArray>& Pair : LineMap)
+ for (TPair<int32, FGPULineArray>& Pair : LineMap)
{
- GPULineArray& LineArray = Pair.Value;
- for (int32 i = 0; i < LineArray.Num(); ++i)
+ FGPULineArray& LineArray = Pair.Value;
+ for (int32 i = 0; i < LineArray.IndexArray.Num(); ++i)
{
- if (LineArray[i].Key >= RemovedInstanceId)
+ if (LineArray.IndexArray[i].InstanceIndex >= RemovedInstanceId)
{
// Apparently unreal also shuffles the instance indices, this might bite us later on
- LineArray[i].Key -= 1;
+ LineArray.IndexArray[i].InstanceIndex -= 1;
}
- if (LineArray[0].Value > LineTextureIndex)
+ if (LineArray.IndexArray[0].TextureIndex > LineTextureIndex)
{
- LineArray[i].Value -= 1;
- SetCustomDataValue(LineArray[i].Key, 4, LineArray[i].Value, false);
+ LineArray.IndexArray[i].TextureIndex -= 1;
+ SetCustomDataValue(LineArray.IndexArray[i].InstanceIndex, 4, LineArray.IndexArray[i].TextureIndex, false);
}
}
}
@@ -1439,11 +1460,11 @@ bool UGPUInstancedLineComponent::RemovePoints(int32 LineId, int32 StartingPointI
bool UGPUInstancedLineComponent::SetLineColor(int32 LineId, const FLinearColor& Color)
{
- const GPULineArray& Line = LineMap[LineId];
+ const FGPULineArray& Line = LineMap[LineId];
- for (const GPULineIndices& LineIndices: Line)
+ for (const FGPULineIndices& LineIndices: Line.IndexArray)
{
- const int32 InstanceId = LineIndices.Key;
+ const int32 InstanceId = LineIndices.InstanceIndex;
if (InstanceId >= 0)
{
SetCustomDataValue(InstanceId, 0, Color.R, false);
@@ -1459,7 +1480,7 @@ bool UGPUInstancedLineComponent::SetSegmentColor(int32 LineId, int32 SegmentId,
{
// Get Instance Id:
- const int32 InstanceId = LineMap[LineId][SegmentId].Key;
+ const int32 InstanceId = LineMap[LineId].IndexArray[SegmentId].InstanceIndex;
SetCustomDataValue(InstanceId, 0, Color.R, false);
SetCustomDataValue(InstanceId, 1, Color.G, false);
@@ -1470,11 +1491,11 @@ bool UGPUInstancedLineComponent::SetSegmentColor(int32 LineId, int32 SegmentId,
bool UGPUInstancedLineComponent::SetLineWidth(int32 LineId, float Width)
{
- const GPULineArray& Line = LineMap[LineId];
+ const FGPULineArray& Line = LineMap[LineId];
- for (const GPULineIndices& LineIndices : Line)
+ for (const FGPULineIndices& LineIndices : Line.IndexArray)
{
- const int32 InstanceId = LineIndices.Key;
+ const int32 InstanceId = LineIndices.InstanceIndex;
if (InstanceId >= 0)
{
SetCustomDataValue(InstanceId, 3, Width, false);
@@ -1486,9 +1507,9 @@ bool UGPUInstancedLineComponent::SetLineWidth(int32 LineId, float Width)
bool UGPUInstancedLineComponent::SetSegmentWidth(int32 LineId, int32 SegmentId, float Width)
{
- const int32 InstanceId = LineMap[LineId][SegmentId].Key;
+ const int32 InstanceId = LineMap[LineId].IndexArray[SegmentId].InstanceIndex;
SetCustomDataValue(InstanceId, 3, Width, false);
return true;
}
-//#pragma optimize("", on)
+#pragma optimize("", on)
diff --git a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
index d3e9bda0ac146af29879f6c2093954f6835fccf0..c9e7e5a4ba6a417fabd1a1281c99891b09a9e989 100644
--- a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
+++ b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
@@ -13,13 +13,20 @@
//typedef TPair<FVector, TTuple<int32, int32, int32>> GPULineSegment;
// Pair of InstanceId and LinearData index.
-typedef TPair<int32, int32> GPULineIndices;
+//
+
+
// LineArray that contains indices into the instance list and the linear data.
+
+typedef TPair<int32, int32> GPULineIndices;
+
typedef TArray<GPULineIndices> GPULineArray;
// Maps a LineId to a LineArray.
-typedef TMap<int32, GPULineArray> GPULinesMap;
+typedef TMap<int32, GPULineArray> GPULinesMap;
+
+
USTRUCT(BlueprintType)
struct FEditorPoint
@@ -55,6 +62,7 @@ struct FEditorLineData
UPROPERTY(EditAnywhere)
FColor Color;
+ UPROPERTY()
int32 RespectiveLineId = -1;
FEditorLineData()
@@ -74,12 +82,59 @@ struct FEditorLineData
}
};
+USTRUCT()
+struct FGPULineIndices
+{
+ GENERATED_USTRUCT_BODY()
+
+ UPROPERTY()
+ int32 InstanceIndex;
+
+ UPROPERTY()
+ int32 TextureIndex;
+
+ FGPULineIndices() = default;
+
+ FGPULineIndices(int32 InstanceIndex, int32 TextureIndex)
+ : InstanceIndex(InstanceIndex), TextureIndex(TextureIndex) {}
+};
+
+USTRUCT()
+struct FGPULineArray
+{
+ GENERATED_USTRUCT_BODY()
+
+ UPROPERTY()
+ TArray<FGPULineIndices> IndexArray;
+};
-UCLASS(Blueprintable, BlueprintType, meta = (BlueprintSpawnableComponent), HideCategories=("Instances", "Object", "LOD", "Physics", "Activation", "Materials", "Cooking", "Sockets", "Collision", "Mobile", "HLOD"))
+UCLASS(Blueprintable, BlueprintType, meta = (BlueprintSpawnableComponent), HideCategories=(Object, LOD, Physics, Activation, Materials, "Cooking", "Sockets", "Collision", "Mobile", "HLOD"))
class INSTANCEDMESHLINERENDERING_API UGPUInstancedLineComponent : public UInstancedStaticMeshComponent
{
GENERATED_BODY()
+public:
+
+ UGPUInstancedLineComponent(const FObjectInitializer& ObjectInitializer);
+ ~UGPUInstancedLineComponent();
+
+ virtual void BeginPlay() override;
+
+ virtual void PostInitProperties() override;
+#if WITH_EDITOR
+ virtual void PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent) override;
+ virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; // need this for the widget as for some godforsaken reason the Chain event doesn't fire...
+ // This is ABSURDLY hacky
+ virtual void OnUpdateTransform(EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport = ETeleportType::None) override;
+
+#endif
+
+ virtual void PostLoad() override;
+ virtual void OnComponentCreated() override;
+ virtual void BeginDestroy() override;
+
+ virtual void Serialize(FArchive& Ar) override;
+
private:
void MoveTextureMarker()
@@ -97,48 +152,13 @@ private:
void Init();
- void RegisterSerializedEditorLines();
+ //void RegisterSerializedEditorLines();
void UpdateAllEditorLines();
FUpdateTextureRegion2D* CalculateTextureRegions(const FIntPoint& StartIndex, int32 NumberOfPoints, int32& NumberOfRegionsOut);
- GPULinesMap LineMap;
-
- TArray<FVector4> LinearLineData;
-
- // Array that keeps track of editor lines. This is ONLY needed because the array can be cleared by a simple stupid button press in the
- // details panel, circumventing the PostEditChangeChainProperty function by clearing the array first. The change callback gets called, but
- // as the EditorLines array has already been cleared, it's not possible to backtrack the removed lines.
- TArray<int32> EditorLineIds;
-
- int32 NextFreeId = 0;
- int32 CurrentTextureIndex;
- FIntPoint CurrentTextureMarker;
-
- bool bIsInitialized = false;
-
-protected:
- virtual void BeginPlay() override;
-
- virtual void PostInitProperties() override;
-#if WITH_EDITOR
- virtual void PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent) override;
- virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; // need this for the widget as for some godforsaken reason the Chain event doesn't fire...
- // This is ABSURDLY hacky
- virtual void OnUpdateTransform(EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport = ETeleportType::None) override;
-
-#endif
-
- virtual void PostLoad() override;
- virtual void OnComponentCreated() override;
- virtual void BeginDestroy() override;
-
public:
-
- UGPUInstancedLineComponent(const FObjectInitializer& ObjectInitializer);
- ~UGPUInstancedLineComponent();
-
// todo
void ReleaseData();
@@ -423,7 +443,7 @@ public:
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Components|InstancedLineComponent")
int32 GetNumberOfPointsInLine(int32 LineId) const
{
- return LineMap[LineId].Num();
+ return LineMap[LineId].IndexArray.Num();
}
UPROPERTY(BlueprintReadWrite, EditAnywhere)
@@ -438,10 +458,34 @@ public:
UPROPERTY(BlueprintReadOnly, EditAnywhere)
int32 TextureHeight;
- UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
+ UPROPERTY(transient)
UMaterialInstanceDynamic* DynamicLineMaterial;
UPROPERTY(EditAnywhere, DisplayName = "Lines", meta = (MakeEditWidget = true, EditFixedOrder))
TArray<FEditorLineData> EditorLines;
+private:
+
+ UPROPERTY()
+ TMap<int32, FGPULineArray> LineMap;
+
+ UPROPERTY()
+ TArray<FVector4> LinearLineData;
+
+ // Array that keeps track of editor lines. This is ONLY needed because the array can be cleared by a simple stupid button press in the
+ // details panel, circumventing the PostEditChangeChainProperty function by clearing the array first. The change callback gets called, but
+ // as the EditorLines array has already been cleared, it's not possible to backtrack the removed lines.
+ UPROPERTY()
+ TArray<int32> EditorLineIds;
+
+ UPROPERTY()
+ int32 NextFreeId;
+
+ UPROPERTY()
+ int32 CurrentTextureIndex;
+
+ UPROPERTY()
+ FIntPoint CurrentTextureMarker;
+
+ bool bIsInitialized = false;
};
\ No newline at end of file