Is the detail view issue resolved?

I found that in the detail view, such as UMG, when I copied a Slot, it worked, but when I clicked compile, it returned to the state before I copied the attribute. Unless I manually input and change another attribute after copying the Slot, the attribute I copied can be saved.

At the same time, in C++, I found

There is a similar problem with the custom detail view. After I add a button, the execution event will not work. But once I manually rewrite a property, the function just now will be triggered.

.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "IDetailCustomization.h"
#include "Components/SplineComponent.h"
#include "ActorComponents/SplineStretchComponent.h"

class EDITOR_API USplineStretchComponentDetails : public IDetailCustomization
{
public:
	// 静态方法,用于注册该自定义细节类
	static TSharedRef<IDetailCustomization> MakeInstance();

	// 覆盖 CustomizeDetails,用于定制细节视图
	virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;
	


	FReply OnResetSplineClicked();

	FReply OnSetSplineClicked();
	FReply OnGenerateClicked();
	FReply OnAverageClicked();
	FReply OnPutOnClicked();
	FReply OnRecordSplinePointsClicked();





	void OnSplineComponentSelected(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo);


	// 生成下拉框项
	TSharedRef<SWidget> GenerateSplineComponentWidget(TSharedPtr<FString> InOption);

	// 获取当前显示的 SplineComponent 名称
	FText GetSelectedSplineComponentText() const;

	FReply OnSetHeightClicked();


	TArray<TSharedPtr<FString>> SplineComponentOptions;  

	TArray<USplineComponent*> SplineComponents;

	USplineStretchComponent* SplineStretchComponent;
	// 下拉框
	TSharedPtr<SComboBox<TSharedPtr<FString>>> SplineComponentComboBox;

	// 显示文本
	TSharedPtr<STextBlock> SplineComponentTextBlock;
	TSharedPtr<STextBlock> ResetSplineTextBlock;

	TSharedPtr<SButton> SetSplineButton;
	TSharedPtr<SButton> ResetSplineButton;
	TSharedPtr<SButton> GenerateButton;
	TSharedPtr<SButton> AverageButton;
	TSharedPtr<SButton> PutOnButton;
	TSharedPtr<SButton>RecordSplinePointsButton;
	TSharedPtr<SButton>SetHeightButton;



};

.cpp:

// Fill out your copyright notice in the Description page of Project Settings.
#include "Details/SplineStretchComponentDetails.h"
#include "DetailLayoutBuilder.h"
#include "DetailCategoryBuilder.h"
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Input/SButton.h"
#include "IDetailChildrenBuilder.h"
#include "Widgets/Input/SButton.h"
#include "DetailWidgetRow.h"


#define LOCTEXT_NAMESPACE "FSplineStretchComponentDetails"



TSharedRef<IDetailCustomization> USplineStretchComponentDetails::MakeInstance()
{
    // 创建一个实例并返回
    return MakeShareable(new USplineStretchComponentDetails);
}


