first commit

This commit is contained in:
2025-07-03 19:02:47 +02:00
parent e32143bba7
commit 8d8d6f0103
324 changed files with 6415 additions and 0 deletions

View File

@ -0,0 +1,30 @@
// Copyright 2023 MrRobin. All Rights Reserved.
using UnrealBuildTool;
public class CommonTime : ModuleRules
{
public CommonTime(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[]
{
"Core",
});
PublicDependencyModuleNames.AddRange(new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"DeveloperSettings",
"UnrealEd",
"PropertyEditor",
"ClassViewer",
"InputCore",
"BlueprintGraph",
});
}
}

View File

@ -0,0 +1,46 @@
// Copyright 2023 MrRobin. All Rights Reserved.
#include "CommonTimeModule.h"
#include "Modules/ModuleManager.h"
#include "DetailCustomizations/MyDateTimeDetailCustomization.h"
#include "DetailCustomizations/MyTimespanDetailCustomization.h"
DEFINE_LOG_CATEGORY(LogCommonTime);
class FCommonTimeModule : public IModuleInterface
{
public:
void StartupModule() override
{
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>(TEXT("PropertyEditor"));
PropertyModule.RegisterCustomPropertyTypeLayout(
TEXT("Timespan"),
FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FMyTimespanDetailCustomization::MakeInstance)
);
PropertyModule.RegisterCustomPropertyTypeLayout(
TEXT("DateTime"),
FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FMyDateTimeDetailCustomization::MakeInstance)
);
PropertyModule.NotifyCustomizationModuleChanged();
}
void ShutdownModule() override
{
if (FModuleManager::Get().IsModuleLoaded(TEXT("PropertyEditor")))
{
FPropertyEditorModule& PropertyModule = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
PropertyModule.UnregisterCustomPropertyTypeLayout(TEXT("Timespan"));
PropertyModule.UnregisterCustomPropertyTypeLayout(TEXT("DateTime"));
PropertyModule.NotifyCustomizationModuleChanged();
}
}
};
IMPLEMENT_MODULE(FCommonTimeModule, CommonTime);

View File

