101 lines
1.6 KiB
Go
101 lines
1.6 KiB
Go
|
|
package object
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"reflect"
|
||
|
|
"zworld/plugins/system/events"
|
||
|
|
)
|
||
|
|
|
||
|
|
type PropValue interface{}
|
||
|
|
|
||
|
|
type GenericProp interface {
|
||
|
|
Type() reflect.Type
|
||
|
|
GetAny() any
|
||
|
|
SetAny(any)
|
||
|
|
}
|
||
|
|
|
||
|
|
type Property[T PropValue] struct {
|
||
|
|
value T
|
||
|
|
def T
|
||
|
|
kind reflect.Type
|
||
|
|
|
||
|
|
OnChange events.Event[T]
|
||
|
|
}
|
||
|
|
|
||
|
|
var _ GenericProp = &Property[int]{}
|
||
|
|
|
||
|
|
func NewProperty[T PropValue](def T) Property[T] {
|
||
|
|
var empty T
|
||
|
|
return Property[T]{
|
||
|
|
value: def,
|
||
|
|
def: def,
|
||
|
|
kind: reflect.TypeOf(empty),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (p *Property[T]) Get() T {
|
||
|
|
return p.value
|
||
|
|
}
|
||
|
|
|
||
|
|
func (p *Property[T]) GetAny() any {
|
||
|
|
return p.value
|
||
|
|
}
|
||
|
|
|
||
|
|
func (p *Property[T]) Set(value T) {
|
||
|
|
p.value = value
|
||
|
|
p.OnChange.Emit(value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (p *Property[T]) SetAny(value any) {
|
||
|
|
if cast, ok := value.(T); ok {
|
||
|
|
p.Set(cast)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (p *Property[T]) String() string {
|
||
|
|
return fmt.Sprintf("%v", p.value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (p *Property[T]) Type() reflect.Type {
|
||
|
|
return p.kind
|
||
|
|
}
|
||
|
|
|
||
|
|
type PropInfo struct {
|
||
|
|
GenericProp
|
||
|
|
Key string
|
||
|
|
Name string
|
||
|
|
}
|
||
|
|
|
||
|
|
func Properties(target Component) []PropInfo {
|
||
|
|
t := reflect.TypeOf(target).Elem()
|
||
|
|
v := reflect.ValueOf(target).Elem()
|
||
|
|
|
||
|
|
properties := make([]PropInfo, 0, t.NumField())
|
||
|
|
for i := 0; i < t.NumField(); i++ {
|
||
|
|
field := t.Field(i)
|
||
|
|
if field.Anonymous {
|
||
|
|
// anonymous fields are not considered
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if !field.IsExported() {
|
||
|
|
// only exported fields can be properties
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
|
||
|
|
value := v.Field(i)
|
||
|
|
|
||
|
|
if prop, isProp := value.Addr().Interface().(GenericProp); isProp {
|
||
|
|
// todo: tags
|
||
|
|
|
||
|
|
properties = append(properties, PropInfo{
|
||
|
|
GenericProp: prop,
|
||
|
|
|
||
|
|
Key: field.Name,
|
||
|
|
Name: field.Name,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return properties
|
||
|
|
}
|