Trying to get a variable from one widget to another

So, I have two different widgets.

The first is a dialogue box. Its structure is like this:

image

I have functionality where, depending on the NPC you are talking to, a number of Text Blocks get created and parented to the GridPanel.

Those Text Blocks are all based on this Widget blueprint:

image

I’m trying add functionality so that when one of these Text Blocks is clicked, it changes the text in the DialogueText Text Block from the first blueprint.

I have an interface to send the exec from the second blueprint to the first upon click, but I cannot figure out how to get a ref to W_DialogueBox into W_DialogueTopic.

image

I can get the parent of the parent of the parent of W_DialogueTopic, which is the Canvas Panel in the first widget, but it won’t let me go one step further and get W_DialogueBox itself.

I thought maybe I could just do what I need to do directly in W_DialogueTopic’s blueprint, but in order to get the DialogueText Text Block variable, I still need a ref to the W_DialogueBox somehow, so either way it’s a dead end.

It might be helpful to know that W_DialogueBox is itself created in a third blueprint, an Actor Component that gets added to anything that can have a dialogue.

I suppose I could refactor this and put some of this logic directly into the W_DialogueBox blueprint, get a reference to self in there, pass that variable to Player Controller or something, then grab that within the W_DialogueTopic blueprint? It seems like a lot of work for this though, so I’m guessing there must be a simpler way to get these actors to talk to each other.

This is a job for event dispatchers. The description is somewhat convoluted, though - could you confirm 2 things:

  • when the Dialogue Topic is clicked, we receive a notification in the Dialogue Box so it can set its Dialogue Text
  • Dialogue Topics are added to the Dialogue Box - but where and how does it happen?

when the Dialogue Topic is clicked, we receive a notification in the Dialogue Box so it can set its `Dialogue Text

This is what I’m trying to achieve, but no luck so far.

Dialogue Topics are added to the Dialogue Box - but where and how does it happen?

I don’t if this is enough of the logic to answer your question, but here it is (inside W_DialogueBox):

Each NPC has its own table that stores the dialogue topics and the corresponding text. Those tables in turn are stored in a master table. Each NPC has a variable integer that acts as the key to use as the look up to pull the index corresponding to the npc’s table.

So the Dialogue Box adds the Topics to its own Grid Panel, got it. In this case this is a trivial and perfect job for the event dispatcher. And you can even use the one that comes with the button:

You can instead add a custom Event Dispatcher that sends specific data back:


Also, instead of this:

You can create an exposed variable in the Dialogue Topic widget:

And pipe the data in:

Much neater and does not clutter the parent’s graph with stuff it does not need to know about.

I already have it set up so that the dialogue topic widgets are getting created and everything. I just need to set it up so that once they are clicked, the text in the dialogue box changes.

That’s what my solution does, precisely. You’d set the Dialogue Box text here:

okay. I don’t understand event dispatchers yet, so I saw it getting added to the logic that already works and I thought you were trying to do something else

  • add a dispatcher to the child widget
  • when parent creates children, bind delegates so the children can talk to the parent
  • when something happens in the child, the parent gets a notification

This is the most standard and natural way of doing it. Once you wrap your mind around dispatchers, there’s no looking back. Give it a try; it’s simpler than you think. Plug this:

Into the ED_SendTopic custom event.

like so?

No. Have a look at my second example where I create a custom dispatcher that sends text:

This needs to go, this is not a job for the Interface; the dispatcher delegate goes here:

But the W_DialogueTopic widget where the button is doesn’t have any text to send. We get the dialogue from the table; I just need the text that goes into W_DialogueTopic’s DialogueText variable because it’s the row name that I use to look up the text that does go into the dialogue box.

Yes it does, you send the text to the widget:

That’s why I suggested this setup which makes it highly efficient:

Because what you’re doing atm:

I already have it set up

Is not really done correctly and would force you to read the data off the widget Text Block. You do not want to access the DT again, you’ve already done it once, the widget already has the text. If you must do it your way (hey, it’s your product):

image

Suboptimal but should work. The idea is to never query widget fields for data, it’s not their job to provide it and it may lead to issues - mostly acquiring stale data.

You want the widget to show some text - give it a variable and let it handle it internally, avoid having something else modify widget fields from the outside. It all subscribes to the getter / setter ideology which is one of the core foundations of the OOP.

The only text in it is the dialogue topic, which shows up in the grid panel on the left of the dialogue box.

When I click on a W_DialogueTopic widget, it should change the text that appears in the larger box on the right. I don’t want the text that is in W_DialogueTopic to show up in the right; that would be redundant.

I want to use that text to look up a row name in my table, then return the text in that row.

What I have here is working now (mostly):

The only issue now is that, for some reason, clicking Hello and looking up the table row “Hello” passes the same value as the text in the table row “Sphere.”

image

I did a print string and you can see what is getting passed through the Event Dispatcher is correct:

image

Table looks fine as well

image

You insist on doing the wrong thing for some reason:

You already have the text in the widget, there’s no need to access the Data Table again.

The DialogueText variable is the text in the large box on the right side of the dialogue box widget. If I just pass the text from W_DialogueTopic, then it’s just going to repeat the text from the left into the right!

I’ll show you…

Doing it your way…

Results in this:

This is not what I want.

Pass the entire DT struct to the widget you’re creating, the dispatcher can send it back. Or send back just this:

Give the widget the text you want it to return via Dispatcher:

I see the issue now.

I need to somehow turn a text variable into a name.

Or I just go back to the struct and change the variable type from Text to Name. That should work

You can, sure. But why? Just give the widget all the data you want it to have. And return it.


If you really insist on searching the DT every time:

I still think you don’t understand what I’m trying to do. The W_DialogueTopic widgets are the text on the left side of the dialogue box, they get created and named based on the row names in the NPC’s dialogue table.

image

The only thing inside of a W_DialogueTopic widget is a button and the text (in this case, “Hello” or “Sphere.”)

The text that should appear in the right side of the dialogue box is inside of that table we referred to earlier. This is a Text widget inside of W_DialogueTable, i.e,. the data table and the Text block that I want to change now, based on what I click on the left, are both already inside of W_DialogueTable, not W_DialogueTopic.

I only needed to get the text from W_DialogueTopic back out to use as a lookup for the table. I’d rather do that than pass the table into W_DialogueTopic, do the lookup, then pass it back into W_DialogueTable.

Apparently, you can turn text into strings and strings into names.

Edit: Unless you were suggesting that I go back and set it up so that, upon creating the W_DialogueTopic widget, I also simultaneously look up the corresponding dialogue text and pack them both into the W_DialogueTopic widget, then just get that when I call the event dispatcher?

I don’t much about programming best practices yet, but it seems like it would be more costly to replicate data that already lives in the object where I need it than to just look it up in the table each time a topic gets clicked.