Skip to content

Instantly share code, notes, and snippets.

@agoose77
Created November 21, 2016 14:04
Show Gist options
  • Save agoose77/d18216dbb793184915a8b7d5e78a2c70 to your computer and use it in GitHub Desktop.
Save agoose77/d18216dbb793184915a8b7d5e78a2c70 to your computer and use it in GitHub Desktop.
from bge import logic, types
from functools import lru_cache
class InspectableProperty:
def __init__(self, fget):
self.fget = fget
self.fset = None
@property
def __name__(self):
return self.fget.__name__
def setter(self, fset):
self.fset = fset
return self
def __get__(self, instance, owner=None):
if instance is not None:
return self.fget.__get__(instance, owner)()
return self
def __set__(self, instance, value):
if self.fset is None:
raise AttributeError("Can't set attribute")
self.fset.__get__(instance, instance.__class__)(value)
class ControllerBase(types.SCA_PythonController):
def __new__(cls, cont):
self = super().__new__(cls, cont)
self._init_from_controller()
return self
def _init_from_controller(self):
own = self.owner
self_name = self.name
for prop_name in own.getPropertyNames():
split_name = prop_name.split('.', 1)
if len(split_name) == 1:
continue
cont_name, name = split_name
if cont_name != self_name:
continue
setattr(self, name, own[prop_name])
def __getitem__(self, name):
return self.__dict__[name]
def __setitem__(self, name, value):
self.__dict__[name] = value
class ClassBuilder:
def __init__(self, main_func):
self.main_func = main_func
self._class_dict = {}
@lru_cache()
def _get_class(self):
return type("{}_class".format(self.main_func.__name__), (ControllerBase,), self._class_dict)
def _build_wrapper(self, cont):
cls = self._get_class()
return cls(cont)
def method(self, func):
try:
name = func.__name__
except AttributeError:
raise ValueError("Can't determine name of object")
wrapped_func = func
if name == "__init__":
def wrapped_func(self, cont):
func(self)
self._class_dict[name] = wrapped_func
return func
def property(self, func):
return self.method(InspectableProperty(func))
def _get_wrapper_for(self, cont):
key = cont.name
owner = cont.owner
try:
return owner[key]
except KeyError:
wrapper = owner[key] = self._build_wrapper(cont)
return wrapper
def __call__(self):
cont = logic.getCurrentController()
wrapper = self._get_wrapper_for(cont)
self.main_func(wrapper)
def magic(func):
return ClassBuilder(func)
"""
@magic
def some_controller(self):
self.x += 1
print(self.x)
self.activate(self.actuators[0])
@magic.method
def __init__(self):
print("Starting with 'x'={}".format(self.x))
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment