Announcement

Collapse
No announcement yet.

[TUTORIAL/SNIPPET] Creating a UMG Widget in C++, and delegate example.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • replied
    Thanks my brudda for posting this

    Leave a comment:


  • replied
    Just in case those who face InventoryUIClass is being NULL like above replies and myself, there is a solution thx to TheJamsh.

    Instead of TSubclassOf, use TAssetSubclassOf with LoadSynchronous();

    here is new code

    Code:
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Player, HUD and UI")
    	TAssetSubclassOf<class UInventoryUserWidget> InventoryUIClass;
    
    	// The instance of the players Inventory UI Widget
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Player, HUD and UI")
    	class UInventoryUserWidget* InventoryWidget;
    Code:
    void AMyPlayerController::BeginPlay()
    {
    	Super::BeginPlay();
    
    	// Only create the UI on the local machine (dose not excist on the server.)
    	if (IsLocalPlayerController())
    	{
    		
    		if (!InventoryWidget) // If the widget is not created and == NULL
    		{
    			InventoryWidget = CreateWidget<UInventoryUserWidget>(this, InventoryUIClass.LoadSynchronous()); // Create Widget
    			if (!InventoryWidget )
    			    return;
    			InventoryWidget->AddToViewport(); // Add it to the viewport so the Construct() method in the UUserWidget:: is run.
    			InventoryWidget->SetVisibility(ESlateVisibility::Hidden); // Set it to hidden so its not open on spawn.
    		}
    		
    	}
    }
    after that, make sure your GameMode has BP version of your controller class. Yes, you need your own GameModeBP with BP version of your controller class.

    https://forums.unrealengine.com/show...ausing-trouble

    this is the thread how I got to know the solution.

    Leave a comment:


  • replied
    Originally posted by cridia View Post
    This looks like an awesome tutorial! Now, I have a question; would it be possible to have the HUD class be responsible for spawning the widgets? My current implementation causes my game to freeze if I put it into the beginplay function. The reason I want to do this is because for certain functions in my widgets, I want access to canvas functions like project or deproject.
    Freeze like lock up, or just pause for a moment while it creates it?

    It should work fine from any class (i have done it from gameinstance, playercontroller, and a gamemode for various things)

    If it is doing it when it creates it, the best way around this is to create the widget on begin play, and hide it, then unhide it when you wish to show it. this is what im doing from player controller and i do not get a pause.)

    My hud is actually a blueprint based off my c++ hud class, that attaches a widget in there.
    Something like that might do what you want.

    Leave a comment:


  • replied
    Thanks for this man this helped me perfectly.

    Leave a comment:


  • replied
    Can anyone help me with this? I am getting an error and don't know what it means:

    error C2228: left of '.__Internal_RemoveDynamic' must have class/struct/union
    error C2228: left of '.__Internal_AddDynamic' must have class/struct/union

    Code:
    if (PC)
    {
    	// Calls CallPlayerPickupItem() that in turn calls the "BlueprintImplementableEvent" on OnPlayerPickedItem()
            PC->UI_UpdateScore.RemoveDynamic(this, &USHud::CallUpdateScore); // Remove the delegate before binding it. (Its always safe to unbind a delegate.)
    	PC->UI_UpdateScore.AddDynamic(this, &USHud::CallUpdateScore); // Bind the delegate from the PC that calls the BlueprintImplementableEvent.
    }

    Leave a comment:


  • replied
    Originally posted by Raikoh View Post
    Hey, if you are having issues with intellisense about not being able to open UserWidget.h you should generate visual studio files to fix it.
    Thanks, that worked for me. For anyone who doesn't know, you generate visual studio files by going to your project folder, right clicking the .uproject file, and clicking "generate visual studio project files".

    Leave a comment:


  • replied
    Pointless if its not working

    Leave a comment:


  • replied
    This looks like an awesome tutorial! Now, I have a question; would it be possible to have the HUD class be responsible for spawning the widgets? My current implementation causes my game to freeze if I put it into the beginplay function. The reason I want to do this is because for certain functions in my widgets, I want access to canvas functions like project or deproject.

    Leave a comment:


  • replied
    Hey, if you are having issues with intellisense about not being able to open UserWidget.h you should generate visual studio files to fix it.

    Leave a comment:


  • replied
    Hey there,

    this is not my tutorial but the "TSubclassOf<class UUInventoryWidget> InventoryUIClass;" should be set in the Blueprint Default Value
    of your PlayerController. Go into your "PlayerController" BP and click on "Class Defaults" at the top. Make sure that you assigned
    the correct Class to the "InventoryUIClass" variable here.

    Leave a comment:


  • replied
    Hi! WCode.

    Thanks for yours tutorial.
    I did your tutorial, but i can't see widget
    because InventoryUIClass is null pointer value.

    When does InventoryUIClass set by pointer value?

    What's wrong?

    I think that widget blueprint not executed.

    How can i call widget blueprint?


    1. Myproject name is widgettest2.

    <widgettest2.h>

    Code:
    #ifndef __WIDGETTEST2_H__
    #define __WIDGETTEST2_H__
    
    #include "EngineMinimal.h"
    
    //UMG
    #include "Runtime/UMG/Public/UMG.h"
    #include "Runtime/UMG/Public/UMGStyle.h"
    #include "Runtime/UMG/Public/Slate/SObjectWidget.h"
    #include "Runtime/UMG/Public/IUMGModule.h"
    #include "Runtime/UMG/Public/Blueprint/UserWidget.h"
    //
    
    #endif
    <UInventoryWidget.h>

    Code:
    // Fill out your copyright notice in the Description page of Project Settings.
    
    #pragma once
    
    #include "Blueprint/UserWidget.h"
    #include "UInventoryWidget.generated.h"
    
    /**
     * 
     */
    UCLASS()
    class WIDGETTEST2_API UUInventoryWidget : public UUserWidget
    {
    	GENERATED_BODY()
    	
    
    	
    	
    };

    <UInventoryWidget.cpp>


    Code:
    // Fill out your copyright notice in the Description page of Project Settings.
    
    #include "widgettest2.h"
    #include "UInventoryWidget.h"

    <MyPlayerController.h>

    Code:
    // Fill out your copyright notice in the Description page of Project Settings.
    
    #pragma once
    
    #include "GameFramework/PlayerController.h"
    #include "MyPlayerController.generated.h"
    
    /**
     * 
     */
    UCLASS()
    class WIDGETTEST2_API AMyPlayerController : public APlayerController
    {
    	GENERATED_BODY()
    
    public:
    	virtual void BeginPlay() override;
    
    
    public:
    		// The class that will be used for the players Inventory UI
    		UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Player, HUD and UI")
    		TSubclassOf<class UUInventoryWidget> InventoryUIClass;
    
    	// The instance of the players Inventory UI Widget
    	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Player, HUD and UI")
    	class UUInventoryWidget* InventoryWidget;
    
    	
    	
    };
    <MyPlayerController.cpp>

    Code:
    // Fill out your copyright notice in the Description page of Project Settings.
    
    #include "widgettest2.h"
    #include "MyPlayerController.h"
    #include "UInventoryWidget.h"
    
    
    
    void AMyPlayerController::BeginPlay()
    {
    	Super::BeginPlay();
    
    	// Only create the UI on the local machine (dose not excist on the server.)
    	if (IsLocalPlayerController())
    	{
    		if (InventoryUIClass) // Check the selected UI class is not NULL		{
    			if (!InventoryWidget) // If the widget is not created and == NULL
    			{
    				InventoryWidget = CreateWidget<UUInventoryWidget>(this, InventoryUIClass); // Create Widget
    				if (!InventoryWidget)
    					return;
    				InventoryWidget->AddToViewport(); // Add it to the viewport so the Construct() method in the UUserWidget:: is run.
    				InventoryWidget->SetVisibility(ESlateVisibility::Hidden); // Set it to hidden so its not open on spawn.
    			}
    		}
    	}
    }

    <MyWidget - Widget Blueprint>
    Click image for larger version

