Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exporting an enum sourced from a Resource doesn't work. #79412

Closed
caimantilla opened this issue Jul 13, 2023 · 3 comments · Fixed by #79510
Closed

Exporting an enum sourced from a Resource doesn't work. #79412

caimantilla opened this issue Jul 13, 2023 · 3 comments · Fixed by #79510

Comments

@caimantilla
Copy link

caimantilla commented Jul 13, 2023

Godot version

4.1.stable

System information

Godot v4.1.stable - Windows 10.0.22621 - Vulkan (Mobile) - dedicated NVIDIA GeForce RTX 3070 Laptop GPU (NVIDIA; 31.0.15.3141) - Intel(R) Core(TM) i7-10870H CPU @ 2.20GHz (16 Threads)

Issue description

Loading constants from a resource should work fine. This is something I do in older versions (pre-3.0) since constants seem to still be only directly accessible by other scripts if they're part of an instance, otherwise I'd have to be calling static functions to get the constant values (yuck!). Even in 4.1, it's useful so that exported values can be tweaked from the inspector while still being treated as constants.
In this case, the issue came up because the plugin I'm writing is configured this way. Upon entering the tree, it ensures the configuration resources exist. An alternative might be to auto-generate a script extending the script containing the constants and overriding the values in the _init function, but there shouldn't be an issue with going through the Resource.

The only issue I've encountered is that exporting an enum doesn't work this way, it just shows a SpinBox as if I exported an integer. Loading the script just to get the enums while using the resource for everything else works, but it's not ideal.

Tiny update:
I tried assigning the type of direction more explicitly like this: @export var direction: Constants.Direction = Constants.Direction.SOUTH
And got these errors:
Parse Error: "Constants" is a constant but does not contain a type.
Parse Error: Cannot use simple "@export" annotation because the type of the initialized value can't be inferred.

Steps to reproduce

Write a script named constants.gd containing the following code:

@tool
extends Resource

enum Direction {
    WEST = 0,
    EAST = 1,
    NORTH = 2,
    SOUTH = 3,
}

Create a new Resource named constants.tres, and assign this script to it.

Create a scene with a script associated, something like character.gd.
Copy this code to it:

@tool
extends Node3D

const Constants = preload( "res://constants.tres" )
const Direction = Constants.Direction

@export var direction := Direction.SOUTH

In the inspector, it should show an OptionButton with all the enum values, but instead, you'll only see "3".

Minimal reproduction project

N/A

@ghost
Copy link

ghost commented Jul 13, 2023

I have a solution for you until this is fixed (It's not pretty, but it works).

@tool
extends Node3D

const Constants = preload( "res://constants.tres" )
const Direction = Constants.Direction

var direction : int


func _get_property_list() -> Array:
  var properties = []
  
  properties.append({
      &'name': &'direction',
      &'type': TYPE_INT,
      &'hint': PROPERTY_HINT_ENUM,
      &'hint_string': ','.join(Direction.keys())
  })

  return properties

@dalexeev
Copy link
Member

const Constants = preload( "res://constants.tres" )

Please note that if you use

const Constants = preload("res://constants.gd")

this will work correctly:

@dalexeev
Copy link
Member

Testing:

const Constants = preload("res://constants.gd")
const Direction = Constants.Direction
@export var direction := Direction.SOUTH
print_line(type.to_string(), type.kind, type.is_constant, type.is_meta_type);
res://constants.gd 3 true true
constants.gd.Direction 4 true true
constants.gd.Direction 4 false false
const Constants = preload("res://constants.tres")
const Direction = Constants.Direction
@export var direction := Direction.SOUTH
print_line(type.to_string(), type.kind, type.is_constant, type.is_meta_type);
res://constants.gd 3 true false
Dictionary 0 true false
int 0 false false

// If the base is a metatype, use the analyzer instead.
if (p_subscript->base->is_constant && !base_type.is_meta_type) {
// Just try to get it.
Variant value = p_subscript->base->reduced_value.get_named(p_subscript->attribute->name, valid);
if (valid) {
p_subscript->is_constant = true;
p_subscript->reduced_value = value;
result_type = type_from_variant(value, p_subscript);
}
} else if (base_type.is_variant() || !base_type.is_hard_type()) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants