Skip to content

Commit f5abb87

Browse files
committed
feat: Improve enum and Variant usability
Change enums to not have unnecessary prefixes. Setup `Variant.getType` to return a `VariantType` enum instead of an integer. Add `Variant.cast<T>` to support getting an object from a Variant easily. refs: #21
1 parent 963d165 commit f5abb87

File tree

8 files changed

+90
-25
lines changed

8 files changed

+90
-25
lines changed

src/dart/godot_dart/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.6.0
2+
3+
- Adjust generate global constats to avoid unnecessary prefixes.
4+
- Have `Variant.getType` return `VariantType` instead of int.
5+
- Add `Variant.cast` to support getting an object directly from a Variant.
6+
17
## 0.5.2
28

39
- Fix `Future<void>` throwing an error when put in a Variant, which could happen with `async` signal recievers.

src/dart/godot_dart/lib/src/core/property_info.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class PropertyInfo {
1010
PropertyInfo({
1111
required this.typeInfo,
1212
required this.name,
13-
this.hint = PropertyHint.propertyHintNone,
13+
this.hint = PropertyHint.none,
1414
this.hintString = '',
1515
this.flags = 6, // PropertyUsage.propertyUsageDefault
1616
});

src/dart/godot_dart/lib/src/variant/variant.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,14 +183,20 @@ class Variant implements Finalizable {
183183
_attachFinalizer();
184184
}
185185

186-
int getType() {
187-
return gde.ffiBindings.gde_variant_get_type(_opaque.cast());
186+
VariantType getType() {
187+
final cValue = gde.ffiBindings.gde_variant_get_type(_opaque.cast());
188+
return VariantType.fromValue(cValue);
188189
}
189190

190191
void constructCopy(GDExtensionTypePtr ptr) {
191192
gde.ffiBindings.gde_variant_new_copy(ptr, nativePtr.cast());
192193
}
193194

195+
T? cast<T>() {
196+
var typeInfo = gde.dartBindings.getGodotTypeInfo(T);
197+
return convertFromVariant(this, typeInfo) as T?;
198+
}
199+
194200
void _attachFinalizer() {
195201
finalizer.attach(this, _opaque.cast());
196202
}

src/dart/godot_dart/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: godot_dart
22
description: Dart bindings for the Godot game engine
33
repository: https://github.com/fuzzybinary/godot_dart
4-
version: 0.5.2
4+
version: 0.6.0
55

66
environment:
77
sdk: '>=3.2.0 <4.0.0'

tools/binding_generator/lib/src/common_helpers.dart

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -739,31 +739,92 @@ void writePtrReturn(ArgumentProxy argument, CodeSink o) {
739739
o.p('$ret;');
740740
}
741741

742+
// A map of enumTypes to prefixes that are different from their type name, and
743+
// can be removed in Dart.
744+
const removePrefixes = <String, String>{
745+
'KeyModifierMask': 'keyMask',
746+
'Variant.Type': 'type',
747+
'Error': 'err',
748+
'MethodFlags': 'methodFlag',
749+
'PropertyUsageFlags': 'propertyUsage',
750+
'Variant.Operator': 'op',
751+
'Planes': 'plane',
752+
};
753+
754+
// Reserved words that get used as enum names, and should instead
755+
// default back to their original, prefixed names.
756+
final reservedWordEnumNames = [
757+
'default',
758+
'const',
759+
'static',
760+
'in',
761+
'index',
762+
'new',
763+
'class',
764+
'continue',
765+
];
766+
767+
Value _transformEnumValues(Value e, String name) {
768+
final lowerEnumName = name.lowerFirstLetter();
769+
String originalName = e.name.toLowerCamelCase();
770+
String transformedName = originalName;
771+
if (originalName != lowerEnumName && originalName.startsWith(lowerEnumName)) {
772+
transformedName =
773+
originalName.replaceFirst(lowerEnumName, '').lowerFirstLetter();
774+
} else if (removePrefixes.containsKey(name)) {
775+
final prefix = removePrefixes[name]!;
776+
transformedName =
777+
transformedName.replaceFirst(prefix, '').lowerFirstLetter();
778+
}
779+
780+
// Don't allow keywords
781+
if (transformedName == 'int') transformedName = 'integer';
782+
if (transformedName == 'enum') transformedName = 'enumVal';
783+
if (reservedWordEnumNames.contains(transformedName)) {
784+
transformedName = originalName;
785+
}
786+
787+
return Value(name: transformedName, value: e.value);
788+
}
789+
790+
extension EnumTransform on BuiltinClassEnum {
791+
List<Value> transformedValues() {
792+
return values.map((e) => _transformEnumValues(e, name)).toList();
793+
}
794+
}
795+
796+
extension EnumTranform on GlobalEnumElement {
797+
List<Value> transformedValues() {
798+
return values.map((e) => _transformEnumValues(e, name)).toList();
799+
}
800+
}
801+
742802
void writeEnum(dynamic godotEnum, String? inClass, CodeSink o) {
743803
String name;
744804
List<Value> valueList;
745805
bool isBitfield = false;
746806
if (godotEnum is BuiltinClassEnum) {
747807
name = godotEnum.name;
748-
valueList = godotEnum.values;
808+
valueList = godotEnum.transformedValues();
749809
} else if (godotEnum is GlobalEnumElement) {
750810
name = godotEnum.name;
751-
valueList = godotEnum.values;
811+
valueList = godotEnum.transformedValues();
752812
isBitfield = godotEnum.isBitfield;
753813
} else {
754814
throw ArgumentError(
755815
'Trying to write an enum that is of type ${godotEnum.runtimeType}');
756816
}
757817

758818
var enumName = getEnumName(name, inClass);
819+
759820
o.b('enum $enumName {', () {
760-
if (isBitfield) {
821+
if (isBitfield && valueList.where((e) => e.name == 'none').isEmpty) {
761822
o.p('none(0),');
762823
}
763824
for (int i = 0; i < valueList.length; ++i) {
764825
final value = valueList[i];
765826
final end = i == valueList.length - 1 ? ';' : ',';
766-
o.p('${value.name.toLowerCamelCase()}(${value.value})$end');
827+
o.p('${value.name}(${value.value})$end');
767828
}
768829
o.nl();
769830

tools/binding_generator/lib/src/godot_api_info.dart

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import 'package:collection/collection.dart';
22
import 'package:tuple/tuple.dart';
33

4+
import 'common_helpers.dart';
45
import 'godot_extension_api_json.dart';
5-
import 'string_extensions.dart';
66
import 'type_helpers.dart';
77

88
enum TypeCategory {
@@ -98,26 +98,14 @@ class GodotApiInfo {
9898
}
9999

100100
String findEnumValue(String type, String value) {
101-
// Special case -- Vector3Axis was reimplemented
102-
if (type == 'Vector3Axis') {
103-
switch (value) {
104-
case '0':
105-
return 'Vector3Axis.x';
106-
case '1':
107-
return 'Vector3Axis.y';
108-
case '2':
109-
return 'Vector3Axis.z';
110-
}
111-
}
112-
113101
final godotEnum = enumMap[type];
114102
if (godotEnum == null) return value;
115103

116104
List<Value> valueList;
117105
if (godotEnum is BuiltinClassEnum) {
118-
valueList = godotEnum.values;
106+
valueList = godotEnum.transformedValues();
119107
} else if (godotEnum is GlobalEnumElement) {
120-
valueList = godotEnum.values;
108+
valueList = godotEnum.transformedValues();
121109
} else {
122110
throw ArgumentError(
123111
'Trying to write an enum that is of type ${godotEnum.runtimeType}');
@@ -126,7 +114,7 @@ class GodotApiInfo {
126114
final foundValue = valueList
127115
.firstWhereOrNull((element) => element.value.toString() == value);
128116
if (foundValue != null) {
129-
return '$type.${foundValue.name.toLowerCamelCase()}';
117+
return '$type.${foundValue.name}';
130118
}
131119

132120
return value;

tools/binding_generator/lib/src/string_extensions.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,8 @@ extension StringHelpers on String {
2626
return lowerCamel.replaceRange(
2727
0, 1, lowerCamel[0].toUpperCase().toString());
2828
}
29+
30+
String lowerFirstLetter() {
31+
return replaceRange(0, 1, this[0].toLowerCase().toString());
32+
}
2933
}

tools/binding_generator/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version: 1.0.0
44
publish_to: none
55

66
environment:
7-
sdk: '>=2.18.2 <3.0.0'
7+
sdk: '>=3.5.0 <4.0.0'
88

99
dependencies:
1010
collection: ^1.17.1

0 commit comments

Comments
 (0)