├── .gitignore ├── Content ├── Console │ ├── ConsoleWidget.uasset │ ├── RVDBpFunctionLibrary.uasset │ ├── RVDFunctionLibrary.uasset │ ├── WRCoreBpFunctionLibrary.uasset │ └── WorldConsole.uasset ├── FloatDebugActor.uasset ├── RotatorDebugActor.uasset └── VectorDebugActor.uasset ├── LICENSE ├── README.md ├── RealtimeValueDebug.uplugin ├── Resources └── Icon128.png └── Source └── RealtimeValueDebug ├── Private ├── RVDBlueprintLibrary.cpp ├── RVDConsumer.cpp └── RealtimeValueDebug.cpp ├── Public ├── RVDBlueprintLibrary.h ├── RVDConsumer.h └── RealtimeValueDebug.h └── RealtimeValueDebug.Build.cs /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | Binaries/* 11 | 12 | # Windows Installer files 13 | *.cab 14 | *.msi 15 | *.msm 16 | *.msp 17 | *.pdb 18 | 19 | # Windows shortcuts 20 | *.lnk 21 | 22 | # ========================= 23 | # Operating System Files 24 | # ========================= 25 | 26 | # OSX 27 | # ========================= 28 | 29 | .DS_Store 30 | .AppleDouble 31 | .LSOverride 32 | 33 | # Thumbnails 34 | ._* 35 | 36 | # Files that might appear in the root of a volume 37 | .DocumentRevisions-V100 38 | .fseventsd 39 | .Spotlight-V100 40 | .TemporaryItems 41 | .Trashes 42 | .VolumeIcon.icns 43 | 44 | # Directories potentially created on remote AFP share 45 | .AppleDB 46 | .AppleDesktop 47 | Network Trash Folder 48 | Temporary Items 49 | .apdisk 50 | Intermediate -------------------------------------------------------------------------------- /Content/Console/ConsoleWidget.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/getnamo/RVD-Unreal/c75f116633e1ffc811f89c6f4f4f836e6d64ae25/Content/Console/ConsoleWidget.uasset -------------------------------------------------------------------------------- /Content/Console/RVDBpFunctionLibrary.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/getnamo/RVD-Unreal/c75f116633e1ffc811f89c6f4f4f836e6d64ae25/Content/Console/RVDBpFunctionLibrary.uasset -------------------------------------------------------------------------------- /Content/Console/RVDFunctionLibrary.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/getnamo/RVD-Unreal/c75f116633e1ffc811f89c6f4f4f836e6d64ae25/Content/Console/RVDFunctionLibrary.uasset -------------------------------------------------------------------------------- /Content/Console/WRCoreBpFunctionLibrary.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/getnamo/RVD-Unreal/c75f116633e1ffc811f89c6f4f4f836e6d64ae25/Content/Console/WRCoreBpFunctionLibrary.uasset -------------------------------------------------------------------------------- /Content/Console/WorldConsole.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/getnamo/RVD-Unreal/c75f116633e1ffc811f89c6f4f4f836e6d64ae25/Content/Console/WorldConsole.uasset -------------------------------------------------------------------------------- /Content/FloatDebugActor.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/getnamo/RVD-Unreal/c75f116633e1ffc811f89c6f4f4f836e6d64ae25/Content/FloatDebugActor.uasset -------------------------------------------------------------------------------- /Content/RotatorDebugActor.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/getnamo/RVD-Unreal/c75f116633e1ffc811f89c6f4f4f836e6d64ae25/Content/RotatorDebugActor.uasset -------------------------------------------------------------------------------- /Content/VectorDebugActor.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/getnamo/RVD-Unreal/c75f116633e1ffc811f89c6f4f4f836e6d64ae25/Content/VectorDebugActor.uasset -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | RealtimeValueDebug (rvd-unreal) 4 | Copyright (c) 2020-present, Jan Kaniewski (Getnamo) 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RVD-Unreal 2 | Real-time Value Debugging for Unreal Engine 4. Mainly used to visualize vectors, floats, rotations, and other values while running your project. Should have easy utilities to emit from C++ and then consume on BP side to lower the number of C++ reload loops needed to write correct vector logic. 3 | -------------------------------------------------------------------------------- /RealtimeValueDebug.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "0.2.2", 5 | "FriendlyName": "RealtimeValueDebug", 6 | "Description": "Real-time Value Debugging for Unreal Engine. Mainly used to visualize vectors, floats, rotations, and other values while running your project.", 7 | "Category": "Utility", 8 | "CreatedBy": "getnamo", 9 | "CreatedByURL": "getnamo.com", 10 | "DocsURL": "https://github.com/getnamo/rvd-unreal", 11 | "MarketplaceURL": "", 12 | "SupportURL": "https://github.com/getnamo/rvd-unreal/issues", 13 | "EnabledByDefault": true, 14 | "CanContainContent": true, 15 | "IsBetaVersion": false, 16 | "IsExperimentalVersion": false, 17 | "Installed": false, 18 | "Modules": [ 19 | { 20 | "Name": "RealtimeValueDebug", 21 | "Type": "Runtime", 22 | "LoadingPhase": "Default" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/getnamo/RVD-Unreal/c75f116633e1ffc811f89c6f4f4f836e6d64ae25/Resources/Icon128.png -------------------------------------------------------------------------------- /Source/RealtimeValueDebug/Private/RVDBlueprintLibrary.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020-current Getnamo. All Rights Reserved 2 | 3 | 4 | #include "RVDBlueprintLibrary.h" 5 | #include "Engine/World.h" 6 | #include "UObject/Object.h" 7 | 8 | TSharedPtr URVDBlueprintLibrary::DebugHandler = nullptr; 9 | 10 | void FRVDTimeData::SetWithFrameTime(float InFrameTime) 11 | { 12 | Precise = FPlatformTime::Seconds(); 13 | Frame = InFrameTime; 14 | } 15 | 16 | FRVDebug::FRVDebug() 17 | { 18 | Data = MakeShareable(new FRVDebugData); 19 | Max = 10; 20 | } 21 | 22 | FRVDebug::~FRVDebug() 23 | { 24 | Data = nullptr; 25 | } 26 | 27 | 28 | void FRVDebug::SetIntValue(int32 Value, const FString& Category /*= TEXT("default")*/, float FrameTime) 29 | { 30 | FRVDIntData NewValue; 31 | NewValue.Timestamp.SetWithFrameTime(FrameTime); 32 | 33 | NewValue.Value = Value; 34 | 35 | //Create bucket if needed 36 | if (!Data->IntData.Contains(Category)) 37 | { 38 | FRVDIntHistoryData History; 39 | History.MaxIndex = Max; 40 | Data->IntData.Add(Category, History); 41 | } 42 | 43 | auto& Bucket = Data->IntData[Category]; 44 | 45 | //Add if num below max, replace if above or equal 46 | if (Bucket.Values.Num() < Bucket.MaxIndex) 47 | { 48 | Bucket.Values.Add(NewValue); 49 | Bucket.LoopIndex++; 50 | } 51 | else 52 | { 53 | if (Bucket.LoopIndex >= Bucket.MaxIndex) 54 | { 55 | Bucket.LoopIndex = 0; 56 | } 57 | Bucket.Values[Bucket.LoopIndex] = NewValue; 58 | Bucket.LoopIndex++; 59 | } 60 | } 61 | 62 | void FRVDebug::SetFloatValue(float Value, const FString& Category /*= TEXT("default")*/, float FrameTime) 63 | { 64 | FRVDFloatData NewValue; 65 | NewValue.Timestamp.SetWithFrameTime(FrameTime); 66 | 67 | NewValue.Value = Value; 68 | 69 | //Create bucket if needed 70 | if (!Data->FloatData.Contains(Category)) 71 | { 72 | FRVDFloatHistoryData History; 73 | History.MaxIndex = Max; 74 | Data->FloatData.Add(Category, History); 75 | } 76 | 77 | auto& Bucket = Data->FloatData[Category]; 78 | 79 | //Add if num below max, replace if above or equal 80 | if (Bucket.Values.Num() < Bucket.MaxIndex) 81 | { 82 | Bucket.Values.Add(NewValue); 83 | Bucket.LoopIndex++; 84 | } 85 | else 86 | { 87 | if (Bucket.LoopIndex >= Bucket.MaxIndex) 88 | { 89 | Bucket.LoopIndex = 0; 90 | } 91 | Bucket.Values[Bucket.LoopIndex] = NewValue; 92 | Bucket.LoopIndex++; 93 | } 94 | } 95 | 96 | void FRVDebug::SetStringValue(FString Value, const FString& Category /*= TEXT("default")*/, float FrameTime) 97 | { 98 | FRVDStringData NewValue; 99 | NewValue.Timestamp.SetWithFrameTime(FrameTime); 100 | 101 | NewValue.Value = Value; 102 | 103 | //Create bucket if needed 104 | if (!Data->StringData.Contains(Category)) 105 | { 106 | FRVDStringHistoryData History; 107 | History.MaxIndex = Max; 108 | Data->StringData.Add(Category, History); 109 | } 110 | 111 | auto& Bucket = Data->StringData[Category]; 112 | 113 | //Add if num below max, replace if above or equal 114 | if (Bucket.Values.Num() < Bucket.MaxIndex) 115 | { 116 | Bucket.Values.Add(NewValue); 117 | Bucket.LoopIndex++; 118 | } 119 | else 120 | { 121 | if (Bucket.LoopIndex >= Bucket.MaxIndex) 122 | { 123 | Bucket.LoopIndex = 0; 124 | } 125 | Bucket.Values[Bucket.LoopIndex] = NewValue; 126 | Bucket.LoopIndex++; 127 | } 128 | } 129 | 130 | void FRVDebug::SetVectorValue(FVector Value, const FString& Category /*= TEXT("default")*/, float FrameTime) 131 | { 132 | FRVDVectorData NewValue; 133 | NewValue.Timestamp.SetWithFrameTime(FrameTime); 134 | 135 | NewValue.Value = Value; 136 | 137 | //Create bucket if needed 138 | if (!Data->VectorData.Contains(Category)) 139 | { 140 | FRVDVectorHistoryData History; 141 | History.MaxIndex = Max; 142 | Data->VectorData.Add(Category, History); 143 | } 144 | 145 | auto& Bucket = Data->VectorData[Category]; 146 | 147 | //Add if num below max, replace if above or equal 148 | if (Bucket.Values.Num() < Bucket.MaxIndex) 149 | { 150 | Bucket.Values.Add(NewValue); 151 | Bucket.LoopIndex++; 152 | } 153 | else 154 | { 155 | if (Bucket.LoopIndex >= Bucket.MaxIndex) 156 | { 157 | Bucket.LoopIndex = 0; 158 | } 159 | Bucket.Values[Bucket.LoopIndex] = NewValue; 160 | Bucket.LoopIndex++; 161 | } 162 | } 163 | 164 | void FRVDebug::SetRotatorValue(FRotator Value, const FString& Category /*= TEXT("default")*/, float FrameTime) 165 | { 166 | FRVDRotatorData NewValue; 167 | NewValue.Timestamp.SetWithFrameTime(FrameTime); 168 | 169 | NewValue.Value = Value; 170 | 171 | //Create bucket if needed 172 | if (!Data->RotatorData.Contains(Category)) 173 | { 174 | FRVDRotatorHistoryData History; 175 | History.MaxIndex = Max; 176 | Data->RotatorData.Add(Category, History); 177 | } 178 | 179 | auto& Bucket = Data->RotatorData[Category]; 180 | 181 | //Add if num below max, replace if above or equal 182 | if (Bucket.Values.Num() < Bucket.MaxIndex) 183 | { 184 | Bucket.Values.Add(NewValue); 185 | Bucket.LoopIndex++; 186 | } 187 | else 188 | { 189 | if (Bucket.LoopIndex >= Bucket.MaxIndex) 190 | { 191 | Bucket.LoopIndex = 0; 192 | } 193 | Bucket.Values[Bucket.LoopIndex] = NewValue; 194 | Bucket.LoopIndex++; 195 | } 196 | } 197 | 198 | int32 FRVDebug::IntFromDebug(const FString& Category /*= TEXT("default")*/, int32 Index /*= 0*/) 199 | { 200 | if (!Data->IntData.Contains(Category)) 201 | { 202 | return 0; 203 | } 204 | 205 | auto& Bucket = Data->IntData[Category]; 206 | 207 | //convert index offset, check for loop back 208 | int32 DesiredIndex = Bucket.LoopIndex - 1 + Index; 209 | if (DesiredIndex < 0) 210 | { 211 | if (Bucket.Values.Num() == 0) 212 | { 213 | return 0; 214 | } 215 | while (DesiredIndex < 0) 216 | { 217 | DesiredIndex += Bucket.Values.Num(); 218 | } 219 | } 220 | return Bucket.Values[DesiredIndex].Value; 221 | } 222 | 223 | float FRVDebug::FloatFromDebug(const FString& Category /*= TEXT("default")*/, int32 Index /*= 0*/) 224 | { 225 | if (!Data->FloatData.Contains(Category)) 226 | { 227 | return 0.f; 228 | } 229 | 230 | auto& Bucket = Data->FloatData[Category]; 231 | 232 | //convert index offset, check for loop back 233 | int32 DesiredIndex = Bucket.LoopIndex - 1 + Index; 234 | if (DesiredIndex < 0) 235 | { 236 | if (Bucket.Values.Num() == 0) 237 | { 238 | return 0.f; 239 | } 240 | while (DesiredIndex < 0) 241 | { 242 | DesiredIndex += Bucket.Values.Num(); 243 | } 244 | } 245 | return Bucket.Values[DesiredIndex].Value; 246 | } 247 | 248 | FString FRVDebug::StringFromDebug(const FString& Category /*= TEXT("default")*/, int32 Index /*= 0*/) 249 | { 250 | if (!Data->StringData.Contains(Category)) 251 | { 252 | return TEXT(""); 253 | } 254 | 255 | auto& Bucket = Data->StringData[Category]; 256 | 257 | //convert index offset, check for loop back 258 | int32 DesiredIndex = Bucket.LoopIndex - 1 + Index; 259 | if (DesiredIndex < 0) 260 | { 261 | if (Bucket.Values.Num() == 0) 262 | { 263 | return TEXT(""); 264 | } 265 | while (DesiredIndex < 0) 266 | { 267 | DesiredIndex += Bucket.Values.Num(); 268 | } 269 | } 270 | return Bucket.Values[DesiredIndex].Value; 271 | } 272 | 273 | FVector FRVDebug::VectorFromDebug(const FString& Category /*= TEXT("default")*/, int32 Index /*= 0*/) 274 | { 275 | if (!Data->VectorData.Contains(Category)) 276 | { 277 | return FVector(0.f); 278 | } 279 | 280 | auto& Bucket = Data->VectorData[Category]; 281 | 282 | //convert index offset, check for loop back 283 | int32 DesiredIndex = Bucket.LoopIndex -1 + Index; 284 | if (DesiredIndex < 0) 285 | { 286 | if (Bucket.Values.Num() == 0) 287 | { 288 | return FVector(0.f); 289 | } 290 | while (DesiredIndex < 0) 291 | { 292 | DesiredIndex += Bucket.Values.Num(); 293 | } 294 | } 295 | return Bucket.Values[DesiredIndex].Value; 296 | } 297 | 298 | FRotator FRVDebug::RotatorFromDebug(const FString& Category /*= TEXT("default")*/, int32 Index /*= 0*/) 299 | { 300 | if (!Data->RotatorData.Contains(Category)) 301 | { 302 | return FRotator(0.f); 303 | } 304 | 305 | auto& Bucket = Data->RotatorData[Category]; 306 | 307 | //convert index offset, check for loop back 308 | int32 DesiredIndex = Bucket.LoopIndex - 1 + Index; 309 | if (DesiredIndex < 0) 310 | { 311 | if (Bucket.Values.Num() == 0) 312 | { 313 | return FRotator(0.f); 314 | } 315 | while (DesiredIndex < 0) 316 | { 317 | DesiredIndex += Bucket.Values.Num(); 318 | } 319 | } 320 | return Bucket.Values[DesiredIndex].Value; 321 | } 322 | 323 | void FRVDebug::SetMax(int32 NewMax /*= 100*/) 324 | { 325 | Max = NewMax; 326 | } 327 | 328 | URVDBlueprintLibrary::URVDBlueprintLibrary() 329 | { 330 | DebugHandler = MakeShareable(new FRVDebug); 331 | } 332 | 333 | void URVDBlueprintLibrary::DebugIntValue(int32 Value, const FString& Category /*= TEXT("default")*/, UObject* WorldContextObject /*= nullptr*/) 334 | { 335 | float FrameTime = 0.f; 336 | if (WorldContextObject != nullptr) 337 | { 338 | FrameTime = WorldContextObject->GetWorld()->TimeSeconds; 339 | } 340 | 341 | DebugHandler->SetIntValue(Value, Category, FrameTime); 342 | } 343 | 344 | void URVDBlueprintLibrary::DebugFloatValue(float Value, const FString& Category /*= TEXT("default")*/, UObject* WorldContextObject /*= nullptr*/) 345 | { 346 | float FrameTime = 0.f; 347 | if (WorldContextObject != nullptr) 348 | { 349 | FrameTime = WorldContextObject->GetWorld()->TimeSeconds; 350 | } 351 | 352 | DebugHandler->SetFloatValue(Value, Category, FrameTime); 353 | } 354 | 355 | void URVDBlueprintLibrary::DebugStringValue(FString Value, const FString& Category /*= TEXT("default")*/, UObject* WorldContextObject /*= nullptr*/) 356 | { 357 | float FrameTime = 0.f; 358 | if (WorldContextObject != nullptr) 359 | { 360 | FrameTime = WorldContextObject->GetWorld()->TimeSeconds; 361 | } 362 | 363 | DebugHandler->SetStringValue(Value, Category, FrameTime); 364 | } 365 | 366 | void URVDBlueprintLibrary::DebugVectorValue(FVector Value, const FString& Category /*= TEXT("default")*/, UObject* WorldContextObject /*= nullptr*/) 367 | { 368 | float FrameTime = 0.f; 369 | if (WorldContextObject != nullptr) 370 | { 371 | FrameTime = WorldContextObject->GetWorld()->TimeSeconds; 372 | } 373 | 374 | DebugHandler->SetVectorValue(Value, Category, FrameTime); 375 | } 376 | 377 | void URVDBlueprintLibrary::DebugRotatorValue(FRotator Value, const FString& Category /*= TEXT("default")*/, UObject* WorldContextObject /*= nullptr*/) 378 | { 379 | float FrameTime = 0.f; 380 | if (WorldContextObject != nullptr) 381 | { 382 | FrameTime = WorldContextObject->GetWorld()->TimeSeconds; 383 | } 384 | 385 | DebugHandler->SetRotatorValue(Value, Category, FrameTime); 386 | } 387 | 388 | void URVDBlueprintLibrary::SetRVDMaxHistory(int32 NewMax) 389 | { 390 | DebugHandler->SetMax(NewMax); 391 | } 392 | 393 | int32 URVDBlueprintLibrary::IntValueFromDebug(const FString& Category /*= TEXT("default")*/, int32 Index /*= 0*/, UObject* WorldContextObject /*= nullptr*/) 394 | { 395 | return DebugHandler->IntFromDebug(Category, Index); 396 | } 397 | 398 | float URVDBlueprintLibrary::FloatValueFromDebug(const FString& Category /*= TEXT("default")*/, int32 Index /*= 0*/, UObject* WorldContextObject /*= nullptr*/) 399 | { 400 | return DebugHandler->FloatFromDebug(Category, Index); 401 | } 402 | 403 | FString URVDBlueprintLibrary::StringValueFromDebug(const FString& Category /*= TEXT("default")*/, int32 Index /*= 0*/, UObject* WorldContextObject /*= nullptr*/) 404 | { 405 | return DebugHandler->StringFromDebug(Category, Index); 406 | } 407 | 408 | FVector URVDBlueprintLibrary::VectorValueFromDebug(const FString& Category /*= TEXT("default")*/, int32 Index /*= 0*/, UObject* WorldContextObject /*= nullptr*/) 409 | { 410 | return DebugHandler->VectorFromDebug(Category, Index); 411 | } 412 | 413 | FRotator URVDBlueprintLibrary::RotatorValueFromDebug(const FString& Category /*= TEXT("default")*/, int32 Index /*= 0*/, UObject* WorldContextObject /*= nullptr*/) 414 | { 415 | return DebugHandler->RotatorFromDebug(Category, Index); 416 | } 417 | 418 | -------------------------------------------------------------------------------- /Source/RealtimeValueDebug/Private/RVDConsumer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020-current Getnamo. All Rights Reserved 2 | 3 | 4 | #include "RVDConsumer.h" 5 | 6 | URVDConsumer::URVDConsumer() 7 | { 8 | PrimaryComponentTick.bCanEverTick = true; 9 | bListenToInt = false; 10 | bListenToFloat = false; 11 | bListenToString = false; 12 | bListenToVector = false; 13 | bListenToRotator = false; 14 | 15 | ListenIndex = 0; 16 | 17 | Category = TEXT("default"); 18 | } 19 | 20 | void URVDConsumer::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) 21 | { 22 | Super::TickComponent(DeltaTime, TickType, ThisTickFunction); 23 | 24 | if (bListenToInt) 25 | { 26 | OnIntValue.Broadcast(URVDBlueprintLibrary::IntValueFromDebug(Category, ListenIndex)); 27 | } 28 | 29 | if (bListenToFloat) 30 | { 31 | OnFloatValue.Broadcast(URVDBlueprintLibrary::FloatValueFromDebug(Category, ListenIndex)); 32 | } 33 | 34 | if (bListenToString) 35 | { 36 | OnStringValue.Broadcast(URVDBlueprintLibrary::StringValueFromDebug(Category, ListenIndex)); 37 | } 38 | 39 | if (bListenToVector) 40 | { 41 | OnVectorValue.Broadcast(URVDBlueprintLibrary::VectorValueFromDebug(Category, ListenIndex)); 42 | } 43 | 44 | if (bListenToRotator) 45 | { 46 | OnRotatorValue.Broadcast(URVDBlueprintLibrary::RotatorValueFromDebug(Category, ListenIndex)); 47 | } 48 | } 49 | 50 | 51 | void URVDConsumer::BeginPlay() 52 | { 53 | Super::BeginPlay(); 54 | } 55 | -------------------------------------------------------------------------------- /Source/RealtimeValueDebug/Private/RealtimeValueDebug.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RealtimeValueDebug.h" 4 | 5 | #define LOCTEXT_NAMESPACE "FRealtimeValueDebugModule" 6 | 7 | void FRealtimeValueDebugModule::StartupModule() 8 | { 9 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module 10 | } 11 | 12 | void FRealtimeValueDebugModule::ShutdownModule() 13 | { 14 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 15 | // we call this function before unloading the module. 16 | } 17 | 18 | #undef LOCTEXT_NAMESPACE 19 | 20 | IMPLEMENT_MODULE(FRealtimeValueDebugModule, RealtimeValueDebug) -------------------------------------------------------------------------------- /Source/RealtimeValueDebug/Public/RVDBlueprintLibrary.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020-current Getnamo. All Rights Reserved 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Kismet/BlueprintFunctionLibrary.h" 7 | #include "RVDBlueprintLibrary.generated.h" 8 | 9 | /** 10 | * NB: these definitions have code duplications, but it's intended this way to keep the system simple for now 11 | * Correct approach would be to use templating, but that's a variable success with unreal built in types. 12 | */ 13 | 14 | USTRUCT() 15 | struct FRVDTimeData 16 | { 17 | GENERATED_USTRUCT_BODY() 18 | 19 | //In seconds 20 | UPROPERTY() 21 | float Frame; 22 | 23 | //In milliseconds, used for event ordering 24 | UPROPERTY() 25 | double Precise; 26 | 27 | 28 | void SetWithFrameTime(float InFrameTime); 29 | }; 30 | 31 | //Ints 32 | USTRUCT() 33 | struct FRVDIntData 34 | { 35 | GENERATED_USTRUCT_BODY() 36 | 37 | UPROPERTY() 38 | int32 Value; 39 | 40 | UPROPERTY() 41 | FRVDTimeData Timestamp; 42 | }; 43 | 44 | USTRUCT() 45 | struct FRVDIntHistoryData 46 | { 47 | GENERATED_USTRUCT_BODY() 48 | 49 | UPROPERTY() 50 | TArray Values; 51 | 52 | UPROPERTY() 53 | int32 LoopIndex; 54 | 55 | UPROPERTY() 56 | int32 MaxIndex; 57 | 58 | FRVDIntHistoryData() { LoopIndex = 0; MaxIndex = 100; } 59 | }; 60 | 61 | //Floats 62 | USTRUCT() 63 | struct FRVDFloatData 64 | { 65 | GENERATED_USTRUCT_BODY() 66 | 67 | UPROPERTY() 68 | float Value; 69 | 70 | UPROPERTY() 71 | FRVDTimeData Timestamp; 72 | }; 73 | 74 | USTRUCT() 75 | struct FRVDFloatHistoryData 76 | { 77 | GENERATED_USTRUCT_BODY() 78 | 79 | UPROPERTY() 80 | TArray Values; 81 | 82 | UPROPERTY() 83 | int32 LoopIndex; 84 | 85 | UPROPERTY() 86 | int32 MaxIndex; 87 | 88 | FRVDFloatHistoryData() { LoopIndex = 0; MaxIndex = 100; } 89 | }; 90 | 91 | //Strings 92 | USTRUCT() 93 | struct FRVDStringData 94 | { 95 | GENERATED_USTRUCT_BODY() 96 | 97 | UPROPERTY() 98 | FString Value; 99 | 100 | UPROPERTY() 101 | FRVDTimeData Timestamp; 102 | }; 103 | 104 | USTRUCT() 105 | struct FRVDStringHistoryData 106 | { 107 | GENERATED_USTRUCT_BODY() 108 | 109 | UPROPERTY() 110 | TArray Values; 111 | 112 | UPROPERTY() 113 | int32 LoopIndex; 114 | 115 | UPROPERTY() 116 | int32 MaxIndex; 117 | 118 | FRVDStringHistoryData() { LoopIndex = 0; MaxIndex = 100; } 119 | }; 120 | 121 | //Vectors 122 | USTRUCT() 123 | struct FRVDVectorData 124 | { 125 | GENERATED_USTRUCT_BODY() 126 | 127 | UPROPERTY() 128 | FVector Value; 129 | 130 | UPROPERTY() 131 | FRVDTimeData Timestamp; 132 | }; 133 | 134 | USTRUCT() 135 | struct FRVDVectorHistoryData 136 | { 137 | GENERATED_USTRUCT_BODY() 138 | 139 | UPROPERTY() 140 | TArray Values; 141 | 142 | UPROPERTY() 143 | int32 LoopIndex; 144 | 145 | UPROPERTY() 146 | int32 MaxIndex; 147 | 148 | FRVDVectorHistoryData() { LoopIndex = 0; MaxIndex = 100; } 149 | }; 150 | 151 | //Rotators 152 | USTRUCT() 153 | struct FRVDRotatorData 154 | { 155 | GENERATED_USTRUCT_BODY() 156 | 157 | UPROPERTY() 158 | FRotator Value; 159 | 160 | UPROPERTY() 161 | FRVDTimeData Timestamp; 162 | }; 163 | 164 | USTRUCT() 165 | struct FRVDRotatorHistoryData 166 | { 167 | GENERATED_USTRUCT_BODY() 168 | 169 | UPROPERTY() 170 | TArray Values; 171 | 172 | UPROPERTY() 173 | int32 LoopIndex; 174 | 175 | UPROPERTY() 176 | int32 MaxIndex; 177 | 178 | FRVDRotatorHistoryData() { LoopIndex = 0; MaxIndex = 100; } 179 | }; 180 | 181 | 182 | USTRUCT() 183 | struct FRVDebugData 184 | { 185 | GENERATED_USTRUCT_BODY() 186 | 187 | UPROPERTY() 188 | TMap IntData; 189 | 190 | UPROPERTY() 191 | TMap FloatData; 192 | 193 | UPROPERTY() 194 | TMap StringData; 195 | 196 | UPROPERTY() 197 | TMap VectorData; 198 | 199 | UPROPERTY() 200 | TMap RotatorData; 201 | 202 | }; 203 | 204 | /** Main class used for setting and retrieving data types */ 205 | class FRVDebug 206 | { 207 | public: 208 | FRVDebug(); 209 | ~FRVDebug(); 210 | 211 | //Setting 212 | void SetIntValue(int32 Value, const FString& Category = TEXT("default"), float FrameTime = 0.f); 213 | void SetFloatValue(float Value, const FString& Category = TEXT("default"), float FrameTime = 0.f); 214 | void SetStringValue(FString Value, const FString& Category = TEXT("default"), float FrameTime = 0.f); 215 | void SetVectorValue(FVector Value, const FString& Category = TEXT("default"), float FrameTime = 0.f); 216 | void SetRotatorValue(FRotator Value, const FString& Category = TEXT("default"), float FrameTime = 0.f); 217 | 218 | //Getting 219 | int32 IntFromDebug(const FString& Category = TEXT("default"), int32 Index = 0); 220 | float FloatFromDebug(const FString& Category = TEXT("default"), int32 Index = 0); 221 | FString StringFromDebug(const FString& Category = TEXT("default"), int32 Index = 0); 222 | FVector VectorFromDebug(const FString& Category = TEXT("default"), int32 Index = 0); 223 | FRotator RotatorFromDebug(const FString& Category = TEXT("default"), int32 Index = 0); 224 | 225 | //for now applies to all data types 226 | void SetMax(int32 NewMax = 100); 227 | 228 | protected: 229 | TSharedPtr Data; 230 | int32 Max; 231 | }; 232 | 233 | /** 234 | * 235 | */ 236 | UCLASS() 237 | class REALTIMEVALUEDEBUG_API URVDBlueprintLibrary : public UBlueprintFunctionLibrary 238 | { 239 | GENERATED_BODY() 240 | public: 241 | URVDBlueprintLibrary(); 242 | 243 | //Setting 244 | 245 | UFUNCTION(BlueprintCallable, Category = "Realtime Value Debug Static", meta = (WorldContext = "WorldContextObject")) 246 | static void DebugIntValue(int32 Value, const FString& DebugCategory = TEXT("default"), UObject* WorldContextObject = nullptr); 247 | 248 | UFUNCTION(BlueprintCallable, Category = "Realtime Value Debug Static", meta = (WorldContext = "WorldContextObject")) 249 | static void DebugFloatValue(float Value, const FString& DebugCategory = TEXT("default"), UObject* WorldContextObject = nullptr); 250 | 251 | UFUNCTION(BlueprintCallable, Category = "Realtime Value Debug Static", meta = (WorldContext = "WorldContextObject")) 252 | static void DebugStringValue(FString Value, const FString& DebugCategory = TEXT("default"), UObject* WorldContextObject = nullptr); 253 | 254 | UFUNCTION(BlueprintCallable, Category = "Realtime Value Debug Static", meta = (WorldContext = "WorldContextObject")) 255 | static void DebugVectorValue(FVector Value, const FString& DebugCategory = TEXT("default"), UObject* WorldContextObject = nullptr); 256 | 257 | UFUNCTION(BlueprintCallable, Category = "Realtime Value Debug Static", meta = (WorldContext = "WorldContextObject")) 258 | static void DebugRotatorValue(FRotator Value, const FString& DebugCategory = TEXT("default"), UObject* WorldContextObject = nullptr); 259 | 260 | UFUNCTION(BlueprintCallable, Category = "Realtime Value Debug Static") 261 | static void SetRVDMaxHistory(int32 NewMax); 262 | 263 | //Getting 264 | 265 | //Index is an offset 0 = latest, -1 is the one before that etc... 266 | UFUNCTION(BlueprintCallable, Category = "Realtime Value Debug Static", meta = (WorldContext = "WorldContextObject")) 267 | static int32 IntValueFromDebug(const FString& DebugCategory = TEXT("default"), int32 Index = 0, UObject* WorldContextObject = nullptr); 268 | 269 | //Index is an offset 0 = latest, -1 is the one before that etc... 270 | UFUNCTION(BlueprintCallable, Category = "Realtime Value Debug Static", meta = (WorldContext = "WorldContextObject")) 271 | static float FloatValueFromDebug(const FString& DebugCategory = TEXT("default"), int32 Index = 0, UObject* WorldContextObject = nullptr); 272 | 273 | //Index is an offset 0 = latest, -1 is the one before that etc... 274 | UFUNCTION(BlueprintCallable, Category = "Realtime Value Debug Static", meta = (WorldContext = "WorldContextObject")) 275 | static FString StringValueFromDebug(const FString& DebugCategory = TEXT("default"), int32 Index = 0, UObject* WorldContextObject = nullptr); 276 | 277 | //Index is an offset 0 = latest, -1 is the one before that etc... 278 | UFUNCTION(BlueprintCallable, Category = "Realtime Value Debug Static", meta = (WorldContext = "WorldContextObject")) 279 | static FVector VectorValueFromDebug(const FString& DebugCategory = TEXT("default"), int32 Index = 0, UObject* WorldContextObject = nullptr); 280 | 281 | //Index is an offset 0 = latest, -1 is the one before that etc... 282 | UFUNCTION(BlueprintCallable, Category = "Realtime Value Debug Static", meta = (WorldContext = "WorldContextObject")) 283 | static FRotator RotatorValueFromDebug(const FString& DebugCategory = TEXT("default"), int32 Index = 0, UObject* WorldContextObject = nullptr); 284 | 285 | 286 | 287 | protected: 288 | static TSharedPtr DebugHandler; 289 | }; 290 | -------------------------------------------------------------------------------- /Source/RealtimeValueDebug/Public/RVDConsumer.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020-current Getnamo. All Rights Reserved 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Components/ActorComponent.h" 7 | #include "RVDBlueprintLibrary.h" 8 | #include "RVDConsumer.generated.h" 9 | 10 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRVDIntSignature, int32, Value); 11 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRVDFloatSignature, float, Value); 12 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRVDStringSignature, FString, Value); 13 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRVDVectorSignature, FVector, Value); 14 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRVDRotatorSignature, FRotator, Value); 15 | 16 | /** 17 | * Simple Listener to debug values being sent. Not optimal. Subclass to provide easy utility for debuggin the value visually. 18 | */ 19 | UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) 20 | class REALTIMEVALUEDEBUG_API URVDConsumer : public UActorComponent 21 | { 22 | GENERATED_BODY() 23 | 24 | public: 25 | UPROPERTY(BlueprintAssignable, Category = "RVD Events") 26 | FRVDIntSignature OnIntValue; 27 | 28 | UPROPERTY(BlueprintAssignable, Category = "RVD Events") 29 | FRVDFloatSignature OnFloatValue; 30 | 31 | UPROPERTY(BlueprintAssignable, Category = "RVD Events") 32 | FRVDStringSignature OnStringValue; 33 | 34 | UPROPERTY(BlueprintAssignable, Category = "RVD Events") 35 | FRVDVectorSignature OnVectorValue; 36 | 37 | UPROPERTY(BlueprintAssignable, Category = "RVD Events") 38 | FRVDRotatorSignature OnRotatorValue; 39 | 40 | //applies to all listens 41 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SocketIO Connection Properties") 42 | FString Category; 43 | 44 | //applies to all listens 45 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SocketIO Connection Properties") 46 | int32 ListenIndex; 47 | 48 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SocketIO Connection Properties") 49 | bool bListenToInt; 50 | 51 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SocketIO Connection Properties") 52 | bool bListenToFloat; 53 | 54 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SocketIO Connection Properties") 55 | bool bListenToString; 56 | 57 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SocketIO Connection Properties") 58 | bool bListenToVector; 59 | 60 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SocketIO Connection Properties") 61 | bool bListenToRotator; 62 | 63 | URVDConsumer(); 64 | virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; 65 | 66 | protected: 67 | virtual void BeginPlay() override; 68 | }; 69 | -------------------------------------------------------------------------------- /Source/RealtimeValueDebug/Public/RealtimeValueDebug.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Modules/ModuleManager.h" 7 | 8 | class FRealtimeValueDebugModule : public IModuleInterface 9 | { 10 | public: 11 | 12 | /** IModuleInterface implementation */ 13 | virtual void StartupModule() override; 14 | virtual void ShutdownModule() override; 15 | }; 16 | -------------------------------------------------------------------------------- /Source/RealtimeValueDebug/RealtimeValueDebug.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class RealtimeValueDebug : ModuleRules 6 | { 7 | public RealtimeValueDebug(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicIncludePaths.AddRange( 12 | new string[] { 13 | // ... add public include paths required here ... 14 | } 15 | ); 16 | 17 | 18 | PrivateIncludePaths.AddRange( 19 | new string[] { 20 | // ... add other private include paths required here ... 21 | } 22 | ); 23 | 24 | 25 | PublicDependencyModuleNames.AddRange( 26 | new string[] 27 | { 28 | "Core", 29 | // ... add other public dependencies that you statically link with here ... 30 | } 31 | ); 32 | 33 | 34 | PrivateDependencyModuleNames.AddRange( 35 | new string[] 36 | { 37 | "CoreUObject", 38 | "Engine", 39 | "Slate", 40 | "SlateCore", 41 | // ... add private dependencies that you statically link with here ... 42 | } 43 | ); 44 | 45 | 46 | DynamicallyLoadedModuleNames.AddRange( 47 | new string[] 48 | { 49 | // ... add any modules that your module loads dynamically here ... 50 | } 51 | ); 52 | } 53 | } 54 | --------------------------------------------------------------------------------