/** * @file * * @author Mamadou Babaei * * @section LICENSE * * (The MIT License) * * Copyright (c) 2020 - 2024 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 "SGCoreImpl/SGDeviceImpl.h" #include #include "Containers/StringConv.h" #include "Misc/AssertionMacros.h" #include "SGBuildHacks/SGInclude_Core_BetaDevice.h" #include "SGBuildHacks/SGInclude_Core_SGDevice.h" #include "SGBuildHacks/SGInclude_Core_HapticChannelInfo.h" #include "SGBuildHacks/SGInclude_Core_HapticGlove.h" #include "SGBuildHacks/SGInclude_Core_Nova2Glove.h" #include "SGBuildHacks/SGInclude_Core_NovaGlove.h" #include "SGBuildHacks/SGInclude_Core_SenseGlove.h" #include "SGCoreImpl/SGBetaDeviceImpl.h" #include "SGCoreImpl/SGCoreEnumCast.h" #include "SGCoreImpl/SGHapticChannelInfoImpl.h" #include "SGCoreImpl/SGHapticGloveImpl.h" #include "SGCoreImpl/SGNova2GloveImpl.h" #include "SGCoreImpl/SGNovaGloveImpl.h" #include "SGCoreImpl/SGSenseGloveImpl.h" #include "Templates/Casts.h" struct FSGDeviceImpl::FImpl { /************************ * Member variables ************************/ FSGDevicePtrType SGDevice; /************************ * Owner object ************************/ FSGDeviceImpl* Owner; /************************ * Constructor / Destructor ************************/ explicit FImpl(FSGDeviceImpl* InOwner); ~FImpl(); /************************ * Default copy constructor & copy assignment operator ************************/ FImpl(const FImpl& Rhs) = default; FImpl& operator=(const FImpl& Rhs) = default; }; void FSGDeviceImpl::ParseFirmware(const FString& RawFirmware, int32& OutMainVersion, int32& OutSubVersion) { FSGDeviceType::ParseFirmware(TCHAR_TO_UTF8(*RawFirmware), OutMainVersion, OutSubVersion); } bool FSGDeviceImpl::FirmwareNewerThan(const int32 MyFirmwareMain, const int32 MyFirmwareSub, const int32 ReferenceMain, const int32 ReferenceSub, const bool bInclusive) { return FSGDeviceType::FirmwareNewerThan(MyFirmwareMain, MyFirmwareSub, ReferenceMain, ReferenceSub, bInclusive); } bool FSGDeviceImpl::FirmwareOlderThan(const int32 MyFirmwareMain, const int32 MyFirmwareSub, const int32 ReferenceMain, const int32 ReferenceSub, const bool bInclusive) { return FSGDeviceType::FirmwareOlderThan(MyFirmwareMain, MyFirmwareSub, ReferenceMain, ReferenceSub, bInclusive); } FString FSGDeviceImpl::ToString(const ESGDeviceType DeviceType) { const FString String{UTF8_TO_TCHAR(FSGDeviceType::ToString(FSGCoreEnumCast::ToEDeviceType(DeviceType)).c_str())}; return String; } FSGDeviceImpl::FSGDeviceImpl() : Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) { } FSGDeviceImpl::FSGDeviceImpl(const FSGDevicePtrType SGDevice) : Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) { ensureAlwaysMsgf(SGDevice.get(), TEXT("Invalid SGDevice!")); Pimpl->SGDevice = SGDevice; } FSGDeviceImpl::FSGDeviceImpl(const FSGDeviceImpl& Rhs) : Pimpl(TUniquePtr(new FImpl{*Rhs.Pimpl}, PimplDeleter)) { Pimpl->Owner = this; } FSGDeviceImpl::FSGDeviceImpl(FSGDeviceImpl&& Rhs) SG_NOEXCEPT = default; FSGDeviceImpl::~FSGDeviceImpl() = default; FSGDeviceImpl& FSGDeviceImpl::operator=(const FSGDeviceImpl& Rhs) { *Pimpl = *Rhs.Pimpl; Pimpl->Owner = this; return *this; } FSGDeviceImpl& FSGDeviceImpl::operator=(FSGDeviceImpl&& Rhs) SG_NOEXCEPT = default; FSGDeviceImpl::FSGDevicePtrType FSGDeviceImpl::ToSGDevicePtr() const { return Pimpl->SGDevice; } FSGDeviceImpl::FSGDevicePtrType FSGDeviceImpl::ToSGDevicePtrChecked() const { ensureAlwaysMsgf(Pimpl->SGDevice.get(), TEXT("Invalid Pimpl->SGDevice!")); return Pimpl->SGDevice; } TSharedRef FSGDeviceImpl::ToSGDeviceImplRef() { return SharedThis(this); } TSharedRef FSGDeviceImpl::ToBetaDeviceImplRef() { FSGBetaDeviceImpl* BetaDevice{dynamic_cast(this)}; ensureAlwaysMsgf(BetaDevice, TEXT("Invalid BetaDevice!")); return SharedThis(BetaDevice); } TSharedRef FSGDeviceImpl::ToHapticGloveImplRef() { FSGHapticGloveImpl* HapticGlove{dynamic_cast(this)}; ensureAlwaysMsgf(HapticGlove, TEXT("Invalid HapticGlove!")); return SharedThis(HapticGlove); } TSharedRef FSGDeviceImpl::ToNova2GloveImplRef() { FSGNova2GloveImpl* Nova2Glove{dynamic_cast(this)}; ensureAlwaysMsgf(Nova2Glove, TEXT("Invalid Nova2Glove!")); return SharedThis(Nova2Glove); } TSharedRef FSGDeviceImpl::ToNovaGloveImplRef() { FSGNovaGloveImpl* NovaGlove{dynamic_cast(this)}; ensureAlwaysMsgf(NovaGlove, TEXT("Invalid NovaGlove!")); return SharedThis(NovaGlove); } TSharedRef FSGDeviceImpl::ToSenseGloveImplRef() { FSGSenseGloveImpl* SenseGlove{dynamic_cast(this)}; ensureAlwaysMsgf(SenseGlove, TEXT("Invalid SenseGlove!")); return SharedThis(SenseGlove); } bool FSGDeviceImpl::IsABetaDevice() const { const FSGBetaDeviceImpl::FBetaDevicePtrType BetaDevice{ std::dynamic_pointer_cast(ToSGDevicePtr()) }; return BetaDevice != nullptr; } bool FSGDeviceImpl::IsAHapticGlove() const { const FSGHapticGloveImpl::FHapticGlovePtrType HapticGlove{ std::dynamic_pointer_cast(ToSGDevicePtr()) }; return HapticGlove != nullptr; } bool FSGDeviceImpl::IsANova2Glove() const { const FSGNova2GloveImpl::FNova2GlovePtrType Nova2Glove{ std::dynamic_pointer_cast(ToSGDevicePtr()) }; return Nova2Glove != nullptr; } bool FSGDeviceImpl::IsANovaGlove() const { const FSGNovaGloveImpl::FNovaGlovePtrType NovaGlove{ std::dynamic_pointer_cast(ToSGDevicePtr()) }; return NovaGlove != nullptr; } bool FSGDeviceImpl::IsASenseGlove() const { const FSGSenseGloveImpl::FSenseGlovePtrType SenseGlove{ std::dynamic_pointer_cast(ToSGDevicePtr()) }; return SenseGlove != nullptr; } TSharedPtr FSGDeviceImpl::AsBetaDevice() const { const FSGBetaDeviceImpl::FBetaDevicePtrType BetaDevice{ std::dynamic_pointer_cast(ToSGDevicePtr()) }; ensureAlwaysMsgf(BetaDevice, TEXT("Invalid BetaDevice!")); return MakeShared(BetaDevice); } TSharedPtr FSGDeviceImpl::AsHapticGlove() const { const FSGHapticGloveImpl::FHapticGlovePtrType HapticGlove{ std::dynamic_pointer_cast(ToSGDevicePtr()) }; ensureAlwaysMsgf(HapticGlove, TEXT("Invalid HapticGlove!")); return MakeShared(HapticGlove); } TSharedPtr FSGDeviceImpl::AsNova2Glove() const { const FSGNova2GloveImpl::FNova2GlovePtrType Nova2Glove{ std::dynamic_pointer_cast(ToSGDevicePtr()) }; ensureAlwaysMsgf(Nova2Glove, TEXT("Invalid Nova2Glove!")); return MakeShared(Nova2Glove); } TSharedPtr FSGDeviceImpl::AsNovaGlove() const { const FSGNovaGloveImpl::FNovaGlovePtrType NovaGlove{ std::dynamic_pointer_cast(ToSGDevicePtr()) }; ensureAlwaysMsgf(NovaGlove, TEXT("Invalid NovaGlove!")); return MakeShared(NovaGlove); } TSharedPtr FSGDeviceImpl::AsSenseGlove() const { const FSGSenseGloveImpl::FSenseGlovePtrType SenseGlove{ std::dynamic_pointer_cast(ToSGDevicePtr()) }; ensureAlwaysMsgf(SenseGlove, TEXT("Invalid SenseGlove!")); return MakeShared(SenseGlove); } ESGDeviceType FSGDeviceImpl::GetDeviceType() const { return FSGCoreEnumCast::ToESGDeviceType(ToSGDevicePtrChecked()->GetDeviceType()); } FString FSGDeviceImpl::GetDeviceId() const { const FString Id{UTF8_TO_TCHAR(ToSGDevicePtrChecked()->GetDeviceId().c_str())}; return Id; } FString FSGDeviceImpl::GetHardwareVersion() const { const FString Version{UTF8_TO_TCHAR(ToSGDevicePtrChecked()->GetHardwareVersion().c_str())}; return Version; } int32 FSGDeviceImpl::GetFirmwareVersion() const { return ToSGDevicePtrChecked()->GetFirmwareVersion(); } int32 FSGDeviceImpl::GetSubFirmwareVersion() const { return ToSGDevicePtrChecked()->GetSubFirmwareVersion(); } FString FSGDeviceImpl::GetFirmwareString() const { const FString String{UTF8_TO_TCHAR(ToSGDevicePtrChecked()->GetFirmwareString().c_str())}; return String; } bool FSGDeviceImpl::FirmwareNewerThan(const int32 FirmwareMain, const int32 FirmwareSub, const bool bInclusive) const { return ToSGDevicePtrChecked()->FirmwareNewerThan(FirmwareMain, FirmwareSub, bInclusive); } bool FSGDeviceImpl::FirmwareOlderThan(const int32 FirmwareMain, const int32 FirmwareSub, const bool bInclusive) const { return ToSGDevicePtrChecked()->FirmwareOlderThan(FirmwareMain, FirmwareSub, bInclusive); } FString FSGDeviceImpl::GetAddress() const { const FString String(UTF8_TO_TCHAR(ToSGDevicePtrChecked()->GetAddress().c_str())); return String; } bool FSGDeviceImpl::IsConnected() const { return ToSGDevicePtrChecked()->IsConnected(); } ESGConnectionType FSGDeviceImpl::GetConnectionType() const { return FSGCoreEnumCast::ToESGConnectionType(ToSGDevicePtrChecked()->GetConnectionType()); } int32 FSGDeviceImpl::PacketsPerSecondReceived() const { return ToSGDevicePtrChecked()->PacketsPerSecondReceived(); } int32 FSGDeviceImpl::PacketsPerSecondSent() const { return ToSGDevicePtrChecked()->PacketsPerSecondSent(); } int32 FSGDeviceImpl::GetDeviceIndex() const { return ToSGDevicePtrChecked()->GetDeviceIndex(); } void FSGDeviceImpl::SetDeviceIndex(const int32 NewIndex) { ToSGDevicePtrChecked()->SetDeviceIndex(NewIndex); } bool FSGDeviceImpl::IsWireless() const { return ToSGDevicePtrChecked()->IsWireless(); } bool FSGDeviceImpl::HasBattery() const { return ToSGDevicePtrChecked()->HasBattery(); } bool FSGDeviceImpl::IsCharging() { return ToSGDevicePtrChecked()->IsCharging(); } bool FSGDeviceImpl::GetBatteryLevel(float& OutLevel) { return ToSGDevicePtrChecked()->GetBatteryLevel(OutLevel); } void FSGDeviceImpl::SetHapticChannels(const FSGHapticChannelInfoImpl& Channels) { ToSGDevicePtrChecked()->SetHapticChannels(Channels.ToHapticChannelInfo()); } int32 FSGDeviceImpl::GetHapticChannelCount() const { return ToSGDevicePtrChecked()->GetHapticChannelCount(); } int32 FSGDeviceImpl::GetHapticChannelCount(const ESGHapticChannelType ChannelType) const { return ToSGDevicePtrChecked()->GetHapticChannelCount(FSGCoreEnumCast::ToEHapticChannelType(ChannelType)); } FString FSGDeviceImpl::ToString() const { const FString String(UTF8_TO_TCHAR(ToSGDevicePtrChecked()->ToString().c_str())); return String; } FSGDeviceImpl::FImpl::FImpl(FSGDeviceImpl* InOwner) : SGDevice(std::make_shared()), Owner(InOwner) { } FSGDeviceImpl::FImpl::~FImpl() = default; void FSGDeviceImpl::FImplDeleter::operator()(const FSGDeviceImpl::FImpl* P) const { delete P; }