How to convert a string to enum in Godot? - enums

Using Godot 3.4, I have an enum setup as:
enum {
STRENGTH, DEXTERITY, CONSTITUTION, INTELLIGENCE, WISDOM, CHARISMA
}
And I would like to be able to make the string "STRENGTH" return the enum value (0). I would like the below code to print the first item in the array however it currently presents an error that STRENGTH is an invalid get index.
boost = "STRENGTH"
print(array[boost])
Am I doing something wrong or is there a function to turn a string into something that can be recognised as an enum?

First of all, your enum needs a name. Without the name, the enum is just a fancy way to make a series of constants. For the purposes of this answer, I'll use MyEnum, like this:
enum MyEnum {
STRENGTH, DEXTERITY, CONSTITUTION, INTELLIGENCE, WISDOM, CHARISMA
}
Now, we can refer to the enum and ask it about its elements. In particular, we can figure out what is the value associated with a name like this:
var boost = "DEXTERITY"
print("Value of ", boost, ": ", MyEnum.get(boost))
That should print:
Value of DEXTERITY: 1
By the way, if you want to get the name from the value, you can do this:
var value = MyEnum.DEXTERITY
print("Name of ", value, ": ", MyEnum.keys()[value])
That should print:
Name of 1: DEXTERITY
What you are getting is just a regular dictionary preset with the contents of the enum. So, we can ask it about all the values:
for boost in MyEnum:
print(boost)
Which will print:
STRENGTH
DEXTERITY
CONSTITUTION
INTELLIGENCE
WISDOM
CHARISMA
And we can also ask it if it has a particular one, for example print(MyEnum.has("ENDURANCE")) prints False.
And yes you could edit the dictionary. It is just a dictionary you get initialized with the values of the enum.

Related

How do I get a random variant of an enum in GDScript, Godot 3.3?

I have declared an enum like so in GDScript:
enum State = { STANDING, WALKING, RUNNING }
I want to get a random variant of this enum without mentioning all variants of it so that I can add more variants to the enum later without changing the code responsible for getting a random variant.
So far, I've tried this:
State.get(randi() % State.size())
And this:
State[randi() % State.size()]
Neither work. The former gives me Null, and the latter gives me the error "Invalid get index '2' (on base: 'Dictionary')."
How might I go about doing this in a way that actually works?
This can be achieved the following way:
State.keys()[randi() % State.size()]
This works because keys() converts the State dictionary to an array, which can be indexed using [].

For/in probem. What is the difference between object.variable and object[variable]?

Why can we use a code like this:
let student = {name:"John", surname:"Doe", index:386754};
let text = "";
let x;
for (x in student) {
text += student[x] + " "; }
And it would preview: John Doe 386754.
But when I formulated it like this:
let student = {name:"John", surname:"Doe", index:386754};
let text = "";
let x;
for (x in student) {
text += student.x + " "; }
, it returnes: undefined undefined undefined.
I suppose it's a pretty basic thing, but I had to ask because I can't find an appropriate answer.
Thank you ahead!
You should check out the data structures. You create a hash table using the variable student. So you can call inner variables (key-value pairs) by using brackets as you did student[name]. The second one student.name means you are calling a method of a class, which you don't have.
I recommend you to check what data structures exist, and how to use them.
The usage of object.something vs object[something] varies in different languages, and JavaScript is particularly loose in this aspect. The big difference here is that in object[something], something must reference a string corresponding to a key in object. So if you had something = 'myKey', and myKey was the name of a key in something (so object = {'myKey': 'value', ...}), you would get value. If you use object.something, you are asking JavaScript to look for a key in object with the name something. Even if you write something = 'myKey', using a dot means that you are looking within the scope of the object, making variables in your program effectively invisible.
So when you write student.x, you get undefined because there is no key 'x': 'value' in student for your program to find. Defining x as a key in your for loop does not change this. On the other hand, writing student[x] means that your program is finding the value x is referencing and plugging it in. When x is 'name', the program is actually looking for student['name'].
Hope that clarifies your issue. Good luck!

Look up Enum by label instead of by value

