自动播放

This commit is contained in:
Sch 2023-07-06 14:59:43 +08:00
parent eb09711d41
commit e0890af948
13 changed files with 287 additions and 49 deletions

View File

@ -95,7 +95,7 @@ r.TranslucentSortPolicy=0
TranslucentSortAxis=(X=0.000000,Y=-1.000000,Z=0.000000)
vr.VRS.HMDFixedFoveationLevel=0
vr.VRS.HMDFixedFoveationDynamic=False
r.CustomDepth=1
r.CustomDepth=3
r.CustomDepthTemporalAAJitter=True
r.PostProcessing.PropagateAlpha=0
r.DefaultFeature.Bloom=True

View File

@ -9,6 +9,12 @@ public:
inline static double DefaultTimeTickSpace = 10.0;
inline static int32 LightArrayX = 70;
inline static int32 LightArrayY = 42;
static int32 GetAlignOfTickSpace(double Align, bool bCeil = false)
{
return bCeil ? FMath::CeilToInt(Align / FGlobalData::DefaultTimeTickSpace) * FGlobalData::DefaultTimeTickSpace :
FMath::TruncToInt(Align / FGlobalData::DefaultTimeTickSpace) * FGlobalData::DefaultTimeTickSpace;
}
};
enum class ETrackType
{
@ -85,10 +91,35 @@ struct CUT5_API FTimelinePropertyData
int32 MovieFrameLength = 0;
};
class CUT5_API FTrackClipDragOperation final : public FDecoratedDragDropOp
class CUT5_API FCutDragDropBase : public FDecoratedDragDropOp
{
public:
enum class EType
{
TrackClip,
Clip2Clip,
};
TSharedPtr<SWidget> DraggingWidget;
FTimelinePropertyData TimelinePropertyData;
EType Type;
};
class CUT5_API FTrackClipDragOperation final : public FCutDragDropBase
{
public:
FTimelinePropertyData TimelinePropertyData;
};
class CUT5_API FClip2ClipDragDropOperation final : public FCutDragDropBase
{
public:
enum class EDragType
{
DragLeft,
DragRight,
Move,
};
EDragType DragType;
};

View File

@ -71,10 +71,10 @@ void SCustomInputPanel::Construct(const FArguments& InArgs)
PropertyData.MovieFrameLength = FrameCount;
GridPanel->AddSlot(GridPanel->GetChildren()->Num() % 3, GridPanel->GetChildren()->Num() / 3)
[
SNew(SCustomInputResource)
.PropertyData(PropertyData)
];
}, TStatId(), nullptr, ENamedThreads::GameThread);
FTaskGraphInterface::Get().WaitUntilTaskCompletes(Task);
});

View File

@ -46,6 +46,7 @@ FReply SCustomInputResource::OnDragDetected(const FGeometry& MyGeometry, const F
const TSharedPtr<FTrackClipDragOperation> Operation = MakeShared<FTrackClipDragOperation>();
Operation->TimelinePropertyData = PropertyData;
Operation->DraggingWidget = SharedThis(this);
Operation->Type = FCutDragDropBase::EType::TrackClip;
return FReply::Handled().BeginDragDrop(Operation.ToSharedRef());
}

View File

@ -23,4 +23,6 @@ public:
void Construct(const FArguments& InArgs);
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
};

View File

