/** * @file * * @author Mamadou Babaei * * @section LICENSE * * (The MIT License) * * Copyright (c) 2020 - 2022 SenseGlove * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * @section DESCRIPTION * * */ #include "SGCore/SGHapticGloveCommandBuffer.h" #include "Runtime/Launch/Resources/Version.h" #include "SGCore/SGBuzzCommand.h" #include "SGCore/SGForceFeedbackCommand.h" #include "SGCore/SGTimedBuzzCommand.h" #include "SGCore/SGThumperCommand.h" #include "SGCoreImpl/SGExportedFunctions.h" #include "SGInterop/SGIC_FSGBuzzCommandImpl.h" #include "SGInterop/SGIC_FSGForceFeedbackCommandImpl.h" #include "SGInterop/SGIC_FSGHapticGloveCommandBufferImpl.h" #include "SGInterop/SGIC_FSGThumperCommandImpl.h" #include "SGInterop/SGIC_FSGTimedBuzzCommandImpl.h" #include "SGInterop/SGIC_FSGTimedThumpCommandImpl.h" #include "SGInterop/SGIC_TArray_FSGForceFeedbackCommandImpl.h" #include "SGInterop/SGIC_TArray_FSGTimedBuzzCommandImpl.h" #include "SGInterop/SGIC_TArray_FSGTimedThumpCommandImpl.h" #include "SGUtils/SGArrayUtils.h" struct USGHapticGloveCommandBuffer::FImpl { /************************ * Member variables ************************/ FSGHapticGloveCommandBufferImpl HapticGloveCommandBufferImpl; /************************ * Owner object ************************/ USGHapticGloveCommandBuffer* Owner; /************************ * Constructor / Destructor ************************/ explicit FImpl(USGHapticGloveCommandBuffer* InOwner); ~FImpl(); /************************ * Default copy constructor & copy assignment operator ************************/ FImpl(const FImpl& Rhs) = default; FImpl& operator=(const FImpl& Rhs) = default; /************************ * Methods ************************/ void SyncUProperties(); void SyncImplObject(); }; USGHapticGloveCommandBuffer* USGHapticGloveCommandBuffer::NewHapticGloveCommandBuffer( UObject* Outer, const FSGHapticGloveCommandBufferImpl& HapticGloveCommandBufferImpl) { USGHapticGloveCommandBuffer* Instance = NewObject(Outer); Instance->SetHapticGloveCommandBufferImpl(HapticGloveCommandBufferImpl); return Instance; } USGHapticGloveCommandBuffer* USGHapticGloveCommandBuffer::NewHapticGloveCommandBuffer(UObject* Outer) { FSGIC_FSGHapticGloveCommandBufferImpl OutHapticGloveCommandBufferImplContainer; SGCoreImpl_FSGHapticGloveCommandBufferImpl_ctor(&OutHapticGloveCommandBufferImplContainer); return NewHapticGloveCommandBuffer( Outer, MoveTemp(OutHapticGloveCommandBufferImplContainer.HapticGloveCommandBufferImpl)); } int32 USGHapticGloveCommandBuffer::GetMaxForceFeedbackCommands() { return SGCoreImpl_FSGHapticGloveCommandBufferImpl_GetMaxForceFeedbackCommands(); } int32 USGHapticGloveCommandBuffer::GetMaxBuzzCommands() { return SGCoreImpl_FSGHapticGloveCommandBufferImpl_GetMaxBuzzCommands(); } int32 USGHapticGloveCommandBuffer::GetMaxThumpCommands() { return SGCoreImpl_FSGHapticGloveCommandBufferImpl_GetMaxThumpCommands(); } USGHapticGloveCommandBuffer::USGHapticGloveCommandBuffer() : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 24 ) Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{this})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 24 ) */ { FSGIC_FSGHapticGloveCommandBufferImpl OutHapticGloveCommandBufferImplContainer; SGCoreImpl_FSGHapticGloveCommandBufferImpl_ctor(&OutHapticGloveCommandBufferImplContainer); Pimpl->HapticGloveCommandBufferImpl = MoveTemp( OutHapticGloveCommandBufferImplContainer.HapticGloveCommandBufferImpl); Pimpl->SyncUProperties(); } USGHapticGloveCommandBuffer::USGHapticGloveCommandBuffer( const FSGHapticGloveCommandBufferImpl& HapticGloveCommandBufferImpl) : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 24 ) Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{this})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 24 ) */ { SetHapticGloveCommandBufferImpl(HapticGloveCommandBufferImpl); Pimpl->SyncUProperties(); } USGHapticGloveCommandBuffer::~USGHapticGloveCommandBuffer() = default; void USGHapticGloveCommandBuffer::SetHapticGloveCommandBufferImpl( const FSGHapticGloveCommandBufferImpl& HapticGloveCommandBufferImpl) { FSGIC_FSGHapticGloveCommandBufferImpl OutHapticGloveCommandBufferContainer; FSGIC_FSGHapticGloveCommandBufferImpl RhsContainer{HapticGloveCommandBufferImpl}; SGCoreImpl_FSGHapticGloveCommandBufferImpl_ctor_copy(&OutHapticGloveCommandBufferContainer, &RhsContainer); Pimpl->HapticGloveCommandBufferImpl = MoveTemp(OutHapticGloveCommandBufferContainer.HapticGloveCommandBufferImpl); } const FSGHapticGloveCommandBufferImpl& USGHapticGloveCommandBuffer::ToHapticGloveCommandBufferImpl() const { Pimpl->SyncImplObject(); return Pimpl->HapticGloveCommandBufferImpl; } TArray USGHapticGloveCommandBuffer::GetForceFeedbackCommandsQueue(UObject* Outer) const { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; FSGIC_TArray_FSGForceFeedbackCommandImpl OutForceFeedbackCommandsQueueContainer; SGCoreImpl_FSGHapticGloveCommandBufferImpl_GetForceFeedbackCommandsQueue(&InstanceContainer, &OutForceFeedbackCommandsQueueContainer); TArray CommandsQueue; for (FSGForceFeedbackCommandImpl& ForceFeedbackCommandImpl: OutForceFeedbackCommandsQueueContainer.Array) { CommandsQueue.Add(USGForceFeedbackCommand::NewForceFeedbackCommand( Outer, MoveTemp(ForceFeedbackCommandImpl))); } return MoveTemp(CommandsQueue); } TArray USGHapticGloveCommandBuffer::GetBuzzCommandsQueue(UObject* Outer) const { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; FSGIC_TArray_FSGTimedBuzzCommandImpl OutBuzzCommandsQueueContainer; SGCoreImpl_FSGHapticGloveCommandBufferImpl_GetBuzzCommandsQueue(&InstanceContainer, &OutBuzzCommandsQueueContainer); TArray CommandsQueue; for (FSGTimedBuzzCommandImpl& TimedBuzzCommandImpl: OutBuzzCommandsQueueContainer.Array) { CommandsQueue.Add(USGTimedBuzzCommand::NewTimedBuzzCommand(Outer, MoveTemp(TimedBuzzCommandImpl))); } return MoveTemp(CommandsQueue); } TArray USGHapticGloveCommandBuffer::GetThumperCommandsQueue(UObject* Outer) const { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; FSGIC_TArray_FSGTimedThumpCommandImpl OutThumperCommandsQueueContainer; SGCoreImpl_FSGHapticGloveCommandBufferImpl_GetThumperCommandsQueue(&InstanceContainer, &OutThumperCommandsQueueContainer); TArray CommandsQueue; for (FSGTimedThumpCommandImpl& TimedThumpCommandImpl: OutThumperCommandsQueueContainer.Array) { CommandsQueue.Add(USGTimedThumpCommand::NewTimedThumpCommand(Outer, MoveTemp(TimedThumpCommandImpl))); } return MoveTemp(CommandsQueue); } void USGHapticGloveCommandBuffer::ClearForceFeedbackCommandsQueue() { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; SGCoreImpl_FSGHapticGloveCommandBufferImpl_ClearForceFeedbackCommandsQueue(&InstanceContainer); Pimpl->SyncUProperties(); } void USGHapticGloveCommandBuffer::ClearVibrations() { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; SGCoreImpl_FSGHapticGloveCommandBufferImpl_ClearVibrations(&InstanceContainer); Pimpl->SyncUProperties(); } void USGHapticGloveCommandBuffer::Clear() { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; SGCoreImpl_FSGHapticGloveCommandBufferImpl_Clear(&InstanceContainer); Pimpl->SyncUProperties(); } void USGHapticGloveCommandBuffer::AddCommand(const USGForceFeedbackCommand* ForceFeedbackCommand) { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; FSGIC_FSGForceFeedbackCommandImpl ForceFeedbackCommandContainer{ ForceFeedbackCommand->ToForceFeedbackCommandImpl().Get()}; SGCoreImpl_FSGHapticGloveCommandBufferImpl_AddCommand_ForceFeedbackCommand( &InstanceContainer, &ForceFeedbackCommandContainer); Pimpl->SyncUProperties(); } void USGHapticGloveCommandBuffer::AddCommand(const USGTimedBuzzCommand* BuzzCommand) { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; FSGIC_FSGTimedBuzzCommandImpl BuzzCommandContainer{BuzzCommand->ToTimedBuzzCommandImpl().Get()}; SGCoreImpl_FSGHapticGloveCommandBufferImpl_AddCommand_BuzzCommand(&InstanceContainer, &BuzzCommandContainer); Pimpl->SyncUProperties(); } void USGHapticGloveCommandBuffer::AddCommand(const USGTimedThumpCommand* ThumpCommand) { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; FSGIC_FSGTimedThumpCommandImpl ThumpCommandContainer{ThumpCommand->ToTimedThumpCommandImpl()}; SGCoreImpl_FSGHapticGloveCommandBufferImpl_AddCommand_ThumpCommand(&InstanceContainer, &ThumpCommandContainer); Pimpl->SyncUProperties(); } void USGHapticGloveCommandBuffer::UpdateTimedCommands(const float DeltaSeconds) { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; SGCoreImpl_FSGHapticGloveCommandBufferImpl_UpdateTimedCommands(&InstanceContainer, DeltaSeconds); Pimpl->SyncUProperties(); } USGForceFeedbackCommand* USGHapticGloveCommandBuffer::GetTotalForceFeedbackLevels( UObject* Outer, const USGForceFeedbackCommand* LastForceFeedbackCommand) const { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; FSGIC_FSGForceFeedbackCommandImpl OutForceFeedbackCommandImplContainer; FSGIC_FSGForceFeedbackCommandImpl LastForceFeedbackCommandContainer{ LastForceFeedbackCommand->ToForceFeedbackCommandImpl().Get()}; SGCoreImpl_FSGHapticGloveCommandBufferImpl_GetTotalForceFeedbackLevels_LastForceFeedbackCommand( &InstanceContainer, &OutForceFeedbackCommandImplContainer, &LastForceFeedbackCommandContainer); return USGForceFeedbackCommand::NewForceFeedbackCommand( Outer, MoveTemp(OutForceFeedbackCommandImplContainer.ForceFeedbackCommandImpl)); } USGForceFeedbackCommand* USGHapticGloveCommandBuffer::GetTotalForceFeedbackLevels(UObject* Outer) const { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; FSGIC_FSGForceFeedbackCommandImpl OutForceFeedbackCommandImplContainer; SGCoreImpl_FSGHapticGloveCommandBufferImpl_GetTotalForceFeedbackLevels( &InstanceContainer, &OutForceFeedbackCommandImplContainer); return USGForceFeedbackCommand::NewForceFeedbackCommand( Outer, MoveTemp(OutForceFeedbackCommandImplContainer.ForceFeedbackCommandImpl)); } USGBuzzCommand* USGHapticGloveCommandBuffer::GetTotalBuzzLevels(UObject* Outer) const { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; FSGIC_FSGBuzzCommandImpl OutBuzzCommandImplContainer; SGCoreImpl_FSGHapticGloveCommandBufferImpl_GetTotalBuzzLevels(&InstanceContainer, &OutBuzzCommandImplContainer); return USGBuzzCommand::NewBuzzCommand(Outer, MoveTemp(OutBuzzCommandImplContainer.BuzzCommandImpl)); } USGThumperCommand* USGHapticGloveCommandBuffer::GetTotalThumperLevels(UObject* Outer) const { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; FSGIC_FSGThumperCommandImpl OutThumperCommandImplContainer; SGCoreImpl_FSGHapticGloveCommandBufferImpl_GetTotalThumperLevels(&InstanceContainer, &OutThumperCommandImplContainer); return USGThumperCommand::NewThumperCommand(Outer, MoveTemp(OutThumperCommandImplContainer.ThumperCommandImpl)); } void USGHapticGloveCommandBuffer::FlushHaptics(UObject* Outer, const USGForceFeedbackCommand* LastBrakeLevel, USGForceFeedbackCommand*& OutForceFeedbackCommand, USGBuzzCommand*& OutBuzzCommand, USGThumperCommand*& OutThumperCommand, const bool bClearForceFeedbackQueue) { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; FSGIC_FSGForceFeedbackCommandImpl LastBrakeLevelContainer{LastBrakeLevel->ToForceFeedbackCommandImpl().Get()}; FSGIC_FSGForceFeedbackCommandImpl OutForceFeedbackCommandImplContainer; FSGIC_FSGBuzzCommandImpl OutBuzzCommandImplContainer; FSGIC_FSGThumperCommandImpl OutThumperCommandImplContainer; SGCoreImpl_FSGHapticGloveCommandBufferImpl_FlushHaptics_LastBrakeLevel_OutForceFeedbackCommand_OutBuzzCommand_OutThumperCommand_bClearForceFeedbackQueue( &InstanceContainer, &LastBrakeLevelContainer, &OutForceFeedbackCommandImplContainer, &OutBuzzCommandImplContainer, &OutThumperCommandImplContainer, bClearForceFeedbackQueue); OutForceFeedbackCommand = USGForceFeedbackCommand::NewForceFeedbackCommand( Outer, MoveTemp(OutForceFeedbackCommandImplContainer.ForceFeedbackCommandImpl)); OutBuzzCommand = USGBuzzCommand::NewBuzzCommand(Outer, MoveTemp(OutBuzzCommandImplContainer.BuzzCommandImpl)); OutThumperCommand = USGThumperCommand::NewThumperCommand( Outer, MoveTemp(OutThumperCommandImplContainer.ThumperCommandImpl)); Pimpl->SyncUProperties(); } void USGHapticGloveCommandBuffer::FlushHaptics(UObject* Outer, const float DeltaSeconds, const USGForceFeedbackCommand* LastBrakeLevel, USGForceFeedbackCommand*& OutForceFeedbackCommand, USGBuzzCommand*& OutBuzzCommand, USGThumperCommand*& OutThumperCommand) { Pimpl->SyncImplObject(); FSGIC_FSGHapticGloveCommandBufferImpl InstanceContainer{ToHapticGloveCommandBufferImpl()}; FSGIC_FSGForceFeedbackCommandImpl LastBrakeLevelContainer{LastBrakeLevel->ToForceFeedbackCommandImpl().Get()}; FSGIC_FSGForceFeedbackCommandImpl OutForceFeedbackCommandImplContainer; FSGIC_FSGBuzzCommandImpl OutBuzzCommandImplContainer; FSGIC_FSGThumperCommandImpl OutThumperCommandImplContainer; SGCoreImpl_FSGHapticGloveCommandBufferImpl_FlushHaptics_DeltaSeconds_LastBrakeLevel_OutForceFeedbackCommand_OutBuzzCommand_OutThumperCommand( &InstanceContainer, DeltaSeconds, &LastBrakeLevelContainer, &OutForceFeedbackCommandImplContainer, &OutBuzzCommandImplContainer, &OutThumperCommandImplContainer); OutForceFeedbackCommand = USGForceFeedbackCommand::NewForceFeedbackCommand( Outer, MoveTemp(OutForceFeedbackCommandImplContainer.ForceFeedbackCommandImpl)); OutBuzzCommand = USGBuzzCommand::NewBuzzCommand(Outer, MoveTemp(OutBuzzCommandImplContainer.BuzzCommandImpl)); OutThumperCommand = USGThumperCommand::NewThumperCommand( Outer, MoveTemp(OutThumperCommandImplContainer.ThumperCommandImpl)); Pimpl->SyncUProperties(); } USGHapticGloveCommandBuffer::FImpl::FImpl(USGHapticGloveCommandBuffer* InOwner) : Owner(InOwner) { } USGHapticGloveCommandBuffer::FImpl::~FImpl() = default; void USGHapticGloveCommandBuffer::FImplDeleter::operator()(const FImpl* P) const { delete P; } void USGHapticGloveCommandBuffer::FImpl::SyncUProperties() { } void USGHapticGloveCommandBuffer::FImpl::SyncImplObject() { }