GUI/Canvas/Pointer/C++ Issues!

Hey Everyone!

I’m having a few issues getting to grasps with the HUD system in UE4.
My current setup is based off of a BluePrinted GameMode Class, which has BluePrinted versions of my custom HUD and PlayerController. (ScreenCap is in the attachments).
Somewhat based off of the HUD tutorial on the UE4 Wiki.

Although, even though I’m having successful builds I can’t get my HUD to work for the life of me.

What I wanted to recreate was an object orientated version of Unity’s OnGUI system, so I could have buttons, boxes, sliders, etc,
all managing there own internal variables, and weren’t being re-instantiated on every DrawHUD call.

For some reason my Client messages won’t work, even though I’m using “ThePC->ClientMessage()”.
My problem is either, I’m being stupid and not creating my objects properly in the HUD class, or I’m not correctly accessing my PC class/BP.
Is there some kind of global debug “`Log()” system like there was in UDK?

My Issues:

  1. I need to find out why I can’t debug log like I need to…
  2. I need the above to find out what’s going on in my HUD script
  3. How do I make my material in HUDObjects an instantiate object, rather than a pointer of a pointer of a point?
  4. Am I passed a HUD reference correctly into my DrawBackground Function?
  5. After I created a new class derived from UObject, my compile times shot up to like 130+ seconds, any ideas why? (I think it has something to do with so many header referencing back and forth… but I’m not sure)

Any and all help will be immensely helpful!
I love going all out in Unreal Engines, and the amount of custom systems I made for myself and my team in UDK was just so much fun.
Learning my problems here and the solutions would help me such a long way.

Thanks!

Here’s my project so far!

**SSPlayerController.h
**


#pragma once


//Input
#include "InputCoreTypes.h"
#include "GameFramework/PlayerController.h"
#include "SSPlayerController.generated.h"


UCLASS()
class ASSPlayerController : public APlayerController
{
    GENERATED_UCLASS_BODY()
};


**SSPlayerController.cpp
**


#include "SleepStep.h"
#include "SSPlayerController.h"


ASSPlayerController::ASSPlayerController(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{


}//Constructor


**SSGameMode.h
**



#pragma once


#include "GameFramework/GameMode.h"
#include "SSGameMode.generated.h"


UCLASS()
class ASSGameMode : public AGameMode
{
    GENERATED_UCLASS_BODY()    
};


**SSGameMode.cpp
**



#include "SleepStep.h"
#include "SSGameMode.h"
#include "SSPlayerController.h"
#include "SSHUD.h"

ASSGameMode::ASSGameMode(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{
    //Backup PC Class
    PlayerControllerClass = ASSPlayerController::StaticClass();


    //BP Referenced version of our PC Class
    static ConstructorHelpers::FObjectFinder<UBlueprint> VictoryPCOb(TEXT("Blueprint'/Game/Blueprints/BL_SSPlayerController.BL_SSPlayerController'"));
    //If the referenced PC class BP isn't null
    if (VictoryPCOb.Object != NULL)
    {
        //Set our PC class as the BP object
        PlayerControllerClass = (UClass*)VictoryPCOb.Object->GeneratedClass;
    }//if


    //Backup HUD Class
    HUDClass = ASSHUD::StaticClass();


    //BP Referenced version of our HUD Class
    static ConstructorHelpers::FObjectFinder<UBlueprint> VictoryHUDOb(TEXT("Blueprint'/Game/Blueprints/BL_SSHUD.BL_SSHUD'"));
    //If the referenced HUD class BP isn't null
    if (VictoryHUDOb.Object != NULL)
    {
        //Set our HUD class as the BP object
        HUDClass = (UClass*)VictoryHUDOb.Object->GeneratedClass;
    }//if
}//Constructor


**SSHUD.h
**



#pragma once


#include "GameFramework/HUD.h"
#include "SSPlayerController.h"
#include "HUDObjects.h"
#include "SSHUD.generated.h"


UENUM()
namespace GAMESTATE
{
    enum Type
    {
        GamePlay,
        Cinematic,
        Paused,
    };
}


UENUM()
namespace HUDSTATE
{
    enum Type
    {
        Standard,
        Options,
        Audio,
        Graphics,
        GraphicsAdv,
        Exit,
    };
}


UCLASS()
class ASSHUD : public AHUD
{
    GENERATED_UCLASS_BODY()


    // Infiltrace
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = SSHUD)
    UFont* InfiltraceFont;


    // Font scale
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = SSHUD)
    float DefaultFontScale;


    // Materials 
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Materials)
    UMaterialInterface* MaterialBackground;


    // Draw Hud?
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Options)
    bool NoHUD;


    //Scaling
    float CenterHorizontal(float Width);
    float CenterVertical(float Height);
    float ScaleWidth(float Width);
    float ScaleHeight(float Height);


    //Core
    public:
        APlayerController* ThePC;
        ASSPlayerController* SSPC;
        TEnumAsByte<GAMESTATE::Type> HudState;
        TEnumAsByte<HUDSTATE::Type> PausedState;


        //PauseMenu
        UHUDObjects* ResumeButton;
        UHUDObjects* OptionsButton;
        UHUDObjects* QuitButton;


        //Screen Sizes
        float SizeX;
        float SizeY;


    protected:
        //SetUp
        void SetUpLabels();
        void SetUpTextures();
        void SetUpAnims();
        void SetUpButtons();


        //Draw HUD
        virtual void DrawHUD() OVERRIDE;


        /** after all game elements are created */
        virtual void PostInitializeComponents() OVERRIDE;
};


**SSHUD.cpp
**



#include "SleepStep.h"
#include "SSHUD.h"


ASSHUD::ASSHUD(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{
    //Draw HUD?
    NoHUD = false;


    //Scale
    DefaultFontScale = 0.7;


    //Default Screen Size
    SizeX = 1920;
    SizeY = 1080;


    //States of the HUD and pause menu
    HudState = GAMESTATE::GamePlay;
    PausedState = HUDSTATE::Standard;


    //Set up buttons in a similar format to OnGUI from Unity
    SetUpButtons();
}//Constructor


void ASSHUD::SetUpButtons()
{
    //Instantiate new object and assign reference to the pointer
    ResumeButton = NewObject<UHUDObjects>();
    //If the pointer has an object
    if (ResumeButton != NULL)
    {
        //Set up the HUD Object
        ResumeButton->Init(ObjectType::Button, MaterialBackground, CenterHorizontal(50), ScaleHeight(100), ScaleWidth(50), ScaleHeight(50), 1);
    }//if    
}//SetUpButtons


float ASSHUD::ScaleWidth(float Width)
{
    return (Width / 1920)*SizeX;
}///Scale Width


float ASSHUD::CenterHorizontal(float Width)
{
    return (SizeX / 2) - (ScaleWidth(Width) / 2);
}//CenterHorizontal


float ASSHUD::ScaleHeight(float Height)
{
    return (Height / 1920)*SizeY;
}//ScaleHeight


float ASSHUD::CenterVertical(float Height)
{
    return (SizeY / 2) - (ScaleHeight(Height) / 2);
}//CenterVertical


//Core 

void ASSHUD::PostInitializeComponents()
{
    Super::PostInitializeComponents();


    //Grab the PC
    ThePC = GetOwningPlayerController();


    //If the PC isn't null
    if (ThePC != NULL)
    {
        //Grab the custom player controller
        ASSPlayerController* YourChar = Cast<ASSPlayerController>(ThePC);


        //If the custom controller isn't null
        if (YourChar != NULL)
        {
            //Set it to the global var
            SSPC = YourChar;
        }//if
    }//if    


    //How to Get The Character
    //ASSCharacterClass* YourChar = Cast<ASSCharacterClass>(GetOwningPawn());


}//PostInitializeComponents


void ASSHUD::DrawHUD()
{
    //If the PC is NULL
    if (!ThePC)
    {
        //Try to get the PC
        ThePC = GetOwningPlayerController();


        //If there still isn't a PC, then return
        if (!ThePC) return;
    }//if


    //Check that the PC's input exists, otherwise, return
    if (!ThePC->PlayerInput) return; 


    //Draw HUD?
    if (NoHUD) return;


    //Super
    Super::DrawHUD();


    //No Canvas?
    if (!Canvas) return;


    //Assign the canvas sizes to the global vars for use outside of DrawHUD
    SizeX = Canvas->SizeX;
    SizeY = Canvas->SizeY;


    //Debug logging the canvas is working
    ThePC->ClientMessage("Canvas Working");


    //If the button pointer isn't null
    if (ResumeButton != NULL)
    {
        //Debug logging the object is working
        ThePC->ClientMessage("Object Working");
        //Pass this hud to the button
        ResumeButton->DrawBackground(this);
    }//if
}//DrawHUD


**HudObjects.h
**


#pragma once


#include "GameFramework/HUD.h"
#include "HUDObjects.generated.h"


UENUM()
namespace ObjectType
{
    enum Type
    {
        Button,
        Anim,
    };
}


USTRUCT()
struct FShapeStruct
{
    GENERATED_USTRUCT_BODY()


    //Vars
    float x;
    float y;
    float w;
    float h;


    //default properties
    FShapeStruct()
    {
        x = 0;
        y = 0;
        w = 0;
        h = 0;
    }
};


UCLASS()
class UHUDObjects : public UObject
{
    GENERATED_UCLASS_BODY()


    //State handler
    TEnumAsByte<ObjectType::Type> objType;


    //Shape and positioning of this object
    FShapeStruct ShapeAndPos;


    //This object's backgroun material reference
    UMaterialInterface* BackGround;


    //Scale of the text
    float ScaleAmount;


    //Functions
    public:
        bool CheckInside(FSHVector2 MousePos);
        void DrawBackground(AHUD* HUDRef);
        void Init(TEnumAsByte<ObjectType::Type> Type, UMaterialInterface* BackgroundMaterial, float x, float y, float w, float h, float Scale);
};


**HUDObjects.cpp
**



#include "SleepStep.h"
#include "HUDObjects.h"


UHUDObjects::UHUDObjects(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{}


void UHUDObjects::Init(TEnumAsByte<ObjectType::Type> Type, UMaterialInterface* BackgroundMaterial, float x, float y, float w, float h, float Scale)
{
    //Initialise global variables with passed parameters
    objType = Type;
    ShapeAndPos.x = x;
    ShapeAndPos.y = y;
    ShapeAndPos.w = w;
    ShapeAndPos.h = h;
    ScaleAmount = Scale;


    //This material pointer is assigned as another pointer isn't it?
    //So how would I make is it's own dynamic instance?
    BackGround = BackgroundMaterial;
}//Init


bool UHUDObjects::CheckInside(FSHVector2 MousePos)
{
    //This will be used to check if the cursor is inside it
    return false;
}//CheckInside


void UHUDObjects::DrawBackground(AHUD* HUDRef)
{
    //If the BG material reference  isn't null, and the passed HUD isn't null
    if (BackGround != NULL && HUDRef != NULL)
    {
        //Draw the material as assigned
        HUDRef->DrawMaterialSimple(BackGround, ShapeAndPos.x, ShapeAndPos.y, ShapeAndPos.w, ShapeAndPos.h, ScaleAmount, false);
    }//If
}//DrawBackground


Sorry about the size guys, but I’m new to C++ for the most part… And I’m still trying to get my head around proper pointer referencing, etc,
so posting it all was really my best option for avoiding any ambiguity with you guys trying to help me! :slight_smile:

-

Logs

The first thing to do is start using UE_LOG

I have entire Wiki Tutorial here:


**OnScreen Log Messages**

You can also use onscreen debug messages:

**wiki link**
https://wiki.unrealengine.com/Logs,_Printing_Messages_To_Yourself_During_Runtime#Logging_message_to_the_screen

once you get your own Log setup,

add logs here


void ASSHUD::PostInitializeComponents()
{
    Super::PostInitializeComponents();

**UE_LOG(YourLog,Warning,TEXT("My Very Special HUD Class: PostInit Did Run, Yaaaaay!"));**


    //Grab the PC
    ThePC = GetOwningPlayerController();


    //If the PC isn't null
    if (ThePC != NULL)
    {
        //Grab the custom player controller
        ASSPlayerController* YourChar = Cast<ASSPlayerController>(ThePC);


        //If the custom controller isn't null
        if (YourChar != NULL)
        {
            **UE_LOG(YourLog,Warning,TEXT("HAPPY HAPPY SUCCESS>>>> Hiiiiiiiiiiiiiiiiii Loken!!!!"));**
            //Set it to the global var
            SSPC = YourChar;
        }//if
    }//if    


    //How to Get The Character
    //ASSCharacterClass* YourChar = Cast<ASSCharacterClass>(GetOwningPawn());


}//PostInitializeComponents

If you see the message in blue in your log, or print yourself an onscreen message

then you know that this code ran successfully

otherwise, you’ve narrowed down the issue: the Casting to your custom PC is not working

:slight_smile:


No matter what you should see the Post Init Ran Yaaaay!!! message in your log

if you dont, well then you need to figure that out first :)


Rama

Rama’s definitely right here - caveman debugging is still very effective. I use logging facilities in every program I write.

Hey Rama,

Thank you so much! This was exactly what I was looking.
I couldn’t believe that they would have just removed something as useful as standard debug log methods,
so I came to you guys!

Thanks again! You always help me out! xD

I’ll let you know how it goes once I get a chance tomorrow!

Hee hee!

Hee heeee!

Rama

Hey Guys!

I’m starting to go a bit insane…

In my custom GameMode, I’m testing this:



ASSGameMode::ASSGameMode(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{
    UE_LOG(LogTemp, Error, TEXT("TESSSSSSSSSSSSSSSSSSSSSSSSSSSTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT"));


    if (GEngine != NULL)
    {
        GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("GameMode Constructor is running..."));
    }
}

But it’s not working.
I have my log window open and I’ve tried using the direct custom GameMode class, as well as a Blueprinted version…

Now I fully rebuilt my project, and my custom HUD only has these properties:



        // Infiltrace
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = SSHUD)
    UFont* InfiltraceFont;


    // Font scale
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = SSHUD)
    float DefaultFontScale;


    // Materials 
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Materials)
    UMaterialInterface* MaterialBackground;


    // Draw Hud?
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Options)
    bool NoHUD;

Yet the blue print of it is coming up with properties I had in it days ago, from when I was following the HUD tutorial on the wiki.

5a01d4c87d29fcf3ec1160bff94250c1.png&stc=1

Don’t suppose anyone has any Ideas?
It seems like it’s not building all of my files… so my Blueprints aren’t updating, and my logs might as well not even exist…

Thanks again guys

-

Hey Guys!

I solved all of my problems.

The cause, as expected was me being stupid!
I had set the build type wrong by mistake at some point, so nothing was being updated in the editor,
and my build times where that of a final project…

**AHHH I’m so angry with myself!
**I’ll never make that mistake again!

On the up side, my custom HUD system is working FANTASTICALLY!

Will get a video or some pictures up in a few days!

Thanks for all the help guys, and sorry for wasting your time on something silly.

-

I’ve done that!

Welcome the club!

Glad you passed that particular C++ initiation :slight_smile:

Rama