diff --git a/Config/FilterPlugin.ini b/Config/FilterPlugin.ini deleted file mode 100644 index ccebca2f326481a66548a0f10cc21de1cf4bad74..0000000000000000000000000000000000000000 --- a/Config/FilterPlugin.ini +++ /dev/null @@ -1,8 +0,0 @@ -[FilterPlugin] -; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and -; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. -; -; Examples: -; /README.txt -; /Extras/... -; /Binaries/ThirdParty/*.dll diff --git a/Source/DasherVR/Private/SDasherWidget.cpp b/Source/DasherVR/Private/SDasherWidget.cpp index 4b3e21678324f734d1a86d606e5132ccce7c260b..1d48f4b1c5fcea8f6a9809c9d6733a664389aea2 100644 --- a/Source/DasherVR/Private/SDasherWidget.cpp +++ b/Source/DasherVR/Private/SDasherWidget.cpp @@ -4,11 +4,6 @@ #include "Brushes/SlateColorBrush.h" #include "Rendering/DrawElements.h" #include "DasherInterface.h" -#include "IDisplayCluster.h" -#include "Cluster/DisplayClusterClusterEvent.h" -#include "Cluster/IDisplayClusterClusterManager.h" - -#include "Utility/RWTHVRUtilities.h" #include "Components/SlateWrapperTypes.h" #include "Framework/Application/SlateApplication.h" @@ -22,331 +17,401 @@ BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION //Set the state if we're in the editor or not. void SDasherWidget::SetEditor(bool EditorState) { - IsEditor = EditorState; + IsEditor = EditorState; } -//Pause the input -void SDasherWidget::PauseInput() + +void SDasherWidget::EnableInput(bool enable) { - if (!URWTHVRUtilities::IsPrimaryNode()) return; - InputPaused = true; + InputPaused = !enable; } -//Unpause the input -void SDasherWidget::UnpauseInput() + +bool SDasherWidget::GetInputEnabled() const { - if (!URWTHVRUtilities::IsPrimaryNode()) return; - InputPaused = false; + return !InputPaused; } //Event Handlers //Mouse position saved for mouse Input -FReply SDasherWidget::HandleMouseMoveEvent(const FGeometry& Geometry, const FPointerEvent& MouseEvent) +FReply SDasherWidget::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { - if (!InputPaused) - { - if (CurrentlyUsingVectorInput) return FReply::Unhandled(); - //The mouse event only contains the Screen Space Position - const FVector2D newMousePosition = Geometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()); - - NewMousePosition.x = newMousePosition.X; - NewMousePosition.y = newMousePosition.Y; - } - return FReply::Handled(); + if (InputPaused) return FReply::Unhandled(); + + FMouseState& MouseState = GetMouseState(MouseEvent.GetPointerIndex()); + + if(MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton && !MouseState.PrimaryButtonPressed) + { + DasherMainInterface->KeyDown(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); + MouseState.PrimaryButtonPressed = true; + MouseListeners.ExecuteIfBound(MouseEvent.GetPointerIndex(), MouseState.PrimaryButtonPressed); + } + else if(MouseEvent.GetEffectingButton() == EKeys::RightMouseButton && !MouseState.SecondaryButtonPressed) + { + DasherMainInterface->KeyDown(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Secondary_Input); + MouseState.SecondaryButtonPressed = true; + BoostListeners.ExecuteIfBound(MouseEvent.GetPointerIndex(), MouseState.SecondaryButtonPressed); + } + + UpdateMouseInteraction(MouseEvent.GetPointerIndex()); + return FReply::Handled(); } -FReply SDasherWidget::HandleMouseDownEvent(const FGeometry& Geometry, const FPointerEvent& MouseEvent) +FMouseState& SDasherWidget::GetMouseState(int Index) { - if (!InputPaused) - { - if(URWTHVRUtilities::IsRoomMountedMode()) - { - FDisplayClusterClusterEventBinary ClusterEvent; - ClusterEvent.EventId = DasherEventID + static_cast<uint8>(DasherEventType::Input_MouseDown); - IDisplayCluster::Get().GetClusterMgr()->EmitClusterEventBinary(ClusterEvent, false); - UE_LOG(LogTemp, Log, TEXT("MouseDownSend")); - return FReply::Handled().LockMouseToWidget(AsShared()); - } + if(!MouseStates.Contains(Index)) MouseStates.Add(Index, {}); + return MouseStates[Index]; +} - if (CurrentlyUsingVectorInput) - { - CurrentlyUsingVectorInput = false; - return FReply::Handled().LockMouseToWidget(AsShared()); - } - DasherMainInterface->KeyDown(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); - MouseDownListeners.ExecuteIfBound(); - } - return FReply::Handled().LockMouseToWidget(AsShared()); +// Moves Item to Back +void SDasherWidget::UpdateMouseInteraction(int Index) +{ + MouseInteractions.RemoveSingle(Index); + MouseInteractions.Add(Index); } -FReply SDasherWidget::HandleMouseUpEvent(const FGeometry& Geometry, const FPointerEvent& MouseEvent) +int SDasherWidget::GetLastActiveMouseInteraction() const { - if(URWTHVRUtilities::IsRoomMountedMode()) + // Find Mouse that already interacted + for(int i = MouseInteractions.Num() - 1; i >= 0; i--) { - FDisplayClusterClusterEventBinary ClusterEvent; - ClusterEvent.EventId = ClusterEvent.EventId = DasherEventID + static_cast<uint8>(DasherEventType::Input_MouseUp); - IDisplayCluster::Get().GetClusterMgr()->EmitClusterEventBinary(ClusterEvent, false); - return FReply::Handled().ReleaseMouseLock(); + if(MouseStates[MouseInteractions[i]].CurrentlyHovering) return MouseInteractions[i]; } - if (CurrentlyUsingVectorInput) - { - CurrentlyUsingVectorInput = false; - return FReply::Handled().ReleaseMouseLock(); - } - DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); - MouseUpListeners.ExecuteIfBound(); + //None found, thus take the first one that currently hovers + for(const TPair<int, FMouseState>& Pair : MouseStates) + { + if(Pair.Value.CurrentlyHovering) return Pair.Key; + } - return FReply::Handled().ReleaseMouseLock(); + return -1; } -FReply SDasherWidget::HandleMouseDoubleClickEvent(const FGeometry& Geometry, const FPointerEvent& MouseEvent) +FReply SDasherWidget::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { + if (InputPaused) return FReply::Unhandled(); - if (!InputPaused) - { - if(URWTHVRUtilities::IsRoomMountedMode()) + FMouseState& MouseState = GetMouseState(MouseEvent.GetPointerIndex()); + + //The mouse event only contains the Screen Space Position + MouseState.CursorPosition = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()); + MouseState.CurrentlyHovering = true; //ensure hover set + + return FReply::Handled(); +} + +void SDasherWidget::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) +{ + SWidget::OnMouseEnter(MyGeometry, MouseEvent); + + FMouseState& MouseState = GetMouseState(MouseEvent.GetPointerIndex()); + + //Reenable if button is still pressed + if(MouseState.DisabledDueToMouseLeave) + { + if(MouseState.PrimaryButtonPressed && MouseEvent.IsMouseButtonDown(EKeys::LeftMouseButton)) + { + DasherMainInterface->KeyDown(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); + UpdateMouseInteraction(MouseEvent.GetPointerIndex()); + MouseListeners.ExecuteIfBound(MouseEvent.GetPointerIndex(), true); + } + if(MouseState.SecondaryButtonPressed && MouseEvent.IsMouseButtonDown(EKeys::RightMouseButton)) { - FDisplayClusterClusterEventBinary ClusterEvent; - ClusterEvent.EventId = ClusterEvent.EventId = DasherEventID + static_cast<uint8>(DasherEventType::Input_MouseDown); - IDisplayCluster::Get().GetClusterMgr()->EmitClusterEventBinary(ClusterEvent, false); - return FReply::Handled(); + DasherMainInterface->KeyDown(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Secondary_Input); + UpdateMouseInteraction(MouseEvent.GetPointerIndex()); + BoostListeners.ExecuteIfBound(MouseEvent.GetPointerIndex(), true); } + MouseState.DisabledDueToMouseLeave = false; + } +} - if (CurrentlyUsingVectorInput) - { - CurrentlyUsingVectorInput = false; - return FReply::Handled(); - } - DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); - } - return FReply::Handled(); +void SDasherWidget::OnMouseLeave(const FPointerEvent& MouseEvent) +{ + SWidget::OnMouseLeave(MouseEvent); + + FMouseState& MouseState = GetMouseState(MouseEvent.GetPointerIndex()); + MouseState.CurrentlyHovering = false; + + if (InputPaused) return; + + if(MouseState.PrimaryButtonPressed) + { + DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); + MouseListeners.ExecuteIfBound(MouseEvent.GetPointerIndex(), false); + MouseState.DisabledDueToMouseLeave = true; + } + + if(MouseState.SecondaryButtonPressed) + { + DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Secondary_Input); + BoostListeners.ExecuteIfBound(MouseEvent.GetPointerIndex(), false); + MouseState.DisabledDueToMouseLeave = true; + } +} + +FReply SDasherWidget::OnMouseButtonDoubleClick(const FGeometry& InMyGeometry, const FPointerEvent& InMouseEvent) +{ + return OnMouseButtonUp(InMyGeometry, InMouseEvent); +} + +FReply SDasherWidget::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) +{ + FMouseState& MouseState = GetMouseState(MouseEvent.GetPointerIndex()); + + if(MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton && MouseState.PrimaryButtonPressed) + { + DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); + MouseState.PrimaryButtonPressed = false; + MouseListeners.ExecuteIfBound(MouseEvent.GetPointerIndex(), MouseState.PrimaryButtonPressed); + } + else if(MouseEvent.GetEffectingButton() == EKeys::RightMouseButton && MouseState.SecondaryButtonPressed) + { + DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Secondary_Input); + MouseState.SecondaryButtonPressed = false; + BoostListeners.ExecuteIfBound(MouseEvent.GetPointerIndex(), MouseState.SecondaryButtonPressed); + } + + return FReply::Handled(); } //Set in the HandleMouseMoveEvent or via Set InputVector //See tick for geometry things that could be use to modify this. FVector2D SDasherWidget::GetCursorPosition() const { - return FVector2D(CursorPosition.x, CursorPosition.y); + const int lastInteraction = GetLastActiveMouseInteraction(); + + if(!MouseStates.Contains(lastInteraction)) return DasherMainInterface->ConvertDasher2Screen(Dasher::CDasherModel::ORIGIN_X, Dasher::CDasherModel::ORIGIN_Y); + + return MouseStates[lastInteraction].CursorPosition; } bool SDasherWidget::GetScreenCoords(screenint& iX, screenint& iY, Dasher::CDasherView* pView) { - const FVector2D Position = GetCursorPosition(); + const FVector2D Position = GetCursorPosition(); - iX = Position.X; - iY = Position.Y; + iX = Position.X; + iY = Position.Y; - return true; + return true; } -void SDasherWidget::HandleClusterEvent(const FDisplayClusterClusterEventBinary& Event) +void SDasherWidget::InputVector(const FVector2D InputVector) { - switch(static_cast<DasherEventType>(Event.EventId - DasherEventID)) - { - case DasherEventType::Input_MouseDown: - DasherMainInterface->KeyDown(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); - MouseDownListeners.ExecuteIfBound(); - UE_LOG(LogTemp, Log, TEXT("MouseDownReceived")); - break; - case DasherEventType::Input_MouseUp: - DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); - MouseUpListeners.ExecuteIfBound(); - break; - case DasherEventType::Tick: - double currentTime = 0; - - FMemory::Memcpy(¤tTime, Event.EventData.GetData(), sizeof(currentTime)); - FMemory::Memcpy(&CursorPosition.x, Event.EventData.GetData() + sizeof(currentTime), sizeof(CursorPosition.x)); - FMemory::Memcpy(&CursorPosition.y, Event.EventData.GetData() + sizeof(currentTime) + sizeof(CursorPosition.x), sizeof(CursorPosition.y)); - - //DasherMainInterface->Tick(static_cast<unsigned long>(currentTime * 1000.0)); - break; - } + if (InputPaused) return; + + FMouseState& MouseState = GetMouseState(VectorInputPointerIndex); + + MouseState.CursorPosition = DasherMainInterface->ConvertDasher2Screen(Dasher::CDasherModel::ORIGIN_X, Dasher::CDasherModel::ORIGIN_Y) + + InputVector * FVector2D(1.0f, -1.0f) * (GetHeight() / 2); + + MouseState.CurrentlyHovering = InputVector.Size() > 0.01; //Deadzone } -void SDasherWidget::InputVector(const FVector2D InputVector) +void SDasherWidget::VectorInputButton(bool Pressed) { - if (!InputPaused) { - if (!CurrentlyUsingVectorInput) return; - const FVector2D pos = DasherMainInterface->ConvertDasher2Screen(Dasher::CDasherModel::ORIGIN_X, Dasher::CDasherModel::ORIGIN_Y) - + InputVector * FVector2D(1.0f, -1.0f) * (GetHeight() / 2); - CursorPosition.x = pos.X; - CursorPosition.y = pos.Y; - } + if (InputPaused) return; + + FMouseState& MouseState = GetMouseState(VectorInputPointerIndex); + + if (Pressed) + { + DasherMainInterface->KeyDown(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); + MouseState.PrimaryButtonPressed = true; + UpdateMouseInteraction(VectorInputPointerIndex); + } + else + { + DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); + MouseState.PrimaryButtonPressed = false; + } } -void SDasherWidget::InputButton(bool Pressed) +void SDasherWidget::VectorBoostButton(bool Pressed) { - if (!InputPaused) { - CurrentlyUsingVectorInput = true; - if (Pressed) - { - DasherMainInterface->KeyDown(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); - } - else { - DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); - } - } + if (InputPaused) return; + + FMouseState& MouseState = GetMouseState(VectorInputPointerIndex); + + if (Pressed) + { + DasherMainInterface->KeyDown(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Secondary_Input); + MouseState.SecondaryButtonPressed = true; + } + else + { + DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Secondary_Input); + MouseState.SecondaryButtonPressed = false; + } + + UpdateMouseInteraction(VectorInputPointerIndex); } //The construction of the Dasher Widget, Dasher parameters are set here, a function to set them outside is not provided, but can be easily implemented void SDasherWidget::Construct(const FArguments& InArgs) { - //Initial resize, needed for setup - Width = InArgs._width; - Height = InArgs._height; - resize(Width, Height); - - //initialize the font measuring service. - FontMeasureService = FSlateApplication::Get().GetRenderer()->GetFontMeasureService(); - - //Setting up Dasher - static Dasher::XMLErrorDisplay display; - Dasher::XmlSettingsStore* Settings = new Dasher::XmlSettingsStore("Settings.xml", &display); //Gets deleted somewhere else - Settings->Load(); - Settings->Save(); - DasherMainInterface = MakeShared<Dasher::DasherInterface>(Settings); - DasherMainInterface->GetModuleManager()->RegisterInputDeviceModule(this, true); - - DasherMainInterface->SetScreen(this); - DasherMainInterface->SetBuffer(0); - - DasherMainInterface->SetCharEnteredCallback([this](FString Char, FString Buffer) {CharacterEnteredFlag = true; AlteredChar = Char; }); - DasherMainInterface->SetCharDeletedCallback([this](FString Char, FString Buffer) {CharacterDeletedFlag = true; AlteredChar = Char; }); - - // Bind the cluster events that manage the door state. - IDisplayClusterClusterManager* ClusterManager = IDisplayCluster::Get().GetClusterMgr(); - if (URWTHVRUtilities::IsRoomMountedMode() && ClusterManager && !ClusterEventListener.IsBound()) - { - ClusterEventListener = - FOnClusterEventBinaryListener::CreateSP(this, &SDasherWidget::HandleClusterEvent); - ClusterManager->AddClusterEventBinaryListener(ClusterEventListener); - } - - if (URWTHVRUtilities::IsPrimaryNode()) - { - //Set up the Event Handlers for Mouse Movement etc. - SetOnMouseMove(FPointerEventHandler::CreateLambda([this](const FGeometry& Geometry, const FPointerEvent& MouseEvent) {return HandleMouseMoveEvent(Geometry, MouseEvent); })); - SetOnMouseButtonDown(FPointerEventHandler::CreateLambda([this](const FGeometry& Geometry, const FPointerEvent& MouseEvent) {return HandleMouseDownEvent(Geometry, MouseEvent); })); - SetOnMouseButtonUp(FPointerEventHandler::CreateLambda([this](const FGeometry& Geometry, const FPointerEvent& MouseEvent) {return HandleMouseUpEvent(Geometry, MouseEvent); })); - SetOnMouseDoubleClick(FPointerEventHandler::CreateLambda([this](const FGeometry& Geometry, const FPointerEvent& MouseEvent) {return HandleMouseDoubleClickEvent(Geometry, MouseEvent); })); //We treat a double click of the mouse as a lift of the mouse button. - } + //Initial resize, needed for setup + Width = InArgs._width; + Height = InArgs._height; + resize(Width, Height); + + //initialize the font measuring service. + FontMeasureService = FSlateApplication::Get().GetRenderer()->GetFontMeasureService(); + + //Setting up Dasher + static Dasher::XMLErrorDisplay display; + Dasher::XmlSettingsStore* Settings = new Dasher::XmlSettingsStore("Settings.xml", &display); //Gets deleted somewhere else + Settings->Load(); + Settings->Save(); + DasherMainInterface = MakeShared<Dasher::DasherInterface>(Settings); + DasherMainInterface->GetModuleManager()->RegisterInputDeviceModule(this, true); + + DasherMainInterface->SetScreen(this); + DasherMainInterface->SetBuffer(0); + + DasherMainInterface->SetCharEnteredCallback([this](FString Char, FString Buffer) + { + CharacterEntered.ExecuteIfBound(Char, Buffer); + CharEnteredInFrame = true; + BufferAltered.ExecuteIfBound(Buffer); + }); + DasherMainInterface->SetCharDeletedCallback([this](FString Char, FString Buffer) + { + CharacterDeleted.ExecuteIfBound(Char, Buffer); + CharDeletedInFrame = true; + BufferAltered.ExecuteIfBound(Buffer); + }); } -void SDasherWidget::SetParameter(FString& ParameterName, bool Value) { - DasherMainInterface->SetBoolParameter(Dasher::Settings::GetParameter(TCHAR_TO_UTF8(*ParameterName)).first, Value); +void SDasherWidget::SetParameter(FString& ParameterName, bool Value) +{ + for (auto param = Dasher::Settings::parameter_defaults.begin(); param != Dasher::Settings::parameter_defaults.end(); ++param) + if (param->second.name == TCHAR_TO_UTF8(*ParameterName)) + { + DasherMainInterface->SetBoolParameter(param->first, Value); + return; + } } -void SDasherWidget::SetParameter(FString& ParameterName, int64 Value) { - DasherMainInterface->SetLongParameter(Dasher::Settings::GetParameter(TCHAR_TO_UTF8(*ParameterName)).first, Value); +void SDasherWidget::SetParameter(FString& ParameterName, int64 Value) +{ + for (auto param = Dasher::Settings::parameter_defaults.begin(); param != Dasher::Settings::parameter_defaults.end(); ++param) + if (param->second.name == TCHAR_TO_UTF8(*ParameterName)) + { + DasherMainInterface->SetLongParameter(param->first, Value); + return; + } } -void SDasherWidget::SetParameter(FString& ParameterName, FString Value) { - DasherMainInterface->SetStringParameter(Dasher::Settings::GetParameter(TCHAR_TO_UTF8(*ParameterName)).first, TCHAR_TO_UTF8(*Value)); +void SDasherWidget::SetParameter(FString& ParameterName, FString Value) +{ + for (auto param = Dasher::Settings::parameter_defaults.begin(); param != Dasher::Settings::parameter_defaults.end(); ++param) + if (param->second.name == TCHAR_TO_UTF8(*ParameterName)) + { + DasherMainInterface->SetStringParameter(param->first, TCHAR_TO_UTF8(*Value)); + return; + } } //paints our stuff, then lets compoundwidget (super::) draw its stuff +//This draws from bottom to top rectangles->lines->labels, this is enough for our use, but for more complex scenarios a proper layering system might have to be implemented int32 SDasherWidget::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const { - ////this doesn't draw anything red, we just need a brush. Could probably find a better "empty" brush - auto MyBrush = FSlateColorBrush(FColor::Red); - - FFilledRect* RectObject; - FWriting* WritingObject; - FPolyLine* LineObject; - FVector2D Size; - FString Text; - FSlateFontInfo Font; - - TArray<TUniquePtr<DasherDrawGeometry>>& GeometryBuffer = *FrontBuffer; - for (TUniquePtr<DasherDrawGeometry>& GeneralObject : GeometryBuffer) { - switch (GeneralObject->Type) - { - case GeometryType::Rectangle: - RectObject = static_cast<FFilledRect*>(GeneralObject.Get()); - Size = { FMath::Abs(RectObject->top.X - RectObject->bottom.X), FMath::Abs(RectObject->top.Y - RectObject->bottom.Y) }; - FSlateDrawElement::MakeBox(OutDrawElements, LayerId++, AllottedGeometry.ToPaintGeometry(Size, FSlateLayoutTransform(1, RectObject->top)), &MyBrush, ESlateDrawEffect::None, RectObject->color); //actually adds the box to the geometry - break; - case GeometryType::Writing: - WritingObject = static_cast<FWriting*>(GeneralObject.Get()); - Font = FCoreStyle::GetDefaultFontStyle("Roboto", WritingObject->size, FFontOutlineSettings::NoOutline); //get the font - FSlateDrawElement::MakeText(OutDrawElements, LayerId++, AllottedGeometry.ToPaintGeometry(FSlateLayoutTransform(1, FVector2D(WritingObject->pos.X, WritingObject->pos.Y))), WritingObject->label, Font, ESlateDrawEffect::None, WritingObject->color); - break; - case GeometryType::PolyLine: - LineObject = static_cast<FPolyLine*>(GeneralObject.Get()); - FSlateDrawElement::MakeLines(OutDrawElements, LayerId++, AllottedGeometry.ToPaintGeometry(), LineObject->points, ESlateDrawEffect::None, LineObject->color, LineObject->AntiAliasing, LineObject->linewidth); - break; - default: break; - } - } - - return SCompoundWidget::OnPaint(Args, AllottedGeometry, MyClippingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled); //call the parent onPaint + //this doesn't draw anything red, we just need a brush. Could probably find a better "empty" brush + auto MyBrush = FSlateColorBrush(FColor::Red); + + FFilledRect* RectObject; + FWriting* WritingObject; + FPolyLine* LineObject; + FVector2D Size; + FString Text; + FSlateFontInfo Font; + + TArray<TUniquePtr<DasherDrawGeometry>>& GeometryBuffer = *FrontBuffer; + for (TUniquePtr<DasherDrawGeometry>& GeneralObject : GeometryBuffer) + { + switch (GeneralObject->Type) + { + case GeometryType::Rectangle: + RectObject = static_cast<FFilledRect*>(GeneralObject.Get()); + Size = {FMath::Abs(RectObject->top.X - RectObject->bottom.X), FMath::Abs(RectObject->top.Y - RectObject->bottom.Y)}; + FSlateDrawElement::MakeBox(OutDrawElements, LayerId++, AllottedGeometry.ToPaintGeometry(Size, FSlateLayoutTransform(1, RectObject->top)), &MyBrush, ESlateDrawEffect::None, RectObject->color); //actually adds the box to the geometry + break; + case GeometryType::Writing: + WritingObject = static_cast<FWriting*>(GeneralObject.Get()); + Text = FString(*WritingObject->label); + + Font = FCoreStyle::GetDefaultFontStyle("Roboto", WritingObject->size, FFontOutlineSettings::NoOutline); //get the font + FSlateDrawElement::MakeText(OutDrawElements, LayerId++, AllottedGeometry.ToPaintGeometry(FSlateLayoutTransform(1, FVector2D(WritingObject->pos.X, WritingObject->pos.Y))), Text, Font, ESlateDrawEffect::None, WritingObject->color); + break; + case GeometryType::PolyLine: + LineObject = static_cast<FPolyLine*>(GeneralObject.Get()); + FSlateDrawElement::MakeLines(OutDrawElements, LayerId++, AllottedGeometry.ToPaintGeometry(), LineObject->points, ESlateDrawEffect::None, LineObject->color, true, LineObject->linewidth); + break; + default: break; + } + } + + return SCompoundWidget::OnPaint(Args, AllottedGeometry, MyClippingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled); //call the parent onPaint } //The tick function, we tick dasher in it and update the screen size for dasher -void SDasherWidget::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) { - SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime); - - //don't tick in the editor - if (IsEditor || InputPaused) return; - - //Needs to be updated in Tick due to event order in cluster mode - CursorPosition = NewMousePosition; - - if(!URWTHVRUtilities::IsRoomMountedMode()){ - DasherMainInterface->Tick(static_cast<unsigned long>(InCurrentTime * 1000.0)); //we need to provide ticks in milliseconds - } - else - if(URWTHVRUtilities::IsPrimaryNode()) - { - FDisplayClusterClusterEventBinary ClusterEvent; - ClusterEvent.EventId = ClusterEvent.EventId = DasherEventID + static_cast<uint8>(DasherEventType::Tick); - ClusterEvent.EventData.SetNumUninitialized(sizeof(InCurrentTime) + sizeof(CursorPosition.x) + sizeof(CursorPosition.y)); - - FMemory::Memcpy(ClusterEvent.EventData.GetData(), &InCurrentTime, sizeof(InCurrentTime)); - FMemory::Memcpy(ClusterEvent.EventData.GetData() + sizeof(InCurrentTime), &CursorPosition.x, sizeof(CursorPosition.x)); - FMemory::Memcpy(ClusterEvent.EventData.GetData() + sizeof(InCurrentTime) + sizeof(CursorPosition.x), &CursorPosition.y, sizeof(CursorPosition.y)); - - IDisplayCluster::Get().GetClusterMgr()->EmitClusterEventBinary(ClusterEvent, false); - } - - //This probably doesn't have to be done every tick, but it does not seem to have a huge hit on performance - const FGeometry Geometry = GetTickSpaceGeometry(); - const FIntPoint AbsoluteSize = Geometry.Size.IntPoint(); - if (Width != AbsoluteSize.X || Height != AbsoluteSize.Y) { - Width = AbsoluteSize.X; - Height = AbsoluteSize.Y; - resize(Width, Height); - //tell dasher we resized the screen, but only if there's actually a screen - if (Width && Height) DasherMainInterface->ScreenResized(this); - } +void SDasherWidget::Tick(const FGeometry& AllotedGeometry, const double InCurrentTime, const float InDeltaTime) +{ + //don't tick in the editor + if (!IsEditor) + { + SCompoundWidget::Tick(AllotedGeometry, InCurrentTime, InDeltaTime); + + DasherMainInterface->Tick(static_cast<unsigned long>(InCurrentTime * 1000.0)); //we need to provide ticks in milliseconds + + + //This probably doesn't have to be done every tick, but it does not seem to have a huge hit on performance + const FGeometry Geometry = GetTickSpaceGeometry(); + const FIntPoint AbsoluteSize = Geometry.Size.IntPoint(); + if (Width != AbsoluteSize.X || Height != AbsoluteSize.Y) + { + Width = AbsoluteSize.X; + Height = AbsoluteSize.Y; + resize(Width, Height); + //tell dasher we resized the screen, but only if there's actually a screen + if (Width && Height) DasherMainInterface->ScreenResized(this); + }; + } } -std::pair<Dasher::screenint, Dasher::screenint> SDasherWidget::TextSize(Label* Label, unsigned Size) +std::pair<SDasherWidget::screenint, SDasherWidget::screenint> SDasherWidget::TextSize(CDasherScreen::Label* Label, unsigned Size) { - const FSlateFontInfo Font = FCoreStyle::GetDefaultFontStyle("Roboto", Size, FFontOutlineSettings::NoOutline); //get the font - const FVector2D TextSize = FontMeasureService->Measure(FString(UTF8_TO_TCHAR(Label->m_strText.c_str())), Font, 1); //get the real size of the text, using the fontmeasuring service - return { static_cast<screenint>(TextSize.X), static_cast<screenint>(TextSize.Y) }; + const FSlateFontInfo Font = FCoreStyle::GetDefaultFontStyle("Roboto", Size, FFontOutlineSettings::NoOutline); //get the font + const FVector2D TextSize = FontMeasureService->Measure(FString(UTF8_TO_TCHAR(Label->m_strText.c_str())), Font, 1); //get the real size of the text, using the fontmeasuring service + return {static_cast<screenint>(TextSize.X), static_cast<screenint>(TextSize.Y)}; } //Double Buffers are rotated here. -void SDasherWidget::Display() { - std::swap(FrontBuffer, BackBuffer); - BackBuffer->Empty(); - - if (CharacterEnteredFlag && CharacterDeletedFlag) { - CharacterSwitched.ExecuteIfBound(AlteredChar, GetBuffer()); - } - else if (CharacterEnteredFlag) { - CharacterEntered.ExecuteIfBound(AlteredChar, GetBuffer()); - } - else if (CharacterDeletedFlag) { - CharacterDeleted.ExecuteIfBound(AlteredChar, GetBuffer()); - } - - CharacterEnteredFlag = false; - CharacterDeletedFlag = false; +void SDasherWidget::Display() +{ + std::swap(FrontBuffer, BackBuffer); + BackBuffer->Empty(); + + if(CharEnteredInFrame && CharDeletedInFrame) + { + CharacterSwitchedLastFrame.ExecuteIfBound(); + } + else if(CharEnteredInFrame) + { + CharacterEnteredLastFrame.ExecuteIfBound(); + } + else if(CharDeletedInFrame) + { + CharacterDeletedLastFrame.ExecuteIfBound(); + } + + CharEnteredInFrame = false; + CharDeletedInFrame = false; + + DasherFrameCompleted.ExecuteIfBound(); } +//Only for testing +#define s(X) static_cast<uint8>(FMath::Clamp(X*(((colour>= 10 && colour <= 36) || (colour>= 140 && colour <= 166)) ? brightness : 1.0f),0.0f,255.0f)) + //Functions for Drawing void SDasherWidget::DrawRectangle(Dasher::screenint x1, Dasher::screenint y1, Dasher::screenint x2, Dasher::screenint y2, const Dasher::ColorPalette::Color& color, const Dasher::ColorPalette::Color& outlineColor, int iThickness) { @@ -397,22 +462,24 @@ void SDasherWidget::Polygon(CDasherScreen::point* points, int number, const Dash BackBuffer->Add(MakeUnique<FPolyLine>(PointArray, static_cast<float>(iwidth), FLinearColor(outlinecolor.Red / 255.0f, outlinecolor.Green / 255.0f, outlinecolor.Blue / 255.0f, outlinecolor.Alpha / 255.0f), true)); } + //We pass through the contents of the dasher buffer FString SDasherWidget::GetBuffer() const { - return DasherMainInterface->GetBuffer(); + return DasherMainInterface->GetBuffer(); } void SDasherWidget::ResetBuffer() { - DasherMainInterface->ResetBuffer(); + DasherMainInterface->ResetBuffer(); } void SDasherWidget::StartTraining(FString PathToTextFile) { - DasherMainInterface->ImportTrainingFile(TCHAR_TO_UTF8(*FPaths::ConvertRelativePathToFull(PathToTextFile))); + DasherMainInterface->ImportTrainingFile(TCHAR_TO_UTF8(*FPaths::ConvertRelativePathToFull(PathToTextFile))); } + // ++ We need to undefine this namespace after we finish creating the Slate widget #undef LOCTEXT_NAMESPACE diff --git a/Source/DasherVR/Private/UDasherWidget.cpp b/Source/DasherVR/Private/UDasherWidget.cpp index b5482574059a07465e738949d71e87d5c52e0c1d..ca9fef7ac5665402d28c5b7da55b73042a9a5e09 100644 --- a/Source/DasherVR/Private/UDasherWidget.cpp +++ b/Source/DasherVR/Private/UDasherWidget.cpp @@ -11,110 +11,105 @@ UDasherWidget::UDasherWidget(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { - //Default Values Set Here, see above + //Default Values Set Here, see above } //Rebuild using custom Slate Widget TSharedRef<SWidget> UDasherWidget::RebuildWidget() { - if (!DasherScreen) - { - DasherScreen = SNew(SDasherWidget).height(1080).width(1920); - } - return DasherScreen.ToSharedRef(); + if (!DasherScreen) + { + DasherScreen = SNew(SDasherWidget).height(1080).width(1920); + } + return DasherScreen.ToSharedRef(); } void UDasherWidget::SynchronizeProperties() { - Super::SynchronizeProperties(); - - //Check if we're in Editor - DasherScreen->SetEditor(IsDesignTime()); - DasherScreen->CharacterEntered.BindLambda([this](FString Char, FString Buffer) - { - CharacterEntered.Broadcast(Char, Buffer); - BufferAltered.Broadcast(Buffer); - }); - DasherScreen->CharacterDeleted.BindLambda([this](FString Char, FString Buffer) - { - CharacterDeleted.Broadcast(Char, Buffer); - BufferAltered.Broadcast(Buffer); - }); - DasherScreen->CharacterSwitched.BindLambda([this](FString Char, FString Buffer) - { - CharacterSwitched.Broadcast(Char, Buffer); - BufferAltered.Broadcast(Buffer); - }); - DasherScreen->MouseUpListeners.BindLambda([this]() {MouseEvent.Broadcast(false); }); - DasherScreen->MouseDownListeners.BindLambda([this]() {MouseEvent.Broadcast(true); }); + Super::SynchronizeProperties(); + + //Check if we're in Editor + DasherScreen->SetEditor(IsDesignTime()); + DasherScreen->CharacterEntered.BindLambda([this](FString Char, FString Buffer){CharacterEntered.Broadcast(Char, Buffer); }); + DasherScreen->CharacterDeleted.BindLambda([this](FString Char, FString Buffer){CharacterDeleted.Broadcast(Char, Buffer); }); + DasherScreen->MouseListeners.BindLambda([this](int index, bool pressed) { MouseEvent.Broadcast(index, pressed); }); + DasherScreen->BoostListeners.BindLambda([this](int index, bool pressed) { BoostEvent.Broadcast(index, pressed); }); + DasherScreen->BufferAltered.BindLambda([this](FString Buffer) { BufferAltered.Broadcast(Buffer); }); + DasherScreen->CharacterEnteredLastFrame.BindLambda([this](){ CharacterEnteredLastFrame.Broadcast(); }); + DasherScreen->CharacterDeletedLastFrame.BindLambda([this](){ CharacterDeletedLastFrame.Broadcast(); }); + DasherScreen->CharacterSwitchedLastFrame.BindLambda([this](){ CharacterSwitchedLastFrame.Broadcast(); }); + DasherScreen->DasherFrameCompleted.BindLambda([this]() { DasherFrameCompleted.Broadcast(); }); } void UDasherWidget::ReleaseSlateResources(bool bReleaseChildren) { - Super::ReleaseSlateResources(bReleaseChildren); + Super::ReleaseSlateResources(bReleaseChildren); - DasherScreen.Reset(); + if(bReleaseChildren) DasherScreen.Reset(); } FString UDasherWidget::GetBuffer() { - return DasherScreen->GetBuffer(); + if(!DasherScreen) return ""; + return DasherScreen->GetBuffer(); } void UDasherWidget::ResetBuffer() { - DasherScreen->ResetBuffer(); - BufferAltered.Broadcast(""); + if(!DasherScreen) return; + DasherScreen->ResetBuffer(); + BufferAltered.Broadcast(""); } void UDasherWidget::StartTraining(FString PathToTextFile) { - DasherScreen->StartTraining(PathToTextFile); + if(!DasherScreen) return; + DasherScreen->StartTraining(PathToTextFile); } void UDasherWidget::SetBoolParamter(FString ParameterName, bool Value) { - DasherScreen->SetParameter(ParameterName, Value); + if(!DasherScreen) return; + DasherScreen->SetParameter(ParameterName, Value); } void UDasherWidget::SetLongParamter(FString ParameterName, int64 Value) { - DasherScreen->SetParameter(ParameterName, Value); + if(!DasherScreen) return; + DasherScreen->SetParameter(ParameterName, Value); } void UDasherWidget::SetStringParamter(FString ParameterName, FString Value) { - DasherScreen->SetParameter(ParameterName, Value); + if(!DasherScreen) return; + DasherScreen->SetParameter(ParameterName, Value); } void UDasherWidget::InputButton(bool Pressed) { - DasherScreen->InputButton(Pressed); + if(!DasherScreen) return; + DasherScreen->VectorInputButton(Pressed); } void UDasherWidget::InputVector(FVector2D InputVector) { + if(!DasherScreen) return; DasherScreen->InputVector(InputVector); } -void UDasherWidget::PauseInput() +bool UDasherWidget::GetInputEnabled() const { - DasherScreen->PauseInput(); + if(!DasherScreen) return false; + return DasherScreen->GetInputEnabled(); } -void UDasherWidget::UnpauseInput() +void UDasherWidget::EnableInput(bool enabled) { - DasherScreen->UnpauseInput(); + if(!DasherScreen) return; + DasherScreen->EnableInput(enabled); } - #if WITH_EDITOR - -//const FSlateBrush* UDasherWidget::GetEditorIcon() -//{ -// return FUMGStyle::Get().GetBrush("Widget.Image"); -//} - const FText UDasherWidget::GetPaletteCategory() { return LOCTEXT("Common", "Common"); @@ -125,4 +120,4 @@ const FText UDasherWidget::GetPaletteCategory() ///////////////////////////////////////////////////// -#undef LOCTEXT_NAMESPACE \ No newline at end of file +#undef LOCTEXT_NAMESPACE diff --git a/Source/DasherVR/Public/SDasherWidget.h b/Source/DasherVR/Public/SDasherWidget.h index 6b6f74603623baab4861e96fe86c1bbf468a4e0f..b3e125514a7cf7e7315947b8cd992c54ec692e22 100644 --- a/Source/DasherVR/Public/SDasherWidget.h +++ b/Source/DasherVR/Public/SDasherWidget.h @@ -16,6 +16,7 @@ enum class GeometryType : uint8 { + Rectangle = 0, Writing = 1, PolyLine = 2 @@ -48,7 +49,6 @@ struct FWriting : DasherDrawGeometry{ FVector2D pos; int size; FLinearColor color; - FWriting(FString Label, FVector2D Pos, int Size, FLinearColor Color) : DasherDrawGeometry(GeometryType::Writing), label(Label), pos(Pos), size(Size), color(Color) {} }; @@ -61,15 +61,26 @@ struct FPolyLine : DasherDrawGeometry{ FPolyLine(TArray<FVector2D> Points, float LineWidth, FLinearColor Color, bool AntiAliasing): DasherDrawGeometry(GeometryType::PolyLine), points(Points), linewidth(LineWidth), AntiAliasing(AntiAliasing), color(Color) {} }; -DECLARE_DELEGATE(FDasherMouseUpDelegate); -DECLARE_DELEGATE(FDasherMouseDownDelegate); -DECLARE_DELEGATE_TwoParams(FBufferManiputlationDelegate, FString, FString); +struct FMouseState +{ + bool PrimaryButtonPressed = false; + bool SecondaryButtonPressed = false; + bool DisabledDueToMouseLeave = false; + FVector2D CursorPosition = {0,0}; + bool CurrentlyHovering = true; +}; + +DECLARE_DELEGATE(FDasherEventDelegate); +DECLARE_DELEGATE_TwoParams(FDasherMouseDelegate, int, bool); +DECLARE_DELEGATE_OneParam(FBufferManiputlationDelegate, FString); +DECLARE_DELEGATE_TwoParams(FCharManiputlationDelegate, FString, FString); class DASHERVR_API SDasherWidget : public SCompoundWidget, public Dasher::CDasherScreen, public Dasher::CScreenCoordInput { public: + SLATE_BEGIN_ARGS(SDasherWidget) {} @@ -122,30 +133,35 @@ public: void SetEditor(bool EditorState); //mouse handling function - FReply HandleMouseMoveEvent(const FGeometry& Geometry, const FPointerEvent& MouseEvent); - FReply HandleMouseDownEvent(const FGeometry& Geometry, const FPointerEvent& MouseEvent); - FReply HandleMouseUpEvent(const FGeometry& Geometry, const FPointerEvent& MouseEvent); - FReply HandleMouseDoubleClickEvent(const FGeometry& Geometry, const FPointerEvent& MouseEvent); + virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; + virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; + virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; + virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override; + virtual FReply OnMouseButtonDoubleClick(const FGeometry& InMyGeometry, const FPointerEvent& InMouseEvent) override; + virtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; virtual bool SupportsKeyboardFocus() const override {return true;} virtual bool GetScreenCoords(screenint& iX, screenint& iY, Dasher::CDasherView* pView) override; - void HandleClusterEvent(const FDisplayClusterClusterEventBinary& Event); - void InputVector(FVector2D InputVector); - void InputButton(bool Pressed); + void VectorInputButton(bool Pressed); + void VectorBoostButton(bool Pressed); FVector2D GetCursorPosition() const; //Allows to Pause Input - void PauseInput(); - void UnpauseInput(); - - FDasherMouseUpDelegate MouseUpListeners; - FDasherMouseUpDelegate MouseDownListeners; - FBufferManiputlationDelegate CharacterEntered; - FBufferManiputlationDelegate CharacterDeleted; + void EnableInput(bool enable); + bool GetInputEnabled() const; FBufferManiputlationDelegate CharacterSwitched; + FDasherMouseDelegate MouseListeners; + FDasherMouseDelegate BoostListeners; + FCharManiputlationDelegate CharacterEntered; + FCharManiputlationDelegate CharacterDeleted; + FDasherEventDelegate CharacterEnteredLastFrame; + FDasherEventDelegate CharacterDeletedLastFrame; + FDasherEventDelegate CharacterSwitchedLastFrame; + FBufferManiputlationDelegate BufferAltered; + FDasherEventDelegate DasherFrameCompleted; private: @@ -157,18 +173,23 @@ private: int Height = 0; int Width = 0; - bool HasBeenPainted = false; + bool CurrentlyUsingVectorInput = false; point CursorPosition = {0,0}; point NewMousePosition = {0,0}; - bool CharacterEnteredFlag = false; - bool CharacterDeletedFlag = false; - FString AlteredChar = ""; - - //are we in the Editor? - bool IsEditor = true; - //is the input paused - bool InputPaused = false; + + bool IsEditor = true; //are we in the Editor? + bool CharDeletedInFrame = false; + bool CharEnteredInFrame = false; + bool InputPaused = false; //is the input paused + + //Mouse States + TMap<int, FMouseState> MouseStates; + TArray<int> MouseInteractions; + const int VectorInputPointerIndex = 42; + FMouseState& GetMouseState(int Index); + void UpdateMouseInteraction(int Index); + int GetLastActiveMouseInteraction() const; //set up the font measure service to ... measure fonts. TSharedPtr<FSlateFontMeasure> FontMeasureService; diff --git a/Source/DasherVR/Public/UDasherWidget.h b/Source/DasherVR/Public/UDasherWidget.h index 849b3f18dd56781b6d47fd2534552aae1ac997cb..aa56bf36935d096709b7a384e8dedd79d66c991e 100644 --- a/Source/DasherVR/Public/UDasherWidget.h +++ b/Source/DasherVR/Public/UDasherWidget.h @@ -14,7 +14,8 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FCharManipulatedEvent, FString, Char, FString, Buffer); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBufferManipulatedEvent, FString, Buffer); -DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMouseEvent, bool, IsMouseDown); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FMouseEvent, int, PointerIndex, bool, IsMouseDown); +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDasherEvent); UCLASS(BlueprintType) class DASHERVR_API UDasherWidget : public UWidget @@ -40,15 +41,19 @@ public: UFUNCTION(BlueprintCallable) void InputButton(bool Pressed); UFUNCTION(BlueprintCallable) void InputVector(FVector2D InputVector); - UFUNCTION(BlueprintCallable) void PauseInput(); - UFUNCTION(BlueprintCallable) void UnpauseInput(); + UFUNCTION(BlueprintPure) bool GetInputEnabled() const; + UFUNCTION(BlueprintCallable) void EnableInput(bool enabled); UPROPERTY(BlueprintAssignable) FCharManipulatedEvent CharacterEntered; UPROPERTY(BlueprintAssignable) FCharManipulatedEvent CharacterDeleted; UPROPERTY(BlueprintAssignable) FCharManipulatedEvent CharacterSwitched; UPROPERTY(BlueprintAssignable) FBufferManipulatedEvent BufferAltered; UPROPERTY(BlueprintAssignable) FMouseEvent MouseEvent; - + UPROPERTY(BlueprintAssignable) FMouseEvent BoostEvent; + UPROPERTY(BlueprintAssignable) FDasherEvent DasherFrameCompleted; + UPROPERTY(BlueprintAssignable) FDasherEvent CharacterSwitchedLastFrame; + UPROPERTY(BlueprintAssignable) FDasherEvent CharacterEnteredLastFrame; + UPROPERTY(BlueprintAssignable) FDasherEvent CharacterDeletedLastFrame; public: // UWidget interface diff --git a/Source/Thirdparty/Dasher/Dasher.Build.cs b/Source/Thirdparty/Dasher/Dasher.Build.cs index 9b52064c9bf9ddab1f234fe6fcb97f4c443960cb..c931821c7ff76d307f07cb8e5ec5ea377c4d2af4 100644 --- a/Source/Thirdparty/Dasher/Dasher.Build.cs +++ b/Source/Thirdparty/Dasher/Dasher.Build.cs @@ -8,7 +8,8 @@ public class Dasher : ModuleRules { public Dasher(ReadOnlyTargetRules Target) : base(Target) { - PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + PCHUsage = PCHUsageMode.NoSharedPCHs; + CppStandard = CppStandardVersion.Cpp17; Type = ModuleType.External; PrivateDefinitions.Add("HAVE_OWN_FILEUTILS"); diff --git a/Source/Thirdparty/docker-compose.yml b/Source/Thirdparty/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..8948afe06a22cda17a26c3c2372efba7a5e0fde8 --- /dev/null +++ b/Source/Thirdparty/docker-compose.yml @@ -0,0 +1,6 @@ +services: + builder: + image: ghcr.io/epicgames/unreal-engine:dev-5.3 + volumes: + - ./:/build + command: bash -c "sudo apt-get update && sudo apt-get install -y cmake && cd /build && rm -rf build && mkdir build && cd build && cmake .. && make" \ No newline at end of file