Is there a quick way to look up an Enum with only using the label of the enum instead of the value. Let's say the Enum type is SalesStatus, I want to be able to basically call into some kind of a function like enumLabel2Value(enumStr(SalesStatus), "Open order") and it will return 1.
I'm trying to avoid looping thru all possible values and checking each one separately, it seems like this should be something that's readily available since whenever a user filters on a enum column on a grid, they enter in the label, not the value, but I haven't seen anything like it.
You can use the str2Enum function for that. From the documentation:
Retrieves the enum element whose localized Label property value
matches the input string.
In addition to the caveats from Alex Kwitny's answer, I recommend taking a look at the comments of the documentation, specifically the comment
Please note that str2Enum performs partial matching and matches the
beginning of the string. If there are multiple matches, it will take
the first one.
In addition take a look at method string2Enum of class DMFEntityBase, which supports different options how the enum element can be specified. I think with the DictEnum.name2Value() method enum elements specified by their label are handled.
Update
OP mentioned in the comments to Alex Kwitny's answer that it is a specific enum ExchangeRateDisplayFactor he has issues with. str2Enum also works with that enum, as the following job demonstrates:
static void str2EnumTest(Args _args)
{
ExchangeRateDisplayFactor factor;
factor = str2Enum(factor, '1');
info(strFmt('%1', factor)); // outputs '1'
factor = str2Enum(factor, '10');
info(strFmt('%1', factor)); // outputs '10'
factor = str2Enum(factor, '100');
info(strFmt('%1', factor)); // outputs '100'
factor = str2Enum(factor, '1000');
info(strFmt('%1', factor)); // outputs '1000'
factor = str2Enum(factor, '10000');
info(strFmt('%1', factor)); // outputs '10000'
}
It doesn't exist because labels can be all sorts of things in different languages. symbol2Value() exists though and may be what you're looking for, but your question is specifically on labels. An example of where this could be very bad...
Let's say you have an enum called GoodBadPresent, to indicate what type of Christmas present you will receive, with two values:
GoodBadPresent::Poison English label: "Poison"; German label: "Gift"
GoodBadPresent::Gift English label: "Gift"; German label: "Geschenk"
If this example isn't clear, the word for Poison in German is Gift. So if you tried to resolve Gift to an enum value, you'd also have to provide the language. The performance problems here are probably greater than the performance problems of looping through an enum.
You can look at DictEnum to see if there are any methods that can help you more succinctly achieve what you want though. https://msdn.microsoft.com/en-us/library/gg837824.aspx
I'm more curious to the details of your scenario where you need to get back to an enum from a label.

Using protobuf enum value as a field number

I'm wondering if it is possible to use Google Protocol Buffers' enum constants as a field number of other messages, like
enum Code {
FOO = 100;
BAR = 101;
}
message Message {
required string foo = FOO;
}
This code doesn't work because FOO's type is enum Code and only a number can be used as a field number.
I am trying to build polymorphic message definitions like this animal example, that defines Cat = 1; in enum Type and required Cat animal = 100; as a unique extension number.
I thought it'd be nice to do
message Message {
required string foo = FOO.value;
}
, so that I can ensure the uniqueness of the extension field number without introducing another magic number.
So the question: is it possible to refer an enum's integer value in the protocol buffer language?
No, there is no way to do this. Sorry.
BTW, two enumerants of the same enum type can actually have the same numeric value, so defining these values in an enum does not actually ensure uniqueness.

How to use Enumerations in DXL Scripts?

I'd like to test the value of an enumeration attribute of a DOORs object. How can this be done? And where can I find a DXL documentation describing basic features like this?
if (o."Progress" == 0) // This does NOT work
{
// do something
}
So after two weeks and an expired bounty I finally made it.
Enum-Attributes can be assigned to int or string variables as desired. But you have to assign to a variable to perform such a conversion. It is not casted when a mere comparison is done like in my example. So here comes the solution:
int tmp = o."Progress"
if (tmp == 0)
{
// do something
}
When tmp is a string, a comparison to the enum literals is possible.
That was easy. Wasn't it? And here I finally found the everything-you-need-to-know-about-DXL manual.
For multi-valued enumerations, the best way is if (isMember(o."Progress", "0")) {. The possible enumerations for single and multi-enumeration variables are considered strings, so Steve's solution is the best dxl way for the single enumeration.
You can also do
if(o."Progress" "" == "0")
{
//do something
}
This will cast the attribute value to a string and compare it to the string "0"
If you're talking about the "related number" that is assignable from the Edit Types box, then you'll need to start by getting the position of the enumeration string within the enum and then retrieve EnumName[k].value .
I'm no expert at DXL, so the only way to find the index that I know of off the top of my head is to loop over 1 : EnumName.size and when you get a match to the enumeration string, use that loop index value to retrieve the enumeration "related number."

Resources