@ -153,6 +153,16 @@ void SCutTimeline::Construct(const FArguments& InArgs)
})
]
+ SHorizontalBox::Slot()
[
SNew(SButton)
.OnClicked_Lambda([this]()
{
SetAutoPlay(!AutoPlaying);
return FReply::Handled();
})
]
+ SHorizontalBox::Slot()
[
SNew(SButton)
.OnClicked_Lambda([this]()
@ -172,6 +182,15 @@ void SCutTimeline::Construct(const FArguments& InArgs)
}
void SCutTimeline::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);
if (AutoPlaying)
{
UpdateCursorPosition(GetCursorPosition() + 1);
}
}
void SCutTimeline::AddNewTrack(FTrackData TrackData, int32 TrackIndex)
{
TrackDataArray.Insert(TrackData, TrackIndex);
@ -188,14 +207,23 @@ void SCutTimeline::AddNewTrack(FTrackData TrackData, int32 TrackIndex)
AllWidgets.Add(NewTrackBody.Get());
}
void SCutTimeline::SetAutoPlay(bool bStart)
{
AutoPlaying = bStart;
}
FReply SCutTimeline::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
{
// Add new Track
const FTrackClipDragOperation& ClipDragOperation = static_cast<FTrackClipDragOperation&>(DragDropEvent.GetOperation().ToSharedRef().Get());
FTrackData TrackData;
TrackData.TrackName = ClipDragOperation.TimelinePropertyData.Name;
TrackData.TrackType = ClipDragOperation.TimelinePropertyData.Type;
AddNewTrack(TrackData, 0);
if (ClipDragOperation.Type != FTrackClipDragOperation::EType::Clip2Clip)
{
FTrackData TrackData;
TrackData.TrackName = ClipDragOperation.TimelinePropertyData.Name;
TrackData.TrackType = ClipDragOperation.TimelinePropertyData.Type;
AddNewTrack(TrackData, 0);
}
return SCompoundWidget::OnDrop(MyGeometry, DragDropEvent);
}

View File

@ -33,7 +33,10 @@ public:
int32 GetCursorPosition() const;
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override;
void AddNewTrack(FTrackData TrackData, int32 TrackIndex);
void SetAutoPlay(bool bStart);
bool AutoPlaying = false;
ICutMainWidgetInterface* MainWidgetInterface;
TArray<FTrackData> TrackDataArray;

View File

@ -18,10 +18,30 @@ void SLightArrayPanel::Construct(const FArguments& InArgs)
SNew(SScaleBox)
[
SNew(SBox)
.WidthOverride(500)
.HeightOverride(400)
.WidthOverride(600)
.HeightOverride(480)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SAssignNew(LightGrid, SGridPanel)
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.SizeParam(FAuto())
[
SAssignNew(LightBar1, SHorizontalBox)
]
+ SVerticalBox::Slot()
.SizeParam(FStretch())
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SAssignNew(LightGrid, SGridPanel)
]
+ SVerticalBox::Slot()
.SizeParam(FAuto())
[
SAssignNew(LightBar2, SHorizontalBox)
]
]
]
@ -47,6 +67,30 @@ void SLightArrayPanel::GenerateLightArray()
];
}
}
for (int32 i = 0; i < FGlobalData::LightArrayX; i++)
{
LightBar1->AddSlot()
[
SNew(SBox)
[
SNew(SBorder)
.ColorAndOpacity(FLinearColor(1, 0, 1, 1))
]
];
}
for (int32 i = 0; i < FGlobalData::LightArrayX; i++)
{
LightBar2->AddSlot()
[
SNew(SBox)
[
SNew(SBorder)
.ColorAndOpacity(FLinearColor(1, 0, 1, 1))
]
];
}
}
void SLightArrayPanel::UpdateLightArray(int32 X, int32 Y, FLinearColor Color)

View File

@ -23,4 +23,6 @@ public:
void GenerateLightArray();
void UpdateLightArray(int32 X, int32 Y, FLinearColor Color);
TSharedPtr<SGridPanel> LightGrid;
TSharedPtr<SHorizontalBox> LightBar1;
TSharedPtr<SHorizontalBox> LightBar2;
};

View File

