Home > other >  (Godot Engine) How do I know which exported enum flags are enabled in script
(Godot Engine) How do I know which exported enum flags are enabled in script

Time:11-25

By using the Godot engine and writing in the GDScript language, let's say I have an enum declared as:

enum eTextMode {CHAR, NUMBER, SYMBOLS_TEXT, SYMBOLS_ALL}

And an export variable as:

export(eTextMode, FLAGS) var _id: int = 0

In the inspector panel I can see which flag is selected or not, but how can I know in code which specifically flag is selected?

By selecting in the inspector, for example: the NUMBER and SYMBOLS_TEXT flags, the _id variable will be set as 5

My approach is the following hard-coded dictionary:

var _selected_flags: Dictionary = {
    CHAR = _id in [1, 3, 5, 7, 9, 11, 13, 15],
    NUMBER = _id in [2, 3, 6, 7, 10, 11, 14, 15],
    SYMBOLS_TEXT = _id in [4, 5, 6, 7, 12, 13, 14, 15],
    SYMBOLS_ALL = _id in [8, 9, 10, 11, 12, 13, 14, 15]
}

Resulting in:

{CHAR:True, NUMBER:False, SYMBOLS_ALL:False, SYMBOLS_TEXT:True}

The above result is exactly what I'm expecting (a dictionary with string keys as they are defined in the enum with a boolean value representing the selection state).

How could I manage to do this dynamically for any enum regardless of size?

Thank you very much,

CodePudding user response:

One tacky solution that I could manage is by not using an enum at all, but instead a dictionary like the following example:

const dTextMode: Dictionary = {CHAR = false, NUMBER = false, SYMBOLS_TEXT = false, SYMBOLS_ALL = false}
export(Dictionary) var m_dTextMode: Dictionary = dTextMode setget Set_TextMode, Get_TextMode

func Get_TextMode() -> Dictionary: return m_dTextMode
func Set_TextMode(_data: Dictionary = m_dTextMode) -> void: m_dTextMode = _data

An exported dictionary is not as good-looking as an exported enum with FLAGS, and by following this approach it kind of invalidates my initial problem.

By selecting CHAR and SYMBOLS_TEXT in the exported dictionary from the inspector, and then calling print(self.Get_TextMode()) the result is indeed what I expected:

{CHAR:True, NUMBER:False, SYMBOLS_ALL:False, SYMBOLS_TEXT:True}

I still can't figure out though how to achieve this result by using the export(*enum, FLAGS) aproach.

Edit: also, the setter function is not feasible to be used in script since the user must know to duplicate the dTextMode constant first, edit it and set is as an argument.

CodePudding user response:

Thanks to the comments from @Thearot from my first answer, I have managed to figure out the following solution which meets all expectations, with one caveat: it seems like an overkill solution...

enum eTestFlags {FLAG_1, FLAG_2, FLAG_3, FLAG_5, FLAG_6}
export(eTestFlags, FLAGS) var m_iTestFlags: int = 0 setget Set_TestFlags

func Get_TestFlags() -> Dictionary: return self._get_enum_flags(m_iTestFlags, eTestFlags)
func Set_TestFlags(_id: int = m_iTestFlags) -> void: m_iTestFlags = _id

func _get_enum_flags(_val_selected: int, _enum: Dictionary, _bit_check_limit: int = 32) -> Dictionary:
    var _enum_keys: Array = _enum.keys() ; _enum_keys.invert()
    var _bin_string: String = "" 
    var _val_temp: int = 0 
    var _val_count: int = _bit_check_limit - int(_is_pow2(_bit_check_limit))
    while(_val_count >= 0): 
        _val_temp = _val_selected >> _val_count
        _bin_string  = "1" if _val_temp & 1 else "0"
        _val_count -= 1
    var _bin_string_padded: String = "%0*d" % [_enum_keys.size(), int(_bin_string)]
    var _result_dict: Dictionary = {}
    for _str_id in range(_bin_string_padded.length(), 0, -1):
        _result_dict[_enum_keys[_str_id - 1]] = bool(_bin_string_padded[_str_id - 1] == "1")
    return _result_dict

func _is_pow2(_value: int) -> bool:
    return _value && (not (_value & (_value - 1)))

Now, if I print(self.Get_TestFlags()) after selecting FLAG_2 and FLAG_6 the result is:

{FLAG_1:False, FLAG_2:True, FLAG_3:False, FLAG_5:False, FLAG_6:True}
  • Related