This commit is contained in:
Sch 2023-08-11 10:28:49 +08:00
parent 40d24a517b
commit 88b1288d3c
16 changed files with 276 additions and 84 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 B

After

Width:  |  Height:  |  Size: 841 B

View File

@ -31,5 +31,5 @@ AMainHUD::AMainHUD()
AMainHUD::~AMainHUD()
{
FCutButtonStyle::Shutdown();
// FCutButtonStyle::Shutdown();
}

View File

@ -87,68 +87,38 @@ void FUtils::CreateDefaultTimelineSave(const FString& SavedPath, const FTimeline
void FUtils::TrackEncodeVideo(const FTrackData& TrackData, const FString& ExportPath)
{
if (TrackData.ClipData.Num() == 0)
return;
AVFormatContext *outctx = NULL;
AVStream *outstream = NULL;
AVCodecContext *outcodecctx = NULL;
AVCodec *outcodec = NULL;
avformat_alloc_output_context2(&outctx, NULL, NULL, "output.mp4");
outcodec = avcodec_find_encoder(AV_CODEC_ID_H264);
outstream = avformat_new_stream(outctx, outcodec);
outcodecctx = avcodec_alloc_context3(outcodec);
TArray<FClipData> ClipData = TrackData.ClipData;
ClipData.Sort([](const FClipData& A, const FClipData& B) {return A.ClipStartFrame < B.ClipStartFrame; });
// 对于每个AVFrame
AVFrame *frame = NULL;
int32 i = 0;
for (FClipData& TempClipData : ClipData)
{
// 先从 ClipData 中读取这个 Clip 的视频数据。
if (TempClipData.ResourcePropertyDataPtr->Context)
{
FTimespan EndTimespan = FTimespan::FromSeconds(TempClipData.VideoEndFrame / FGlobalData::GlobalFPS);
FTimespan StartTimespan = FTimespan::FromSeconds(TempClipData.VideoStartFrame / FGlobalData::GlobalFPS);
FString StartTime = FString::Printf(TEXT("%02d:%02d:%02d"), StartTimespan.GetHours(), StartTimespan.GetMinutes(), StartTimespan.GetSeconds());
FString EndTime = FString::Printf(TEXT("%02d:%02d:%02d"), EndTimespan.GetHours(), EndTimespan.GetMinutes(), EndTimespan.GetSeconds());
FString InputFile = TempClipData.ResourcePropertyDataPtr->MoviePath;
FString OutputFile = FPaths::ConvertRelativePathToFull((FPaths::Combine(FPaths::ProjectDir(), TEXT("output.mp4"))));
// 给定一个路径,创建所有不存在的文件夹
FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*(ExportPath / FString::FromInt(i)));
FString OutputFile = FPaths::ConvertRelativePathToFull(ExportPath / FString::FromInt(i) + TEXT(".mp4"));
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, OutputFile);
int32 StartFrame = (TempClipData.VideoStartFrame) % static_cast<int>(FGlobalData::GlobalFPS);;
int32 EndFrame = (TempClipData.VideoEndFrame) % static_cast<int>(FGlobalData::GlobalFPS);
//
// GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("StartFrame: %d, EndFrame: %d"), StartFrame, EndFrame));
// //输出文件名字
// GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("OutputFile: %s"), *OutputFile));
// //输入文件名字
// GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("InputFile: %s"), *InputFile));
// //开始时间
// GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("StartTime: %s"), *StartTime));
// //结束时间
// GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("EndTime: %s"), *EndTime));
// 构造FFmpeg命令
FString Command = FString::Printf(TEXT("-y -i %s -ss %s -to %s -c copy %s"),
*InputFile, *StartTime, *EndTime, *OutputFile);
FString FFmpegPath = FPaths::ConvertRelativePathToFull(FPaths::ProjectDir() / TEXT("Binaries") / TEXT("Win64") / TEXT("ffmpeg.exe"));
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FFmpegPath + " " + FString::Printf(TEXT("%s"), *Command));
// FFmpeg的路径需要根据实际情况修改
// 创建进程
FPlatformProcess::CreateProc(*FFmpegPath, *Command, true, false, false, nullptr, 0, nullptr, nullptr);
FPlatformProcess::CreateProc(*GetFfmepg(), *Command, true, false, false, nullptr, 0, nullptr, nullptr);
}
i++;
}
@ -169,6 +139,11 @@ void FUtils::TrackEncodeVideo(const FTrackData& TrackData, const FString& Export
}
FString FUtils::GetFfmepg()
{
return FPaths::ConvertRelativePathToFull(FPaths::ProjectDir() / TEXT("Binaries") / TEXT("Win64") / TEXT("ffmpeg.exe"));
}
FSaveModifier::FSaveModifier(const FString& FullSavedPath)
{

View File

@ -56,6 +56,12 @@ public:
.SetNormal(FSlateImageBrush(*FUtils::GetResourcesPath("CurtainNormal.png", true), FVector2D(257, 32), FLinearColor(42.0f /255, 42.0f /255, 42.0f /255, 1.0f)))
.SetHovered(FSlateBoxBrush(*FUtils::GetResourcesPath("CurtainHover.png", true), FMargin(1.0), FLinearColor(46.0 /255,48.0/255,54.0/255,1.0f)))
.SetPressed(FSlateBoxBrush(*FUtils::GetResourcesPath("CurtainSelected.png", true), FMargin(1.0), FLinearColor(88.0/255,96.0/255,121.0/255,1.0f)));
static FString GetFfmepg();
};
class FSaveModifier

