Anyone know where I can find an entry point for the details pane?

Here’s a fun one I’m having. I have overridden a perception component for my AI, I have the same setup as the default perception in terms of setup, so I don’t change any of that functionality. I override the default perception component using this:

AGBAIController::AGBAIController(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer.SetDefaultSubobjectClass<UCrowdFollowingComponent>(TEXT("PathFollowingComponent")).SetDefaultSubobjectClass<UAITacticalPerceptionComponent>(TEXT("PerceptionComponent")))

So essentially I should get a tactical perception component instead of the default one.

All is good, I have that component and it seems to work ok. Only I’m getting a bug that the AI is sensing its own team! So I go to check the Sense config setup on the component and I notice that the affiliation part isn’t actually drawing its checkboxes in the details pane!

So here’s another quirkyness to my problem… if I copy and paste the component onto the actor, the affiliation checkboxes appear on the copy! Similarly if I do the same on the default component I get the checkboxes displaying.

So I guess two questions: 1) Does anyone know what might interfere with the property system displaying the correct check boxes for the FAISenseAffiliationFilter? or 2) Anyone know where I can actually grab where the details panel is being filled so I can try and see whats up?

Ta for any ideas!

You’re probably just missing the correct metadata on your properties. If you wish to edit your properties, make sure they have EditAnywhere set. There is also VisibleAnywhere for read-only fields.

For example:

UPROPERTY(EditAnywhere, BlueprintReadWrite)
float MySetting;

You can find the full list of available property flags in namespace UP in ObjectBase.h

I don’t think its that, because the area that’s being displayed (basically a set of flags) is actually coming from the base class. So unless somehow you can override the base class selectively (the other properties of the structure are rendering just fine) then I can’t see how that could be the case.

As I said, if I add a new component of the same type, the fields render as expected. If I copy the existing one and paste it the fields render as expected. Its literally just the current one.

Having said that, worth a try because I can tell this isn’t going to go away :slight_smile:

Please post the full declaration of your class(es) then.

Here’s the header…

The declaration is pretty much verbatim from the base class afaik. The thing is, it renders correctly if I add a second one of these to the actor. Or if I copy and paste the original one. So it makes me suspect an issue with deserializing properties somehow. Like it fails to get the property type to draw in the details pane or something.

[FONT=Courier New]// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#pragma once

#include “Perception/AIPerceptionSystem.h”
#include “Perception/AIPerceptionComponent.h”
#include “AITacticalPerceptionComponent.generated.h”

DECLARE_LOG_CATEGORY_EXTERN(LogAITacticalPerception, Warning, All);

struct FTacticalActorSenseInfo

	AActor * threat;
	float activation;


// wonky bloody macro so we can have a return value delegate method call… ugh!
DECLARE_DELEGATE_RetVal_ThreeParams(float , FActivationScoreDelegate, float , float , FTacticalActorSenseInfo& );

UCLASS(ClassGroup=AI, HideCategories=(Activation, Collision), meta=(BlueprintSpawnableComponent), config=Game)
class TACTICALAI_API UAITacticalPerceptionComponent : public UAIPerceptionComponent
// how quickly should an ideal sight sense activate the perception threshold (modified by curves)
UPROPERTY(EditDefaultsOnly,BlueprintReadWrite, Category = “AI Tactical Perception”, Config)
float TacticalSenseSightThreatBaseValue = 10.0f;

// how quickly should an ideal hearing sense activate the perception threshold (modified by curves)
UPROPERTY(EditDefaultsOnly,BlueprintReadWrite, Category = "AI Tactical Perception", Config)
float TacticalSenseHeardThreatBaseValue = 10.0f;

// ignore non hostiles?
UPROPERTY(EditDefaultsOnly, Category = "AI Tactical Perception", Config)
bool IgnoreNonCharacterActors = true;

// what is the threshold for actually sensing an enemy?
UPROPERTY(EditAnywhere,BlueprintReadWrite, Category = "AI Tactical Perception", Config)
float TacticalSenseActivationThreshold = 0.5f;

/** How much activation do we have if we spot an actor within our field of view */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Sense")
UCurveFloat* PeripheralVisionCurve;

/** Scale activation of spotting based on distance curve */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Sense")
UCurveFloat * DistanceVisionCurve;

/** Scale activation of spotting based on movement of threat */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Sense")
UCurveFloat * MovementAwarenessCurve;

// visible stuff for debugging?
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "AI Tactical Perception")
float Alertness = 0.6;

virtual void GetHostileActors(TArray&lt;AActor*&gt;& OutActors) const override;
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction * ThisTickFunction) override;