@ -11,20 +11,45 @@
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
FReply STimelineClip::OnBorderMouseButtonDown(const FGeometry& Geometry, const FPointerEvent& PointerEvent)
{
const FVector2D LocalPos = Geometry.AbsoluteToLocal(PointerEvent.GetScreenSpacePosition());
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Blue, LocalPos.ToString());
if (LocalPos.X <= 10)
{
const TSharedPtr<FClip2ClipDragDropOperation> Clip2ClipDragDropOperation = MakeShared<FClip2ClipDragDropOperation>();
Clip2ClipDragDropOperation->DraggingWidget = SharedThis(this);
Clip2ClipDragDropOperation->Type = FCutDragDropBase::EType::Clip2Clip;
Clip2ClipDragDropOperation->DragType = FClip2ClipDragDropOperation::EDragType::DragLeft;
return FReply::Handled().DetectDrag(SharedThis(this), EKeys::LeftMouseButton).BeginDragDrop(Clip2ClipDragDropOperation.ToSharedRef());
}
if (LocalPos.X >= Geometry.GetLocalSize().X - 10)
{
const TSharedPtr<FClip2ClipDragDropOperation> Clip2ClipDragDropOperation = MakeShared<FClip2ClipDragDropOperation>();
Clip2ClipDragDropOperation->DraggingWidget = SharedThis(this);
Clip2ClipDragDropOperation->Type = FCutDragDropBase::EType::Clip2Clip;
Clip2ClipDragDropOperation->DragType = FClip2ClipDragDropOperation::EDragType::DragRight;
return FReply::Handled().DetectDrag(SharedThis(this), EKeys::LeftMouseButton).BeginDragDrop(Clip2ClipDragDropOperation.ToSharedRef());
}
return SCompoundWidget::OnMouseButtonDown(Geometry, PointerEvent);
}
void STimelineClip::Construct(const FArguments& InArgs)
{
ClipData = InArgs._InClipData;
MainWidgetInterface = InArgs._MainWidgetInterface;
SetRenderTransform(FSlateRenderTransform(FVector2D(FMath::TruncToInt(ClipData->ClipStartTime / FGlobalData::DefaultTimeTickSpace) * FGlobalData::DefaultTimeTickSpace, 0)));
ChildSlot
[
SNew(SBox)
.WidthOverride(ClipData.ClipEndTime - ClipData.ClipStartTime)
SAssignNew(ClipDataBox, SBox)
.WidthOverride(FGlobalData::GetAlignOfTickSpace(ClipData->ClipEndTime - ClipData->ClipStartTime, true))
.HeightOverride(FGlobalData::DefaultTrackHeight)
.RenderTransform(FSlateRenderTransform(FVector2D(ClipData.ClipStartTime, 0)))
[
SNew(SBorder)
.ColorAndOpacity(ClipData.ClipColors[0])
.BorderBackgroundColor(ClipData.ClipColors[0])
.ColorAndOpacity(ClipData->ClipColors[0])
.BorderBackgroundColor(ClipData->ClipColors[0])
.OnMouseButtonDown(this, &STimelineClip::OnBorderMouseButtonDown)
]
];
@ -32,17 +57,17 @@ void STimelineClip::Construct(const FArguments& InArgs)
void STimelineClip::Seek(int32 Frame)
{
switch (ClipData.ClipType)
switch (ClipData->ClipType)
{
case ETrackType::VideoTrack:
{
FDateTime A = FDateTime::Now();
cv::VideoCapture Capture;
Capture.open(TCHAR_TO_UTF8(*ClipData.MoviePath));
Capture.open(TCHAR_TO_UTF8(*ClipData->MoviePath));
GEngine->AddOnScreenDebugMessage(-1, 10.0F, FColor::Red, FString::Printf(TEXT("Read Time: %f"), (FDateTime::Now() - A).GetTotalMilliseconds()));
const int32 Offset = Frame - (ClipData.ClipStartTime / FGlobalData::TrackLength);
const int32 Offset = Frame - (ClipData->ClipStartTime / FGlobalData::TrackLength);
Capture.set(cv::CAP_PROP_POS_FRAMES, ClipData.VideoStartFrame + Offset);
Capture.set(cv::CAP_PROP_POS_FRAMES, ClipData->VideoStartFrame + Offset);
cv::Mat Read;
Capture.read(Read);
@ -66,22 +91,6 @@ void STimelineClip::Seek(int32 Frame)
MainWidgetInterface->OnUpdateVideo(FGuid::NewGuid(), Texture);
}
// Async(EAsyncExecution::Thread, [this, Frame]()
// {
// cv::VideoCapture Capture;
// Capture.open(TCHAR_TO_UTF8(*ClipData.MoviePath), cv::CAP_FFMPEG);
// const int32 Offset = Frame - (ClipData.ClipStartTime / FGlobalData::TrackLength);
// Capture.set(cv::CAP_PROP_POS_FRAMES, ClipData.VideoStartFrame + Offset);
// cv::Mat Read;
// Capture.read(Read);
// FGraphEventRef Task = FFunctionGraphTask::CreateAndDispatchWhenReady([&]()
// {
//
//
// }, TStatId(), nullptr, ENamedThreads::GameThread);
// FTaskGraphInterface::Get().WaitUntilTaskCompletes(Task);
// });
}
break;
@ -90,6 +99,39 @@ void STimelineClip::Seek(int32 Frame)
}
}
void STimelineClip::UpdatePosition(double StartTime)
{
if (StartTime - ClipData->ClipEndTime >= -1)
{
return;
}
const double NewPosX = FMath::TruncToInt(StartTime / FGlobalData::DefaultTimeTickSpace) * FGlobalData::DefaultTimeTickSpace;
SetRenderTransform(FSlateRenderTransform(FVector2D(NewPosX, 0)));
ClipDataBox->SetWidthOverride(FGlobalData::GetAlignOfTickSpace(ClipData->ClipEndTime - StartTime, true));
if (ClipData->ClipType == ETrackType::VideoTrack)
{
ClipData->VideoStartFrame += (StartTime - ClipData->ClipStartTime) / FGlobalData::DefaultTimeTickSpace;
}
ClipData->ClipStartTime = StartTime;
}
void STimelineClip::UpdateLength(double EndTime)
{
ClipDataBox->SetWidthOverride(FGlobalData::GetAlignOfTickSpace(EndTime - ClipData->ClipStartTime, true));
if (ClipData->ClipType == ETrackType::VideoTrack)
{
ClipData->VideoEndFrame += (EndTime - ClipData->ClipEndTime) / FGlobalData::DefaultTimeTickSpace;
}
ClipData->ClipEndTime = EndTime;
}
FReply STimelineClip::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
const FVector2D LocalPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());
return FReply::Handled();
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -16,14 +16,19 @@ public:
SLATE_BEGIN_ARGS(STimelineClip)
{
}
SLATE_ARGUMENT(FClipData, InClipData)
SLATE_ARGUMENT(FClipData*, InClipData)
SLATE_ARGUMENT(ICutMainWidgetInterface*, MainWidgetInterface)
SLATE_END_ARGS()
FReply OnBorderMouseButtonDown(const FGeometry& Geometry, const FPointerEvent& PointerEvent);
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
FClipData ClipData;
FClipData* ClipData;
ICutMainWidgetInterface* MainWidgetInterface;
TSharedPtr<SBox> ClipDataBox;
virtual void Seek(int32 Frame);
void UpdatePosition(double StartTime);
void UpdateLength(double X);
virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
};