void USplineStretchComponentDetails::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
    IDetailCategoryBuilder& Category = DetailBuilder.EditCategory("Spline");
  
    // 清空数组
    SplineComponents.Empty();
    SplineComponentOptions.Empty();

    // 重置指针
    SplineStretchComponent = nullptr;
    SplineComponentComboBox.Reset();
    SplineComponentTextBlock.Reset();
    ResetSplineTextBlock.Reset();
    PutOnButton.Reset();
    ResetSplineButton.Reset();
    
    // 获取正在定制的对象(即当前正在打开的 USplineStretchComponent)
    TArray<TWeakObjectPtr<UObject>> Objects;
    DetailBuilder.GetObjectsBeingCustomized(Objects);




    if (Objects.Num() > 0)
    {
        SplineStretchComponent = Cast<USplineStretchComponent>(Objects[0].Get());
        if (!SplineStretchComponent)
        {
            UE_LOG(LogTemp, Warning, TEXT("Failed to cast object to USplineStretchComponent."));
            return;
        }


        if (SplineStretchComponent && SplineStretchComponent->SelectedActor != nullptr)
        {
            SplineStretchComponent->SelectedActor->GetComponents(SplineComponents);

            SplineComponentOptions.Add(MakeShareable(new FString("None"))); // 第一个选项为 None

            for (USplineComponent* SplineComponent : SplineComponents)
            {
                if (SplineComponent)
                {
                    SplineComponentOptions.Add(MakeShareable(new FString(SplineComponent->GetName())));
                }
            }

            // 当前选中的 SplineComponent
           /* TSharedPtr<FString> CurrentlySelectedOption = MakeShareable(new FString("None"));
            if (!SplineStretchComponent->SplineComponentName.IsEmpty())
            {
                CurrentlySelectedOption = MakeShareable(new FString(SplineStretchComponent->SplineComponentName));
            }*/

            // 创建文本框和下拉框
            SplineComponentTextBlock = SNew(STextBlock)
                .Text(LOCTEXT("SelectSplineComponent", "Spline Component"));

            SplineComponentComboBox = SNew(SComboBox<TSharedPtr<FString>>)
                .OptionsSource(&SplineComponentOptions)
                //.InitiallySelectedItem(CurrentlySelectedOption)
                .OnGenerateWidget(this, &USplineStretchComponentDetails::GenerateSplineComponentWidget)
                .OnSelectionChanged(this, &USplineStretchComponentDetails::OnSplineComponentSelected)
                .Content()
                [
                    SNew(STextBlock)
                        .Text(this, &USplineStretchComponentDetails::GetSelectedSplineComponentText)
                ];

            // 添加下拉框到细节面板
            Category.AddCustomRow(LOCTEXT("SplineComponent", "Spline Component"))
                .NameContent()
                [
                    SplineComponentTextBlock.ToSharedRef()
                ]
                .ValueContent()
                [
                    SplineComponentComboBox.ToSharedRef()
                ];


            // 创建 SetSpline 按钮
            TSharedPtr<STextBlock> SetSplineTextBlock = SNew(STextBlock)
                .Text(LOCTEXT("SetSplineLabel", "Set Spline"));

            SetSplineButton = SNew(SButton)
                .Text(LOCTEXT("SetSplineButton", "Set Spline"))
                .HAlign(HAlign_Center)
                .OnClicked(this, &USplineStretchComponentDetails::OnSetSplineClicked);

            // 添加 Set Spline 按钮到细节面板
            Category.AddCustomRow(LOCTEXT("SetSpline", "Set Spline"))
                .NameContent()
                [
                    SetSplineTextBlock.ToSharedRef()
                ]
                .ValueContent()
                [
                    SetSplineButton.ToSharedRef()
                ];


            TSharedPtr<STextBlock> GenerateTextBlock = SNew(STextBlock)
                .Text(LOCTEXT("GenerateLabel", "Generate"));

            GenerateButton = SNew(SButton)
                .Text(LOCTEXT("GenerateButton", "Generate"))
                .HAlign(HAlign_Center)
                .OnClicked(this, &USplineStretchComponentDetails::OnGenerateClicked);

            // 添加 Generate 按钮到细节面板
            Category.AddCustomRow(LOCTEXT("Generate", "Generate"))
                .NameContent()
                [
                    GenerateTextBlock.ToSharedRef()
                ]
                .ValueContent()
                [
                    GenerateButton.ToSharedRef()
                ];

            // 创建 Average 按钮
            TSharedPtr<STextBlock> AverageTextBlock = SNew(STextBlock)
                .Text(LOCTEXT("AverageLabel", "Average"));

            AverageButton = SNew(SButton)
                .Text(LOCTEXT("AverageButton", "Average"))
                .HAlign(HAlign_Center)
                .OnClicked(this, &USplineStretchComponentDetails::OnAverageClicked);

            // 添加 Average 按钮到细节面板
            Category.AddCustomRow(LOCTEXT("Average", "Average"))
                .NameContent()
                [
                    AverageTextBlock.ToSharedRef()
                ]
                .ValueContent()
                [
                    AverageButton.ToSharedRef()
                ];

            // 创建 Put On 按钮
            TSharedPtr<STextBlock> PutOnTextBlock = SNew(STextBlock)
                .Text(LOCTEXT("PutOnLabel", "Put On"));

            PutOnButton = SNew(SButton)
                .Text(LOCTEXT("PutOnButton", "Put On"))
                .HAlign(HAlign_Center)
                .OnClicked(this, &USplineStretchComponentDetails::OnPutOnClicked);

            // 添加按钮到细节面板
            Category.AddCustomRow(LOCTEXT("PutOn", "Put On"))
                .NameContent()
                [
                    PutOnTextBlock.ToSharedRef()
                ]
                .ValueContent()
                [
                    PutOnButton.ToSharedRef()
                ];

            // 创建 Record Spline Points 按钮
            TSharedPtr<STextBlock> RecordTextBlock = SNew(STextBlock)
                .Text(LOCTEXT("RecordSplinePointsLabel", "Record Spline Points"));

            RecordSplinePointsButton = SNew(SButton)
                .Text(LOCTEXT("RecordButton", "Record Spline Points"))
                .HAlign(HAlign_Center)
                .OnClicked(this, &USplineStretchComponentDetails::OnRecordSplinePointsClicked);

            // 添加 Record Spline Points 按钮到细节面板
            Category.AddCustomRow(LOCTEXT("RecordSplinePoints", "Record Spline Points"))
                .NameContent()
                [
                    RecordTextBlock.ToSharedRef()
                ]
                .ValueContent()
                [
                    RecordSplinePointsButton.ToSharedRef()
                ];


            TSharedPtr<STextBlock> SetHeightTextBlock = SNew(STextBlock)
                .Text(LOCTEXT("SetHeightLabel", "Set Height"));

            SetHeightButton = SNew(SButton)
                .Text(LOCTEXT("SetHeightButton", "Set Height"))
                .HAlign(HAlign_Center)
                .OnClicked(this, &USplineStretchComponentDetails::OnSetHeightClicked);

            // 添加 Set Height 按钮到细节面板
            Category.AddCustomRow(LOCTEXT("SetHeight", "Set Height"))
                .NameContent()
                [
                    SetHeightTextBlock.ToSharedRef()
                ]
                .ValueContent()
                [
                    SetHeightButton.ToSharedRef()
                ];

        
        }
    }
}