View File

@ -361,8 +361,8 @@ void SEffectCardGroup::CallRender()
})
]
+ SOverlay::Slot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(SBox)
.WidthOverride(32)

View File

@ -5,6 +5,7 @@
#include "SlateOptMacros.h"
#include "Cut5/Utils/Utils.h"
#include "Cut5/Widgets/Style/CutButtonWidgetStyle.h"
#include "Widgets/Input/SComboBox.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
@ -33,8 +34,8 @@ void SEffectPreset::Construct(const FArguments& InArgs)
ChildSlot
[
SNew(SBox)
.WidthOverride(76)
.HeightOverride(76)
.WidthOverride(80)
.HeightOverride(80)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.Padding(2)
@ -45,6 +46,7 @@ void SEffectPreset::Construct(const FArguments& InArgs)
.VAlign(VAlign_Fill)
[
SNew(SButton)
.ButtonStyle(FCutButtonStyle::Get(), "Preset.PresetButton")
.ClickMethod(EButtonClickMethod::MouseDown)
.OnClicked_Lambda([this]()
{

View File

@ -172,9 +172,13 @@ void SCustomInputPanel::Construct(const FArguments& InArgs)
+ SWidgetSwitcher::Slot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.Padding(16, 0, 0, 0)
.Padding(8, 13, 0, 0)
[
SAssignNew(EffectGridPanel, SGridPanel)
SNew(SScrollBox)
+ SScrollBox::Slot()
[
SAssignNew(EffectGridPanel, SGridPanel)
]
]
+ SWidgetSwitcher::Slot()
.HAlign(HAlign_Fill)

View File

@ -28,6 +28,7 @@
#include "StatePanel/SStatePanel.h"
#include "Widgets/Layout/SConstraintCanvas.h"
#include "Widgets/Layout/SScaleBox.h"
#include "Widgets/Layout/SSpacer.h"
#include "Widgets/Layout/SWidgetSwitcher.h"
#include "Widgets/Views/STreeView.h"
#include "Windows/AllowWindowsPlatformTypes.h"
@ -43,9 +44,9 @@ void SCutMainWindow::Construct(const FArguments& InArgs)
FTextBlockStyle MainBarTextStyle = FAppStyle::GetWidgetStyle<FTextBlockStyle>("NormalText");
MainBarTextStyle.SetFontSize(17);
MainBarTextStyle.SetFontSize(14);
FTextBlockStyle TitleBarTextStyle = FAppStyle::GetWidgetStyle<FTextBlockStyle>("NormalText");
MainBarTextStyle.SetFontSize(15);
TitleBarTextStyle.SetFontSize(15);
ChildSlot
@ -83,8 +84,7 @@ void SCutMainWindow::Construct(const FArguments& InArgs)
]
]
+ SHorizontalBox::Slot()
.Padding(32, 0, -32, 0)
.HAlign(HAlign_Fill)
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
.SizeParam(FAuto())
[
@ -117,6 +117,12 @@ void SCutMainWindow::Construct(const FArguments& InArgs)
]
]
+ SHorizontalBox::Slot()
.SizeParam(FStretch(1.0))
[
SNew(SSpacer)
]
+ SHorizontalBox::Slot()
.SizeParam(FAuto())
.VAlign(VAlign_Center)
.HAlign(HAlign_Right)
[
@ -129,6 +135,7 @@ void SCutMainWindow::Construct(const FArguments& InArgs)
]
]
+ SHorizontalBox::Slot()
.SizeParam(FAuto())
.VAlign(VAlign_Center)
.HAlign(HAlign_Right)
[
@ -141,6 +148,7 @@ void SCutMainWindow::Construct(const FArguments& InArgs)
]
]
+ SHorizontalBox::Slot()
.SizeParam(FAuto())
.VAlign(VAlign_Center)
.HAlign(HAlign_Right)
[
@ -651,19 +659,18 @@ void SCutMainWindow::OpenProject(const FString& Project)
void SCutMainWindow::ExportProject(const FString& ExportPath)
{
// 先读取所有保存下来的轨道
for (FTrackGroup& TrackGroup : CutTimeline->TrackGroups)
{
for (FTrackData& TrackData : TrackGroup.TrackDataArray)
{
FUtils::TrackEncodeVideo(TrackData, {});
// FUtils::TrackEncodeVideo(TrackData, FPaths::Combine(ExportPath, TEXT("Video")));
}
}
for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++)
{
FUtils::TrackEncodeVideo(StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData, TEXT("D:\\Project\\Cut5\\Movie.mp4"));
FUtils::TrackEncodeVideo(StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData, FPaths::Combine(ExportPath, TEXT("Video")));
}
if (ExportPath.IsEmpty())
@ -733,17 +740,31 @@ void SCutMainWindow::ExportProject(const FString& ExportPath)
tinyxml2::XMLElement* CardList = RootElement->InsertNewChildElement("CardList");
for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); i ++)
{
for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); j++)
if (EffectCardsPanel->EffectCardGroups[i].bIsDedicated)
{
for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); j++)
{
tinyxml2::XMLElement* Card = CardList->InsertNewChildElement("Card");
Card->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[j].ID)));
Card->InsertNewChildElement("Type")->InsertNewText(EffectCardsPanel->EffectCardGroups[0].bIsDedicated ? "0" : "2");
Card->InsertNewChildElement("Times");
Card->InsertNewChildElement("Step");
Card->InsertNewChildElement("SpecialEffectID");
Card->InsertNewChildElement("SerialNumberList");
}
}
else
{
tinyxml2::XMLElement* Card = CardList->InsertNewChildElement("Card");
Card->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ID)));
Card->InsertNewChildElement("Type")->InsertNewText(EffectCardsPanel->EffectCardGroups[0].bIsDedicated ? "0" : "1");
Card->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].ID)));
Card->InsertNewChildElement("Type")->InsertNewText(EffectCardsPanel->EffectCardGroups[0].bIsDedicated ? "0" : "2");
Card->InsertNewChildElement("Times");
Card->InsertNewChildElement("Step");
Card->InsertNewChildElement("SpecialEffectID");
Card->InsertNewChildElement("SerialNumberList");
ID++;
}
}
// KeyBoard
@ -761,30 +782,67 @@ void SCutMainWindow::ExportProject(const FString& ExportPath)
tinyxml2::XMLElement* TimeLength = ProcessB->InsertNewChildElement("TimeLength");
tinyxml2::XMLElement* SoundList = ProcessB->InsertNewChildElement("SoundList");
{
tinyxml2::XMLElement* Sound = SoundList->InsertNewChildElement("Sound");
tinyxml2::XMLElement* URL = Sound->InsertNewChildElement("URL");
tinyxml2::XMLElement* Loop = Sound->InsertNewChildElement("Loop");
tinyxml2::XMLElement* Mode = Sound->InsertNewChildElement("Mode");
tinyxml2::XMLElement* Round = Sound->InsertNewChildElement("Round");
tinyxml2::XMLElement* Timecode = Sound->InsertNewChildElement("Timecode");
tinyxml2::XMLElement* VolumeEventList = Sound->InsertNewChildElement("VolumeEventList");
{
tinyxml2::XMLElement* VolumeEvent = VolumeEventList->InsertNewChildElement("VolumeEvent");
tinyxml2::XMLElement* VolumeEventTimeCode = VolumeEvent->InsertNewChildElement("TimeCode");
tinyxml2::XMLElement* VolumeEventValue = VolumeEvent->InsertNewChildElement("Value");
}
GetSoundElement(SoundList);
}
ProcessB->InsertEndChild(GetDeviceElement(ProcessB));
tinyxml2::XMLElement* VideoList = ProcessB->InsertNewChildElement("VideoList");
{
// for video
GetVideoElement(VideoList);
}
// 非必须项
tinyxml2::XMLElement* Identity_SpecialEffects = ProcessB->InsertNewChildElement("Identity_SpecialEffects");
{
}
tinyxml2::XMLElement* IsGlobal = ProcessB->InsertNewChildElement("IsGlobal");
{
}
tinyxml2::XMLElement* State = ProcessB->InsertNewChildElement("State");
{
}
}
}
// Effect Lists
for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); i++)
{
for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); j++)
{
}
}
tinyxml2::XMLElement* SpecialEffect = RootElement->InsertNewChildElement("SpecialEffect");
{
tinyxml2::XMLElement* Test = SpecialEffect->InsertNewChildElement("Test");
{
Test->InsertNewChildElement("ID");
Test->InsertNewChildElement("AutoNext");
Test->InsertNewChildElement("TimeLength");
GetSoundElement(Test);
GetDeviceElement(Test);
GetVideoElement(Test);
Test->InsertNewChildElement("IsGlobal");
Test->InsertNewChildElement("State");
}
}
Document.SaveFile(TCHAR_TO_UTF8(*(ExportPath + "/" + FGlobalData::CurrentProjectName + "/" + FGlobalData::CurrentProjectName + TEXT(".xml"))));
FString XMLExportPath = FPaths::ConvertRelativePathToFull(FPaths::Combine(ExportPath, FGlobalData::CurrentProjectName, FGlobalData::CurrentProjectName + TEXT(".xml")));
TArray<uint8> Data;
FFileHelper::SaveArrayToFile(Data, *XMLExportPath);
// FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*XMLExportPath);
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, XMLExportPath);
Document.SaveFile(TCHAR_TO_UTF8(*XMLExportPath));
}
void SCutMainWindow::ImportProject(const FString& ImportPath)
@ -969,5 +1027,81 @@ void SCutMainWindow::PreSettingBeforeSeek()
OnUpdateVideo(FGuid::NewGuid(), 1920, 1080, nullptr);
}
tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Parent)
{
tinyxml2::XMLElement* Device = Parent->InsertNewChildElement("Device");
{
tinyxml2::XMLElement* Light = Device->InsertNewChildElement("Light");
{
// DMLightList
tinyxml2::XMLElement* DMLightList = Light->InsertNewChildElement("DMLightList");
{
}
tinyxml2::XMLElement* PlayerLightList = Light->InsertNewChildElement("PlayerLightList");
{
}
tinyxml2::XMLElement* GuangZhenList = Light->InsertNewChildElement("GuangZhenList");
{
}
tinyxml2::XMLElement* RoomLight = Light->InsertNewChildElement("RoomLight");
{
}
tinyxml2::XMLElement* JLight = Light->InsertNewChildElement("JLight");
{
}
tinyxml2::XMLElement* Incense_Machine = Light->InsertNewChildElement("Incense_Machine");
{
}
}
}
return Device;
}
tinyxml2::XMLElement* SCutMainWindow::GetVideoElement(tinyxml2::XMLElement* Parent)
{
tinyxml2::XMLElement* Video = Parent->InsertNewChildElement("Video");
tinyxml2::XMLElement* URL = Video->InsertNewChildElement("URL");
tinyxml2::XMLElement* Timecode = Video->InsertNewChildElement("Timecode");
tinyxml2::XMLElement* Loop = Video->InsertNewChildElement("Loop");
tinyxml2::XMLElement* Mode = Video->InsertNewChildElement("Mode");
tinyxml2::XMLElement* ProjectorID = Video->InsertNewChildElement("ProjectorID");
tinyxml2::XMLElement* ProjectorEventList = Video->InsertNewChildElement("ProjectorEventList");
{
tinyxml2::XMLElement* ProjectorEvent = ProjectorEventList->InsertNewChildElement("ProjectorEvent");
{
tinyxml2::XMLElement* TimeCode = ProjectorEvent->InsertNewChildElement("TimeCode");
tinyxml2::XMLElement* Value = ProjectorEvent->InsertNewChildElement("Value");
}
}
return Parent;
}
tinyxml2::XMLElement* SCutMainWindow::GetSoundElement(tinyxml2::XMLElement* Parent)
{
tinyxml2::XMLElement* Sound = Parent->InsertNewChildElement("Sound");
tinyxml2::XMLElement* URL = Sound->InsertNewChildElement("URL");
tinyxml2::XMLElement* Loop = Sound->InsertNewChildElement("Loop");
tinyxml2::XMLElement* Mode = Sound->InsertNewChildElement("Mode");
tinyxml2::XMLElement* Round = Sound->InsertNewChildElement("Round");
tinyxml2::XMLElement* Timecode = Sound->InsertNewChildElement("Timecode");
tinyxml2::XMLElement* VolumeEventList = Sound->InsertNewChildElement("VolumeEventList");
{
tinyxml2::XMLElement* VolumeEvent = VolumeEventList->InsertNewChildElement("VolumeEvent");
{
tinyxml2::XMLElement* VolumeEventTimeCode = VolumeEvent->InsertNewChildElement("TimeCode");
tinyxml2::XMLElement* VolumeEventValue = VolumeEvent->InsertNewChildElement("Value");
}
}
return Parent;
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -2,6 +2,8 @@
#pragma once
#include <Cut5/Xml/tinyxml2.h>
#include "CoreMinimal.h"
#include "Curtain/SCurtainPanel.h"
@ -75,4 +77,8 @@ public:
virtual void DeleteAllAssetsInTimeline() override;
virtual SCutTimeline* GetCutTimeline() override { return CutTimeline.Get(); };
virtual void PreSettingBeforeSeek() override;
static tinyxml2::XMLElement* GetDeviceElement(tinyxml2::XMLElement* Parent);
static tinyxml2::XMLElement* GetVideoElement(tinyxml2::XMLElement* Parent);
static tinyxml2::XMLElement* GetSoundElement(tinyxml2::XMLElement* Parent);
};

