From 445dc0cc5770f9aa62264efb37c35d5964e41c0f Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Wed, 11 Dec 2013 18:24:21 +0000 Subject: unpacking elements so as to be able to remove cjson dependency --- (limited to 'elements/callbacks.py') diff --git a/elements/callbacks.py b/elements/callbacks.py new file mode 100644 index 0000000..01e9545 --- /dev/null +++ b/elements/callbacks.py @@ -0,0 +1,122 @@ +""" +This file is part of the 'Elements' Project +Elements is a 2D Physics API for Python (supporting Box2D2) + +Copyright (C) 2008, The Elements Team, + +Home: http://elements.linuxuser.at +IRC: #elements on irc.freenode.org + +Code: http://www.assembla.com/wiki/show/elements + svn co http://svn2.assembla.com/svn/elements + +License: GPLv3 | See LICENSE for the full text +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" +from locals import * +from elements import box2d + +class CallbackHandler: + # List of contact callbacks and shapes to start them - sorted by type for quicker access + # Callbacks are saved as callbacks[callback_type][[function, parameters], ...] + callbacks = {} + + def __init__(self, parent): + self.parent = parent + + # init callback dict to avoid those slow try + # (especially for self.get, as it is called *often*) + for i in xrange(10): + self.callbacks[i] = [] + + def add(self, callback_type, callback_handler, *args): + """ Users can add callbacks for certain (or all) collisions + + Parameters: + callback_type ......... CALLBACK_CONTACT (nothing else for now) + callback_handler ...... a callback function + args (optional) ....... a list of parameters which can be used with callbacks.get + + Return: + callback_id ... used to remove a callback later (int) + """ + # Create contact listener if required + if callback_type in [CALLBACK_CONTACT_ADD, CALLBACK_CONTACT_PERSIST, CALLBACK_CONTACT_REMOVE]: + if self.parent.listener == None: + self.parent.listener = kContactListener(self.get) + self.parent.world.SetContactListener( self.parent.listener ) + print "* ContactListener added" + + # Get callback dict for this callback_type + c = self.callbacks[callback_type] + + # Append to the Callback Dictionary + c.append([callback_handler, args]) + self.callbacks[callback_type] = c + + # Return Callback ID + # ID = callback_type.callback_index (1...n) + return "%i.%i" % (callback_type, len(c)) + + def get(self, callback_type): + return self.callbacks[callback_type] + + def start(self, callback_type, *args): + callbacks = self.get(callback_type) + for c in callbacks: + callback, params = c + callback() + +class kContactListener(box2d.b2ContactListener): + def __init__(self, get_callbacks): + # Init the Box2D b2ContactListener + box2d.b2ContactListener.__init__(self) + + # Function to get the current callbacks + self.get_callbacks = get_callbacks + + def check_contact(self, contact_type, point): + # Checks if a callback should be started with this contact point + contacts = self.get_callbacks(contact_type) + + # Step through all callbacks for this type (eg ADD, PERSIST, REMOVE) + for c in contacts: + callback, bodylist = c + if len(bodylist) == 0: + # Without bodylist it's a universal callback (for all bodies) + callback(point) + + else: + # This is a callback with specified bodies + # See if this contact involves one of the specified + b1 = str(point.shape1.GetBody()) + b2 = str(point.shape2.GetBody()) + for s in bodylist: + s = str(s) + if b1 == s or b2 == s: + # Yes, that's the one :) + callback(point) + + def Add(self, point): + """Called when a contact point is created""" + self.check_contact(CALLBACK_CONTACT_ADD, point) + + def Persist(self, point): + """Called when a contact point persists for more than a time step""" + self.check_contact(CALLBACK_CONTACT_PERSIST, point) + + def Remove(self, point): + """Called when a contact point is removed""" + self.check_contact(CALLBACK_CONTACT_REMOVE, point) + -- cgit v0.9.1