diff --git a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
index 5cdc7b3a6e1a739767650fb0e31daf6f3d3ce1ed..939db5dccab26c21de6ebf36f370415428318f1a 100644
--- a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
+++ b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
@@ -55,8 +55,8 @@ void UGPUInstancedLineComponent::UpdateWholeTexture()
 {
 	TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UGPUInstancedLineComponent::UpdateWholeTexture"))
 
-		// todo optimize height computation
-		FUpdateTextureRegion2D* Region = new FUpdateTextureRegion2D(
+	// todo optimize height computation
+	FUpdateTextureRegion2D* Region = new FUpdateTextureRegion2D(
 			0,
 			0,
 			0,
@@ -271,11 +271,18 @@ void UGPUInstancedLineComponent::PostEditChangeChainProperty(FPropertyChangedCha
 				check(AddedAtIndex != INDEX_NONE);
 				check(LineIndex != INDEX_NONE);
 
-				// Set the point to the previous one instead of defaulting to 0,0,0
-				if (AddedAtIndex > 0) // this *should* be always true
+				// 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) 
+					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;
-				
-				AddPoint(EditorLines[LineIndex].RespectiveLineId, EditorLines[LineIndex].Points[AddedAtIndex].Point);
+				else
+				{
+					EditorLines[LineIndex].Points[AddedAtIndex].Point =   0.5 * EditorLines[LineIndex].Points[AddedAtIndex - 1].Point
+																		+ 0.5 * EditorLines[LineIndex].Points[AddedAtIndex + 1].Point;
+				}
+
+				InsertPointWithSameColor(EditorLines[LineIndex].RespectiveLineId, AddedAtIndex, EditorLines[LineIndex].Points[AddedAtIndex].Point);
 				
 			}
 			else if (PropertyChangedEvent.ChangeType == EPropertyChangeType::Duplicate)
@@ -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)
 				{
@@ -362,14 +369,20 @@ void UGPUInstancedLineComponent::PostEditChangeChainProperty(FPropertyChangedCha
 					UpdatePoint(EditorLines[LineIndex].RespectiveLineId, PointIndex, EditorLines[LineIndex].Points[PointIndex].Point);
 				}
 			}
-		}		
-		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);
@@ -443,8 +456,54 @@ 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,
-	TArray<FVector4>& Points, const TArray<FLinearColor>& Colors, const TArray<float>& Widths)
+                                                       TArray<FVector4>& Points, const TArray<FLinearColor>& Colors, const TArray<float>& Widths)
 {
 	if (LinearLineData.Num() != 0 || LineMap.Num() != 0 || GetInstanceCount() != 0)
 	{
@@ -1349,4 +1408,59 @@ bool UGPUInstancedLineComponent::RemovePoints(int32 LineId, int32 StartingPointI
 	
 	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)
diff --git a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
index 712c07014229e0bda72df50de6ae415d290e59b1..9c87a461585bfb09f7d268f69f863b466586d7e6 100644
--- a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
+++ b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
@@ -145,6 +145,18 @@ public:
 	UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
 	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
@@ -335,6 +347,54 @@ public:
 	// todo
 	UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
 	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
 	UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
@@ -349,6 +409,14 @@ public:
 		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")
 	int32 GetNumberOfPointsInLine(int32 LineId) const
 	{
@@ -361,10 +429,10 @@ public:
 	UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
 	UTexture2D* PositionTexture;
 
-	UPROPERTY(BlueprintReadWrite, EditAnywhere)
+	UPROPERTY(BlueprintReadOnly, EditAnywhere)
 	int32 TextureWidth;
 
-	UPROPERTY(BlueprintReadWrite, EditAnywhere)
+	UPROPERTY(BlueprintReadOnly, EditAnywhere)
 	int32 TextureHeight;
 
 	UPROPERTY(BlueprintReadOnly, VisibleAnywhere)