Most of the time people using the BGE who ask for help scripting are trying to achieve similar tasks.
This library makes this easier by using a verbose api that allows combinations of modular functions.
from bge import logic, types
from operator import gt as MORE_THAN, lt as LESS_THAN, eq as EQUALS
FIRST = 0
GAMEOBJECT = types.KX_GameObject
CAMERA = types.KX_Camera
LAMP = types.KX_LightObject
SCENE = types.KX_Scene
ARMATURE = types.BL_ArmatureObject
def get_first(iterable):
try:
return next(iter(iterable))
except StopIteration:
return
def is_iterable(iterable):
try:
iter(iterable)
except TypeError:
return False
else:
return True
def get_scene():
return logic.getCurrentScene()
def get_objects():
return get_scene().objects
def get_controller():
return logic.getCurrentController()
def get_owner():
return get_controller().owner
class Condition:
def __call__(self, obj):
raise NotImplementedError()
class Filter:
def __call__(self, obj):
raise NotImplementedError()
class Modifier:
def __call__(self, obj):
raise NotImplementedError()
class Key:
def __call__(self, obj):
raise NotImplementedError()
def AllOf(*filters):
def wrapper(obj):
for filter in filters:
if not filter(obj):
return False
else:
return True
return wrapper
def AnyOf(*filters):
def wrapper(obj):
for filter in filters:
if filter(obj):
return True
else:
return False
return wrapper
def InOrder(*callers):
def wrapper(args):
for caller in callers:
args = caller(args)
return args
return wrapper
class SortBy(Modifier):
def __init__(self, function):
self.function = function
def __call__(self, iterable):
return sorted(iterable, key=self.function)
class DistanceKey(Key):
def __init__(self, get_obj):
self.get_obj = get_obj
def __call__(self, obj):
base_obj = self.get_obj()
return (base_obj.worldPosition - obj.worldPosition).length
class GetFirst(Modifier):
def __init__(self, function):
self.function = function
def __call__(self, iterable):
try:
return next(iter(self.function(iterable)))
except StopIteration:
return
class GetAtIndex(Modifier):
def __init__(self, function, index):
self.function = function
self.index = index
def __call__(self, iterable):
try:
return self.function(iterable)[self.index]
except IndexError:
return
class WithinRange(Condition):
def __init__(self, get_obj, range):
self.get_obj = get_obj
self.range = range
def __call__(self, obj):
base_obj = self.get_obj()
return (base_obj.worldPosition - obj.worldPosition).length <= self.range
class IsVisible(Condition):
def __init__(self, get_scene):
self.get_scene = get_scene
def __call__(self, obj):
camera = self.get_scene().active_camera
if "radius" in obj:
return camera.sphereInsideFrustum(obj.worldPosition, obj['radius']) != CAMERA.OUTSIDE
else:
return camera.pointInsideFrustum(obj.worldPosition)
class NameIs(Condition):
def __init__(self, name):
self.name = name
def __call__(self, obj):
return obj.name == self.name
class TypeIs(Condition):
def __init__(self, type):
self.type = type
def __call__(self, obj):
return type(obj) == self.type
class HasProperty(Condition):
def __init__(self, prop_name):
self.prop_name = prop_name
def __call__(self, obj):
return self.prop_name in obj
class PropertyComparison(Condition):
def __init__(self, prop_name, value, comparator=EQUALS):
self.prop_name = prop_name
self.value = value
self.comparator = comparator
def __call__(self, obj):
return self.comparator(obj[self.prop_name], self.value)
class FilterIterable(Filter):
def __init__(self, condition):
self.condition = condition
def __call__(self, iterable):
return [i for i in iterable if self.condition(i)]
For example, finding objects by name:
name_condition = NameIs("object_name")
with_name_filter = FilterIterable(name_condition)
with_name = with_name_filter(scene.objects)
For example, finding objects by type:
type_condition = TypeIs(LAMP)
with_type_filter = FilterIterable(type_condition)
with_type = with_type_filter(scene.objects)
To combine filters, you can use two methods:
type_condition = TypeIs(LAMP)
name_condition = NameIs("object_name")
with_name_filter = FilterIterable(name_condition)
with_type_filter = FilterIterable(type_condition)
with_type_and_name = with_name_filter(with_type_filter(scene.objects))
Or:
type_condition = TypeIs(LAMP)
name_condition = NameIs("object_name")
type_and_name = AllOf(type_condition, name_condition)
with_type_and_name_filter = FilterIterable(name_condition)
with_type_and_name = with_type_and_name_filter(scene.objects)
There aren’t many functions that act upon the results of these functions, primarily because that is the role of the existing API.
