Skip to content
Snippets Groups Projects
Commit e6ea37b6 authored by David Gilbert's avatar David Gilbert :bug:
Browse files

- Added functionality to update width and color of a line and individual segments.

- Added functionality to resize the underlying texture, this is not done automatically yet.
- Fixed inserting a point in the middle of a line from the editor details panel.
- Fixed a crash that could occur when changing the TextureWidth/Height from the details panel.
parent 376092fe
Branches
No related tags found
No related merge requests found
...@@ -271,11 +271,18 @@ void UGPUInstancedLineComponent::PostEditChangeChainProperty(FPropertyChangedCha ...@@ -271,11 +271,18 @@ void UGPUInstancedLineComponent::PostEditChangeChainProperty(FPropertyChangedCha
check(AddedAtIndex != INDEX_NONE); check(AddedAtIndex != INDEX_NONE);
check(LineIndex != INDEX_NONE); check(LineIndex != INDEX_NONE);
// Set the point to the previous one instead of defaulting to 0,0,0 // Set the point to the previous one instead of defaulting to 0,0,0 - default to 0 if we insert it at the front
if (AddedAtIndex > 0) // this *should* be always true if (AddedAtIndex == 0)
EditorLines[LineIndex].Points[AddedAtIndex].Point = EditorLines[LineIndex].Points[AddedAtIndex + 1].Point;
else if(AddedAtIndex == EditorLines[LineIndex].Points.Num() - 1)
EditorLines[LineIndex].Points[AddedAtIndex].Point = EditorLines[LineIndex].Points[AddedAtIndex - 1].Point; EditorLines[LineIndex].Points[AddedAtIndex].Point = EditorLines[LineIndex].Points[AddedAtIndex - 1].Point;
else
{
EditorLines[LineIndex].Points[AddedAtIndex].Point = 0.5 * EditorLines[LineIndex].Points[AddedAtIndex - 1].Point
+ 0.5 * EditorLines[LineIndex].Points[AddedAtIndex + 1].Point;
}
AddPoint(EditorLines[LineIndex].RespectiveLineId, EditorLines[LineIndex].Points[AddedAtIndex].Point); InsertPointWithSameColor(EditorLines[LineIndex].RespectiveLineId, AddedAtIndex, EditorLines[LineIndex].Points[AddedAtIndex].Point);
} }
else if (PropertyChangedEvent.ChangeType == EPropertyChangeType::Duplicate) else if (PropertyChangedEvent.ChangeType == EPropertyChangeType::Duplicate)
...@@ -341,9 +348,9 @@ void UGPUInstancedLineComponent::PostEditChangeChainProperty(FPropertyChangedCha ...@@ -341,9 +348,9 @@ void UGPUInstancedLineComponent::PostEditChangeChainProperty(FPropertyChangedCha
} }
} }
} }
else if(PropertyChangedEvent.PropertyChain.GetActiveNode()->GetPrevNode()->GetValue()->GetFName() == GET_MEMBER_NAME_CHECKED(FEditorPoint, Point)) else if (PropertyChangedEvent.Property->GetName() == "X" || PropertyChangedEvent.Property->GetName() == "Y" || PropertyChangedEvent.Property->GetName() == "Z")
{ {
if (PropertyChangedEvent.Property->GetName() == "X" || PropertyChangedEvent.Property->GetName() == "Y" || PropertyChangedEvent.Property->GetName() == "Z") if (PropertyChangedEvent.PropertyChain.GetActiveNode()->GetPrevNode() != nullptr && PropertyChangedEvent.PropertyChain.GetActiveNode()->GetPrevNode()->GetValue()->GetFName() == GET_MEMBER_NAME_CHECKED(FEditorPoint, Point))
{ {
if (PropertyChangedEvent.ChangeType == EPropertyChangeType::ValueSet || PropertyChangedEvent.ChangeType == EPropertyChangeType::Interactive) if (PropertyChangedEvent.ChangeType == EPropertyChangeType::ValueSet || PropertyChangedEvent.ChangeType == EPropertyChangeType::Interactive)
{ {
...@@ -363,13 +370,19 @@ void UGPUInstancedLineComponent::PostEditChangeChainProperty(FPropertyChangedCha ...@@ -363,13 +370,19 @@ void UGPUInstancedLineComponent::PostEditChangeChainProperty(FPropertyChangedCha
} }
} }
} }
else if (PropertyChangedEvent.Property->GetFName() == "TextureWidth") else if (PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(FEditorLineData, Color))
{ {
const int32 LineIndex = PropertyChangedEvent.GetArrayIndex(PropertyChangedEvent.PropertyChain.GetActiveNode()->GetPrevNode()->GetValue()->GetFName().ToString());
SetLineColor(EditorLines[LineIndex].RespectiveLineId, EditorLines[LineIndex].Color);
} }
else if (PropertyChangedEvent.Property->GetFName() == "TextureHeight") else if (PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(FEditorLineData, Width))
{ {
const int32 LineIndex = PropertyChangedEvent.GetArrayIndex(PropertyChangedEvent.PropertyChain.GetActiveNode()->GetPrevNode()->GetValue()->GetFName().ToString());
SetLineWidth(EditorLines[LineIndex].RespectiveLineId, EditorLines[LineIndex].Width);
}
else if (PropertyChangedEvent.Property->GetFName() == "TextureWidth" || PropertyChangedEvent.Property->GetFName() == "TextureHeight")
{
ResizeTexture(TextureWidth, TextureHeight);
} }
} }
Super::PostEditChangeChainProperty(PropertyChangedEvent); Super::PostEditChangeChainProperty(PropertyChangedEvent);
...@@ -443,6 +456,52 @@ void UGPUInstancedLineComponent::ReserveMemory(int32 NumberOfSegments, int32 Num ...@@ -443,6 +456,52 @@ void UGPUInstancedLineComponent::ReserveMemory(int32 NumberOfSegments, int32 Num
} }
bool UGPUInstancedLineComponent::ResizeTexture(int32 Width, int32 Height)
{
if (LinearLineData.Num() > Width * Height)
return false;
// what basically needs to be done is a complete re-calculation of the texture indices
CurrentTextureMarker = { 0, 0 };
CurrentTextureIndex = 0;
TextureWidth = Width;
TextureHeight = Height;
//int32 TextureIndex = 0;
// Sequentially update the custom data and the line map.
// 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 (GPULineIndices& LineIndices : Line.Value)
{
// Key is instance id, value is texture index.
if(LineIndices.Key >= 0)
SetCustomDataValue(LineIndices.Key, 4, CurrentTextureIndex, false);
LineIndices.Value = CurrentTextureIndex;
CurrentTextureIndex++;
MoveTextureMarker();
}
}
// Recreate texture
UE_LOG(LogTemp, Display, TEXT("UGPUInstancedLineComponent::ResizeTexture - Creating New Texture"));
PositionTexture = UTexture2D::CreateTransient(TextureWidth, TextureHeight, PF_A32B32G32R32F);
// Allocate the texture RHI
PositionTexture->UpdateResource();
UpdateWholeTexture();
// Update material parameters and texture
DynamicLineMaterial->SetTextureParameterValue("PositionTexture", PositionTexture);
DynamicLineMaterial->SetScalarParameterValue("TextureWidth", TextureWidth);
return true;
}
void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int32 NumberOfSegmentsPerLine, void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int32 NumberOfSegmentsPerLine,
TArray<FVector4>& Points, const TArray<FLinearColor>& Colors, const TArray<float>& Widths) TArray<FVector4>& Points, const TArray<FLinearColor>& Colors, const TArray<float>& Widths)
{ {
...@@ -1349,4 +1408,59 @@ bool UGPUInstancedLineComponent::RemovePoints(int32 LineId, int32 StartingPointI ...@@ -1349,4 +1408,59 @@ bool UGPUInstancedLineComponent::RemovePoints(int32 LineId, int32 StartingPointI
return false; return false;
} }
bool UGPUInstancedLineComponent::SetLineColor(int32 LineId, const FLinearColor& Color)
{
const GPULineArray& Line = LineMap[LineId];
for (const GPULineIndices& LineIndices: Line)
{
const int32 InstanceId = LineIndices.Key;
if (InstanceId >= 0)
{
SetCustomDataValue(InstanceId, 0, Color.R, false);
SetCustomDataValue(InstanceId, 1, Color.G, false);
SetCustomDataValue(InstanceId, 2, Color.B, false);
}
}
MarkRenderStateDirty();
return true;
}
bool UGPUInstancedLineComponent::SetSegmentColor(int32 LineId, int32 SegmentId, const FLinearColor& Color)
{
// Get Instance Id:
const int32 InstanceId = LineMap[LineId][SegmentId].Key;
SetCustomDataValue(InstanceId, 0, Color.R, false);
SetCustomDataValue(InstanceId, 1, Color.G, false);
SetCustomDataValue(InstanceId, 2, Color.B, true);
return true;
}
bool UGPUInstancedLineComponent::SetLineWidth(int32 LineId, float Width)
{
const GPULineArray& Line = LineMap[LineId];
for (const GPULineIndices& LineIndices : Line)
{
const int32 InstanceId = LineIndices.Key;
if (InstanceId >= 0)
{
SetCustomDataValue(InstanceId, 3, Width, false);
}
}
MarkRenderStateDirty();
return true;
}
bool UGPUInstancedLineComponent::SetSegmentWidth(int32 LineId, int32 SegmentId, float Width)
{
const int32 InstanceId = LineMap[LineId][SegmentId].Key;
SetCustomDataValue(InstanceId, 3, Width, false);
return true;
}
//#pragma optimize("", on) //#pragma optimize("", on)
...@@ -145,6 +145,18 @@ public: ...@@ -145,6 +145,18 @@ public:
UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent") UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
void ReserveMemory(int32 NumberOfSegments, int32 NumberOfLines); void ReserveMemory(int32 NumberOfSegments, int32 NumberOfLines);
/**
* Manually resized the texture to the specified width and height. Returns false if the texture couldn't be resized, e.g. if more lines are
* being rendered than can be displayed in the texture.
*
* @param Width [in] New texture width.
* @param Height [in] New texture height.
*
* @return bool Returns true on success, false on failure.
*/
UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
bool ResizeTexture(int32 Width, int32 Height);
/** /**
* Initializes the component with a number of lines with the same length. Existing data will be cleared. The data with which to initialize the texture needs to be already in a consistent format and * Initializes the component with a number of lines with the same length. Existing data will be cleared. The data with which to initialize the texture needs to be already in a consistent format and
...@@ -336,6 +348,54 @@ public: ...@@ -336,6 +348,54 @@ public:
UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent") UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
bool RemovePoints(int32 LineId, int32 StartingPointId, int32 NumberOfPoints); bool RemovePoints(int32 LineId, int32 StartingPointId, int32 NumberOfPoints);
/**
* This function sets the color of a whole line.
*
* @param LineId [in] The id of the line.
* @param Color [in] The new color.
*
* @return bool Returns true on successful update.
*/
UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
bool SetLineColor(int32 LineId, const FLinearColor& Color);
/**
* This function sets the color of a single segment in a line.
*
* @param LineId [in] The id of the line.
* @param SegmentId [in] The index of the segment.
* @param Color [in] The new color.
*
* @return bool Returns true on successful update.
*/
UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
bool SetSegmentColor(int32 LineId, int32 SegmentId, const FLinearColor& Color);
/**
* This function sets the width of a whole line.
*
* @param LineId [in] The id of the line.
* @param Width [in] The new width.
*
* @return bool Returns true on successful update.
*/
UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
bool SetLineWidth(int32 LineId, float Width);
/**
* This function sets the width of a single segment in a line.
*
* @param LineId [in] The id of the line.
* @param SegmentId [in] The index of the segment.
* @param Width [in] The new width.
*
* @return bool Returns true on successful update.
*/
UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
bool SetSegmentWidth(int32 LineId, int32 SegmentId, float Width);
// todo // todo
UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent") UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
bool ClearAllLines() bool ClearAllLines()
...@@ -349,6 +409,14 @@ public: ...@@ -349,6 +409,14 @@ public:
return LineMap.Num(); return LineMap.Num();
} }
/**
* Returns the number of points (not segments) of a given line.
*
* @param LineId [in] Id of the line
*
* @return int32 Number of points.
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Components|InstancedLineComponent") UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Components|InstancedLineComponent")
int32 GetNumberOfPointsInLine(int32 LineId) const int32 GetNumberOfPointsInLine(int32 LineId) const
{ {
...@@ -361,10 +429,10 @@ public: ...@@ -361,10 +429,10 @@ public:
UPROPERTY(BlueprintReadOnly, VisibleAnywhere) UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
UTexture2D* PositionTexture; UTexture2D* PositionTexture;
UPROPERTY(BlueprintReadWrite, EditAnywhere) UPROPERTY(BlueprintReadOnly, EditAnywhere)
int32 TextureWidth; int32 TextureWidth;
UPROPERTY(BlueprintReadWrite, EditAnywhere) UPROPERTY(BlueprintReadOnly, EditAnywhere)
int32 TextureHeight; int32 TextureHeight;
UPROPERTY(BlueprintReadOnly, VisibleAnywhere) UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment