Library for common bge tools

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.

eh?? :smiley:
well much more “simple” than the other one to implement FSM or something, but too “abstract” , hard understand what this code do for humans without a very basic example.

with_type_and_name = with_name_filter(with_type_filter(scene.objects))

is not by chance much more simple and flexible using [i for i in scene.objects if this in i and isinstance(i,LAMP) ]

i found very complex encapsulate the condition(i make a class to manage it and keep also the last output) but seem a trap and at the end seem ever better a good and old list comp that at least is readable

It isn’t too complex in actuality . You have the filter, which accepts a condition (and runs it on every entry, which determines if it is in the list)

Sent from my Nexus 5 using Tapatalk