diff --git a/Source/SkyPortal/Private/SkyPortalSubsystem.cpp b/Source/SkyPortal/Private/SkyPortalSubsystem.cpp index ee954f7..a60a599 100644 --- a/Source/SkyPortal/Private/SkyPortalSubsystem.cpp +++ b/Source/SkyPortal/Private/SkyPortalSubsystem.cpp @@ -139,17 +139,18 @@ bool USkyPortalSubsystem::OpenPortalHandle() { UE_LOG(LogHIDApi, Error, TEXT("No Portals found")); return false; } - +//{ Region Color & light functions void USkyPortalSubsystem::ChangePortalColor(const FLinearColor& Color) { 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 b = FMath::Clamp(Color.B * 100, 0.0f, 100.0f); RWBlock req; memset(req.buf, 0, rw_buf_size); + req.buf[1] = 'C'; req.buf[2] = r; // R req.buf[3] = g; // G @@ -158,7 +159,48 @@ 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 ) +{ + 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); + RWBlock req, res; + + memset(req.buf, 0, rw_buf_size); + + req.buf[1] = 'J'; + switch (PortalSide) { + case EPortalSide::LEFT: + req.buf[2] = 0x00; + case EPortalSide::RIGHT: + req.buf[2] = 0x02; + case EPortalSide::BOTH: + req.buf[2] = 0x01; //maybe that doesnt work, will give it a try + } + + req.buf[3] = r; // R + req.buf[4] = g; // G + req.buf[5] = b; // B + + //Convert the time in millisecond into two bytes + uint16_t _time = BlendTime; + uint8_t _time_low = _time & 0xFF; // Get the low byte by masking the least significant 8 bits + uint8_t _time_high = (_time >> 8) & 0xFF; // Get the high byte extracted by shifting the bits 8 positions to the right and masking the result + req.buf[6] = _time_low; + req.buf[7] = _time_high; + + do { Write(&req); } while (CheckResponse(&res, 'J')); + +} +//} + + +// write function need to be different on windows, as hid_write doesn't work with the way windows handle I/O #if PLATFORM_WINDOWS #include @@ -188,6 +230,10 @@ struct hid_device_ { void USkyPortalSubsystem::Write(RWBlock* pb) { + if (!ensure(PortalDevice)) { + UE_LOG(LogSkyportalIO, Error, TEXT("No Portal found")); + return; + } BOOL res; OVERLAPPED ol; @@ -200,7 +246,7 @@ void USkyPortalSubsystem::Write(RWBlock* pb) (unsigned char*)pb->buf, 0x21, (unsigned char*)pb->buf, 0x21, &bytes_returned, &ol); - ensureMsgf(res, TEXT("Unable to write to Portal, %s"), hid_error(PortalDevice)); + ensureMsgf(res, TEXT("Unable to write to Portal")); } #else @@ -215,7 +261,7 @@ void USkyPortalSubsystem::Write(RWBlock *pb) { 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 after multiple attempts. error:\n %s"), hid_error(PortalDevice)); + UE_LOG(LogSkyportalIO, Error, TEXT("Unable to write to Portal. error:\n %s"), hid_error(PortalDevice)); } #endif @@ -224,7 +270,7 @@ 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) { if (!PortalDevice) { @@ -262,6 +308,10 @@ bool USkyPortalSubsystem::CheckResponse(RWBlock *res, char expect) UE_LOG(LogSkyportalIO, Warning, TEXT("Status says no skylander on portal")); } + if (res->buf[0] == 'R' && res->buf[1] == 0) { + UE_LOG(LogSkyportalIO, Warning, TEXT("Status says no skylander on portal")); + } + return (res->buf[0] != expect); } diff --git a/Source/SkyPortal/Public/SkyPortalSubsystem.h b/Source/SkyPortal/Public/SkyPortalSubsystem.h index 8afbd75..643aeb5 100644 --- a/Source/SkyPortal/Public/SkyPortalSubsystem.h +++ b/Source/SkyPortal/Public/SkyPortalSubsystem.h @@ -8,6 +8,16 @@ #include "SkyPortalSubsystem.generated.h" +UENUM(BlueprintType) +enum EPortalSide { + LEFT UMETA(DisplayName = "Left side"), + RIGHT UMETA(DisplayName = "Right side"), + BOTH UMETA(DisplayName = "Both left and right"), + TRAP UMETA(DisplayName = "Trap") +}; + + + /* Macro Definitions */ #define rw_buf_size 0x21 #define TIMEOUT 30000 @@ -17,8 +27,8 @@ DECLARE_LOG_CATEGORY_EXTERN(LogHIDApi, Log, All); DECLARE_LOG_CATEGORY_EXTERN(LogSkyportalIO, Log, All); /* Subsystem */ -UCLASS() -class SKYPORTAL_API USkyPortalSubsystem : public UEngineSubsystem +UCLASS(MinimalAPI) +class USkyPortalSubsystem : public UEngineSubsystem { GENERATED_BODY() @@ -34,7 +44,7 @@ public: // Connect to Portal, return false if portal is not found UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal")) - bool ConnectPortal(); + SKYPORTAL_API bool ConnectPortal(); @@ -44,9 +54,21 @@ public: FString HidError; - UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "Color", Category = "SkyPortal")) - void ChangePortalColor(const FLinearColor& Color = FLinearColor::Green); + /* 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(); @@ -82,7 +104,7 @@ protected: //Constants const int VendorIds[4] = { 0x12ba, 0x54c, 0x1430, 0x1430 }; const int ProductIds[4] = { 0x150, 0x967, 0x1f17 }; - + /////Defaults values, should not be used