Name:	MyWidget1.PNG
Views:	1
Size:	160.8 KB
ID:	1071442

    Click image for larger version

Name:	MyWidget2.PNG
Views:	1
Size:	136.0 KB
ID:	1071443

    That's all!!

    Help me, please.

    Engine Version : 4.7.0
    OS : Windows 7
    Last edited by eXi; 03-29-2015, 06:16 AM. Reason: Added Code Tag

    Leave a comment:


  • replied
    Thanks for this.
    I think for people that are not familiar with Delegate & BlueprintImplementableEvent, you may just update your sample for the delegate part with the .H delegate & BlueprintImplementableEvent declaration so people understand how to setup this.

    You can also put the RPC function to demonstrate how you called the delegate.

    in all case, it's clearly an useful information.

    Leave a comment:


  • [TUTORIAL/SNIPPET] Creating a UMG Widget in C++, and delegate example.

    Hey everyone i just wanted to post this quik tutorial about creating widgets in C++.
    For a tutorial on How to extend a UUserWidget:: for UMG in C++ see link.

    Now doing this is prety straight forward except for when dealing with multiplayer.
    And i spent some houers trying diferent solution and this is what i came up with.

    1 In your player controller class add two new member variabels like this.
    Code:
    	// The class that will be used for the players Inventory UI
    	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Player, HUD and UI")
    		TSubclassOf<class UInventoryUserWidget> InventoryUIClass;
    
    	// The instance of the players Inventory UI Widget
    	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Player, HUD and UI")
    		class UInventoryUserWidget* InventoryWidget;
    2 Override the BeginPlay() method in your Player Controller class.
    Code:
    void AMyPlayerController::BeginPlay()
    {
    	Super::BeginPlay();
    
    	// Only create the UI on the local machine (dose not excist on the server.)
    	if (IsLocalPlayerController())
    	{
    		if (InventoryUIClass) // Check the selected UI class is not NULL
    		{
    			if (!InventoryWidget) // If the widget is not created and == NULL
    			{
    				InventoryWidget = CreateWidget<UInventoryUserWidget>(this, InventoryUIClass); // Create Widget
    				if (!InventoryWidget )
    				    return;
    				InventoryWidget->AddToViewport(); // Add it to the viewport so the Construct() method in the UUserWidget:: is run.
    				InventoryWidget->SetVisibility(ESlateVisibility::Hidden); // Set it to hidden so its not open on spawn.
    			}
    		}
    	}
    }
    3 Open and close inventory UI example.
    Code:
    void AMyPlayerController::ToggleInventory()
    {
    	if (bShowingInvetory)
    		bShowingInvetory = false;
    	else
    		bShowingInvetory = true;
    
    	if (InventoryWidget)
    	{
    		if (bShowingInvetory)
    		{
    			InventoryWidget->SetVisibility(ESlateVisibility::Visible);
    		}
    		else {
    			InventoryWidget->SetVisibility(ESlateVisibility::Hidden);
    		}
    	}
    }
    Thats it!
    Now if you are wondering way I don`t create it on the server, how do you have server > client behavior?
    I do this by creating delegates on the Player Controller and bind them in the Contruct_Implementation() method, that in turns call a "BlueprintImplementableEvent" to notifie the widget it self so it can behave accordingly.
    Note: OnPlayerPickupItem delegate is called from server to client using a Remote Procedure Call (RPC)

    Here is a example of this.
    Code:
    void UInventoryUserWidget::Construct_Implementation()
    {
    	Super::Construct_Implementation();
    
    	AMyPlayerController* PC = CAST_TO_MY_PC(GetOwningPlayer());
    	if (PC)
    	{
    		// Calls CallPlayerPickupItem() that in turn calls the "BlueprintImplementableEvent" on OnPlayerPickedItem()
    		PC->OnPlayerPickupItem.RemoveDynamic(this, &UInventoryUserWidget::CallPlayerPickupItem); // Remove the delegate before binding it. (Its always safe to unbind a delegate.)
    		PC->OnPlayerPickupItem.AddDynamic(this, &UInventoryUserWidget::CallPlayerPickupItem); // Bind the delegate from the PC that calls the BlueprintImplementableEvent.
    	}
    }
    Hope this was helpful i spent some time on the crash i got when not checking for IsLocalPlayerController().
    And tought it might be a nice share for anyone else having the issue.

    WCode
    Last edited by WCode; 11-25-2014, 11:46 AM.
Working...
X