-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
register_properties.go
259 lines (250 loc) · 7.87 KB
/
register_properties.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
//go:build !generate
package gd
import (
"fmt"
"reflect"
"strings"
gd "grow.graphics/gd/internal"
)
/*func attachProperties(ctx Context, className StringName, info *ClassCreationInfo, rtype reflect.Type) {
var (
properties []PropertyInfo
propertyPinner runtime.Pinner
)
defer propertyPinner.Unpin()
ctx.Defer(func() {
propertyPinner.Unpin()
})
var groups [][2]string
var subgroups [][2]string
var addProperties func(rtype reflect.Type, prefix string, subgroup bool)
addProperties = func(rtype reflect.Type, prefix string, subgroup bool) {
for i := 0; i < rtype.NumField(); i++ {
field := rtype.Field(i)
if !field.IsExported() || field.Anonymous {
continue
}
if field.Type.Kind() == reflect.Struct && field.Type.Name() == "" {
group := [2]string{field.Name, prefix + strings.ToLower(field.Name) + "_"}
if subgroup {
subgroups = append(subgroups, group)
} else {
groups = append(groups, group)
}
addProperties(field.Type, strings.ToLower(field.Name)+"_", true)
} else {
field.Name = prefix + field.Name
properties = append(properties, derivePropertyInfo(ctx, &propertyPinner, rtype, field))
}
}
}
addProperties(rtype, "", false)
if len(properties) > 0 {
propertyPinner.Pin(&properties[0])
info.GetPropertyList.Set(func(instance cgo.Handle, length *uint32) *PropertyInfo {
*length = uint32(len(properties))
return &properties[0]
})
info.FreePropertyList.Set(func(instance cgo.Handle, properties *PropertyInfo) {})
info.Set.Set(func(instance cgo.Handle, name StringNamePtr, value VariantPtr) bool {
ctx := NewContext(ctx.API)
sname := mmm.Let[StringName](ctx.Lifetime, ctx.API, *name)
field := reflect.ValueOf(instance.Value()).Elem().FieldByName(sname.String())
if !field.IsValid() {
return false
}
var fieldPin = instance.Value().(IsClass).Pin()
variant := mmm.Let[Variant](ctx.Lifetime, ctx.API, *value)
ptr, ok := field.Interface().(interface {
Pin() Context
Free()
})
if ok {
fieldPin = ptr.Pin()
if !field.IsZero() {
ptr.Free()
}
}
field.Set(reflect.ValueOf(variant.Interface(fieldPin)))
ctx.End()
return true
})
info.Get.Set(func(instance cgo.Handle, name StringNamePtr, value VariantPtr) bool {
ctx := NewContext(ctx.API)
sname := mmm.Let[StringName](ctx.Lifetime, ctx.API, *name)
field := reflect.ValueOf(instance.Value()).Elem().FieldByName(sname.String())
if !field.IsValid() {
return false
}
tmp := ctx.Variant(field.Interface())
*value = mmm.Get(tmp)
//mmm.MarkFree(tmp)
ctx.End()
return true
})
}
var frame = ctx.API.NewFrame()
for _, group := range groups {
FrameSet[uintptr](0, frame, mmm.Get(className))
FrameSet[uintptr](1, frame, mmm.Get(ctx.String(group[0])))
FrameSet[uintptr](2, frame, mmm.Get(ctx.String(group[1])))
ctx.API.ClassDB.RegisterClassPropertyGroup(ctx.API.ExtensionToken, frame.Get(0), frame.Get(1), frame.Get(2))
}
for _, group := range subgroups {
FrameSet[uintptr](0, frame, mmm.Get(className))
FrameSet[uintptr](1, frame, mmm.Get(ctx.String(group[0])))
FrameSet[uintptr](2, frame, mmm.Get(ctx.String(group[1])))
ctx.API.ClassDB.RegisterClassPropertySubGroup(ctx.API.ExtensionToken, frame.Get(0), frame.Get(1), frame.Get(2))
}
frame.Free()
}*/
func propertyOf(godot Context, field reflect.StructField) gd.PropertyInfo {
var name = field.Name
tag, ok := field.Tag.Lookup("gd")
if ok {
name = tag
}
var hint gd.PropertyHint
var hintString = classNameOf(field.Type)
vtype := variantTypeOf(field.Type)
if vtype == TypeArray {
_, generic, ok := strings.Cut(field.Type.String(), "[")
if ok {
hint |= PropertyHintArrayType
split := strings.Split(generic, ".")
elem := split[len(split)-1]
elem = elem[:len(elem)-1]
hintString = fmt.Sprintf("%d/%d:%s", gd.TypeObject, PropertyHintResourceType, elem) // MAKE_RESOURCE_TYPE_HINT
}
}
if field.Type.Implements(reflect.TypeOf([0]isResource{}).Elem()) {
hint |= PropertyHintResourceType
}
var usage = PropertyUsageStorage | PropertyUsageEditor
if vtype == TypeNil {
usage |= PropertyUsageNilIsVariant
}
if rangeHint, ok := field.Tag.Lookup("range"); ok {
hint |= PropertyHintRange
hintString = rangeHint
}
return gd.PropertyInfo{
Type: vtype,
Name: godot.StringName(name),
ClassName: godot.StringName(classNameOf(field.Type)),
Hint: hint,
HintString: godot.String(hintString),
Usage: usage,
}
}
func classNameOf(rtype reflect.Type) string {
if rtype.Kind() == reflect.Ptr {
return classNameOf(rtype.Elem())
}
if rtype.Implements(reflect.TypeOf([0]gd.IsClass{}).Elem()) {
if rtype.Field(0).Anonymous {
if rename, ok := rtype.Field(0).Tag.Lookup("gd"); ok {
return rename
}
}
if rtype.Name() == "" && rtype.Field(0).Anonymous {
return rtype.Field(0).Name
}
return rtype.Name()
}
return ""
}
func variantTypeOf(rtype reflect.Type) (vtype VariantType) {
switch rtype.Kind() {
case reflect.Int32, reflect.Int64, reflect.Int:
return TypeInt
}
switch rtype {
case reflect.TypeOf([0]Variant{}).Elem():
vtype = TypeNil
case reflect.TypeOf([0]Bool{}).Elem():
vtype = TypeBool
case reflect.TypeOf([0]Int{}).Elem():
vtype = TypeInt
case reflect.TypeOf([0]Float{}).Elem():
vtype = TypeFloat
case reflect.TypeOf([0]String{}).Elem():
vtype = TypeString
case reflect.TypeOf([0]Vector2{}).Elem():
vtype = TypeVector2
case reflect.TypeOf([0]Vector2i{}).Elem():
vtype = TypeVector2i
case reflect.TypeOf([0]Rect2{}).Elem():
vtype = TypeRect2
case reflect.TypeOf([0]Rect2i{}).Elem():
vtype = TypeRect2i
case reflect.TypeOf([0]Vector3{}).Elem():
vtype = TypeVector3
case reflect.TypeOf([0]Vector3i{}).Elem():
vtype = TypeVector3i
case reflect.TypeOf([0]Transform2D{}).Elem():
vtype = TypeTransform2d
case reflect.TypeOf([0]Vector4{}).Elem():
vtype = TypeVector4
case reflect.TypeOf([0]Vector4i{}).Elem():
vtype = TypeVector4i
case reflect.TypeOf([0]Plane{}).Elem():
vtype = TypePlane
case reflect.TypeOf([0]Quaternion{}).Elem():
vtype = TypeQuaternion
case reflect.TypeOf([0]AABB{}).Elem():
vtype = TypeAabb
case reflect.TypeOf([0]Basis{}).Elem():
vtype = TypeBasis
case reflect.TypeOf([0]Transform3D{}).Elem():
vtype = TypeTransform3d
case reflect.TypeOf([0]Projection{}).Elem():
vtype = TypeProjection
case reflect.TypeOf([0]Color{}).Elem():
vtype = TypeColor
case reflect.TypeOf([0]StringName{}).Elem():
vtype = TypeStringName
case reflect.TypeOf([0]NodePath{}).Elem():
vtype = TypeNodePath
case reflect.TypeOf([0]RID{}).Elem():
vtype = TypeRid
case reflect.TypeOf([0]Object{}).Elem():
vtype = TypeObject
case reflect.TypeOf([0]Callable{}).Elem():
vtype = TypeCallable
case reflect.TypeOf([0]Dictionary{}).Elem():
vtype = TypeDictionary
case reflect.TypeOf([0]Array{}).Elem():
vtype = TypeArray
case reflect.TypeOf([0]PackedByteArray{}).Elem():
vtype = TypePackedByteArray
case reflect.TypeOf([0]PackedInt32Array{}).Elem():
vtype = TypePackedInt32Array
case reflect.TypeOf([0]PackedInt64Array{}).Elem():
vtype = TypePackedInt64Array
case reflect.TypeOf([0]PackedFloat32Array{}).Elem():
vtype = TypePackedFloat32Array
case reflect.TypeOf([0]PackedFloat64Array{}).Elem():
vtype = TypePackedFloat64Array
case reflect.TypeOf([0]PackedStringArray{}).Elem():
vtype = TypePackedStringArray
case reflect.TypeOf([0]PackedVector2Array{}).Elem():
vtype = TypePackedVector2Array
case reflect.TypeOf([0]PackedVector3Array{}).Elem():
vtype = TypePackedVector3Array
case reflect.TypeOf([0]PackedColorArray{}).Elem():
vtype = TypePackedColorArray
default:
switch {
case rtype.Implements(reflect.TypeOf([0]gd.IsClass{}).Elem()):
vtype = TypeObject
case rtype.Implements(reflect.TypeOf([0]gd.IsArray{}).Elem()):
vtype = TypeArray
case rtype.Implements(reflect.TypeOf([0]gd.IsSignal{}).Elem()):
vtype = TypeSignal
default:
panic("gdextension.RegisterClass: unsupported property type " + rtype.String())
}
}
return
}