From 804e5fe911efd3260821c3e63d2bb68a70c404fb Mon Sep 17 00:00:00 2001 From: LUCASTUCIOUS Date: Sun, 22 Sep 2024 23:58:01 +0200 Subject: [PATCH] wip:cleanup --- .../SkyPortal/Private/SkyPortalSubsystem.cpp | 91 +++++++++++-------- Source/SkyPortal/Public/SkyPortalSubsystem.h | 91 ++++++++++++++----- 2 files changed, 118 insertions(+), 64 deletions(-) diff --git a/Source/SkyPortal/Private/SkyPortalSubsystem.cpp b/Source/SkyPortal/Private/SkyPortalSubsystem.cpp index a60a599..e0754a8 100644 --- a/Source/SkyPortal/Private/SkyPortalSubsystem.cpp +++ b/Source/SkyPortal/Private/SkyPortalSubsystem.cpp @@ -13,22 +13,6 @@ void USkyPortalSubsystem::Initialize(FSubsystemCollectionBase& Collection) // Custom initialization logic UE_LOG(LogTemp, Log, TEXT("SkyPortalSubsystem Initialized")); - // Initialize HIDAPI - /*May be not needed - int res = hid_init(); - if (res == 0) - { - UE_LOG(LogHIDApi, Log, TEXT("HIDAPI initialized successfully.")); - - } - else - { - UE_LOG(LogHIDApi, Error, TEXT("Failed to initialize HIDAPI.")); - HidError = hid_error(NULL); - UE_LOG(LogHIDApi, Error, TEXT("%s"), *HidError); - } - */ - } void USkyPortalSubsystem::Deinitialize() @@ -159,30 +143,36 @@ void USkyPortalSubsystem::ChangePortalColor(const FLinearColor& Color) // no response for this one. Write(&req); } -void USkyPortalSubsystem::ChangePortalColorside(const FLinearColor& Color, const EPortalSide PortalSide, const float BlendTime ) +void USkyPortalSubsystem::ChangePortalColorside(const FLinearColor& Color, const EPortalSide PortalSide, const float BlendTime) { - if (PortalSide == EPortalSide::TRAP) { - UE_LOG(LogSkyportalIO, Error, TEXT("This function should only be called for the left or right side of the portal")); - return; - } - unsigned char r = FMath::Clamp(Color.R * 100, 0.0f, 100.0f); - unsigned char g = FMath::Clamp(Color.G * 100, 0.0f, 100.0f); - unsigned char b = FMath::Clamp(Color.B * 100, 0.0f, 100.0f); + unsigned char r = FMath::Clamp(Color.R * 100, 0, 255); + unsigned char g = FMath::Clamp(Color.G * 100, 0, 255); + unsigned char b = FMath::Clamp(Color.B * 100, 0, 255); + EPortalSide _portalside; RWBlock req, res; memset(req.buf, 0, rw_buf_size); - req.buf[1] = 'J'; - switch (PortalSide) { + if (PortalSide == EPortalSide::BOTH) { + _portalside = EPortalSide::LEFT; + } + + switch (_portalside) { case EPortalSide::LEFT: + req.buf[1] = 'J'; req.buf[2] = 0x00; case EPortalSide::RIGHT: + req.buf[1] = 'J'; req.buf[2] = 0x02; - case EPortalSide::BOTH: - req.buf[2] = 0x01; //maybe that doesnt work, will give it a try + case EPortalSide::TRAP: + req.buf[1] = 'L'; + req.buf[2] = 0x01; + req.buf[3] = FMath::Max3(r, g, b); // calculate brightness + Write(&req); //since it's a color command for trap, only 3 bytes are needed, no response. + return; } - + req.buf[3] = r; // R req.buf[4] = g; // G req.buf[5] = b; // B @@ -196,6 +186,9 @@ void USkyPortalSubsystem::ChangePortalColorside(const FLinearColor& Color, const do { Write(&req); } while (CheckResponse(&res, 'J')); + if (PortalSide == EPortalSide::BOTH) { + ChangePortalColorside(Color, EPortalSide::RIGHT, BlendTime); // send a second command for the right side + } } //} @@ -250,18 +243,18 @@ void USkyPortalSubsystem::Write(RWBlock* pb) } #else -void USkyPortalSubsystem::Write(RWBlock *pb) { +void USkyPortalSubsystem::Write(RWBlock* pb) { - if (!ensure(PortalDevice)) { - UE_LOG(LogSkyportalIO, Error, TEXT("No Portal found")); - return; - } + if (!ensure(PortalDevice)) { + UE_LOG(LogSkyportalIO, Error, TEXT("No Portal found")); + return; + } - pb->buf[0] = 0; // Use report 0 + pb->buf[0] = 0; // Use report 0 - ensureMsgf(hid_write(PortalDevice, pb->buf, 0x21) != -1, TEXT("Unable to write to Portal, %s"), hid_error(PortalDevice)); - UE_LOG(LogSkyportalIO, Error, TEXT("Unable to write to Portal. error:\n %s"), hid_error(PortalDevice)); + ensureMsgf(hid_write(PortalDevice, pb->buf, 0x21) != -1, TEXT("Unable to write to Portal, %s"), hid_error(PortalDevice)); + UE_LOG(LogSkyportalIO, Error, TEXT("Unable to write to Portal. error:\n %s"), hid_error(PortalDevice)); } #endif @@ -270,8 +263,11 @@ void USkyPortalSubsystem::Sleep(int sleepMs) { FPlatformProcess::Sleep(sleepMs * 0.0001); } -// TODO: Refacto this function to handle better the response/output from the portal -bool USkyPortalSubsystem::CheckResponse(RWBlock *res, char expect) +/* Verify the command response, when only a character is sended by the portal. +* +*TODO: Refacto this function to handle better the response/output from the portal +*/ +bool USkyPortalSubsystem::CheckResponse(RWBlock* res, char expect) { if (!PortalDevice) { return false; @@ -415,11 +411,26 @@ bool USkyPortalSubsystem::ConnectPortal() Sleep(500); ChangePortalColor(FLinearColor(0xC8, 0xC8, 0xC8)); - UE_LOG(LogSkyportalIO, Log, TEXT("Portal Status: %d\n"), PortalStatus()); + UE_LOG(LogSkyportalIO, Log, TEXT("Portal Status: "), PortalStatus()); } return bPortalConnected; } +bool USkyPortalSubsystem::bIsPortalReady() +{ + return false; +} + +void USkyPortalSubsystem::SendPortalCommand(EPortalCommand Command) +{ + +} + +void USkyPortalSubsystem::SendPortalSound(USoundWave* Sound) +{ + +} + unsigned char USkyPortalSubsystem::PortalStatus() diff --git a/Source/SkyPortal/Public/SkyPortalSubsystem.h b/Source/SkyPortal/Public/SkyPortalSubsystem.h index 643aeb5..e6f93fd 100644 --- a/Source/SkyPortal/Public/SkyPortalSubsystem.h +++ b/Source/SkyPortal/Public/SkyPortalSubsystem.h @@ -7,6 +7,7 @@ #include "SkyPortalSubsystem.generated.h" +#pragma region Definitions UENUM(BlueprintType) enum EPortalSide { @@ -16,9 +17,21 @@ enum EPortalSide { TRAP UMETA(DisplayName = "Trap") }; +UENUM(BlueprintType) +enum EPortalCommand { + A UMETA(DisplayName = "Activate"), + C UMETA(DisplayName = "Color"), + J UMETA(DisplayName = "Advanced color"), + L UMETA(DisplayName = "Trap color"), + M UMETA(DisplayName = "Music"), + Q UMETA(DisplayName = "Query"), + R UMETA(DisplayName = "Ready"), + S UMETA(DisplayName = "Status") +}; -/* Macro Definitions */ + +/* Macro constants Definitions */ #define rw_buf_size 0x21 #define TIMEOUT 30000 #define DEBUG true @@ -26,7 +39,18 @@ enum EPortalSide { DECLARE_LOG_CATEGORY_EXTERN(LogHIDApi, Log, All); DECLARE_LOG_CATEGORY_EXTERN(LogSkyportalIO, Log, All); -/* Subsystem */ +//// Delegates +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderAddedDelegate, int32, SkylanderID, int32, Index); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderRemovedDelegate, int32, SkylanderID, int32, Index); + +#pragma endregion + + +/* Handle all the portal I/O +* +* +* +*/ UCLASS(MinimalAPI) class USkyPortalSubsystem : public UEngineSubsystem { @@ -40,13 +64,48 @@ public: virtual void Initialize(FSubsystemCollectionBase& Collection) override; virtual void Deinitialize() override; - + /********* Portal Actions *************/ - // Connect to Portal, return false if portal is not found + /* The first function to run, before anything else. + * It will re-init and prepare the portal for receiving/sending inputs + * + * return false if portal is not found + */ UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal")) SKYPORTAL_API bool ConnectPortal(); - + /*Send a **Status** command, to see if the portal is ready to receive new commands*/ + UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|NOT FUNCTIONING")) + SKYPORTAL_API bool bIsPortalReady(); + + UFUNCTION(BlueprintCallable, meta = (Category = "SkyPortal|NOT FUNCTIONING")) + SKYPORTAL_API void SendPortalCommand(EPortalCommand Command); + + UFUNCTION(BlueprintCallable, meta = (Category = "SkyPortal|NOT FUNCTIONING")) + SKYPORTAL_API void SendPortalSound(USoundWave* Sound); + + /* Change portal color, ideally should be called just at the start.For gameplay usage, use ChangePortalColorside()*/ + UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "Color", Category = "SkyPortal|Cosmetic")) + SKYPORTAL_API void ChangePortalColor(const FLinearColor& Color = FLinearColor::Green); + + /** + * Change the color of the portal, can separate side and even trap ligth + * @param NextColor New color + * @param PortalSide The actors to record + * @param BlendTime Blend between current color and NextColor, in milliseconds + */ + UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "NextColor", Category = "SkyPortal|Cosmetic")) + SKYPORTAL_API void ChangePortalColorside(const FLinearColor& NextColor = FLinearColor::Green, const EPortalSide PortalSide = EPortalSide::BOTH, const float BlendTime = 500.0f); + + + // Blueprint-assignable event property + UPROPERTY(BlueprintAssignable, Category = "SkyPortal|Skylander") + FOnSkylanderAddedDelegate OnSkylanderAdded; + + // Blueprint-assignable event property + UPROPERTY(BlueprintAssignable, Category = "SkyPortal|Skylander") + FOnSkylanderRemovedDelegate OnSkylanderRemoved; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) bool bPortalConnected = false; @@ -54,22 +113,6 @@ public: FString HidError; - /* Portal Actions*/ - - // Change portal color, ideally should be called just at the start. For gameplay usage, use ChangePortalColorside() - UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "Color", Category = "SkyPortal|Cosmetic")) - SKYPORTAL_API void ChangePortalColor(const FLinearColor& Color = FLinearColor::Green); - - - - /** - * Change the color of the portal, can separate side and even trap ligth - * @param PortalSide The actors to record - * @param BlendTime Blend between current color and NextColor - */ - UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "NextColor", Category = "SkyPortal|Cosmetic")) - SKYPORTAL_API void ChangePortalColorside(const FLinearColor& NextColor = FLinearColor::Green,const EPortalSide PortalSide = EPortalSide::BOTH,const float BlendTime=100.0f); - unsigned char PortalStatus(); @@ -95,8 +138,8 @@ private: bool OpenPortalHandle(); bool ReadBlock(unsigned int block, unsigned char data[0x10], int skylander); bool WriteBlock(unsigned int, unsigned char[0x10], int); - bool CheckResponse(RWBlock *, char); - void Write(RWBlock *); + bool CheckResponse(RWBlock*, char); + void Write(RWBlock*); protected: @@ -104,7 +147,7 @@ protected: //Constants const int VendorIds[4] = { 0x12ba, 0x54c, 0x1430, 0x1430 }; const int ProductIds[4] = { 0x150, 0x967, 0x1f17 }; - + /////Defaults values, should not be used