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/Content/InstanceMaterial.uasset b/Content/InstanceMaterial.uasset new file mode 100644 index 0000000000000000000000000000000000000000..2fb267b53bfd278ae16752cd0e518422e251670e --- /dev/null +++ b/Content/InstanceMaterial.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd8257ab5d1829b9ff175b290de9ffed71b9cb974d838f525de39089fdda5e02 +size 49757 diff --git a/Content/textmaterial.uasset b/Content/textmaterial.uasset new file mode 100644 index 0000000000000000000000000000000000000000..ecb4b3901b8284e446d840a556f5dc86a565083c --- /dev/null +++ b/Content/textmaterial.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28e0e621930bd6cfba91edf24730fcf6cde5528501d697e984309a2d4447753f +size 24983 diff --git a/DasherVR.uplugin b/DasherVR.uplugin index 5697244bb824b2d5ab7d1092a8b3ac431876bb83..b36b042eda04d4b521a7fd80db5a18e0e7f11ad7 100644 --- a/DasherVR.uplugin +++ b/DasherVR.uplugin @@ -20,5 +20,15 @@ "Type": "Runtime", "LoadingPhase": "PreDefault" } + ], + "Plugins": [ + { + "Name": "nDisplay", + "Enabled": true + }, + { + "Name": "RWTHVRToolkit", + "Enabled": true + } ] } diff --git a/Source/DasherVR/DasherVR.Build.cs b/Source/DasherVR/DasherVR.Build.cs index d7f74ec1345122dd45a9b6295a765488486a4eb4..bf038bb08991a927c5ae61bfe0a2ecadc83a9817 100644 --- a/Source/DasherVR/DasherVR.Build.cs +++ b/Source/DasherVR/DasherVR.Build.cs @@ -6,7 +6,9 @@ public class DasherVR : ModuleRules { public DasherVR(ReadOnlyTargetRules Target) : base(Target) { - PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + PCHUsage = PCHUsageMode.NoSharedPCHs; + CppStandard = CppStandardVersion.Cpp17; + PrivatePCHHeaderFile = "Private/DasherVRPrivatePCH.h"; PrivateDefinitions.Add("HAVE_OWN_FILEUTILS"); PublicIncludePaths.AddRange( @@ -40,7 +42,9 @@ public class DasherVR : ModuleRules "Slate", "SlateCore", "UMG", - "RenderCore" + "RenderCore", + "DisplayCluster", + "RWTHVRToolkit" // ... add private dependencies that you statically link with here ... } ); diff --git a/Source/DasherVR/Private/DasherFileUtils.cpp b/Source/DasherVR/Private/DasherFileUtils.cpp index 8f346a33bc02e3dee5e606b181ea025213995991..8e1f40a87d2f571c44af9affe5bd94e1cea891da 100644 --- a/Source/DasherVR/Private/DasherFileUtils.cpp +++ b/Source/DasherVR/Private/DasherFileUtils.cpp @@ -2,6 +2,8 @@ #include "DasherCoreWrapper.h" #include "HAL/FileManagerGeneric.h" #include "Misc/FileHelper.h" +#include "Misc/Paths.h" +#include "Internationalization/Regex.h" namespace Dasher { diff --git a/Source/DasherVR/Private/DasherInterface.cpp b/Source/DasherVR/Private/DasherInterface.cpp index 9eaea7b3d89e0c61bf010850ada712ac7c84353a..b6b085be38e353ac3334ae91bd50eaa379499206 100644 --- a/Source/DasherVR/Private/DasherInterface.cpp +++ b/Source/DasherVR/Private/DasherInterface.cpp @@ -28,11 +28,11 @@ namespace Dasher //The next functions operate on the buffer //For now can only return one character around the cursor - std::string DasherInterface::GetTextAroundCursor(Dasher::CControlManager::EditDistance iDist) + std::string DasherInterface::GetTextAroundCursor(Dasher::EditDistance iDist) { if (Buffer.Len()>Cursor) { - if (iDist == Dasher::CControlManager::EditDistance::EDIT_CHAR) + if (iDist == Dasher::EditDistance::EDIT_CHAR) { const FString Output = Buffer.Mid(Cursor, 1); return TCHAR_TO_UTF8(*Output); @@ -47,9 +47,9 @@ namespace Dasher return std::string("Cursor out of bounds"); } - unsigned int DasherInterface::ctrlMove(bool bForwards, Dasher::CControlManager::EditDistance dist) + unsigned int DasherInterface::ctrlMove(bool bForwards, Dasher::EditDistance dist) { - if (dist == Dasher::CControlManager::EditDistance::EDIT_CHAR) + if (dist == Dasher::EditDistance::EDIT_CHAR) { if (bForwards) Cursor++; else Cursor--; @@ -57,9 +57,9 @@ namespace Dasher return Cursor; } - unsigned int DasherInterface::ctrlDelete(bool bForwards, Dasher::CControlManager::EditDistance dist) + unsigned int DasherInterface::ctrlDelete(bool bForwards, Dasher::EditDistance dist) { - if (dist == Dasher::CControlManager::EditDistance::EDIT_CHAR) + if (dist == Dasher::EditDistance::EDIT_CHAR) { const int Index = Cursor - (bForwards ? 0 : 1); const FString DeletedChar = Buffer.Mid(Index, 1); @@ -129,7 +129,7 @@ namespace Dasher NewFrame(time, true); } - void DasherInterface::SetScreen(SDasherWidget* screen) + void DasherInterface::SetScreen(CDasherScreen* screen) { //set the widget as screen that dasher will be displayed on ChangeScreen(screen); diff --git a/Source/DasherVR/Private/DasherVRPrivatePCH.h b/Source/DasherVR/Private/DasherVRPrivatePCH.h new file mode 100644 index 0000000000000000000000000000000000000000..e9cda3f89f2a68c2afdae9ce7dc82a88b39841fb --- /dev/null +++ b/Source/DasherVR/Private/DasherVRPrivatePCH.h @@ -0,0 +1,3 @@ +#pragma once +#include "CoreMinimal.h" +#include "DasherVR.h" \ No newline at end of file diff --git a/Source/DasherVR/Private/SDasherWidget.cpp b/Source/DasherVR/Private/SDasherWidget.cpp index 3e770e343de12e02f56c4f435d14aed58303401e..1d48f4b1c5fcea8f6a9809c9d6733a664389aea2 100644 --- a/Source/DasherVR/Private/SDasherWidget.cpp +++ b/Source/DasherVR/Private/SDasherWidget.cpp @@ -6,6 +6,7 @@ #include "DasherInterface.h" #include "Components/SlateWrapperTypes.h" +#include "Framework/Application/SlateApplication.h" BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION @@ -19,62 +20,173 @@ void SDasherWidget::SetEditor(bool EditorState) IsEditor = EditorState; } +void SDasherWidget::EnableInput(bool enable) +{ + InputPaused = !enable; +} + +bool SDasherWidget::GetInputEnabled() const +{ + 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) 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(); +} + +FMouseState& SDasherWidget::GetMouseState(int Index) +{ + if(!MouseStates.Contains(Index)) MouseStates.Add(Index, {}); + return MouseStates[Index]; +} + +// Moves Item to Back +void SDasherWidget::UpdateMouseInteraction(int Index) +{ + MouseInteractions.RemoveSingle(Index); + MouseInteractions.Add(Index); +} + +int SDasherWidget::GetLastActiveMouseInteraction() const +{ + // Find Mouse that already interacted + for(int i = MouseInteractions.Num() - 1; i >= 0; i--) + { + if(MouseStates[MouseInteractions[i]].CurrentlyHovering) return MouseInteractions[i]; + } + + //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 -1; +} + +FReply SDasherWidget::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { - if (CurrentlyUsingVectorInput) return FReply::Unhandled(); + if (InputPaused) return FReply::Unhandled(); + + FMouseState& MouseState = GetMouseState(MouseEvent.GetPointerIndex()); + //The mouse event only contains the Screen Space Position - CursorPosition = Geometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()); + MouseState.CursorPosition = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()); + MouseState.CurrentlyHovering = true; //ensure hover set + return FReply::Handled(); } -FReply SDasherWidget::HandleMouseDownEvent(const FGeometry& Geometry, const FPointerEvent& MouseEvent) +void SDasherWidget::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { - if (CurrentlyUsingVectorInput) + SWidget::OnMouseEnter(MyGeometry, MouseEvent); + + FMouseState& MouseState = GetMouseState(MouseEvent.GetPointerIndex()); + + //Reenable if button is still pressed + if(MouseState.DisabledDueToMouseLeave) { - CurrentlyUsingVectorInput = false; - return FReply::Handled().LockMouseToWidget(AsShared()); + 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)) + { + DasherMainInterface->KeyDown(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Secondary_Input); + UpdateMouseInteraction(MouseEvent.GetPointerIndex()); + BoostListeners.ExecuteIfBound(MouseEvent.GetPointerIndex(), true); + } + MouseState.DisabledDueToMouseLeave = false; } - DasherMainInterface->KeyDown(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), 100); //100 is the keycode for LMB - MouseDownListeners.ExecuteIfBound(); - return FReply::Handled().LockMouseToWidget(AsShared()); } -FReply SDasherWidget::HandleMouseUpEvent(const FGeometry& Geometry, const FPointerEvent& MouseEvent) +void SDasherWidget::OnMouseLeave(const FPointerEvent& MouseEvent) { - if (CurrentlyUsingVectorInput) + SWidget::OnMouseLeave(MouseEvent); + + FMouseState& MouseState = GetMouseState(MouseEvent.GetPointerIndex()); + MouseState.CurrentlyHovering = false; + + if (InputPaused) return; + + if(MouseState.PrimaryButtonPressed) { - CurrentlyUsingVectorInput = false; - return FReply::Handled().ReleaseMouseLock(); + DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); + MouseListeners.ExecuteIfBound(MouseEvent.GetPointerIndex(), false); + MouseState.DisabledDueToMouseLeave = true; } - DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), 100); //100 is the keycode for LMB - MouseUpListeners.ExecuteIfBound(); - return FReply::Handled().ReleaseMouseLock(); + + 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::HandleMouseDoubleClickEvent(const FGeometry& Geometry, const FPointerEvent& MouseEvent) +FReply SDasherWidget::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { - if(CurrentlyUsingVectorInput) + 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) { - CurrentlyUsingVectorInput = false; - return FReply::Handled(); + DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Secondary_Input); + MouseState.SecondaryButtonPressed = false; + BoostListeners.ExecuteIfBound(MouseEvent.GetPointerIndex(), MouseState.SecondaryButtonPressed); } - DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), 100); //100 is the keycode for LMB + 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() +FVector2D SDasherWidget::GetCursorPosition() const { - return CursorPosition; + 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(); - + iX = Position.X; iY = Position.Y; @@ -83,26 +195,58 @@ bool SDasherWidget::GetScreenCoords(screenint& iX, screenint& iY, Dasher::CDashe void SDasherWidget::InputVector(const FVector2D InputVector) { - if (!CurrentlyUsingVectorInput) return; - CursorPosition = DasherMainInterface->ConvertDasher2Screen(Dasher::CDasherModel::ORIGIN_X, Dasher::CDasherModel::ORIGIN_Y) - + InputVector * FVector2D(1.0f,-1.0f) * (GetHeight() / 2); + 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::InputButton(bool Pressed) +void SDasherWidget::VectorInputButton(bool Pressed) { - CurrentlyUsingVectorInput = true; - if(Pressed) + if (InputPaused) return; + + FMouseState& MouseState = GetMouseState(VectorInputPointerIndex); + + if (Pressed) { - DasherMainInterface->KeyDown(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), 100); //100 is the keycode for LMB + 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(), 100); //100 is the keycode for LMB + else + { + DasherMainInterface->KeyUp(FDateTime::Now().GetSecond() + FDateTime::Now().GetMillisecond(), Dasher::Keys::Primary_Input); + MouseState.PrimaryButtonPressed = false; } } +void SDasherWidget::VectorBoostButton(bool Pressed) +{ + 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; @@ -113,65 +257,57 @@ void SDasherWidget::Construct(const FArguments& InArgs) //Setting up Dasher static Dasher::XMLErrorDisplay display; - Dasher::XmlSettingsStore* Settings = new Dasher::XmlSettingsStore("Settings.xml", &display); //Gets deleted somewhere else - Settings->Load(); + Dasher::XmlSettingsStore* Settings = new Dasher::XmlSettingsStore("Settings.xml", &display); //Gets deleted somewhere else + Settings->Load(); Settings->Save(); - DasherMainInterface = MakeShared<Dasher::DasherInterface>(Settings); - DasherMainInterface->SetDefaultInputDevice(this); + 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);}); - DasherMainInterface->SetCharDeletedCallback([this](FString Char, FString Buffer){CharacterDeleted.ExecuteIfBound(Char, Buffer);}); - - //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. - //You could add Slate Code here for child slots etc. + 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::SetBoolParamter(FString ParameterName, bool Value) +void SDasherWidget::SetParameter(FString& ParameterName, bool Value) { - for(Dasher::Settings::bp_table Setting : Dasher::Settings::boolparamtable) - { - if(FString(Setting.regName).Compare(ParameterName, ESearchCase::IgnoreCase)) + 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(Setting.key, Value); + DasherMainInterface->SetBoolParameter(param->first, Value); return; } - } } -void SDasherWidget::SetLongParamter(FString ParameterName, int64 Value) +void SDasherWidget::SetParameter(FString& ParameterName, int64 Value) { - for(Dasher::Settings::bp_table Setting : Dasher::Settings::boolparamtable) - { - if(FString(Setting.regName).Compare(ParameterName, ESearchCase::IgnoreCase)) + 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(Setting.key, Value); + DasherMainInterface->SetLongParameter(param->first, Value); return; } - } } -void SDasherWidget::SetStringParamter(FString ParameterName, FString Value) +void SDasherWidget::SetParameter(FString& ParameterName, FString Value) { - for(Dasher::Settings::bp_table Setting : Dasher::Settings::boolparamtable) - { - if(FString(Setting.regName).Compare(ParameterName, ESearchCase::IgnoreCase)) + 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(Setting.key, TCHAR_TO_UTF8(*Value)); + DasherMainInterface->SetStringParameter(param->first, TCHAR_TO_UTF8(*Value)); return; } - } -} - -//Set the colour Scheme for dasher -void SDasherWidget::SetColourScheme(const Dasher::CColourIO::ColourInfo* pcolours) { - ColorPalette = pcolours; } //paints our stuff, then lets compoundwidget (super::) draw its stuff @@ -189,45 +325,49 @@ int32 SDasherWidget::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe FSlateFontInfo Font; TArray<TUniquePtr<DasherDrawGeometry>>& GeometryBuffer = *FrontBuffer; - for(TUniquePtr<DasherDrawGeometry>& GeneralObject : GeometryBuffer) { - switch(GeneralObject->Type) + for (TUniquePtr<DasherDrawGeometry>& GeneralObject : GeometryBuffer) + { + switch (GeneralObject->Type) { - case 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 Writing: - WritingObject = static_cast<FWriting*>(GeneralObject.Get()); - Text = FString(UTF8_TO_TCHAR(WritingObject->label->m_strText.c_str())); - - 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 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; + 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 + 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& AllotedGeometry, const double InCurrentTime, const float InDeltaTime) { +void SDasherWidget::Tick(const FGeometry& AllotedGeometry, const double InCurrentTime, const float InDeltaTime) +{ //don't tick in the editor - if (!IsEditor) { + 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) { + 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); @@ -245,86 +385,84 @@ std::pair<SDasherWidget::screenint, SDasherWidget::screenint> SDasherWidget::Tex } //Double Buffers are rotated here. -void SDasherWidget::Display() { +void SDasherWidget::Display() +{ std::swap(FrontBuffer, BackBuffer); BackBuffer->Empty(); -} - -//Functions for Drawing -void SDasherWidget::DrawRectangle(Dasher::screenint x1, Dasher::screenint y1, Dasher::screenint x2, Dasher::screenint y2, int colour, int iOutlineColour, int iThickness) -{ - const FVector2D Top(x1, y1); - const FVector2D Bottom(x2, y2); - - FLinearColor RectColor; - - if (ColorPalette) { - RectColor = FLinearColor(ColorPalette->Colors[colour].Red/255.0, ColorPalette->Colors[colour].Green / 255.0, ColorPalette->Colors[colour].Blue / 255.0); + if(CharEnteredInFrame && CharDeletedInFrame) + { + CharacterSwitchedLastFrame.ExecuteIfBound(); } - else { - RectColor = FLinearColor::Blue; + else if(CharEnteredInFrame) + { + CharacterEnteredLastFrame.ExecuteIfBound(); + } + else if(CharDeletedInFrame) + { + CharacterDeletedLastFrame.ExecuteIfBound(); } - - BackBuffer->Add(MakeUnique<FFilledRect>(Top, Bottom, RectColor)); -} - -void SDasherWidget::DrawString(CDasherScreen::Label* lab, screenint x1, screenint y1, unsigned int iSize, int colour) { - const FVector2D Pos(x1, y1); - FLinearColor TextColor; + CharEnteredInFrame = false; + CharDeletedInFrame = false; - if (ColorPalette) { - TextColor = FLinearColor(ColorPalette->Colors[colour].Red / 255.0, ColorPalette->Colors[colour].Green / 255.0, ColorPalette->Colors[colour].Blue / 255.0); - } - else { - TextColor = FLinearColor::Black; - } - - BackBuffer->Add(MakeUnique<FWriting>(lab, Pos, static_cast<int>(iSize), TextColor)); + DasherFrameCompleted.ExecuteIfBound(); } -void SDasherWidget::Polyline(CDasherScreen::point* points, int number, int iwidth, int colour) { - - FLinearColor LinearColor; +//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)) - if (ColorPalette) { - LinearColor = FLinearColor(ColorPalette->Colors[colour].Red / 255.0, ColorPalette->Colors[colour].Green / 255.0, ColorPalette->Colors[colour].Blue / 255.0); - } - else { - LinearColor = FLinearColor::Blue; - } +//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) +{ + if (outlineColor == Dasher::ColorPalette::noColor) iThickness = 0; // Draw till brim if no outline color is given + + if (color != Dasher::ColorPalette::noColor && !color.isFullyTransparent()) + { + BackBuffer->Add(MakeUnique<FFilledRect>(FVector2D(x1 + iThickness, y1 + iThickness), FVector2D(x2 - iThickness, y2 - iThickness), FLinearColor(color.Red / 255.0f, color.Green / 255.0f, color.Blue / 255.0f, color.Alpha / 255.0f))); + } + + if (iThickness && outlineColor != Dasher::ColorPalette::noColor && !outlineColor.isFullyTransparent()) + { + const float hThickness = iThickness / 2.0f; + const FVector2D CornerMin = FVector2D(x1 + hThickness, y1 + hThickness); + const FVector2D CornerMax = FVector2D(x2 - hThickness, y2 - hThickness); + + const FLinearColor oColor = FLinearColor(outlineColor.Red / 255.0f, outlineColor.Green / 255.0f, outlineColor.Blue / 255.0f, outlineColor.Alpha / 255.0f); + BackBuffer->Add(MakeUnique<FPolyLine>(TArray({ FVector2D(CornerMin.X, CornerMin.Y - hThickness),FVector2D(CornerMin.X, CornerMax.Y + hThickness) }), static_cast<float>(iThickness), oColor, false)); + BackBuffer->Add(MakeUnique<FPolyLine>(TArray({ FVector2D(CornerMin.X - hThickness, CornerMax.Y),FVector2D(CornerMax.X + hThickness, CornerMax.Y) }), static_cast<float>(iThickness), oColor, false)); + BackBuffer->Add(MakeUnique<FPolyLine>(TArray({ FVector2D(CornerMax.X, CornerMax.Y + hThickness),FVector2D(CornerMax.X, CornerMin.Y - hThickness) }), static_cast<float>(iThickness), oColor, false)); + BackBuffer->Add(MakeUnique<FPolyLine>(TArray({ FVector2D(CornerMax.X + hThickness, CornerMin.Y),FVector2D(CornerMin.X - hThickness, CornerMin.Y) }), static_cast<float>(iThickness), oColor, false)); + } +} - TArray<FVector2D> PointArray; - for (int i = 0; i < number; i++) { - FVector2D Point(points[i].x, points[i].y); - PointArray.Add(Point); - } - - BackBuffer->Add(MakeUnique<FPolyLine>(PointArray, static_cast<float>(iwidth), LinearColor)); +void SDasherWidget::DrawString(CDasherScreen::Label* lab, screenint x1, screenint y1, unsigned int iSize, const Dasher::ColorPalette::Color& color) { + BackBuffer->Add(MakeUnique<FWriting>(UTF8_TO_TCHAR(lab->m_strText.c_str()), FVector2D(x1, y1), static_cast<int>(iSize), FLinearColor(color.Red / 255.0f, color.Green / 255.0f, color.Blue / 255.0f, color.Alpha / 255.0f))); } -//techincally polygons are just multiple polylines. Dasher doesn't actually draw polygons in our case. -void SDasherWidget::Polygon(CDasherScreen::point* points, int number, int fillcolour, int outlinecolour, int iwidth) { - FLinearColor LinearColor; +void SDasherWidget::Polyline(CDasherScreen::point* points, int number, int iwidth, const Dasher::ColorPalette::Color& color) { + TArray<FVector2D> PointArray; + for (int i = 0; i < number; i++) { + FVector2D Point(points[i].x, points[i].y); + PointArray.Add(Point); + } - if (ColorPalette) { - LinearColor = FLinearColor(ColorPalette->Colors[outlinecolour].Red / 255.0, ColorPalette->Colors[outlinecolour].Green / 255.0, ColorPalette->Colors[outlinecolour].Blue / 255.0); - } - else { - LinearColor = FLinearColor::Blue; - } - - TArray<FVector2D> PointArray; - for (int i = 0; i < number; i++) { - FVector2D Point(points[i].x, points[i].y); - PointArray.Add(Point); - } - PointArray.Add(FVector2D(points[0].x, points[0].y)); + BackBuffer->Add(MakeUnique<FPolyLine>(PointArray, static_cast<float>(iwidth), FLinearColor(color.Red / 255.0f, color.Green / 255.0f, color.Blue / 255.0f, color.Alpha / 255.0f), true)); +} - BackBuffer->Add(MakeUnique<FPolyLine>(PointArray, static_cast<float>(iwidth), LinearColor)); +//techincally polygons are just multiple polylines. Dasher doesn't actually draw polygons in our case. +void SDasherWidget::Polygon(CDasherScreen::point* points, int number, const Dasher::ColorPalette::Color& fillcolor, const Dasher::ColorPalette::Color& outlinecolor, int iwidth) { + TArray<FVector2D> PointArray; + for (int i = 0; i < number; i++) { + FVector2D Point(points[i].x, points[i].y); + PointArray.Add(Point); + } + PointArray.Add(FVector2D(points[0].x, points[0].y)); + + 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 { @@ -341,6 +479,7 @@ void SDasherWidget::StartTraining(FString 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 29031715ffeb8bf132a0e7b038f7b8eeec9bfcec..ca9fef7ac5665402d28c5b7da55b73042a9a5e09 100644 --- a/Source/DasherVR/Private/UDasherWidget.cpp +++ b/Source/DasherVR/Private/UDasherWidget.cpp @@ -1,5 +1,5 @@ /* - Adapted from JoySoftEdgeImage by Rama https://nerivec.github.io/old-ue4-wiki/pages/umg-custom-widget-components-and-render-code-usable-in-umg-designer.html + Adapted from JoySoftEdgeImage by Rama https://nerivec.github.io/old-ue4-wiki/pages/umg-custom-widget-components-and-render-code-usable-in-umg-designer.html */ #include "UDasherWidget.h" @@ -9,7 +9,7 @@ ///////////////////////////////////////////////////// // UDasherWidget UDasherWidget::UDasherWidget(const FObjectInitializer& ObjectInitializer) - : Super(ObjectInitializer) + : Super(ObjectInitializer) { //Default Values Set Here, see above } @@ -30,78 +30,89 @@ void UDasherWidget::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->MouseUpListeners.BindLambda([this]() {MouseEvent.Broadcast(false); }); - DasherScreen->MouseDownListeners.BindLambda([this]() {MouseEvent.Broadcast(true); }); + 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); - DasherScreen.Reset(); + if(bReleaseChildren) DasherScreen.Reset(); } FString UDasherWidget::GetBuffer() { + if(!DasherScreen) return ""; return DasherScreen->GetBuffer(); } void UDasherWidget::ResetBuffer() { + if(!DasherScreen) return; DasherScreen->ResetBuffer(); BufferAltered.Broadcast(""); } void UDasherWidget::StartTraining(FString PathToTextFile) { + if(!DasherScreen) return; DasherScreen->StartTraining(PathToTextFile); } void UDasherWidget::SetBoolParamter(FString ParameterName, bool Value) { - DasherScreen->SetBoolParamter(ParameterName, Value); + if(!DasherScreen) return; + DasherScreen->SetParameter(ParameterName, Value); } void UDasherWidget::SetLongParamter(FString ParameterName, int64 Value) { - DasherScreen->SetLongParamter(ParameterName, Value); + if(!DasherScreen) return; + DasherScreen->SetParameter(ParameterName, Value); } void UDasherWidget::SetStringParamter(FString ParameterName, FString Value) { - DasherScreen->SetStringParamter(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) { - DasherScreen->InputVector(InputVector); + if(!DasherScreen) return; + DasherScreen->InputVector(InputVector); } -#if WITH_EDITOR +bool UDasherWidget::GetInputEnabled() const +{ + if(!DasherScreen) return false; + return DasherScreen->GetInputEnabled(); +} -//const FSlateBrush* UDasherWidget::GetEditorIcon() -//{ -// return FUMGStyle::Get().GetBrush("Widget.Image"); -//} +void UDasherWidget::EnableInput(bool enabled) +{ + if(!DasherScreen) return; + DasherScreen->EnableInput(enabled); +} +#if WITH_EDITOR const FText UDasherWidget::GetPaletteCategory() { - return LOCTEXT("Common", "Common"); + return LOCTEXT("Common", "Common"); } #endif @@ -109,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/DasherInterface.h b/Source/DasherVR/Public/DasherInterface.h index b7427f2e4032b97ff8fecff814108aab6a60592b..6ff93a03db10f9d7c146f9293c49dfa47f245295 100644 --- a/Source/DasherVR/Public/DasherInterface.h +++ b/Source/DasherVR/Public/DasherInterface.h @@ -37,7 +37,7 @@ namespace Dasher /// For character around cursor decision is arbitrary. Let's settle for character before cursor. /// TODO. Consistently name functions dealing with dasher context, versus functions dealing with editor text. /// I.E. GetAllContext should be named GetAllTtext - virtual std::string GetTextAroundCursor(Dasher::CControlManager::EditDistance) override; + virtual std::string GetTextAroundCursor(Dasher::EditDistance) override; ///Called to execute a control-mode "move" command. @@ -45,7 +45,7 @@ namespace Dasher ///\param dist how far to move: character, word, line, file. (Usually defined /// by OS, e.g. for non-european languages) ///\return the offset, into the edit buffer of the cursor *after* the move. - virtual unsigned int ctrlMove(bool bForwards, Dasher::CControlManager::EditDistance dist) override; + virtual unsigned int ctrlMove(bool bForwards, Dasher::EditDistance dist) override; ///Called to execute a control-mode "delete" command. @@ -54,7 +54,7 @@ namespace Dasher /// by OS, e.g. for non-european languages) ///\return the offset, into the edit buffer, of the cursor *after* the delete /// (for forwards deletion, this will be the same as the offset *before - virtual unsigned int ctrlDelete(bool bForwards, Dasher::CControlManager::EditDistance dist) override; + virtual unsigned int ctrlDelete(bool bForwards, Dasher::EditDistance dist) override; ///Clears all written text from edit buffer and rebuilds the model. The default /// implementation does this using the control mode editDelete mechanism @@ -75,7 +75,7 @@ namespace Dasher void Tick(unsigned long time); // set the screen, needed for maximum spaghetti, to make changeScreen accessible to the outside aka SDasherWidget - virtual void SetScreen(SDasherWidget* screen); + virtual void SetScreen(CDasherScreen* screen); //Sets the Training Filename virtual void ImportTrainingFile(std::string filename); diff --git a/Source/DasherVR/Public/DasherVR.h b/Source/DasherVR/Public/DasherVR.h index 5aa2e2597631e06f77ab8e30ca5af57361e6da16..8a2bcca67e14c89f4d9b16b6196193fb26aa6964 100644 --- a/Source/DasherVR/Public/DasherVR.h +++ b/Source/DasherVR/Public/DasherVR.h @@ -3,6 +3,7 @@ #include "CoreMinimal.h" #include "DasherCoreWrapper.h" +#include "Modules/ModuleInterface.h" class FDasherVRModule : public IModuleInterface { diff --git a/Source/DasherVR/Public/SDasherWidget.h b/Source/DasherVR/Public/SDasherWidget.h index 31c993f819e6d1ddbdea130627718ba11dd8855c..b3e125514a7cf7e7315947b8cd992c54ec692e22 100644 --- a/Source/DasherVR/Public/SDasherWidget.h +++ b/Source/DasherVR/Public/SDasherWidget.h @@ -7,18 +7,26 @@ #include "DasherInterface.h" #include "Math/Vector2D.h" #include "Fonts/FontMeasure.h" +#include "Widgets/DeclarativeSyntaxSupport.h" +#include "Cluster/IDisplayClusterClusterManager.h" //using namespace Dasher; +//Structs to hold the elements making up the UI +enum class GeometryType : uint8 +{ -//Structs to hold the elements making up the UI + Rectangle = 0, + Writing = 1, + PolyLine = 2 +}; -enum GeometryType +enum class DasherEventType : uint8 { - Rectangle, - Writing, - PolyLine + Input_MouseDown = 1, + Input_MouseUp = 2, + Tick = 3 }; struct DasherDrawGeometry @@ -28,40 +36,51 @@ struct DasherDrawGeometry virtual ~DasherDrawGeometry() {}; }; -struct FFilledRect : DasherDrawGeometry{ +struct FFilledRect : DasherDrawGeometry { FVector2D top; FVector2D bottom; FLinearColor color; - FFilledRect(FVector2D Top, FVector2D Bottom, FLinearColor Color) : DasherDrawGeometry(Rectangle), top(Top), bottom(Bottom), color(Color) {} + FFilledRect(FVector2D Top, FVector2D Bottom, FLinearColor Color) : DasherDrawGeometry(GeometryType::Rectangle), top(Top), bottom(Bottom), color(Color) {} }; struct FWriting : DasherDrawGeometry{ - Dasher::CDasherScreen::Label *label; + FString label; FVector2D pos; int size; FLinearColor color; - - FWriting(Dasher::CDasherScreen::Label *Label, FVector2D Pos, int Size, FLinearColor Color) : DasherDrawGeometry(Writing), label(Label), pos(Pos), size(Size), color(Color) {} + FWriting(FString Label, FVector2D Pos, int Size, FLinearColor Color) : DasherDrawGeometry(GeometryType::Writing), label(Label), pos(Pos), size(Size), color(Color) {} }; struct FPolyLine : DasherDrawGeometry{ TArray<FVector2D> points; float linewidth; + bool AntiAliasing; FLinearColor color; - FPolyLine(TArray<FVector2D> Points, float LineWidth, FLinearColor Color): DasherDrawGeometry(PolyLine), points(Points), linewidth(LineWidth), color(Color) {} + FPolyLine(TArray<FVector2D> Points, float LineWidth, FLinearColor Color, bool AntiAliasing): DasherDrawGeometry(GeometryType::PolyLine), points(Points), linewidth(LineWidth), AntiAliasing(AntiAliasing), color(Color) {} +}; + +struct FMouseState +{ + bool PrimaryButtonPressed = false; + bool SecondaryButtonPressed = false; + bool DisabledDueToMouseLeave = false; + FVector2D CursorPosition = {0,0}; + bool CurrentlyHovering = true; }; -DECLARE_DELEGATE(FDasherMouseUpDelegate); -DECLARE_DELEGATE(FDasherMouseDownDelegate); -DECLARE_DELEGATE_TwoParams(FBufferManiputlationDelegate, FString, FString); +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) {} @@ -73,40 +92,34 @@ public: typedef Dasher::screenint screenint; - SDasherWidget(): CDasherScreen(0,0), CScreenCoordInput(0, _("Mouse Input")) {} + SDasherWidget(): CDasherScreen(0,0), CScreenCoordInput("Mouse Input") {} // Constructs this widget with InArgs. Needed for every widget. Builds this widget and any of its children void Construct(const FArguments& InArgs); - void SetBoolParamter(FString ParameterName, bool Value); - void SetLongParamter(FString ParameterName, int64 Value); - void SetStringParamter(FString ParameterName, FString Value); + void SetParameter(FString& ParameterName, bool Value); + void SetParameter(FString& ParameterName, int64 Value); + void SetParameter(FString& ParameterName, FString Value); virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override; //set of functions inherited from Dasherscreen used for displaying, see DasherScreen for further info - virtual void SetColourScheme(const Dasher::CColourIO::ColourInfo* pcolours) override; - virtual std::pair<screenint, screenint> TextSize(CDasherScreen::Label* Label, unsigned int Size) override; - virtual void DrawString(CDasherScreen::Label *label, screenint x1, screenint y1, unsigned int size, int colour) override; + virtual void DrawString(CDasherScreen::Label *label, screenint x1, screenint y1, unsigned int size, const Dasher::ColorPalette::Color& color) override; - virtual void DrawRectangle(Dasher::screenint x1, Dasher::screenint y1, Dasher::screenint x2, Dasher::screenint y2, int colour, int ioutlinecolour, int ithickness) override; + virtual void 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) override; - virtual void DrawCircle(screenint icx, screenint icy, screenint ir, int ifillcolour, int ilinecolour, int ithickness) override {} //we don't really need to draw circles, so it's not implemented + virtual void DrawCircle(screenint icx, screenint icy, screenint ir, const Dasher::ColorPalette::Color& ifillcolor, const Dasher::ColorPalette::Color& ilinecolor, int ithickness) override {} //we don't really need to draw circles, so it's not implemented - virtual void Polyline(CDasherScreen::point* points, int number, int iwidth, int colour) override; + virtual void Polyline(CDasherScreen::point* points, int number, int iwidth, const Dasher::ColorPalette::Color& color) override; - virtual void Polygon(CDasherScreen::point* points, int number, int fillcolour, int outlinecolour, int iwidth) override; + virtual void Polygon(CDasherScreen::point* points, int number, const Dasher::ColorPalette::Color& fillcolor, const Dasher::ColorPalette::Color& outlinecolor, int iwidth) override; virtual void Display() override; - virtual void SendMarker(int imarker) override {} - virtual bool IsPointVisible(screenint x, screenint y) override { return true; } - virtual bool MultiSizeFonts() override {return true;} - //Pass-me-down returning Buffer FString GetBuffer() const; void ResetBuffer(); @@ -114,29 +127,41 @@ public: void StartTraining(FString PathToTextFile); //Tick function inherited from SCompoundWidget - virtual void Tick(const FGeometry& AllotedGeometry, const double InCurrentTime, const float InDeltaTime) override; + virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; //Function to set if the widget is in editor or not 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 SupportsKeyboardFocus() const override {return true;} virtual bool GetScreenCoords(screenint& iX, screenint& iY, Dasher::CDasherView* pView) override; void InputVector(FVector2D InputVector); - void InputButton(bool Pressed); - FVector2D GetCursorPosition(); - - FDasherMouseUpDelegate MouseUpListeners; - FDasherMouseUpDelegate MouseDownListeners; - FBufferManiputlationDelegate CharacterEntered; - FBufferManiputlationDelegate CharacterDeleted; + void VectorInputButton(bool Pressed); + void VectorBoostButton(bool Pressed); + FVector2D GetCursorPosition() const; + + //Allows to Pause Input + 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: @@ -146,21 +171,35 @@ private: TArray<TUniquePtr<DasherDrawGeometry>>* BackBuffer = &GeometryBufferA; TArray<TUniquePtr<DasherDrawGeometry>>* FrontBuffer = &GeometryBufferB; - int Height; - int Width; - bool HasBeenPainted = false; - bool CurrentlyUsingVectorInput = false; - FVector2D CursorPosition; + int Height = 0; + int Width = 0; - //are we in the Editor? - bool IsEditor = true; + bool CurrentlyUsingVectorInput = false; + point CursorPosition = {0,0}; + point NewMousePosition = {0,0}; + + 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; + //CAVE Sync + FOnClusterEventBinaryListener ClusterEventListener; + inline static int32 DasherEventID = 424240; + protected: // stores color information - const Dasher::CColourIO::ColourInfo* ColorPalette = nullptr; TSharedPtr<Dasher::DasherInterface> DasherMainInterface; }; diff --git a/Source/DasherVR/Public/UDasherWidget.h b/Source/DasherVR/Public/UDasherWidget.h index ae0cb7aecbcd3251e6438442002f72955648f02d..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,11 +41,19 @@ public: UFUNCTION(BlueprintCallable) void InputButton(bool Pressed); UFUNCTION(BlueprintCallable) void InputVector(FVector2D InputVector); + 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/DasherVR/Public/pch_plugin.h b/Source/DasherVR/Public/pch_plugin.h new file mode 100644 index 0000000000000000000000000000000000000000..6f70f09beec2219624baeca92e2cd7deaa104fb4 --- /dev/null +++ b/Source/DasherVR/Public/pch_plugin.h @@ -0,0 +1 @@ +#pragma once diff --git a/Source/Thirdparty/CMakeLists.txt b/Source/Thirdparty/CMakeLists.txt index 4c001d32bb46711687653f3ba04b89fd51750962..dc66fff409921184fb5c97aea50af2e039d4f665 100644 --- a/Source/Thirdparty/CMakeLists.txt +++ b/Source/Thirdparty/CMakeLists.txt @@ -14,12 +14,11 @@ project("DasherLib") # If using visual studio, make sure to select the release configuration if it is not your default ############################################################################################################ - ############################################################################################################ # Set this to your libc++ path included with Unreal ############################################################################################################ -set(LIBC_PATH "/home/unreal/UE4_Build_426/Engine/Source/ThirdParty/Linux/LibCxx/") - +# set(LIBC_PATH "/work/vrdemo/unreal_engines/5.3.2/Engine/Source/ThirdParty/Unix/LibCxx/") +set(LIBC_PATH "/home/ue4/UnrealEngine/Engine/Source/ThirdParty/Unix/LibCxx/") if (UNIX) ############################################################################################################ @@ -28,9 +27,9 @@ if (UNIX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) - add_compile_definitions(HAVE_ROUND XML_STATIC _CRT_SECURE_NO_WARNINGS HAVE_OWN_FILEUTILS HAVE_OWN_FILELOGGER) + add_compile_definitions(HAVE_ROUND XML_STATIC _CRT_SECURE_NO_WARNINGS HAVE_OWN_FILEUTILS HAVE_OWN_FILELOGGER PUGIXML_NO_EXCEPTIONS) set(CMAKE_SUPPRESS_REGENERATION true) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -std=c++17 -stdlib=libc++ -nostdinc++ -I${LIBC_PATH}include/c++/v1 -L${LIBC_PATH}lib -Wl -rpath ${LIBC_PATH}lib") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -std=c++17 -nostdinc++ -fno-exceptions -I${LIBC_PATH}include/c++/v1 -L${LIBC_PATH}lib ${LIBC_PATH}lib") set(CMAKE_EXE_LINKER_FLAGS "-stdlib=libc++") diff --git a/Source/Thirdparty/Dasher/Dasher.Build.cs b/Source/Thirdparty/Dasher/Dasher.Build.cs index fbaf4ffc6ef0f8aa75057032b7366e932ea0025b..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"); @@ -47,6 +48,7 @@ public class Dasher : ModuleRules if (Target.Platform == UnrealTargetPlatform.Linux) { PublicAdditionalLibraries.Add(Path.Combine(ModuleDirectory, "Lib", "DasherCore.a")); + PublicAdditionalLibraries.Add(Path.Combine(ModuleDirectory, "Lib", "libpugixml.a")); } } } diff --git a/Source/Thirdparty/Dasher/DasherCore b/Source/Thirdparty/Dasher/DasherCore index a94a47badf40d9b7f7e8c80c08b015c41d1ecc90..e654a32606dd360cafdb8956971fc94653f4c88d 160000 --- a/Source/Thirdparty/Dasher/DasherCore +++ b/Source/Thirdparty/Dasher/DasherCore @@ -1 +1 @@ -Subproject commit a94a47badf40d9b7f7e8c80c08b015c41d1ecc90 +Subproject commit e654a32606dd360cafdb8956971fc94653f4c88d diff --git a/Source/Thirdparty/Dasher/Lib/DasherCore.a b/Source/Thirdparty/Dasher/Lib/DasherCore.a new file mode 100644 index 0000000000000000000000000000000000000000..07b54651cd309089dcfdcdd9827ae3f0a41af66c Binary files /dev/null and b/Source/Thirdparty/Dasher/Lib/DasherCore.a differ diff --git a/Source/Thirdparty/Dasher/Lib/DasherCore.lib b/Source/Thirdparty/Dasher/Lib/DasherCore.lib index 649532f6b3811d45e73e539ecfa9f151629881ba..e84f68856171851b4922525037191d04a76ba225 100644 --- a/Source/Thirdparty/Dasher/Lib/DasherCore.lib +++ b/Source/Thirdparty/Dasher/Lib/DasherCore.lib @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d51488c01a9dd197c65a23d33c65ff5f7f0cbf9853d0f9d634fa31423f90d56c -size 17686042 +oid sha256:4d560e7ca59bee8fdc05b7178c51579f6ab13bee39256280e222527dddb84058 +size 29899184 diff --git a/Source/Thirdparty/Dasher/Lib/DasherCore.pdb b/Source/Thirdparty/Dasher/Lib/DasherCore.pdb index f6044a85dcead2424134c4c7695360f57f29db1e..aa3548dbae81aa4ab322b860d0cb0c2e0746dd44 100644 Binary files a/Source/Thirdparty/Dasher/Lib/DasherCore.pdb and b/Source/Thirdparty/Dasher/Lib/DasherCore.pdb differ diff --git a/Source/Thirdparty/Dasher/Lib/pugixml.lib b/Source/Thirdparty/Dasher/Lib/pugixml.lib index cce3a4936cd35ce16565522cefeb54f99f96efc2..d70b5dc2d5a1a70e5232ca233b7ae60cf56c73d5 100644 --- a/Source/Thirdparty/Dasher/Lib/pugixml.lib +++ b/Source/Thirdparty/Dasher/Lib/pugixml.lib @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:af6d87774854f597e9a3dc390060d76ab870e9dde54b5935d8029e336ac2eed2 -size 1463018 +oid sha256:9d1e2128f0f0e9423efe3d44823bd7e9768ee34aff6fb0f47ab6ac587a0bd973 +size 1502654 diff --git a/Source/Thirdparty/Dasher/Lib/pugixml.pdb b/Source/Thirdparty/Dasher/Lib/pugixml.pdb index dc52d69d6d2a95beb29cb8419f2dadf1eb8b7be3..404bfd8c649e178052d3448e8a93cb460c3ba55b 100644 Binary files a/Source/Thirdparty/Dasher/Lib/pugixml.pdb and b/Source/Thirdparty/Dasher/Lib/pugixml.pdb differ 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