diff --git a/Config/DefaultGame.ini b/Config/DefaultGame.ini index b3076d07..e6748162 100644 --- a/Config/DefaultGame.ini +++ b/Config/DefaultGame.ini @@ -148,3 +148,6 @@ LOD3ColorPointHashWidth=10000.000000 ActiveColorPointHashWidth=500.000000 ActiveColorPointHashUpdateTimeSeconds=1.000000 +[/Script/LuckyWorld.LuckyWorldSettings] +GameWidgetClass=/Game/GameBP/UI/WB_GameWidget.WB_GameWidget_C + diff --git a/Content/Blueprint/Core/BP_PickAndPlaceManager.uasset b/Content/Blueprint/Core/BP_PickAndPlaceManager.uasset new file mode 100644 index 00000000..e192ef2e Binary files /dev/null and b/Content/Blueprint/Core/BP_PickAndPlaceManager.uasset differ diff --git a/Content/Blueprint/Core/BP_PickAndPlaceTarget.uasset b/Content/Blueprint/Core/BP_PickAndPlaceTarget.uasset new file mode 100644 index 00000000..023e9da0 Binary files /dev/null and b/Content/Blueprint/Core/BP_PickAndPlaceTarget.uasset differ diff --git a/Content/Blueprint/Core/BP_RobotArmPlacementVolume.uasset b/Content/Blueprint/Core/BP_RobotArmPlacementVolume.uasset new file mode 100644 index 00000000..08fc2d5c Binary files /dev/null and b/Content/Blueprint/Core/BP_RobotArmPlacementVolume.uasset differ diff --git a/Content/Blueprint/Core/BP_RobotArmRandomItemsVolume.uasset b/Content/Blueprint/Core/BP_RobotArmRandomItemsVolume.uasset new file mode 100644 index 00000000..2541a699 Binary files /dev/null and b/Content/Blueprint/Core/BP_RobotArmRandomItemsVolume.uasset differ diff --git a/Content/Blueprint/RobotPawnActors/BP_mujoco_SOArm100.uasset b/Content/Blueprint/RobotPawnActors/BP_mujoco_SOArm100.uasset new file mode 100644 index 00000000..79989b84 Binary files /dev/null and b/Content/Blueprint/RobotPawnActors/BP_mujoco_SOArm100.uasset differ diff --git a/Content/Blueprint/RobotPawnActors/BP_mujokoArm1.uasset b/Content/Blueprint/RobotPawnActors/BP_mujokoArm1.uasset deleted file mode 100644 index dfa43dc4..00000000 Binary files a/Content/Blueprint/RobotPawnActors/BP_mujokoArm1.uasset and /dev/null differ diff --git a/Content/Blueprint/robotAccessoriesSensors/BPI_interface_cameraSensor.uasset b/Content/Blueprint/robotAccessoriesSensors/BPI_interface_cameraSensor.uasset index d64c90c3..c9bd971f 100644 Binary files a/Content/Blueprint/robotAccessoriesSensors/BPI_interface_cameraSensor.uasset and b/Content/Blueprint/robotAccessoriesSensors/BPI_interface_cameraSensor.uasset differ diff --git a/Content/Developers/Bhrama/DT_LuckyStateTreeTags.uasset b/Content/Developers/Bhrama/DT_LuckyStateTreeTags.uasset new file mode 100644 index 00000000..d40fd371 Binary files /dev/null and b/Content/Developers/Bhrama/DT_LuckyStateTreeTags.uasset differ diff --git a/Content/Developers/Wdev/Robots/BP_SoArm100robot.uasset b/Content/Developers/Wdev/Robots/BP_SoArm100robot.uasset index 35b89450..78b96210 100644 Binary files a/Content/Developers/Wdev/Robots/BP_SoArm100robot.uasset and b/Content/Developers/Wdev/Robots/BP_SoArm100robot.uasset differ diff --git a/Content/GameBP/UI/WB_GameWidget.uasset b/Content/GameBP/UI/WB_GameWidget.uasset index 1737c78d..a9cf8a81 100644 Binary files a/Content/GameBP/UI/WB_GameWidget.uasset and b/Content/GameBP/UI/WB_GameWidget.uasset differ diff --git a/Content/Map/Test_Level.umap b/Content/Map/Test_Level.umap index 26896d9a..04de3d8e 100644 Binary files a/Content/Map/Test_Level.umap and b/Content/Map/Test_Level.umap differ diff --git a/Content/Maps/House02/Materials/MI_AI_vol8_01_picture_02.uasset b/Content/Maps/House02/Materials/MI_AI_vol8_01_picture_02.uasset new file mode 100644 index 00000000..97cd88eb Binary files /dev/null and b/Content/Maps/House02/Materials/MI_AI_vol8_01_picture_02.uasset differ diff --git a/Content/luckyBot/Luckywidget/ChildItems/LO_CameraSetting.uasset b/Content/luckyBot/Luckywidget/ChildItems/LO_CameraSetting.uasset new file mode 100644 index 00000000..37d8f067 Binary files /dev/null and b/Content/luckyBot/Luckywidget/ChildItems/LO_CameraSetting.uasset differ diff --git a/Content/luckyBot/Luckywidget/ChildItems/WB_CameraSetting.uasset b/Content/luckyBot/Luckywidget/ChildItems/WB_CameraSetting.uasset new file mode 100644 index 00000000..367436b7 Binary files /dev/null and b/Content/luckyBot/Luckywidget/ChildItems/WB_CameraSetting.uasset differ diff --git a/Content/luckyBot/Luckywidget/ChildItems/WB_CameraSettings.uasset b/Content/luckyBot/Luckywidget/ChildItems/WB_CameraSettings.uasset new file mode 100644 index 00000000..9d8b828f Binary files /dev/null and b/Content/luckyBot/Luckywidget/ChildItems/WB_CameraSettings.uasset differ diff --git a/Content/luckyBot/Luckywidget/ChildItems/WB_Stationary_ArmRobotMenu.uasset b/Content/luckyBot/Luckywidget/ChildItems/WB_Stationary_ArmRobotMenu.uasset new file mode 100644 index 00000000..e76065ab Binary files /dev/null and b/Content/luckyBot/Luckywidget/ChildItems/WB_Stationary_ArmRobotMenu.uasset differ diff --git a/Content/luckyBot/Luckywidget/menu/WB_CameraList.uasset b/Content/luckyBot/Luckywidget/menu/WB_CameraList.uasset new file mode 100644 index 00000000..33cad494 Binary files /dev/null and b/Content/luckyBot/Luckywidget/menu/WB_CameraList.uasset differ diff --git a/Content/luckyBot/Luckywidget/menu/WB_SelectGoalMenu_Camera.uasset b/Content/luckyBot/Luckywidget/menu/WB_SelectGoalMenu_Camera.uasset new file mode 100644 index 00000000..3e519c9d Binary files /dev/null and b/Content/luckyBot/Luckywidget/menu/WB_SelectGoalMenu_Camera.uasset differ diff --git a/LuckyWorldV2.uproject b/LuckyWorldV2.uproject index fd97d820..a2655e6a 100644 --- a/LuckyWorldV2.uproject +++ b/LuckyWorldV2.uproject @@ -1,6 +1,6 @@ { "FileVersion": 3, - "EngineAssociation": "5.5", + "EngineAssociation": "{DE82EB6D-473F-1481-4E35-93AB246AA955}", "Category": "", "Description": "", "Modules": [ @@ -68,6 +68,10 @@ "SupportedTargetPlatforms": [ "Win64" ] + }, + { + "Name": "GameplayStateTree", + "Enabled": true } ], "TargetPlatforms": [ diff --git a/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor-BlueprintJson.dll b/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor-BlueprintJson.dll index a6d313b4..ca100339 100644 Binary files a/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor-BlueprintJson.dll and b/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor-BlueprintJson.dll differ diff --git a/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor-BlueprintJson.exp b/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor-BlueprintJson.exp index f0fc26c0..50489823 100644 Binary files a/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor-BlueprintJson.exp and b/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor-BlueprintJson.exp differ diff --git a/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor-BlueprintJson.pdb b/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor-BlueprintJson.pdb index 7c3ecd7f..121768f8 100644 Binary files a/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor-BlueprintJson.pdb and b/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor-BlueprintJson.pdb differ diff --git a/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor.modules b/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor.modules index 9df34895..497b552b 100644 --- a/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor.modules +++ b/Plugins/BlueprintJson/Binaries/Win64/UnrealEditor.modules @@ -1,5 +1,5 @@ { - "BuildId": "37670630", + "BuildId": "827e4aed-aff1-4853-85bd-51def0d581c9", "Modules": { "BlueprintJson": "UnrealEditor-BlueprintJson.dll" diff --git a/Plugins/CPathfinding/Binaries/Win64/UnrealEditor-CPathfinding.dll b/Plugins/CPathfinding/Binaries/Win64/UnrealEditor-CPathfinding.dll new file mode 100644 index 00000000..56486724 Binary files /dev/null and b/Plugins/CPathfinding/Binaries/Win64/UnrealEditor-CPathfinding.dll differ diff --git a/Plugins/CPathfinding/Binaries/Win64/UnrealEditor-CPathfinding.exp b/Plugins/CPathfinding/Binaries/Win64/UnrealEditor-CPathfinding.exp new file mode 100644 index 00000000..3f59f43e Binary files /dev/null and b/Plugins/CPathfinding/Binaries/Win64/UnrealEditor-CPathfinding.exp differ diff --git a/Plugins/CPathfinding/Binaries/Win64/UnrealEditor-CPathfinding.pdb b/Plugins/CPathfinding/Binaries/Win64/UnrealEditor-CPathfinding.pdb new file mode 100644 index 00000000..fba9704d Binary files /dev/null and b/Plugins/CPathfinding/Binaries/Win64/UnrealEditor-CPathfinding.pdb differ diff --git a/Plugins/CPathfinding/Binaries/Win64/UnrealEditor.modules b/Plugins/CPathfinding/Binaries/Win64/UnrealEditor.modules new file mode 100644 index 00000000..81916837 --- /dev/null +++ b/Plugins/CPathfinding/Binaries/Win64/UnrealEditor.modules @@ -0,0 +1,7 @@ +{ + "BuildId": "827e4aed-aff1-4853-85bd-51def0d581c9", + "Modules": + { + "CPathfinding": "UnrealEditor-CPathfinding.dll" + } +} \ No newline at end of file diff --git a/Plugins/CPathfinding/CPathfinding.uplugin b/Plugins/CPathfinding/CPathfinding.uplugin new file mode 100644 index 00000000..42caedd8 --- /dev/null +++ b/Plugins/CPathfinding/CPathfinding.uplugin @@ -0,0 +1,26 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.03", + "FriendlyName": "CPathfinding", + "Description": "This plugin lets you find paths in (not only) 3D space between two points. For detailed info, please refer to the documentation.", + "Category": "AI", + "CreatedBy": "Dominik Trautman", + "CreatedByURL": "https://github.com/NonStaticGH", + "DocsURL": "https://docs.google.com/document/d/1j3NQCgR5H0Uz8qd1RfNvZPzvJEcxNIapOkz0MESesWY/edit?usp=sharing", + "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/c533ad0234c540fb81bdfa7bd55d3514", + "SupportURL": "", + "EngineVersion": "5.5.0", + "CanContainContent": true, + "Installed": true, + "Modules": [ + { + "Name": "CPathfinding", + "Type": "Runtime", + "LoadingPhase": "Default", + "PlatformAllowList": [ + "Win64" + ] + } + ] +} \ No newline at end of file diff --git a/Plugins/CPathfinding/Config/FilterPlugin.ini b/Plugins/CPathfinding/Config/FilterPlugin.ini new file mode 100644 index 00000000..ccebca2f --- /dev/null +++ b/Plugins/CPathfinding/Config/FilterPlugin.ini @@ -0,0 +1,8 @@ +[FilterPlugin] +; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and +; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. +; +; Examples: +; /README.txt +; /Extras/... +; /Binaries/ThirdParty/*.dll diff --git a/Plugins/CPathfinding/Content/Blueprints/BP_CPathVolume.uasset b/Plugins/CPathfinding/Content/Blueprints/BP_CPathVolume.uasset new file mode 100644 index 00000000..973efff1 Binary files /dev/null and b/Plugins/CPathfinding/Content/Blueprints/BP_CPathVolume.uasset differ diff --git a/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathExampleFlyingPawn.uasset b/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathExampleFlyingPawn.uasset new file mode 100644 index 00000000..e4ea3a49 Binary files /dev/null and b/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathExampleFlyingPawn.uasset differ diff --git a/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathMovingMeshComponent.uasset b/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathMovingMeshComponent.uasset new file mode 100644 index 00000000..918cab77 Binary files /dev/null and b/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathMovingMeshComponent.uasset differ diff --git a/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathPawnSpawner.uasset b/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathPawnSpawner.uasset new file mode 100644 index 00000000..61539fbd Binary files /dev/null and b/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathPawnSpawner.uasset differ diff --git a/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathVolumeGroundPrio.uasset b/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathVolumeGroundPrio.uasset new file mode 100644 index 00000000..e3111305 Binary files /dev/null and b/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathVolumeGroundPrio.uasset differ diff --git a/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathWorldLocationDummy.uasset b/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathWorldLocationDummy.uasset new file mode 100644 index 00000000..c1208d4a Binary files /dev/null and b/Plugins/CPathfinding/Content/Blueprints/ExampleLevelsBlueprints/BP_CPathWorldLocationDummy.uasset differ diff --git a/Plugins/CPathfinding/Content/Maps/CPathExample_2DSideScroller.umap b/Plugins/CPathfinding/Content/Maps/CPathExample_2DSideScroller.umap new file mode 100644 index 00000000..d2388b11 Binary files /dev/null and b/Plugins/CPathfinding/Content/Maps/CPathExample_2DSideScroller.umap differ diff --git a/Plugins/CPathfinding/Content/Maps/CPathExample_Dynamic.umap b/Plugins/CPathfinding/Content/Maps/CPathExample_Dynamic.umap new file mode 100644 index 00000000..d81cddf4 Binary files /dev/null and b/Plugins/CPathfinding/Content/Maps/CPathExample_Dynamic.umap differ diff --git a/Plugins/CPathfinding/Content/Maps/CPathExample_DynamicLabirynthLimitTest.umap b/Plugins/CPathfinding/Content/Maps/CPathExample_DynamicLabirynthLimitTest.umap new file mode 100644 index 00000000..3fa33a97 Binary files /dev/null and b/Plugins/CPathfinding/Content/Maps/CPathExample_DynamicLabirynthLimitTest.umap differ diff --git a/Plugins/CPathfinding/Content/Materials/MF_ProcGrid.uasset b/Plugins/CPathfinding/Content/Materials/MF_ProcGrid.uasset new file mode 100644 index 00000000..6d5274aa Binary files /dev/null and b/Plugins/CPathfinding/Content/Materials/MF_ProcGrid.uasset differ diff --git a/Plugins/CPathfinding/Content/Materials/MI_CPathDynamicNoPhysics.uasset b/Plugins/CPathfinding/Content/Materials/MI_CPathDynamicNoPhysics.uasset new file mode 100644 index 00000000..179303b1 Binary files /dev/null and b/Plugins/CPathfinding/Content/Materials/MI_CPathDynamicNoPhysics.uasset differ diff --git a/Plugins/CPathfinding/Content/Materials/MI_CPathDynamicWithPhysics.uasset b/Plugins/CPathfinding/Content/Materials/MI_CPathDynamicWithPhysics.uasset new file mode 100644 index 00000000..01ba698d Binary files /dev/null and b/Plugins/CPathfinding/Content/Materials/MI_CPathDynamicWithPhysics.uasset differ diff --git a/Plugins/CPathfinding/Content/Materials/MI_CPathPawn.uasset b/Plugins/CPathfinding/Content/Materials/MI_CPathPawn.uasset new file mode 100644 index 00000000..34dccd6b Binary files /dev/null and b/Plugins/CPathfinding/Content/Materials/MI_CPathPawn.uasset differ diff --git a/Plugins/CPathfinding/Content/Materials/MI_CPathSpawner.uasset b/Plugins/CPathfinding/Content/Materials/MI_CPathSpawner.uasset new file mode 100644 index 00000000..e942f081 Binary files /dev/null and b/Plugins/CPathfinding/Content/Materials/MI_CPathSpawner.uasset differ diff --git a/Plugins/CPathfinding/Content/Materials/MI_CPathWorldLocationDummy.uasset b/Plugins/CPathfinding/Content/Materials/MI_CPathWorldLocationDummy.uasset new file mode 100644 index 00000000..f7751ba0 Binary files /dev/null and b/Plugins/CPathfinding/Content/Materials/MI_CPathWorldLocationDummy.uasset differ diff --git a/Plugins/CPathfinding/Content/Materials/MI_PrototypeGrid_Gray.uasset b/Plugins/CPathfinding/Content/Materials/MI_PrototypeGrid_Gray.uasset new file mode 100644 index 00000000..76ef0b8f Binary files /dev/null and b/Plugins/CPathfinding/Content/Materials/MI_PrototypeGrid_Gray.uasset differ diff --git a/Plugins/CPathfinding/Content/Materials/MI_PrototypeGrid_Gray_02.uasset b/Plugins/CPathfinding/Content/Materials/MI_PrototypeGrid_Gray_02.uasset new file mode 100644 index 00000000..72d0a585 Binary files /dev/null and b/Plugins/CPathfinding/Content/Materials/MI_PrototypeGrid_Gray_02.uasset differ diff --git a/Plugins/CPathfinding/Content/Materials/MI_PrototypeGrid_TopDark.uasset b/Plugins/CPathfinding/Content/Materials/MI_PrototypeGrid_TopDark.uasset new file mode 100644 index 00000000..01dcb54f Binary files /dev/null and b/Plugins/CPathfinding/Content/Materials/MI_PrototypeGrid_TopDark.uasset differ diff --git a/Plugins/CPathfinding/Content/Materials/M_CPathSolid.uasset b/Plugins/CPathfinding/Content/Materials/M_CPathSolid.uasset new file mode 100644 index 00000000..66b9f5cc Binary files /dev/null and b/Plugins/CPathfinding/Content/Materials/M_CPathSolid.uasset differ diff --git a/Plugins/CPathfinding/Content/Materials/M_CPathTransparent.uasset b/Plugins/CPathfinding/Content/Materials/M_CPathTransparent.uasset new file mode 100644 index 00000000..a1a42482 Binary files /dev/null and b/Plugins/CPathfinding/Content/Materials/M_CPathTransparent.uasset differ diff --git a/Plugins/CPathfinding/Content/Materials/M_PrototypeGrid.uasset b/Plugins/CPathfinding/Content/Materials/M_PrototypeGrid.uasset new file mode 100644 index 00000000..21badc21 Binary files /dev/null and b/Plugins/CPathfinding/Content/Materials/M_PrototypeGrid.uasset differ diff --git a/Plugins/CPathfinding/Content/Meshes/SM_ChamferCube.uasset b/Plugins/CPathfinding/Content/Meshes/SM_ChamferCube.uasset new file mode 100644 index 00000000..5a1d6e8a Binary files /dev/null and b/Plugins/CPathfinding/Content/Meshes/SM_ChamferCube.uasset differ diff --git a/Plugins/CPathfinding/Content/Meshes/SM_Cube.uasset b/Plugins/CPathfinding/Content/Meshes/SM_Cube.uasset new file mode 100644 index 00000000..ae97027d Binary files /dev/null and b/Plugins/CPathfinding/Content/Meshes/SM_Cube.uasset differ diff --git a/Plugins/CPathfinding/Content/Textures/T_GridChecker_A.uasset b/Plugins/CPathfinding/Content/Textures/T_GridChecker_A.uasset new file mode 100644 index 00000000..6697e5d9 Binary files /dev/null and b/Plugins/CPathfinding/Content/Textures/T_GridChecker_A.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/0/2X/439APO07E3OS2ONQ332OA0.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/0/2X/439APO07E3OS2ONQ332OA0.uasset new file mode 100644 index 00000000..82d908a6 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/0/2X/439APO07E3OS2ONQ332OA0.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/1/0W/V4Z4S30BTL1ET6OGDFFP7I.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/1/0W/V4Z4S30BTL1ET6OGDFFP7I.uasset new file mode 100644 index 00000000..755de580 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/1/0W/V4Z4S30BTL1ET6OGDFFP7I.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/1/11/EZDLGTLBCELFS4ONL3F9SM.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/1/11/EZDLGTLBCELFS4ONL3F9SM.uasset new file mode 100644 index 00000000..2670d875 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/1/11/EZDLGTLBCELFS4ONL3F9SM.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/1/6V/SFSYZKLDPU1E41XAD4FYKO.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/1/6V/SFSYZKLDPU1E41XAD4FYKO.uasset new file mode 100644 index 00000000..84f838b1 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/1/6V/SFSYZKLDPU1E41XAD4FYKO.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/1/SX/QBWPLR4YLZSJSFL9XBPL3X.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/1/SX/QBWPLR4YLZSJSFL9XBPL3X.uasset new file mode 100644 index 00000000..69e9fc35 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/1/SX/QBWPLR4YLZSJSFL9XBPL3X.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/2/1W/XV3X2HC14G06PFSANH80MI.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/2/1W/XV3X2HC14G06PFSANH80MI.uasset new file mode 100644 index 00000000..87eb6dc6 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/2/1W/XV3X2HC14G06PFSANH80MI.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/2/V1/JNSLHI8ZUPM3V73QPVEESS.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/2/V1/JNSLHI8ZUPM3V73QPVEESS.uasset new file mode 100644 index 00000000..2d013712 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/2/V1/JNSLHI8ZUPM3V73QPVEESS.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/2/WR/MBWUHREZ0H18BE8PE4A4PR.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/2/WR/MBWUHREZ0H18BE8PE4A4PR.uasset new file mode 100644 index 00000000..ed46f4e0 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/2/WR/MBWUHREZ0H18BE8PE4A4PR.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/3/KF/F9IR4FU5AEM7RU2IKUYD94.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/3/KF/F9IR4FU5AEM7RU2IKUYD94.uasset new file mode 100644 index 00000000..6c3b1a0d Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/3/KF/F9IR4FU5AEM7RU2IKUYD94.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/3/OT/ID3PH8U4C5TFTP0V7QVGF5.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/3/OT/ID3PH8U4C5TFTP0V7QVGF5.uasset new file mode 100644 index 00000000..5ed03487 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/3/OT/ID3PH8U4C5TFTP0V7QVGF5.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/3/QS/LNT527CP8LW3PY1Q5LTBOW.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/3/QS/LNT527CP8LW3PY1Q5LTBOW.uasset new file mode 100644 index 00000000..e818e70b Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/3/QS/LNT527CP8LW3PY1Q5LTBOW.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/3/VI/B56F7OW2EHW02W427J66ED.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/3/VI/B56F7OW2EHW02W427J66ED.uasset new file mode 100644 index 00000000..ed44fec4 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/3/VI/B56F7OW2EHW02W427J66ED.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/4/1H/IIGXJL2Y2Y04AXTLDWDYVZ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/4/1H/IIGXJL2Y2Y04AXTLDWDYVZ.uasset new file mode 100644 index 00000000..24be4384 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/4/1H/IIGXJL2Y2Y04AXTLDWDYVZ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/4/FX/ACEWBWF4HQWLR97888YKYD.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/4/FX/ACEWBWF4HQWLR97888YKYD.uasset new file mode 100644 index 00000000..ded62066 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/4/FX/ACEWBWF4HQWLR97888YKYD.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/4/QK/J26ILU9U316XRV1U3HWAOG.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/4/QK/J26ILU9U316XRV1U3HWAOG.uasset new file mode 100644 index 00000000..ba2e7f58 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/4/QK/J26ILU9U316XRV1U3HWAOG.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/5/LL/JJHLNV8XL14HPZBU4ZFIP4.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/5/LL/JJHLNV8XL14HPZBU4ZFIP4.uasset new file mode 100644 index 00000000..3b648a53 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/5/LL/JJHLNV8XL14HPZBU4ZFIP4.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/5/OL/3CY7VE93JZ73OYBZK7UJQ1.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/5/OL/3CY7VE93JZ73OYBZK7UJQ1.uasset new file mode 100644 index 00000000..447ab492 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/5/OL/3CY7VE93JZ73OYBZK7UJQ1.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/5/TB/25RE4QJZQTXUBC8B68NZ4D.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/5/TB/25RE4QJZQTXUBC8B68NZ4D.uasset new file mode 100644 index 00000000..600b3790 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/5/TB/25RE4QJZQTXUBC8B68NZ4D.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/5/VB/LHQ434T5G2NTGPHFK9A2AE.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/5/VB/LHQ434T5G2NTGPHFK9A2AE.uasset new file mode 100644 index 00000000..bdd1cd85 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/5/VB/LHQ434T5G2NTGPHFK9A2AE.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/6/E4/P2M2XC7ERYHE6PRQV00ZSE.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/6/E4/P2M2XC7ERYHE6PRQV00ZSE.uasset new file mode 100644 index 00000000..a73b7ee0 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/6/E4/P2M2XC7ERYHE6PRQV00ZSE.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/6/QL/07728LGURX7KG9QRIOY11B.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/6/QL/07728LGURX7KG9QRIOY11B.uasset new file mode 100644 index 00000000..e2dfe9f3 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/6/QL/07728LGURX7KG9QRIOY11B.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/7/NF/2EJSTLJ6L5UJPIZ94TCRPX.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/7/NF/2EJSTLJ6L5UJPIZ94TCRPX.uasset new file mode 100644 index 00000000..46fba190 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/7/NF/2EJSTLJ6L5UJPIZ94TCRPX.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/7/P2/5GWY22UPV6NZIZK6T0DGC8.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/7/P2/5GWY22UPV6NZIZK6T0DGC8.uasset new file mode 100644 index 00000000..b036be19 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/7/P2/5GWY22UPV6NZIZK6T0DGC8.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/8/9T/YBQ57GLCSWD5T8GJZ84IKO.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/8/9T/YBQ57GLCSWD5T8GJZ84IKO.uasset new file mode 100644 index 00000000..430e22dc Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/8/9T/YBQ57GLCSWD5T8GJZ84IKO.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/8/D3/29RUX287JFFLR4G0YKS3EL.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/8/D3/29RUX287JFFLR4G0YKS3EL.uasset new file mode 100644 index 00000000..37228e63 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/8/D3/29RUX287JFFLR4G0YKS3EL.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/8/KA/65P403YGUUW9KIHV6JMZCJ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/8/KA/65P403YGUUW9KIHV6JMZCJ.uasset new file mode 100644 index 00000000..3a0cd0bf Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/8/KA/65P403YGUUW9KIHV6JMZCJ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/8/QG/CVH6WV4G9300J6UCFAO4KP.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/8/QG/CVH6WV4G9300J6UCFAO4KP.uasset new file mode 100644 index 00000000..17571116 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/8/QG/CVH6WV4G9300J6UCFAO4KP.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/9/9J/E7C5CZOI53F0KT7IJ9KE5Y.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/9/9J/E7C5CZOI53F0KT7IJ9KE5Y.uasset new file mode 100644 index 00000000..cd5840e7 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/9/9J/E7C5CZOI53F0KT7IJ9KE5Y.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/9/9W/DJXZPIGKGJTQE2D7J0L0JG.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/9/9W/DJXZPIGKGJTQE2D7J0L0JG.uasset new file mode 100644 index 00000000..d706da7f Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/9/9W/DJXZPIGKGJTQE2D7J0L0JG.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/9/FV/874BC7QRWELGS7JSP6ORV6.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/9/FV/874BC7QRWELGS7JSP6ORV6.uasset new file mode 100644 index 00000000..c465c794 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/9/FV/874BC7QRWELGS7JSP6ORV6.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/9/T5/FJS7W2F67EUIA11XOCV9AJ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/9/T5/FJS7W2F67EUIA11XOCV9AJ.uasset new file mode 100644 index 00000000..62dc5f20 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/9/T5/FJS7W2F67EUIA11XOCV9AJ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/A/CO/8X07SSHLJUPQHFSJ1MRXAG.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/A/CO/8X07SSHLJUPQHFSJ1MRXAG.uasset new file mode 100644 index 00000000..6e45631c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/A/CO/8X07SSHLJUPQHFSJ1MRXAG.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/A/DX/C7OHOI8JBSDOZ7FSKITNE4.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/A/DX/C7OHOI8JBSDOZ7FSKITNE4.uasset new file mode 100644 index 00000000..13e4e0f9 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/A/DX/C7OHOI8JBSDOZ7FSKITNE4.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/A/NS/666N5I7MCI2SEAI89MXTW5.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/A/NS/666N5I7MCI2SEAI89MXTW5.uasset new file mode 100644 index 00000000..8a5d73b4 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/A/NS/666N5I7MCI2SEAI89MXTW5.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/A/PB/3MWBWYLGDVXSWL6LQRGV2T.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/A/PB/3MWBWYLGDVXSWL6LQRGV2T.uasset new file mode 100644 index 00000000..c73e5971 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/A/PB/3MWBWYLGDVXSWL6LQRGV2T.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/B/3Z/24J2DFMBFIPTLZFUYDGNQU.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/B/3Z/24J2DFMBFIPTLZFUYDGNQU.uasset new file mode 100644 index 00000000..5a82cda4 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/B/3Z/24J2DFMBFIPTLZFUYDGNQU.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/B/A6/9GYZ6UV9NNP7V0QTIQKJYM.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/B/A6/9GYZ6UV9NNP7V0QTIQKJYM.uasset new file mode 100644 index 00000000..b6fdf553 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/B/A6/9GYZ6UV9NNP7V0QTIQKJYM.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/B/DT/O8U193OX2BB5UAEMIKMQX9.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/B/DT/O8U193OX2BB5UAEMIKMQX9.uasset new file mode 100644 index 00000000..c4063f17 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/B/DT/O8U193OX2BB5UAEMIKMQX9.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/B/PF/MK367UHADC6VSEO4NZ1XPZ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/B/PF/MK367UHADC6VSEO4NZ1XPZ.uasset new file mode 100644 index 00000000..72630835 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/B/PF/MK367UHADC6VSEO4NZ1XPZ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/C/L5/TIIOLI8A3S38SY6Q3W9IU9.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/C/L5/TIIOLI8A3S38SY6Q3W9IU9.uasset new file mode 100644 index 00000000..d58331ae Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/C/L5/TIIOLI8A3S38SY6Q3W9IU9.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/D/42/XOQ1IALLGCW2R3A57DY9X9.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/D/42/XOQ1IALLGCW2R3A57DY9X9.uasset new file mode 100644 index 00000000..4417d865 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/D/42/XOQ1IALLGCW2R3A57DY9X9.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/D/AP/WXG41HP2ZO3JKXJ3W9K6EC.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/D/AP/WXG41HP2ZO3JKXJ3W9K6EC.uasset new file mode 100644 index 00000000..eb16e5b6 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/D/AP/WXG41HP2ZO3JKXJ3W9K6EC.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/D/IK/Q2S2MA4EBL5FS0H6S6FTGS.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/D/IK/Q2S2MA4EBL5FS0H6S6FTGS.uasset new file mode 100644 index 00000000..918c4b73 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/D/IK/Q2S2MA4EBL5FS0H6S6FTGS.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/6I/QEGE29W6W1XULW5YGP4WJX.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/6I/QEGE29W6W1XULW5YGP4WJX.uasset new file mode 100644 index 00000000..5718dc95 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/6I/QEGE29W6W1XULW5YGP4WJX.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/CS/A1NUDOTHAR24IPIJPZROO5.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/CS/A1NUDOTHAR24IPIJPZROO5.uasset new file mode 100644 index 00000000..f345dc0f Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/CS/A1NUDOTHAR24IPIJPZROO5.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/FI/EOO1642WTB6HXYXPPAG851.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/FI/EOO1642WTB6HXYXPPAG851.uasset new file mode 100644 index 00000000..ee736b24 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/FI/EOO1642WTB6HXYXPPAG851.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/HJ/Y9T5HWS8770R25YJMM1JN0.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/HJ/Y9T5HWS8770R25YJMM1JN0.uasset new file mode 100644 index 00000000..c6253767 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/HJ/Y9T5HWS8770R25YJMM1JN0.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/MR/R2T7HO6IUYCN7A33RU7G8Z.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/MR/R2T7HO6IUYCN7A33RU7G8Z.uasset new file mode 100644 index 00000000..382c99c2 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/MR/R2T7HO6IUYCN7A33RU7G8Z.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/NF/28ZKDNZ3BIUFND2UZZP9ET.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/NF/28ZKDNZ3BIUFND2UZZP9ET.uasset new file mode 100644 index 00000000..e4db2f4d Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/NF/28ZKDNZ3BIUFND2UZZP9ET.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/O4/JYCOIGB4Y2SVTIWUZTBSLF.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/O4/JYCOIGB4Y2SVTIWUZTBSLF.uasset new file mode 100644 index 00000000..59433330 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_2DSideScroller/E/O4/JYCOIGB4Y2SVTIWUZTBSLF.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/0/51/I4I34H19FAVTOI3IRBFKSK.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/0/51/I4I34H19FAVTOI3IRBFKSK.uasset new file mode 100644 index 00000000..a368b079 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/0/51/I4I34H19FAVTOI3IRBFKSK.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/0/71/UXZH1O3D0DQEMO1JHIC4AE.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/0/71/UXZH1O3D0DQEMO1JHIC4AE.uasset new file mode 100644 index 00000000..7e10db53 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/0/71/UXZH1O3D0DQEMO1JHIC4AE.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/0/BN/XC5EWBCY24QDO07YQA58SL.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/0/BN/XC5EWBCY24QDO07YQA58SL.uasset new file mode 100644 index 00000000..7722c4d0 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/0/BN/XC5EWBCY24QDO07YQA58SL.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/0/KU/GPDHT8SZLHANWH0EFH7K4K.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/0/KU/GPDHT8SZLHANWH0EFH7K4K.uasset new file mode 100644 index 00000000..f6f9da8d Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/0/KU/GPDHT8SZLHANWH0EFH7K4K.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/1/7Q/51FVPMX8EHJ82DRFIVUPXN.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/1/7Q/51FVPMX8EHJ82DRFIVUPXN.uasset new file mode 100644 index 00000000..bc095901 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/1/7Q/51FVPMX8EHJ82DRFIVUPXN.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/1/HF/CPXT5AT0M041OZ31PJ430F.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/1/HF/CPXT5AT0M041OZ31PJ430F.uasset new file mode 100644 index 00000000..14f09ac7 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/1/HF/CPXT5AT0M041OZ31PJ430F.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/1/IL/B65NQ9C7OQ99GXBFFP6VRU.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/1/IL/B65NQ9C7OQ99GXBFFP6VRU.uasset new file mode 100644 index 00000000..e746e786 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/1/IL/B65NQ9C7OQ99GXBFFP6VRU.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/1/Z2/E10SJCTKBOQSNF8VG9DYWG.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/1/Z2/E10SJCTKBOQSNF8VG9DYWG.uasset new file mode 100644 index 00000000..624e4d9f Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/1/Z2/E10SJCTKBOQSNF8VG9DYWG.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/2/6Q/W0XH5MWSHRGBAUQ338CE5G.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/2/6Q/W0XH5MWSHRGBAUQ338CE5G.uasset new file mode 100644 index 00000000..32e0e47c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/2/6Q/W0XH5MWSHRGBAUQ338CE5G.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/2/YV/2UDJLZAZJQVMG6YOZ62BOM.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/2/YV/2UDJLZAZJQVMG6YOZ62BOM.uasset new file mode 100644 index 00000000..7c1f75ea Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/2/YV/2UDJLZAZJQVMG6YOZ62BOM.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/BH/9XLBO2XX2PIQAR427N02OV.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/BH/9XLBO2XX2PIQAR427N02OV.uasset new file mode 100644 index 00000000..a6e9b8ed Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/BH/9XLBO2XX2PIQAR427N02OV.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/IL/NVCLD6DZADZOSSKIPNTFN8.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/IL/NVCLD6DZADZOSSKIPNTFN8.uasset new file mode 100644 index 00000000..cc4282ea Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/IL/NVCLD6DZADZOSSKIPNTFN8.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/LR/RWNC41FV08C323Y24CBUHZ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/LR/RWNC41FV08C323Y24CBUHZ.uasset new file mode 100644 index 00000000..471f9ccd Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/LR/RWNC41FV08C323Y24CBUHZ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/PS/H5J90KRTHYHKNK198ZYYWW.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/PS/H5J90KRTHYHKNK198ZYYWW.uasset new file mode 100644 index 00000000..acb44a3f Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/PS/H5J90KRTHYHKNK198ZYYWW.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/V8/QGM650VAH4LFRN64J2SJFA.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/V8/QGM650VAH4LFRN64J2SJFA.uasset new file mode 100644 index 00000000..eac8ed86 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/V8/QGM650VAH4LFRN64J2SJFA.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/XE/28BPYVK7GF2GNGA6MSG6IH.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/XE/28BPYVK7GF2GNGA6MSG6IH.uasset new file mode 100644 index 00000000..06199d34 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/3/XE/28BPYVK7GF2GNGA6MSG6IH.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/4/8T/QV20GK6ERP9EFT7SPJ5BHX.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/4/8T/QV20GK6ERP9EFT7SPJ5BHX.uasset new file mode 100644 index 00000000..e3e17c45 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/4/8T/QV20GK6ERP9EFT7SPJ5BHX.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/4/I0/6IZB7KZ5QVM2SII8J6J8R5.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/4/I0/6IZB7KZ5QVM2SII8J6J8R5.uasset new file mode 100644 index 00000000..61788f08 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/4/I0/6IZB7KZ5QVM2SII8J6J8R5.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/4/M4/VO7B0VY8DZZ3WXPI4I6D1K.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/4/M4/VO7B0VY8DZZ3WXPI4I6D1K.uasset new file mode 100644 index 00000000..3aca48d5 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/4/M4/VO7B0VY8DZZ3WXPI4I6D1K.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/0S/TTURPGL2II6OD41U9LSOI2.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/0S/TTURPGL2II6OD41U9LSOI2.uasset new file mode 100644 index 00000000..e65a79e1 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/0S/TTURPGL2II6OD41U9LSOI2.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/66/95FJRMX0KXVUHY056MBZ1N.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/66/95FJRMX0KXVUHY056MBZ1N.uasset new file mode 100644 index 00000000..1c0a9e1f Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/66/95FJRMX0KXVUHY056MBZ1N.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/E9/TAW1OS6QJFQ3YMHIVL9WKA.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/E9/TAW1OS6QJFQ3YMHIVL9WKA.uasset new file mode 100644 index 00000000..23bad963 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/E9/TAW1OS6QJFQ3YMHIVL9WKA.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/LU/IR498FXWTWH3GKBN8JZWR5.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/LU/IR498FXWTWH3GKBN8JZWR5.uasset new file mode 100644 index 00000000..dbc596be Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/LU/IR498FXWTWH3GKBN8JZWR5.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/PF/ATI6HXCONQITMRRU8A9DX4.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/PF/ATI6HXCONQITMRRU8A9DX4.uasset new file mode 100644 index 00000000..d5dad5d3 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/PF/ATI6HXCONQITMRRU8A9DX4.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/U9/8ZSVM8FHTTVHBGGHXJHEP9.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/U9/8ZSVM8FHTTVHBGGHXJHEP9.uasset new file mode 100644 index 00000000..64b8c873 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/5/U9/8ZSVM8FHTTVHBGGHXJHEP9.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/6/OR/ULPFK8GBC9CMBUHIA4AU05.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/6/OR/ULPFK8GBC9CMBUHIA4AU05.uasset new file mode 100644 index 00000000..63130232 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/6/OR/ULPFK8GBC9CMBUHIA4AU05.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/6/W7/ZYTFT3UUBEIAK9E8FSBG8P.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/6/W7/ZYTFT3UUBEIAK9E8FSBG8P.uasset new file mode 100644 index 00000000..61842d74 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/6/W7/ZYTFT3UUBEIAK9E8FSBG8P.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/41/Y4UHLH1688IDKSKT6WQF9Q.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/41/Y4UHLH1688IDKSKT6WQF9Q.uasset new file mode 100644 index 00000000..6687331d Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/41/Y4UHLH1688IDKSKT6WQF9Q.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/6Y/I2EL9FZ89AB9JNYHKTZ9BH.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/6Y/I2EL9FZ89AB9JNYHKTZ9BH.uasset new file mode 100644 index 00000000..c66e5d79 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/6Y/I2EL9FZ89AB9JNYHKTZ9BH.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/AQ/V1HS9WX9399UEDA33YF8BN.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/AQ/V1HS9WX9399UEDA33YF8BN.uasset new file mode 100644 index 00000000..f2a19ff2 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/AQ/V1HS9WX9399UEDA33YF8BN.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/F2/JBXPA02DHTG4TQUOT1AFAD.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/F2/JBXPA02DHTG4TQUOT1AFAD.uasset new file mode 100644 index 00000000..f7c52840 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/F2/JBXPA02DHTG4TQUOT1AFAD.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/N6/H81967OGPTS7GCNW8Q325K.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/N6/H81967OGPTS7GCNW8Q325K.uasset new file mode 100644 index 00000000..224746fe Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/N6/H81967OGPTS7GCNW8Q325K.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/QS/T39415BMUCZXR53DM40A42.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/QS/T39415BMUCZXR53DM40A42.uasset new file mode 100644 index 00000000..01f0d0f6 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/QS/T39415BMUCZXR53DM40A42.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/R1/PKSN18K8TQY9CLQ4BGFRH4.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/R1/PKSN18K8TQY9CLQ4BGFRH4.uasset new file mode 100644 index 00000000..77ac04d6 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/R1/PKSN18K8TQY9CLQ4BGFRH4.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/ZB/WHHMPJXU9UI5PB362M9M3S.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/ZB/WHHMPJXU9UI5PB362M9M3S.uasset new file mode 100644 index 00000000..68fe7cb0 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/7/ZB/WHHMPJXU9UI5PB362M9M3S.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/46/A8QF7TMFB5ZEXL5RNZ93EL.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/46/A8QF7TMFB5ZEXL5RNZ93EL.uasset new file mode 100644 index 00000000..16601248 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/46/A8QF7TMFB5ZEXL5RNZ93EL.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/CS/WFFK90GAFHVMDHLV4FF7VW.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/CS/WFFK90GAFHVMDHLV4FF7VW.uasset new file mode 100644 index 00000000..565f8fda Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/CS/WFFK90GAFHVMDHLV4FF7VW.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/DV/UOT50S6XBV66MFY89O35C6.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/DV/UOT50S6XBV66MFY89O35C6.uasset new file mode 100644 index 00000000..f1d0046c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/DV/UOT50S6XBV66MFY89O35C6.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/HP/9OKU6AI1JZ8NCLPJK8DL8M.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/HP/9OKU6AI1JZ8NCLPJK8DL8M.uasset new file mode 100644 index 00000000..0731aaa1 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/HP/9OKU6AI1JZ8NCLPJK8DL8M.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/LM/N5UR4WF9IRT7TPY5T5BDTP.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/LM/N5UR4WF9IRT7TPY5T5BDTP.uasset new file mode 100644 index 00000000..65fb07c0 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/LM/N5UR4WF9IRT7TPY5T5BDTP.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/T4/PIT378TMO0PKYC5IRVUR1L.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/T4/PIT378TMO0PKYC5IRVUR1L.uasset new file mode 100644 index 00000000..a18eb045 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/8/T4/PIT378TMO0PKYC5IRVUR1L.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/9/6O/9BAUCR3D68V8YDPAEKW3K5.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/9/6O/9BAUCR3D68V8YDPAEKW3K5.uasset new file mode 100644 index 00000000..5d1adf47 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/9/6O/9BAUCR3D68V8YDPAEKW3K5.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/9/AZ/7IW8FE9C06SXAL5F9V4QIY.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/9/AZ/7IW8FE9C06SXAL5F9V4QIY.uasset new file mode 100644 index 00000000..6e4fa526 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/9/AZ/7IW8FE9C06SXAL5F9V4QIY.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/9/Y2/5U103QCK4XBI46V96P8GSG.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/9/Y2/5U103QCK4XBI46V96P8GSG.uasset new file mode 100644 index 00000000..a278c0f2 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/9/Y2/5U103QCK4XBI46V96P8GSG.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/A/3E/4QBIVCS7MI4DI3GDDDKO26.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/A/3E/4QBIVCS7MI4DI3GDDDKO26.uasset new file mode 100644 index 00000000..b94d51e8 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/A/3E/4QBIVCS7MI4DI3GDDDKO26.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/A/EB/N2NJ97EYZRBPO78ASEY0B6.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/A/EB/N2NJ97EYZRBPO78ASEY0B6.uasset new file mode 100644 index 00000000..232df674 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/A/EB/N2NJ97EYZRBPO78ASEY0B6.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/A/K8/GEUE5MLPMH82APGHD205JP.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/A/K8/GEUE5MLPMH82APGHD205JP.uasset new file mode 100644 index 00000000..b22f5dd5 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/A/K8/GEUE5MLPMH82APGHD205JP.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/A/V9/JWUHX23Q4V1F77TFK5V7FB.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/A/V9/JWUHX23Q4V1F77TFK5V7FB.uasset new file mode 100644 index 00000000..4671313c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/A/V9/JWUHX23Q4V1F77TFK5V7FB.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/B/3Q/DFZOJP7I2KKVF7KRNLGC8Y.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/B/3Q/DFZOJP7I2KKVF7KRNLGC8Y.uasset new file mode 100644 index 00000000..64f2b345 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/B/3Q/DFZOJP7I2KKVF7KRNLGC8Y.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/B/RL/EPNLJER38APVSFUR0WECTL.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/B/RL/EPNLJER38APVSFUR0WECTL.uasset new file mode 100644 index 00000000..c704f626 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/B/RL/EPNLJER38APVSFUR0WECTL.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/B/ZZ/FTI40VVLN0TN688IZ0GJVV.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/B/ZZ/FTI40VVLN0TN688IZ0GJVV.uasset new file mode 100644 index 00000000..af97a876 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/B/ZZ/FTI40VVLN0TN688IZ0GJVV.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/4L/1S9NRZCSSZ1AY2B59KNGXA.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/4L/1S9NRZCSSZ1AY2B59KNGXA.uasset new file mode 100644 index 00000000..78858bcf Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/4L/1S9NRZCSSZ1AY2B59KNGXA.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/79/VCXQKX6SREWY9VYW8CCZY9.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/79/VCXQKX6SREWY9VYW8CCZY9.uasset new file mode 100644 index 00000000..10b4986d Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/79/VCXQKX6SREWY9VYW8CCZY9.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/7W/PA2D42CCYZZ336DWXV2Q1I.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/7W/PA2D42CCYZZ336DWXV2Q1I.uasset new file mode 100644 index 00000000..5f6f1f20 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/7W/PA2D42CCYZZ336DWXV2Q1I.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/7Z/PMHO89SZ18YFZP7N79X9S2.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/7Z/PMHO89SZ18YFZP7N79X9S2.uasset new file mode 100644 index 00000000..940c3747 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/7Z/PMHO89SZ18YFZP7N79X9S2.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/AM/RBSCOL19B5CMW644TVJTR4.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/AM/RBSCOL19B5CMW644TVJTR4.uasset new file mode 100644 index 00000000..a0f37527 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/AM/RBSCOL19B5CMW644TVJTR4.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/BR/9XPZ2GMZZ1NY4PMT5B1X16.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/BR/9XPZ2GMZZ1NY4PMT5B1X16.uasset new file mode 100644 index 00000000..d4e8ee24 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/BR/9XPZ2GMZZ1NY4PMT5B1X16.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/DJ/RMT2OIUYZLAQ2ORC3A6P07.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/DJ/RMT2OIUYZLAQ2ORC3A6P07.uasset new file mode 100644 index 00000000..8961299d Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/DJ/RMT2OIUYZLAQ2ORC3A6P07.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/NM/3VCBC7UIGWUSBXEVJ0JEHK.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/NM/3VCBC7UIGWUSBXEVJ0JEHK.uasset new file mode 100644 index 00000000..5e74e2f0 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/C/NM/3VCBC7UIGWUSBXEVJ0JEHK.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/D/1U/LTAMNHS4NP0Y4X5K26HM6X.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/D/1U/LTAMNHS4NP0Y4X5K26HM6X.uasset new file mode 100644 index 00000000..2dfae36d Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/D/1U/LTAMNHS4NP0Y4X5K26HM6X.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/E/2J/3HZCQHIBDKQKDQBEZQYMQ9.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/E/2J/3HZCQHIBDKQKDQBEZQYMQ9.uasset new file mode 100644 index 00000000..4b199b60 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/E/2J/3HZCQHIBDKQKDQBEZQYMQ9.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/E/3E/J1GUWC8ZTW15EXCJHF9HKF.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/E/3E/J1GUWC8ZTW15EXCJHF9HKF.uasset new file mode 100644 index 00000000..c8923678 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_Dynamic/E/3E/J1GUWC8ZTW15EXCJHF9HKF.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/00/O0L2FOK0305KZ4DGXC4CPX.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/00/O0L2FOK0305KZ4DGXC4CPX.uasset new file mode 100644 index 00000000..c8555996 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/00/O0L2FOK0305KZ4DGXC4CPX.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/7H/82YIEYKEJ13CTJ0Y7TBU23.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/7H/82YIEYKEJ13CTJ0Y7TBU23.uasset new file mode 100644 index 00000000..303cfb20 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/7H/82YIEYKEJ13CTJ0Y7TBU23.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/85/LDBQPT4FXQRAOHN6F4ZJYV.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/85/LDBQPT4FXQRAOHN6F4ZJYV.uasset new file mode 100644 index 00000000..03277ef6 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/85/LDBQPT4FXQRAOHN6F4ZJYV.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/F3/YK8T4QBYSEJJGA9XX16J85.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/F3/YK8T4QBYSEJJGA9XX16J85.uasset new file mode 100644 index 00000000..56c07069 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/F3/YK8T4QBYSEJJGA9XX16J85.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/G4/CX7JBR21L13GGREQ6YYGDU.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/G4/CX7JBR21L13GGREQ6YYGDU.uasset new file mode 100644 index 00000000..a493989a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/G4/CX7JBR21L13GGREQ6YYGDU.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/IT/VQK5QT7WWZUQKE9GXPIXKP.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/IT/VQK5QT7WWZUQKE9GXPIXKP.uasset new file mode 100644 index 00000000..5d73efef Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/IT/VQK5QT7WWZUQKE9GXPIXKP.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/KQ/JEHOWT6SILKGP0BU4JLOIE.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/KQ/JEHOWT6SILKGP0BU4JLOIE.uasset new file mode 100644 index 00000000..08526799 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/KQ/JEHOWT6SILKGP0BU4JLOIE.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/QU/4O2LB2Q5JAKOOZOMC38K67.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/QU/4O2LB2Q5JAKOOZOMC38K67.uasset new file mode 100644 index 00000000..b0bbd6de Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/QU/4O2LB2Q5JAKOOZOMC38K67.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/UR/B0IK6PQIO2GGGWXQ2UI7B2.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/UR/B0IK6PQIO2GGGWXQ2UI7B2.uasset new file mode 100644 index 00000000..a5245a39 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/UR/B0IK6PQIO2GGGWXQ2UI7B2.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/WY/PDV8Y1M482X0CITREBC5UL.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/WY/PDV8Y1M482X0CITREBC5UL.uasset new file mode 100644 index 00000000..7cd02e7b Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/0/WY/PDV8Y1M482X0CITREBC5UL.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/43/RKJCD7FNPQ7N3UHGZO5Z09.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/43/RKJCD7FNPQ7N3UHGZO5Z09.uasset new file mode 100644 index 00000000..d8faba49 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/43/RKJCD7FNPQ7N3UHGZO5Z09.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/7N/Y1P5W76HMQN8Z4Q1O34K37.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/7N/Y1P5W76HMQN8Z4Q1O34K37.uasset new file mode 100644 index 00000000..9b53e4d6 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/7N/Y1P5W76HMQN8Z4Q1O34K37.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/B2/L7Y6E0YCP6JFWXV6DRW2VY.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/B2/L7Y6E0YCP6JFWXV6DRW2VY.uasset new file mode 100644 index 00000000..20c0cea7 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/B2/L7Y6E0YCP6JFWXV6DRW2VY.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/C8/UIWBS8K2VLHBK8A39ABAFX.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/C8/UIWBS8K2VLHBK8A39ABAFX.uasset new file mode 100644 index 00000000..a98eaa5d Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/C8/UIWBS8K2VLHBK8A39ABAFX.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/CT/CZ5P9IDY9CMO3MVGS6VFSQ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/CT/CZ5P9IDY9CMO3MVGS6VFSQ.uasset new file mode 100644 index 00000000..03dcf42d Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/CT/CZ5P9IDY9CMO3MVGS6VFSQ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/DI/DIK0JHG69ZMUQS86R888FV.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/DI/DIK0JHG69ZMUQS86R888FV.uasset new file mode 100644 index 00000000..f59fb846 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/DI/DIK0JHG69ZMUQS86R888FV.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/L6/CSSHVNPIXXDCWX2ASRD1YI.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/L6/CSSHVNPIXXDCWX2ASRD1YI.uasset new file mode 100644 index 00000000..3ac81879 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/L6/CSSHVNPIXXDCWX2ASRD1YI.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/LN/VK1UQXYZM526D3VMAI1VDX.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/LN/VK1UQXYZM526D3VMAI1VDX.uasset new file mode 100644 index 00000000..7a3e6891 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/LN/VK1UQXYZM526D3VMAI1VDX.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/R8/KWN7Q74BK5JED9LLCY6IA5.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/R8/KWN7Q74BK5JED9LLCY6IA5.uasset new file mode 100644 index 00000000..1d3f8ffb Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/R8/KWN7Q74BK5JED9LLCY6IA5.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/SQ/8BO7YE7RFLCZ5EW3KMR2BC.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/SQ/8BO7YE7RFLCZ5EW3KMR2BC.uasset new file mode 100644 index 00000000..bc54fa91 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/SQ/8BO7YE7RFLCZ5EW3KMR2BC.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/WN/BYOONDYDL529SQYYHQU8ZC.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/WN/BYOONDYDL529SQYYHQU8ZC.uasset new file mode 100644 index 00000000..12a9df97 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/WN/BYOONDYDL529SQYYHQU8ZC.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/XN/R32F6Y2GYWQUEFCHXMP5S4.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/XN/R32F6Y2GYWQUEFCHXMP5S4.uasset new file mode 100644 index 00000000..73f1bacf Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/1/XN/R32F6Y2GYWQUEFCHXMP5S4.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/1R/8Z7VZJM4OQL0CHLRNPO1NW.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/1R/8Z7VZJM4OQL0CHLRNPO1NW.uasset new file mode 100644 index 00000000..5fa9aba6 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/1R/8Z7VZJM4OQL0CHLRNPO1NW.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/A8/C8R4D4IZUTSOLBO1CUMNEC.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/A8/C8R4D4IZUTSOLBO1CUMNEC.uasset new file mode 100644 index 00000000..39fc5962 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/A8/C8R4D4IZUTSOLBO1CUMNEC.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/AK/9V1SK51D68Z4GBZ8FV6XF3.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/AK/9V1SK51D68Z4GBZ8FV6XF3.uasset new file mode 100644 index 00000000..a5cefeb3 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/AK/9V1SK51D68Z4GBZ8FV6XF3.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/AU/NOM3UNGCOOY0U3PUH05IVH.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/AU/NOM3UNGCOOY0U3PUH05IVH.uasset new file mode 100644 index 00000000..c52164af Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/AU/NOM3UNGCOOY0U3PUH05IVH.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/C0/QOAZ9E6OGII3QKYDYPMI6D.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/C0/QOAZ9E6OGII3QKYDYPMI6D.uasset new file mode 100644 index 00000000..b25cb4e1 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/C0/QOAZ9E6OGII3QKYDYPMI6D.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/DG/707567XKTKWKTZTH9JRNA4.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/DG/707567XKTKWKTZTH9JRNA4.uasset new file mode 100644 index 00000000..1571c437 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/DG/707567XKTKWKTZTH9JRNA4.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/KD/P0M5OY1M1HU8J2G7RU3T6D.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/KD/P0M5OY1M1HU8J2G7RU3T6D.uasset new file mode 100644 index 00000000..26b40f29 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/KD/P0M5OY1M1HU8J2G7RU3T6D.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/RL/PL2NPOCEDFXF0P3NA72GLT.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/RL/PL2NPOCEDFXF0P3NA72GLT.uasset new file mode 100644 index 00000000..f99a900e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/RL/PL2NPOCEDFXF0P3NA72GLT.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/S6/VEZFP9QJ5LNIKZFBZM0FN0.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/S6/VEZFP9QJ5LNIKZFBZM0FN0.uasset new file mode 100644 index 00000000..cd149c8e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/S6/VEZFP9QJ5LNIKZFBZM0FN0.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/T4/WW0WTQAXR20WGT2JCNEU7V.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/T4/WW0WTQAXR20WGT2JCNEU7V.uasset new file mode 100644 index 00000000..9de6a20e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/T4/WW0WTQAXR20WGT2JCNEU7V.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/UC/C1A1RRV76BANYNR0TEWF5U.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/UC/C1A1RRV76BANYNR0TEWF5U.uasset new file mode 100644 index 00000000..5f0a30e4 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/UC/C1A1RRV76BANYNR0TEWF5U.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/V3/5HC5P2BEBRPFBY44QL50X9.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/V3/5HC5P2BEBRPFBY44QL50X9.uasset new file mode 100644 index 00000000..a053dfbb Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/V3/5HC5P2BEBRPFBY44QL50X9.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/W8/82SZV9TNE359NMYF5CDEQ0.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/W8/82SZV9TNE359NMYF5CDEQ0.uasset new file mode 100644 index 00000000..378cad6f Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/W8/82SZV9TNE359NMYF5CDEQ0.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/Z0/V88AWTYM4K19PSYQZNR51D.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/Z0/V88AWTYM4K19PSYQZNR51D.uasset new file mode 100644 index 00000000..13172f35 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/2/Z0/V88AWTYM4K19PSYQZNR51D.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/3K/W82Y1E1BQMLVD3WI9MLEYX.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/3K/W82Y1E1BQMLVD3WI9MLEYX.uasset new file mode 100644 index 00000000..6deeccb2 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/3K/W82Y1E1BQMLVD3WI9MLEYX.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/5D/UN3385S0AE956BVV0GYO54.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/5D/UN3385S0AE956BVV0GYO54.uasset new file mode 100644 index 00000000..3ee2ca10 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/5D/UN3385S0AE956BVV0GYO54.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/65/KFT6TFEG5397RZS84RTCFM.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/65/KFT6TFEG5397RZS84RTCFM.uasset new file mode 100644 index 00000000..de95b26a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/65/KFT6TFEG5397RZS84RTCFM.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/9A/SLNJ3VUJF09TIVDQKCTBWW.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/9A/SLNJ3VUJF09TIVDQKCTBWW.uasset new file mode 100644 index 00000000..d89dc1cb Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/9A/SLNJ3VUJF09TIVDQKCTBWW.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/9S/S9QGJKULR5QA4ATOH66CUP.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/9S/S9QGJKULR5QA4ATOH66CUP.uasset new file mode 100644 index 00000000..0d4a6dfd Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/9S/S9QGJKULR5QA4ATOH66CUP.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/C2/3JU9SY9CEOOQINLNADKWD1.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/C2/3JU9SY9CEOOQINLNADKWD1.uasset new file mode 100644 index 00000000..118bacba Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/C2/3JU9SY9CEOOQINLNADKWD1.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/DD/ZI595561VT3412HC6PAQJL.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/DD/ZI595561VT3412HC6PAQJL.uasset new file mode 100644 index 00000000..6ab7a8b0 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/DD/ZI595561VT3412HC6PAQJL.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/F4/M8N9363A05PYTYSYOIN7GH.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/F4/M8N9363A05PYTYSYOIN7GH.uasset new file mode 100644 index 00000000..18227ff8 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/F4/M8N9363A05PYTYSYOIN7GH.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/HL/XCJ1T5AWL7O7XW30CMCBOZ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/HL/XCJ1T5AWL7O7XW30CMCBOZ.uasset new file mode 100644 index 00000000..b3a38244 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/HL/XCJ1T5AWL7O7XW30CMCBOZ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/KU/0S2IAAVWDJGMO3MKPYFP5N.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/KU/0S2IAAVWDJGMO3MKPYFP5N.uasset new file mode 100644 index 00000000..defa48bd Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/KU/0S2IAAVWDJGMO3MKPYFP5N.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/QD/PZXM2KORSOQ5CY7SOK32YJ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/QD/PZXM2KORSOQ5CY7SOK32YJ.uasset new file mode 100644 index 00000000..b4792382 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/QD/PZXM2KORSOQ5CY7SOK32YJ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/RJ/2OFYSD6STQ21NKX6DSTYDL.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/RJ/2OFYSD6STQ21NKX6DSTYDL.uasset new file mode 100644 index 00000000..baa0743f Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/RJ/2OFYSD6STQ21NKX6DSTYDL.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/RM/1AG27QJ88MAXWFG1B4B09U.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/RM/1AG27QJ88MAXWFG1B4B09U.uasset new file mode 100644 index 00000000..846e4f8a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/RM/1AG27QJ88MAXWFG1B4B09U.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/U2/1C3ZPRMGPL7SWV0YOZM2QL.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/U2/1C3ZPRMGPL7SWV0YOZM2QL.uasset new file mode 100644 index 00000000..a1c5e2f7 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/3/U2/1C3ZPRMGPL7SWV0YOZM2QL.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/09/V0OH52K1FXRS9LXIRUYK9T.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/09/V0OH52K1FXRS9LXIRUYK9T.uasset new file mode 100644 index 00000000..c35c245d Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/09/V0OH52K1FXRS9LXIRUYK9T.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/46/4PAX5IAFCABDJ2D6IBSFY3.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/46/4PAX5IAFCABDJ2D6IBSFY3.uasset new file mode 100644 index 00000000..a71734d4 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/46/4PAX5IAFCABDJ2D6IBSFY3.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/BH/DOCN7FE4Y9IN9GD0VXXFW0.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/BH/DOCN7FE4Y9IN9GD0VXXFW0.uasset new file mode 100644 index 00000000..709d5a2f Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/BH/DOCN7FE4Y9IN9GD0VXXFW0.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/DU/17LBXWI99DH26SC2HL5SCG.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/DU/17LBXWI99DH26SC2HL5SCG.uasset new file mode 100644 index 00000000..81a1339a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/DU/17LBXWI99DH26SC2HL5SCG.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/HL/MMU2F4XPGESVA6WGH5YS2B.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/HL/MMU2F4XPGESVA6WGH5YS2B.uasset new file mode 100644 index 00000000..94548a50 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/HL/MMU2F4XPGESVA6WGH5YS2B.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/IB/30ZK0ZJ9SC3UEJ6I72R56J.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/IB/30ZK0ZJ9SC3UEJ6I72R56J.uasset new file mode 100644 index 00000000..844dbf83 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/IB/30ZK0ZJ9SC3UEJ6I72R56J.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/IB/L0ONAUDJPWHXWUYNKGY729.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/IB/L0ONAUDJPWHXWUYNKGY729.uasset new file mode 100644 index 00000000..527bd41b Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/IB/L0ONAUDJPWHXWUYNKGY729.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/LG/1W9TTEJDTRD7XOO29XGS1K.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/LG/1W9TTEJDTRD7XOO29XGS1K.uasset new file mode 100644 index 00000000..37ea9bc4 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/LG/1W9TTEJDTRD7XOO29XGS1K.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/MW/8EQBBTO6VI8ZRBLEG5B9RG.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/MW/8EQBBTO6VI8ZRBLEG5B9RG.uasset new file mode 100644 index 00000000..89bfe371 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/MW/8EQBBTO6VI8ZRBLEG5B9RG.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/OZ/C823XY2FMYPN9BRNCME9J6.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/OZ/C823XY2FMYPN9BRNCME9J6.uasset new file mode 100644 index 00000000..dd579630 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/OZ/C823XY2FMYPN9BRNCME9J6.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/PF/K0G7BKSPHUATBVZH1ZOFP4.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/PF/K0G7BKSPHUATBVZH1ZOFP4.uasset new file mode 100644 index 00000000..dbae8185 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/PF/K0G7BKSPHUATBVZH1ZOFP4.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/PV/A7ZF8FDYKRUJL8248OX58Q.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/PV/A7ZF8FDYKRUJL8248OX58Q.uasset new file mode 100644 index 00000000..93bb461a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/PV/A7ZF8FDYKRUJL8248OX58Q.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/SJ/SQOPLXZ9O36LSA6AKKCZOJ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/SJ/SQOPLXZ9O36LSA6AKKCZOJ.uasset new file mode 100644 index 00000000..3279aa1e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/SJ/SQOPLXZ9O36LSA6AKKCZOJ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/UA/GRWWB6VTVXO61G0GCRP1FV.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/UA/GRWWB6VTVXO61G0GCRP1FV.uasset new file mode 100644 index 00000000..b71d5834 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/UA/GRWWB6VTVXO61G0GCRP1FV.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/UC/8JECJML8DCQ3JGNXIAI8UX.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/UC/8JECJML8DCQ3JGNXIAI8UX.uasset new file mode 100644 index 00000000..2fd1584a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/UC/8JECJML8DCQ3JGNXIAI8UX.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/V4/EO1YM1HMWYW5MVI1SKC0OX.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/V4/EO1YM1HMWYW5MVI1SKC0OX.uasset new file mode 100644 index 00000000..4d3ddd4a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/V4/EO1YM1HMWYW5MVI1SKC0OX.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/Z6/OXK9R4OGDCYS09IB5KBW2Z.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/Z6/OXK9R4OGDCYS09IB5KBW2Z.uasset new file mode 100644 index 00000000..8249c8a0 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/4/Z6/OXK9R4OGDCYS09IB5KBW2Z.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/49/QJ0IS6R91HZFLQ5I9R34S1.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/49/QJ0IS6R91HZFLQ5I9R34S1.uasset new file mode 100644 index 00000000..9b21227e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/49/QJ0IS6R91HZFLQ5I9R34S1.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/52/AYVE6CVAS432WGTMUJD4UD.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/52/AYVE6CVAS432WGTMUJD4UD.uasset new file mode 100644 index 00000000..ee15fc33 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/52/AYVE6CVAS432WGTMUJD4UD.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/7Z/QDXK30X66EX7MKD2L5YGLF.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/7Z/QDXK30X66EX7MKD2L5YGLF.uasset new file mode 100644 index 00000000..24ade93a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/7Z/QDXK30X66EX7MKD2L5YGLF.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/AF/R30Y39F0RJPQN7DW032WIX.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/AF/R30Y39F0RJPQN7DW032WIX.uasset new file mode 100644 index 00000000..0e718051 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/AF/R30Y39F0RJPQN7DW032WIX.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/AI/BX016W3PULF7ZD35FLYJ11.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/AI/BX016W3PULF7ZD35FLYJ11.uasset new file mode 100644 index 00000000..ccc4aaa8 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/AI/BX016W3PULF7ZD35FLYJ11.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/CG/742LUQ8CRQUK8HBZU7ECXP.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/CG/742LUQ8CRQUK8HBZU7ECXP.uasset new file mode 100644 index 00000000..f00c4f5e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/CG/742LUQ8CRQUK8HBZU7ECXP.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/CX/JCW7BQXCWQE9AB7BF72SCY.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/CX/JCW7BQXCWQE9AB7BF72SCY.uasset new file mode 100644 index 00000000..45dfab6e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/CX/JCW7BQXCWQE9AB7BF72SCY.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/EU/UT8OOWYWC417KYPGBBJAA8.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/EU/UT8OOWYWC417KYPGBBJAA8.uasset new file mode 100644 index 00000000..25041f5a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/EU/UT8OOWYWC417KYPGBBJAA8.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/GV/WPBJFR8S8DDN1CZUZWYAAY.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/GV/WPBJFR8S8DDN1CZUZWYAAY.uasset new file mode 100644 index 00000000..02adce7a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/GV/WPBJFR8S8DDN1CZUZWYAAY.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/H6/RSZUPL5YGYSGWSS0LT3J3D.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/H6/RSZUPL5YGYSGWSS0LT3J3D.uasset new file mode 100644 index 00000000..9fe57ecb Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/H6/RSZUPL5YGYSGWSS0LT3J3D.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/OW/Z978QSMPQV3OB22UDNQFUH.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/OW/Z978QSMPQV3OB22UDNQFUH.uasset new file mode 100644 index 00000000..1b66fc14 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/OW/Z978QSMPQV3OB22UDNQFUH.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/PD/WVRH74AWHQQQ128U5JP9U4.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/PD/WVRH74AWHQQQ128U5JP9U4.uasset new file mode 100644 index 00000000..6d85f257 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/PD/WVRH74AWHQQQ128U5JP9U4.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/PO/34VEJ5LRJA2E8YKARUCWKC.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/PO/34VEJ5LRJA2E8YKARUCWKC.uasset new file mode 100644 index 00000000..e95fe758 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/PO/34VEJ5LRJA2E8YKARUCWKC.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/R9/CW9GV5E1IZI0BDOL85EXY8.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/R9/CW9GV5E1IZI0BDOL85EXY8.uasset new file mode 100644 index 00000000..8e04ece3 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/R9/CW9GV5E1IZI0BDOL85EXY8.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/X4/YTHVAE85GS6RLUC5KQVMDS.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/X4/YTHVAE85GS6RLUC5KQVMDS.uasset new file mode 100644 index 00000000..4c6d0c6f Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/X4/YTHVAE85GS6RLUC5KQVMDS.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/XD/MSA4Z2N59TFFZMY1LEYK61.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/XD/MSA4Z2N59TFFZMY1LEYK61.uasset new file mode 100644 index 00000000..29712eb3 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/XD/MSA4Z2N59TFFZMY1LEYK61.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/Z1/XTNK0Q3AYE8A9I1IP47XC6.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/Z1/XTNK0Q3AYE8A9I1IP47XC6.uasset new file mode 100644 index 00000000..95310ee1 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/5/Z1/XTNK0Q3AYE8A9I1IP47XC6.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/2W/NQ8897V6AY2PZH9237K1AW.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/2W/NQ8897V6AY2PZH9237K1AW.uasset new file mode 100644 index 00000000..09a7df2c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/2W/NQ8897V6AY2PZH9237K1AW.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/7B/A5OTC05CVUO4GJ14EQAHL3.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/7B/A5OTC05CVUO4GJ14EQAHL3.uasset new file mode 100644 index 00000000..b4c123d4 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/7B/A5OTC05CVUO4GJ14EQAHL3.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/A1/5KS3RIRGOKAQE4YR23A38W.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/A1/5KS3RIRGOKAQE4YR23A38W.uasset new file mode 100644 index 00000000..5bdc9433 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/A1/5KS3RIRGOKAQE4YR23A38W.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/CG/HEB05G011067ZMW1C7TSI6.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/CG/HEB05G011067ZMW1C7TSI6.uasset new file mode 100644 index 00000000..628ed4fd Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/CG/HEB05G011067ZMW1C7TSI6.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/FR/Z5BDCUBF6DOP4H4G4I1CTX.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/FR/Z5BDCUBF6DOP4H4G4I1CTX.uasset new file mode 100644 index 00000000..fd641f9b Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/FR/Z5BDCUBF6DOP4H4G4I1CTX.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/IR/W9TNTPGIVXPCLHWKHTWS1E.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/IR/W9TNTPGIVXPCLHWKHTWS1E.uasset new file mode 100644 index 00000000..e2af05bc Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/IR/W9TNTPGIVXPCLHWKHTWS1E.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/IZ/QFCZ0747SYCJMLPSBDWOPW.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/IZ/QFCZ0747SYCJMLPSBDWOPW.uasset new file mode 100644 index 00000000..e8f65ef1 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/IZ/QFCZ0747SYCJMLPSBDWOPW.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/KB/93F2IU8OLKSPVRUZGB4FEO.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/KB/93F2IU8OLKSPVRUZGB4FEO.uasset new file mode 100644 index 00000000..5f6828aa Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/KB/93F2IU8OLKSPVRUZGB4FEO.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/NK/LEBDZE931MDW44U2AGB85F.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/NK/LEBDZE931MDW44U2AGB85F.uasset new file mode 100644 index 00000000..908df2a1 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/NK/LEBDZE931MDW44U2AGB85F.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/O0/I47E53OQMX7RPDZ7TNU090.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/O0/I47E53OQMX7RPDZ7TNU090.uasset new file mode 100644 index 00000000..ca327a7e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/O0/I47E53OQMX7RPDZ7TNU090.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/OA/2KVWGQ99A4Y194TSYRDF04.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/OA/2KVWGQ99A4Y194TSYRDF04.uasset new file mode 100644 index 00000000..31ed0301 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/OA/2KVWGQ99A4Y194TSYRDF04.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/OQ/JL02J0LM1LHYSS7RAYN4XM.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/OQ/JL02J0LM1LHYSS7RAYN4XM.uasset new file mode 100644 index 00000000..b96785d4 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/OQ/JL02J0LM1LHYSS7RAYN4XM.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/U5/UWD3FH58PWVW8AT28FOQDR.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/U5/UWD3FH58PWVW8AT28FOQDR.uasset new file mode 100644 index 00000000..247a0bde Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/U5/UWD3FH58PWVW8AT28FOQDR.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/UY/3ZY79V0FX5V97PI4K7TLW7.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/UY/3ZY79V0FX5V97PI4K7TLW7.uasset new file mode 100644 index 00000000..71637e6e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/UY/3ZY79V0FX5V97PI4K7TLW7.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/WI/05H4SIGF8JKI53VCOIEBGQ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/WI/05H4SIGF8JKI53VCOIEBGQ.uasset new file mode 100644 index 00000000..cc7364f6 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/6/WI/05H4SIGF8JKI53VCOIEBGQ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/0L/HWXVX7UFX9A81FBL86EIB0.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/0L/HWXVX7UFX9A81FBL86EIB0.uasset new file mode 100644 index 00000000..c09652e7 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/0L/HWXVX7UFX9A81FBL86EIB0.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/2Y/PQSRHOAKXVQPVQNCE618QQ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/2Y/PQSRHOAKXVQPVQNCE618QQ.uasset new file mode 100644 index 00000000..f032cf73 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/2Y/PQSRHOAKXVQPVQNCE618QQ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/5A/YDHGSH0141VPCHS9FYOCV6.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/5A/YDHGSH0141VPCHS9FYOCV6.uasset new file mode 100644 index 00000000..90db7955 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/5A/YDHGSH0141VPCHS9FYOCV6.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/7I/9L1HD651JMQO0YO1KDRKDW.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/7I/9L1HD651JMQO0YO1KDRKDW.uasset new file mode 100644 index 00000000..3c4607d9 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/7I/9L1HD651JMQO0YO1KDRKDW.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/BX/RITA1EVB9AKXVOLNPIZJV1.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/BX/RITA1EVB9AKXVOLNPIZJV1.uasset new file mode 100644 index 00000000..b874328e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/BX/RITA1EVB9AKXVOLNPIZJV1.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/BY/RV2EBUACJ5QWF8U12QUTXL.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/BY/RV2EBUACJ5QWF8U12QUTXL.uasset new file mode 100644 index 00000000..71700abc Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/BY/RV2EBUACJ5QWF8U12QUTXL.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/CC/O7K2HJMPC7570GNDBGENOO.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/CC/O7K2HJMPC7570GNDBGENOO.uasset new file mode 100644 index 00000000..8b51cd3c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/CC/O7K2HJMPC7570GNDBGENOO.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/D3/O4X491172B6MUQGWJ6MVJI.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/D3/O4X491172B6MUQGWJ6MVJI.uasset new file mode 100644 index 00000000..c9c259ae Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/D3/O4X491172B6MUQGWJ6MVJI.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/F3/U76OD7QNA4P291PTPTF2ON.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/F3/U76OD7QNA4P291PTPTF2ON.uasset new file mode 100644 index 00000000..b95c1141 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/F3/U76OD7QNA4P291PTPTF2ON.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/LK/660XFQ37GOCGJHJA6FCRB3.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/LK/660XFQ37GOCGJHJA6FCRB3.uasset new file mode 100644 index 00000000..7a8c9b27 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/LK/660XFQ37GOCGJHJA6FCRB3.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/VH/ZIZHLLXR3XXXZ32X08GD53.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/VH/ZIZHLLXR3XXXZ32X08GD53.uasset new file mode 100644 index 00000000..b9889ecc Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/VH/ZIZHLLXR3XXXZ32X08GD53.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/W7/4XYZ5TIH3ZW3F9KLZUOVWS.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/W7/4XYZ5TIH3ZW3F9KLZUOVWS.uasset new file mode 100644 index 00000000..abcea0f5 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/7/W7/4XYZ5TIH3ZW3F9KLZUOVWS.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/6R/WWP32OXNXSPPLG7EC5NJ5Q.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/6R/WWP32OXNXSPPLG7EC5NJ5Q.uasset new file mode 100644 index 00000000..ef67d42d Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/6R/WWP32OXNXSPPLG7EC5NJ5Q.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/8X/0CQVY420398NT7KUFUOE8C.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/8X/0CQVY420398NT7KUFUOE8C.uasset new file mode 100644 index 00000000..4ec33c32 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/8X/0CQVY420398NT7KUFUOE8C.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/AR/U59J6N4GGMKBWDG507N57Y.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/AR/U59J6N4GGMKBWDG507N57Y.uasset new file mode 100644 index 00000000..6cc4fbc9 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/AR/U59J6N4GGMKBWDG507N57Y.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/CO/EH2KMR9VK0XOB5U8AI3X3B.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/CO/EH2KMR9VK0XOB5U8AI3X3B.uasset new file mode 100644 index 00000000..8e70c0c9 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/CO/EH2KMR9VK0XOB5U8AI3X3B.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/I6/PJVK37XW65S9D7UJHTWYHS.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/I6/PJVK37XW65S9D7UJHTWYHS.uasset new file mode 100644 index 00000000..fb4c2757 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/I6/PJVK37XW65S9D7UJHTWYHS.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/N8/M2PM7CJ2A9SBWKC60LAM78.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/N8/M2PM7CJ2A9SBWKC60LAM78.uasset new file mode 100644 index 00000000..8d67c4fc Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/N8/M2PM7CJ2A9SBWKC60LAM78.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/NU/DBL0OVUXSFKQB40X28H023.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/NU/DBL0OVUXSFKQB40X28H023.uasset new file mode 100644 index 00000000..b0ac60cc Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/NU/DBL0OVUXSFKQB40X28H023.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/TD/CC494ZSGBSQB2WZQU2EYOM.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/TD/CC494ZSGBSQB2WZQU2EYOM.uasset new file mode 100644 index 00000000..4d4e9763 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/TD/CC494ZSGBSQB2WZQU2EYOM.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/X6/709TO2KVEHPMESCKQNOTEA.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/X6/709TO2KVEHPMESCKQNOTEA.uasset new file mode 100644 index 00000000..b07b556c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/X6/709TO2KVEHPMESCKQNOTEA.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/YD/TI858ODS5NERJR4F0KBCMT.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/YD/TI858ODS5NERJR4F0KBCMT.uasset new file mode 100644 index 00000000..e979664c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/8/YD/TI858ODS5NERJR4F0KBCMT.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/23/E3J1NS5SPUZS2X1I9C6LAV.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/23/E3J1NS5SPUZS2X1I9C6LAV.uasset new file mode 100644 index 00000000..945ad612 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/23/E3J1NS5SPUZS2X1I9C6LAV.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/2C/3JPGOIOIK5QU1ULVP2SDFP.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/2C/3JPGOIOIK5QU1ULVP2SDFP.uasset new file mode 100644 index 00000000..036b1906 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/2C/3JPGOIOIK5QU1ULVP2SDFP.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/6Q/D4VEPJ5KEO3NSXN8FNYO9D.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/6Q/D4VEPJ5KEO3NSXN8FNYO9D.uasset new file mode 100644 index 00000000..6cae567b Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/6Q/D4VEPJ5KEO3NSXN8FNYO9D.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/9C/P7U1SQTZXDK4JIX4U7IC9H.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/9C/P7U1SQTZXDK4JIX4U7IC9H.uasset new file mode 100644 index 00000000..3f31a96b Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/9C/P7U1SQTZXDK4JIX4U7IC9H.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/CJ/0GREZPLZN5OG8EHOH662CB.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/CJ/0GREZPLZN5OG8EHOH662CB.uasset new file mode 100644 index 00000000..69015507 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/CJ/0GREZPLZN5OG8EHOH662CB.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/HJ/5VHPQ9CJORLYNG3QUJH9D9.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/HJ/5VHPQ9CJORLYNG3QUJH9D9.uasset new file mode 100644 index 00000000..3e7b81ef Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/HJ/5VHPQ9CJORLYNG3QUJH9D9.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/LT/XD47O5M0SF3YQKP20PSGNR.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/LT/XD47O5M0SF3YQKP20PSGNR.uasset new file mode 100644 index 00000000..33ba66cb Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/LT/XD47O5M0SF3YQKP20PSGNR.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/M4/QWRLXKQMGPGZ58MS30R1H6.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/M4/QWRLXKQMGPGZ58MS30R1H6.uasset new file mode 100644 index 00000000..b7dc0592 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/M4/QWRLXKQMGPGZ58MS30R1H6.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/TY/KD3UVON8NNIKAPQBKMHBFC.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/TY/KD3UVON8NNIKAPQBKMHBFC.uasset new file mode 100644 index 00000000..a61f4131 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/TY/KD3UVON8NNIKAPQBKMHBFC.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/V1/PFZL3PCZ52SEMOVUJT2NAO.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/V1/PFZL3PCZ52SEMOVUJT2NAO.uasset new file mode 100644 index 00000000..add2ac42 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/V1/PFZL3PCZ52SEMOVUJT2NAO.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/VP/PN458QVUDXJ1MHTI3HOEMC.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/VP/PN458QVUDXJ1MHTI3HOEMC.uasset new file mode 100644 index 00000000..4c023939 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/VP/PN458QVUDXJ1MHTI3HOEMC.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/W8/00BBXU3PVRGQRLD4QYF7Y7.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/W8/00BBXU3PVRGQRLD4QYF7Y7.uasset new file mode 100644 index 00000000..c0b72cef Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/W8/00BBXU3PVRGQRLD4QYF7Y7.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/WU/8SD90DFZAK3BFZFWXZEJFN.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/WU/8SD90DFZAK3BFZFWXZEJFN.uasset new file mode 100644 index 00000000..b7203005 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/WU/8SD90DFZAK3BFZFWXZEJFN.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/ZR/5KLVF2FQNZTTODFVKXCH6D.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/ZR/5KLVF2FQNZTTODFVKXCH6D.uasset new file mode 100644 index 00000000..9f6a8591 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/9/ZR/5KLVF2FQNZTTODFVKXCH6D.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/6M/672RKXXWIBXI82UB702UMZ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/6M/672RKXXWIBXI82UB702UMZ.uasset new file mode 100644 index 00000000..aeba24cd Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/6M/672RKXXWIBXI82UB702UMZ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/70/9L22342LVDNIWN2ORPDI51.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/70/9L22342LVDNIWN2ORPDI51.uasset new file mode 100644 index 00000000..3cf20271 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/70/9L22342LVDNIWN2ORPDI51.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/7T/RZETSWBIKZ3XQ4GT87V57B.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/7T/RZETSWBIKZ3XQ4GT87V57B.uasset new file mode 100644 index 00000000..50adf9f8 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/7T/RZETSWBIKZ3XQ4GT87V57B.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/AW/GRPY6LJI22MIZUHXFMB5EI.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/AW/GRPY6LJI22MIZUHXFMB5EI.uasset new file mode 100644 index 00000000..786eec2a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/AW/GRPY6LJI22MIZUHXFMB5EI.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/DV/1C37UW3TITNAHVFRE1YHOR.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/DV/1C37UW3TITNAHVFRE1YHOR.uasset new file mode 100644 index 00000000..426b3931 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/DV/1C37UW3TITNAHVFRE1YHOR.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/M6/O3LTA5XCLJOA5CCRRSDN75.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/M6/O3LTA5XCLJOA5CCRRSDN75.uasset new file mode 100644 index 00000000..51d5e570 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/M6/O3LTA5XCLJOA5CCRRSDN75.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/VL/2CR1N302CRV1OICUI9BBH6.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/VL/2CR1N302CRV1OICUI9BBH6.uasset new file mode 100644 index 00000000..6623c713 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/VL/2CR1N302CRV1OICUI9BBH6.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/YA/0CJMLVR2N0S0JU0F75H1DS.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/YA/0CJMLVR2N0S0JU0F75H1DS.uasset new file mode 100644 index 00000000..002981d5 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/YA/0CJMLVR2N0S0JU0F75H1DS.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/Z5/X3LJ0WE3ZYSVCXEH1QZWQH.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/Z5/X3LJ0WE3ZYSVCXEH1QZWQH.uasset new file mode 100644 index 00000000..d58f9ff7 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/A/Z5/X3LJ0WE3ZYSVCXEH1QZWQH.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/0C/890SDPREDSHT63KQ7LCCC3.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/0C/890SDPREDSHT63KQ7LCCC3.uasset new file mode 100644 index 00000000..93b2bd5b Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/0C/890SDPREDSHT63KQ7LCCC3.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/2T/9FIX2B4DWE1M06MYRI6W3A.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/2T/9FIX2B4DWE1M06MYRI6W3A.uasset new file mode 100644 index 00000000..c2807915 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/2T/9FIX2B4DWE1M06MYRI6W3A.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/7R/A4B4NMVVNUFR6FWX5LM6I2.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/7R/A4B4NMVVNUFR6FWX5LM6I2.uasset new file mode 100644 index 00000000..c7d8cba5 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/7R/A4B4NMVVNUFR6FWX5LM6I2.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/8N/2UT0C723LV7DIHM2FSR6SN.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/8N/2UT0C723LV7DIHM2FSR6SN.uasset new file mode 100644 index 00000000..485ec8ba Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/8N/2UT0C723LV7DIHM2FSR6SN.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/9A/0UNMSPU5AZ5HJY3CTVGP3L.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/9A/0UNMSPU5AZ5HJY3CTVGP3L.uasset new file mode 100644 index 00000000..41b4c70c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/9A/0UNMSPU5AZ5HJY3CTVGP3L.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/9U/ZSKOB37PNUEUQICMJW45PL.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/9U/ZSKOB37PNUEUQICMJW45PL.uasset new file mode 100644 index 00000000..c350a677 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/9U/ZSKOB37PNUEUQICMJW45PL.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/CQ/MN2NU6GNGUDV8YJPSHBJIV.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/CQ/MN2NU6GNGUDV8YJPSHBJIV.uasset new file mode 100644 index 00000000..cc47958e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/CQ/MN2NU6GNGUDV8YJPSHBJIV.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/O5/FQGS7OSSGRA1XHVH3QMZ3D.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/O5/FQGS7OSSGRA1XHVH3QMZ3D.uasset new file mode 100644 index 00000000..80a798fe Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/O5/FQGS7OSSGRA1XHVH3QMZ3D.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/P8/Z2VSKG1JPXG2UCW1TBWY1Q.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/P8/Z2VSKG1JPXG2UCW1TBWY1Q.uasset new file mode 100644 index 00000000..0faccce8 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/P8/Z2VSKG1JPXG2UCW1TBWY1Q.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/PR/JHOFR4EU70FVA5NPUDL2JB.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/PR/JHOFR4EU70FVA5NPUDL2JB.uasset new file mode 100644 index 00000000..3fe30c2a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/PR/JHOFR4EU70FVA5NPUDL2JB.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/QE/J7CRTPGYAF7R5Z5Y2PW9LK.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/QE/J7CRTPGYAF7R5Z5Y2PW9LK.uasset new file mode 100644 index 00000000..a5926886 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/QE/J7CRTPGYAF7R5Z5Y2PW9LK.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/W0/PSRGPEES6VR95LQ6RMQKAF.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/W0/PSRGPEES6VR95LQ6RMQKAF.uasset new file mode 100644 index 00000000..5e29faf2 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/B/W0/PSRGPEES6VR95LQ6RMQKAF.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/0B/DX7CESOTBOIVOS6DNGN6XA.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/0B/DX7CESOTBOIVOS6DNGN6XA.uasset new file mode 100644 index 00000000..d462cd57 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/0B/DX7CESOTBOIVOS6DNGN6XA.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/5W/SL8PKXK8HIP1Y5Z5BWYKZ8.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/5W/SL8PKXK8HIP1Y5Z5BWYKZ8.uasset new file mode 100644 index 00000000..70a0711e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/5W/SL8PKXK8HIP1Y5Z5BWYKZ8.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/80/5NR8FRGUV26PHZ074AYEA9.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/80/5NR8FRGUV26PHZ074AYEA9.uasset new file mode 100644 index 00000000..6480799a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/80/5NR8FRGUV26PHZ074AYEA9.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/8U/YTQYO46R12T60UCTY054MW.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/8U/YTQYO46R12T60UCTY054MW.uasset new file mode 100644 index 00000000..37dc7cae Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/8U/YTQYO46R12T60UCTY054MW.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/I2/DMZF9RGN7R2ACI1SR8XY5W.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/I2/DMZF9RGN7R2ACI1SR8XY5W.uasset new file mode 100644 index 00000000..8e17b675 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/I2/DMZF9RGN7R2ACI1SR8XY5W.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/KB/FM6UY3MX053W7E07P9YVPQ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/KB/FM6UY3MX053W7E07P9YVPQ.uasset new file mode 100644 index 00000000..c60becb8 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/KB/FM6UY3MX053W7E07P9YVPQ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/TD/MP0ZJER41Q4UCZY5X5PS0Z.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/TD/MP0ZJER41Q4UCZY5X5PS0Z.uasset new file mode 100644 index 00000000..b16e4811 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/TD/MP0ZJER41Q4UCZY5X5PS0Z.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/TJ/NWWJ2XLF5OXOJTDG1BO6SZ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/TJ/NWWJ2XLF5OXOJTDG1BO6SZ.uasset new file mode 100644 index 00000000..ebb88cc2 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/TJ/NWWJ2XLF5OXOJTDG1BO6SZ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/WA/A0N2QWLQCS44D02T26IX48.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/WA/A0N2QWLQCS44D02T26IX48.uasset new file mode 100644 index 00000000..d896e23c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/C/WA/A0N2QWLQCS44D02T26IX48.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/0D/PQ6VHU620D7AQ0FV1V4EGV.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/0D/PQ6VHU620D7AQ0FV1V4EGV.uasset new file mode 100644 index 00000000..9024f5b2 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/0D/PQ6VHU620D7AQ0FV1V4EGV.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/2L/9FV44SETXDKFSBK8Q26UNJ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/2L/9FV44SETXDKFSBK8Q26UNJ.uasset new file mode 100644 index 00000000..78827a74 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/2L/9FV44SETXDKFSBK8Q26UNJ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/30/15KB9R55PIN3HC6ABQN01M.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/30/15KB9R55PIN3HC6ABQN01M.uasset new file mode 100644 index 00000000..f7cbbdc8 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/30/15KB9R55PIN3HC6ABQN01M.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/4Q/ZYCMKCLF3ITGZYKTGTYGOH.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/4Q/ZYCMKCLF3ITGZYKTGTYGOH.uasset new file mode 100644 index 00000000..62eb6ab2 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/4Q/ZYCMKCLF3ITGZYKTGTYGOH.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/5I/COGM41FNJUCWIOE02L391U.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/5I/COGM41FNJUCWIOE02L391U.uasset new file mode 100644 index 00000000..c78f3983 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/5I/COGM41FNJUCWIOE02L391U.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/74/6J0DHA1KMJPA5EHI35VFYV.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/74/6J0DHA1KMJPA5EHI35VFYV.uasset new file mode 100644 index 00000000..eeb5c21b Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/74/6J0DHA1KMJPA5EHI35VFYV.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/FW/8XI8C70YS887K6PICM7VUL.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/FW/8XI8C70YS887K6PICM7VUL.uasset new file mode 100644 index 00000000..17c9d4f0 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/FW/8XI8C70YS887K6PICM7VUL.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/GU/Q417MZZ8YDZIHUP5O2GP2G.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/GU/Q417MZZ8YDZIHUP5O2GP2G.uasset new file mode 100644 index 00000000..8787dc61 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/GU/Q417MZZ8YDZIHUP5O2GP2G.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/IR/QA0JLPASVRPNW90R1IY0QF.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/IR/QA0JLPASVRPNW90R1IY0QF.uasset new file mode 100644 index 00000000..5b10a64c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/IR/QA0JLPASVRPNW90R1IY0QF.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/L7/YN0507J5Q4I3KWZ5ATC4DJ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/L7/YN0507J5Q4I3KWZ5ATC4DJ.uasset new file mode 100644 index 00000000..8a32916d Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/L7/YN0507J5Q4I3KWZ5ATC4DJ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/N3/FJQHWYSDH05OZ6D400K8Q7.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/N3/FJQHWYSDH05OZ6D400K8Q7.uasset new file mode 100644 index 00000000..460c69ea Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/N3/FJQHWYSDH05OZ6D400K8Q7.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/VI/61D1C6P9GCRPBR0IA778S5.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/VI/61D1C6P9GCRPBR0IA778S5.uasset new file mode 100644 index 00000000..def4fe3c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/D/VI/61D1C6P9GCRPBR0IA778S5.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/1W/KRJQE7L9EZII2L2HTW51W3.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/1W/KRJQE7L9EZII2L2HTW51W3.uasset new file mode 100644 index 00000000..ed4b30a2 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/1W/KRJQE7L9EZII2L2HTW51W3.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/40/V1PA887K5L5IWH83JZVHZ3.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/40/V1PA887K5L5IWH83JZVHZ3.uasset new file mode 100644 index 00000000..f6d0f5e0 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/40/V1PA887K5L5IWH83JZVHZ3.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/B2/33ZTVT5PI3AQQ6XU1DJ2TW.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/B2/33ZTVT5PI3AQQ6XU1DJ2TW.uasset new file mode 100644 index 00000000..869c5ae7 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/B2/33ZTVT5PI3AQQ6XU1DJ2TW.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/BJ/B41YI7U4BM557PDX1AAC6L.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/BJ/B41YI7U4BM557PDX1AAC6L.uasset new file mode 100644 index 00000000..60e0ceaf Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/BJ/B41YI7U4BM557PDX1AAC6L.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/EE/PKKTI7YWT2RHYAE4EG7FGA.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/EE/PKKTI7YWT2RHYAE4EG7FGA.uasset new file mode 100644 index 00000000..618cea6e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/EE/PKKTI7YWT2RHYAE4EG7FGA.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/I4/JQL5RCBXR7JX96LLHQMCTC.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/I4/JQL5RCBXR7JX96LLHQMCTC.uasset new file mode 100644 index 00000000..ecd8da0c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/I4/JQL5RCBXR7JX96LLHQMCTC.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/II/HFARG09E4DMGMBPZ3HDF22.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/II/HFARG09E4DMGMBPZ3HDF22.uasset new file mode 100644 index 00000000..08cb6201 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/II/HFARG09E4DMGMBPZ3HDF22.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/K9/7E4JVTLSBPXQZKT8U6UKUK.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/K9/7E4JVTLSBPXQZKT8U6UKUK.uasset new file mode 100644 index 00000000..56c8bfef Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/K9/7E4JVTLSBPXQZKT8U6UKUK.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/L2/J35B9SUC8QNE7NYUMTEY2T.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/L2/J35B9SUC8QNE7NYUMTEY2T.uasset new file mode 100644 index 00000000..59ca2e72 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/L2/J35B9SUC8QNE7NYUMTEY2T.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/M3/J6ZZ5IMN5GTP6JSG2OGJTN.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/M3/J6ZZ5IMN5GTP6JSG2OGJTN.uasset new file mode 100644 index 00000000..64541fff Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/M3/J6ZZ5IMN5GTP6JSG2OGJTN.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/NL/N0H50W6GXKL27WZ1XP7Y1P.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/NL/N0H50W6GXKL27WZ1XP7Y1P.uasset new file mode 100644 index 00000000..21607cdd Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/NL/N0H50W6GXKL27WZ1XP7Y1P.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/R6/QZ6ELUVISU9PLY2MW435EX.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/R6/QZ6ELUVISU9PLY2MW435EX.uasset new file mode 100644 index 00000000..59eb049f Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/R6/QZ6ELUVISU9PLY2MW435EX.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/WK/JQBCMNEKHTJDWRGD802P6X.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/WK/JQBCMNEKHTJDWRGD802P6X.uasset new file mode 100644 index 00000000..50a7ed3b Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/WK/JQBCMNEKHTJDWRGD802P6X.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/WY/WMDAN3X9SHFVEXED6GYLO8.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/WY/WMDAN3X9SHFVEXED6GYLO8.uasset new file mode 100644 index 00000000..dd8105a2 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/WY/WMDAN3X9SHFVEXED6GYLO8.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/XX/CYW9X5BDVIAPAB3CAGWXTG.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/XX/CYW9X5BDVIAPAB3CAGWXTG.uasset new file mode 100644 index 00000000..fbddce86 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/E/XX/CYW9X5BDVIAPAB3CAGWXTG.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/F/0Q/WR3HKZE10XJOVQG5HI4XPJ.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/F/0Q/WR3HKZE10XJOVQG5HI4XPJ.uasset new file mode 100644 index 00000000..64040805 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/F/0Q/WR3HKZE10XJOVQG5HI4XPJ.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/F/1X/2UV246VXT19CQE1F8O06TF.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/F/1X/2UV246VXT19CQE1F8O06TF.uasset new file mode 100644 index 00000000..cfaf24ab Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/F/1X/2UV246VXT19CQE1F8O06TF.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/F/1X/SDG49ALWJH7LUGECVQUBGL.uasset b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/F/1X/SDG49ALWJH7LUGECVQUBGL.uasset new file mode 100644 index 00000000..d205e80f Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalActors__/Maps/CPathExample_DynamicLabirynthLimitTest/F/1X/SDG49ALWJH7LUGECVQUBGL.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/0/5H/U8LY246NWF6RCWT7WVOKWD.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/0/5H/U8LY246NWF6RCWT7WVOKWD.uasset new file mode 100644 index 00000000..d6a32719 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/0/5H/U8LY246NWF6RCWT7WVOKWD.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/1/0S/OMQHX8BV892ZDV8IRYGLOF.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/1/0S/OMQHX8BV892ZDV8IRYGLOF.uasset new file mode 100644 index 00000000..95702e89 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/1/0S/OMQHX8BV892ZDV8IRYGLOF.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/3/8A/YFUTLIYRNHCJF9O8ZT14FS.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/3/8A/YFUTLIYRNHCJF9O8ZT14FS.uasset new file mode 100644 index 00000000..b43bd88e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/3/8A/YFUTLIYRNHCJF9O8ZT14FS.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/4/4T/3F6SSNK35O4NS5G9JYCFQ3.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/4/4T/3F6SSNK35O4NS5G9JYCFQ3.uasset new file mode 100644 index 00000000..c18c09ea Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/4/4T/3F6SSNK35O4NS5G9JYCFQ3.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/5/AX/JHWEN4Q76PZ78GESFPQTQM.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/5/AX/JHWEN4Q76PZ78GESFPQTQM.uasset new file mode 100644 index 00000000..ad0d99cd Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/5/AX/JHWEN4Q76PZ78GESFPQTQM.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/5/OI/BKZ1PEFDEBHM6ZCJLFOJCV.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/5/OI/BKZ1PEFDEBHM6ZCJLFOJCV.uasset new file mode 100644 index 00000000..cd28befa Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/5/OI/BKZ1PEFDEBHM6ZCJLFOJCV.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/7/NW/NJ5TMTZJLCL166HSGYZQCD.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/7/NW/NJ5TMTZJLCL166HSGYZQCD.uasset new file mode 100644 index 00000000..e138c5ff Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/7/NW/NJ5TMTZJLCL166HSGYZQCD.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/C/QP/TE4CJH1ZUZAO5XQ490I75C.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/C/QP/TE4CJH1ZUZAO5XQ490I75C.uasset new file mode 100644 index 00000000..907c22d7 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/C/QP/TE4CJH1ZUZAO5XQ490I75C.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/D/7G/JUBRFLJATEBCRZI0LMKD9X.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/D/7G/JUBRFLJATEBCRZI0LMKD9X.uasset new file mode 100644 index 00000000..dac09559 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/D/7G/JUBRFLJATEBCRZI0LMKD9X.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/D/J5/NOV3L4GOLGQUVHVZ7K74Y5.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/D/J5/NOV3L4GOLGQUVHVZ7K74Y5.uasset new file mode 100644 index 00000000..69ead957 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/D/J5/NOV3L4GOLGQUVHVZ7K74Y5.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/E/54/VCK0CFZAL13BKA9Z8PXX49.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/E/54/VCK0CFZAL13BKA9Z8PXX49.uasset new file mode 100644 index 00000000..ef00449c Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/E/54/VCK0CFZAL13BKA9Z8PXX49.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/E/B0/L279E3PHMYTLGDZMCS91GS.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/E/B0/L279E3PHMYTLGDZMCS91GS.uasset new file mode 100644 index 00000000..0cefb0c7 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_2DSideScroller/E/B0/L279E3PHMYTLGDZMCS91GS.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/4/ST/F1KXROFT2YBBT96T2FK5PI.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/4/ST/F1KXROFT2YBBT96T2FK5PI.uasset new file mode 100644 index 00000000..de4d5f58 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/4/ST/F1KXROFT2YBBT96T2FK5PI.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/5/N8/LFTVA1ZONTE52JH4AT145W.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/5/N8/LFTVA1ZONTE52JH4AT145W.uasset new file mode 100644 index 00000000..5cdaa4d6 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/5/N8/LFTVA1ZONTE52JH4AT145W.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/7/VF/CQQRQEO2RIU17J9GDTZ6YA.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/7/VF/CQQRQEO2RIU17J9GDTZ6YA.uasset new file mode 100644 index 00000000..e6473f14 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/7/VF/CQQRQEO2RIU17J9GDTZ6YA.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/7/WG/DX4XXSLHMJM1XELFV3Z1Y4.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/7/WG/DX4XXSLHMJM1XELFV3Z1Y4.uasset new file mode 100644 index 00000000..129a13ff Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/7/WG/DX4XXSLHMJM1XELFV3Z1Y4.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/8/TP/9DKMFEGHN8Y9VFHF15E88P.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/8/TP/9DKMFEGHN8Y9VFHF15E88P.uasset new file mode 100644 index 00000000..f1c725fc Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/8/TP/9DKMFEGHN8Y9VFHF15E88P.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/9/EX/FZ369RKUQ0N2M7V9H13LYS.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/9/EX/FZ369RKUQ0N2M7V9H13LYS.uasset new file mode 100644 index 00000000..2397e876 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/9/EX/FZ369RKUQ0N2M7V9H13LYS.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/A/CQ/T2GOBB00NN38CJDSO63PO8.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/A/CQ/T2GOBB00NN38CJDSO63PO8.uasset new file mode 100644 index 00000000..d2332350 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/A/CQ/T2GOBB00NN38CJDSO63PO8.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/A/YN/FB40SOHPZ51HM5L2I29QX1.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/A/YN/FB40SOHPZ51HM5L2I29QX1.uasset new file mode 100644 index 00000000..96212758 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/A/YN/FB40SOHPZ51HM5L2I29QX1.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/B/9Q/U3DU69E9E6HJCEC9676WZM.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/B/9Q/U3DU69E9E6HJCEC9676WZM.uasset new file mode 100644 index 00000000..9c37f4ea Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/B/9Q/U3DU69E9E6HJCEC9676WZM.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/C/Z5/O2VGR62STHLZEYVZCJPR7U.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/C/Z5/O2VGR62STHLZEYVZCJPR7U.uasset new file mode 100644 index 00000000..2185a9d4 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/C/Z5/O2VGR62STHLZEYVZCJPR7U.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/E/AN/3L0JK7QPELSYSE4ON1GZ1R.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/E/AN/3L0JK7QPELSYSE4ON1GZ1R.uasset new file mode 100644 index 00000000..c7606d31 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_Dynamic/E/AN/3L0JK7QPELSYSE4ON1GZ1R.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/4/GM/QLWVDPI9UBFM1NJ7N76E6H.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/4/GM/QLWVDPI9UBFM1NJ7N76E6H.uasset new file mode 100644 index 00000000..c39ab750 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/4/GM/QLWVDPI9UBFM1NJ7N76E6H.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/5/ZU/D80FZEBX39G1566D8BSP34.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/5/ZU/D80FZEBX39G1566D8BSP34.uasset new file mode 100644 index 00000000..89b02b46 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/5/ZU/D80FZEBX39G1566D8BSP34.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/6/89/8CPOFJ277S4G2C7FTAD6D4.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/6/89/8CPOFJ277S4G2C7FTAD6D4.uasset new file mode 100644 index 00000000..9fb495ce Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/6/89/8CPOFJ277S4G2C7FTAD6D4.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/8/EG/43SN0JRXITEIPB0WUSP06N.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/8/EG/43SN0JRXITEIPB0WUSP06N.uasset new file mode 100644 index 00000000..e41d7e47 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/8/EG/43SN0JRXITEIPB0WUSP06N.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/8/T3/909H3W5UKANL5HFLZRBXKC.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/8/T3/909H3W5UKANL5HFLZRBXKC.uasset new file mode 100644 index 00000000..bdc208dc Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/8/T3/909H3W5UKANL5HFLZRBXKC.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/A/F1/1MC1QCVH6MNE3QQ5320UDE.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/A/F1/1MC1QCVH6MNE3QQ5320UDE.uasset new file mode 100644 index 00000000..64f33091 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/A/F1/1MC1QCVH6MNE3QQ5320UDE.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/A/RB/SQ4IOAOV28O92WMVHVW8HI.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/A/RB/SQ4IOAOV28O92WMVHVW8HI.uasset new file mode 100644 index 00000000..c6716482 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/A/RB/SQ4IOAOV28O92WMVHVW8HI.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/B/A1/WVAJJJ4ODWWL7MQY09T9Z3.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/B/A1/WVAJJJ4ODWWL7MQY09T9Z3.uasset new file mode 100644 index 00000000..2653470a Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/B/A1/WVAJJJ4ODWWL7MQY09T9Z3.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/C/JR/HMB2BKYNRC0G9CAIYHZ50M.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/C/JR/HMB2BKYNRC0G9CAIYHZ50M.uasset new file mode 100644 index 00000000..d73b8f42 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/C/JR/HMB2BKYNRC0G9CAIYHZ50M.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/C/UG/4O3SGXLG2QX6GMB94IGA0N.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/C/UG/4O3SGXLG2QX6GMB94IGA0N.uasset new file mode 100644 index 00000000..e56bc212 Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/C/UG/4O3SGXLG2QX6GMB94IGA0N.uasset differ diff --git a/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/D/EU/95JLTT6J7FBSAGE74EUDVV.uasset b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/D/EU/95JLTT6J7FBSAGE74EUDVV.uasset new file mode 100644 index 00000000..72bda33e Binary files /dev/null and b/Plugins/CPathfinding/Content/__ExternalObjects__/Maps/CPathExample_DynamicLabirynthLimitTest/D/EU/95JLTT6J7FBSAGE74EUDVV.uasset differ diff --git a/Plugins/CPathfinding/Resources/Icon128.png b/Plugins/CPathfinding/Resources/Icon128.png new file mode 100644 index 00000000..1231d4aa Binary files /dev/null and b/Plugins/CPathfinding/Resources/Icon128.png differ diff --git a/Plugins/CPathfinding/Source/CPathfinding/CPathfinding.Build.cs b/Plugins/CPathfinding/Source/CPathfinding/CPathfinding.Build.cs new file mode 100644 index 00000000..f0a753f4 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/CPathfinding.Build.cs @@ -0,0 +1,53 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +using UnrealBuildTool; + +public class CPathfinding : ModuleRules +{ + public CPathfinding(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicIncludePaths.AddRange( + new string[] { + // ... add public include paths required here ... + } + ); + + + PrivateIncludePaths.AddRange( + new string[] { + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/CPathfinding/Source/CPathfinding/Private/CPathAsyncVolumeGeneration.cpp b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathAsyncVolumeGeneration.cpp new file mode 100644 index 00000000..fb738e7b --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathAsyncVolumeGeneration.cpp @@ -0,0 +1,164 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + + +#include "CPathAsyncVolumeGeneration.h" +#include "CPathVolume.h" +#include "Engine/World.h" +#include + +FCPathAsyncVolumeGenerator::FCPathAsyncVolumeGenerator(ACPathVolume* Volume, uint32 StartIndex, uint32 EndIndex, uint8 ThreadID, FString ThreadName, bool Obstacles) + : + FCPathAsyncVolumeGenerator(Volume) +{ + bObstacles = Obstacles; + FirstIndex = StartIndex; + LastIndex = EndIndex; + GenThreadID = ThreadID; + Name = ThreadName; +} + +// Sets default values +FCPathAsyncVolumeGenerator::FCPathAsyncVolumeGenerator(ACPathVolume* Volume) +{ + VolumeRef = Volume; + +} + +FCPathAsyncVolumeGenerator::~FCPathAsyncVolumeGenerator() +{ + bStop = true; + if (ThreadRef) + ThreadRef->Kill(true); +} + +bool FCPathAsyncVolumeGenerator::Init() +{ + return true; +} + +uint32 FCPathAsyncVolumeGenerator::Run() +{ + bIncreasedGenRunning = true; + VolumeRef->GeneratorsRunning++; + + // Waiting for pathfinders to finish. + // Generators have priority over pathfinders, so we block further pathfinders from starting by incrementing GeneratorsRunning first + while (VolumeRef->PathfindersRunning.load() > 0 && !bStop) + std::this_thread::sleep_for(std::chrono::milliseconds(25)); + +#ifdef LOG_GENERATORS + auto GenerationStart = TIMENOW; +#endif + + if (LastIndex > 0) + { + if (bObstacles) + { + auto StartIter = VolumeRef->TreesToRegenerate.begin(); + for (uint32 i = 0; i < FirstIndex; i++) + StartIter++; + + auto EndIter = StartIter; + for (uint32 i = FirstIndex; i < LastIndex; i++) + EndIter++; + + for (auto Iter = StartIter; Iter != EndIter && !bStop; Iter++) + { + RefreshTree(*Iter); + } + } + else + { + for (uint32 OuterIndex = FirstIndex; OuterIndex < LastIndex && !bStop; OuterIndex++) + { + RefreshTree(OuterIndex); + } + } + } + +#ifdef LOG_GENERATORS + auto GenerationTime = TIMEDIFF(GenerationStart, TIMENOW); + + int NodeCount = 0; + for (int i = 0; i <= VolumeRef->OctreeDepth; i++) + { + NodeCount += OctreeCountAtDepth[i]; + } + + UE_LOG(LogTemp, Warning, TEXT("%s generated %d nodes in %lfms"), *Name, NodeCount, GenerationTime); +#endif + + if (bIncreasedGenRunning) + VolumeRef->GeneratorsRunning--; + bIncreasedGenRunning = false; + return 0; +} + +void FCPathAsyncVolumeGenerator::Stop() +{ + + // Preventing a potential deadlock if the process is killed without waiting + if (bIncreasedGenRunning) + VolumeRef->GeneratorsRunning--; + + bIncreasedGenRunning = false; +} + +void FCPathAsyncVolumeGenerator::Exit() +{ + +} + +void FCPathAsyncVolumeGenerator::RefreshTree(uint32 OuterIndex) +{ + CPathOctree* OctreeRef = &VolumeRef->Octrees[OuterIndex]; + if (!OctreeRef) + { + return; + } + RefreshTreeRec(OctreeRef, 0, VolumeRef->WorldLocationFromTreeID(OuterIndex)); +} + +bool FCPathAsyncVolumeGenerator::RefreshTreeRec(CPathOctree* OctreeRef, uint32 Depth, FVector TreeLocation) +{ + + bool IsFree = VolumeRef->RecheckOctreeAtDepth(OctreeRef, TreeLocation, Depth); + + OctreeCountAtDepth[Depth]++; + + if (IsFree) + { + delete[] OctreeRef->Children; + OctreeRef->Children = nullptr; + return true; + } + else if (++Depth <= (uint32)VolumeRef->OctreeDepth) + { + float HalfSize = VolumeRef->GetVoxelSizeByDepth(Depth) / 2.f; + + if (!OctreeRef->Children) + OctreeRef->Children = new CPathOctree[8]; + uint8 FreeChildren = 0; + // Checking children + for (uint32 ChildIndex = 0; ChildIndex < 8; ChildIndex++) + { + FVector Location = TreeLocation + VolumeRef->LookupTable_ChildPositionOffsetMaskByIndex[ChildIndex] * HalfSize; + FreeChildren += RefreshTreeRec(&OctreeRef->Children[ChildIndex], Depth, Location); + } + + if (FreeChildren) + { + return true; + } + else + { + delete[] OctreeRef->Children; + OctreeRef->Children = nullptr; + return false; + } + + } + return false; +} + + diff --git a/Plugins/CPathfinding/Source/CPathfinding/Private/CPathDefines.cpp b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathDefines.cpp new file mode 100644 index 00000000..d4c966b9 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathDefines.cpp @@ -0,0 +1,5 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + + +#include "CPathDefines.h" + diff --git a/Plugins/CPathfinding/Source/CPathfinding/Private/CPathDynamicObstacle.cpp b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathDynamicObstacle.cpp new file mode 100644 index 00000000..2b7bc153 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathDynamicObstacle.cpp @@ -0,0 +1,151 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +#include "CPathDynamicObstacle.h" +#include "CPathVolume.h" + +// Sets default values for this component's properties +UCPathDynamicObstacle::UCPathDynamicObstacle() +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = false; + PrimaryComponentTick.bStartWithTickEnabled = false; + bAutoActivate = false; + + if (GetOwner()) + { + if (!GetOwner()->IsRootComponentMovable()) + { + UE_LOG(LogTemp, Warning, TEXT("CPath - Dynamic obstacle '%s' is not Movable."), *GetOwner()->GetName()); + } + if (ActivateOnBeginPlay) + GetOwner()->bGenerateOverlapEventsDuringLevelStreaming = true; + } + + // ... +} + + +void UCPathDynamicObstacle::Activate(bool bReset) +{ + + Super::Activate(); + + TSubclassOf Filter = ACPathVolume::StaticClass(); + GetOwner()->GetOverlappingActors(OverlappigVolumes, ACPathVolume::StaticClass()); + + for (AActor* Volume : OverlappigVolumes) + { + Cast(Volume)->TrackedDynamicObstacles.insert(this); + } + +} + +void UCPathDynamicObstacle::Deactivate() +{ + Super::Deactivate(); + for (AActor* Volume : OverlappigVolumes) + { + auto CastedVolume = Cast(Volume); + if (IsValid(CastedVolume)) + { + CastedVolume->TrackedDynamicObstacles.erase(this); + } + } + OverlappigVolumes.Empty(); +} + +void UCPathDynamicObstacle::AddIndexesToUpdate(ACPathVolume* Volume) +{ + FVector Origin, Extent; + GetOwner()->GetActorBounds(true, Origin, Extent); + + FVector XYZ = Volume->WorldLocationToLocalCoordsInt3(Origin); + if (!Volume->IsInBounds(XYZ)) + { + return; + } + uint32 Index = Volume->LocalCoordsInt3ToIndex(XYZ); + FVector DistanceFromCenter = Origin - Volume->WorldLocationFromTreeID(Index); + + float VoxelSize = Volume->GetVoxelSizeByDepth(0); + float VoxelExtent = VoxelSize / 2.f; + + // How many outer trees should we include in given direction + int MaxOffsetInDirection[6]; + MaxOffsetInDirection[Left] = FMath::CeilToInt((Extent.Y - (VoxelExtent + DistanceFromCenter.Y)) / VoxelSize); + MaxOffsetInDirection[Front] = FMath::CeilToInt((Extent.X - (VoxelExtent + DistanceFromCenter.X)) / VoxelSize); + MaxOffsetInDirection[Right] = FMath::CeilToInt((Extent.Y - (VoxelExtent - DistanceFromCenter.Y)) / VoxelSize); + MaxOffsetInDirection[Behind] = FMath::CeilToInt((Extent.X - (VoxelExtent - DistanceFromCenter.X)) / VoxelSize); + MaxOffsetInDirection[Below] = FMath::CeilToInt((Extent.Z - (VoxelExtent + DistanceFromCenter.Z)) / VoxelSize); + MaxOffsetInDirection[Above] = FMath::CeilToInt((Extent.Z - (VoxelExtent - DistanceFromCenter.Z)) / VoxelSize); + + FVector Offset = FVector::ZeroVector; + for (int X = -MaxOffsetInDirection[Front]; X <= MaxOffsetInDirection[Behind]; X++) + { + Offset.X = X; + for (int Y = -MaxOffsetInDirection[Left]; Y <= MaxOffsetInDirection[Right]; Y++) + { + Offset.Y = Y; + for (int Z = -MaxOffsetInDirection[Below]; Z <= MaxOffsetInDirection[Above]; Z++) + { + Offset.Z = Z; + + FVector CurrXYZ = XYZ + Offset; + if (Volume->IsInBounds(CurrXYZ)) + { + Index = Volume->LocalCoordsInt3ToIndex(CurrXYZ); + Volume->TreesToRegenerate.insert(Index); + Volume->TreesToRegeneratePreviousUpdate.insert(Index); + } + } + } + } +} + +void UCPathDynamicObstacle::EndPlay(EEndPlayReason::Type Reason) +{ + Super::EndPlay(Reason); + Deactivate(); +} + + +void UCPathDynamicObstacle::BeginPlay() +{ + Super::BeginPlay(); + GetOwner()->OnActorBeginOverlap.AddDynamic(this, &UCPathDynamicObstacle::OnBeginOverlap); + GetOwner()->OnActorEndOverlap.AddDynamic(this, &UCPathDynamicObstacle::OnBeginOverlap); + if (ActivateOnBeginPlay) + { + Activate(); + } +} + + + +void UCPathDynamicObstacle::OnBeginOverlap(AActor* Owner, AActor* OtherActor) +{ + if (IsActive()) + { + ACPathVolume* Volume = Cast(OtherActor); + if (Volume) + { + Volume->TrackedDynamicObstacles.insert(this); + OverlappigVolumes.Add(Volume); + } + } +} + +void UCPathDynamicObstacle::OnEndOverlap(AActor* Owner, AActor* OtherActor) +{ + if (IsActive()) + { + ACPathVolume* Volume = Cast(OtherActor); + if (Volume) + { + Volume->TrackedDynamicObstacles.erase(this); + OverlappigVolumes.Remove(Volume); + } + } +} + diff --git a/Plugins/CPathfinding/Source/CPathfinding/Private/CPathFindPath.cpp b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathFindPath.cpp new file mode 100644 index 00000000..ac869439 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathFindPath.cpp @@ -0,0 +1,423 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +#include "CPathFindPath.h" +#include "CPathVolume.h" +#include +#include +#include +#include +#include +#include +#include "Algo/Reverse.h" +#include "TimerManager.h" +#include "Engine/World.h" + + +CPathAStar::CPathAStar() +{ +} + +CPathAStar::CPathAStar(ACPathVolume* VolumeRef, FVector Start, FVector End, uint32 SmoothingPasses, int32 UserData, float TimeLimit) + : + Volume(VolumeRef), + PathStart(Start), + PathEnd(End), + Smoothing(SmoothingPasses), + UsrData(UserData), + SearchTimeLimit(TimeLimit) +{ +} + +CPathAStar::~CPathAStar() +{ + +} + +CPathAStarNode* CPathAStar::FindPath(ACPathVolume* VolumeRef, FVector Start, FVector End, uint32 SmoothingPasses, int32 UserData, float TimeLimit, TArray* RawNodes) +{ + if (!IsValid(VolumeRef)) + { + FailReason = VolumeNotValid; + return nullptr; + } + if (!VolumeRef->InitialGenerationCompleteAtom.load()) + { + FailReason = VolumeNotGenerated; + return nullptr; + } + + Volume = VolumeRef; + SearchTimeLimit = TimeLimit; + UsrData = UserData; + auto TimeStart = TIMENOW; + + // time limit in miliseconds + double TimeLimitMS = SearchTimeLimit * 1000; + + // The A* priority queue + std::priority_queue, std::greater> Pq; + + // Nodes visited OR added to priority queue + std::unordered_set VisitedNodes; + + // In case someome called FindPath on the same AStar instance + ProcessedNodes.clear(); + + + // Finding start and end node + uint32 TempID; + if (!Volume->FindClosestFreeLeaf(Start, TempID)) + { + FailReason = WrongStartLocation; + return nullptr; + } + + CPathAStarNode StartNode(TempID); + StartNode.WorldLocation = Start; + + if (!Volume->FindClosestFreeLeaf(End, TempID)) + { + FailReason = WrongEndLocation; + return nullptr; + } + + // Initializing priority queue + CPathAStarNode TargetNode(TempID); + TargetLocation = Volume->WorldLocationFromTreeID(TargetNode.TreeID); + TargetNode.WorldLocation = TargetLocation; + CalcFitness(TargetNode); + CalcFitness(StartNode); + Pq.push(StartNode); + VisitedNodes.insert(StartNode); + CPathAStarNode* FoundPathEnd = nullptr; + + // A* loop + while (Pq.size() > 0 && !bStop) + { + CPathAStarNode CurrentNode = Pq.top(); + Pq.pop(); + ProcessedNodes.push_back(std::make_unique(CurrentNode)); + + if (CurrentNode == TargetNode) + { + FoundPathEnd = ProcessedNodes.back().get(); + break; + } + + std::vector Neighbours = VolumeRef->FindFreeNeighbourLeafs(CurrentNode); + for (CPathAStarNode NewTreeNode : Neighbours) + { + if (bStop) + break; + + if (!VisitedNodes.count(NewTreeNode)) + { + NewTreeNode.PreviousNode = ProcessedNodes.back().get(); + NewTreeNode.WorldLocation = Volume->WorldLocationFromTreeID(NewTreeNode.TreeID); + + // CalcFitness(NewNode); - this is inline and not virtual so in theory faster, but not extendable. + // Also from my testing, the speed difference between the two was unnoticeable at 150000 nodes processed. + + VolumeRef->CalcFitness(NewTreeNode, TargetLocation, UserData); + VisitedNodes.insert(NewTreeNode); + Pq.push(NewTreeNode); + } + } + + auto CurrDuration = TIMEDIFF(TimeStart, TIMENOW); + if (CurrDuration >= TimeLimitMS) + { + bStop = true; + FailReason = ECPathfindingFailReason::Timeout; + } + } + + // Pathfinidng has been interrupted due to premature thread kill, so we dont want to return an incomplete path + if (bStop) + { + if (FailReason != Timeout) + FailReason = UnknownFailure; + + return nullptr; + } + + + if (FoundPathEnd) + { + // Adding last node that exactly reflects user's requested location + uint32 LastTreeID; + if (Volume->FindLeafByWorldLocation(End, LastTreeID, false)) + { + ProcessedNodes.push_back(std::make_unique(CPathAStarNode(LastTreeID))); + ProcessedNodes.back()->WorldLocation = End; + ProcessedNodes.back()->PreviousNode = FoundPathEnd; + FoundPathEnd = ProcessedNodes.back().get(); + } + + // For debugging + if (RawNodes) + { + auto CurrNode = FoundPathEnd; + while (CurrNode) + { + RawNodes->Add(*CurrNode); + CurrNode = CurrNode->PreviousNode; + } + } + + // Post processing to remove unnecessary nodes + for (uint32 i = 0; i < SmoothingPasses; i++) + { + SmoothenPath(FoundPathEnd); + } + FailReason = None; + } + else + { + FailReason = EndLocationUnreachable; + } + +#ifdef LOG_PATHFINDERS + auto CurrDuration = TIMEDIFF(TimeStart, TIMENOW); + UE_LOG(LogTemp, Warning, TEXT("FindPath: time= %lfms NodesVisited= %d NodesProcessed= %d"), CurrDuration, VisitedNodes.size(), ProcessedNodes.size()); +#endif + + return FoundPathEnd; +} + +bool CPathAStar::FindPath() +{ + if (!IsValid(Volume)) + { + FailReason = VolumeNotValid; + return false; + } + + + RawPathNodes.Empty(); + UserPath.Empty(); + + auto FoundPathEnd = FindPath(Volume, PathStart, PathEnd, Smoothing, UsrData, SearchTimeLimit, &RawPathNodes); + + if (FoundPathEnd) + { + TransformToUserPath(FoundPathEnd, UserPath); + return true; + } + return false; +} + + +void CPathAStar::TransformToUserPath(CPathAStarNode* PathEndNode, TArray& InUserPath, bool bReverse) +{ + float Tolerance = FMath::Cos(FMath::DegreesToRadians(LineAngleToleranceDegrees)); + if (!PathEndNode) + return; + + CPathAStarNode* CurrNode = PathEndNode; + + // Initializing variables for loop + FVector Normal = CurrNode->WorldLocation - CurrNode->PreviousNode->WorldLocation; + Normal.Normalize(); + InUserPath.Add(FCPathNode(CurrNode->WorldLocation)); + + while (CurrNode->PreviousNode && CurrNode->PreviousNode->PreviousNode) + { + FVector NextNormal = CurrNode->PreviousNode->WorldLocation - CurrNode->PreviousNode->PreviousNode->WorldLocation; + NextNormal.Normalize(); + + + if (FVector::DotProduct(Normal, NextNormal) >= Tolerance) + { + CurrNode->PreviousNode = CurrNode->PreviousNode->PreviousNode; + Normal = CurrNode->WorldLocation - CurrNode->PreviousNode->WorldLocation; + Normal.Normalize(); + } + else + { + InUserPath.Add(FCPathNode(CurrNode->PreviousNode->WorldLocation)); + InUserPath.Last().Normal = Normal; + + CurrNode = CurrNode->PreviousNode; + Normal = NextNormal; + } + } + if (CurrNode->PreviousNode) + { + InUserPath.Add(FCPathNode(CurrNode->PreviousNode->WorldLocation)); + InUserPath.Last().Normal = Normal; + } + if (bReverse) + Algo::Reverse(InUserPath); + + +} + +float CPathAStar::EucDistance(CPathAStarNode& Node, FVector Target) const +{ + return FVector::Distance(Node.WorldLocation, Target); +} + +void CPathAStar::CalcFitness(CPathAStarNode& Node) +{ + if (Node.PreviousNode) + { + Node.DistanceSoFar = Node.PreviousNode->DistanceSoFar + EucDistance(*Node.PreviousNode, Node.WorldLocation); + } + Node.FitnessResult = Node.DistanceSoFar + 3.5f * EucDistance(Node, TargetLocation); +} + +inline bool CPathAStar::CanSkip(FVector Start, FVector End) +{ + FHitResult HitResult; + Volume->GetWorld()->SweepSingleByChannel(HitResult, Start, End, FQuat(FRotator(0, 0, 0)), Volume->TraceChannel, Volume->TraceShapesByDepth.back().back()); + + return !HitResult.bBlockingHit; +} + +void CPathAStar::SmoothenPath(CPathAStarNode* PathEndNode) +{ + if (!PathEndNode) + return; + CPathAStarNode* CurrNode = PathEndNode; + while (CurrNode->PreviousNode && CurrNode->PreviousNode->PreviousNode && !bStop) + { + if (CanSkip(CurrNode->WorldLocation, CurrNode->PreviousNode->PreviousNode->WorldLocation)) + { + CurrNode->PreviousNode = CurrNode->PreviousNode->PreviousNode; + } + + CurrNode = CurrNode->PreviousNode; + } +} + +UCPathAsyncFindPath* UCPathAsyncFindPath::FindPathAsync(ACPathVolume* Volume, FVector StartLocation, FVector EndLocation, int SmoothingPasses, int32 UserData, float TimeLimit) +{ +#if WITH_EDITOR + checkf(IsValid(Volume), TEXT("CPATH - FindPathAsync:::Volume was invalid")); +#endif + + UCPathAsyncFindPath* Instance = NewObject(); + Instance->RunnableFindPath = new FCPathRunnableFindPath(Instance); + Instance->AStar = new CPathAStar(Volume, StartLocation, EndLocation, SmoothingPasses, UserData, TimeLimit); + Instance->RegisterWithGameInstance(Volume->GetGameInstance()); + + return Instance; +} + +void UCPathAsyncFindPath::Activate() +{ + if (!IsValid(AStar->Volume)) + { + Failure.Broadcast(AStar->UserPath, TEnumAsByte(AStar->FailReason)); + SetReadyToDestroy(); + RemoveFromRoot(); + } + else + { + CurrentThread = FRunnableThread::Create(RunnableFindPath, TEXT("CPath Pathfinding Thread")); + AStar->Volume->GetWorld()->GetTimerManager().SetTimer(CheckThreadTimerHandle, this, &UCPathAsyncFindPath::CheckThreadStatus, 1.f / 30.f, true); + } +} + +void UCPathAsyncFindPath::BeginDestroy() +{ + Super::BeginDestroy(); + if (CurrentThread) + { + CurrentThread->Suspend(true); + if (RunnableFindPath && AStar) + { + AStar->bStop = true; + } + CurrentThread->Suspend(false); + CurrentThread->WaitForCompletion(); + CurrentThread->Kill(); + } + + delete AStar; + delete RunnableFindPath; +} + +void UCPathAsyncFindPath::CheckThreadStatus() +{ + if (ThreadResponse >= 0) + { + if (ThreadResponse == 1) + { + Success.Broadcast(AStar->UserPath, TEnumAsByte(AStar->FailReason)); + } + else + Failure.Broadcast(AStar->UserPath, TEnumAsByte(AStar->FailReason)); + + if (IsValid(AStar->Volume)) + { + AStar->Volume->GetWorld()->GetTimerManager().ClearTimer(CheckThreadTimerHandle); + } + + SetReadyToDestroy(); + RemoveFromRoot(); + } +} + + + +FCPathRunnableFindPath::FCPathRunnableFindPath(UCPathAsyncFindPath* AsyncNode) +{ + AsyncActionRef = AsyncNode; +} + +bool FCPathRunnableFindPath::Init() +{ + return true; +} + +uint32 FCPathRunnableFindPath::Run() +{ + // Waiting for the volume to finish generating + while ((AsyncActionRef->AStar->Volume->GeneratorsRunning.load() > 0 || !AsyncActionRef->AStar->Volume->InitialGenerationCompleteAtom.load()) && !AsyncActionRef->AStar->bStop) + { + std::this_thread::sleep_for(std::chrono::milliseconds(25)); + SleepCounter += 25; + + // Cancel request for path if idled for 5 seconds or more + if (SleepCounter >= 5000) + { + AsyncActionRef->AStar->FailReason = VolumeNotGenerated; + AsyncActionRef->ThreadResponse.store(0); + } + } + + // Preventing further generation while we search for a path + bIncreasedPathfRunning = true; + AsyncActionRef->AStar->Volume->PathfindersRunning++; + + auto FoundPath = AsyncActionRef->AStar->FindPath(); + if (FoundPath) + { + AsyncActionRef->ThreadResponse.store(1); + } + else + { + AsyncActionRef->ThreadResponse.store(0); + } + + if (bIncreasedPathfRunning) + AsyncActionRef->AStar->Volume->PathfindersRunning--; + bIncreasedPathfRunning = false; + return 0; +} + +void FCPathRunnableFindPath::Stop() +{ + // Preventing a potential deadlock if the process is killed without waiting + if (bIncreasedPathfRunning) + AsyncActionRef->AStar->Volume->PathfindersRunning--; + bIncreasedPathfRunning = false; + +} + +void FCPathRunnableFindPath::Exit() +{ + +} diff --git a/Plugins/CPathfinding/Source/CPathfinding/Private/CPathNode.cpp b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathNode.cpp new file mode 100644 index 00000000..4755bbcf --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathNode.cpp @@ -0,0 +1,11 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +#include "CPathNode.h" + +CPathAStarNode::CPathAStarNode() +{ +} + +CPathAStarNode::~CPathAStarNode() +{ +} diff --git a/Plugins/CPathfinding/Source/CPathfinding/Private/CPathOctree.cpp b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathOctree.cpp new file mode 100644 index 00000000..e41d0ac9 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathOctree.cpp @@ -0,0 +1,9 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +#include "CPathOctree.h" + +CPathOctree::CPathOctree() +{ +} + + diff --git a/Plugins/CPathfinding/Source/CPathfinding/Private/CPathVolume.cpp b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathVolume.cpp new file mode 100644 index 00000000..4f2fa262 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathVolume.cpp @@ -0,0 +1,1089 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +#include "CPathVolume.h" + +#include "DrawDebugHelpers.h" +#include "Components/BoxComponent.h" +#include +#include +#include +#include +#include "CPathDynamicObstacle.h" +#include "CPathNode.h" +#include "TimerManager.h" +#include "Engine/Selection.h" +#include "GenericPlatform/GenericPlatformAtomics.h" + + + + + +ACPathVolume::ACPathVolume() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + VolumeBox = CreateDefaultSubobject("VolumeBox"); + RootComponent = VolumeBox; + VolumeBox->InitBoxExtent(FVector(VoxelSize)); + +#if WITH_EDITOR + + +#endif + DepthsToDraw = { true, true, true, true }; + + + FVector Location = GetActorLocation() - VolumeBox->GetScaledBoxExtent() + VoxelSize; + DrawDebugBox(GetWorld(), Location, FVector(VoxelSize), FColor::White, true); + +} + +void ACPathVolume::DebugDrawNeighbours(FVector WorldLocation) +{ + uint32 LeafID; + if (FindLeafByWorldLocation(WorldLocation, LeafID)) + { + DrawDebugBox(GetWorld(), WorldLocationFromTreeID(LeafID), FVector(GetVoxelSizeByDepth(ExtractDepth(LeafID)) / 2.f), FColor::Emerald, false, 5, 10, DebugBoxesThickness*1.3); + auto Neighbours = FindNeighbourLeafs(LeafID, true); + + for (auto N : Neighbours) + { + DrawDebugBox(GetWorld(), WorldLocationFromTreeID(N), FVector(GetVoxelSizeByDepth(ExtractDepth(N)) / 2.f), FColor::Yellow, false, 5, 0U, DebugBoxesThickness*1.4); + } + } +} + +bool ACPathVolume::DrawDebugVoxel(uint32 TreeID, bool DrawIfNotLeaf, float Duration, FColor Color, CPathVoxelDrawData* OutDrawData) +{ + + uint32 Depth; + float Thickness = DebugBoxesThickness; + auto Tree = FindTreeByID(TreeID, Depth); + if (Tree->Children && !DrawIfNotLeaf) + return false; + bool IsFree = Tree->GetIsFree(); + if (IsFree) + { + if (!DrawFree) + return false; + } + else + { + if (!DrawOccupied) + return false; + if (Color == FColor::Green) + { + Color = FColor::Red; + Thickness *= 1.5; + } + } + + + bool Persistent = false; + if (Duration < 0) + Persistent = true; + + if (DepthsToDraw[Depth]) + { + float Extent = GetVoxelSizeByDepth(ExtractDepth(TreeID)) / 2.f; + FVector Location = WorldLocationFromTreeID(TreeID); + DrawDebugBox(GetWorld(), Location, FVector(Extent), Color, Persistent, Duration, 0U, Thickness); + if (OutDrawData) + { + OutDrawData->Extent = Extent; + OutDrawData->Free = IsFree; + OutDrawData->Location = Location; + } + + return true; + } + + return false; +} + +void ACPathVolume::DrawDebugVoxel(const CPathVoxelDrawData& DrawData, float Duration) const +{ + float Thickness = DebugBoxesThickness; + FColor Color = FColor::Green; + if (!DrawData.Free) + { + Color = FColor::Red; + Thickness *= 1.5; + } + + bool Persistent = false; + if (Duration < 0) + Persistent = true; + + DrawDebugBox(GetWorld(), DrawData.Location, FVector(DrawData.Extent), Color, Persistent, Duration, 0U, Thickness); +} + +void ACPathVolume::DrawDebugNodesAroundLocation(FVector WorldLocation, int VoxelLimit, float Duration) +{ + // We dont want to get new data while its generating + if (GeneratorsRunning.load()) + { + for (auto Data : PreviousDrawAroundLocationData) + { + DrawDebugVoxel(Data, Duration); + } + return; + } + PreviousDrawAroundLocationData.clear(); + + uint32 OriginTreeID = 0xFFFFFFFF; + CPathOctree* OriginTree = FindLeafByWorldLocation(WorldLocation, OriginTreeID, false); + if (!OriginTree) + return; + + std::list IndexList; + std::unordered_set VisitedIndexes; + + CPathAStarNode StartNode(OriginTreeID); + StartNode.FitnessResult = 0; + + + // Ordered by neighbours, first come first served + IndexList.push_back(StartNode.TreeID); + + + + while (!IndexList.empty() && VoxelLimit > 0) + { + uint32 CurrID = IndexList.front(); + IndexList.pop_front(); + CPathVoxelDrawData DrawData; + if (DrawDebugVoxel(CurrID, true, Duration, FColor::Green, &DrawData)) + { + VoxelLimit--; + PreviousDrawAroundLocationData.push_back(DrawData); + } + + + std::vector Neighbours = FindNeighbourLeafs(CurrID, !DrawOccupied); + for (uint32 NewTreeID : Neighbours) + { + + // We dont want to redraw nodes + if (!VisitedIndexes.count(NewTreeID)) + { + IndexList.push_back(NewTreeID); + VisitedIndexes.insert(NewTreeID); + } + } + } +} + +void ACPathVolume::DrawDebugPath(const TArray& Path, float Duration, bool DrawPoints, FColor Color) +{ + bool Persistent = Duration < 0; + for (int i = 0; i < Path.Num() - 1; i++) + { + DrawDebugLine(GetWorld(), Path[i].WorldLocation, Path[i + 1].WorldLocation, Color, Persistent, Duration, 0U, DebugPathThickness); + if (DrawPoints) + DrawDebugPoint(GetWorld(), Path[i].WorldLocation, 10, FColor::Cyan, Persistent, Duration); + } +} + + +void ACPathVolume::BeginPlay() +{ + Super::BeginPlay(); + + VolumeBox->SetCollisionResponseToChannel(TraceChannel, ECR_Ignore); + + if (GenerateOnBeginPlay) + GenerateGraph(); +} + +bool ACPathVolume::GenerateGraph() +{ + GenerationStarted = true; + PrintGenerationTime = true; + + UBoxComponent* tempBox = Cast(GetRootComponent()); + tempBox->UpdateOverlaps(); + + + float Divider = VoxelSize * FMath::Pow(2.f, OctreeDepth); + + NodeCount[0] = FMath::CeilToInt(VolumeBox->GetScaledBoxExtent().X * 2.0 / Divider); + NodeCount[1] = FMath::CeilToInt(VolumeBox->GetScaledBoxExtent().Y * 2.0 / Divider); + NodeCount[2] = FMath::CeilToInt(VolumeBox->GetScaledBoxExtent().Z * 2.0 / Divider); + + checkf(OctreeDepth <= MAX_DEPTH && OctreeDepth >= 0, TEXT("CPATH - Graph Generation:::OctreeDepth must be within 0 and MAX_DEPTH")); + //checkf(AgentShape == ECollisionShapeType::Capsule || AgentShape == ECollisionShapeType::Sphere || AgentShape == ECollisionShapeType::Box, TEXT("CPATH - Graph Generation:::Agent shape must be Capsule, Sphere or Box")); + + + for (int i = 0; i <= OctreeDepth; i++) + { + + LookupTable_VoxelSizeByDepth[i] = VoxelSize * FMath::Pow(2.f, OctreeDepth - i); + TraceShapesByDepth.emplace_back(); + TraceShapesByDepth.back().push_back(FCollisionShape::MakeBox(FVector(GetVoxelSizeByDepth(i) / 2.f))); + + float CurrSize = GetVoxelSizeByDepth(i); + if (AgentRadius * 2 > CurrSize || AgentHalfHeight * 2 > CurrSize) + { + switch (AgentShape) + { + case Capsule: + TraceShapesByDepth.back().push_back(FCollisionShape::MakeCapsule(AgentRadius, AgentHalfHeight)); + case Box: + TraceShapesByDepth.back().push_back(FCollisionShape::MakeBox(FVector(AgentRadius, AgentRadius, AgentHalfHeight))); + case Sphere: + TraceShapesByDepth.back().push_back(FCollisionShape::MakeSphere(AgentRadius)); + default: + break; + } + } + } + + StartPosition = GetActorLocation() - VolumeBox->GetScaledBoxExtent() + GetVoxelSizeByDepth(0) / 2; + + uint32 OuterNodeCount = NodeCount[0] * NodeCount[1] * NodeCount[2]; + checkf(OuterNodeCount < DEPTH_0_LIMIT, TEXT("CPATH - Graph Generation:::Depth 0 is too dense, increase OctreeDepth and/or voxel size, or decrease volume area.")); + Octrees = new CPathOctree[OuterNodeCount]; + + // If we use all logical threads in the system, the rest of the game + // will have no computing power to work with. From my small test sample + // Using hyper threads barely increased performance so its not worth it + /*if (FPlatformMisc::NumberOfCoresIncludingHyperthreads() > FPlatformMisc::NumberOfCores()) + ThreadCount = FPlatformMisc::NumberOfCores() + (FPlatformMisc::NumberOfCoresIncludingHyperthreads() - FPlatformMisc::NumberOfCores()) / 3; + else + ThreadCount = FPlatformMisc::NumberOfCores() - 1;*/ + if (MaxGenerationThreads <= 0) + MaxGenerationThreads = FPlatformMisc::NumberOfCores() - 1; + + MaxGenerationThreads = FMath::Min(MaxGenerationThreads, 31); + + uint32 NodesPerThread = OuterNodeCount / MaxGenerationThreads; + + for (int i = 0; i < 64; i++) + { + ThreadIDs[1] = false; + } + + + for (int CurrentThread = 0; CurrentThread < MaxGenerationThreads; CurrentThread++) + { + uint32 LastIndex = NodesPerThread * (CurrentThread + 1); + if (CurrentThread == MaxGenerationThreads - 1) + LastIndex += OuterNodeCount % MaxGenerationThreads; + + int ThreadID = GetFreeThreadID(); + FString ThreadName = "CPathGenerator Initial, ID: "; + ThreadName.AppendInt(ThreadID); + GeneratorThreads.push_back(std::make_unique(this, NodesPerThread * CurrentThread, LastIndex, ThreadID, ThreadName)); + GeneratorThreads.back()->ThreadRef = FRunnableThread::Create(GeneratorThreads.back().get(), *ThreadName); + if (GeneratorThreads.back()->ThreadRef) + { + ThreadIDs[ThreadID] = true; + } + else + { + GeneratorThreads.pop_back(); + } + + } + OuterIndexesPerThread = 5 * (5 + OctreeDepth) * FMath::Pow(8.f, MAX_DEPTH - OctreeDepth); + // Setting timer for dynamic generation and garbage collection + GetWorld()->GetTimerManager().SetTimer(GenerationTimerHandle, this, &ACPathVolume::InitialGenerationUpdate, 1.f / 60.f, true); + return true; +} + +void ACPathVolume::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ACPathVolume::BeginDestroy() +{ + Super::BeginDestroy(); + + GeneratorThreads.clear(); + delete[] Octrees; +} + + +inline FVector ACPathVolume::WorldLocationToLocalCoordsInt3(FVector WorldLocation) const +{ + FVector RelativePos = WorldLocation - StartPosition; + RelativePos = RelativePos / GetVoxelSizeByDepth(0); + return FVector(FMath::RoundToFloat(RelativePos.X), + FMath::RoundToFloat(RelativePos.Y), + FMath::RoundToFloat(RelativePos.Z)); + +} + +inline int ACPathVolume::WorldLocationToIndex(FVector WorldLocation) const +{ + FVector XYZ = WorldLocationToLocalCoordsInt3(WorldLocation); + return LocalCoordsInt3ToIndex(XYZ); +} + +inline bool ACPathVolume::IsInBounds(FVector XYZ) const +{ + if (XYZ.X < 0 || XYZ.X >= NodeCount[0]) + return false; + + if (XYZ.Y < 0 || XYZ.Y >= NodeCount[1]) + return false; + + if (XYZ.Z < 0 || XYZ.Z >= NodeCount[2]) + return false; + + return true; +} + +inline float ACPathVolume::LocalCoordsInt3ToIndex(FVector V) const +{ + return (V.X * (NodeCount[1] * NodeCount[2])) + (V.Y * NodeCount[2]) + V.Z; +} + +inline float ACPathVolume::GetVoxelSizeByDepth(int Depth) const +{ +#if WITH_EDITOR + checkf(Depth <= OctreeDepth, TEXT("CPATH - Graph Generation:::DEPTH was higher than OctreeDepth")); +#endif + + return LookupTable_VoxelSizeByDepth[Depth]; +} + +inline uint32 ACPathVolume::CreateTreeID(uint32 Index, uint32 Depth) const +{ +#if WITH_EDITOR + checkf(Depth <= MAX_DEPTH, TEXT("CPATH - Graph Generation:::DEPTH can be up to MAX_DEPTH")); +#endif + Index |= Depth << DEPTH_0_BITS; + + return Index; +} + +inline uint32 ACPathVolume::ExtractOuterIndex(uint32 TreeID) const +{ + return TreeID & DEPTH_0_MASK; +} + +inline void ACPathVolume::ReplaceDepth(uint32& TreeID, uint32 NewDepth) +{ +#if WITH_EDITOR + checkf(NewDepth <= MAX_DEPTH, TEXT("CPATH - Graph Generation:::DEPTH can be up to MAX_DEPTH")); +#endif + + TreeID &= ~DEPTH_MASK; + TreeID |= NewDepth << DEPTH_0_BITS; +} + +inline uint32 ACPathVolume::ExtractDepth(uint32 TreeID) const +{ + return (TreeID & DEPTH_MASK) >> DEPTH_0_BITS; +} + +inline uint32 ACPathVolume::ExtractChildIndex(uint32 TreeID, uint32 Depth) const +{ +#if WITH_EDITOR + checkf(Depth <= MAX_DEPTH && Depth > 0, TEXT("CPATH - Graph Generation:::DEPTH can be up to MAX_DEPTH")); +#endif + uint32 DepthOffset = (Depth - 1) * 3 + DEPTH_0_BITS + 2; + uint32 Mask = 0x00000007 << DepthOffset; + + return (TreeID & Mask) >> DepthOffset; +} + +inline void ACPathVolume::AddChildIndex(uint32& TreeID, uint32 Depth, uint32 ChildIndex) +{ +#if WITH_EDITOR + checkf(Depth <= MAX_DEPTH && Depth > 0, TEXT("CPATH - Graph Generation:::DEPTH can be up to MAX_DEPTH")); + checkf(ChildIndex < 8, TEXT("CPATH - Graph Generation:::Child Index can be up to 7")); +#endif + + ChildIndex <<= (Depth - 1) * 3 + DEPTH_0_BITS + 2; + + TreeID |= ChildIndex; +} + +inline FVector ACPathVolume::WorldLocationFromTreeID(uint32 TreeID) const +{ + uint32 OuterIndex = ExtractOuterIndex(TreeID); + uint32 Depth = ExtractDepth(TreeID); + + FVector CurrPosition = StartPosition + GetVoxelSizeByDepth(0) * LocalCoordsInt3FromOuterIndex(OuterIndex); + + for (uint32 CurrDepth = 1; CurrDepth <= Depth; CurrDepth++) + { + CurrPosition += GetVoxelSizeByDepth(CurrDepth) * 0.5f * LookupTable_ChildPositionOffsetMaskByIndex[ExtractChildIndex(TreeID, CurrDepth)]; + } + + return CurrPosition; +} + +inline FVector ACPathVolume::LocalCoordsInt3FromOuterIndex(uint32 OuterIndex) const +{ + uint32 X = OuterIndex / (NodeCount[1] * NodeCount[2]); + OuterIndex -= X * NodeCount[1] * NodeCount[2]; + return FVector(X, OuterIndex / NodeCount[2], OuterIndex % NodeCount[2]); +} + +inline void ACPathVolume::ReplaceChildIndex(uint32& TreeID, uint32 Depth, uint32 ChildIndex) +{ +#if WITH_EDITOR + checkf(Depth <= MAX_DEPTH && Depth > 0, TEXT("CPATH - Graph Generation:::DEPTH can be up to MAX_DEPTH")); + checkf(ChildIndex < 8, TEXT("CPATH - Graph Generation:::Child Index can be up to 7")); +#endif + + uint32 DepthOffset = (Depth - 1) * 3 + DEPTH_0_BITS + 2; + + // Clearing previous child index + TreeID &= ~(0x00000007 << DepthOffset); + + ChildIndex <<= DepthOffset; + TreeID |= ChildIndex; +} + +inline void ACPathVolume::ReplaceChildIndexAndDepth(uint32& TreeID, uint32 Depth, uint32 ChildIndex) +{ +#if WITH_EDITOR + checkf(Depth <= MAX_DEPTH && Depth > 0, TEXT("CPATH - Graph Generation:::DEPTH can be up to MAX_DEPTH")); + checkf(ChildIndex < 8, TEXT("CPATH - Graph Generation:::Child Index can be up to 7")); +#endif + + uint32 DepthOffset = (Depth - 1) * 3 + DEPTH_0_BITS + 2; + + // Clearing previous child index + TreeID &= ~(0x00000007 << DepthOffset); + + ChildIndex <<= DepthOffset; + TreeID |= ChildIndex; + ReplaceDepth(TreeID, Depth); +} + +inline void ACPathVolume::GetAllSubtrees(uint32 TreeID, std::vector& Container) +{ + uint32 Depth = 0; + CPathOctree* Tree = FindTreeByID(TreeID, Depth); + GetAllSubtreesRec(TreeID, Tree, Container, Depth); +} + +void ACPathVolume::GetAllSubtreesRec(uint32 TreeID, CPathOctree* Tree, std::vector& Container, uint32 Depth) +{ + if (Tree->Children) + { + Depth++; + for (uint32 ChildID = 0; ChildID < 8; ChildID++) + { + uint32 ID = TreeID; + ReplaceChildIndexAndDepth(ID, Depth, ChildID); + GetAllSubtreesRec(ID, &Tree->Children[ChildID], Container, Depth); + Container.push_back(ID); + } + } +} + +inline CPathOctree* ACPathVolume::FindTreeByID(uint32 TreeID) +{ + uint32 Depth = ExtractDepth(TreeID); + CPathOctree* CurrTree = &Octrees[ExtractOuterIndex(TreeID)]; + + + for (uint32 CurrDepth = 1; CurrDepth <= Depth; CurrDepth++) + { + // Child not found, returning the deepest found parent + if (!CurrTree->Children) + { + break; + } + + CurrTree = &CurrTree->Children[ExtractChildIndex(TreeID, CurrDepth)]; + } + return CurrTree; +} + +CPathOctree* ACPathVolume::FindTreeByID(uint32 TreeID, uint32& DepthReached) +{ + uint32 Depth = ExtractDepth(TreeID); + CPathOctree* CurrTree = &Octrees[ExtractOuterIndex(TreeID)]; + DepthReached = 0; + + for (uint32 CurrDepth = 1; CurrDepth <= Depth; CurrDepth++) + { + // Child not found, returning the deepest found parent + if (!CurrTree->Children) + { + break; + } + + CurrTree = &CurrTree->Children[ExtractChildIndex(TreeID, CurrDepth)]; + DepthReached = CurrDepth; + } + return CurrTree; +} + +CPathOctree* ACPathVolume::FindTreeByWorldLocation(FVector WorldLocation, uint32& TreeID) +{ + FVector LocalCoords = WorldLocationToLocalCoordsInt3(WorldLocation); + if (!IsInBounds(LocalCoords)) + return nullptr; + + TreeID = LocalCoordsInt3ToIndex(LocalCoords); + return &Octrees[TreeID]; +} + +inline CPathOctree* ACPathVolume::FindLeafByWorldLocation(FVector WorldLocation, uint32& TreeID, bool MustBeFree) +{ + CPathOctree* CurrentTree = FindTreeByWorldLocation(WorldLocation, TreeID); + CPathOctree* FoundLeaf = nullptr; + if (CurrentTree) + { + FVector RelativeLocation = WorldLocation - GetOuterTreeWorldLocation(TreeID); + + if (CurrentTree->Children) + FoundLeaf = FindLeafRecursive(RelativeLocation, TreeID, 0, CurrentTree); + else + FoundLeaf = CurrentTree; + } + + // Checking if the found leaf is free, and if not returning its free neighbour + if (MustBeFree && FoundLeaf && !FoundLeaf->GetIsFree()) + { + /*CurrentTree = GetParentTree(TreeID); + if (CurrentTree) + { + for (int i = 0; i < 8; i++) + { + if (CurrentTree->Children[i].GetIsFree()) + FoundLeaf = &CurrentTree->Children[i]; + } + } + + if(!FoundLeaf->GetIsFree())*/ + FoundLeaf = nullptr; + } + + return FoundLeaf; +} + +CPathOctree* ACPathVolume::FindClosestFreeLeaf(FVector WorldLocation, uint32& TreeID, float SearchRange) +{ + uint32 OriginTreeID = 0xFFFFFFFF; + CPathOctree* OriginTree = FindLeafByWorldLocation(WorldLocation, OriginTreeID, false); + if (!OriginTree) + return nullptr; + + if (OriginTree->GetIsFree()) + { + TreeID = OriginTreeID; + return OriginTree; + } + + if (SearchRange <= 0) + { + uint32 Depth = FMath::Max((uint32)1, ExtractDepth(OriginTreeID) - 1); + Depth = FMath::Min(Depth, (uint32)OctreeDepth); + SearchRange = GetVoxelSizeByDepth(Depth); + } + + // Nodes visited OR added to priority queue + std::unordered_set VisitedNodes; + + std::priority_queue, std::greater> Pq; + std::priority_queue, std::greater> PqNeighbours; + + + CPathAStarNode StartNode(OriginTreeID); + StartNode.FitnessResult = 0; + VisitedNodes.insert(StartNode); + + // STEP 1 - considering StartNode neighbours only, we dont check range cause neighbours take priority + // (its faster and solves almost all cases without needing to go to the other queue) + + std::vector StartNeighbours = FindFreeNeighbourLeafs(StartNode); + for (CPathAStarNode NewNode : StartNeighbours) + { + NewNode.WorldLocation = WorldLocationFromTreeID(NewNode.TreeID); + + // Fitness function here is distance from WorldLocation - The voxel extent, cause we want distance to the border of the voxel, not to it's center + NewNode.FitnessResult = FVector::Distance(NewNode.WorldLocation, WorldLocation) - GetVoxelSizeByDepth(ExtractDepth(NewNode.TreeID)) / 2.f; + + VisitedNodes.insert(NewNode); + PqNeighbours.push(NewNode); + } + + while (PqNeighbours.size() > 0) + { + CPathAStarNode CurrentNode = PqNeighbours.top(); + PqNeighbours.pop(); + CPathOctree* Tree = FindTreeByID(CurrentNode.TreeID); + if (Tree->GetIsFree()) + { + if (!GetWorld()->LineTraceTestByChannel(WorldLocation, CurrentNode.WorldLocation, TraceChannel)) + { + TreeID = CurrentNode.TreeID; + //DrawDebugLine(GetWorld(), WorldLocation, CurrentNode.WorldLocation, FColor::Green, false, 1); + return Tree; + } + //DrawDebugLine(GetWorld(), WorldLocation, CurrentNode.WorldLocation, FColor::Red, false, 1); + } + + std::vector Neighbours = FindFreeNeighbourLeafs(CurrentNode); + for (CPathAStarNode NewNode : Neighbours) + { + // We dont want to revisit nodes + if (!VisitedNodes.count(NewNode)) + { + NewNode.WorldLocation = WorldLocationFromTreeID(NewNode.TreeID); + // Fitness function here is distance from WorldLocation - The voxel extent, cause we want distance to the border of the voxel, not to it's center + NewNode.FitnessResult = FVector::Distance(NewNode.WorldLocation, WorldLocation) - GetVoxelSizeByDepth(ExtractDepth(NewNode.TreeID)) / 2.f; + + VisitedNodes.insert(NewNode); + // Search range condition + if (NewNode.FitnessResult <= SearchRange) + { + Pq.push(NewNode); + } + } + } + } + + // STEP 2 - If no neighbour was free, we're looking for the closest node in range + // We're putting neighbouring nodes as long as they are in SearchRange, until we find one that is free. + // Priority queue ensures that we find the closest node to the given WorldLocation. + while (Pq.size() > 0) + { + CPathAStarNode CurrentNode = Pq.top(); + Pq.pop(); + CPathOctree* Tree = FindTreeByID(CurrentNode.TreeID); + if (Tree->GetIsFree()) + { + if (!GetWorld()->LineTraceTestByChannel(WorldLocation, CurrentNode.WorldLocation, TraceChannel)) + { + TreeID = CurrentNode.TreeID; + //DrawDebugLine(GetWorld(), WorldLocation, CurrentNode.WorldLocation, FColor::Green, false, 1); + return Tree; + } + //DrawDebugLine(GetWorld(), WorldLocation, CurrentNode.WorldLocation, FColor::Red, false, 1); + } + + std::vector Neighbours = FindFreeNeighbourLeafs(CurrentNode); + + for (CPathAStarNode NewNode : Neighbours) + { + // We dont want to revisit nodes + if (!VisitedNodes.count(NewNode)) + { + NewNode.WorldLocation = WorldLocationFromTreeID(NewNode.TreeID); + // Fitness function here is distance from WorldLocation - The voxel extent, cause we want distance to the border of the voxel, not to it's center + NewNode.FitnessResult = FVector::Distance(NewNode.WorldLocation, WorldLocation) - GetVoxelSizeByDepth(ExtractDepth(NewNode.TreeID)) / 2.f; + + VisitedNodes.insert(NewNode); + // Search range condition + if (NewNode.FitnessResult <= SearchRange) + { + Pq.push(NewNode); + } + } + } + } + return nullptr; +} + +CPathOctree* ACPathVolume::FindLeafRecursive(FVector RelativeLocation, uint32& TreeID, uint32 CurrentDepth, CPathOctree* CurrentTree) +{ + CurrentDepth += 1; + + // Determining which child the RelativeLocation is in + uint32 ChildIndex = 0; + if (RelativeLocation.X > 0.f) + ChildIndex += 4; + if (RelativeLocation.Z > 0.f) + ChildIndex += 2; + if (RelativeLocation.Y > 0.f) + ChildIndex += 1; + + + ReplaceChildIndex(TreeID, CurrentDepth, ChildIndex); + + CPathOctree* ChildTree = &CurrentTree->Children[ChildIndex]; + if (ChildTree->Children) + { + RelativeLocation = RelativeLocation - (LookupTable_ChildPositionOffsetMaskByIndex[ChildIndex] * (GetVoxelSizeByDepth(CurrentDepth) / 2.f)); + return FindLeafRecursive(RelativeLocation, TreeID, CurrentDepth, ChildTree); + } + ReplaceDepth(TreeID, CurrentDepth); + return ChildTree; +} + +FVector ACPathVolume::GetOuterTreeWorldLocation(uint32 TreeID) const +{ + FVector LocalCoords = LocalCoordsInt3FromOuterIndex(ExtractOuterIndex(TreeID)); + LocalCoords *= GetVoxelSizeByDepth(0); + return StartPosition + LocalCoords; +} + +inline CPathOctree* ACPathVolume::GetParentTree(uint32 TreeId) +{ + uint32 Depth = ExtractDepth(TreeId); + if (Depth) + { + ReplaceDepth(TreeId, Depth - 1); + return FindTreeByID(TreeId, Depth); + } + return nullptr; +} + + + +CPathOctree* ACPathVolume::FindNeighbourByID(uint32 TreeID, ENeighbourDirection Direction, uint32& NeighbourID) +{ + + // Depth 0, getting neighbour from Octrees + uint32 Depth = ExtractDepth(TreeID); + if (Depth == 0) + { + int OuterIndex = ExtractOuterIndex(TreeID); + FVector NeighbourLocalCoords = LocalCoordsInt3FromOuterIndex(OuterIndex) + LookupTable_NeighbourOffsetByDirection[Direction]; + + if (!IsInBounds(NeighbourLocalCoords)) + return nullptr; + + NeighbourID = LocalCoordsInt3ToIndex(NeighbourLocalCoords); + return &Octrees[NeighbourID]; + } + + uint8 ChildIndex = ExtractChildIndex(TreeID, Depth); + int8 NeighbourChildIndex = LookupTable_NeighbourChildIndex[ChildIndex][Direction]; + + // The neighbour a is child of the same octree + if (NeighbourChildIndex >= 0) + { + NeighbourID = TreeID; + ReplaceChildIndex(NeighbourID, Depth, NeighbourChildIndex); + CPathOctree* Neighbour = FindTreeByID(NeighbourID, Depth); + ReplaceDepth(NeighbourID, Depth); + return Neighbour; + } + else + { // Getting the neighbour of parent Octree and then its correct child + ReplaceDepth(TreeID, Depth - 1); + CPathOctree* NeighbourOfParent = FindNeighbourByID(TreeID, Direction, NeighbourID); + if (NeighbourOfParent) + { + if (NeighbourOfParent->Children) + { + // Look at the description of LookupTable_NeighbourChildIndex + NeighbourChildIndex = -1 * NeighbourChildIndex - 1; + ReplaceDepth(NeighbourID, Depth); + ReplaceChildIndex(NeighbourID, Depth, NeighbourChildIndex); + return &NeighbourOfParent->Children[NeighbourChildIndex]; + } + else + { + // NeighbourID is already correct from calling FindNeighbourByID + return NeighbourOfParent; + } + } + } + + return nullptr; +} + +std::vector ACPathVolume::FindNeighbourLeafs(uint32 TreeID, bool MustBeFree) +{ + std::vector FreeNeighbours; + + for (int Direction = 0; Direction < 6; Direction++) + { + uint32 NeighbourID = 0; + CPathOctree* Neighbour = FindNeighbourByID(TreeID, (ENeighbourDirection)Direction, NeighbourID); + if (Neighbour) + { + if (Neighbour->GetIsFree()) + FreeNeighbours.push_back(NeighbourID); + else if (Neighbour->Children) + { + FindLeafsOnSide(Neighbour, NeighbourID, (ENeighbourDirection)LookupTable_OppositeSide[Direction], &FreeNeighbours, MustBeFree); + } + else if(!MustBeFree) + FreeNeighbours.push_back(NeighbourID); + } + } + + return FreeNeighbours; +} + +std::vector ACPathVolume::FindFreeNeighbourLeafs(CPathAStarNode& Node) +{ + std::vector FreeNeighbours; + + for (int Direction = 0; Direction < 6; Direction++) + { + uint32 NeighbourID = 0; + CPathOctree* Neighbour = FindNeighbourByID(Node.TreeID, (ENeighbourDirection)Direction, NeighbourID); + if (Neighbour) + { + if (Neighbour->GetIsFree()) + FreeNeighbours.push_back(CPathAStarNode(NeighbourID, Neighbour->Data)); + else if (Neighbour->Children) + { + FindLeafsOnSide(Neighbour, NeighbourID, (ENeighbourDirection)LookupTable_OppositeSide[Direction], &FreeNeighbours); + } + } + } + + + return FreeNeighbours; +} + + +void ACPathVolume::FindLeafsOnSide(uint32 TreeID, ENeighbourDirection Side, std::vector* Vector, bool MustBeFree) +{ + uint32 TempDepthReached; + FindLeafsOnSide(FindTreeByID(TreeID, TempDepthReached), TreeID, Side, Vector, MustBeFree); +} + +void ACPathVolume::FindLeafsOnSide(CPathOctree* Tree, uint32 TreeID, ENeighbourDirection Side, std::vector* Vector, bool MustBeFree) +{ +#if WITH_EDITOR + checkf(Tree->Children, TEXT("CPATH - FindAllLeafsOnSide, requested tree has no children")); +#endif + uint8 NewDepth = ExtractDepth(TreeID) + 1; + for (uint8 i = 0; i < 4; i++) + { + uint8 ChildIndex = LookupTable_ChildrenOnSide[Side][i]; + CPathOctree* Child = &Tree->Children[ChildIndex]; + uint32 ChildTreeID = TreeID; + ReplaceChildIndexAndDepth(ChildTreeID, NewDepth, ChildIndex); + if (Child->Children) + FindLeafsOnSide(Child, ChildTreeID, Side, Vector); + else + { + if (Child->GetIsFree() || !MustBeFree) + Vector->push_back(ChildTreeID); + } + } +} + +void ACPathVolume::FindLeafsOnSide(CPathOctree* Tree, uint32 TreeID, ENeighbourDirection Side, std::vector* Vector, bool MustBeFree) +{ +#if WITH_EDITOR + checkf(Tree->Children, TEXT("CPATH - FindAllLeafsOnSide, requested tree has no children")); +#endif + uint8 NewDepth = ExtractDepth(TreeID) + 1; + for (uint8 i = 0; i < 4; i++) + { + uint8 ChildIndex = LookupTable_ChildrenOnSide[Side][i]; + CPathOctree* Child = &Tree->Children[ChildIndex]; + uint32 ChildTreeID = TreeID; + ReplaceChildIndexAndDepth(ChildTreeID, NewDepth, ChildIndex); + if (Child->Children) + FindLeafsOnSide(Child, ChildTreeID, Side, Vector); + else + { + if (Child->GetIsFree() || !MustBeFree) + Vector->push_back(CPathAStarNode(ChildTreeID, Child->Data)); + } + } +} + + + +inline uint32 ACPathVolume::GetFreeThreadID() const +{ + for (int ID = 0; ID < 64; ID++) + { + if (!ThreadIDs[ID]) + return ID; + } + + // This will never return as max number of generation threads is always less than 64 + return 0; +} + +void ACPathVolume::CleanFinishedGenerators() +{ + for (auto Generator = GeneratorThreads.begin(); Generator != GeneratorThreads.end(); Generator++) + { + ThreadIDs[(*Generator)->GenThreadID] = false; + if (!(*Generator)->ThreadRef) + { + Generator = GeneratorThreads.erase(Generator); + } + } + +} + +void ACPathVolume::InitialGenerationUpdate() +{ + if (GeneratorsRunning.load() <= 0) + { + InitialGenerationCompleteAtom.store(true); + InitialGenerationFinished = true; + + for (auto Generator = GeneratorThreads.begin(); Generator != GeneratorThreads.end(); Generator++) + { + for (int Depth = 0; Depth <= OctreeDepth; Depth++) + { + OctreeCountAtDepth[Depth] += Generator->get()->OctreeCountAtDepth[Depth]; + + } + } + for (int Depth = 0; Depth <= OctreeDepth; Depth++) + { + TotalNodeCount += OctreeCountAtDepth[Depth]; + } + + + CleanFinishedGenerators(); + GetWorld()->GetTimerManager().ClearTimer(GenerationTimerHandle); + if (DynamicObstaclesUpdateRate > 0) + GetWorld()->GetTimerManager().SetTimer(GenerationTimerHandle, this, &ACPathVolume::GenerationUpdate, 1.f / DynamicObstaclesUpdateRate, true); + } + +} + +void ACPathVolume::GenerationUpdate() +{ +#if WITH_EDITOR + checkf(GeneratorsRunning.load() >= 0, TEXT("CPATH - Graph Generation:::GenerationUpdate - GeneratorsRunning was negative!!!!!")); +#endif + // Garbage collecting generators that finished their job + CleanFinishedGenerators(); + + + + // We skip this update if generation from previous update is still running + // This can be the cause if we set DynamicObstaclesUpdateRate too high, or when it's initial generation, + // or if there were a lot of pathfinding requests and generators are waiting for them to finish. + if (GeneratorsRunning.load() == 0 && TrackedDynamicObstacles.size()) + { + + //Drawing previously updated trees + /*for (auto TreeID : TreesToRegenerate) + { + std::vector Subtrees; + Subtrees.push_back(TreeID); + GetAllSubtrees(TreeID, Subtrees); + for (auto SubID : Subtrees) + { + DrawDebugVoxel(SubID, false, 1.f / DynamicObstaclesUpdateRate); + } + }*/ + + // Adding indexes from previous update + TreesToRegenerate = TreesToRegeneratePreviousUpdate; + TreesToRegeneratePreviousUpdate.clear(); + + // Adding new indexes + for (auto Obstacle : TrackedDynamicObstacles) + { + if (IsValid(Obstacle)) + { + Obstacle->AddIndexesToUpdate(this); + } + } + + // Creating threads + // In case there is a lot of trees to update, we split the work into multiple threads to make it faster + if (TreesToRegenerate.size()) + { + + uint32 ThreadCount = FMath::Min(FMath::Min(FPlatformMisc::NumberOfCores(), (int)TreesToRegenerate.size() / OuterIndexesPerThread), MaxGenerationThreads); + ThreadCount = FMath::Max(ThreadCount, (uint32)1); + uint32 NodesPerThread = (uint32)TreesToRegenerate.size() / ThreadCount; + + // Starting generation + for (uint32 CurrentThread = 0; CurrentThread < ThreadCount; CurrentThread++) + { + uint32 LastIndex = NodesPerThread * (CurrentThread + 1); + if (CurrentThread == ThreadCount - 1) + LastIndex += TreesToRegenerate.size() % ThreadCount; + + int ThreadID = GetFreeThreadID(); + FString ThreadName = "CPathGenerator Dynamic, ID: "; + ThreadName.AppendInt(ThreadID); + GeneratorThreads.push_back(std::make_unique(this, NodesPerThread * CurrentThread, LastIndex, ThreadID, ThreadName, true)); + GeneratorThreads.back()->ThreadRef = FRunnableThread::Create(GeneratorThreads.back().get(), *ThreadName); + if (GeneratorThreads.back()->ThreadRef) + { + ThreadIDs[ThreadID] = true; + } + else + { + GeneratorThreads.pop_back(); + } + } + //UE_LOG(LogTemp, Warning, TEXT("GENERATION UPDATE Tracked - %d, Indexes - %d, Threads - %d"), TrackedDynamicObstacles.size(), TreesToRegenerate.size(), ThreadCount); + } + } +} + +void ACPathVolume::CalcFitness(CPathAStarNode& Node, FVector TargetLocation, int32 UserData) +{ + // Standard weithted A* Heuristic, f(n) = g(n) + e*h(n). (e = 3.5f) + if (Node.PreviousNode) + { + Node.DistanceSoFar = Node.PreviousNode->DistanceSoFar + FVector::Distance(Node.PreviousNode->WorldLocation, Node.WorldLocation); + } + Node.FitnessResult = Node.DistanceSoFar + 3.5f * FVector::Distance(Node.WorldLocation, TargetLocation); +} + +bool ACPathVolume::RecheckOctreeAtDepth(CPathOctree* OctreeRef, FVector TreeLocation, uint32 Depth) +{ + bool IsFree = true; + for (auto Shape : TraceShapesByDepth[Depth]) + { + if (GetWorld()->OverlapAnyTestByChannel(TreeLocation, FQuat(FRotator(0)), TraceChannel, Shape)) + { + IsFree = false; + break; + } + } + + // This is mandatory, as AStar only considers nodes that are free. + OctreeRef->SetIsFree(IsFree); + return IsFree; +} + +const FVector ACPathVolume::LookupTable_ChildPositionOffsetMaskByIndex[8] = { + {-1, -1, -1}, + {-1, 1, -1}, + {-1, -1, 1}, + {-1, 1, 1}, + + {1, -1, -1}, + {1, 1, -1}, + {1, -1, 1}, + {1, 1, 1} +}; + + +const FVector ACPathVolume::LookupTable_NeighbourOffsetByDirection[6] = { + {0, -1, 0}, + {-1, 0, 0}, + {0, 1, 0}, + {1, 0, 0}, + {0, 0, -1}, + {0, 0, 1} }; + +const int8 ACPathVolume::LookupTable_NeighbourChildIndex[8][6] = { + {-2, -5, 1, 4, -3, 2}, + {0, -6, -1, 5, -4, 3}, + {-4, -7, 3, 6, 0, -1}, + {2, -8, -3, 7, 1, -2}, + {-6, 0, 5, -1, -7, 6}, + {4, 1, -5, -2, -8, 7}, + {-8, 2, 7, -3, 4, -5}, + {6, 3, -7, -4, 5, -6}, +}; + +const int8 ACPathVolume::LookupTable_ChildrenOnSide[6][4] = { + {0, 2, 4, 6}, + {0, 1, 2, 3}, + {1, 3, 5, 7}, + {4, 5, 6, 7}, + {0, 1, 4, 5}, + {2, 3, 6, 7} +}; + +const int8 ACPathVolume::LookupTable_OppositeSide[6] = { + 2, 3, 0, 1, 5, 4 }; diff --git a/Plugins/CPathfinding/Source/CPathfinding/Private/CPathVolumeGroundPrio.cpp b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathVolumeGroundPrio.cpp new file mode 100644 index 00000000..ca001e47 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathVolumeGroundPrio.cpp @@ -0,0 +1,46 @@ +// // Copyright Dominik Trautman. All Rights Reserved. + + +#include "CPathVolumeGroundPrio.h" + +void ACPathVolumeGroundPrio::CalcFitness(CPathAStarNode& Node, FVector TargetLocation, int32 UserData) +{ + // Standard weithted A* Heuristic, f(n) = g(n) + e*h(n). (e = 3.5f) + if (Node.PreviousNode) + { + Node.DistanceSoFar = Node.PreviousNode->DistanceSoFar + FVector::Distance(Node.PreviousNode->WorldLocation, Node.WorldLocation); + } + float CurrDistance = FVector::Distance(Node.WorldLocation, TargetLocation); + + + if (CurrDistance > VoxelSize && !ExtractIsGroundFromData(Node.TreeUserData)) + { + Node.DistanceSoFar += UserData; + } + + Node.FitnessResult = Node.DistanceSoFar + 3.5f * CurrDistance; + + + +} + +bool ACPathVolumeGroundPrio::RecheckOctreeAtDepth(CPathOctree* OctreeRef, FVector TreeLocation, uint32 Depth) +{ + // We still want the normal trace to check if the node is free + bool IsFree = Super::RecheckOctreeAtDepth(OctreeRef, TreeLocation, Depth); + + // We dont need to calculate anything if its not free since it won't be searched + if (IsFree) + { + // Checking if this is a ground node + uint32 IsGround = GetWorld()->LineTraceTestByChannel(TreeLocation, FVector(TreeLocation.X, TreeLocation.Y, TreeLocation.Z - VoxelSize*1.49), TraceChannel); + + // Setting IsGround to 2nd bit in tree's data + OctreeRef->Data &= 0xFFFFFFFD; + OctreeRef->Data |= (IsGround << 1); + } + + + return IsFree; + +} diff --git a/Plugins/CPathfinding/Source/CPathfinding/Private/CPathfinding.cpp b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathfinding.cpp new file mode 100644 index 00000000..0c9dba86 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Private/CPathfinding.cpp @@ -0,0 +1,20 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +#include "CPathfinding.h" + +#define LOCTEXT_NAMESPACE "FCPathfindingModule" + +void FCPathfindingModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FCPathfindingModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FCPathfindingModule, CPathfinding) \ No newline at end of file diff --git a/Plugins/CPathfinding/Source/CPathfinding/Public/CPathAsyncVolumeGeneration.h b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathAsyncVolumeGeneration.h new file mode 100644 index 00000000..9390e6e2 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathAsyncVolumeGeneration.h @@ -0,0 +1,66 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "HAL/Runnable.h" +#include "HAL/RunnableThread.h" + +class ACPathVolume; +class CPathOctree; + + + + +class CPATHFINDING_API FCPathAsyncVolumeGenerator : public FRunnable +{ + + +public: + // Geneated trees in range Start(inclusive) - End(not inclusive). If Obstacles = true, it takes from Volume->TreesToRegenerate, if not, it takes from Volume->Octrees (default) + FCPathAsyncVolumeGenerator(ACPathVolume* Volume, uint32 StartIndex, uint32 EndIndex, uint8 ThreadID, FString ThreadName, bool Obstacles = false); + + // Not used for now + FCPathAsyncVolumeGenerator(ACPathVolume* Volume); + + ~FCPathAsyncVolumeGenerator(); + + virtual bool Init(); + + virtual uint32 Run(); + + virtual void Stop(); + + virtual void Exit(); + + // The main generating function, generated/regenerates the whole octree at given index + void RefreshTree(uint32 OuterIndex); + + bool bStop = false; + bool bObstacles = false; + + FRunnableThread* ThreadRef = nullptr; + + uint8 GenThreadID; + + FString Name = ""; + + uint32 OctreeCountAtDepth[4] = { 0, 0, 0, 0 }; + + +protected: + + ACPathVolume* VolumeRef; + + uint32 FirstIndex = 0; + uint32 LastIndex = 0; + + bool bIncreasedGenRunning = false; + + // Gets called by RefreshTree. Returns true if ANY child is free + bool RefreshTreeRec(CPathOctree* OctreeRef, uint32 Depth, FVector TreeLocation); + + +public: + +}; diff --git a/Plugins/CPathfinding/Source/CPathfinding/Public/CPathDefines.h b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathDefines.h new file mode 100644 index 00000000..3b16c639 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathDefines.h @@ -0,0 +1,56 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" + +// TreeID settings +// If you change these, you will also need to change some masks in functions like ReplaceDepth, ExtractDepth, etc +#define DEPTH_0_BITS 21 +#define DEPTH_0_LIMIT (uint32)1<(END - BEGIN).count())/1000000.0 + +// Uncomment these or define somwhere else to see performance logs +//#define LOG_GENERATORS 1 +//#define LOG_PATHFINDERS 1 + +enum ENeighbourDirection +{ + Left, // -Y + Front, // -X + Right, // +Y + Behind, // +X + Below, // -Z + Above // +Z +}; + +UENUM() +enum EAgentShape +{ + Capsule = 3, + Box = 2, + Sphere = 0 +}; + +// Wrong Start and End Location mean that requested location was out of volume, or it was inside an occupied space. +UENUM() +enum ECPathfindingFailReason +{ + None, + VolumeNotValid, + VolumeNotGenerated, + Timeout, + WrongStartLocation, + WrongEndLocation, + EndLocationUnreachable, + UnknownFailure +}; + + diff --git a/Plugins/CPathfinding/Source/CPathfinding/Public/CPathDynamicObstacle.h b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathDynamicObstacle.h new file mode 100644 index 00000000..cf7b399a --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathDynamicObstacle.h @@ -0,0 +1,56 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "CPathDynamicObstacle.generated.h" + +// Make sure this actor's collision has Generate Overlaps turned on. +// Owning actor must be movable. +// For better performance, call Deactivate() on this component once you dont need it to be updated anymore. +// bAutoActivate should be left unckecked for this component. +UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +class CPATHFINDING_API UCPathDynamicObstacle : public UActorComponent +{ + GENERATED_BODY() + +public: + + UCPathDynamicObstacle(); + + UFUNCTION() + void OnBeginOverlap(AActor* Owner, AActor* OtherActor); + + UFUNCTION() + void OnEndOverlap(AActor* Owner, AActor* OtherActor); + + // CPathVolumes that consider this actor an obstacle. + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = CPath) + TSet OverlappigVolumes; + + // If this actor gets spawned inside a CPathVolume, it will tell the volume about it. + // If this is left unchecked, you must make sure that this actor spawns outside of a CPathVolume, or do it manually. + // If you spawn CPathVolume AFTEr this actor, you will need to handle overlaps manually. + // In case of Level Streaming, CPathVolume should be placed on the same level as each actor it's supposed to track. + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = CPath) + bool ActivateOnBeginPlay = true; + + virtual void Activate(bool bReset = false) override; + + virtual void Deactivate() override; + + void AddIndexesToUpdate(class ACPathVolume* Volume); + + virtual void EndPlay(EEndPlayReason::Type Reason) override; +protected: + // Called when the game starts + virtual void BeginPlay() override; + //TArray OverlappingVolumes; + +public: + + + + + +}; diff --git a/Plugins/CPathfinding/Source/CPathfinding/Public/CPathFindPath.h b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathFindPath.h new file mode 100644 index 00000000..48296595 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathFindPath.h @@ -0,0 +1,155 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +#pragma once + + +#include "CoreMinimal.h" +#include "CPathNode.h" +#include "HAL/Runnable.h" +#include "HAL/RunnableThread.h" +#include "Kismet/BlueprintAsyncActionBase.h" +#include +#include +#include +#include +#include +#include "CPathFindPath.generated.h" + + +class ACPathVolume; + +/** +The class for pathfinding, used in UCPathAsyncFindPath. Can also be used on game thread to get the path instantly. +*/ +class CPathAStar +{ +public: + CPathAStar(); + CPathAStar(ACPathVolume* VolumeRef, FVector Start, FVector End, uint32 SmoothingPasses = 1, int32 UserData = 0, float TimeLimit = 1.f / 200.f); + + ~CPathAStar(); + + // Can be called from main thread, but can freeze the game if you increase TimeLimit. + CPathAStarNode* FindPath(ACPathVolume* VolumeRef, FVector Start, FVector End, uint32 SmoothingPasses = 1, int32 UserData = 0, float TimeLimit = 1.f / 200.f, TArray* RawNodes = nullptr); + + // Uses cached data in this class, only working if all the arguments were passed via constructor. + // Returns true on success, result is in UserPath + bool FindPath(); + + // Set this to true to interrupt pathfinding. FindPath returns an empty array. + bool bStop = false; + + // Removes nodes in (nearly)straight sections, transforms to Blueprint exposed struct, optionally reverses it so that the path is from start to end and returns raw nodes. + void TransformToUserPath(CPathAStarNode* PathEndNode, TArray& UserPath, bool bReverse = true); + + // This is used by FindPath if it failed null. + ECPathfindingFailReason FailReason = None; + + // The final usable path + TArray UserPath; + + // The path before preprocessing + TArray RawPathNodes; + + // Cached FindPath parameters + FVector PathStart, PathEnd; + uint32 Smoothing = 2; + int32 UsrData = 0; + float SearchTimeLimit = 1.f / 200.f; + + // Used in removing nodes that lay on the same line. The biger the number, the more nodes will be removed, but the path potentially loses data. + float LineAngleToleranceDegrees = 3; + +protected: + + ACPathVolume* Volume; + + inline float EucDistance(CPathAStarNode& Node, FVector TargetWorldLocation) const; + + inline void CalcFitness(CPathAStarNode& Node); + + // Nodes that were consumed from priority queue + // This is emptied whenever FindPath is called + std::vector> ProcessedNodes; + +private: + FVector TargetLocation; + // Sweeps from Start to End using the tracing shape from volume. Returns true if no obstacles + inline bool CanSkip(FVector Start, FVector End); + + // Iterates over the path from end to start, removing every other node if CanSkip returns true + inline void SmoothenPath(CPathAStarNode* PathEndNode); + + friend class UCPathAsyncFindPath; + friend class FCPathRunnableFindPath; + +}; + + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FResponseDelegate, const TArray&, Path, TEnumAsByte, FailReason); + +/** + Accessing this class through ANY MEANS other than delegates is UNSAFE. + */ +UCLASS() +class CPATHFINDING_API UCPathAsyncFindPath : public UBlueprintAsyncActionBase +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintAssignable) + FResponseDelegate Success; + + UPROPERTY(BlueprintAssignable) + FResponseDelegate Failure; + + // On success, returns a path from Start to End location. Both start and end must be inside the given Volume. + // If start or end is unreachable (or time limit was exceeded) returns nothing. + // SmoothingPasses - During a smoothing pass, every other node is potentially removed, as long as there is an empty space to the next one. + // With SmoothingPasses=0, the path will be very jagged since the graph is Discrete. + // With SmoothingPasses > 2 there is a potential loss of data, especially if a custom Cost function is used. + UFUNCTION(BlueprintCallable, Category = CPath, meta = (BlueprintInternalUseOnly = "true")) + static UCPathAsyncFindPath* FindPathAsync(class ACPathVolume* Volume, FVector StartLocation, FVector EndLocation, int SmoothingPasses = 2, int32 UserData = 0, float TimeLimit = 0.2f); + + virtual void Activate() override; + virtual void BeginDestroy() override; + + // 1 = finished Success + // 0 = finished failed + std::atomic_int ThreadResponse = -1; + FTimerHandle CheckThreadTimerHandle; + void CheckThreadStatus(); + +private: + + // Thread objects + CPathAStar* AStar = nullptr; + class FCPathRunnableFindPath* RunnableFindPath = nullptr; + FRunnableThread* CurrentThread = nullptr; + + friend class FCPathRunnableFindPath; +}; + +// The class used to perform pathfinding on its own thread +class CPATHFINDING_API FCPathRunnableFindPath : public FRunnable +{ +public: + FCPathRunnableFindPath(class UCPathAsyncFindPath* AsyncNode); + + virtual bool Init(); + + virtual uint32 Run(); + + virtual void Stop(); + + virtual void Exit(); + + //bool StopThread = false; + +private: + float SleepCounter = 0; + + bool bIncreasedPathfRunning = false; + + class UCPathAsyncFindPath* AsyncActionRef = nullptr; +}; diff --git a/Plugins/CPathfinding/Source/CPathfinding/Public/CPathNode.h b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathNode.h new file mode 100644 index 00000000..20e7e377 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathNode.h @@ -0,0 +1,90 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "CPathNode.generated.h" + +/** + * + */ + + // Internal class used while generating path +class CPATHFINDING_API CPathAStarNode +{ +public: + CPathAStarNode(); + CPathAStarNode(uint32 ID) + : + TreeID(ID) + {} + CPathAStarNode(uint32 ID, uint32 Data) + : + TreeID(ID), + TreeUserData(Data) + {} + + uint32 TreeID = 0xFFFFFFFF; + + // Data from Octree that you may modify by overriding `RecheckOctreeAtDepth` + // and access from `CalcFitness` + uint32 TreeUserData = 0; + + // We want to find a node with minimum fitness, this way distance doesnt have to be inverted + float FitnessResult = 9999999999.f; + float DistanceSoFar = 0; + + // This is NOT always valid. + CPathAStarNode* PreviousNode = nullptr; + + FVector WorldLocation; + + // ------ Operators for containers ---------------------------------------- + bool operator <(const CPathAStarNode& Rhs) const + { + return FitnessResult < Rhs.FitnessResult; + } + + bool operator >(const CPathAStarNode& Rhs) const + { + return FitnessResult > Rhs.FitnessResult; + } + + bool operator ==(const CPathAStarNode& Rhs) const + { + return TreeID == Rhs.TreeID; + } + + struct Hash + { + size_t operator()(const CPathAStarNode& Node) const + { + return Node.TreeID; + } + }; + + ~CPathAStarNode(); +}; + + +USTRUCT(BlueprintType) +struct FCPathNode +{ + GENERATED_BODY() + + FCPathNode() {} + FCPathNode(FVector Location) + : + WorldLocation(Location) + {} + + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = CPath) + FVector WorldLocation; + + // Normalized vector pointing to next node. ZeroVector on last node. + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = CPath) + FVector Normal = FVector(0, 0, 0); + + +}; \ No newline at end of file diff --git a/Plugins/CPathfinding/Source/CPathfinding/Public/CPathOctree.h b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathOctree.h new file mode 100644 index 00000000..6d1d869e --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathOctree.h @@ -0,0 +1,63 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" + +/** + * + */ + + + + // The Octree representation +class CPATHFINDING_API CPathOctree +{ +public: + CPathOctree(); + + + CPathOctree* Children = nullptr; + + uint32 Data = 0; + + + inline void SetIsFree(bool IsFree) + { + Data &= 0xFFFFFFFE; + Data |= (uint32)IsFree; + } + + inline bool GetIsFree() const + { + return Data << 31; + } + + ~CPathOctree() + { + delete[] Children; + }; +}; + +// Class used to remember data needed to draw a debug voxel +class CPATHFINDING_API CPathVoxelDrawData +{ + +public: + + CPathVoxelDrawData() + {} + + CPathVoxelDrawData(FVector WorldLocation, float VoxelExtent, bool IsFree) + : + Location(WorldLocation), + Extent(VoxelExtent), + Free(IsFree) + {} + + FVector Location; + float Extent; + bool Free = false; + +}; + diff --git a/Plugins/CPathfinding/Source/CPathfinding/Public/CPathVolume.h b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathVolume.h new file mode 100644 index 00000000..60e0d244 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathVolume.h @@ -0,0 +1,344 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "WorldCollision.h" +#include +#include +#include +#include +#include +#include +#include "PhysicsInterfaceTypesCore.h" +#include "CPathDefines.h" +#include "CPathOctree.h" +#include "CPathNode.h" +#include "CPathAsyncVolumeGeneration.h" +#include "CPathVolume.generated.h" + + +UCLASS() +class CPATHFINDING_API ACPathVolume : public AActor +{ + GENERATED_BODY() + + friend class FCPathAsyncVolumeGenerator; + friend class UCPathDynamicObstacle; +public: + ACPathVolume(); + + virtual void Tick(float DeltaTime) override; + + virtual void BeginDestroy() override; + + + // ------- EXTENDABLE ------ + + // Overwrite this function to change the priority of nodes as they are selected for the path. + // Note that this is potentially called thousands of times per FindPath call, so it shouldnt be too complex (unless your graph not very dense) + virtual void CalcFitness(CPathAStarNode& Node, FVector TargetLocation, int32 UserData); + + // Overwrite this function to change the default conditions of a tree being free/ocupied. + // You may also save other information in the Data field of an Octree, as only the least significant bit is used. + // This is called during graph generation, for every subtree including leafs, so potentially millions of times. + virtual bool RecheckOctreeAtDepth(CPathOctree* OctreeRef, FVector TreeLocation, uint32 Depth); + + + // -------- BP EXPOSED ---------- + + //Box to mark the area to generate graph in. It should not be rotated, the rotation will be ignored. + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Components", meta = (EditCondition = "GenerationStarted==false")) + class UBoxComponent* VolumeBox; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CPath", meta = (EditCondition = "GenerationStarted==false")) + TEnumAsByte TraceChannel = ECollisionChannel::ECC_Visibility; + + // Spports Capsule, sphere and box. + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CPath", meta = (EditCondition = "GenerationStarted==false")) + TEnumAsByte AgentShape = EAgentShape::Capsule; + + // In case of a box, this is X and Y extent. Z and Y should be the same, since the actual agent will most likely rotate. + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CPath", meta = (EditCondition = "GenerationStarted==false", ClampMin = "0", UIMin = "0")) + float AgentRadius = 0; + + // In case of a box, this is Z extent. + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CPath", meta = (EditCondition = "GenerationStarted==false && AgentShape!=EAgentShape::Sphere", ClampMin = "0", UIMin = "0")) + float AgentHalfHeight = 0; + + + + + // Size of the smallest voxel edge. + // In most cases, setting this to min(AgentRadius, AgentHalfHeight)*2 is enough. + // For precise (dense) graph - set this to min(AgentRadius, AgentHalfHeight). + // Small values increase memory cost, and potentially CPU load. + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CPath", meta = (EditCondition = "GenerationStarted==false", ClampMin = "0.1", UIMin = "0.1")) + float VoxelSize = 60; + + // How many times per second do parts of the volume get regenerated based on dynamic obstacles, in seconds. + // Values higher than 5 are an overkill, but for the purpose of user freedom, I leave it unlocked. + // If no dynamic obstacles were added, this doesnt have any performance impact + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CPath", meta = (EditCondition = "GenerationStarted==false", ClampMin = "0.01", UIMin = "0.01", ClampMax = "30", UIMax = "30")) + float DynamicObstaclesUpdateRate = 3; + + // 2 Is optimal in most cases. If you have very large open speces with small amount of obstacles, then 3 will be better. + // For dense labirynths with little to no open space, 1 or even 0 will be faster. + // Check documentation for detailed performance guidance. + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CPath", meta = (EditCondition = "GenerationStarted==false", ClampMin = "0", ClampMax = "3", UIMin = "0", UIMax = "3")) + int OctreeDepth = 2; + + + // If want to call Generate() later or with some condition. + // Note that volume wont be usable before it is generated + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CPath") + bool GenerateOnBeginPlay = true; + + // Set a custom generation thread limit. By default, it's system's Physical Core count - 1. + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CPath") + bool OverwriteMaxGenerationThreads = false; + + // How many threads can graph generation split into. + // If left <=0 (RECOMMENDED), it uses system's Physical Core count - 1. + // Generation threads are allocated dynamically, so it only uses more than 1 thread when necessary. + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CPath", meta = (EditCondition = "GenerationStarted==false && OverwriteMaxGenerationThreads==true", ClampMin = "0", ClampMax = "31", UIMin = "0", UIMax = "31")) + int MaxGenerationThreads = 0; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CPath|Render") + bool DrawFree = true; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CPath|Render") + bool DrawOccupied = false; + + // You can hide selected depths from rendering + UPROPERTY(EditAnywhere, BlueprintReadOnly, EditFixedSize, Category = "CPath|Render") + TArray DepthsToDraw; + + // How thick should the green and red debug boxes be + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CPath|Render") + float DebugBoxesThickness = 1.f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CPath|Render") + float DebugPathThickness = 1.5f; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CPath|Info") + bool GenerationStarted = false; + + // This is a read only info about initially generated graph + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CPath|Info") + TArray OctreeCountAtDepth = { 0, 0, 0, 0 }; + + // This is a read only info about initially generated graph + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CPath|Info") + int TotalNodeCount = 0; + + // Draws FREE neighbouring leafs + UFUNCTION(BlueprintCallable, Category = "CPath|Render") + void DebugDrawNeighbours(FVector WorldLocation); + + // Draws the octree structure around WorldLocation, up tp VoxelLlimit + UFUNCTION(BlueprintCallable, Category = "CPath|Render") + void DrawDebugNodesAroundLocation(FVector WorldLocation, int VoxelLimit, float Duration); + + // Draws path with points, for visualization only + // Duration == 0 - draw for one frame + // Duration < 0 - persistent + UFUNCTION(BlueprintCallable, Category = "CPath|Render") + void DrawDebugPath(const TArray& Path, float Duration, bool DrawPoints = true, FColor Color = FColor::Magenta); + + // Before this is true, the graph is inoperable + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "CPath|Info") + bool InitialGenerationFinished = false; + + // Shapes to use when checking if voxel is free or not + std::vector> TraceShapesByDepth; + + // Returns false if graph couldnt start generating + bool GenerateGraph(); + +protected: + + virtual void BeginPlay() override; + + CPathOctree* Octrees = nullptr; + + +public: + + // Location of the first voxel, set during graph generation + FVector StartPosition; + + // Dimension sizes of the Nodes array, XYZ + uint32 NodeCount[3]; + + //----------- TreeID ------------------------------------------------------------------------ + + // Returns the child with this tree id, or his parent at DepthReached in case the child doesnt exist + CPathOctree* FindTreeByID(uint32 TreeID, uint32& DepthReached); + + inline CPathOctree* FindTreeByID(uint32 TreeID); + + // Returns a tree and its TreeID by world location, returns null if location outside of volume. Only for Outer index + CPathOctree* FindTreeByWorldLocation(FVector WorldLocation, uint32& TreeID); + + // Returns a leaf and its TreeID by world location, returns null if location outside of volume. + inline CPathOctree* FindLeafByWorldLocation(FVector WorldLocation, uint32& TreeID, bool MustBeFree = 1); + + // Returns a free leaf and its TreeID by world location, as long as it exists in provided search range and WorldLocation is in this Volume + // If SearchRange <= 0, it uses a default dynamic search range + // If SearchRange is too large, you might get a free node that is inaccessible from provided WorldLocation + CPathOctree* FindClosestFreeLeaf(FVector WorldLocation, uint32& TreeID, float SearchRange = -1); + + // Returns a neighbour of the tree with TreeID in given direction, also returns TreeID if the neighbour if found + CPathOctree* FindNeighbourByID(uint32 TreeID, ENeighbourDirection Direction, uint32& NeighbourID); + + // Returns a list of adjecent leafs as TreeIDs + std::vector FindNeighbourLeafs(uint32 TreeID, bool MustBeFree = true); + + // Returns a list of adjecent free leafs as CPathAStarNode + std::vector FindFreeNeighbourLeafs(CPathAStarNode& Node); + + // Returns a parent of tree with given TreeID or null if TreeID has depth of 0 + inline CPathOctree* GetParentTree(uint32 TreeId); + + // Returns world location of a voxel at this TreeID. This returns CENTER of the voxel + inline FVector WorldLocationFromTreeID(uint32 TreeID) const; + + inline FVector LocalCoordsInt3FromOuterIndex(uint32 OuterIndex) const; + + // Creates TreeID for AsyncOverlapByChannel + inline uint32 CreateTreeID(uint32 Index, uint32 Depth) const; + + // Extracts Octrees array index from TreeID + inline uint32 ExtractOuterIndex(uint32 TreeID) const; + + // Replaces Depth in the TreeID with NewDepth + inline void ReplaceDepth(uint32& TreeID, uint32 NewDepth); + + // Extracts depth from TreeID + inline uint32 ExtractDepth(uint32 TreeID) const; + + // Returns a number from 0 to 7 - a child index at requested Depth + inline uint32 ExtractChildIndex(uint32 TreeID, uint32 Depth) const; + + // This assumes that child index at Depth is 000, if its not use ReplaceChildIndex + inline void AddChildIndex(uint32& TreeID, uint32 Depth, uint32 ChildIndex); + + // Replaces child index at given depth + inline void ReplaceChildIndex(uint32& TreeID, uint32 Depth, uint32 ChildIndex); + + // Replaces child index at given depth and also replaces depth to the same one + inline void ReplaceChildIndexAndDepth(uint32& TreeID, uint32 Depth, uint32 ChildIndex); + + // Traverses the tree downwards and adds every tree to the container + void GetAllSubtrees(uint32 TreeID, std::vector& Container); + + // Volume is not safe to access as long as this is not 0, pathfinders should wait till this is 0 + std::atomic_int GeneratorsRunning = 0; + + // Volume wont start generating as long as this is not 0 + std::atomic_int PathfindersRunning = 0; + + // This is for other threads to check if graph is accessible + std::atomic_bool InitialGenerationCompleteAtom = false; + + // This is filled by DynamicObstacle component + std::set TrackedDynamicObstacles; + + // ----------- Other helper functions --------------------- + + inline float GetVoxelSizeByDepth(int Depth) const; + + // Draws the voxel, this takes all the drawing options into condition. If Duraiton is below 0, it never disappears. + // If Color = green, free trees are green and occupied are red. + // Returns true if drawn, false otherwise + bool DrawDebugVoxel(uint32 TreeID, bool DrawIfNotLeaf = true, float Duration = 0, FColor Color = FColor::Green, CPathVoxelDrawData* OutDrawData = nullptr); + void DrawDebugVoxel(const CPathVoxelDrawData& DrawData, float Duration) const; + + +protected: + + // Returns an index in the Octree array from world position. NO BOUNDS CHECK + inline int WorldLocationToIndex(FVector WorldLocation) const; + + // Multiplies local integer coordinates into index + inline float LocalCoordsInt3ToIndex(FVector V) const; + + // Returns the X Y and Z relative to StartPosition and divided by VoxelSize. Multiply them to get the index. NO BOUNDS CHECK + inline FVector WorldLocationToLocalCoordsInt3(FVector WorldLocation) const; + + // Returns world location of a tree at depth 0. Extracts only outer index from TreeID + inline FVector GetOuterTreeWorldLocation(uint32 TreeID) const; + + // takes in what `WorldLocationToLocalCoordsInt3` returns and performs a bounds check + inline bool IsInBounds(FVector LocalCoordsInt3) const; + + // Helper function for 'FindLeafByWorldLocation'. Relative location is location relative to the middle of CurrentTree + CPathOctree* FindLeafRecursive(FVector RelativeLocation, uint32& TreeID, uint32 CurrentDepth, CPathOctree* CurrentTree); + + // Returns IDs of all free leafs on chosen side of a tree. Sides are indexed in the same way as neighbours, and adds them to passed Vector. + // ASSUMES THAT PASSED TREE HAS CHILDREN + void FindLeafsOnSide(uint32 TreeID, ENeighbourDirection Side, std::vector* Vector, bool MustBeFree = true); + + // Same as above, but skips the part of getting a tree by TreeID so its faster + void FindLeafsOnSide(CPathOctree* Tree, uint32 TreeID, ENeighbourDirection Side, std::vector* Vector, bool MustBeFree = true); + + // Same as above, but wrapped in CPathAStarNode + void FindLeafsOnSide(CPathOctree* Tree, uint32 TreeID, ENeighbourDirection Side, std::vector* Vector, bool MustBeFree = true); + + // Internal function used in GetAllSubtrees + void GetAllSubtreesRec(uint32 TreeID, CPathOctree* Tree, std::vector& Container, uint32 Depth); + + + // -------- GENERATION ----- + FTimerHandle GenerationTimerHandle; + + std::list> GeneratorThreads; + + // Garbage collection + void CleanFinishedGenerators(); + + // Checking if initial generation has finished + void InitialGenerationUpdate(); + + // Checking if there are any trees to regenerate from dynamic obstacles + void GenerationUpdate(); + + std::set TreesToRegenerate; + + // This is so that when an actor moves, the previous space it was in needs to be regenerated as well + std::set TreesToRegeneratePreviousUpdate; + + // This is set in GenerateGraph() using a formula that estimates total voxel count + int OuterIndexesPerThread; + + bool ThreadIDs[64]; + + inline uint32 GetFreeThreadID() const; + + + // ----- Lookup tables------- + static const FVector LookupTable_ChildPositionOffsetMaskByIndex[8]; + static const FVector LookupTable_NeighbourOffsetByDirection[6]; + + // Positive values = ChildIndex of the same parent, negative values = (-ChildIndex - 1) of neighbour at Direction [6] + static const int8 LookupTable_NeighbourChildIndex[8][6]; + + // First index is side as in ENeighbourDirection, and then you get indices of children on that side (in ascending order) + static const int8 LookupTable_ChildrenOnSide[6][4]; + + // Left returns right, up returns down, Front returns behind, etc + static const int8 LookupTable_OppositeSide[6]; + + // Set in begin play + float LookupTable_VoxelSizeByDepth[MAX_DEPTH + 1]; + + + // -------- DEBUGGING ----- + std::vector PreviousDrawAroundLocationData; + + std::chrono::steady_clock::time_point GenerationStart; + bool PrintGenerationTime = false; + + +}; diff --git a/Plugins/CPathfinding/Source/CPathfinding/Public/CPathVolumeGroundPrio.h b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathVolumeGroundPrio.h new file mode 100644 index 00000000..d323b343 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathVolumeGroundPrio.h @@ -0,0 +1,26 @@ +// // Copyright Dominik Trautman. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "CPathVolume.h" +#include "CPathVolumeGroundPrio.generated.h" + +/** + * + */ +UCLASS() +class CPATHFINDING_API ACPathVolumeGroundPrio : public ACPathVolume +{ + GENERATED_BODY() +public: + virtual void CalcFitness(CPathAStarNode& Node, FVector TargetLocation, int32 UserData) override; + + virtual bool RecheckOctreeAtDepth(CPathOctree* OctreeRef, FVector TreeLocation, uint32 Depth); + + inline bool ExtractIsGroundFromData(uint32 TreeUserData) + { + return TreeUserData & 0x00000002; + } + +}; diff --git a/Plugins/CPathfinding/Source/CPathfinding/Public/CPathfinding.h b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathfinding.h new file mode 100644 index 00000000..96aa8fd2 --- /dev/null +++ b/Plugins/CPathfinding/Source/CPathfinding/Public/CPathfinding.h @@ -0,0 +1,16 @@ +// Copyright Dominik Trautman. Published in 2022. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + + +class CPATHFINDING_API FCPathfindingModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor-FileHelper.dll b/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor-FileHelper.dll index 7c2db1a1..8ced580d 100644 Binary files a/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor-FileHelper.dll and b/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor-FileHelper.dll differ diff --git a/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor-FileHelper.exp b/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor-FileHelper.exp index 84313cb7..7ae97232 100644 Binary files a/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor-FileHelper.exp and b/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor-FileHelper.exp differ diff --git a/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor-FileHelper.pdb b/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor-FileHelper.pdb index 8d015ea3..09936b3b 100644 Binary files a/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor-FileHelper.pdb and b/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor-FileHelper.pdb differ diff --git a/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor.modules b/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor.modules index f14aedf4..387ed052 100644 --- a/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor.modules +++ b/Plugins/FileHelperPlugin/Binaries/Win64/UnrealEditor.modules @@ -1,5 +1,5 @@ { - "BuildId": "37670630", + "BuildId": "827e4aed-aff1-4853-85bd-51def0d581c9", "Modules": { "FileHelper": "UnrealEditor-FileHelper.dll" diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0001.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0001.exp new file mode 100644 index 00000000..dcb4e133 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0001.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0002.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0002.exp new file mode 100644 index 00000000..84a86d65 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0002.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0003.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0003.exp new file mode 100644 index 00000000..4030ce0f Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0003.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0004.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0004.exp new file mode 100644 index 00000000..480c36ad Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0004.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0005.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0005.exp new file mode 100644 index 00000000..acefddbd Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0005.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0006.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0006.exp new file mode 100644 index 00000000..35e8c499 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0006.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0007.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0007.exp new file mode 100644 index 00000000..1ce78467 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0007.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0008.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0008.exp new file mode 100644 index 00000000..07ca6384 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco-0008.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco.dll b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco.dll index 6ae1fe4b..6cbd3067 100644 Binary files a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco.dll and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco.dll differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco.exp index ca77de5a..0c629360 100644 Binary files a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco.exp and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco.pdb b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco.pdb index 9522816b..b4504142 100644 Binary files a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco.pdb and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujoco.pdb differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0001.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0001.exp new file mode 100644 index 00000000..f27ac5b3 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0001.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0002.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0002.exp new file mode 100644 index 00000000..76d37a10 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0002.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0003.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0003.exp new file mode 100644 index 00000000..8d91eed9 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0003.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0004.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0004.exp new file mode 100644 index 00000000..8c74bd26 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0004.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0005.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0005.exp new file mode 100644 index 00000000..3f363985 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0005.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0006.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0006.exp new file mode 100644 index 00000000..7e82cd16 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0006.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0007.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0007.exp new file mode 100644 index 00000000..4707dd98 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0007.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0008.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0008.exp new file mode 100644 index 00000000..f1f5c094 Binary files /dev/null and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor-0008.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor.dll b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor.dll index cb0e757e..b9c09a3c 100644 Binary files a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor.dll and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor.dll differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor.exp b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor.exp index 027a3154..e5d5b951 100644 Binary files a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor.exp and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor.exp differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor.pdb b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor.pdb index b539b53b..18f36502 100644 Binary files a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor.pdb and b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor-LuckyMujocoEditor.pdb differ diff --git a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor.modules b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor.modules index c60d1175..9a4500b4 100644 --- a/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor.modules +++ b/Plugins/LuckyMujoco/Binaries/Win64/UnrealEditor.modules @@ -1,5 +1,5 @@ { - "BuildId": "37670630", + "BuildId": "827e4aed-aff1-4853-85bd-51def0d581c9", "Modules": { "LuckyMujoco": "UnrealEditor-LuckyMujoco.dll", diff --git a/Plugins/LuckyMujoco/Source/LuckyMujoco/LuckyMujoco.Build.cs b/Plugins/LuckyMujoco/Source/LuckyMujoco/LuckyMujoco.Build.cs index ec93bbb7..94f46788 100644 --- a/Plugins/LuckyMujoco/Source/LuckyMujoco/LuckyMujoco.Build.cs +++ b/Plugins/LuckyMujoco/Source/LuckyMujoco/LuckyMujoco.Build.cs @@ -30,8 +30,14 @@ public class LuckyMujoco : ModuleRules "Mujoco", "CoreUObject", "GameplayTasks", - "Projects" - // ... add other public dependencies that you statically link with here ... + "Json", + "JsonUtilities", + "JsonSerialization", + "CPathfinding", + "StateTreeModule", + "GameplayTags", + "Projects", + // ... add other public dependencies that you statically link with here ... } ); @@ -39,6 +45,7 @@ public class LuckyMujoco : ModuleRules PrivateDependencyModuleNames.AddRange( new string[] { + "StateTreeModule", "GameplayStateTreeModule" // ... add private dependencies that you statically link with here ... } ); diff --git a/Plugins/LuckyMujoco/Source/LuckyMujoco/Private/Actors/MujocoVolumeActor.cpp b/Plugins/LuckyMujoco/Source/LuckyMujoco/Private/Actors/MujocoVolumeActor.cpp index 2aa1ba5e..dd6a1bb3 100644 --- a/Plugins/LuckyMujoco/Source/LuckyMujoco/Private/Actors/MujocoVolumeActor.cpp +++ b/Plugins/LuckyMujoco/Source/LuckyMujoco/Private/Actors/MujocoVolumeActor.cpp @@ -11,6 +11,7 @@ #include "LuckyMujoco.h" #include "fstream" #include "filesystem" +#include "Misc/FMujocoSimWorker.h" AMujocoVolumeActor::AMujocoVolumeActor() { @@ -21,7 +22,6 @@ AMujocoVolumeActor::AMujocoVolumeActor() SpriteComponent = CreateDefaultSubobject(TEXT("Sprite")); RootComponent = SpriteComponent; - if (SpriteComponent) { SpriteComponent->bHiddenInGame = true; @@ -118,6 +118,7 @@ void AMujocoVolumeActor::InitializeMujoco() if (auto* World = GetWorld()) { + //GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("Generating Mujoco model...")); OnMujocoCompileBegin.Broadcast(); @@ -190,7 +191,15 @@ void AMujocoVolumeActor::InitializeMujoco() AssignComponentsToArray(World, TendonComponents); mj_resetData(MujocoModel.Get(), MujocoData.Get()); + if (MujocoModel && MujocoData && bMultithreaded) + { + SimulatedPositions.SetNum(MujocoModel->nbody); + SimulatedRotations.SetNum(MujocoModel->nbody); + SimWorker = MakeUnique( + MujocoModel.Get(), MujocoData.Get(), Options.Get()->Options.TimeStep, + &SimulatedPositions, &SimulatedRotations, &MujocoDataLock); + } //GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("Mujoco model generated!")); OnMujocoCompileSuccess.Broadcast(); } @@ -389,6 +398,31 @@ void AMujocoVolumeActor::PostRegisterAllComponents() void AMujocoVolumeActor::Tick(float DeltaTime) { + // Super::Tick(DeltaTime); + if (bMultithreaded) + { + FScopeLock Lock(&MujocoDataLock); + + for (int32 i = 1; i < BodyComponents.Num(); ++i) + { + if (BodyComponents[i].IsValid() && SimulatedPositions.IsValidIndex(i) && SimulatedRotations.IsValidIndex(i)) + { + if (bUpdatePositions) + { + BodyComponents[i]->SetWorldLocationAndRotation(SimulatedPositions[i], SimulatedRotations[i]); + } + if (bUpdateBounds) + { + BodyComponents[i]->UpdateBounds(); + } + if (bUpdateOverlaps) + { + BodyComponents[i]->UpdateOverlaps(); + } + } + } + return; + } if (MujocoData) { mj_step(MujocoModel.Get(), MujocoData.Get()); @@ -397,7 +431,7 @@ void AMujocoVolumeActor::Tick(float DeltaTime) { mj_step(MujocoModel.Get(), MujocoData.Get()); } - + for (int32 i = 1; i < BodyComponents.Num(); ++i) { if (BodyComponents[i].IsValid()) @@ -408,16 +442,25 @@ void AMujocoVolumeActor::Tick(float DeltaTime) FVector Position = FVector(Pos[0], -Pos[1], Pos[2]) * 100.0f; FQuat Rotation = FQuat(Quat[1], -Quat[2], Quat[3], -Quat[0]); - BodyComponents[i]->SetWorldLocationAndRotation(Position, Rotation); - BodyComponents[i]->UpdateBounds(); - BodyComponents[i]->UpdateOverlaps(); + if (bUpdatePositions) + { + BodyComponents[i]->SetWorldLocationAndRotation(Position, Rotation); + } + if (bUpdateBounds) + { + BodyComponents[i]->UpdateBounds(); + } + if (bUpdateOverlaps) + { + BodyComponents[i]->UpdateOverlaps(); + } } else { UE_LOG(LogMujoco, Warning, TEXT("Invalid body component at index: %d"), i); } } - } + } } void AMujocoVolumeActor::PostInitializeComponents() @@ -427,13 +470,19 @@ void AMujocoVolumeActor::PostInitializeComponents() void AMujocoVolumeActor::BeginPlay() { - Super::BeginPlay(); + Super::BeginPlay(); } void AMujocoVolumeActor::EndPlay(const EEndPlayReason::Type EndPlayReason) { Super::EndPlay(EndPlayReason); + if (SimWorker) + { + SimWorker->EnsureCompletion(); + SimWorker.Reset(); + } + MujocoData.Reset(); MujocoModel.Reset(); } diff --git a/Plugins/LuckyMujoco/Source/LuckyMujoco/Private/Components/MujocoIKControllerComponent.cpp b/Plugins/LuckyMujoco/Source/LuckyMujoco/Private/Components/MujocoIKControllerComponent.cpp new file mode 100644 index 00000000..f0d746ab --- /dev/null +++ b/Plugins/LuckyMujoco/Source/LuckyMujoco/Private/Components/MujocoIKControllerComponent.cpp @@ -0,0 +1,112 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +// MujocoIKControllerComponent.cpp +#include "Components/MujocoIKControllerComponent.h" +#include "GameFramework/Actor.h" +#include "Kismet/KismetMathLibrary.h" + +void UMujocoIKControllerComponent::BeginPlay() +{ + Super::BeginPlay(); + PrimaryComponentTick.bCanEverTick = true; +} + +void UMujocoIKControllerComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); +} + +void UMujocoIKControllerComponent::InitializeChain(UMujocoBodyComponent* Root, USceneComponent* InEndEffector) +{ + JointChain.Empty(); + EndEffector = InEndEffector; + + TArray Stack = { Root }; + + while (Stack.Num() > 0) + { + UMujocoBodyComponent* CurrentBody = Stack.Pop(); + + // Get joint components directly attached to this body + TArray Children; + CurrentBody->GetChildrenComponents(true, Children); + + for (USceneComponent* Child : Children) + { + if (auto* Joint = Cast(Child)) + { + FIKJoint IKJoint; + IKJoint.Joint = Joint; + IKJoint.Axis = Joint->Joint.Axis.GetValue(); + IKJoint.MinRange = Joint->Joint.Range.GetValue().X; + IKJoint.MaxRange = Joint->Joint.Range.GetValue().Y; + + // Find the actuator matching this joint + TArray Actuators; + CurrentBody->GetOwner()->GetComponents(Actuators); + + for (auto* Act : Actuators) + { + if (Act->Actuator.Joint == Joint->GetName()) + { + IKJoint.Actuator = Act; + break; + } + } + + if (IKJoint.Actuator) + { + JointChain.Add(IKJoint); + } + } + } + + // Add next level of child MujocoBodies to stack + for (USceneComponent* Child : Children) + { + if (UMujocoBodyComponent* ChildBody = Cast(Child)) + { + Stack.Add(ChildBody); + } + } + } +} + +void UMujocoIKControllerComponent::SolveIK(const FVector& TargetPosition, int32 Iterations, float Threshold) +{ + if (!EndEffector || JointChain.Num() == 0) + return; + + for (int32 Iter = 0; Iter < Iterations; ++Iter) + { + FVector EffectorPos = EndEffector->GetComponentLocation(); + if (FVector::Dist(EffectorPos, TargetPosition) < Threshold) + break; + + for (int32 i = JointChain.Num() - 1; i >= 0; --i) + { + FIKJoint& Joint = JointChain[i]; + FVector JointPos = Joint.Joint->GetComponentLocation(); + + FVector ToEffector = EffectorPos - JointPos; + FVector ToTarget = TargetPosition - JointPos; + + ToEffector.Normalize(); + ToTarget.Normalize(); + + FVector AxisWorld = Joint.Joint->GetComponentTransform().TransformVectorNoScale(Joint.Axis).GetSafeNormal(); + float Angle = FMath::Acos(FVector::DotProduct(ToEffector, ToTarget)); + FVector RotationAxis = FVector::CrossProduct(ToEffector, ToTarget).GetSafeNormal(); + + if (FVector::DotProduct(RotationAxis, AxisWorld) < 0) + Angle *= -1; + + //float CurrentAngle = Joint.Actuator->GetTargetPosition(); // You may need to track this manually + // float NewAngle = FMath::Clamp(CurrentAngle + Angle, Joint.MinRange, Joint.MaxRange); + // Joint.Actuator->SetControl(NewAngle); + + // EffectorPos = EndEffector->GetComponentLocation(); // Recompute after update + } + } +} diff --git a/Plugins/LuckyMujoco/Source/LuckyMujoco/Private/Misc/FMujocoSimWorker.cpp b/Plugins/LuckyMujoco/Source/LuckyMujoco/Private/Misc/FMujocoSimWorker.cpp new file mode 100644 index 00000000..5bf45933 --- /dev/null +++ b/Plugins/LuckyMujoco/Source/LuckyMujoco/Private/Misc/FMujocoSimWorker.cpp @@ -0,0 +1,72 @@ +// MujocoSimWorker.cpp + +#include "Misc/FMujocoSimWorker.h" +#include "HAL/PlatformProcess.h" + +FMujocoSimWorker::FMujocoSimWorker(mjModel* InModel, mjData* InData, float InTimestep, + TArray* InPositions, TArray* InRotations, FCriticalSection* InLock) + : Model(InModel), Data(InData), Timestep(InTimestep), + Positions(InPositions), Rotations(InRotations), DataLock(InLock), bStopThread(false) +{ + Thread = FRunnableThread::Create(this, TEXT("FMujocoSimWorker"), 0, TPri_AboveNormal); + if (!Thread) + { + UE_LOG(LogTemp, Fatal, TEXT("Failed to create MuJoCo simulation thread!")); + } +} + +FMujocoSimWorker::~FMujocoSimWorker() +{ + if (Thread) + { + Thread->Kill(true); + delete Thread; + Thread = nullptr; + } +} + +bool FMujocoSimWorker::Init() +{ + return true; +} + +uint32 FMujocoSimWorker::Run() +{ + int NumBodies = Model->nbody; + + Positions->SetNum(NumBodies); + Rotations->SetNum(NumBodies); + + while (!bStopThread) + { + mj_step(Model, Data); + + // Lock the buffer + FScopeLock Lock(DataLock); + for (int i = 0; i < NumBodies; ++i) + { + mjtNum* Pos = Data->xpos + 3 * i; + mjtNum* Quat = Data->xquat + 4 * i; + + (*Positions)[i] = FVector(Pos[0], -Pos[1], Pos[2]) * 100.0f; + (*Rotations)[i] = FQuat(Quat[1], -Quat[2], Quat[3], -Quat[0]); + } + FPlatformProcess::Sleep(Timestep); + } + + return 0; +} + +void FMujocoSimWorker::Stop() +{ + bStopThread = true; +} + +void FMujocoSimWorker::EnsureCompletion() +{ + Stop(); + if (Thread) + { + Thread->WaitForCompletion(); + } +} diff --git a/Plugins/LuckyMujoco/Source/LuckyMujoco/Public/Actors/MujocoVolumeActor.h b/Plugins/LuckyMujoco/Source/LuckyMujoco/Public/Actors/MujocoVolumeActor.h index 12b041e8..174f15e3 100644 --- a/Plugins/LuckyMujoco/Source/LuckyMujoco/Public/Actors/MujocoVolumeActor.h +++ b/Plugins/LuckyMujoco/Source/LuckyMujoco/Public/Actors/MujocoVolumeActor.h @@ -6,6 +6,7 @@ #include "Components/BillboardComponent.h" #include "Misc/MujocoWrapper.h" #include "Delegates/DelegateCombinations.h" +#include "Misc/FMujocoSimWorker.h" #include "MujocoVolumeActor.generated.h" class UMujocoBodyComponent; @@ -61,6 +62,18 @@ public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mujoco | Simulation", meta = (Min = 0, Max = 100, ClampMin = 0, ClampMax = 100)) int32 FrameSkip = 0; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mujoco | Simulation") + bool bMultithreaded = true; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mujoco | Simulation") + bool bUpdatePositions = true; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mujoco | Simulation") + bool bUpdateBounds = true; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mujoco | Simulation") + bool bUpdateOverlaps = true; + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Mujoco") TObjectPtr SpriteComponent; @@ -117,4 +130,12 @@ protected: virtual void BeginPlay() override; virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +private: + TUniquePtr SimWorker; + FCriticalSection MujocoDataLock; + + TArray SimulatedPositions; + TArray SimulatedRotations; + }; diff --git a/Plugins/LuckyMujoco/Source/LuckyMujoco/Public/Components/MujocoIKControllerComponent.h b/Plugins/LuckyMujoco/Source/LuckyMujoco/Public/Components/MujocoIKControllerComponent.h new file mode 100644 index 00000000..e742d649 --- /dev/null +++ b/Plugins/LuckyMujoco/Source/LuckyMujoco/Public/Components/MujocoIKControllerComponent.h @@ -0,0 +1,54 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "MujocoJointComponent.h" +#include "MujocoActuatorComponent.h" +#include "MujocoBodyComponent.h" +#include "MujocoIKControllerComponent.generated.h" + + +USTRUCT() +struct FIKJoint +{ + GENERATED_BODY() + + UPROPERTY() + UMujocoJointComponent* Joint; + + UPROPERTY() + UMujocoActuatorComponent* Actuator; + + UPROPERTY() + FVector Axis; + + float MinRange; + float MaxRange; +}; + +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class LUCKYMUJOCO_API UMujocoIKControllerComponent : public UActorComponent +{ + GENERATED_BODY() + +protected: + // Called when the game starts + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + UFUNCTION(BlueprintCallable) + void InitializeChain(UMujocoBodyComponent* Root, USceneComponent* EndEffector); + + UFUNCTION(BlueprintCallable) + void SolveIK(const FVector& TargetPosition, int32 Iterations = 10, float Threshold = 1.0f); + +private: + TArray JointChain; + USceneComponent* EndEffector; + +}; diff --git a/Plugins/LuckyMujoco/Source/LuckyMujoco/Public/Misc/FMujocoSimWorker.h b/Plugins/LuckyMujoco/Source/LuckyMujoco/Public/Misc/FMujocoSimWorker.h new file mode 100644 index 00000000..a4299d18 --- /dev/null +++ b/Plugins/LuckyMujoco/Source/LuckyMujoco/Public/Misc/FMujocoSimWorker.h @@ -0,0 +1,34 @@ +// MujocoSimWorker.h + +#pragma once + +#include "CoreMinimal.h" +#include "HAL/Runnable.h" +#include "HAL/ThreadSafeBool.h" +#include + +class FMujocoSimWorker : public FRunnable +{ +public: + FMujocoSimWorker(mjModel* InModel, mjData* InData, float InTimestep, + TArray* InPositions, TArray* InRotations, FCriticalSection* InLock); + virtual ~FMujocoSimWorker(); + + virtual bool Init() override; + virtual uint32 Run() override; + virtual void Stop() override; + + void EnsureCompletion(); + +private: + FThreadSafeBool bStopThread; + FRunnableThread* Thread; + + mjModel* Model; + mjData* Data; + float Timestep; + TArray* Positions; + TArray* Rotations; + FCriticalSection* DataLock; +}; + diff --git a/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor-LuckyTextWrite.dll b/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor-LuckyTextWrite.dll index 2e8a1223..90f7c0f9 100644 Binary files a/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor-LuckyTextWrite.dll and b/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor-LuckyTextWrite.dll differ diff --git a/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor-LuckyTextWrite.exp b/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor-LuckyTextWrite.exp index bc0bad32..0894f0a0 100644 Binary files a/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor-LuckyTextWrite.exp and b/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor-LuckyTextWrite.exp differ diff --git a/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor-LuckyTextWrite.pdb b/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor-LuckyTextWrite.pdb index 5a658686..0acaa839 100644 Binary files a/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor-LuckyTextWrite.pdb and b/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor-LuckyTextWrite.pdb differ diff --git a/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor.modules b/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor.modules index 63461a9d..296a600d 100644 --- a/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor.modules +++ b/Plugins/LuckyTextWrite/Binaries/Win64/UnrealEditor.modules @@ -1,5 +1,5 @@ { - "BuildId": "37670630", + "BuildId": "827e4aed-aff1-4853-85bd-51def0d581c9", "Modules": { "LuckyTextWrite": "UnrealEditor-LuckyTextWrite.dll" diff --git a/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld-0386.exp b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld-0386.exp new file mode 100644 index 00000000..af1ac9f3 Binary files /dev/null and b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld-0386.exp differ diff --git a/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld-5457.exp b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld-5457.exp new file mode 100644 index 00000000..b3effa44 Binary files /dev/null and b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld-5457.exp differ diff --git a/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.dll b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.dll new file mode 100644 index 00000000..b812d679 Binary files /dev/null and b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.dll differ diff --git a/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.exp b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.exp new file mode 100644 index 00000000..eefe17bd Binary files /dev/null and b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.exp differ diff --git a/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.patch_0.exe b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.patch_0.exe new file mode 100644 index 00000000..c1ef5c8c Binary files /dev/null and b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.patch_0.exe differ diff --git a/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.patch_0.exp b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.patch_0.exp new file mode 100644 index 00000000..78ea8b45 Binary files /dev/null and b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.patch_0.exp differ diff --git a/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.patch_0.lib b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.patch_0.lib new file mode 100644 index 00000000..954d4973 Binary files /dev/null and b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.patch_0.lib differ diff --git a/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.patch_0.pdb b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.patch_0.pdb new file mode 100644 index 00000000..1ac8b2c7 Binary files /dev/null and b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.patch_0.pdb differ diff --git a/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.pdb b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.pdb new file mode 100644 index 00000000..6e69e244 Binary files /dev/null and b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor-LuckyWorld.pdb differ diff --git a/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor.modules b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor.modules new file mode 100644 index 00000000..3e04c410 --- /dev/null +++ b/Plugins/LuckyWorld/Binaries/Win64/UnrealEditor.modules @@ -0,0 +1,7 @@ +{ + "BuildId": "827e4aed-aff1-4853-85bd-51def0d581c9", + "Modules": + { + "LuckyWorld": "UnrealEditor-LuckyWorld.dll" + } +} \ No newline at end of file diff --git a/Plugins/LuckyWorld/LuckyWorld.uplugin b/Plugins/LuckyWorld/LuckyWorld.uplugin new file mode 100644 index 00000000..55f57292 --- /dev/null +++ b/Plugins/LuckyWorld/LuckyWorld.uplugin @@ -0,0 +1,42 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "LuckyWorld", + "Description": "A plugin for interacting with the Lucky World Simulation.", + "Category": "Other", + "CreatedBy": "Behron Georgantas", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": false, + "IsExperimentalVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "LuckyWorld", + "Type": "Runtime", + "LoadingPhase": "Default" + } + ], + "Plugins": [ + { + "Name": "EditorScriptingUtilities", + "Enabled": true + }, + { + "Name": "CPathfinding", + "Enabled": true + }, + { + "Name": "StateTree", + "Enabled": true + }, + { + "Name": "GameplayStateTree", + "Enabled": true + } + ] +} \ No newline at end of file diff --git a/Plugins/LuckyWorld/Resources/Icon128.png b/Plugins/LuckyWorld/Resources/Icon128.png new file mode 100644 index 00000000..1231d4aa Binary files /dev/null and b/Plugins/LuckyWorld/Resources/Icon128.png differ diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/LuckyWorld.Build.cs b/Plugins/LuckyWorld/Source/LuckyWorld/LuckyWorld.Build.cs new file mode 100644 index 00000000..e4cf53ec --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/LuckyWorld.Build.cs @@ -0,0 +1,64 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class LuckyWorld : ModuleRules +{ + public LuckyWorld(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicIncludePaths.AddRange( + new string[] { + // ... add public include paths required here ... + } + ); + + + PrivateIncludePaths.AddRange( + new string[] { + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "Json", + "JsonUtilities", + "JsonSerialization", + "CPathfinding", + "StateTreeModule", + "GameplayStateTreeModule", + "GameplayTags", + "UMG" + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "DeveloperSettings", + "Engine", + "Slate", + "SlateCore", + "StateTreeModule", + "GameplayStateTreeModule" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/CameraSensorHandler.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/CameraSensorHandler.cpp new file mode 100644 index 00000000..329a4f6e --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/CameraSensorHandler.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AI/CameraSensorHandler.h" + + +// Add default functionality here for any ICameraSensorHandler functions that are not pure virtual. diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/LuckyMovement.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/LuckyMovement.cpp new file mode 100644 index 00000000..a44b5ba8 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/LuckyMovement.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AI/LuckyMovement.h" + + +// Add default functionality here for any ILuckyMovement functions that are not pure virtual. diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/PickAndPlaceManager.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/PickAndPlaceManager.cpp new file mode 100644 index 00000000..105e898a --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/PickAndPlaceManager.cpp @@ -0,0 +1,84 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AI/PickAndPlaceManager.h" + +#include "Components/StateTreeComponent.h" + + +// Sets default values +APickAndPlaceManager::APickAndPlaceManager() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = false; + +} + +// Called when the game starts or when spawned +void APickAndPlaceManager::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void APickAndPlaceManager::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + +bool APickAndPlaceManager::SetNewTarget_Implementation(AActor* StateTreeOwner, AActor* TargetActor, AActor* PlaceArea) +{ + if (IsValid(TargetActor) && IsValid(PlaceArea) && IsValid(StateTreeOwner)) + { + if (UStateTreeComponent* STC = StateTreeOwner->FindComponentByClass()) + { + FStateTreeEvent Event; + Event.Origin = "PickAndPlaceStart"; + Event.Tag = PickAndPlaceStartTag; + STC->SendStateTreeEvent(Event); + } + CurrentTargetActor = TargetActor; + CurrentPlaceArea = PlaceArea; + if (!CurrentTargetActor->Tags.Contains(PickAndPlaceTag)) + { + CurrentTargetActor->Tags.Add(PickAndPlaceTag); + } + if (OnPickAndPlaceTargetsUpdated.IsBound()) + { + OnPickAndPlaceTargetsUpdated.Broadcast(this); + } + return true; + } + return false; +} + +bool APickAndPlaceManager::PickAndPlaceSuccess_Implementation(AActor* StateTreeOwner) +{ + if (IsValid(StateTreeOwner)) + { + if (UStateTreeComponent* STC = StateTreeOwner->FindComponentByClass()) + { + FStateTreeEvent Event; + Event.Origin = "PickAndPlaceSuccess"; + Event.Tag = PickAndPlaceSuccessTag; + STC->SendStateTreeEvent(Event); + } + } + if (OnPickAndPlaceSuccess.IsBound()) + { + OnPickAndPlaceSuccess.Broadcast(this); + } + return true; +} + +AActor* APickAndPlaceManager::GetCurrentTargetActor() const +{ + return CurrentTargetActor; +} + +AActor* APickAndPlaceManager::GetCurrentPlaceArea() const +{ + return CurrentPlaceArea; +} diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/PickAndPlaceUser.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/PickAndPlaceUser.cpp new file mode 100644 index 00000000..9aaa53da --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/PickAndPlaceUser.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AI/PickAndPlaceUser.h" + + +// Add default functionality here for any IPickAndPlaceUser functions that are not pure virtual. diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/Tasks/STT_LuckyDebug.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/Tasks/STT_LuckyDebug.cpp new file mode 100644 index 00000000..b77b5aad --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/Tasks/STT_LuckyDebug.cpp @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AI/Tasks/STT_LuckyDebug.h" + +EStateTreeRunStatus FSTT_LuckyDebug::EnterState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const +{ + if (bEnabled) + { + UE_LOG(LogTemp, Log, TEXT("%s"), *Message); + if (GEngine) + { + GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::White, Message); + } + } + return EStateTreeRunStatus::Succeeded; +} diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/Tasks/STT_PickAndPlace.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/Tasks/STT_PickAndPlace.cpp new file mode 100644 index 00000000..ca3ffb5f --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/Tasks/STT_PickAndPlace.cpp @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AI/Tasks/STT_PickAndPlace.h" +#include "StateTreeExecutionContext.h" +#include "AI/PickAndPlaceUser.h" +#include "Lib/LuckyWorldFunctions.h" + +EStateTreeRunStatus FSTT_PickAndPlace::EnterState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const +{ + if (UObject* Ref = Context.GetOwner()) + { + if (Ref->GetClass()->ImplementsInterface(UPickAndPlaceUser::StaticClass())) + { + if (APickAndPlaceManager* Manager = ULuckyWorldFunctions::GetPickAndPlaceManager(Ref)) + { + IPickAndPlaceUser::Execute_SetPickAndPlaceTargets(Ref,Manager->GetCurrentTargetActor(),Manager->GetCurrentPlaceArea()); + FStateTreeSharedEvent Event = FStateTreeSharedEvent(Manager->PickAndPlaceStartTag, FConstStructView(), "PickAndPlace"); + Context.ConsumeEvent(Event); + return EStateTreeRunStatus::Running; + } + } + } + return EStateTreeRunStatus::Failed; +} diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/Tasks/STT_RobotMoveTo.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/Tasks/STT_RobotMoveTo.cpp new file mode 100644 index 00000000..98480f76 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/AI/Tasks/STT_RobotMoveTo.cpp @@ -0,0 +1,83 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AI/Tasks/STT_RobotMoveTo.h" +#include "StateTreeExecutionContext.h" +#include "AI/LuckyMovement.h" +#include "Components/LuckyCustomMovementComponent.h" +#include "Components/StateTreeComponent.h" + +EStateTreeRunStatus FSTT_RobotMoveTo::EnterState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const +{ + Actor = Cast(Context.GetOwner()); + { + if (IsValid(Actor)) + { + return EStateTreeRunStatus::Running; + } + } + return EStateTreeRunStatus::Failed; +} + +EStateTreeRunStatus FSTT_RobotMoveTo::Tick(FStateTreeExecutionContext& Context, const float DeltaTime) const +{ + //Since we don't really have a full state tree yet, I'm running this on tick. + //When we have a better system fleshed out we can start to move this away from tick. + if (bIsFinished) + { + return EStateTreeRunStatus::Succeeded; + } + if (IsValid(Actor)) + { + if (ULuckyCustomMovementComponent* Movement = Actor->FindComponentByClass()) + { + FVector TargetLocation = FVector::ZeroVector; + //We start with our movement actor as the Actor, but it can be overriden in the interface. + AActor* MovementProxy = Actor; + if (Actor->GetClass()->ImplementsInterface(ULuckyMovement::StaticClass())) + { + //We get target location from the interface so we don't have to pass it into the state tree via context. + TargetLocation = ILuckyMovement::Execute_GetMovementTargetLocation(Actor); + if (AActor* Temp = ILuckyMovement::Execute_GetMovementProxy(Actor)) + { + //Set actor to movement proxy if we have a valid movement proxy. + MovementProxy = Temp; + } + } + //Start movement. + Movement->OnLuckyMovementFinishedNative.Unbind(); + Movement->OnLuckyMovementFinishedNative.BindRaw(this, &FSTT_RobotMoveTo::OnLuckyMovementFinished); + Movement->OnLuckyMovementFailedNative.Unbind(); + Movement->OnLuckyMovementFailedNative.BindRaw(this, &FSTT_RobotMoveTo::OnLuckyMovementFailed); + Movement->MoveToLocation(TargetLocation,nullptr,MovementProxy); + } + } + return EStateTreeRunStatus::Running; +} + +void FSTT_RobotMoveTo::OnLuckyMovementFinished(ULuckyCustomMovementComponent* Component, ULuckyMovementAlgorithmBase* Algo) const +{ + if (IsValid(Algo) && IsValid(Actor)) + { + if (Actor->GetClass()->ImplementsInterface(ULuckyMovement::StaticClass())) + { + //Send lucky movement call through the interface instead of the component. + //The delegate will still fire, but we don't want to have to check that if we don't need to. + ILuckyMovement::Execute_PerformLuckyMovement(Actor,Algo); + if (UStateTreeComponent* StateTreeComponent = Actor->FindComponentByClass()) + { + const FGameplayTag OnFinishedTag = ILuckyMovement::Execute_GetMovementFinishedTag(Actor); + FStateTreeEvent Event; + Event.Origin = "RobotMoveTo"; + Event.Tag = OnFinishedTag; + StateTreeComponent->SendStateTreeEvent(Event); + } + } + bIsFinished = true; + } +} + +void FSTT_RobotMoveTo::OnLuckyMovementFailed(ULuckyCustomMovementComponent* Component) const +{ + bIsFinished = false; +} diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/Algo/LuckyMovementAlgorithmBase.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Algo/LuckyMovementAlgorithmBase.cpp new file mode 100644 index 00000000..217dbc06 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Algo/LuckyMovementAlgorithmBase.cpp @@ -0,0 +1,48 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Algo/LuckyMovementAlgorithmBase.h" + + +ULuckyMovementAlgorithmBase::ULuckyMovementAlgorithmBase() +{ + OwningActor = nullptr; + CurrentInputVector = FVector::ZeroVector; +} + +ULuckyMovementAlgorithmBase::~ULuckyMovementAlgorithmBase() +{ +} + +void ULuckyMovementAlgorithmBase::SolveForLeftRight_Implementation(float& Left, float& Right) +{ + if (IsValid(OwningActor)) + { + const FVector Forward = OwningActor->GetActorForwardVector(); + const FVector RightVector = OwningActor->GetActorRightVector(); + + // Project input onto forward and right vectors + const float ForwardComponent = FVector::DotProduct(CurrentInputVector, Forward); + const float TurnComponent = FVector::DotProduct(CurrentInputVector, RightVector); + + // Combine them into differential drive logic + Left = ForwardComponent - TurnComponent; + Right = ForwardComponent + TurnComponent; + + // Optional: normalize torque to stay within [-1, 1] range + const float MaxTorque = FMath::Max(FMath::Abs(Left), FMath::Abs(Right)); + if (MaxTorque > 1.f) + { + Left /= MaxTorque; + Right /= MaxTorque; + } + return; + } + Left = Right = 0.f; +} + +void ULuckyMovementAlgorithmBase::Init_Implementation(AActor* InOwningActor,const FVector& InInputVector) +{ + OwningActor = InOwningActor; + CurrentInputVector = InInputVector; +} diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/Components/LuckyCustomMovementComponent.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Components/LuckyCustomMovementComponent.cpp new file mode 100644 index 00000000..258b835f --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Components/LuckyCustomMovementComponent.cpp @@ -0,0 +1,280 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Components/LuckyCustomMovementComponent.h" + +#include "CPathFindPath.h" +#include "AI/LuckyMovement.h" +#include "Kismet/KismetMathLibrary.h" + + +// Sets default values for this component's properties +ULuckyCustomMovementComponent::ULuckyCustomMovementComponent() +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = false; +} + + +// Called when the game starts +void ULuckyCustomMovementComponent::BeginPlay() +{ + Super::BeginPlay(); + if (UWorld* W = GetWorld()) + { + //Start draw path handle. Won't draw path if the bools are false, but will constantly run in case we want a user option to toggle it or something. + FTimerHandle Handle; + W->GetTimerManager().SetTimer(Handle,this,&ULuckyCustomMovementComponent::DrawPath,DrawPathDuration,true); + } + if (bAutoScalePathfindingVolume && GetPathfindingVolume() && IsValid(CurrentPathVolume) && !CurrentPathVolume->GenerateOnBeginPlay && IsValid(GetOwner())) + { + Actor = GetOwner(); + if (GetOwner()->GetClass()->ImplementsInterface(ULuckyMovement::StaticClass())) + { + if (AActor* Temp = ILuckyMovement::Execute_GetMovementProxy(GetOwner())) + { + //Set actor to movement proxy if we have a valid movement proxy. + Actor = Temp; + } + } + FVector Origin = FVector::ZeroVector; + FVector BoxExtent = FVector::ZeroVector; + Actor->GetActorBounds(true,Origin,BoxExtent,true); + CurrentPathVolume->AgentRadius = BoxExtent.X; + CurrentPathVolume->AgentHalfHeight = BoxExtent.Z; + CurrentPathVolume->VoxelSize = BoxExtent.X*2; + CurrentPathVolume->GenerateGraph(); + } +} + +// Called every frame +void ULuckyCustomMovementComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); +} + +void ULuckyCustomMovementComponent::MoveToLocation(const FVector& TargetLocation, ACPathVolume* PathVolume, AActor* InOverrideActor) +{ + CurrentNodeIndex = 0; + CurrentTargetLocation = TargetLocation; + Actor = InOverrideActor; + if (!IsValid(Actor)) + { + //If we don't pass through an override actor we just default to GetOwner(). + Actor = GetOwner(); + } + if (IsValid(Actor)) + { + CurrentPathVolume = PathVolume; + //Find path dynamically if we pass through a nullptr. + if (!IsValid(CurrentPathVolume)) + { + GetPathfindingVolume(); + } + if (!IsValid(CurrentPathVolume)) + { + //If we still don't have a path do nothing. + return; + } + bFindingPath = true; + //Start the pathfinding request. + Request = UCPathAsyncFindPath::FindPathAsync(CurrentPathVolume,Actor->GetActorLocation() + LocationZOffset,TargetLocation + LocationZOffset, + PathfindingSmoothingPasses,PathfindingUserData,PathfindingTimeLimit); + Request->Failure.AddDynamic(this, &ULuckyCustomMovementComponent::PathfindingFailed); + Request->Success.AddDynamic(this, &ULuckyCustomMovementComponent::PathfindingSuccess); + Request->Activate(); + } +} + +ACPathVolume* ULuckyCustomMovementComponent::GetPathfindingVolume() +{ + if (!IsValid(Actor)) + { + UE_LOG(LogTemp, Warning, TEXT("GetPathfindingVolume: Actor is null")); + return nullptr; + } + + TArray FoundActors; + Actor->GetOverlappingActors(FoundActors, ACPathVolume::StaticClass()); + + for (AActor* Found : FoundActors) + { + if (ACPathVolume* PathVolume = Cast(Found)) + { + CurrentPathVolume = PathVolume; + break; + } + } + + return CurrentPathVolume; +} + +void ULuckyCustomMovementComponent::PathfindingSuccess(const TArray& Path, TEnumAsByte FailReason) +{ + PathBuffer = Path; + //If we have a valid path, run the movement logic. + if (bRecheckPath && PathRecheckRate > 0) + { + FTimerHandle Handle; + GetWorld()->GetTimerManager().SetTimer(Handle,this,&ULuckyCustomMovementComponent::RecheckPath,PathRecheckRate,false); + } + PerformMovement(); +} + +void ULuckyCustomMovementComponent::PathfindingFailed(const TArray& Path, TEnumAsByte FailReason) +{ + //If we don't have a path, retry if bool is set. + bFindingPath = false; + const FString DebugMessage = FString::Printf(TEXT("LuckyCustomMovementComponent::%s failed to find a path to location %s for reason: %d!"), *Actor->GetFName().ToString(), + *CurrentTargetLocation.ToString(), FailReason.GetValue()); + UE_LOG(LogTemp,Warning,TEXT("%s"),*DebugMessage); + if (GEngine) + { + GEngine->AddOnScreenDebugMessage(0,3.f,FColor::Red,DebugMessage); + } + if (bRetryPathfinding) + { + MoveToLocation(CurrentTargetLocation,CurrentPathVolume); + } + if (OnLuckyMovementFailed.IsBound()) + { + OnLuckyMovementFailed.Broadcast(this); + } + OnLuckyMovementFailedNative.ExecuteIfBound(this); +} + +void ULuckyCustomMovementComponent::RecheckPathfindingSuccess(const TArray& Path, TEnumAsByte FailReason) +{ + PathBuffer = Path; + CurrentNodeIndex = GetNextOptimalNode(0); + if (bRecheckPath && PathRecheckRate > 0) + { + FTimerHandle Handle; + GetWorld()->GetTimerManager().SetTimer(Handle,this,&ULuckyCustomMovementComponent::RecheckPath,PathRecheckRate,false); + } +} + +void ULuckyCustomMovementComponent::RecheckPathfindingFailed(const TArray& Path, TEnumAsByte FailReason) +{ + const FString DebugMessage = FString::Printf(TEXT("LuckyCustomMovementComponent::%s failed to recheck path to location %s for reason: %d!"), *Actor->GetFName().ToString(), + *CurrentTargetLocation.ToString(), FailReason.GetValue()); + UE_LOG(LogTemp,Warning,TEXT("%s"),*DebugMessage); + if (GEngine) + { + GEngine->AddOnScreenDebugMessage(0,3.f,FColor::Red,DebugMessage); + } +} + +int32 ULuckyCustomMovementComponent::GetNextOptimalNode(int32 InNodeIndex) const +{ + int32 BestIndex = CurrentNodeIndex; + if (PathBuffer.IsValidIndex(BestIndex) && IsValid(CurrentPathVolume) && IsValid(Actor)) + { + float BestDot = GetDotToNode(PathBuffer[BestIndex]); + bool bWasHit = false; + while (!bWasHit && BestIndex < PathBuffer.Num()-1) + { + const FCPathNode NodeCheck = PathBuffer[BestIndex+1]; + float CurrentDot = GetDotToNode(NodeCheck); + if (CurrentDot > BestDot) //If false, we already likely have the best dot. + { + FCollisionShape Shape; + Shape.MakeSphere(1.f); + FCollisionQueryParams Params; + FCollisionResponseParams Response; + Params.AddIgnoredActor(Actor); + FHitResult Hit; + bWasHit = GetWorld()->SweepSingleByChannel(Hit,Actor->GetActorLocation(),NodeCheck.WorldLocation,FQuat(),CurrentPathVolume->TraceChannel,Shape,Params,Response); + //Make sure that we aren't hitting something along this path. + if (!bWasHit) + { + //If we aren't then we have a better dot than the last one. + BestDot = CurrentDot; + BestIndex++; + //If we've reached the end of the path buffer then we need to return so we don't crash. + if (BestIndex >= PathBuffer.Num()-2) + { + return BestIndex; + } + } + } + return BestIndex; + } + return BestIndex; + } + return BestIndex; //Ensure we don't crash by returning the current best index which should likely be 0. +} + +float ULuckyCustomMovementComponent::GetDotToNode(const FCPathNode& CurrentNode) const +{ + if (IsValid(Actor)) + { + const FVector NormVelocity = Actor->GetVelocity().GetSafeNormal(); + const FVector NormDirection = (CurrentNode.WorldLocation - Actor->GetActorLocation()).GetSafeNormal(); + return FVector::DotProduct(NormVelocity,NormDirection); + } + return -1.f; +} + +void ULuckyCustomMovementComponent::DrawPath() +{ + if (bDrawPath && IsValid(CurrentPathVolume) && IsValid(Actor)) + { + CurrentPathVolume->DrawDebugPath(PathBuffer,DrawPathDuration,bDrawPathPoints,DebugPathColor); + if (bDrawDebugNodes) + { + CurrentPathVolume->DrawDebugNodesAroundLocation(Actor->GetActorLocation(),DebugNodesVoxelLimit, DrawNodesDuration); + } + } +} + +void ULuckyCustomMovementComponent::PerformMovement() +{ + //Start actual movement logic. + if (PathBuffer.IsValidIndex(CurrentNodeIndex)) + { + const FCPathNode CurrentNode = PathBuffer[CurrentNodeIndex]; + const FVector CurrentLocation = Actor->GetActorLocation() + LocationZOffset; + const FVector Target = CurrentNode.WorldLocation;// + LocationZOffset; + //Only move if we are not within the same octree. + if (FVector::Dist(Target,CurrentLocation) > NodeDistanceTolerance) + { + //Find input target direction. + CurrentInputVector = (Target-CurrentLocation); + CurrentInputVector.Normalize(); + //Construct movement algorithm. + ULuckyMovementAlgorithmBase* Algo = NewObject(MovementAlgorithm.LoadSynchronous()); + Algo->Init(Actor,CurrentInputVector); + //Broadcast event if bound. + if (OnLuckyMovementFinished.IsBound()) + { + OnLuckyMovementFinished.Broadcast(this,Algo); + } + OnLuckyMovementFinishedNative.ExecuteIfBound(this,Algo); + } + //Increment movement index and attempt to move to the next path node. + CurrentNodeIndex++; + if (CurrentNodeIndex < PathBuffer.Num() && bFindingPath) + { + FTimerHandle Handle; + GetWorld()->GetTimerManager().SetTimer(Handle,this,&ULuckyCustomMovementComponent::PerformMovement,NodeDistanceCheckRate,false); + return; + } + bFindingPath = false; + } +} + +void ULuckyCustomMovementComponent::RecheckPath() +{ + if (bRecheckPath && PathRecheckRate > 0 && bFindingPath && IsValid(CurrentPathVolume)) + { + //Start the pathfinding request. + Request = UCPathAsyncFindPath::FindPathAsync(CurrentPathVolume,Actor->GetActorLocation() + LocationZOffset,CurrentTargetLocation + LocationZOffset, + PathfindingSmoothingPasses,PathfindingUserData,PathfindingTimeLimit); + Request->Failure.AddDynamic(this, &ULuckyCustomMovementComponent::RecheckPathfindingFailed); + Request->Success.AddDynamic(this, &ULuckyCustomMovementComponent::RecheckPathfindingSuccess); + Request->Activate(); + } +} + diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/Core/LuckyDataManager.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Core/LuckyDataManager.cpp new file mode 100644 index 00000000..008ecc11 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Core/LuckyDataManager.cpp @@ -0,0 +1,8 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Core/LuckyDataManager.h" + + + + diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/Core/LuckyWidgetManager.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Core/LuckyWidgetManager.cpp new file mode 100644 index 00000000..15bbebf4 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Core/LuckyWidgetManager.cpp @@ -0,0 +1,69 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Core/LuckyWidgetManager.h" + +#include "Blueprint/UserWidget.h" +#include "Core/LuckyWorldSettings.h" +#include "GameFramework/PlayerController.h" +#include "Lib/LuckyGameWidget.h" + +bool ULuckyWidgetManager::CreateGameWidget(APlayerController* OwningPlayer, UUserWidget*& Value) +{ + if (const ULuckyWorldSettings* Settings = ULuckyWorldSettings::GetLuckyWorldSettings()) + { + if (IsValid(Settings->GameWidgetClass.LoadSynchronous())) + { + GameWidget = CreateWidget(OwningPlayer, Settings->GameWidgetClass.LoadSynchronous()); + Value = GameWidget; //This is just for easy of use in blueprints. We can just get game widget, but meh. + if (IsValid(GameWidget)) + { + return true; + } + } + } + return false; +} + +bool ULuckyWidgetManager::SetCameraTextures() +{ + if (IsValid(GameWidget)) + { + if (GameWidget->GetClass()->ImplementsInterface(ULuckyGameWidget::StaticClass())) + { + return ILuckyGameWidget::Execute_SetCameraTextures(GameWidget); + } + } + return false; +} + +bool ULuckyWidgetManager::ShowCameraSettings() +{ + if (IsValid(GameWidget)) + { + if (GameWidget->GetClass()->ImplementsInterface(ULuckyGameWidget::StaticClass())) + { + return ILuckyGameWidget::Execute_ShowCameraSettings(GameWidget); + } + } + return false; +} + +bool ULuckyWidgetManager::HideCameraSettings() +{ + if (IsValid(GameWidget)) + { + if (GameWidget->GetClass()->ImplementsInterface(ULuckyGameWidget::StaticClass())) + { + return ILuckyGameWidget::Execute_HideCameraSettings(GameWidget); + } + } + return false; +} + +UUserWidget* ULuckyWidgetManager::GetGameWidget() const +{ + return GameWidget; +} + + diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/Core/LuckyWorldSettings.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Core/LuckyWorldSettings.cpp new file mode 100644 index 00000000..3fb43619 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Core/LuckyWorldSettings.cpp @@ -0,0 +1,4 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Core/LuckyWorldSettings.h" diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/Lib/LuckyGameWidget.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Lib/LuckyGameWidget.cpp new file mode 100644 index 00000000..d40097d8 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Lib/LuckyGameWidget.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Lib/LuckyGameWidget.h" + + +// Add default functionality here for any ILuckyGameWidget functions that are not pure virtual. diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/Lib/LuckyWorldFunctions.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Lib/LuckyWorldFunctions.cpp new file mode 100644 index 00000000..a26136f5 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/Lib/LuckyWorldFunctions.cpp @@ -0,0 +1,168 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Lib/LuckyWorldFunctions.h" +#include "EngineUtils.h" +#include "IImageWrapperModule.h" +#include "IImageWrapper.h" +#include "Modules/ModuleManager.h" +#include "Engine/TextureRenderTarget2D.h" +#include "Modules/ModuleManager.h" +#include "Misc/FileHelper.h" +#include "Engine/Texture2D.h" +#include "RenderUtils.h" +#include "Serialization/JsonWriter.h" +#include "Serialization/JsonSerializer.h" +#include "Dom/JsonObject.h" + +#include "Core/LuckyWorldSettings.h" + + +APickAndPlaceManager* ULuckyWorldFunctions::GetPickAndPlaceManager(UObject* WorldContextObject) +{ + if (IsValid(WorldContextObject)) + { + for (TActorIterator Itr(WorldContextObject->GetWorld()); Itr; ++Itr) + { + return *Itr; + } + } + return nullptr; +} + +bool ULuckyWorldFunctions::SaveRenderTargetToDisk(UTextureRenderTarget2D* RenderTarget, const FString& Filename, bool bAsPNG, bool bFlipVertically) +{ + if (!IsValid(RenderTarget)) return false; + + FRenderTarget* RenderTargetResource = RenderTarget->GameThread_GetRenderTargetResource(); + TArray Bitmap; + RenderTargetResource->ReadPixels(Bitmap); + + if (Bitmap.Num() <= 0) return false; + + if (bFlipVertically) + { + for (int32 Row = 0; Row < RenderTarget->SizeY / 2; Row++) + { + int32 IndexA = Row * RenderTarget->SizeX; + int32 IndexB = (RenderTarget->SizeY - Row - 1) * RenderTarget->SizeX; + for (int32 Col = 0; Col < RenderTarget->SizeX; Col++) + { + Bitmap.SwapMemory(IndexA + Col, IndexB + Col); + } + } + } + + FString FullPath = Filename; + FPaths::NormalizeFilename(FullPath); + IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked(FName("ImageWrapper")); + EImageFormat Format = bAsPNG ? EImageFormat::PNG : EImageFormat::JPEG; + TSharedPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper(Format); + + ImageWrapper->SetRaw(Bitmap.GetData(), Bitmap.GetAllocatedSize(), RenderTarget->SizeX, RenderTarget->SizeY, ERGBFormat::BGRA, 8); + const TArray64& ImageData = bAsPNG + ? ImageWrapper->GetCompressed(100) + : ImageWrapper->GetCompressed(75); + + return FFileHelper::SaveArrayToFile(ImageData, *FullPath); +} + +bool ULuckyWorldFunctions::SaveTextureToDisk(UTexture2D* Texture, const FString& Filename, bool bAsPNG, bool bFlipVertically) +{ + if (IsValid(Texture) || !Texture->GetPlatformData() || Texture->GetPlatformData()->Mips.Num() == 0) + { + return false; + } + + FTexture2DMipMap& Mip = Texture->GetPlatformData()->Mips[0]; + const void* Data = Mip.BulkData.LockReadOnly(); + + int32 Width = Mip.SizeX; + int32 Height = Mip.SizeY; + TArray Pixels; + Pixels.AddUninitialized(Width * Height); + + if (Texture->GetPlatformData()->PixelFormat == PF_B8G8R8A8) + { + FMemory::Memcpy(Pixels.GetData(), Data, Width * Height * sizeof(FColor)); + } + else + { + Mip.BulkData.Unlock(); + return false; + } + + Mip.BulkData.Unlock(); + + if (bFlipVertically) + { + for (int32 Row = 0; Row < Height / 2; Row++) + { + int32 IndexA = Row * Width; + int32 IndexB = (Height - Row - 1) * Width; + for (int32 Col = 0; Col < Width; Col++) + { + Pixels.SwapMemory(IndexA + Col, IndexB + Col); + } + } + } + + IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked(FName("ImageWrapper")); + EImageFormat Format = bAsPNG ? EImageFormat::PNG : EImageFormat::JPEG; + TSharedPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper(Format); + + ImageWrapper->SetRaw(Pixels.GetData(), Pixels.GetAllocatedSize(), Width, Height, ERGBFormat::BGRA, 8); + const TArray64& ImageData = bAsPNG + ? ImageWrapper->GetCompressed(100) + : ImageWrapper->GetCompressed(75); + + FString FullPath = FPaths::ProjectSavedDir() / TEXT("CapturedImages") / Filename; + FPaths::NormalizeFilename(FullPath); + return FFileHelper::SaveArrayToFile(ImageData, *FullPath); +} + +FString ULuckyWorldFunctions::ConvertMapToJsonString(const TMap& InMap) +{ + TSharedRef JsonObject = MakeShared(); + + for (const TPair& Pair : InMap) + { + JsonObject->SetStringField(Pair.Key, Pair.Value); + } + + FString OutputString; + TSharedRef>> Writer = + TJsonWriterFactory>::Create(&OutputString); + + if (FJsonSerializer::Serialize(JsonObject, Writer)) + { + return OutputString; + } + + return TEXT("{}"); +} + +FString ULuckyWorldFunctions::FVectorToJsonString(const FVector& Vector) +{ + TSharedRef JsonObject = MakeShared(); + JsonObject->SetNumberField(TEXT("x"), Vector.X); + JsonObject->SetNumberField(TEXT("y"), Vector.Y); + JsonObject->SetNumberField(TEXT("z"), Vector.Z); + + FString OutputString; + + TSharedRef>> Writer = + TJsonWriterFactory>::Create(&OutputString); + + if (FJsonSerializer::Serialize(JsonObject, Writer)) + { + return OutputString; + } + + return TEXT("{}"); +} + +const ULuckyWorldSettings* ULuckyWorldFunctions::GetLuckyWorldSettings() +{ + return ULuckyWorldSettings::GetLuckyWorldSettings(); +} diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/LuckyWorld.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/LuckyWorld.cpp new file mode 100644 index 00000000..635725c8 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/LuckyWorld.cpp @@ -0,0 +1,20 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "LuckyWorld.h" + +#define LOCTEXT_NAMESPACE "FLuckyWorldModule" + +void FLuckyWorldModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FLuckyWorldModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FLuckyWorldModule, LuckyWorld) \ No newline at end of file diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Private/World/LLMWorldManager.cpp b/Plugins/LuckyWorld/Source/LuckyWorld/Private/World/LLMWorldManager.cpp new file mode 100644 index 00000000..aace47c2 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Private/World/LLMWorldManager.cpp @@ -0,0 +1,58 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "World/LLMWorldManager.h" +#include "EngineUtils.h" +#include "Components/LightComponent.h" +#include "Engine/DirectionalLight.h" + +// Sets default values +ALLMWorldManager::ALLMWorldManager() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = false; + +} + +// Called when the game starts or when spawned +void ALLMWorldManager::BeginPlay() +{ + Super::BeginPlay(); + TArray Lights; + for (TActorIterator Itr(GetWorld()); Itr; ++Itr) + { + DefaultLighting.Add(*Itr,Itr->GetLightComponent()->Intensity); + } +} + +// Called every frame +void ALLMWorldManager::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + +void ALLMWorldManager::ProcessLLMCommand_Implementation(const FString& Command) +{ + const FString CMD = Command.Replace(*CommandPrefix,*FString("")); + FString Left = ""; + FString Right = ""; + CMD.Split(" ", &Left, &Right); + + if (Left.IsEmpty() || Right.IsEmpty()) + { + return; + } + + if (Left == GlobalLightingCommandPrefix) + { + TArray Lights; + for (TActorIterator Itr(GetWorld()); Itr; ++Itr) + { + //Right == "0" ? 0 : DefaultLighting.FindRef(*Itr) + Itr->GetLightComponent()->SetIntensity(FCString::Atof(*Right)); + } + } + +} + diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/CameraSensorHandler.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/CameraSensorHandler.h new file mode 100644 index 00000000..b5f7e63e --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/CameraSensorHandler.h @@ -0,0 +1,61 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" + +#include "CameraSensorHandler.generated.h" + +// This class does not need to be modified. +UINTERFACE(MinimalAPI) +class UCameraSensorHandler : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class LUCKYWORLD_API ICameraSensorHandler +{ + GENERATED_BODY() + + // Add interface functions to this class. This is the class that will be inherited to implement this interface. +public: + + /** + * @return - The array of camera sensors. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category = "Cameras") + TArray GetCameraSensors(); + + /** + * Spawn a camera sensor child actor component. + * NOTE::You will need to make sure you set the class in the AddChildActorComponent function or this will return a nullptr. + * @param Transform - The new transform to spawn the camera at. + * @param Value - The return index for the new camera in the array. + * @return - The spawned camera component. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category = "Cameras") + UChildActorComponent* AddCameraSensor(const FTransform& Transform, int32& Value); + + /** + * Move a camera to a new world transform at the given index. + * @param Transform - The new camera transform. + * @param Index - The index for the camera in the array. + * @return - True if valid index. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category = "Cameras") + bool UpdateCameraSensorTransform(const FTransform& Transform, int32 Index); + + /** + * Reset the camera to its original position. + * NOTE::The camera indexes need to be cached in the actor or it will fail. + * @param Index - The camera index. + * @return - True if valid index. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category = "Cameras") + bool ResetCameraSensorTransform(int32 Index); + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/LuckyMovement.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/LuckyMovement.h new file mode 100644 index 00000000..8a6cce8b --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/LuckyMovement.h @@ -0,0 +1,59 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Algo/LuckyMovementAlgorithmBase.h" +#include "UObject/Interface.h" +#include "GameplayTags.h" +#include "LuckyMovement.generated.h" + +// This class does not need to be modified. +UINTERFACE(MinimalAPI) +class ULuckyMovement : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class LUCKYWORLD_API ILuckyMovement +{ + GENERATED_BODY() + + // Add interface functions to this class. This is the class that will be inherited to implement this interface. +public: + + /** + * If using a state tree, this interface will allow the state tree owner to run through the lucky movement scenario without needing to check for a new algo. + * @param Algo - The input algorithm. + * @return - Dummy value. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category = "LuckyMovement") + bool PerformLuckyMovement(ULuckyMovementAlgorithmBase* Algo); + + /** + * Return a movement proxy (i.e. the BP_Stretch property in the BP_mujokoStretch actor). + * This is a bit of a hacky solution for handling the proxy actors in the pawns. + * In the generic state tree implementation, if this property is nullptr we just use the context actor. + * @return - The movement proxy. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category = "LuckyMovement") + AActor* GetMovementProxy(); + + /** + * Return the target location that we are trying to move to. + * @return - The movement target location. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category = "LuckyMovement") + FVector GetMovementTargetLocation(); + + /** + * Return the state tree finished tag for movement. + * @return - The tag that we use to send finished event to state tree. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category = "LuckyMovement") + FGameplayTag GetMovementFinishedTag(); + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/PickAndPlaceManager.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/PickAndPlaceManager.h new file mode 100644 index 00000000..e115f3af --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/PickAndPlaceManager.h @@ -0,0 +1,98 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameplayTagContainer.h" +#include "GameFramework/Actor.h" +#include "PickAndPlaceManager.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPickAndPlaceTargetsUpdated, APickAndPlaceManager*, Manager); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPickAndPlaceSuccess, APickAndPlaceManager*, Manager); + +UCLASS() +class LUCKYWORLD_API APickAndPlaceManager : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + APickAndPlaceManager(); + + /** + * Notify pick and place has started. + */ + UPROPERTY(BlueprintAssignable,Category = "PickAndPlace") + FOnPickAndPlaceTargetsUpdated OnPickAndPlaceTargetsUpdated; + + /** + * Notify pick and place has succeeded. + */ + UPROPERTY(BlueprintAssignable,Category = "PickAndPlace") + FOnPickAndPlaceSuccess OnPickAndPlaceSuccess; + + /** + * The gameplay tag to send to the state tree to start pick and place. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "PickAndPlace") + FGameplayTag PickAndPlaceStartTag; + + /** + * The gameplay tag to send to the state tree to stop pick and place. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "PickAndPlace") + FGameplayTag PickAndPlaceSuccessTag; + + /** + * The actor tag that is required to consider an object entering the "box" to be a valid pick and place object. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "PickAndPlace") + FName PickAndPlaceTag; + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + /** + * Initialize the pick and place logic. + * @param StateTreeOwner - The owner of the state tree so we can send an event to the state tree to continue. + * @param TargetActor - The target to pick and place. + * @param PlaceArea - The area to place the target actor. + * @return - True if both target actor and place area are valid. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category = "PickAndPlace") + bool SetNewTarget(AActor* StateTreeOwner, AActor* TargetActor, AActor* PlaceArea); + + /** + * For now, this just broadcasts the event and sends a gameplay tag to the owner of the state tree, but more can be done here if needed. + * @param StateTreeOwner - The owner of the state tree so we can send an event to the state tree to continue. + * @return - Dummy value. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category = "PickAndPlace") + bool PickAndPlaceSuccess(AActor* StateTreeOwner); + + /** + * @return - CurrentTargetActor. + */ + UFUNCTION(BlueprintPure,Category = "PickAndPlace") + AActor* GetCurrentTargetActor() const; + + /** + * @return - CurrentPlaceArea. + */ + UFUNCTION(BlueprintPure,Category = "PickAndPlace") + AActor* GetCurrentPlaceArea() const; + +private: + + UPROPERTY() + AActor* CurrentTargetActor; + + UPROPERTY() + AActor* CurrentPlaceArea; + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/PickAndPlaceUser.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/PickAndPlaceUser.h new file mode 100644 index 00000000..5819c4bd --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/PickAndPlaceUser.h @@ -0,0 +1,66 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" + +#include "PickAndPlaceUser.generated.h" + +// This class does not need to be modified. +UINTERFACE(MinimalAPI) +class UPickAndPlaceUser : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class LUCKYWORLD_API IPickAndPlaceUser +{ + GENERATED_BODY() + + // Add interface functions to this class. This is the class that will be inherited to implement this interface. +public: + + /** + * Set pick and place targets. + * @param PickAndPlaceTarget - The target to pick up. + * @param PickAndPlaceArea - The area to drop the location at. + * @return - True if both targets are valid. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category="PickAndPlaceUser") + bool SetPickAndPlaceTargets(AActor* PickAndPlaceTarget, AActor* PickAndPlaceArea); + + /** + * Tell the robot to place the target at the desired location. + * @return - True if both targets are valid. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category="PickAndPlaceUser") + bool PlaceTarget(); + + /** + * Tell the robot to close its jaw. + * @param TargetValue - The target value for the jaw. + * @return - True if both targets are valid. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category="PickAndPlaceUser") + bool CloseJaw(float TargetValue); + + /** + * Tell the robot to open its jaw. + * @param TargetValue - The target value for the jaw. + * @return - True if both targets are valid. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category="PickAndPlaceUser") + bool OpenJaw(float TargetValue); + + /** + * Tell the robot to release the object. + * @return - True if both targets are valid. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category="PickAndPlaceUser") + bool DropTarget(); + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/Tasks/STT_LuckyDebug.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/Tasks/STT_LuckyDebug.h new file mode 100644 index 00000000..76a7830f --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/Tasks/STT_LuckyDebug.h @@ -0,0 +1,41 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "StateTreeTaskBase.h" +#include "StateTreeExecutionContext.h" +#include "STT_LuckyDebug.generated.h" + +USTRUCT(BlueprintType) +struct FSTT_LuckyDebugInstanceData +{ + GENERATED_BODY() + + UPROPERTY() + bool Dummy = false; +}; + +/** + * Basic move to using LuckyCustomMovementComponent. + */ +USTRUCT(BlueprintType, meta = (DisplayName = "Lucky Debug")) +struct LUCKYWORLD_API FSTT_LuckyDebug : public FStateTreeTaskCommonBase + +{ + GENERATED_BODY() + +public: + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + bool bEnabled = true; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Message; + + using FInstanceData = FSTT_LuckyDebugInstanceData; + virtual const UStruct* GetInstanceDataType() const override {return FInstanceData::StaticStruct();} + + virtual EStateTreeRunStatus EnterState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const override; + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/Tasks/STT_PickAndPlace.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/Tasks/STT_PickAndPlace.h new file mode 100644 index 00000000..5d76033c --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/Tasks/STT_PickAndPlace.h @@ -0,0 +1,35 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "StateTreeTaskBase.h" +#include "StateTreeExecutionContext.h" +#include "STT_PickAndPlace.generated.h" + +USTRUCT(BlueprintType) +struct FSTT_PickAndPlaceInstanceData +{ + GENERATED_BODY() + + UPROPERTY() + bool Dummy = false; +}; + +/** + * Basic pick and place. + */ +USTRUCT(BlueprintType, meta = (DisplayName = "Lucky Pick And Place")) +struct LUCKYWORLD_API FSTT_PickAndPlace : public FStateTreeTaskCommonBase + +{ + GENERATED_BODY() + +public: + + using FInstanceData = FSTT_PickAndPlaceInstanceData; + virtual const UStruct* GetInstanceDataType() const override {return FInstanceData::StaticStruct();} + + virtual EStateTreeRunStatus EnterState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const override; + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/Tasks/STT_RobotMoveTo.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/Tasks/STT_RobotMoveTo.h new file mode 100644 index 00000000..675fe6ff --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/AI/Tasks/STT_RobotMoveTo.h @@ -0,0 +1,45 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "StateTreeTaskBase.h" +#include "StateTreeExecutionContext.h" +#include "Components/LuckyCustomMovementComponent.h" +#include "STT_RobotMoveTo.generated.h" + +USTRUCT(BlueprintType) +struct FSTT_RobotMoveToInstanceData +{ + GENERATED_BODY() + + UPROPERTY() + bool Dummy = false; +}; + +/** + * Basic move to using LuckyCustomMovementComponent. + */ +USTRUCT(BlueprintType, meta = (DisplayName = "Lucky Move To")) +struct LUCKYWORLD_API FSTT_RobotMoveTo : public FStateTreeTaskCommonBase + +{ + GENERATED_BODY() + +public: + + using FInstanceData = FSTT_RobotMoveToInstanceData; + virtual const UStruct* GetInstanceDataType() const override {return FInstanceData::StaticStruct();} + + virtual EStateTreeRunStatus EnterState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const override; + virtual EStateTreeRunStatus Tick(FStateTreeExecutionContext& Context, const float DeltaTime) const override; + +private: + + UPROPERTY() + mutable AActor* Actor = nullptr; + mutable bool bIsFinished = false; + void OnLuckyMovementFinished(ULuckyCustomMovementComponent* Component, ULuckyMovementAlgorithmBase* Algo) const; + void OnLuckyMovementFailed(ULuckyCustomMovementComponent* Component) const; + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/Algo/LuckyMovementAlgorithmBase.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Algo/LuckyMovementAlgorithmBase.h new file mode 100644 index 00000000..947bd943 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Algo/LuckyMovementAlgorithmBase.h @@ -0,0 +1,45 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "LuckyMovementAlgorithmBase.generated.h" + +/** + * An algorithm object that will convert a direction vector into left/right tire movement for the MuJoCo simulation. + * TODO::Make sure this algo works for drone movement as well. + */ +UCLASS(BlueprintType,Blueprintable) +class LUCKYWORLD_API ULuckyMovementAlgorithmBase : public UObject +{ + + GENERATED_BODY() + +public: + ULuckyMovementAlgorithmBase(); + ~ULuckyMovementAlgorithmBase(); + + /** + * Solve for left/right wheels. + * @param Left - The return left wheel torque. + * @param Right - The return right wheel torque. + */ + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Algo") + void SolveForLeftRight(float& Left, float& Right); + + /** + * Base initialization function. + * @param InInputVector - The input vector that we store. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category="Algo") + void Init(AActor* InOwningActor, const FVector& InInputVector); + +private: + + UPROPERTY() + AActor* OwningActor; + + UPROPERTY() + FVector CurrentInputVector; + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/Components/LuckyCustomMovementComponent.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Components/LuckyCustomMovementComponent.h new file mode 100644 index 00000000..8ec12a1e --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Components/LuckyCustomMovementComponent.h @@ -0,0 +1,259 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CPathFindPath.h" +#include "Components/ActorComponent.h" +#include "CPathVolume.h" +#include "Algo/LuckyMovementAlgorithmBase.h" +#include "LuckyCustomMovementComponent.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnLuckyMovementFinished, ULuckyCustomMovementComponent*, Component, ULuckyMovementAlgorithmBase*, Algo); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLuckyMovementFailed, ULuckyCustomMovementComponent*, Component); +DECLARE_DELEGATE_TwoParams(FOnLuckyMovementFinishedNative, ULuckyCustomMovementComponent*, ULuckyMovementAlgorithmBase*); +DECLARE_DELEGATE_OneParam(FOnLuckyMovementFailedNative, ULuckyCustomMovementComponent*); + +/** + * Custom movement component that uses the CPathfinding plugin. + * To use the component, call MoveToLocation and pass through your target location. + * When movement is completed OnLuckyMovementFinished will be broadcast with a pointer to the LuckyMovementAlgorithmBase object. + * When the delegate is broadcast, just call the Solve function that you need from the Algo object when the delegate fires and pass the values into the MuJoCo system. + */ +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class LUCKYWORLD_API ULuckyCustomMovementComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + // Sets default values for this component's properties + ULuckyCustomMovementComponent(); + + /** + * Notify that movement has finished. + * @return Component - The component that called the delegate. I like to do this to make it easier to reference if needed. + * @return Algo - The constructed algorithm that will store the property reference. You can take this reference and call your desired solve function to return the values you need. + */ + UPROPERTY(BlueprintAssignable,Category = "Movement") + FOnLuckyMovementFinished OnLuckyMovementFinished; + + /** + * Notify that movement has failed. + * @return Component - The component that called the delegate. I like to do this to make it easier to reference if needed. + */ + UPROPERTY(BlueprintAssignable,Category = "Movement") + FOnLuckyMovementFailed OnLuckyMovementFailed; + + FOnLuckyMovementFinishedNative OnLuckyMovementFinishedNative; + FOnLuckyMovementFailedNative OnLuckyMovementFailedNative; + + /** + * The movement algorithm for converting the final input vector to a usable left/right torque for the MuJoCo simulation. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement") + TSoftClassPtr MovementAlgorithm; + + /** + * If true, we scale the volume on begin play. + * If you do this, you need to make sure the volume does not generate itself on play or you will run into major performance issues. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement") + bool bAutoScalePathfindingVolume = false; + + /** + * If true, we try to find a path if the failed delegate fires. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement") + bool bRetryPathfinding = true; + + /** + * If true, we will run another pathfinding task in parallel with the PerformMovement() function to make sure we have the best path buffer. + * WARNING::This is dangerous if you are running pathfinding at a constant interval. + * Only set this value if you are running this once between waypoints. + * For example, if this is running on tick, set this to false, but if we are running this in the state tree then it should be fine since the state runs to completion. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement") + bool bRecheckPath = true; + + /** + * If true, we will draw our current path to the next node. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement|Debug") + bool bDrawPath = true; + + /** + * If true, we will draw our current path points to the next node. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement|Debug") + bool bDrawPathPoints = true; + + /** + * If true, we will draw debug nodes around the Actor location. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement|Debug") + bool bDrawDebugNodes = true; + + /** + * Determines how many times we re-run pathfinding to find the most optimal path. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement") + int32 PathfindingSmoothingPasses = 5; + + /** + * User data to help with filtering multiple objects. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement") + int32 PathfindingUserData = 0; + + /** + * The maximum amount of voxels we draw if debugging. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement|Debug") + int32 DebugNodesVoxelLimit = 600; + + /** + * Determines frequently we recheck the current path. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement") + float PathRecheckRate = 0.5f; + + /** + * Determines how long we have until we "time out" when finding a new path. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement") + float PathfindingTimeLimit = 0.2f; + + /** + * Determines how far two nodes have to be considered for movement. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement") + float NodeDistanceTolerance = 60.f; + + /** + * Determines how fast we check out node buffer when building our path. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement") + float NodeDistanceCheckRate = 0.02f; + + /** + * Determines long our path debug lasts on screen. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement|Debug") + float DrawPathDuration = 0.2f; + + /** + * Determines long our node debug lasts on screen. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement|Debug") + float DrawNodesDuration = 0.2f; + + /** + * The color of our debug path + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement|Debug") + FColor DebugPathColor = FColor::Green; + + /** + * In some cases we might need a Z offset for pathfinding. + * TODO::Find out why this is happening. + */ + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Movement") + FVector LocationZOffset = FVector(0.f,0.f,128.f); + +protected: + // Called when the game starts + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + /** + * Move to the desired location. + * @param TargetLocation - The location we want to move to. + * @param PathVolume - The path volume we use to compute navigation. If nullptr, we find a path volume that is overlapping the owner pawn. + */ + UFUNCTION(BlueprintCallable,Category = "Movement") + void MoveToLocation(const FVector& TargetLocation, ACPathVolume* PathVolume = nullptr, AActor* InOverrideActor = nullptr); + + UFUNCTION(BlueprintPure,Category = "Movement|Getters") + TArray GetPathBuffer() const{ return PathBuffer;} + + UFUNCTION(BlueprintPure,Category = "Movement|Getters") + ACPathVolume* GetCurrentPathVolume() const{ return CurrentPathVolume; } + + UFUNCTION(BlueprintPure,Category = "Movement|Getters") + ACPathVolume* GetPathfindingVolume(); + + UFUNCTION(BlueprintPure,Category = "Movement|Getters") + AActor* GetActor() const{ return Actor;} + + UFUNCTION(BlueprintPure,Category = "Movement|Getters") + UCPathAsyncFindPath* GetRequest() const{ return Request;} + + UFUNCTION(BlueprintPure,Category = "Movement|Getters") + bool FindingPath() const{ return bFindingPath;} + + UFUNCTION(BlueprintPure,Category = "Movement|Getters") + int32 GetCurrentNodeIndex() const{ return CurrentNodeIndex;} + + UFUNCTION(BlueprintPure,Category = "Movement|Getters") + FVector GetCurrentInputVector() const{ return CurrentInputVector;} + + UFUNCTION(BlueprintPure,Category = "Movement|Getters") + FVector GetCurrentTargetLocation() const{ return CurrentTargetLocation;} + +private: + + UFUNCTION() + void PathfindingSuccess(const TArray& Path, TEnumAsByte FailReason); + + UFUNCTION() + void PathfindingFailed(const TArray& Path, TEnumAsByte FailReason); + + UFUNCTION() + void RecheckPathfindingSuccess(const TArray& Path, TEnumAsByte FailReason); + + UFUNCTION() + void RecheckPathfindingFailed(const TArray& Path, TEnumAsByte FailReason); + + UFUNCTION() + int32 GetNextOptimalNode(int32 InNodeIndex) const; + + UFUNCTION() + float GetDotToNode(const FCPathNode& CurrentNode) const; + + UFUNCTION() + void DrawPath(); + + UFUNCTION() + void PerformMovement(); + + UFUNCTION() + void RecheckPath(); + + UPROPERTY() + TArray PathBuffer; + + UPROPERTY() + ACPathVolume* CurrentPathVolume; + + UPROPERTY() + AActor* Actor; + + UPROPERTY() + UCPathAsyncFindPath* Request; + + UPROPERTY() + bool bFindingPath = false; + + UPROPERTY() + int32 CurrentNodeIndex = 0; + + UPROPERTY() + FVector CurrentInputVector = FVector::ZeroVector; + + UPROPERTY() + FVector CurrentTargetLocation = FVector::ZeroVector; + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/Core/LuckyDataManager.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Core/LuckyDataManager.h new file mode 100644 index 00000000..e4bada40 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Core/LuckyDataManager.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Subsystems/WorldSubsystem.h" +#include "LuckyDataManager.generated.h" + +/** + * + */ +UCLASS() +class LUCKYWORLD_API ULuckyDataManager : public UWorldSubsystem +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/Core/LuckyWidgetManager.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Core/LuckyWidgetManager.h new file mode 100644 index 00000000..3953cf09 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Core/LuckyWidgetManager.h @@ -0,0 +1,60 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Subsystems/WorldSubsystem.h" +#include "LuckyWidgetManager.generated.h" + +/** + * + */ +UCLASS() +class LUCKYWORLD_API ULuckyWidgetManager : public UWorldSubsystem +{ + GENERATED_BODY() + +public: + + /** + * Create and register the game widget. + * @param OwningPlayer - The player who owns the widget. + * @param Value - The return widget. + * @return - True if we have a valid game widget class and the widget is valid. + */ + UFUNCTION(BlueprintCallable,Category = "LuckyWorld") + bool CreateGameWidget(APlayerController* OwningPlayer, UUserWidget*& Value); + + /** + * Tell the GameWidget to call it's SetCameraTextures interface function. + * @return - True if we have a valid game widget and it implements ILuckyGameWidget. + */ + UFUNCTION(BlueprintCallable,Category = "LuckyWorld") + bool SetCameraTextures(); + + /** + * Show camera settings widget. + * @return - True if everything is valid. + */ + UFUNCTION(BlueprintCallable,Category="LuckyGameWidget") + bool ShowCameraSettings(); + + /** + * Hide camera settings widget. + * @return - True if everything is valid. + */ + UFUNCTION(BlueprintCallable,Category="LuckyGameWidget") + bool HideCameraSettings(); + + /** + * @return - GameWidget + */ + UFUNCTION(BlueprintPure,Category = "LuckyWorld|Getters") + UUserWidget* GetGameWidget() const; + +private: + + UPROPERTY() + UUserWidget* GameWidget; + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/Core/LuckyWorldSettings.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Core/LuckyWorldSettings.h new file mode 100644 index 00000000..eb5beb23 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Core/LuckyWorldSettings.h @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DeveloperSettings.h" +#include "Blueprint/UserWidget.h" +#include "LuckyWorldSettings.generated.h" + +/** + * + */ +UCLASS(config = Game, defaultconfig, meta = (DisplayName = "Lucky World Settings")) +class LUCKYWORLD_API ULuckyWorldSettings : public UDeveloperSettings +{ + + GENERATED_BODY() + +public: + + static const ULuckyWorldSettings* GetLuckyWorldSettings() { return GetDefault(); } + + /** + * Override game data manager class for the lucky data manager. + */ + UPROPERTY(config, EditAnywhere, BlueprintReadWrite, Category = "LuckyWorld") + TSoftClassPtr GameWidgetClass; + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/Lib/LuckyGameWidget.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Lib/LuckyGameWidget.h new file mode 100644 index 00000000..37197a98 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Lib/LuckyGameWidget.h @@ -0,0 +1,48 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" + +#include "LuckyGameWidget.generated.h" + +// This class does not need to be modified. +UINTERFACE(MinimalAPI) +class ULuckyGameWidget : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class LUCKYWORLD_API ILuckyGameWidget +{ + GENERATED_BODY() + + // Add interface functions to this class. This is the class that will be inherited to implement this interface. +public: + + /** + * Set the camera textures for the simulation game widget. + * @return - True if everything is valid. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category="LuckyGameWidget") + bool SetCameraTextures(); + + /** + * Show camera settings widget. + * @return - True if everything is valid. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category="LuckyGameWidget") + bool ShowCameraSettings(); + + /** + * Hide camera settings widget. + * @return - True if everything is valid. + */ + UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category="LuckyGameWidget") + bool HideCameraSettings(); + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/Lib/LuckyWorldFunctions.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Lib/LuckyWorldFunctions.h new file mode 100644 index 00000000..b1160467 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/Lib/LuckyWorldFunctions.h @@ -0,0 +1,72 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "AI/PickAndPlaceManager.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "LuckyWorldFunctions.generated.h" + +/** + * + */ +UCLASS() +class LUCKYWORLD_API ULuckyWorldFunctions : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + + /** + * Get the pick and place manager. + * @param WorldContextObject - The world context owner. + * @return - The first pick and place manager. + */ + UFUNCTION(BlueprintCallable,Category = "LuckyWorld|PickAndPlace", meta = (WorldContext = "WorldContextObject")) + static APickAndPlaceManager* GetPickAndPlaceManager(UObject* WorldContextObject); + + /** + * Save a render target (texture target from scene capture component 2D) to disk. + * @param RenderTarget - The render target to save to disk. + * @param Filename - The path for the file. + * @param bAsPNG - If true, we write as a png. + * @param bFlipVertically - If true, we will flip the pixels. + * @return - True if saved. + */ + UFUNCTION(BlueprintCallable,Category = "LuckyWorld|Utils|Images") + static bool SaveRenderTargetToDisk(UTextureRenderTarget2D* RenderTarget, const FString& Filename, bool bAsPNG = true, bool bFlipVertically = false); + + /** + * Save a texture to disk. + * @param Texture - The texure to save to disk. + * @param Filename - The path for the file. + * @param bAsPNG - If true, we write as a png. + * @param bFlipVertically - If true, we will flip the pixels. + * @return - True if saved. + */ + UFUNCTION(BlueprintCallable,Category = "LuckyWorld|Utils|Images") + static bool SaveTextureToDisk(UTexture2D* Texture, const FString& Filename, bool bAsPNG = true, bool bFlipVertically = true); + + /** + * Convert a TMap to a json struct. + * @param InMap - The Map to convert to a string. + * @return - The JSON string. + */ + UFUNCTION(BlueprintPure,Category = "LuckyWorld|Utils", meta = (BlueprintAutocast, CompactNodeTitle = "->")) + static FString ConvertMapToJsonString(const TMap& InMap); + + /** + * Convert a FVector to a json struct. + * @param Vector - The Vector to convert to a string. + * @return - The JSON string. + */ + UFUNCTION(BlueprintPure,Category = "LuckyWorld|Utils", meta = (BlueprintAutocast, CompactNodeTitle = "->")) + static FString FVectorToJsonString(const FVector& Vector); + + /** + * @return - Lucky World Settings. + */ + UFUNCTION(BlueprintPure,Category = "LuckyWorld|Utils") + static const ULuckyWorldSettings* GetLuckyWorldSettings(); + +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/LuckyWorld.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/LuckyWorld.h new file mode 100644 index 00000000..6c05b6c1 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/LuckyWorld.h @@ -0,0 +1,14 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "Modules/ModuleManager.h" + +class FLuckyWorldModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/Plugins/LuckyWorld/Source/LuckyWorld/Public/World/LLMWorldManager.h b/Plugins/LuckyWorld/Source/LuckyWorld/Public/World/LLMWorldManager.h new file mode 100644 index 00000000..6817d203 --- /dev/null +++ b/Plugins/LuckyWorld/Source/LuckyWorld/Public/World/LLMWorldManager.h @@ -0,0 +1,40 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DirectionalLight.h" +#include "GameFramework/Actor.h" +#include "LLMWorldManager.generated.h" + +UCLASS(BlueprintType,Blueprintable) +class LUCKYWORLD_API ALLMWorldManager : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + ALLMWorldManager(); + + UPROPERTY(EditAnywhere,BlueprintReadWrite) + FString CommandPrefix = "World:"; + + UPROPERTY(EditAnywhere,BlueprintReadWrite) + FString GlobalLightingCommandPrefix = "Lighting"; + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + UFUNCTION(BlueprintCallable,BlueprintNativeEvent) + void ProcessLLMCommand(const FString& Command); + +private: + + TMap DefaultLighting; + +}; diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-CoreUtility.dll b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-CoreUtility.dll index 31626fbb..884479db 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-CoreUtility.dll and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-CoreUtility.dll differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-CoreUtility.exp b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-CoreUtility.exp index 81e49774..a0761afe 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-CoreUtility.exp and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-CoreUtility.exp differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-CoreUtility.pdb b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-CoreUtility.pdb index 1411b0af..48b94d2e 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-CoreUtility.pdb and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-CoreUtility.pdb differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJEditorPlugin.dll b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJEditorPlugin.dll index 7e88c4e3..c1098a2e 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJEditorPlugin.dll and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJEditorPlugin.dll differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJEditorPlugin.exp b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJEditorPlugin.exp index 4cab3b40..ce24dae4 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJEditorPlugin.exp and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJEditorPlugin.exp differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJEditorPlugin.pdb b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJEditorPlugin.pdb index 1541b95d..47e88d21 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJEditorPlugin.pdb and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJEditorPlugin.pdb differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJson.dll b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJson.dll index f9082dae..3feab71f 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJson.dll and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJson.dll differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJson.exp b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJson.exp index 0d9b8de6..91359871 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJson.exp and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJson.exp differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJson.pdb b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJson.pdb index ace58a81..85f79146 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJson.pdb and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SIOJson.pdb differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOClient.dll b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOClient.dll index f102f52b..c6d68285 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOClient.dll and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOClient.dll differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOClient.exp b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOClient.exp index dc90f243..126dd8f4 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOClient.exp and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOClient.exp differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOClient.pdb b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOClient.pdb index ad1add65..78f3904e 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOClient.pdb and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOClient.pdb differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOLib.dll b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOLib.dll index 43b33b6e..ee4ef03d 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOLib.dll and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOLib.dll differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOLib.exp b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOLib.exp index fdd3c34b..0f138b1d 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOLib.exp and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOLib.exp differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOLib.pdb b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOLib.pdb index 4a816bd1..485292ee 100644 Binary files a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOLib.pdb and b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor-SocketIOLib.pdb differ diff --git a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor.modules b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor.modules index 63e035e7..d834f3b5 100644 --- a/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor.modules +++ b/Plugins/SocketIOClient/Binaries/Win64/UnrealEditor.modules @@ -1,5 +1,5 @@ { - "BuildId": "37670630", + "BuildId": "827e4aed-aff1-4853-85bd-51def0d581c9", "Modules": { "CoreUtility": "UnrealEditor-CoreUtility.dll", diff --git a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRest.dll b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRest.dll index de6e1e97..b56e72bb 100644 Binary files a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRest.dll and b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRest.dll differ diff --git a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRest.exp b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRest.exp index e0b8a6b8..d97058cb 100644 Binary files a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRest.exp and b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRest.exp differ diff --git a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRest.pdb b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRest.pdb index 42f527f9..20328007 100644 Binary files a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRest.pdb and b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRest.pdb differ diff --git a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRestEditor.dll b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRestEditor.dll index d6d047a7..be06ffa0 100644 Binary files a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRestEditor.dll and b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRestEditor.dll differ diff --git a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRestEditor.exp b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRestEditor.exp index c4d0a80c..d9bcf118 100644 Binary files a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRestEditor.exp and b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRestEditor.exp differ diff --git a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRestEditor.pdb b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRestEditor.pdb index 3893857c..c069cfb1 100644 Binary files a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRestEditor.pdb and b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor-VaRestEditor.pdb differ diff --git a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor.modules b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor.modules index 5e46479c..3ced2b21 100644 --- a/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor.modules +++ b/Plugins/VaRestPlugin/Binaries/Win64/UnrealEditor.modules @@ -1,5 +1,5 @@ { - "BuildId": "37670630", + "BuildId": "827e4aed-aff1-4853-85bd-51def0d581c9", "Modules": { "VaRest": "UnrealEditor-VaRest.dll", diff --git a/README.md b/README.md index 07db023c..bc36d6ed 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,199 @@ -# LuckyWorldV2 +

+ Lucky World Simulator +

+

+ Infinite Synthetic Data Generation for Embodied AI +

+ +
+ +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![UE Version](https://img.shields.io/badge/Unreal%20Engine-5.5-blue)](https://www.unrealengine.com/) +[![Discord](https://dcbadge.vercel.app/api/server/5CH3wx3tAs?style=flat)](https://discord.gg/5CH3wx3tAs) + +
+ +

+ +

+ +## Overview + +Lucky World is a state-of-the-art simulator built by Lucky Robots to create hyperrealistic environment interactions using the power of Unreal Engine 5 and MuJoCo physics. Designed from the ground up for robotic learning, Lucky World enables you to generate infinitely many hyperrealistic demonstrations for training robust robotic systems that can easily bridge the gap the sim2real gap. + +

+ Bedroom environment + Loft environment +

+ + +## Core Technology + +- **Unreal Engine 5** - Leveraging Nanite virtualized micropolygon geometry and Lumen global illumination for immaculate visual fidelity +- **MuJoCo Physics** - Industry-leading physics simulation ensuring accurate object interactions, contacts, and material properties +- **Procedural Generation** - Dynamic environment creation with randomized object placement, lighting conditions, and material properties +- **Sensor Simulation** - High-fidelity simulated sensors including RGB cameras, depth sensors, LiDAR, and IMUs + +## Features + +- **Hyperrealistic Environments** - Meticulously crafted indoor scenes with physically based materials and lighting +- **Dynamic Interactions** - Fully interactive objects with realistic physics responses and material properties +- **Advanced Robotics** - Pre-configured robots including Stretch v1 and Franka Arm with accurate kinematic models +- **Configurable Difficulty** - Adjustable environment complexity, lighting conditions, and object arrangements +- **Data Collection** - Built-in tools for capturing ground truth data, including depth maps, segmentation masks, and bounding boxes +- **Real-time Rendering** - Optimized for real-time performance on modern hardware + +## System Requirements + +- **Operating Systems**: Windows 10/11, macOS, Linux (Ubuntu 20.04+) +- **Hardware**: + - GPU: NVIDIA GTX 1080 or AMD equivalent (minimum), RTX 3080 or equivalent (recommended) + - CPU: 8-core processor (recommended) + - RAM: 16GB (minimum), 32GB (recommended) + - Storage: 50GB available SSD space +- **Software**: + - Unreal Engine 5.5 + - Git LFS + - Visual Studio 2022 or Rider (Windows) + - Xcode 14+ (macOS) + - Clang or GCC (Linux) + +## Installation + +Follow these steps to pull down the source code and compile the project: + +### 1. Clone the Repository + +**Important**: Don't download the .zip file. It's best to use the CLI or a visual tool so Git LFS can install the proper libraries. + +```bash +git clone https://luckyrobots.com/luckyrobots/luckyworld.git +cd luckyworld +``` + +### 2. Install Git LFS + +Install Git LFS based on your operating system: + +**macOS**: +```bash +brew install git-lfs +``` + +**Linux**: +```bash +sudo yum install git-lfs +``` + +**Windows**: +```bash +# Install via Visual Installer +# https://git-scm.com/download/win +# (Be sure to select the option to install git-lfs) + +# Or via Chocolatey +choco install git +``` + +### 3. Pull LFS Files + +Run this command to ensure all large binary files are properly downloaded: + +```bash +git lfs pull +``` + +### 4. Setup Project Files + +**Windows**: +- Right-click the `.uproject` file +- Select "Generate Visual Studio Project Files" +- Open the generated `.sln` file with your IDE (i.e. Visual Studio or Rider) + +**macOS/Linux**: +- Right-click the `.uproject` file +- Follow platform-specific steps to generate project files + +### 5. Engine Version Note + +The project starts in UE 5.5 binary version. If you're using source: +- Right-click the `.uproject` file +- Select "Switch Unreal Engine version..." +- Choose your installed engine version + +### 6. Build and Run + +- Debug 'luckyrobots' + +## Using Lucky World + +### Editor Mode + +Lucky World can be used directly in the Unreal Editor for: + +1. **Environment Creation**: + - Design custom environments using UE5's powerful editor tools + - Place and configure objects, furniture, and obstacles + - Adjust lighting, materials, and atmospheric conditions + +2. **Robot Configuration**: + - Configure robot parameters through the Robot Blueprint editor + - Adjust sensor placement, field of view, and resolution + - Calibrate physics parameters for realistic robot movement + +3. **Simulation Settings**: + - Set simulation frame rate and physics substeps + - Configure environment difficulty and randomization parameters + - Adjust camera properties and sensor noise levels + +### Standalone Mode + +For pure simulation or data collection: + +1. Package the project (File > Package Project) +2. Run the standalone executable +3. Configure simulation parameters via the settings menu +4. Collect data using the built-in recording tools + +## Configuration + +### Environments + +Lucky World includes several pre-built environments: + +- Loft +- Rome +- Paris +- Marseille +- Istanbul +- Kitchen (for Panda Arm) + +Each environment can be customized through the Content Browser (`Content/Environments/`). + +## Troubleshooting + +### Common Issues + +**Missing Assets / LFS Files**: +```bash +git lfs install +git lfs pull +``` + +**Compilation Errors**: +- Verify correct Unreal Engine version is selected +- Clear derived data folder (`[Engine]/DerivedDataCache/`) +- Rebuild project + +**Performance Issues**: +- Adjust rendering settings in `Edit > Project Settings > Engine > Rendering` +- Lower simulation physics detail in `Edit > Project Settings > Engine > Physics` + +**Crashes on Startup**: +- Check logs in `[ProjectFolder]/Saved/Logs/` +- Verify GPU drivers are up to date + +## License + +Lucky World is licensed under the Polyform License - see the [LICENSE](LICENSE) file for details. \ No newline at end of file