@ -0,0 +1,395 @@
// Copyright 2023 MrRobin. All Rights Reserved.
#include "DetailCustomizations/MyDateTimeDetailCustomization.h"
#include "Containers/Array.h"
#include "Containers/UnrealString.h"
#include "DetailWidgetRow.h"
#include "Fonts/SlateFontInfo.h"
#include "HAL/PlatformCrt.h"
#include "Internationalization/Internationalization.h"
#include "Misc/Attribute.h"
#include "Misc/DateTime.h"
#include "PropertyHandle.h"
#include "Styling/AppStyle.h"
#include "Styling/ISlateStyle.h"
#include "UObject/NameTypes.h"
#include "UObject/UnrealType.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "DetailLayoutBuilder.h"
#include "Widgets/Input/SNumericEntryBox.h"
#include "Widgets/Input/SVectorInputBox.h"
#include "Widgets/Input/NumericTypeInterface.h"
#include "Widgets/Input/NumericUnitTypeInterface.inl"
#include "Math/UnitConversion.h"
// SExpanderArrow
#define LOCTEXT_NAMESPACE "MyDateTimeDetailCustomization"
/* IDetailCustomization interface
*****************************************************************************/
void FMyDateTimeDetailCustomization::CustomizeChildren(TSharedRef<IPropertyHandle> StructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
/* do nothing */
}
void FMyDateTimeDetailCustomization::CustomizeHeader(TSharedRef<IPropertyHandle> StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
PropertyHandle = StructPropertyHandle;
SAssignNew(YearEntryBox, SNumericEntryBox<double>)
.AllowSpin(true)
.MinValue(1)
.MaxValue(9999)
.MinSliderValue(1)
.MaxSliderValue(9999)
.MinFractionalDigits(0)
.MaxFractionalDigits(0)
.Font(IDetailLayoutBuilder::GetDetailFont())
.Value(this, &FMyDateTimeDetailCustomization::OnGetValue, 3)
.OnValueChanged(this, &FMyDateTimeDetailCustomization::OnValueChanged, 3)
.OnValueCommitted(this, &FMyDateTimeDetailCustomization::OnValueCommitted, 3)
.OnBeginSliderMovement(this, &FMyDateTimeDetailCustomization::OnBeginSliderMovement)
.OnEndSliderMovement(this, &FMyDateTimeDetailCustomization::OnEndSliderMovement)
.TypeInterface(MakeShareable(new TNumericUnitTypeInterface<double>(EUnit::Years)))
.LinearDeltaSensitivity(1);
SAssignNew(MonthEntryBox, SNumericEntryBox<double>)
.AllowSpin(true)
.MinValue(1)
.MaxValue(12)
.MinSliderValue(1)
.MaxSliderValue(12)
.MinFractionalDigits(0)
.MaxFractionalDigits(0)
.Font(IDetailLayoutBuilder::GetDetailFont())
.Value(this, &FMyDateTimeDetailCustomization::OnGetValue, 4)
.OnValueChanged(this, &FMyDateTimeDetailCustomization::OnValueChanged, 4)
.OnValueCommitted(this, &FMyDateTimeDetailCustomization::OnValueCommitted, 4)
.OnBeginSliderMovement(this, &FMyDateTimeDetailCustomization::OnBeginSliderMovement)
.OnEndSliderMovement(this, &FMyDateTimeDetailCustomization::OnEndSliderMovement)
.TypeInterface(MakeShareable(new TNumericUnitTypeInterface<double>(EUnit::Months)))
.LinearDeltaSensitivity(1);
SAssignNew(DayEntryBox, SNumericEntryBox<double>)
.AllowSpin(true)
.MinValue(1)
.MaxValue(31)
.MinSliderValue(1)
.MaxSliderValue(31)
.MinFractionalDigits(0)
.MaxFractionalDigits(0)
.Font(IDetailLayoutBuilder::GetDetailFont())
.Value(this, &FMyDateTimeDetailCustomization::OnGetValue, 5)
.OnValueChanged(this, &FMyDateTimeDetailCustomization::OnValueChanged, 5)
.OnValueCommitted(this, &FMyDateTimeDetailCustomization::OnValueCommitted, 5)
.OnBeginSliderMovement(this, &FMyDateTimeDetailCustomization::OnBeginSliderMovement)
.OnEndSliderMovement(this, &FMyDateTimeDetailCustomization::OnEndSliderMovement)
.TypeInterface(MakeShareable(new TNumericUnitTypeInterface<double>(EUnit::Days)))
.LinearDeltaSensitivity(1);
SAssignNew(HourEntryBox, SNumericEntryBox<double>)
.AllowSpin(true)
.MinValue(0)
.MaxValue(23)
.MinSliderValue(0)
.MaxSliderValue(23)
.MinFractionalDigits(0)
.MaxFractionalDigits(0)
.Font(IDetailLayoutBuilder::GetDetailFont())
.Value(this, &FMyDateTimeDetailCustomization::OnGetValue, 0)
.OnValueChanged(this, &FMyDateTimeDetailCustomization::OnValueChanged, 0)
.OnValueCommitted(this, &FMyDateTimeDetailCustomization::OnValueCommitted, 0)
.OnBeginSliderMovement(this, &FMyDateTimeDetailCustomization::OnBeginSliderMovement)
.OnEndSliderMovement(this, &FMyDateTimeDetailCustomization::OnEndSliderMovement)
.TypeInterface(MakeShareable(new TNumericUnitTypeInterface<double>(EUnit::Hours)))
.LinearDeltaSensitivity(1);
SAssignNew(MinuteEntryBox, SNumericEntryBox<double>)
.AllowSpin(true)
.MinValue(0)
.MaxValue(59)
.MinSliderValue(0)
.MaxSliderValue(59)
.MinFractionalDigits(0)
.MaxFractionalDigits(0)
.Font(IDetailLayoutBuilder::GetDetailFont())
.Value(this, &FMyDateTimeDetailCustomization::OnGetValue, 1)
.OnValueChanged(this, &FMyDateTimeDetailCustomization::OnValueChanged, 1)
.OnValueCommitted(this, &FMyDateTimeDetailCustomization::OnValueCommitted, 1)
.OnBeginSliderMovement(this, &FMyDateTimeDetailCustomization::OnBeginSliderMovement)
.OnEndSliderMovement(this, &FMyDateTimeDetailCustomization::OnEndSliderMovement)
.TypeInterface(MakeShareable(new TNumericUnitTypeInterface<double>(EUnit::Minutes)))
.LinearDeltaSensitivity(1);
SAssignNew(SecondEntryBox, SNumericEntryBox<double>)
.AllowSpin(true)
.MinValue(0)
.MaxValue(59)
.MinSliderValue(0)
.MaxSliderValue(59)
.MinFractionalDigits(0)
.MaxFractionalDigits(0)
.Font(IDetailLayoutBuilder::GetDetailFont())
.Value(this, &FMyDateTimeDetailCustomization::OnGetValue, 2)
.OnValueChanged(this, &FMyDateTimeDetailCustomization::OnValueChanged, 2)
.OnValueCommitted(this, &FMyDateTimeDetailCustomization::OnValueCommitted, 2)
.OnBeginSliderMovement(this, &FMyDateTimeDetailCustomization::OnBeginSliderMovement)
.OnEndSliderMovement(this, &FMyDateTimeDetailCustomization::OnEndSliderMovement)
.TypeInterface(MakeShareable(new TNumericUnitTypeInterface<double>(EUnit::Seconds)))
.LinearDeltaSensitivity(1);
HeaderRow
.NameContent()
[
StructPropertyHandle->CreatePropertyNameWidget()
]
.ValueContent()
.MinDesiredWidth(125.0f * 3.0f)
.MaxDesiredWidth(125.0f * 3.0f)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.Padding(0.0f, 0.0f, 2.0f, 0.0f)
[
YearEntryBox.ToSharedRef()
]
+ SHorizontalBox::Slot()
.Padding(2.0f, 0.0f)
[
MonthEntryBox.ToSharedRef()
]
+ SHorizontalBox::Slot()
.Padding(2.0f, 0.0f, 0.0f, 0.0f)
[
DayEntryBox.ToSharedRef()
]
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SSpacer)
.Size(FVector2D(8.0f))
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.Padding(0.0f, 0.0f, 2.0f, 0.0f)
[
HourEntryBox.ToSharedRef()
]
+ SHorizontalBox::Slot()
.Padding(2.0f, 0.0f)
[
MinuteEntryBox.ToSharedRef()
]
+ SHorizontalBox::Slot()
.Padding(2.0f, 0.0f, 0.0f, 0.0f)
[
SecondEntryBox.ToSharedRef()
]
]
];
}
/* FMyDateTimeDetailCustomization callbacks
*****************************************************************************/
TOptional<double> FMyDateTimeDetailCustomization::OnGetValue(int32 Index) const
{
TArray<void*> RawData;
PropertyHandle->AccessRawData(RawData);
if (RawData.Num() != 1)
return TOptional<double>();
if (RawData[0] == nullptr)
return TOptional<double>();
auto* DateTime = ((FDateTime*)RawData[0]);
switch (Index)
{
case 0:
return TOptional<double>(DateTime->GetHour());
case 1:
return TOptional<double>(DateTime->GetMinute());
case 2:
return TOptional<double>(DateTime->GetSecond());
case 3:
return TOptional<double>(DateTime->GetYear());
case 4:
return TOptional<double>(DateTime->GetMonth());
case 5:
return TOptional<double>(DateTime->GetDay());
default:
return TOptional<double>();
}
}
void FMyDateTimeDetailCustomization::OnBeginSliderMovement()
{
bIsUsingSlider = true;
GEditor->BeginTransaction(
FText::Format(
NSLOCTEXT("MyDateTimeDetailCustomization", "SetDateTimeProperty", "Edit {0}"),
PropertyHandle->GetPropertyDisplayName())
);
}
void FMyDateTimeDetailCustomization::OnEndSliderMovement(double NewValue)
{
bIsUsingSlider = false;
GEditor->EndTransaction();
}
void FMyDateTimeDetailCustomization::OnValueCommitted(double NewValue, ETextCommit::Type CommitType, int32 Index)
{
NewValue = FMath::CeilToDouble(NewValue);
TArray<void*> RawData;
PropertyHandle->AccessRawData(RawData);
PropertyHandle->NotifyPreChange();
for (auto RawDataInstance : RawData)
{
auto* DateTime = (FDateTime*)RawDataInstance;
int32 Year = DateTime->GetYear();
int32 Month = DateTime->GetMonth();
int32 Day = DateTime->GetDay();
int32 Hour = DateTime->GetHour();
int32 Minute = DateTime->GetMinute();
int32 Second = DateTime->GetSecond();
int32 MaxDays = FDateTime::DaysInMonth(Year, Month);
switch (Index)
{
case 0:
*DateTime = FDateTime(Year, Month, Day > MaxDays ? MaxDays : Day, NewValue, Minute, Second);
break;
case 1:
*DateTime = FDateTime(Year, Month, Day > MaxDays ? MaxDays : Day, Hour, NewValue, Second);
break;
case 2:
*DateTime = FDateTime(Year, Month, Day > MaxDays ? MaxDays : Day, Hour, Minute, NewValue);
break;
case 3:
{
MaxDays = FDateTime::DaysInMonth(NewValue, Month);
*DateTime = FDateTime(NewValue, Month, Day > MaxDays ? MaxDays : Day, Hour, Minute, Second);
}
break;
case 4:
{
MaxDays = FDateTime::DaysInMonth(Year, NewValue);
*DateTime = FDateTime(Year, NewValue, Day > MaxDays ? MaxDays : Day, Hour, Minute, Second);
}
break;
case 5:
*DateTime = FDateTime(Year, Month, NewValue > MaxDays ? MaxDays : NewValue, Hour, Minute, Second);
break;
default:
break;
}
}
PropertyHandle->NotifyPostChange(EPropertyChangeType::ValueSet);
PropertyHandle->NotifyFinishedChangingProperties();
}
void FMyDateTimeDetailCustomization::OnValueChanged(double NewValue, int32 Index)
{
if (!bIsUsingSlider)
return;
NewValue = FMath::CeilToDouble(NewValue);
TArray<void*> RawData;
PropertyHandle->AccessRawData(RawData);
PropertyHandle->NotifyPreChange();
for (auto RawDataInstance : RawData)
{
auto* DateTime = (FDateTime*)RawDataInstance;
int32 Year = DateTime->GetYear();
int32 Month = DateTime->GetMonth();
int32 Day = DateTime->GetDay();
int32 Hour = DateTime->GetHour();
int32 Minute = DateTime->GetMinute();
int32 Second = DateTime->GetSecond();
int32 MaxDays = FDateTime::DaysInMonth(Year, Month);
switch (Index)
{
case 0:
*DateTime = FDateTime(Year, Month, Day > MaxDays ? MaxDays : Day, NewValue, Minute, Second);
break;
case 1:
*DateTime = FDateTime(Year, Month, Day > MaxDays ? MaxDays : Day, Hour, NewValue, Second);
break;
case 2:
*DateTime = FDateTime(Year, Month, Day > MaxDays ? MaxDays : Day, Hour, Minute, NewValue);
break;
case 3:
{
MaxDays = FDateTime::DaysInMonth(NewValue, Month);
*DateTime = FDateTime(NewValue, Month, Day > MaxDays ? MaxDays : Day, Hour, Minute, Second);
}
break;
case 4:
{
MaxDays = FDateTime::DaysInMonth(Year, NewValue);
*DateTime = FDateTime(Year, NewValue, Day > MaxDays ? MaxDays : Day, Hour, Minute, Second);
}
break;
case 5:
*DateTime = FDateTime(Year, Month, NewValue > MaxDays ? MaxDays : NewValue, Hour, Minute, Second);
break;
default:
break;
}
}
PropertyHandle->NotifyPostChange(EPropertyChangeType::ValueSet);
PropertyHandle->NotifyFinishedChangingProperties();
}
#undef LOCTEXT_NAMESPACE