FReply USplineStretchComponentDetails::OnResetSplineClicked()
{
    if (SplineStretchComponent)
    {
        SplineStretchComponent->ResetSpline();
    }
    return FReply::Handled();
}



FReply USplineStretchComponentDetails::OnSetSplineClicked()
{
    if (!SplineStretchComponent)
        return FReply::Handled();

    TSharedPtr<FString> NewSelection = SplineComponentComboBox->GetSelectedItem();

    if (!NewSelection.IsValid())
    {
        UE_LOG(LogTemp, Warning, TEXT("NewSelection is nullptr."));
        return FReply::Handled();
    }
    else
    {
        if (*NewSelection == "None")
        {
            SplineStretchComponent->SplineComponent = nullptr;
        }
        else
        {
            // 遍历找到与名称匹配的 SplineComponent
            for (UActorComponent* Component : SplineStretchComponent->SelectedActor->GetComponents())
            {
                // 尝试将 Component 转换为 USplineComponent
                if (USplineComponent* SplineComponent = Cast<USplineComponent>(Component))
                {
                    if (SplineComponent && SplineComponent->GetName() == *NewSelection)
                    {
                        SplineStretchComponent->SplineComponent = SplineComponent;
                        SplineStretchComponent->SplineComponentName = SplineComponent->GetName();
                        break;
                    }
                }
            }
        }
    }
    return FReply::Handled();
}

FReply USplineStretchComponentDetails::OnGenerateClicked()
{
    if (!SplineStretchComponent)
        return FReply::Handled();
    SplineStretchComponent->UpdateSplineFromDataTable();
    return FReply::Handled();
}

FReply USplineStretchComponentDetails::OnAverageClicked()
{
    if (!SplineStretchComponent)
        return FReply::Handled();
    SplineStretchComponent->AverageResetPoint();
    return FReply::Handled();
}

FReply USplineStretchComponentDetails::OnPutOnClicked()
{
    if (!SplineStretchComponent)
        return FReply::Handled();
    SplineStretchComponent->PutOn();
    return FReply::Handled();
}

FReply USplineStretchComponentDetails::OnRecordSplinePointsClicked()
{
    if (!SplineStretchComponent || !SplineStretchComponent->SplineComponent)
    {
        UE_LOG(LogTemp, Warning, TEXT("Spline component is not valid."));
        return FReply::Handled();
    }

    // 清空之前记录的点
    SplineStretchComponent->SplinePointsPositions.Empty();

    // 遍历样条线的所有点并记录位置
    int32 NumPoints = SplineStretchComponent->SplineComponent->GetNumberOfSplinePoints();
    for (int32 i = 0; i < NumPoints; ++i)
    {
        FVector PointLocation = SplineStretchComponent->SplineComponent->GetLocationAtSplinePoint(i, ESplineCoordinateSpace::World);
        SplineStretchComponent->SplinePointsPositions.Add(PointLocation);
    }

    UE_LOG(LogTemp, Log, TEXT("Recorded %d spline points."), SplineStretchComponent->SplinePointsPositions.Num());

    return FReply::Handled();
}



void USplineStretchComponentDetails::OnSplineComponentSelected(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo)
{
    if (NewSelection.IsValid())
    {
        SplineStretchComponent->SplineComponentName = *NewSelection;
    }
    

}


   


TSharedRef<SWidget> USplineStretchComponentDetails::GenerateSplineComponentWidget(TSharedPtr<FString> InOption)
{
    return SNew(STextBlock).Text(FText::FromString(*InOption));
}

FText USplineStretchComponentDetails::GetSelectedSplineComponentText() const
{
    TSharedPtr<FString> SelectedItem = SplineComponentComboBox->GetSelectedItem();

    // 如果选项有效,返回选中的文本
    if (SelectedItem.IsValid())
    {
        return FText::FromString(*SelectedItem);
    }

    if (!SplineStretchComponent->SplineComponentName.IsEmpty())
    {
        return FText::FromString(SplineStretchComponent->SplineComponentName);
    }
    else
    {
        return FText::FromString(TEXT("None"));
    }

}

FReply USplineStretchComponentDetails::OnSetHeightClicked()
{
  /*  if (!SplineStretchComponent || !SplineStretchComponent->SplineComponent)
    {
        UE_LOG(LogTemp, Warning, TEXT("Spline component is not valid."));
        return FReply::Handled();
    }

    SplineStretchComponent->SetHeight()*/;
    return FReply::Handled();
}
#undef LOCTEXT_NAMESPACE