diff --git a/Source/SkyPortal/Private/SkyPortalIO.cpp b/Source/SkyPortal/Private/SkyPortalIO.cpp index df1b749..dbce435 100644 --- a/Source/SkyPortal/Private/SkyPortalIO.cpp +++ b/Source/SkyPortal/Private/SkyPortalIO.cpp @@ -123,6 +123,8 @@ void USkyPortalIO::Write(FWriteBlock* pb) (unsigned char*)pb->data, write_buf_size, &bytes_returned, &ol); ensureMsgf(res, TEXT("Unable to write to Portal")); + pb->BytesTransferred = bytes_returned; + } #else @@ -133,23 +135,23 @@ void USkyPortalIO::Write(FWriteBlock* pb) { return; } - pb->buf[0] = 0; // Use report 0 + pb->data[0] = 0; // Use report 0 - - ensureMsgf(hid_write(PortalDevice, pb->data, read_buf_size) != -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)); + res = hid_write(PortalDevice, pb->data, write_buf_size); + ensureMsgf(res != -1, TEXT("Unable to write to Portal, %s"), hid_error(PortalDevice)); + pb->BytesTransferred = res; } #endif -void USkyPortalIO::WriteRaw(FWriteBlock* block) +void USkyPortalIO::WriteRaw(const TArray block) { - int res = hid_write(PortalDevice, block->data, write_buf_size); + block.GetData; + int res = hid_write(PortalDevice, block, block.GetAllocatedSize()); //return the number of byte written if (res == -1) { UE_LOG(LogSkyportalIO, Error, TEXT("Unable to write raw data to Portal. error:\n %s"), hid_error(PortalDevice)); return; } - block->BytesTransferred = res; } uint8* USkyPortalIO::Read() @@ -163,4 +165,14 @@ void USkyPortalIO::Close() { if (PortalDevice) { hid_close(PortalDevice); } -} \ No newline at end of file +} + + +/* TODO: Should not be here +bool USkyPortalIO::IsFalsePositive() const +{ + int dif = FMath::Abs(CurrentStatusData.Counter - OldStatusData.Counter); + return (dif <= 2 || dif >= 254); + +} +*/ \ No newline at end of file diff --git a/Source/SkyPortal/Private/SkyPortalRunner.cpp b/Source/SkyPortal/Private/SkyPortalRunner.cpp index ebcbd86..b59265c 100644 --- a/Source/SkyPortal/Private/SkyPortalRunner.cpp +++ b/Source/SkyPortal/Private/SkyPortalRunner.cpp @@ -1,2 +1,54 @@ #include "SkyPortalRunner.h" +FPortalStatusChecker::FPortalStatusChecker(USkyPortalSubsystem* InSubsystem, float InCheckInterval) + : SkyPortalSubsystem(InSubsystem), CheckInterval(InCheckInterval), bShouldRun(true) +{ +} + +bool FPortalStatusChecker::Init() +{ + // Initialization logic, if necessary (e.g., logging) + return true; +} + +uint32 FPortalStatusChecker::Run() +{ + // Main loop of the thread, runs until Stop() is called + while (bShouldRun) + { + // Check the portal status + CheckPortalStatus(); + + // Sleep for the specified interval + FPlatformProcess::Sleep(CheckInterval); + } + + return 0; // Exit code for the thread +} + +void FPortalStatusChecker::Stop() +{ + // Signal the thread to stop running + bShouldRun = false; +} + +void FPortalStatusChecker::Exit() +{ + // Cleanup after the thread has stopped +} + +void FPortalStatusChecker::CheckPortalStatus() +{ + // Ensure the subsystem is valid + if (SkyPortalSubsystem && SkyPortalSubsystem->bPortalConnected) + { + UE_LOG(LogSkyportalIO, Verbose, TEXT("Check portal")); + + // Call the subsystem function to get portal status + + SkyPortalSubsystem->CheckComplexResponse(); + + // Do something with the status (log, notify, etc.) + UE_LOG(LogSkyportalIO, Verbose, TEXT("Portal Status:")); + } +} \ No newline at end of file diff --git a/Source/SkyPortal/Private/SkyPortalSubsystem.cpp b/Source/SkyPortal/Private/SkyPortalSubsystem.cpp index aee2b46..95b3946 100644 --- a/Source/SkyPortal/Private/SkyPortalSubsystem.cpp +++ b/Source/SkyPortal/Private/SkyPortalSubsystem.cpp @@ -5,7 +5,6 @@ #include "HAL/RunnableThread.h" #include "Misc/ScopeLock.h" -#include "SkyPortalIO.h" void USkyPortalSubsystem::Initialize(FSubsystemCollectionBase& Collection) @@ -35,8 +34,8 @@ void USkyPortalSubsystem::Deinitialize() } // Disconnect portal - if (PortalDevice) { - hid_close(PortalDevice); + if (PortalHandle) { + PortalHandle->Close(); } hid_exit(); @@ -45,29 +44,34 @@ void USkyPortalSubsystem::Deinitialize() Super::Deinitialize(); } -// Antenna up / activate -void USkyPortalSubsystem::ActivatePortal(int active) -{ - FWriteBlock req, res; - memset(req.data, 0, write_buf_size); - req.buf[1] = 'A'; - req.buf[2] = active; - do { Write(&req); } while (CheckResponse(&res, 'A')); - -} - -// Start portal -void USkyPortalSubsystem::Ready() +void USkyPortalSubsystem::PortalActivate(const bool bShouldActivate) { FWriteBlock command; - //memset(command.data, 0, write_buf_size); + memset(command.data, 0, write_buf_size); + command.data[1] = 'A'; + command.data[2] = bShouldActivate; + uint8* output; + do { + PortalHandle->Write(&command); + output = PortalHandle->Read(); + } while (output[0] != 'A'); + +} + + + +void USkyPortalSubsystem::PortalReady() +{ + FWriteBlock command; + + memset(command.data, 0, write_buf_size); //maybe not needed here command.data[1] = 'R'; uint8* output; - do { + do { PortalHandle->Write(&command); - output = PortalHandle->Read(); + output = PortalHandle->Read(); } while (output[0] != 'R'); uint16 _PortalId = ((output[1] << 8) + output[2]); @@ -76,7 +80,9 @@ void USkyPortalSubsystem::Ready() } -//{ Region Color & light functions + +#pragma region Color functions + void USkyPortalSubsystem::ChangePortalColor(const FLinearColor& Color) { @@ -84,28 +90,29 @@ void USkyPortalSubsystem::ChangePortalColor(const FLinearColor& Color) unsigned char g = FMath::Clamp(Color.G * 100, 0.0f, 255.0f); unsigned char b = FMath::Clamp(Color.B * 100, 0.0f, 255.0f); - RWBlock req; + FWriteBlock command; - memset(req.buf, 0, rw_buf_size); + memset(command.data, 0, write_buf_size); - req.buf[1] = 'C'; - req.buf[2] = r; // R - req.buf[3] = g; // G - req.buf[4] = b; // B + command.data[1] = 'C'; + command.data[2] = r; // R + command.data[3] = g; // G + command.data[4] = b; // B // no response for this one. - Write(&req); + PortalHandle->Write(&command); } -void USkyPortalSubsystem::ChangePortalColorside(const FLinearColor& Color, const EPortalSide PortalSide, const float BlendTime) + +void USkyPortalSubsystem::ChangePortalColorSide(const FLinearColor& Color, const EPortalSide PortalSide, const float BlendTime) { 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; + FWriteBlock command; - memset(req.buf, 0, rw_buf_size); + memset(command.data, 0, write_buf_size); if (PortalSide == EPortalSide::BOTH) { _portalside = EPortalSide::LEFT; @@ -113,43 +120,47 @@ void USkyPortalSubsystem::ChangePortalColorside(const FLinearColor& Color, const switch (_portalside) { case EPortalSide::LEFT: - req.buf[1] = 'J'; - req.buf[2] = 0x00; + command.data[1] = 'J'; + command.data[2] = 0x00; case EPortalSide::RIGHT: - req.buf[1] = 'J'; - req.buf[2] = 0x02; + command.data[1] = 'J'; + command.data[2] = 0x02; 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. + command.data[1] = 'L'; + command.data[2] = 0x01; + command.data[3] = FMath::Max3(r, g, b); // calculate brightness + PortalHandle->Write(&command); //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 + command.data[3] = r; // R + command.data[4] = g; // G + command.data[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; + command.data[6] = _time_low; + command.data[7] = _time_high; - do { Write(&req); } while (CheckResponse(&res, 'J')); + uint8* output; + do { + PortalHandle->Write(&command); + output = PortalHandle->Read(); + } while (output[0] != 'J'); if (PortalSide == EPortalSide::BOTH) { - ChangePortalColorside(Color, EPortalSide::RIGHT, BlendTime); // send a second command for the right side + ChangePortalColorSide(Color, EPortalSide::RIGHT, BlendTime); // send a second command for the right side } } -//} +#pragma endregion -FPortalStatusData USkyPortalSubsystem::ParsePortalStatus(const RWBlock& ResponseBlock) +FPortalStatusData USkyPortalSubsystem::ParsePortalStatus(const FWriteBlock& ResponseBlock) { FPortalStatusData PortalStatusData; @@ -214,8 +225,8 @@ void USkyPortalSubsystem::CheckComplexResponse() { RWBlock req, res; - memset(req.buf, 0, rw_buf_size); - req.buf[1] = 'S'; + memset(command.data, 0, rw_buf_size); + command.data[1] = 'S'; Write(&req); int BuffResponse = hid_read_timeout(PortalDevice, res.buf, rw_buf_size, TIMEOUT); @@ -303,18 +314,14 @@ TArray USkyPortalSubsystem::QueryBlock(uint8 characterIndex, uint8 block) -bool USkyPortalSubsystem::FalsePositive() const -{ - int dif = FMath::Abs(CurrentStatusData.Counter - OldStatusData.Counter); - return (dif <= 2 || dif >= 254); -} + /* 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) { @@ -330,35 +337,27 @@ bool USkyPortalSubsystem::CheckResponse(RWBlock* res, char expect) res->BytesTransferred = b; - /* this is here to debug the different responses from the portal. - #if DEBUG - SkylanderIO* skio; - skio = new SkylanderIO(); - printf("<<<\n"); - skio->fprinthex(stdout, res->buf, 0x21); - delete skio; - #endif - */ + // found wireless USB but portal is not connected - if (res->buf[0] == 'Z') - { - UE_LOG(LogSkyportalIO, Error, TEXT("found wireless USB but portal is not connected")); - return false; - } - - // Status says no skylander on portal - if (res->buf[0] == 'Q' && res->buf[1] == 0) { - 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); +if (res->buf[0] == 'Z') +{ + UE_LOG(LogSkyportalIO, Error, TEXT("found wireless USB but portal is not connected")); + return false; } +// Status says no skylander on portal +if (res->buf[0] == 'Q' && res->buf[1] == 0) { + 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); +} +*/ @@ -412,14 +411,14 @@ bool USkyPortalSubsystem::ReadBlock(unsigned int block, unsigned char data[0x10] { int i = 0; - memset(req.buf, 0, rw_buf_size); // Clear the request buffer (initialize all bytes to zero) - req.buf[1] = 'Q'; + memset(command.data, 0, rw_buf_size); // Clear the request buffer (initialize all bytes to zero) + command.data[1] = 'Q'; followup = 0x10 + skylanderIndex; - req.buf[2] = followup; + command.data[2] = followup; if (block == 0) { - req.buf[2] = followup + 0x10; // may not be needed + command.data[2] = followup + 0x10; // may not be needed } - req.buf[3] = (unsigned char)block; + command.data[3] = (unsigned char)block; memset(&(res.buf), 0, rw_buf_size); // Clear the response buffer to prepare for incoming data @@ -444,13 +443,13 @@ bool USkyPortalSubsystem::ReadBlock(unsigned int block, unsigned char data[0x10] return false; } -bool USkyPortalSubsystem::ConnectPortal() +bool USkyPortalSubsystem::PortalConnect() { PortalHandle = NewObject(); if (IsValidLowLevelFast(PortalHandle)) { UE_LOG(LogSkyportalIO, Log, TEXT("Portal connected: ")); - Ready(); - ActivatePortal(1); + PortalReady(); + PortalActivate(1); Sleep(500); ChangePortalColor(FLinearColor(0.5, 0.5, 0.5)); @@ -476,58 +475,7 @@ void USkyPortalSubsystem::SendPortalSound(USoundWave* Sound) -FPortalStatusChecker::FPortalStatusChecker(USkyPortalSubsystem* InSubsystem, float InCheckInterval) - : SkyPortalSubsystem(InSubsystem), CheckInterval(InCheckInterval), bShouldRun(true) -{ -} -bool FPortalStatusChecker::Init() -{ - // Initialization logic, if necessary (e.g., logging) - return true; -} - -uint32 FPortalStatusChecker::Run() -{ - // Main loop of the thread, runs until Stop() is called - while (bShouldRun) - { - // Check the portal status - CheckPortalStatus(); - - // Sleep for the specified interval - FPlatformProcess::Sleep(CheckInterval); - } - - return 0; // Exit code for the thread -} - -void FPortalStatusChecker::Stop() -{ - // Signal the thread to stop running - bShouldRun = false; -} - -void FPortalStatusChecker::Exit() -{ - // Cleanup after the thread has stopped -} - -void FPortalStatusChecker::CheckPortalStatus() -{ - // Ensure the subsystem is valid - if (SkyPortalSubsystem && SkyPortalSubsystem->bPortalConnected) - { - UE_LOG(LogSkyportalIO, Verbose, TEXT("Check portal")); - - // Call the subsystem function to get portal status - - SkyPortalSubsystem->CheckComplexResponse(); - - // Do something with the status (log, notify, etc.) - UE_LOG(LogSkyportalIO, Verbose, TEXT("Portal Status:")); - } -} FigureDataBlock USkyPortalSubsystem::ReadFigureBlocks(uint8 FigureIndex) { @@ -540,10 +488,10 @@ FigureDataBlock USkyPortalSubsystem::ReadFigureBlocks(uint8 FigureIndex) for (uint8 BlockIndex = 0; BlockIndex < FIGURE_TOTAL_BLOCKS; ++BlockIndex) { // Prepare the request buffer - memset(req.buf, 0, rw_buf_size); - req.buf[1] = 'Q'; // Command character - req.buf[2] = FigureIndex; // Figure index (0x00 to 0x0F) - req.buf[3] = BlockIndex; // Block index (0x00 to 0x3F) + memset(command.data, 0, rw_buf_size); + command.data[1] = 'Q'; // Command character + command.data[2] = FigureIndex; // Figure index (0x00 to 0x0F) + command.data[3] = BlockIndex; // Block index (0x00 to 0x3F) // Send the request Write(&req); diff --git a/Source/SkyPortal/Public/SkyPortalFigure.h b/Source/SkyPortal/Public/SkyPortalFigure.h index e2e12f4..c8813d1 100644 --- a/Source/SkyPortal/Public/SkyPortalFigure.h +++ b/Source/SkyPortal/Public/SkyPortalFigure.h @@ -19,11 +19,7 @@ typedef struct { unsigned char blockdata[FIGURE_TOTAL_BLOCKS][FIGURE_BLOCK_SIZE]; bool error; } FigureDataBlock; -UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure")) -uint32 GetFigureID(const FigureDataBlock& DataBlock); -UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure")) -uint32 GetFigureIdByIndex(uint32 index); class FigureData { public: @@ -58,6 +54,13 @@ public: } // Methods + + UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure")) + uint32 GetFigureID(const FigureDataBlock& DataBlock); + + UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure")) + uint32 GetFigureIdByIndex(uint32 index); + void ReadData(uint8 index); void ClearData(); uint8 GetByte(int block, int offset); diff --git a/Source/SkyPortal/Public/SkyPortalIO.h b/Source/SkyPortal/Public/SkyPortalIO.h index 33f501a..371486f 100644 --- a/Source/SkyPortal/Public/SkyPortalIO.h +++ b/Source/SkyPortal/Public/SkyPortalIO.h @@ -18,7 +18,7 @@ const int VendorIds[4] = { 0x12ba, 0x54c, 0x1430, 0x1430 }; const int ProductIds[4] = { 0x150, 0x967, 0x1f17 }; /* WriteBlock -* +* * Contain all the data that pass inside hidapi write + the number of bytes in case of successful write * @param data all the block data, should be 0x21 sized * @param BytesTransferred In case of successful write, print the number of byte transfered. Could be used for verifications @@ -26,9 +26,9 @@ const int ProductIds[4] = { 0x150, 0x967, 0x1f17 }; USTRUCT() struct FWriteBlock { GENERATED_BODY() - unsigned char data[write_buf_size]; + unsigned char data[write_buf_size]; int BytesTransferred; -} ; +}; /* This class will contain and handle all the low-lewel functions * Should be able to be called anywhere @@ -50,18 +50,23 @@ public: /* Connect to Portal - will write the PortalDevice var if success */ bool OpenPortalHandle(); + /* Send block to portal. In windows, don't use the hidapi */ void Write(FWriteBlock* Block); - void WriteRaw(FWriteBlock* Block); + + /* Send raw command to portal */ + void WriteRaw(const TArray* block); /* Listen to portal * @return The data sended by the portal device */ - UFUNCTION() uint8* Read(); void Close(); private: + /*TODO: Should not be here + bool IsFalsePositive() const; + */ /* Portal ref used in the subsystem */ diff --git a/Source/SkyPortal/Public/SkyPortalRunner.h b/Source/SkyPortal/Public/SkyPortalRunner.h index 9bda771..33c9f69 100644 --- a/Source/SkyPortal/Public/SkyPortalRunner.h +++ b/Source/SkyPortal/Public/SkyPortalRunner.h @@ -1,13 +1,9 @@ #pragma once +#include "CoreMinimal.h" #include "HAL/Runnable.h" #include "SkyPortalFigure.h" -class SkyPortalRunner -{ - -}; - USTRUCT(BlueprintType) struct FPortalStatusData { @@ -65,6 +61,8 @@ public: virtual void Stop() override; virtual void Exit() override; + + private: // Pointer to the subsystem that contains PortalStatus() USkyPortalSubsystem* SkyPortalSubsystem; diff --git a/Source/SkyPortal/Public/SkyPortalSubsystem.h b/Source/SkyPortal/Public/SkyPortalSubsystem.h index 5e85e97..b1d04e1 100644 --- a/Source/SkyPortal/Public/SkyPortalSubsystem.h +++ b/Source/SkyPortal/Public/SkyPortalSubsystem.h @@ -2,6 +2,7 @@ #include "Subsystems/EngineSubsystem.h" #include "SkyPortalRunner.h" +#include "SkyPortalIO.h" #include "SkyPortalSubsystem.generated.h" @@ -50,7 +51,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderRemovedDelegate, int32, /* * Handle all the blueprints functions and game logic. -* +* */ UCLASS(MinimalAPI) class USkyPortalSubsystem : public UEngineSubsystem @@ -59,10 +60,13 @@ class USkyPortalSubsystem : public UEngineSubsystem public: // Override initialization and deinitialization methods + virtual void Initialize(FSubsystemCollectionBase& Collection) override; virtual void Deinitialize() override; - /********* Portal Actions *************/ + /***********************************************************/ + /********************* Portal Actions *********************/ + /***********************************************************/ /* The first function to run, before anything else. * It will re-init and prepare the portal for receiving/sending inputs @@ -70,11 +74,33 @@ public: * return false if portal is not found */ UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal")) - SKYPORTAL_API bool ConnectPortal(); - + SKYPORTAL_API bool PortalConnect(); + /* Make sure that the connection to the portal works and that the device that is connected is actually a portal. + * + * In case of success, will update the PortalId, wich is different for each portal model. + */ UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal|Commands")) - SKYPORTAL_API void Ready(); + SKYPORTAL_API void PortalReady(); + + /* Activate all the main functions of the portal, like figure detection or wireless signal. + * This command should be used before any other commands with the exception of the Ready command + * + * When the portal is activated, it will periodically send out Status responses even when no Status request has been sent. If the portal has not been activated, or if it has been deactivated again, Status responses will still be sent when requested. + * If a Deactivate request is received by a portal, all LEDs will turn off. They can be turned on again by their respective commands. + * + * @param bShouldActivate Optional : If false, send a Deactivate command. + */ + UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal|Commands")) + SKYPORTAL_API void PortalActivate(const bool bShouldActivate = true); + + + /* Change portal color, ideally should be called just at the start. For gameplay usage, use ChangePortalColorSide() + * + * @param NextColor New color + */ + UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "NextColor", Category = "SkyPortal|Commands|Cosmetic", HideAlphaChannel)) + SKYPORTAL_API void ChangePortalColor(const FLinearColor& NextColor = FLinearColor::Green); /*Send a **Status** command, to see if the portal is ready to receive new commands*/ UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|NOT FUNCTIONING")) @@ -88,9 +114,7 @@ public: - /* 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 @@ -98,8 +122,8 @@ public: * @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", HideAlphaChannel)) - SKYPORTAL_API void ChangePortalColorside(const FLinearColor& NextColor = FLinearColor::Green, const EPortalSide PortalSide = EPortalSide::BOTH, const float BlendTime = 500.0f); + UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "NextColor", Category = "SkyPortal|Commands|Cosmetic", HideAlphaChannel)) + SKYPORTAL_API void ChangePortalColorSide(const FLinearColor& NextColor = FLinearColor::Green, const EPortalSide PortalSide = EPortalSide::BOTH, const float BlendTime = 500.0f); // Blueprint-assignable event property @@ -116,8 +140,17 @@ public: UPROPERTY(BlueprintReadOnly) FPortalStatusData OldStatusData; + /* Different for each portal model. + * + * SSA : + * GIANTS : + * SWAP FORCE : 0000547 ? + * TRAP TEAM : + * SUPERCHARGERS : + * IMAGINATORS : + */ UPROPERTY(BlueprintReadOnly) - uint32 PortalId; + int PortalId; EPortalCommand GetPortalCommandFromChar(unsigned char Char); @@ -126,30 +159,33 @@ public: bool bPortalConnected = false; - + UFUNCTION() TArray QueryBlock(uint8 characterIndex, uint8 block = 0x00); USkyPortalIO* PortalHandle; private: - FPortalStatusData ParsePortalStatus(const WriteBlock& ResponseBlock); - + FPortalStatusData ParsePortalStatus(const FWriteBlock& ResponseBlock); + /* Sleep the system + * + * @param sleepMs Sleep time (in milliseconds) + */ static void Sleep(int sleepMs); - void ActivatePortal(int active); - + + // Block/byte related data write/read functions - - + + FigureDataBlock ReadFigureBlocks(uint8 FigureIndex); bool FalsePositive() const;