View File

@ -0,0 +1,256 @@
// Copyright 2023 MrRobin. All Rights Reserved.
#include "DetailCustomizations/MyTimespanDetailCustomization.h"
#include "Containers/Array.h"
#include "Containers/UnrealString.h"
#include "DetailWidgetRow.h"
#include "Fonts/SlateFontInfo.h"
#include "HAL/PlatformCrt.h"
#include "Internationalization/Internationalization.h"
#include "Misc/Attribute.h"
#include "Misc/Timespan.h"
#include "PropertyHandle.h"
#include "Styling/AppStyle.h"
#include "Styling/ISlateStyle.h"
#include "UObject/NameTypes.h"
#include "UObject/UnrealType.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "DetailLayoutBuilder.h"
#include "Widgets/Input/SNumericEntryBox.h"
#include "Widgets/Input/SVectorInputBox.h"
#include "Widgets/Input/NumericTypeInterface.h"
#include "Widgets/Input/NumericUnitTypeInterface.inl"
#include "Math/UnitConversion.h"
#define LOCTEXT_NAMESPACE "MyTimespanDetailCustomization"
/* IDetailCustomization interface
*****************************************************************************/
void FMyTimespanDetailCustomization::CustomizeChildren(
TSharedRef<IPropertyHandle> StructPropertyHandle,
class IDetailChildrenBuilder& StructBuilder,
IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
/* do nothing */
}
void FMyTimespanDetailCustomization::CustomizeHeader(
TSharedRef<IPropertyHandle> StructPropertyHandle,
class FDetailWidgetRow& HeaderRow,
IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
PropertyHandle = StructPropertyHandle;
SAssignNew(HourEntryBox, SNumericEntryBox<double>)
.AllowSpin(true)
.MinValue(0)
.MaxValue(23)
.MinSliderValue(0)
.MaxSliderValue(23)
.MinFractionalDigits(0)
.MaxFractionalDigits(0)
.Font(IDetailLayoutBuilder::GetDetailFont())
.Value(this, &FMyTimespanDetailCustomization::OnGetValue, 0)
.OnValueChanged(this, &FMyTimespanDetailCustomization::OnValueChanged, 0)
.OnValueCommitted(this, &FMyTimespanDetailCustomization::OnValueCommitted, 0)
.OnBeginSliderMovement(this, &FMyTimespanDetailCustomization::OnBeginSliderMovement)
.OnEndSliderMovement(this, &FMyTimespanDetailCustomization::OnEndSliderMovement)
.TypeInterface(MakeShareable(new TNumericUnitTypeInterface<double>(EUnit::Hours)))
.LinearDeltaSensitivity(1);
SAssignNew(MinuteEntryBox, SNumericEntryBox<double>)
.AllowSpin(true)
.MinValue(0)
.MaxValue(59)
.MinSliderValue(0)
.MaxSliderValue(59)
.MinFractionalDigits(0)
.MaxFractionalDigits(0)
.Font(IDetailLayoutBuilder::GetDetailFont())
.Value(this, &FMyTimespanDetailCustomization::OnGetValue, 1)
.OnValueChanged(this, &FMyTimespanDetailCustomization::OnValueChanged, 1)
.OnValueCommitted(this, &FMyTimespanDetailCustomization::OnValueCommitted, 1)
.OnBeginSliderMovement(this, &FMyTimespanDetailCustomization::OnBeginSliderMovement)
.OnEndSliderMovement(this, &FMyTimespanDetailCustomization::OnEndSliderMovement)
.TypeInterface(MakeShareable(new TNumericUnitTypeInterface<double>(EUnit::Minutes)))
.LinearDeltaSensitivity(1);
SAssignNew(SecondEntryBox, SNumericEntryBox<double>)
.AllowSpin(true)
.MinValue(0)
.MaxValue(59)
.MinSliderValue(0)
.MaxSliderValue(59)
.MinFractionalDigits(0)
.MaxFractionalDigits(0)
.Font(IDetailLayoutBuilder::GetDetailFont())
.Value(this, &FMyTimespanDetailCustomization::OnGetValue, 2)
.OnValueChanged(this, &FMyTimespanDetailCustomization::OnValueChanged, 2)
.OnValueCommitted(this, &FMyTimespanDetailCustomization::OnValueCommitted, 2)
.OnBeginSliderMovement(this, &FMyTimespanDetailCustomization::OnBeginSliderMovement)
.OnEndSliderMovement(this, &FMyTimespanDetailCustomization::OnEndSliderMovement)
.TypeInterface(MakeShareable(new TNumericUnitTypeInterface<double>(EUnit::Seconds)))
.LinearDeltaSensitivity(1);
HeaderRow
.NameContent()
[
StructPropertyHandle->CreatePropertyNameWidget()
]
.ValueContent()
.MinDesiredWidth(125.0f * 3.0f)
.MaxDesiredWidth(125.0f * 3.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.Padding(0.0f)
[
HourEntryBox.ToSharedRef()
]
+ SHorizontalBox::Slot()
.Padding(2.5f, 0.0f)
[
MinuteEntryBox.ToSharedRef()
]
+ SHorizontalBox::Slot()
.Padding(0.0f)
[
SecondEntryBox.ToSharedRef()
]
];
}
/* FMyTimespanDetailCustomization callbacks
*****************************************************************************/
TOptional<double> FMyTimespanDetailCustomization::OnGetValue(int32 Index) const
{
TArray<void*> RawData;
PropertyHandle->AccessRawData(RawData);
if (RawData.Num() != 1)
return TOptional<double>();
if (RawData[0] == nullptr)
return TOptional<double>();
auto* Timespan = ((FTimespan*)RawData[0]);
switch (Index)
{
case 0:
return TOptional<double>(Timespan->GetHours());
case 1:
return TOptional<double>(Timespan->GetMinutes());
case 2:
return TOptional<double>(Timespan->GetSeconds());
default:
return TOptional<double>();
}
}
void FMyTimespanDetailCustomization::OnBeginSliderMovement()
{
bIsUsingSlider = true;
GEditor->BeginTransaction(FText::Format(NSLOCTEXT("MyTimespanDetailCustomization", "SetTimespanProperty", "Edit {0}"), PropertyHandle->GetPropertyDisplayName()));
}
void FMyTimespanDetailCustomization::OnEndSliderMovement(double NewValue)
{
bIsUsingSlider = false;
GEditor->EndTransaction();
}
void FMyTimespanDetailCustomization::OnValueCommitted(double NewValue, ETextCommit::Type CommitType, int32 Index)
{
NewValue = FMath::CeilToDouble(NewValue);
TArray<void*> RawData;
PropertyHandle->AccessRawData(RawData);
PropertyHandle->NotifyPreChange();
for (auto RawDataInstance : RawData)
{
auto* Timespan = (FTimespan*)RawDataInstance;
int32 Hours = Timespan->GetHours();
int32 Minutes = Timespan->GetMinutes();
int32 Seconds = Timespan->GetSeconds();
switch (Index)
{
case 0:
*Timespan = FTimespan(NewValue, Minutes, Seconds);
break;
case 1:
*Timespan = FTimespan(Hours, NewValue, Seconds);
break;
case 2:
*Timespan = FTimespan(Hours, Minutes, NewValue);
break;
default:
break;
}
}
PropertyHandle->NotifyPostChange(EPropertyChangeType::ValueSet);
PropertyHandle->NotifyFinishedChangingProperties();
}
void FMyTimespanDetailCustomization::OnValueChanged(double NewValue, int32 Index)
{
if (!bIsUsingSlider)
return;
NewValue = FMath::CeilToDouble(NewValue);
TArray<void*> RawData;
PropertyHandle->AccessRawData(RawData);
PropertyHandle->NotifyPreChange();
for (auto RawDataInstance : RawData)
{
auto* Timespan = (FTimespan*)RawDataInstance;
int32 Hours = Timespan->GetHours();
int32 Minutes = Timespan->GetMinutes();
int32 Seconds = Timespan->GetSeconds();
switch (Index)
{
case 0:
*Timespan = FTimespan(NewValue, Minutes, Seconds);
break;
case 1:
*Timespan = FTimespan(Hours, NewValue, Seconds);
break;
case 2:
*Timespan = FTimespan(Hours, Minutes, NewValue);
break;
default:
break;
}
}
PropertyHandle->NotifyPostChange(EPropertyChangeType::ValueSet);
PropertyHandle->NotifyFinishedChangingProperties();
}
#undef LOCTEXT_NAMESPACE