// get a new delegate to bind to for scoring purposes
FActivationScoreDelegate& GetNewActivationScoreDelegate();

// functions used to score activation value for threat..
// score an individual threat for activation
void UpdateThreatActivation(float DeltaTime,FTacticalActorSenseInfo& info);
// perception update handler (from the AIPerceptionComponent broadcast delegate)
void HandlePerceptionUpdate(TArray&lt;AActor *&gt; targets);

// scoring methods (take input score and threat, return changed score)
float ActivationScoreAngle(float currentactivation, float DeltaTime, FTacticalActorSenseInfo& info);
float ActivationScoreDistance(float currentactivation, float DeltaTime, FTacticalActorSenseInfo& info);

void ForgetHostileActor(AActor * act);

void GrabGameplayDebuggerData(TArray<FString>& OnScreenStrings, TArray<FGameplayDebuggerShapeElement>& DebugShapes) const;

// this holds the array of “sensed” actors… i.e. ones we have perceived and need to calculate activation values for
TArray<FTacticalActorSenseInfo> SensedHostileActors;
TArray<FActivationScoreDelegate> ActivationScoringDelegates;


So I just tried creating a new blueprint based off my C++ controller class with the new perception component type and it still doesn’t render the flags properly. So that does point to some class initialization issue, that gets resolved once the component is added again. I also tried copying the whole actor and its not showing the flags. So some combination of actor creation and component instantiation seems to be causing it.

Hmm, my own perception class created as a default object seems to have an issue.

Is DetectionByAffiliation the only property that’s missing? Pretty strange if so, a quick search on the Github repo suggests it doesn’t get any special attention, nor is there a details customization for the perception component. Suspect this might be a difficult one to nail down.

Entry point into the details code isn’t likely to help you, since without a customization you’d just be stepping through thousands of lines of generic slate and property code. You could add your own details customization for your component to try to force the properties to show up, but simplest workaround would just be to hard code in the values you want if they won’t change, or otherwise duplicate the properties on your own component and then copy them over during initialization.

Yeah, its the only thing thats missing (doesn’t render the checkboxes or the arrow to expand those anymore). As you say, nothing special in the uproperty either. I guess I’m not overriding some function or not doing something that the base class needs to register itself properly, although its very strange its just this one property.

Having said that, I suspect it does have a custom drawer in the properties, because its a flags thing so not just individual bools if I remember rightly. Just haven’t been able to identify what actually draws it to hook the code there as yet.

Nah it’s FAISenseAffiliationFilter, which is just a simple USTRUCT with three boolean bitfield properties. If it was customized, a search for the struct name (minus the F prefix) on Github would show the code, but nothing comes up. Really is bizarre.

I’ll bow to your knowledge on that one :slight_smile:

Which makes it even more curious. Its like I’ve missed something in the component itself… I might try taking it to a different build and see if I get the same result with that component. I didn’t think I’d need to do anything specific to register properties though. Whats weird is that you can cut and paste the values in the actual properties ok, so the property is there and has some area being drawn for it, it just doesn’t show the expand arrow or the checkboxes themselves.

Ah okay I didn’t realise the section itself was still there. Can’t imagine what would cause that behaviour, sounds like some obscure bug in the details panel code.

You could try using the Widget Reflector (Window | Developer Tools) to see if the check boxes are there but just not visible, but to be honest I don’t see where it’s going to get you. As I said, trying to debug the detail panel code when there’s no customization would be a nightmare. Sounds like it’s hacky workaround time to me!

Hacky workaround is my middle name! :slight_smile:

I’ll have a look at the widget reflector though… you never know. Thanks!

OK, so I tried the widget reflector and the controls are all there, but they’re set to disabled in the actual properties area and there’s an SNullContent item where you would expect the properties to actually draw. Which suggests to me some kind of serialization mess.

I guess all of this isn’t fully dynamic, so where would I go to delete any cached layout items to see if I can fix this?

As far as I know, Slate handles things like visibility and enabled state in a completely dynamic manner. The thing is, it’s normal for the details panel to hide properties completely, or disable them, but to leave the section there and just put null widgets - I have no idea why it would do that.

Also, no matter what may be happening with the serialization, these properties are just bit fields - it’s not like a boolean flag can get corrupted, it’s either 0 or 1. :slight_smile:
Really hard to see what could be causing this, so I’d say blame it on Mieszko and move on!

Did you try using EditAnywhere instead of EditDefaultsOnly? I’m not sure, but EditDefaultsOnly doesn’t make much sense for components, since you’re always working with instances, not derived classes.

I just copied the settings from the base class’s declaration, so didn’t think to try that. Worth giving it a go I guess.