Verse UI - How to convert strings from exposed properties into messages, to use with SetText()?

So I’m updating an old outdated Verse UI snippet I wrote months ago, which was broken by API changes. It appears my main issue is that in Verse the use of string for text blocks and buttons has been replaced with message. Could y’all help me fix a few lines? I thought it would be a quick fix of me just dropping in " : message = " where needed, but I guess not! Any help is welcome :blush:

I have two main problem areas:

1. Defining variables for text_block widgets with blank Default Text that I set later in the script:

var WidgetLine1:text_block = text_block { DefaultText := ""}

Error:
Red underline underneath the “” part, with the error “This variable expects to be initialized with a value of type message, but this initializer is an incompatible value of type []char.(3509)”

I understand this means that I need to define default text as a message type, right?

So I tried:

var WidgetLine2:text_block = text_block { DefaultText : message = "" }

or

var WidgetLine2:text_block = text_block { DefaultText<localizes> : message = "" }

Error:
The word “message” is underlined in red, with the error “Unexpected expression”. What does that mean? Am I not allowed to use message inside of variables?


2. Converting strings from exposed properties into messages:

These are examples of my exposed properties for my UI text, and functions that that don’t work anymore.

@editable TextTitle: string = ""
@editable TextLine1List: []string = array{}

WidgetTitle.SetText("{TextTitle}")
            
if(currentStr := TextLine1List[Index]){ 
                WidgetLine1.SetText(currentStr)

Error:
“This function parameter expects a value of type message, but this argument is an incompatible value of type []char.(3509)”

Because the TextTitle property is a string type, not a message, I can’t it for SetText(). But I can’t expose message types as properties, because I get the error “The editable attribute is not supported for classes that aren’t concrete.” So how do I convert the string, and the array of strings, into messages?

Thanks in advance! I look forward to publishing my fixed snippet for everyone! :slightly_smiling_face:

Something like this should work.

Method to convert:
StringToMessage<localizes>(value:string) : message = "{value}"

Set text on widget:
WidgetTitle.SetText(StringToMessage(TextTitle))

8 Likes

Oh cool, thanks! That fixed that part! :blush:

Also I just deleted {DefaultText := “”} from

var WidgetLine1:text_block = text_block { DefaultText := ""}

because maybe I don’t need it? I don’t remember why I put it. I think I thought it was needed in order for me to call SetText later?

Now that the string/message stuff is fixed I’m running into problems with Player/Agent for OnClicked and InteractedWithEvent. More API changes. Do you know what’s going on here?

OnBegin<override>()<suspends>:void={
            ButtonUIAdd.InteractedWithEvent.Subscribe(OnButtonUISpawnInteracted)
            WidgetUIButton.OnClick.Subscribe(UIButtonClicked)

OnButtonUISpawnInteracted(Player:player):void={ 
            AddCanvas(Player) 

UIButtonClicked(Message: widget_message):void={ 
            Print("UI Button clicked")

OnButtonUISpawnInteracted “expects a value of type agent”, but I need to use Player:player for the function so that I can use AddCanvas(Player). Also OnClick.Subscribe now says “Unknown member Subscribe in tuple()->listenable(widget_message)

a player type is also an agent type, so just replace:
OnButtonUISpawnInteracted(Player:agent):void=

1 Like

So this takes the red underline away from OnButtonUISpawnInteracted, but now I get an underline for AddCanvas(Player)

“This function parameter expects a value of type player, but this argument is an incompatible value of type agent”

I assume that’s because your AddCanvas needs a player type? If so, then you can convert an agent to a player like this:
type[base type ref]

So:
AddCanvas(player[Player])

1 Like

Hmm Now I’m seeing this

“This type invocation has the ‘decides’ effect, which is not allowed by its context.”

My AddCanvas function does need a player type. Because I’m using GetPlayerUI[Player] I wrote all of this so long ago I’m rusty.

AddCanvas(Player:player):void={
            Print("Add canvas")
            if(myPlayerUI := GetPlayerUI[Player]){
                if(TmpCanvas := Canvas?){
                    myPlayerUI.RemoveWidget(TmpCanvas)
                    set Canvas = false
                    # ^ If an old Canvas already shows for player, remove it.
                }
                else {
                    NewCanvas := MakeCanvas()
                    myPlayerUI.AddWidget(NewCanvas, player_ui_slot{InputMode := ui_input_mode.All})
                    set Canvas = option{NewCanvas}
                    # ^ Add new Canvas and set Input Mode to UI (ie mouse controls cursor, not player movement.)
                }
            }

It might be because of this line that it needs the “decides”, which basically means it could fail, so check first. Try this:

if (NewCanvas := MakeCanvas()):
    myPlayerUI.AddWidget(NewCanvas, player_ui_slot{InputMode := ui_input_mode.All})
    set Canvas = option{NewCanvas}

Dang, this is really hard for me to understand my own script. These particular lines, the part for making the canvas, were lines I just copied from other people’s UI scripts, without me totally understanding what it meant. I’m not a very strong programmer yet so a lot of what I do is trial and error.

I just replaced the “else” with “if” in my example but I’m guessing that’s not what you meant for me to do. :laughing:

            Print("Add canvas")
            if(myPlayerUI := GetPlayerUI[Player]){
                if(TmpCanvas := Canvas?){
                    myPlayerUI.RemoveWidget(TmpCanvas)
                    set Canvas = false
                    # ^ If an old Canvas already shows for player, remove it.
                }     
                if (NewCanvas := MakeCanvas()): 
                    myPlayerUI.AddWidget(NewCanvas, player_ui_slot{InputMode := ui_input_mode.All})
                    set Canvas = option{NewCanvas}
                    # ^ Add new Canvas and set Input Mode to UI (ie mouse controls cursor, not player movement.)
            }
        } 

I was using curly braces when I initially wrote this script, because the examples that I was inspired by used them. But is it gonna trip me up if I keep trying to use curly braces when the Verse docs don’t use them, and some people in the Forums don’t use them? I liked them because they help me keep track of where by blocks start and end.