View File

@ -115,6 +115,7 @@ void SCutTimeline::Construct(const FArguments& InArgs)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.SizeParam(FAuto())
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
@ -143,6 +144,7 @@ void SCutTimeline::Construct(const FArguments& InArgs)
.AutoWidth()
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
.SizeParam(FAuto())
[
SNew(SImage)
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("PlayButton.png"), {}))

View File

@ -18,7 +18,7 @@ void STimelineProperty::Construct(const FArguments& InArgs)
SNew(SBox)
.WidthOverride(80)
.HeightOverride(80)
.Padding(5)
.Padding(4)
[
SNew(SOverlay)
+ SOverlay::Slot()

View File

@ -36,6 +36,7 @@ void STimelinePropertyPanel::Construct(const FArguments& InArgs)
.SizeParam(FAuto())
[
SNew(SBox)
.Padding(0, 0 , 0, 14)
[
SNew(SOverlay)
+ SOverlay::Slot()
@ -90,9 +91,37 @@ void STimelinePropertyPanel::Construct(const FArguments& InArgs)
.Visibility(EVisibility::HitTestInvisible)
]
+ SOverlay::Slot()
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
.Padding(0, 0 , 0, 10)
[
SNew(SBox)
.WidthOverride(16)
.HeightOverride(21)
[
SNew(SImage)
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("CharacterGroupIcon.png"), {16, 21}))
.Visibility(EVisibility::HitTestInvisible)
]
]
+ SOverlay::Slot()
.Padding(0, 0, 9, 9)
.VAlign(VAlign_Bottom)
.HAlign(HAlign_Right)
[
SNew(SBox)
.WidthOverride(24)
.HeightOverride(24)
[
SNew(SImage)
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("add-circle-fill.png"), {24, 24}))
.Visibility(EVisibility::HitTestInvisible)
]
]
+ SOverlay::Slot()
.VAlign(VAlign_Bottom)
.HAlign(HAlign_Fill)
.Padding(0, 0, 0, 3)
.Padding(0, 0, 0, 9)
[
SNew(STextBlock)
.Text(FText::FromString(TEXT("角色组")))
@ -100,6 +129,7 @@ void STimelinePropertyPanel::Construct(const FArguments& InArgs)
.Visibility(EVisibility::HitTestInvisible)
]
]
]

