CogEngine: improve collision tester

This commit is contained in:
Arnaud Jamin
2023-12-30 01:28:01 -05:00
parent 81fc6269ad
commit dd20cff959
7 changed files with 318 additions and 165 deletions
+16 -13
View File
@@ -88,35 +88,37 @@ ManualIPAddress=
-Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.",bCanModify=False)
-Profiles=(Name="UI",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Block),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False)
+Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision")
+Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=,HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.")
+Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ")
+Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ")
+Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic"),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.")
+Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="CharacterMesh",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.")
+Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Projectile")),HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap),(Channel="Projectile",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Projectile")),HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap),(Channel="Projectile",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Projectile")),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.")
+Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Projectile")),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ")
+Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ")
+Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.")
+Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="CharacterMesh",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Projectile",Response=ECR_Overlap)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.")
+Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors")
+Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors")
+Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.")
+Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.")
+Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.")
+Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.")
+Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.")
+Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.")
+Profiles=(Name="UI",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="UI",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="ProjectileCollision",CollisionEnabled=QueryOnly,bCanModify=True,ObjectTypeName="Projectile",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore),(Channel="CharacterMesh",Response=ECR_Overlap)),HelpMessage="Needs description")
+Profiles=(Name="ProjectileAssistance",CollisionEnabled=QueryOnly,bCanModify=True,ObjectTypeName="Projectile",CustomResponses=((Channel="WorldStatic",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore),(Channel="CharacterMesh",Response=ECR_Overlap)),HelpMessage="Needs description")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Ignore,bTraceType=False,bStaticObject=False,Name="CharacterMesh")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,DefaultResponse=ECR_Ignore,bTraceType=False,bStaticObject=False,Name="Projectile")
+EditProfiles=(Name="Pawn",CustomResponses=((Channel="Camera",Response=ECR_Ignore),(Channel="Projectile",Response=ECR_Ignore)))
+EditProfiles=(Name="CharacterMesh",CustomResponses=((Channel="Camera",Response=ECR_Ignore),(Channel="Projectile",Response=ECR_Overlap)))
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel3,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="TraceCustom")
+EditProfiles=(Name="Pawn",CustomResponses=((Channel="Camera",Response=ECR_Ignore),(Channel="Projectile",Response=ECR_Ignore),(Channel="TraceCustom")))
+EditProfiles=(Name="CharacterMesh",CustomResponses=((Channel="Camera",Response=ECR_Ignore),(Channel="Projectile",Response=ECR_Overlap),(Channel="TraceCustom",Response=ECR_Ignore)))
+EditProfiles=(Name="BlockAll",CustomResponses=((Channel="Projectile")))
+EditProfiles=(Name="OverlapAll",CustomResponses=((Channel="Projectile",Response=ECR_Overlap)))
+EditProfiles=(Name="BlockAllDynamic",CustomResponses=((Channel="Projectile")))
+EditProfiles=(Name="OverlapAllDynamic",CustomResponses=((Channel="Projectile",Response=ECR_Overlap)))
+EditProfiles=(Name="IgnoreOnlyPawn",CustomResponses=((Channel="Projectile")))
+EditProfiles=(Name="OverlapOnlyPawn",CustomResponses=((Channel="Projectile")))
+EditProfiles=(Name="Spectator",CustomResponses=((Channel="TraceCustom",Response=ECR_Ignore)))
-ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall")
-ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn")
-ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic")
@@ -135,4 +137,5 @@ ManualIPAddress=
+CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic")
+CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle")
+CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn")
+CollisionChannelRedirects=(OldName="Test",NewName="TraceCustom")
@@ -110,7 +110,7 @@ struct FCogDebugSettings
TEnumAsByte<ECollisionChannel> GizmoGroundRaycastChannel = ECollisionChannel::ECC_WorldStatic;
UPROPERTY(Config)
float GizmoGroundRaycastCircleRadius = 10.f;
float GizmoGroundRaycastCircleRadius = 5.0f;
UPROPERTY(Config)
FColor GizmoAxisColorsZHighX = FColor(255, 50, 50, 255);
@@ -35,6 +35,75 @@ void FCogEngineWindow_CollisionTester::ResetConfig()
Config->Reset();
}
//--------------------------------------------------------------------------------------------------------------------------
bool RenderCollisionProfileChannels(const UCollisionProfile& CollisionProfileChannels, int32& Channels, const TArray<FCogCollisionChannel>& ChannelsConfig)
{
bool Result = false;
for (const FCogCollisionChannel& ChannelConfig : ChannelsConfig)
{
const ECollisionChannel Channel = ChannelConfig.Channel.GetValue();
ImGui::PushID(Channel);
ImColor Color = FCogImguiHelper::ToImColor(ChannelConfig.Color);
ImGui::ColorEdit4("Color", (float*)&Color.Value, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
ImGui::SameLine();
bool IsCollisionActive = (Channels & ECC_TO_BITFIELD(Channel)) > 0;
const FName ChannelName = CollisionProfileChannels.ReturnChannelNameFromContainerIndex(Channel);
if (ImGui::Checkbox(TCHAR_TO_ANSI(*ChannelName.ToString()), &IsCollisionActive))
{
Result = true;
if (IsCollisionActive)
{
Channels |= ECC_TO_BITFIELD(Channel);
}
else
{
Channels &= ~ECC_TO_BITFIELD(Channel);
}
}
ImGui::PopID();
}
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
bool RenderComboCollisionChannel(const char* Label, const UCollisionProfile& CollisionProfile, ECollisionChannel& SelectedChannel, const TArray<FCogCollisionChannel>& ChannelsConfig)
{
const FName SelectedChannelName = CollisionProfile.ReturnChannelNameFromContainerIndex(SelectedChannel);
bool Result = false;
if (ImGui::BeginCombo(Label, TCHAR_TO_ANSI(*SelectedChannelName.ToString()), ImGuiComboFlags_HeightLarge))
{
for (const FCogCollisionChannel& ChannelConfig : ChannelsConfig)
{
const ECollisionChannel Channel = ChannelConfig.Channel.GetValue();
ImGui::PushID(Channel);
const FName ChannelName = CollisionProfile.ReturnChannelNameFromContainerIndex(Channel);
ImColor Color = FCogImguiHelper::ToImColor(ChannelConfig.Color);
ImGui::ColorEdit4("Color", (float*)&Color.Value, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
ImGui::SameLine();
if (ImGui::Selectable(TCHAR_TO_ANSI(*ChannelName.ToString())))
{
SelectedChannel = Channel;
Result = true;
}
ImGui::PopID();
}
ImGui::EndCombo();
}
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_CollisionTester::RenderContent()
{
@@ -82,6 +151,9 @@ void FCogEngineWindow_CollisionTester::RenderContent()
FCogWindowWidgets::SetNextItemToShortWidth();
FCogWindowWidgets::ComboboxEnum("Type", Config->Type);
FCogWindowWidgets::SetNextItemToShortWidth();
FCogWindowWidgets::ComboboxEnum("Mode", Config->Mode);
FCogWindowWidgets::SetNextItemToShortWidth();
FCogWindowWidgets::ComboboxEnum("By", Config->By);
@@ -92,7 +164,7 @@ void FCogEngineWindow_CollisionTester::RenderContent()
{
FCogWindowWidgets::SetNextItemToShortWidth();
ECollisionChannel Channel = Config->Channel.GetValue();
if (FCogWindowWidgets::ComboCollisionChannel("Channel", Channel))
if (RenderComboCollisionChannel("Channel", *CollisionProfile, Channel, Asset->Channels))
{
Config->Channel = Channel;
}
@@ -103,7 +175,7 @@ void FCogEngineWindow_CollisionTester::RenderContent()
else if (Config->By == ECogEngine_CollisionQueryBy::Profile)
{
const FCollisionResponseTemplate* SelectedProfile = CollisionProfile->GetProfileByIndex(Config->ProfileIndex);
FName SelectedProfileName = SelectedProfile != nullptr ? SelectedProfile->Name : FName("Custom");
const FName SelectedProfileName = SelectedProfile != nullptr ? SelectedProfile->Name : FName("Custom");
FCogWindowWidgets::SetNextItemToShortWidth();
if (ImGui::BeginCombo("Profile", TCHAR_TO_ANSI(*SelectedProfileName.ToString()), ImGuiComboFlags_HeightLargest))
@@ -121,7 +193,7 @@ void FCogEngineWindow_CollisionTester::RenderContent()
{
for (int j = 0; j < ECC_MAX; ++j)
{
ECollisionResponse Response = Profile->ResponseToChannels.GetResponse((ECollisionChannel)j);
const ECollisionResponse Response = Profile->ResponseToChannels.GetResponse((ECollisionChannel)j);
if (Response != ECR_Ignore)
{
Config->ObjectTypesToQuery |= ECC_TO_BITFIELD(j);
@@ -132,52 +204,13 @@ void FCogEngineWindow_CollisionTester::RenderContent()
}
ImGui::EndCombo();
}
ImGui::Separator();
//-------------------------------------------------
// Query Filtering
//-------------------------------------------------
for (int ChannelIndex = 0; ChannelIndex < (int32)ECC_MAX; ++ChannelIndex)
{
const FChannel& Channel = Channels[ChannelIndex];
if (Channel.IsValid == false)
{
continue;
}
ImGui::PushID(ChannelIndex);
ImColor Color = FCogImguiHelper::ToImColor(Channel.Color);
ImGui::ColorEdit4("Color", (float*)&Color.Value, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
ImGui::SameLine();
bool IsCollisionActive = (Config->ObjectTypesToQuery & ECC_TO_BITFIELD(ChannelIndex)) > 0;
const FName ChannelName = CollisionProfile->ReturnChannelNameFromContainerIndex(ChannelIndex);
if (ImGui::Checkbox(TCHAR_TO_ANSI(*ChannelName.ToString()), &IsCollisionActive))
{
if (IsCollisionActive)
{
Config->ObjectTypesToQuery |= ECC_TO_BITFIELD(ChannelIndex);
Config->ProfileIndex = INDEX_NONE;
}
else
{
Config->ObjectTypesToQuery &= ~ECC_TO_BITFIELD(ChannelIndex);
Config->ProfileIndex = INDEX_NONE;
}
}
ImGui::PopID();
}
}
ImGui::Checkbox("Multi", &Config->MultiHits);
ImGui::Checkbox("Complex", &Config->TraceComplex);
//-------------------------------------------------
// Shape
//-------------------------------------------------
ImGui::Separator();
if (Config->Type != ECogEngine_CollisionQueryType::LineTrace)
{
@@ -186,32 +219,49 @@ void FCogEngineWindow_CollisionTester::RenderContent()
switch (Config->Shape)
{
case ECogEngine_CollisionQueryShape::Sphere:
{
FCogWindowWidgets::SetNextItemToShortWidth();
FCogImguiHelper::DragDouble("Sphere Radius", &Config->ShapeExtent.X, 0.1f, 0, FLT_MAX, "%.1f");
break;
}
case ECogEngine_CollisionQueryShape::Sphere:
{
FCogWindowWidgets::SetNextItemToShortWidth();
FCogImguiHelper::DragDouble("Sphere Radius", &Config->ShapeExtent.X, 0.1f, 0, FLT_MAX, "%.1f");
break;
}
case ECogEngine_CollisionQueryShape::Box:
{
FCogWindowWidgets::SetNextItemToShortWidth();
FCogImguiHelper::DragFVector("Box Extent", Config->ShapeExtent, 0.1f, 0, FLT_MAX, "%.1f");
break;
}
case ECogEngine_CollisionQueryShape::Box:
{
FCogWindowWidgets::SetNextItemToShortWidth();
FCogImguiHelper::DragFVector("Box Extent", Config->ShapeExtent, 0.1f, 0, FLT_MAX, "%.1f");
break;
}
case ECogEngine_CollisionQueryShape::Capsule:
{
FCogWindowWidgets::SetNextItemToShortWidth();
FCogImguiHelper::DragDouble("Capsule Radius", &Config->ShapeExtent.X, 0.1f, 0, FLT_MAX, "%.1f");
case ECogEngine_CollisionQueryShape::Capsule:
{
FCogWindowWidgets::SetNextItemToShortWidth();
FCogImguiHelper::DragDouble("Capsule Radius", &Config->ShapeExtent.X, 0.1f, 0, FLT_MAX, "%.1f");
FCogWindowWidgets::SetNextItemToShortWidth();
FCogImguiHelper::DragDouble("Capsule Half Height", &Config->ShapeExtent.Z, 0.1f, 0, FLT_MAX, "%.1f");
break;
}
FCogWindowWidgets::SetNextItemToShortWidth();
FCogImguiHelper::DragDouble("Capsule Half Height", &Config->ShapeExtent.Z, 0.1f, 0, FLT_MAX, "%.1f");
break;
}
}
}
ImGui::Separator();
//-------------------------------------------------
// Channels
//-------------------------------------------------
if (Config->By == ECogEngine_CollisionQueryBy::Profile)
{
ImGui::BeginDisabled();
RenderCollisionProfileChannels(*CollisionProfile, Config->ObjectTypesToQuery, Asset->Channels);
ImGui::EndDisabled();
}
else if (Config->By == ECogEngine_CollisionQueryBy::ObjectType)
{
RenderCollisionProfileChannels(*CollisionProfile, Config->ObjectTypesToQuery, Asset->Channels);
}
Query();
}
@@ -236,7 +286,10 @@ void FCogEngineWindow_CollisionTester::Query()
static const FName TraceTag(TEXT("FCogWindow_Collision"));
FCollisionQueryParams QueryParams(TraceTag, SCENE_QUERY_STAT_ONLY(CogHitDetection), Config->TraceComplex);
const FCollisionQueryParams QueryParams(TraceTag, SCENE_QUERY_STAT_ONLY(CogHitDetection), Config->TraceComplex);
const FCollisionResponseTemplate* Profile = UCollisionProfile::Get()->GetProfileByIndex(Config->ProfileIndex);
const FName ProfileName = Profile != nullptr ? Profile->Name : FName();
FCollisionShape QueryShape;
@@ -257,25 +310,25 @@ void FCogEngineWindow_CollisionTester::Query()
{
switch (Config->By)
{
case ECogEngine_CollisionQueryBy::Channel:
{
HasHits = GetWorld()->OverlapMultiByChannel(Overlaps, QueryStart, QueryRotation, (ECollisionChannel)Config->Channel, QueryShape, QueryParams);
break;
}
case ECogEngine_CollisionQueryBy::Channel:
{
HasHits = GetWorld()->OverlapMultiByChannel(Overlaps, QueryStart, QueryRotation, Config->Channel, QueryShape, QueryParams);
break;
}
case ECogEngine_CollisionQueryBy::ObjectType:
{
FCollisionObjectQueryParams QueryObjectParams;
QueryObjectParams.ObjectTypesToQuery = Config->ObjectTypesToQuery;
HasHits = GetWorld()->OverlapMultiByObjectType(Overlaps, QueryStart, QueryRotation, QueryObjectParams, QueryShape, QueryParams);
break;
}
case ECogEngine_CollisionQueryBy::ObjectType:
{
FCollisionObjectQueryParams QueryObjectParams;
QueryObjectParams.ObjectTypesToQuery = Config->ObjectTypesToQuery;
HasHits = GetWorld()->OverlapMultiByObjectType(Overlaps, QueryStart, QueryRotation, QueryObjectParams, QueryShape, QueryParams);
break;
}
case ECogEngine_CollisionQueryBy::Profile:
{
HasHits = GetWorld()->OverlapMultiByProfile(Overlaps, QueryStart, QueryRotation, Config->Profile, QueryShape, QueryParams);
break;
}
case ECogEngine_CollisionQueryBy::Profile:
{
HasHits = GetWorld()->OverlapMultiByProfile(Overlaps, QueryStart, QueryRotation, ProfileName, QueryShape, QueryParams);
break;
}
}
break;
@@ -285,62 +338,93 @@ void FCogEngineWindow_CollisionTester::Query()
{
switch (Config->By)
{
case ECogEngine_CollisionQueryBy::Channel:
case ECogEngine_CollisionQueryBy::Channel:
{
switch (Config->Mode)
{
if (Config->MultiHits)
case ECogEngine_CollisionQueryMode::Single:
{
FHitResult Hit;
HasHits = GetWorld()->LineTraceSingleByChannel(Hit, QueryStart, QueryEnd, Config->Channel, QueryParams);
if (HasHits)
{
HasHits = GetWorld()->LineTraceMultiByChannel(Hits, QueryStart, QueryEnd, (ECollisionChannel)Config->Channel, QueryParams);
}
else
{
FHitResult Hit;
HasHits = GetWorld()->LineTraceSingleByChannel(Hit, QueryStart, QueryEnd, (ECollisionChannel)Config->Channel, QueryParams);
if (HasHits)
{
Hits.Add(Hit);
}
Hits.Add(Hit);
}
break;
}
case ECogEngine_CollisionQueryBy::ObjectType:
case ECogEngine_CollisionQueryMode::Multi:
{
FCollisionObjectQueryParams QueryObjectParams;
QueryObjectParams.ObjectTypesToQuery = Config->ObjectTypesToQuery;
HasHits = GetWorld()->LineTraceMultiByChannel(Hits, QueryStart, QueryEnd, Config->Channel, QueryParams);
break;
}
case ECogEngine_CollisionQueryMode::Test:
{
HasHits = GetWorld()->LineTraceTestByChannel(QueryStart, QueryEnd, Config->Channel, QueryParams);
break;
}
}
if (Config->MultiHits)
break;
}
case ECogEngine_CollisionQueryBy::ObjectType:
{
FCollisionObjectQueryParams QueryObjectParams;
QueryObjectParams.ObjectTypesToQuery = Config->ObjectTypesToQuery;
switch (Config->Mode)
{
case ECogEngine_CollisionQueryMode::Single:
{
FHitResult Hit;
HasHits = GetWorld()->LineTraceSingleByObjectType(Hit, QueryStart, QueryEnd, QueryObjectParams, QueryParams);
if (HasHits)
{
HasHits = GetWorld()->LineTraceMultiByObjectType(Hits, QueryStart, QueryEnd, QueryObjectParams, QueryParams);
}
else
{
FHitResult Hit;
HasHits = GetWorld()->LineTraceSingleByObjectType(Hit, QueryStart, QueryEnd, QueryObjectParams, QueryParams);
if (HasHits)
{
Hits.Add(Hit);
}
Hits.Add(Hit);
}
break;
}
case ECogEngine_CollisionQueryBy::Profile:
case ECogEngine_CollisionQueryMode::Multi:
{
if (Config->MultiHits)
HasHits = GetWorld()->LineTraceMultiByObjectType(Hits, QueryStart, QueryEnd, QueryObjectParams, QueryParams);
break;
}
case ECogEngine_CollisionQueryMode::Test:
{
HasHits = GetWorld()->LineTraceTestByObjectType(QueryStart, QueryEnd, QueryObjectParams, QueryParams);
break;
}
}
break;
}
case ECogEngine_CollisionQueryBy::Profile:
{
switch (Config->Mode)
{
case ECogEngine_CollisionQueryMode::Single:
{
FHitResult Hit;
HasHits = GetWorld()->LineTraceSingleByProfile(Hit, QueryStart, QueryEnd, ProfileName, QueryParams);
if (HasHits)
{
GetWorld()->LineTraceMultiByProfile(Hits, QueryStart, QueryEnd, Config->Profile, QueryParams);
}
else
{
FHitResult Hit;
HasHits = GetWorld()->LineTraceSingleByProfile(Hit, QueryStart, QueryEnd, Config->Profile, QueryParams);
if (HasHits)
{
Hits.Add(Hit);
}
Hits.Add(Hit);
}
break;
}
case ECogEngine_CollisionQueryMode::Multi:
{
HasHits = GetWorld()->LineTraceMultiByProfile(Hits, QueryStart, QueryEnd, ProfileName, QueryParams);
break;
}
case ECogEngine_CollisionQueryMode::Test:
{
HasHits = GetWorld()->LineTraceTestByProfile(QueryStart, QueryEnd, ProfileName, QueryParams);
break;
}
}
break;
}
}
break;
}
@@ -351,59 +435,87 @@ void FCogEngineWindow_CollisionTester::Query()
{
case ECogEngine_CollisionQueryBy::Channel:
{
if (Config->MultiHits)
switch (Config->Mode)
{
HasHits = GetWorld()->SweepMultiByChannel(Hits, QueryStart, QueryEnd, QueryRotation, (ECollisionChannel)Config->Channel, QueryShape, QueryParams);
}
else
case ECogEngine_CollisionQueryMode::Single:
{
FHitResult Hit;
HasHits = GetWorld()->SweepSingleByChannel(Hit, QueryStart, QueryEnd, QueryRotation, (ECollisionChannel)Config->Channel, QueryShape, QueryParams);
HasHits = GetWorld()->SweepSingleByChannel(Hit, QueryStart, QueryEnd, QueryRotation, Config->Channel, QueryShape, QueryParams);
if (HasHits)
{
Hits.Add(Hit);
}
break;
}
case ECogEngine_CollisionQueryMode::Multi:
{
HasHits = GetWorld()->SweepMultiByChannel(Hits, QueryStart, QueryEnd, QueryRotation, Config->Channel, QueryShape, QueryParams);
break;
}
case ECogEngine_CollisionQueryMode::Test:
{
HasHits = GetWorld()->SweepTestByChannel(QueryStart, QueryEnd, QueryRotation, Config->Channel, QueryShape, QueryParams);
break;
}
}
break;
}
case ECogEngine_CollisionQueryBy::ObjectType:
{
if (Config->MultiHits)
{
FCollisionObjectQueryParams QueryObjectParams;
QueryObjectParams.ObjectTypesToQuery = Config->ObjectTypesToQuery;
HasHits = GetWorld()->SweepMultiByObjectType(Hits, QueryStart, QueryEnd, QueryRotation, QueryObjectParams, QueryShape, QueryParams);
}
else
{
FCollisionObjectQueryParams QueryObjectParams;
QueryObjectParams.ObjectTypesToQuery = Config->ObjectTypesToQuery;
FCollisionObjectQueryParams QueryObjectParams;
QueryObjectParams.ObjectTypesToQuery = Config->ObjectTypesToQuery;
switch (Config->Mode)
{
case ECogEngine_CollisionQueryMode::Single:
{
FHitResult Hit;
HasHits = GetWorld()->SweepSingleByObjectType(Hit, QueryStart, QueryEnd, QueryRotation, QueryObjectParams, QueryShape, QueryParams);
if (HasHits)
{
Hits.Add(Hit);
}
break;
}
case ECogEngine_CollisionQueryMode::Multi:
{
HasHits = GetWorld()->SweepMultiByObjectType(Hits, QueryStart, QueryEnd, QueryRotation, QueryObjectParams, QueryShape, QueryParams);
break;
}
case ECogEngine_CollisionQueryMode::Test:
{
HasHits = GetWorld()->SweepTestByObjectType(QueryStart, QueryEnd, QueryRotation, QueryObjectParams, QueryShape, QueryParams);
break;
}
}
break;
}
case ECogEngine_CollisionQueryBy::Profile:
{
if (Config->MultiHits)
switch (Config->Mode)
{
HasHits = GetWorld()->SweepMultiByProfile(Hits, QueryStart, QueryEnd, QueryRotation, Config->Profile, QueryShape, QueryParams);
}
else
case ECogEngine_CollisionQueryMode::Single:
{
FHitResult Hit;
HasHits = GetWorld()->SweepSingleByProfile(Hit, QueryStart, QueryEnd, QueryRotation, Config->Profile, QueryShape, QueryParams);
HasHits = GetWorld()->SweepSingleByProfile(Hit, QueryStart, QueryEnd, QueryRotation, ProfileName, QueryShape, QueryParams);
if (HasHits)
{
Hits.Add(Hit);
}
break;
}
case ECogEngine_CollisionQueryMode::Multi:
{
HasHits = GetWorld()->SweepMultiByProfile(Hits, QueryStart, QueryEnd, QueryRotation, ProfileName, QueryShape, QueryParams);
break;
}
case ECogEngine_CollisionQueryMode::Test:
{
HasHits = GetWorld()->SweepTestByProfile(QueryStart, QueryEnd, QueryRotation, ProfileName, QueryShape, QueryParams);
break;
}
}
break;
}
@@ -413,7 +525,6 @@ void FCogEngineWindow_CollisionTester::Query()
}
const FColor Color = HasHits ? FLinearColor(Config->HitColor).ToFColor(true) : FLinearColor(Config->NoHitColor).ToFColor(true);
const bool bUseTrace = Config->Type == ECogEngine_CollisionQueryType::LineTrace || Config->Type == ECogEngine_CollisionQueryType::Sweep;
if (bUseTrace)
{
@@ -12,7 +12,7 @@ struct COGENGINE_API FCogCollisionChannel
GENERATED_BODY()
UPROPERTY(EditAnywhere)
TEnumAsByte<ECollisionChannel> Channel = ECollisionChannel::ECC_WorldStatic;
TEnumAsByte<ECollisionChannel> Channel = ECC_WorldStatic;
UPROPERTY(EditAnywhere)
FLinearColor Color = FLinearColor(0.5f, 0.5f, 0.5f, 1.0f);
@@ -23,10 +23,11 @@ enum class ECogEngine_CollisionQueryType : uint8
//--------------------------------------------------------------------------------------------------------------------------
UENUM()
enum class ECogEngine_CollisionQueryCount : uint8
enum class ECogEngine_CollisionQueryMode : uint8
{
Single,
Multi,
Test,
};
//--------------------------------------------------------------------------------------------------------------------------
@@ -62,7 +63,6 @@ public:
protected:
virtual void ResetConfig() override;
void DoWork(const UCollisionProfile* CollisionProfile);
virtual void RenderHelp() override;
@@ -125,24 +125,21 @@ public:
UPROPERTY(Config)
ECogEngine_CollisionQueryType Type;
UPROPERTY(Config)
ECogEngine_CollisionQueryMode Mode;
UPROPERTY(Config)
ECogEngine_CollisionQueryBy By;
UPROPERTY(Config)
ECogEngine_CollisionQueryShape Shape;
UPROPERTY(Config)
bool MultiHits;
UPROPERTY(Config)
bool TraceComplex;
UPROPERTY(Config)
int32 ObjectTypesToQuery;
UPROPERTY(Config)
FName Profile;
UPROPERTY(Config)
TEnumAsByte<ECollisionChannel> Channel;
@@ -199,8 +196,8 @@ public:
Type = ECogEngine_CollisionQueryType::LineTrace;
By = ECogEngine_CollisionQueryBy::Channel;
Mode = ECogEngine_CollisionQueryMode::Multi;
Channel = ECC_WorldStatic;
MultiHits = false;
TraceComplex = false;
Shape = ECogEngine_CollisionQueryShape::Sphere;
ShapeExtent = FVector(50.0f, 50.0f, 50.0f);
@@ -646,5 +646,44 @@ bool FCogWindowWidgets::ComboCollisionChannel(const char* Label, ECollisionChann
ImGui::EndCombo();
}
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogWindowWidgets::CollisionProfileChannel(const UCollisionProfile& CollisionProfile, const int32 ChannelIndex, int32& Channels)
{
bool Result = false;
bool IsCollisionActive = (Channels & ECC_TO_BITFIELD(ChannelIndex)) > 0;
const FName ChannelName = CollisionProfile.ReturnChannelNameFromContainerIndex(ChannelIndex);
if (ImGui::Checkbox(TCHAR_TO_ANSI(*ChannelName.ToString()), &IsCollisionActive))
{
Result = true;
if (IsCollisionActive)
{
Channels |= ECC_TO_BITFIELD(ChannelIndex);
}
else
{
Channels &= ~ECC_TO_BITFIELD(ChannelIndex);
}
}
return Result;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogWindowWidgets::CollisionProfileChannels(const UCollisionProfile& CollisionProfile, int32& Channels)
{
bool Result = false;
for (int32 ChannelIndex = 0; ChannelIndex < (int32)ECC_MAX; ++ChannelIndex)
{
ImGui::PushID(ChannelIndex);
Result |= CollisionProfileChannel(CollisionProfile, ChannelIndex, Channels);
ImGui::PopID();
}
return Result;
}
@@ -82,6 +82,9 @@ public:
static bool ComboCollisionChannel(const char* Label, ECollisionChannel& Channel);
static bool CollisionProfileChannel(const UCollisionProfile& CollisionProfile, int32 ChannelIndex, int32& Channels);
static bool CollisionProfileChannels(const UCollisionProfile& CollisionProfile, int32& Channels);
};