Creating Game Object Properties Via Python

Is there a way to create an object timer property in python? Like own[‘delay’].timerProperty?

I don’t believe you can, as it doesn’t belong to the default python types.
You could easily create a class instance with a property that updates when called. Using the get() method, every time you call

time = myclass.timer_prop_1 

it would update the value. Bare in mind you’d need both the container class as well as the timer property class.

Otherwise, you could write a class with methods like get_time, or a property decorated function that returns the time.

Here is an example of a descriptor version (hacky)

from time import time,  sleep

def unbind(function):
        return function.__func__
    except AttributeError:
        raise Exception("Function is not bound")

def is_bound(function):
    return hasattr(function, "__self__")

class SpecialProperty(object):
    "Emulate PyProperty_Type() in Objects/descrobject.c"

    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        if is_bound(self.fget):
            self.fget = unbind(self.fget)
        if is_bound(self.fset):
            self.fset = unbind(self.fset)
        if is_bound(self.fdel):
            self.fdel = unbind(self.fdel)
        self.__doc__ = doc

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError("unreadable attribute")
        return self.fget(obj)

    def __set__(self, obj, value):
        if self.fset is None:
            raise AttributeError("can't set attribute")
        self.fset(obj, value)

    def __delete__(self, obj):
        if self.fdel is None:
            raise AttributeError("can't delete attribute")
    def setter(self, func):
        if is_bound(func):
            func = unbind(func)
        self.fset = func
        return self
class InstanceDescriptor:
    def __getattribute__(self, name):
        value = object.__getattribute__(self, name)
        if hasattr(value, "__get__"):
            return value.__get__(self, self.__class__)
        return value
    def __setattr__(self, name, value):
            obj = object.__getattribute__(self, name)
        except AttributeError:
            if hasattr(obj, '__set__'):
                return obj.__set__(self, value)
        return object.__setattr__(self, name, value)    

class Timer:
    def __init__(self):
        self.time = time()
    def __get__(self, inst, typ):
        if inst is None: return self
        return time() - self.time
    def __set__(self, inst, value):
        if inst is None: return 
        self.time = time() - value       
class ExampleClass(InstanceDescriptor):
    def __init__(self):
        self.timer = Timer()

a = ExampleClass()


a.timer = 0.0

Here is a simple property version, but less hidden

from time import time

class ExampleClass:
    def __init__(self):
        self._time = time()
    def timer(self):
        return time() - self._time
    def timer(self, value):
        self._time = time() - value

That’s a to bad you cant use properties in that way. It would be very useful.

you mean a object that keep the time for all objects of the scene ?

if so, you can make a obj that keep the time, call it Time or something .
with a script that run every frame(and calculate the time)

then , from other obj , you call this obj from the scene , and read the time .

objTime = scene.objects[“Time”]

time = objTime[“time”]

I would have liked each object to work independently on its own properties, but it will work.
Thanks =D

Since you took the time to create these I decided to try them out and, it works great! Thanks! I like to look over the code and try to figure out how it works so at first it looked a little intimidating. Still does kinda. I’m still learning how classes work.
Thank you for your help! Thank you for creating these!

That’s kind of you to try them, although I really wanted to see how easy it was. Fundamentally you can never trick C++ into thinking a PyObject isn’t a PyObject unless you explicitly try to do so, so that would always be an issue with debug properties and logic bricks. I wouldn’t try and understand the classes too badly; they’re non-conventional hacking. I took the concept of descriptors, then allowed them to work with instances (using the InstancedDescriptor base class) and then I overwrote the property access mechanism on the game object to call any descriptors if they existed before reading the property.

It is pretty simple. I added the script to my addons folder so all I have to do is import “from timer_lib import Timer, ObjectPatch”
set own = ObjectPatch(own) and your good to go!

import bge
from timer_lib import Timer, ObjectPatch

def main(cont):
    own = cont.owner
    own = ObjectPatch(own)

    if not "timer" in own:
        own['timer'] = Timer()

Do you need to use this?

if not isinstance(own, ObjectPatch):
    own = ObjectPatch(own)

Yes. That is the only part you “need”. It only needs to (and should only) be run once to setup the object.