How to bind to OnItemSelectionChanged of a list view - c++

In Unreal Engine 4, I want to bind an event to UListView::OnItemSelectionChanged. That event FOnItemSelectionChanged requires a NullableItemType, so I'm passing a pointer to the list entry class of the list view (my custom class derived from IUserObjectListEntry) as parameter.
UCLASS()
class PROJECT_API UMyListViewEntry : public UUserWidget, public IUserObjectListEntry
{
GENERATED_BODY()
// Members and functions don't matter here.
};
UCLASS()
class PROJECT_API UMyUserWidget : public UUserWidget
{
GENERATED_BODY()
void NativeConstruct() final
{
MyList->OnItemSelectionChanged.AddDynamic(this, &UMyUserWidget::MyEventCallback);
}
void MyEventCallback(UMyListViewEntry* e)
{
// implementation details
}
private:
UPROPERTY(meta = (BindWidget))
UListView* MyList;
};
However, the AddDynamic() call causes the error
C2228: Left of ".__Internal_AddDynamic" has to be in a class/structure/union
so I suppose, the signature of the callback function I want to bind (the MyEventCallback()) is wrong.
What would be the correct signature for a function which should be bound to UListView::OnItemSelectionChanged?

It is not only about the signature of the callback, but also about how to add the callback.
Option #1: Use return value of OnItemSelectionChanged (the callback will be limited to UObject)
In UListView, its member OnItemSelectionChanged is implemented via a macro IMPLEMENT_TYPED_UMG_LIST, which does
virtual FOnItemSelectionChanged& OnItemSelectionChanged() const override { return OnItemSelectionChangedEvent; }
So to add a callback function to the delegate, use the return value:
UCLASS()
class PROJECT_API UMyUserWidget : public UUserWidget
{
GENERATED_BODY()
void NativeConstruct() final
{
auto event = MyList->OnItemSelectionChanged();
event.AddUObject(this, &UMyUserWidget::MyEventCallback);
}
void MyEventCallback(UObject* e)
{
// implementation details, cast e to UMyListViewEntry*
}
// ...
};
You are limited to callbacks having UObject* as parameter (UListView is a specialization of its base classes using UObject as entry type).
The delegate which is available in blueprint (BP_OnItemSelectionChanged) can't be used, since it is private.
Option #2: Define custom delegate
If you want to use your custom entry type directly as parameter in the callback, you either could
implement your own list view or
derive from UListView and call a custom delegate in virtual void OnSelectionChangedInternal(UObject* FirstSelectedItem)
While the first approach is similar to the UListView implementation, the second approach is very short and might look similar to BP_OnItemSelectionChanged:
DECLARE_MULTICAST_DELEGATE_TwoParams(FOnMyListItemSelectionChanged, UMyListViewEntry*, bool);
UCLASS(meta = (EntryInterface = UserObjectListEntry, EntryClass = UMyListViewEntry))
class PROJECT_API UMyListView : public UListView
{
GENERATED_BODY()
public:
FOnMyListItemSelectionChanged OnMyListItemSelectionChanged;
private:
void OnSelectionChangedInternal(UObject* FirstSelectedItem) override
{
Super::OnSelectionChangedInternal(FirstSelectedItem);
auto entry = Cast<UMyListViewEntry>(FirstSelectedItem);
OnMyListItemSelectionChanged.Broadcast(entry, entry != nullptr);
}
};
UCLASS()
class PROJECT_API UMyUserWidget : public UUserWidget
{
GENERATED_BODY()
void NativeConstruct() final
{
MyList->OnMyListItemSelectionChanged.AddUObject(this, &UMyUserWidget::MyEventCallback);
}
void MyEventCallback(UMyListViewEntry* e, bool isSelected)
{
// implementation details
}
private:
UPROPERTY(meta = (BindWidget), meta = (EntryClass = UMyListViewEntry))
UMyListView* MyList;
};

Related

How to refer to instances of a class universally without type codes?