View File

@ -46,6 +46,7 @@ FReply STimelineProperty::OnDragDetected(const FGeometry& MyGeometry, const FPoi
const TSharedPtr<FTrackClipDragOperation> Operation = MakeShared<FTrackClipDragOperation>();
Operation->TimelinePropertyData = TimelinePropertyData;
Operation->DraggingWidget = SharedThis(this);
Operation->Type = FCutDragDropBase::EType::TrackClip;
return FReply::Handled().BeginDragDrop(Operation.ToSharedRef());
}

View File

@ -41,15 +41,15 @@ void STrackBody::CallRender()
{
Overlay->ClearChildren();
SlateClips.Empty();
for (const FClipData& TempClipData : TrackHead->TrackData.ClipData)
for (FClipData& TempClipData : TrackHead->TrackData.ClipData)
{
if (TempClipData.ClipEndTime > FGlobalData::TrackLength)
{
FGlobalData::TrackLength = TempClipData.ClipEndTime;
FGlobalData::TrackLength = TempClipData.ClipEndTime + 50;
TrackHead->CutTimeline->UpdateTimelineLength();
}
TSharedPtr<STimelineClip> TimelineClip;
TimelineClip = SNew(STimelineClip).InClipData(TempClipData).MainWidgetInterface(MainWidgetInterface);
TimelineClip = SNew(STimelineClip).InClipData(&TempClipData).MainWidgetInterface(MainWidgetInterface);
Overlay->AddSlot()
.HAlign(HAlign_Left)
@ -57,6 +57,7 @@ void STrackBody::CallRender()
TimelineClip.ToSharedRef()
];
SlateClips.Add(TimelineClip);
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("%f"), TempClipData.ClipEndTime - TempClipData.ClipStartTime));
}
}
@ -64,9 +65,14 @@ void STrackBody::CallRender()
FReply STrackBody::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
{
const FTrackClipDragOperation& ClipDragOperation = static_cast<FTrackClipDragOperation&>(DragDropEvent.GetOperation().ToSharedRef().Get());
if (ClipDragOperation.TimelinePropertyData.Type == TrackHead->TrackData.TrackType)
// ClipDrag
const auto& DragDropOperation = static_cast<FTrackClipDragOperation&>(DragDropEvent.GetOperation().ToSharedRef().Get());
if (DragDropOperation.Type == FCutDragDropBase::EType::TrackClip)
{
const FTrackClipDragOperation& ClipDragOperation = static_cast<FTrackClipDragOperation&>(DragDropEvent.GetOperation().ToSharedRef().Get());
if (ClipDragOperation.TimelinePropertyData.Type != TrackHead->TrackData.TrackType)
return FReply::Handled().EndDragDrop();
FClipData NewClipData;
NewClipData.ClipGuid = FGuid::NewGuid();
NewClipData.ClipType = ClipDragOperation.TimelinePropertyData.Type;
@ -131,13 +137,86 @@ FReply STrackBody::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& Dra
GEngine->AddOnScreenDebugMessage(-1, 10.0, FColor::Green, FString::Printf(TEXT("Track %d"), TrackHead->TrackData.ClipData.Num()));
CallRender();
}
if (DragDropOperation.Type == FCutDragDropBase::EType::Clip2Clip)
{
// OnDrop We Calculate Overwrite of all
const auto& ClipDragOperation = static_cast<FClip2ClipDragDropOperation&>(DragDropEvent.GetOperation().ToSharedRef().Get());
TSharedPtr<STimelineClip> TimelineClip = StaticCastSharedPtr<STimelineClip>(ClipDragOperation.DraggingWidget);
for (int32 i = TrackHead->TrackData.ClipData.Num() - 1; i >= 0; i--)
{
if (TimelineClip->ClipData->ClipStartTime == TrackHead->TrackData.ClipData[i].ClipStartTime || TimelineClip->ClipData->ClipEndTime == TrackHead->TrackData.ClipData[i].ClipEndTime)
{
continue;
}
const double ClipStartTime = TrackHead->TrackData.ClipData[i].ClipStartTime;
const double ClipEndTime = TrackHead->TrackData.ClipData[i].ClipEndTime;
if (TimelineClip->ClipData->ClipStartTime >= ClipStartTime && TimelineClip->ClipData->ClipEndTime <= ClipEndTime)
{
// It mean the new clip is in the old clip
FClipData SaveClipData = TrackHead->TrackData.ClipData[i];
TrackHead->TrackData.ClipData.RemoveAt(i);
// Left
FClipData LeftClipData = SaveClipData;
LeftClipData.ClipEndTime = TimelineClip->ClipData->ClipStartTime;
TrackHead->TrackData.ClipData.Add(LeftClipData);
FClipData RightClipData = SaveClipData;
RightClipData.ClipStartTime = TimelineClip->ClipData->ClipEndTime;
TrackHead->TrackData.ClipData.Add(RightClipData);
continue;
}
if (TimelineClip->ClipData->ClipStartTime <= ClipEndTime && TimelineClip->ClipData->ClipEndTime >= ClipEndTime)
{
// It mean the new clip start point is in the old clip
int32 NewLeftFrame = FGlobalData::GetAlignOfTickSpace(TimelineClip->ClipData->ClipEndTime - TimelineClip->ClipData->ClipStartTime, true) / FGlobalData::DefaultTimeTickSpace;
NewLeftFrame -= FGlobalData::GetAlignOfTickSpace(TrackHead->TrackData.ClipData[i].ClipEndTime - TrackHead->TrackData.ClipData[i].ClipStartTime, true) / FGlobalData::DefaultTimeTickSpace;
TrackHead->TrackData.ClipData[i].CropClip(FClipData::ECropMethod::FromBack, NewLeftFrame);
continue;
}
if (TimelineClip->ClipData->ClipEndTime > ClipStartTime && TimelineClip->ClipData->ClipStartTime < ClipStartTime)
{
// It mean the new clip end point is in the old clip
TrackHead->TrackData.ClipData[i].CropClip(FClipData::ECropMethod::FromFront, (TimelineClip->ClipData->ClipEndTime - ClipStartTime) / FGlobalData::DefaultTimeTickSpace);
continue;
}
if (TimelineClip->ClipData->ClipStartTime <= ClipStartTime && TimelineClip->ClipData->ClipEndTime >= ClipEndTime)
{
// It mean the new clip is out of the old clip
TrackHead->TrackData.ClipData.RemoveAt(i);
continue;
}
}
CallRender();
}
return FReply::Handled().EndDragDrop();
}
FReply STrackBody::OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
{
const auto& DragDropOperation = static_cast<FClip2ClipDragDropOperation&>(DragDropEvent.GetOperation().ToSharedRef().Get());
if (DragDropOperation.Type == FCutDragDropBase::EType::Clip2Clip)
{
if (DragDropOperation.DragType == FClip2ClipDragDropOperation::EDragType::DragLeft)
{
TSharedPtr<STimelineClip> TimelineClip = StaticCastSharedPtr<STimelineClip>(DragDropOperation.DraggingWidget);
TimelineClip->UpdatePosition(MyGeometry.AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).X);
// show the clip length
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("DragLeft %f / %f"), TimelineClip->ClipData->ClipStartTime, TimelineClip->ClipData->ClipEndTime));
}
if (DragDropOperation.DragType == FClip2ClipDragDropOperation::EDragType::DragRight)
{
TSharedPtr<STimelineClip> TimelineClip = StaticCastSharedPtr<STimelineClip>(DragDropOperation.DraggingWidget);
TimelineClip->UpdateLength(MyGeometry.AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).X);
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("DragLeft %f / %f"), TimelineClip->ClipData->ClipStartTime, TimelineClip->ClipData->ClipEndTime));
}
}
return SCompoundWidget::OnDragOver(MyGeometry, DragDropEvent);
}
@ -155,7 +234,7 @@ void STrackBody::Seek(int32 Frame)
{
for (int32 i = 0; i < SlateClips.Num(); i++)
{
if (SlateClips[i]->ClipData.GetClipStartFrame() <= Frame && SlateClips[i]->ClipData.GetClipEndFrame() > Frame)
if (SlateClips[i]->ClipData->GetClipStartFrame() <= Frame && SlateClips[i]->ClipData->GetClipEndFrame() > Frame)
{
SlateClips[i]->Seek(Frame);
break;