View File

@ -0,0 +1,7 @@
// Copyright 2023 MrRobin. All Rights Reserved.
#pragma once
#include "Logging/LogMacros.h"
DECLARE_LOG_CATEGORY_EXTERN(LogCommonTime, Log, All);

View File

@ -0,0 +1,58 @@
// Copyright 2023 MrRobin. All Rights Reserved.
#pragma once
#include "IPropertyTypeCustomization.h"
#include "Internationalization/Text.h"
#include "Styling/SlateColor.h"
#include "Templates/SharedPointer.h"
#include "Types/SlateEnums.h"
class IPropertyHandle;
class SEditableTextBox;
/**
* Implements a details view customization for the FDateTime structure.
*/
class FMyDateTimeDetailCustomization
: public IPropertyTypeCustomization
{
public:
public:
/**
* Creates an instance of this class.
*
* @return The new instance.
*/
static TSharedRef<IPropertyTypeCustomization> MakeInstance()
{
return MakeShareable(new FMyDateTimeDetailCustomization());
}
public:
// IPropertyTypeCustomization interface
void CustomizeChildren(TSharedRef<class IPropertyHandle> StructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override;
void CustomizeHeader(TSharedRef<class IPropertyHandle> StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override;
private:
TOptional<double> OnGetValue(int32 Index) const;
void OnValueCommitted(double NewValue, ETextCommit::Type CommitType, int32 Index);
void OnValueChanged(double NewValue, int32 Index);
void OnBeginSliderMovement();
void OnEndSliderMovement(double NewValue);
private:
/** Holds a handle to the property being edited. */
TSharedPtr<IPropertyHandle> PropertyHandle;
/** True if a value is being changed by dragging a slider */
bool bIsUsingSlider;
TSharedPtr<SWidget> YearEntryBox;
TSharedPtr<SWidget> MonthEntryBox;
TSharedPtr<SWidget> DayEntryBox;
TSharedPtr<SWidget> HourEntryBox;
TSharedPtr<SWidget> MinuteEntryBox;
TSharedPtr<SWidget> SecondEntryBox;
};

View File

@ -0,0 +1,54 @@
// Copyright 2023 MrRobin. All Rights Reserved.
#pragma once
#include "IPropertyTypeCustomization.h"
#include "Internationalization/Text.h"
#include "Styling/SlateColor.h"
#include "Templates/SharedPointer.h"
#include "Types/SlateEnums.h"
class IPropertyHandle;
class SEditableTextBox;
/**
* Implements a details view customization for the FTimespan structure.
*/
class FMyTimespanDetailCustomization
: public IPropertyTypeCustomization
{
public:
/**
* Creates an instance of this class.
*
* @return The new instance.
*/
static TSharedRef<IPropertyTypeCustomization> MakeInstance()
{
return MakeShareable(new FMyTimespanDetailCustomization());
}
public:
// IPropertyTypeCustomization interface
void CustomizeChildren(TSharedRef<class IPropertyHandle> StructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override;
void CustomizeHeader(TSharedRef<class IPropertyHandle> StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override;
private:
TOptional<double> OnGetValue(int32 Index) const;
void OnValueCommitted(double NewValue, ETextCommit::Type CommitType, int32 Index);
void OnValueChanged(double NewValue, int32 Index);
void OnBeginSliderMovement();
void OnEndSliderMovement(double NewValue);
private:
/** Holds a handle to the property being edited. */
TSharedPtr<IPropertyHandle> PropertyHandle;
/** True if a value is being changed by dragging a slider */
bool bIsUsingSlider;
TSharedPtr<SWidget> HourEntryBox;
TSharedPtr<SWidget> MinuteEntryBox;
TSharedPtr<SWidget> SecondEntryBox;
};