I was making a text based RPG in which I have an abstract Item class. From this Item class, I have the classes Weapon, Potion, Key, and Armor. The main character class, Protagonist uses these items and has a function doItemEffect(Item*). How do I implement doItemEffect(Item*) in a way that I refer to all items in universally? To better phrase my problem, if I wasn't clear, here is an example that uses a quite ugly solution.
class Protagonist
{
public:
void doItemEffect(Item* it)
{
switch(it->getType()) //<-- The type is an enum class
{
case ItemType::WEAPON:
attackOpponent(it.getAttackPower()); //If it is a weapon it would have this function
break;
case ItemType::POTION:
heal(it.getHealPower()); //If it is a weapon it would have this function
break;
case ItemType::KEY:
//..Code..
break;
case ItemType::ARMOR:
//More Code...
break;
}
};
And an example of two of the classes Potion and Weapon (The type of the class is a private variable stored in Item with a mutator method setType()):
class Potion : public Item
{
int healPower;
public:
Potion(std::string name, std::string description) : Item(name, description)
{
setType(ItemType::POTION);
}
//Code
};
Weapon:
class Weapon : public Item
{
int attackPower;
public:
Weapon(std::string name, std::string description) : Item(name, description)
{
setType(ItemType::WEAPON);
}
//Code
};
As you can see, this code relies on an class code and a switch in the Protagonist class. Because of this, this doesn't seem very object oriented or polymorphic. Thus, is there a way I could get what subclass a type of Item is, without having to use class codes? Or is there any other solution? The other problem with this snippet above is also that whenever I refer to an item outside of its class, I have to use the same switch statement for each type of item.
Create a virtual function use() in your Item class. Override this function from your derived classes to trigger the various actions (attack, heal, etc.), so that all your subclassed items have an abstract interface to use/apply them.
You can either use RTTI (e.g. dynamic_cast<>()) as an alternative to a dedicated type field:
class Protagonist
{
public:
void doItemEffect(Item* it)
{
Potion *potion = dynamic_cast<Potion *>(item);
Weapon *weapon = dynamic_cast<Weapon *>(item);
if (potion != nullptr) {
heal(potion->getHealPower());
}
else if (weapon != nullptr) {
attackOpponent(weapon->getAttackPower());
}
or use polymorphism by adding a virtual effect() class member function in the abstract Item class:
class Item {
// ...
public:
virtual void effect(Protagonist *) = 0;
// ...
};
and overriding it in the derived classes:
class Potion : public Item
{
// ...
public:
void effect(Protagonist *) override;
};
which has the drawback that your Potion class needs to know that it can be used by a Protagonist. To remedy this, double dispatch is often used. The problem being that C++ does not support double dispatch as a language feature. It can be simulated using the visitor pattern as such:
class Weapon;
class Potion;
class DispatchReceiver {
public:
virtual void effect(Weapon *) = 0;
virtual void effect(Potion *) = 0;
};
class Item {
// ...
public:
virtual void effect(DispatchReceiver *) = 0;
// ...
};
class Potion : public Item {
// ...
virtual void effect(DispatchReceiver *dr) override
{
dr->effect(this);
}
// ...
};
class Weapon : public Item {
// ...
public:
virtual void effect(DispatchReceiver *dr) override
{
dr->effect(this);
}
// ...
};
class Protagonist : public DispatchReceiver {
// ...
public:
void effect(Weapon *weapon) override
{
attackOpponent(weapon->getAttackPower());
}
void effect(Potion *potion) override
{
heal(potion->getHealPower());
}
void doItemEffect(Item* it)
{
it->effect(this);
}
};
Have a list of item types
template<class...Types>
struct type_list_t{};
using Items=type_list_t<Potion, Weapon, etc>;
this replaces your enum. You can write get index of type, and get type from (compile time) index. You can even write what I call a magic switch, mapping runtime (bounded) index to a compile time type via continuation passing style.
Next add a visit method to Item. It takes a index into the type list and then static casts this to the type of the child, then invokes a passed-in callback with the result of the cast.
Write function overloads that look like this:
void use_item( Protagonist*, Potion* );
void use_item( Protagonist*, Weapon* );
Then dispatch to it using visit in Protagonist.
Now you can simplify this by using a pre written variant.
template<class Base, class...Ts>
struct poly_variant:boost::variant<Ts...>{
using boost::variant<Ts...>::variant;
Base& base();
Base const& base() const;
};
now you can visit in Protagonist. A variant of this can be used if you want to make the storage be a pointer (or a smart pointer).
Write base() via apply visitor.

What is best way to know type of sender object?

I have hierarchy of classes:
class A
{
};
class B : public A
{
};
class C : public B
{
};
class D : public A
{
};
and I have some function, which performs notification:
void notify(A* sender, const NotificationType notification)
{
}
My problem is how to find out exact type of sender object. I want to find elegant way to solve this problem. I don't like to use dynamic cast for these purposes. Possible way is to define enum within class A like:
enum ClassType
{
CLASS_A,
CLASS_B,
CLASS_C,
CLASS_D
};
and defining virtual method:
virtual ClassType get_type(void) const;
But this approach has bad scalability. Another way to keep this information in NotificationType, but it has bad scalability too.
P.S. I just want to use similar code:
I want to use similar code:
void notify(A* sender, const NotificationType notification)
{
if (sender is object of A)
new GuiA();
else if (sender is object of B)
new GuiB();
else if (sender is object of C)
new GuiC();
else
new GuiD();
}
To create a matching GUI object based on the concrete type of sender, you could pass a factory to some kind of factory method in A.
class A
{
public:
virtual Agui* createGui(GuiFactory& fac) = 0;
};
class GuiFactory
{
public:
virtual Agui* forB(B&) = 0;
virtual Agui* forC(B&) = 0;
virtual Agui* forD(D&) = 0;
};
class B : public A
{
public:
Agui* createGui(GuiFactory& fac)
{
return fac.forB(*this);
}
};
void notify(A* sender, const NotificationType notification)
{
// Use A interface...
// Get the concrete GuiFactory from somewhere, and use it
auto gui = sender->createGui(win32GuiFactory);
}
If you want know type to persist your hierarchy, conside to use boost::TypeIndex (http://www.boost.org/doc/libs/develop/doc/html/boost_typeindex.html).
If you want know type to process different types in different manners, conside to use Visitor insted of type identifier or make abstract interface with virtual functions covers your needs.
EDITED
Your goal is to create different UI object for different types. You can use the following model to reach your goal:
class UIObject {...};
class UIObjectFactory {...};
class A {
public:
virtual std::unique_ptr<UIObject> Create(UIObjectFactory& factory) = 0;
};
void OnNotify(A* sender) {
auto ptr = sender->Create(GetUIFactory());
...
}
and defining virtual method:
virtual ClassType get_type(void) const;
The easiest way to achieve this and get rid of scalability issue is to implement your get_type() member function in each class A, B, C, ... this way:
typedef uintptr_t ClassType;
virtual ClassType get_type() const
{
static int dummy;
return reinterpret_cast<ClassType>(&dummy);
}
A static variable dummy will be created for each class you add this member function, so that the return value identifies uniquely the class.

c++ Why i need pointer casting each time i request method from container object

i have annoying problem where i need to pointer cast pointer member
here is example
class GlobalInterface
{
public:
virtual void DoAction() = 0;
}
class ActionClass_A: public GlobalInterface
{
public:
ActionClass_A(){};
~ActionClass_A(){};
void DoAction() { ..... } ;
void DoSomeActionOnlyForA() { ..... } ;
}
class ActionClass_B: public GlobalInterface
{
public:
ActionClass_B(){};
~ActionClass_B(){};
void DoAction() { ..... } ;
void DoSomeActionOnlyForB() { ..... } ;
}
#include "GlobalInterface.h"
#include "ActionClass_A.h"
#include "ActionClass_B.h"
class GlobalContainer()
{
public:
GlobalContainer(GlobalInterface* _action)
{
pAction = _action;
}
GlobalInterface* getAction() { return pAction; };
private:
GlobalInterface* pAction;
}
// Main
GlobalContainer* pGlobalContainer = new GlobalContainer(new ActionClass_B());
// WHY i need this casting to get the ActionClass_B DoAction()???
((ActionClass_B*)pGlobalContainer->getAction())->DoSomeActionOnlyForA();
i just want to avoid this casting , and call it like this :
and it will know which implamention it should invoke based on the object type
pGlobalContainer->getAction()->DoSomeActionOnlyForA()
or
pGlobalContainer->getAction()->DoSomeActionOnlyForB()
The virtual function in the base class is private. It should work with a public function.
... and it will know which implamention it should invoke based on the
object type.
But you're not letting it decide what implementation it should invoke based on type, you're trying to make that decision yourself by calling DoSomeActionOnlyForA() or DoSomeActionOnlyForB() directly.
This doesn't work because at the moment of the call the static type of the object is GlobalInterface* and the GlobalInterface class doesn't have member functions named like that.
The way to achieve what you want, let each derived class have it's own behavior, is to understand and use virtual functions correctly. For example you could do this:
class GlobalInterface
{
public:
virtual ~GlobalInterface() {}
virtual void DoAction() = 0;
};
class ActionClass_A: public GlobalInterface
{
public:
ActionClass_A() {}
~ActionClass_A() {}
void DoAction()
{
DoSomeActionOnlyForA(); // call specific action for A
}
void DoSomeActionOnlyForA() { /* implement specific action for A */ } ;
};
class ActionClass_B: public GlobalInterface
{
public:
ActionClass_B() {}
~ActionClass_B() {}
void DoAction()
{
DoSomeActionOnlyForB(); // call specific action for B
}
void DoSomeActionOnlyForB() { /* implement specific action for B */ } ;
};
As you can see, you have a virtual function DoAction() that is overridden in each of the derived classes to call the appropriate functionality for that class.
Then you can use it like this:
GlobalContainer* pGlobalContainer = new GlobalContainer(new ActionClass_B());
pGlobalContainer->getAction()->DoAction();
This will call ActionClass_B::DoAction() which in turn calls ActionClass_B::DoSomeActionOnlyForB().
If you instead create the container like this:
GlobalContainer* pGlobalContainer = new GlobalContainer(new ActionClass_A());
then the same call pGlobalContainer->getAction()->DoAction(); will instead call ActionClass_A::DoAction() which in turn calls the appropriate functionality for A.
As you can see, in this case it does indeed call the appropriate function based on the dynamic type of the object (DoAction() from A or from B).

Common base class in plug-in code

The application defines 3 interfaces to be implemented in a plug-in. Widget is always the base.
// Application code...
class Widget {
virtual void animate() = 0;
};
class BigWidget : public Widget {
};
class SmallWidget : public Widget {
};
Every interface implementation is derived from NiceWidget which provides some plug-in internal common information.
// Plug-in code...
class NiceWidget {
// nice::Thing is only known in plug-in code.
nice::Thing thing();
};
class NiceBigWidget : public NiceWidget, public BigWidget {
void animate() override;
};
class NiceSmallWidget : public NiceWidget, public SmallWidget {
void animate() override;
};
func is called from application code. wid is known to be implemented by this plugin. Thus wid is also a NiceWidget. The goal of func is to call the thing method of it.
// Plugin-in code...
void func(Widget* wid) {
// wid is either NiceBigWidget or NiceSmallWidget.
auto castedBig = dynamic_cast<NiceBigWidget*>(wid);
if (castedBig) {
castedBig->thing().foo();
return;
}
auto castedSmall = dynamic_cast<NiceSmallWidget*>(wid);
if (castedSmall) {
castedSmall->thing().foo();
return;
}
assert(false);
}
But trying to cast wid to every Nice* can become very awful with increasing hierarchy size. Are there better solutions out there?
First: if you know that wid will always be a NiceWidget*, why not say so in func()? And you would not need a cast at all:
void func(NiceWidget* wid)
{
wid->thing().foo(); // Done
}
Even if you can't change the function signature for whatever reason, you would only need one cast:
void func(Widget* wid)
{
NiceWidget* casted = dynamic_cast<NiceWidget*>(wid);
if (casted)
casted->thing().foo();
else
throw std::exception(); // Well, throw the right exception
}
You can assert() instead of throwing an exception, of course, if you think it is better for your purposes.
In any case, you just need a pointer to the class that defines the functions you need to use (in this case, thing()), not to the most derived classes. If you will override the function in derived classes, make it virtual and you are done anyway.
If you know, that every NiceWidget is Widget, you should consider extending NiceWidget from Widget.
class Widget {
virtual void animate() = 0;
};
class BigWidget : public Widget {
};
class SmallWidget : public Widget {
};
class NiceWidget : Widget{
// nice::Thing is only known in plug-in code.
nice::Thing thing();
};
class NiceBigWidget : public NiceWidget, public BigWidget {
void animate() override;
};
class NiceSmallWidget : public NiceWidget, public SmallWidget {
void animate() override;
};
There will be another problem called The diamond problem, and it may be solved using virtual extending
After that it's should be OK to dynamic_cast from Widget to NiceWidget

How to use shared_ptr in a member which is not a shared_ptr?

I'm working on a couple of classes and I'm wondering how I can use a normal member in my application class, where the member needs to use shared_from_this()?
Here is some code to clarify what I mean (see comments)
class Observable {
public:
void addObserver(boost::shared_ptr<Observer> observer) {
// add to a list
}
};
class Observer {
public:
virtual void onUpdate() = 0;
};
class MyObservableType : public Observable {
};
class ApplicationModel : public Observer {
private:
MyObservableType mot;
public:
void setup() {
// how do I pass this as a boost::shared_ptr, as ApplicationModel is not
// a boost::shared_ptr in the Application class this using a call to
// "shared_from_this()" (and inheriting public shared_from_this<ApplicationModel>
mot.addObserver([shared_from_this])
}
};
class Application {
private:
ApplicationModel model;
public:
void setup() {
model.
}
};
You have three solutions to this problem:
First solution: force the application to create a shared_ptr by making its constructor private. This is what I would recommend to do for any class that derivates from enable_shared_from_this
class ApplicationModel : public Observer, public boost::enable_shared_from_this<ApplicationModel> {
private:
ApplicationModel(); // private constructor
MyObservableType mot;
public:
// an instance of this class can only be created using this function
static boost::shared_ptr<ApplicationModel> buildApplicationModel() {
return boost::make_shared<ApplicationModel>();
}
void setup() {
mot.addObserver(shared_from_this()) ;
}
};
Second solution: change your code design.
You should not ask the ApplicationModel to register itself to the Observable, but do it yourself. This way the ApplicationModel doesn't enforce anything, but if its owner wants to call addObservable, it has to create a shared_ptr. This is more or less what is called dependency injection.
class Application {
private:
boost::shared_ptr<ApplicationModel> model;
MyObservableType mot;
public:
void setup() {
model = boost::make_shared<ApplicationModel>();
mot.addObserver(model);
}
};
EDIT: Third solution: use a dummy shared_ptr, like this:
class ApplicationModel : public Observer {
private:
boost::shared_ptr<ApplicationModel> myself;
MyObservableType mot;
public:
void setup() {
mot.addObserver(myself) ;
}
ApplicationModel() {
myself = boost::shared_ptr<ApplicationModel>(this, [](ApplicationModel*) {});
}
~ApplicationModel() {
mot.removeObserver(myself);
assert(myself.unique());
}
};
The idea is to create a shared_ptr to this and to tell shared_ptr not to call the destructor (here I use an empty lambda function but you can easily create an inline structure). This is a hack and you shouldn't do so.
You can't. shared_from_this() requires that your object be allocated dynamically via a shared_ptr.
See this page of the documentation, which states:
Requires: enable_shared_from_this must be an accessible base class of T. *this must be a subobject of an instance t of type T . There must exist at least one shared_ptr instance p that owns t.
So you would need to alter your code to have any instances of ApplicationModel be "owned" by a shared_ptr. For example:
class ApplicationModel :
public Observer,
public boost::enable_shared_from_this<ApplicationModel>
{
//...
void setup() {
mot.addObserver(shared_from_this());
}
};
class Application {
private:
// Application object must initialize this somewhere
boost::shared_ptr<ApplicationModel> model;
//...
};