View File

@ -134,26 +134,52 @@ void SStatePanel::Construct(const FArguments& InArgs)
+ SOverlay::Slot()
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
.Padding(50, 0, 0, 0)
[
SNew(SBox)
.WidthOverride(100)
.HeightOverride(100)
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.SizeParam(FAuto())
[
SAssignNew(Projector, SImage)
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath(TEXT("Projector.png")), FVector2D(0, 0)))
SNew(SBox)
.WidthOverride(32)
.HeightOverride(32)
[
SAssignNew(Projector, SImage)
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath(TEXT("Projector.png")), FVector2D(0, 0)))
]
]
+ SVerticalBox::Slot()
.SizeParam(FAuto())
[
SNew(STextBlock)
.Text(FText::FromString(TEXT("投影仪")))
]
]
+ SOverlay::Slot()
.Padding(0, 0, 50, 0)
.HAlign(HAlign_Right)
.VAlign(VAlign_Center)
[
SNew(SBox)
.WidthOverride(100)
.HeightOverride(100)
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.SizeParam(FAuto())
[
SAssignNew(SpotLight, SImage)
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath(TEXT("SpotLight.png")), FVector2D(0, 0)))
SNew(SBox)
.WidthOverride(59)
.HeightOverride(49)
[
SAssignNew(SpotLight, SImage)
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath(TEXT("SpotLight.png")), FVector2D(0, 0)))
]
]
+ SVerticalBox::Slot()
.SizeParam(FAuto())
[
SNew(STextBlock)
.Text(FText::FromString(TEXT("投射灯")))
]
]
+ SOverlay::Slot()
.HAlign(HAlign_Right)

View File

@ -83,6 +83,13 @@ TSharedPtr< FSlateStyleSet > FCutButtonStyle::Create()
.SetNormal( BOX_BRUSH( "CurtainSelected", FVector2D(240,32), 0.25) )
);
Style->Set("Preset.PresetButton", FButtonStyle(Button)
.SetNormal( BOX_BRUSH( "PresetButtonNormal", FVector2D(76,76), 0.25) )
.SetHovered( BOX_BRUSH( "PresetButtonHover", FVector2D(76,76), 0.25) )
.SetPressed( BOX_BRUSH( "PresetButtonSelected", FVector2D(76,76), 0.25) )
);
return Style;
}

Binary file not shown.